diff --git a/AGENTS.md b/AGENTS.md index cd4d356..478abee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,10 +30,10 @@ ## 代码结构 / 平台插件 -- 业务代码都在 `src/study_tool/` 包里;根目录只放启动壳 `app.py`、`pyproject.toml`、`static/`、`data/`、`des*.js` 这类运行时资源。 +- 业务代码都在 `src/study_tool/` 包里;根目录只放启动壳 `app.py`、`pyproject.toml`、`static/`、`data/`、`script/` 这类运行时资源。散落的 JS 脚本统一收进 `script/`,不参与运行的参考脚本放 `script/reference/`。 - 平台代码只能放在 `src/study_tool/platforms/` 下;一个平台只注册一次(`Platform` + `registry.register`),并在 `Platform.entries` 里声明登录 / 学习入口。同一平台的不同页面代际可以拆成实现模块(如莞易学的 `jspx.py` / `study.py`),由平台模块按 `course["generation"]` 分发。 -- 新增平台的标准步骤:写 `platforms/<名字>.py`(实现 `study(key, s, d, **opts)`、声明 `entries`)→ 在 `platforms/__init__.py` 的 `load_builtin()` 里 import → 结束。不要改 `engine.py`、`routes/`、前端。 -- 引擎、路由、前端都不允许直接 import 某个具体平台模块;需要平台能力时用 `registry.get(course["platform"])`;识别平台用 `registry.detect(url, html)`。 +- 新增平台的标准步骤:写 `platforms/<名字>.py`(实现 `study(key, s, d, **opts)`、声明 `entries`,需要登录 / 课程列表 / 发现时再实现对应可选入口)→ 在 `platforms/__init__.py` 的 `load_builtin()` 里 import → 结束。不要改 `engine.py`、`routes/`、前端。 +- 引擎、路由、前端都不允许直接 import 某个具体平台模块;需要平台能力时用 `registry.get(course["platform"])`;账号级操作(登录 / 刷新课程 / 发现课程 / 会话)按 `accounts.platform` 用 `registry.get()` 取 `Platform` 上的 `session` / `dump_cookies` / `login` / `list_courses` / `discover` / `renew_session` / `profile`;「添加账号」的平台下拉来自 `GET /api/platforms`。 - 前端源码在 `web/`(React + TypeScript + Vite + Tailwind CSS),构建产物输出到 `static/` 并提交进仓库;改完前端必须执行 `cd web && pnpm build`,不要直接改 `static/` 里的产物。 - 新代码的 import 一律显式(如 `from study_tool.config import JSPX`),不要再新增 `from xxx import *`;历史遗留的 star import 只保留在拆分前就存在的模块里。 - `docs/architecture.md` 维护分层与插件契约,改动结构时同步更新。 diff --git a/CHANGELOG.md b/CHANGELOG.md index 078f5c2..c6adbb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,13 @@ - 前端从单文件 `static/index.html`(原生 JS)改为 `web/` 工程:React 19 + TypeScript + Vite + Tailwind CSS v4;Vite 直接输出到 `static/`,FastAPI 托管 `/` 与 `/assets`,运行 Python 不再需要 Node - 新旧学习平台合并为「莞易学」:`jspx.dgjy.net`(登录入口)与 `study.dgjy.net`(学习入口)统一注册为 `Platform(id="guanyixue", label="莞易学")`,课程页代际(`legacy` / `spa`)由 `platforms/detect.py` 判断,平台内部按代际分发到 `jspx.py` / `study.py` - `Platform` 新增 `entries`(登录 / 学习入口 URL 片段)与 `registry.detect()`;课程发现按入口识别平台,新增平台不再需要改引擎。新增 `GET /api/platforms` 供前端展示平台名 +- 添加账号新增「学习平台」下拉(数据来自 `GET /api/platforms`);`accounts` 表新增 `platform` 字段(老库启动时自动补列),账号选定平台后,登录 / 刷新课程 / 发现课程分别走该平台的 `login` / `list_courses` / `discover`,学习与测验按 `course["platform"]` + `generation` 分发 +- `Platform` 增加账号级可选入口:`session` / `dump_cookies` / `login` / `list_courses` / `discover` / `renew_session` / `profile`;引擎和路由按 `registry.get(account["platform"])` 取实现,接入第二个平台只需写一个模块 - 测验交卷从 `platform`(jspx / study)改为 `generation`(legacy / spa),接口返回 `platform="guanyixue"` + `generation` - 代码改为标准 `src/` 包布局:业务代码全部在 `src/study_tool/`,根目录 `app.py` 只做启动壳(`python app.py`、`start.bat`、Dockerfile 都不用改);新增 `pyproject.toml`,`pip install -e .` 后可用 `study-tool` 命令 - 平台拆成插件包 `src/study_tool/platforms/`:`base.py` 定义 `Platform` 契约、`registry.py` 注册表;引擎按 `course["platform"]` 从注册表分发 - HTTP 接口收进 `routes/`(accounts / misc / logs),`docs/architecture.md` 说明分层、平台识别与新增平台的步骤 +- 散落的 JS 脚本统一收进 `script/`:运行必需的 `des.js` / `desenc.js` 放 `script/`(`config.py` 的 `DESENC` 指向 `script/desenc.js`),不参与运行的 `dgjy-toolkit.user.js`、`study-axios.mjs` 移到 `script/reference/` 作参考 ### 新增 @@ -20,6 +23,7 @@ ### 修复 +- 账号接口的错误分支引用未导入的 `JSONResponse`、删除账号引用未导入的 `RUNS` / `RUNS_LOCK`,登录失败 / 删除账号会 500:补齐导入 - `discover()` 引用未定义的 `detect_platform` / `has_study_marker` 导致课程发现 `NameError`:代际识别集中到 `platforms/detect.py`,两代页面共用同一套判断 - 系统设置里的大模型配置保存后重新打开会回到默认值:`save_settings` 写的是嵌套结构 `{llm, study}`,`load_settings` 却按顶层字段读,现在改成从 `llm` 子对象读取 - AI 答题整段同步等待导致浏览器 / 反代超时:`/api/quiz/answer` 改为流式(text/event-stream)分批返回,每批失败自动重试一次 diff --git a/Dockerfile b/Dockerfile index 5c6879c..14ccb9c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ ENV PYTHONUNBUFFERED=1 \ WORKDIR /app -# nodejs: desenc.js 要用(登录表单 rsa 字段走站点原版 DES 算法) +# nodejs: script/desenc.js 要用(登录表单 rsa 字段走站点原版 DES 算法) # curl: 健康检查用 RUN apt-get update \ && apt-get install -y --no-install-recommends nodejs ca-certificates curl tzdata \ diff --git a/OPTIMIZATION.md b/OPTIMIZATION.md index bd63775..01bff25 100644 --- a/OPTIMIZATION.md +++ b/OPTIMIZATION.md @@ -2,6 +2,34 @@ 已实现、但还需要你实测确认的事项。确认没问题后把对应条目删掉。 +## 添加账号选择平台 + +**状态**:已实现,待实测确认。 + +### 做了什么 + +- 「添加账号」弹窗最上面新增「学习平台」下拉,选项来自 `GET /api/platforms`(当前只有「莞易学」)。 +- 账号记录新增 `platform` 字段(SQLite 老库启动时自动 `ALTER TABLE` 补列)。 +- 登录(`/api/login`)、刷新课程(`/api/courses`)、发现课程(`/api/discover`、`/api/quiz`)、 + 开始学习(引擎 `run_one_course`)都按账号所选平台取 `Platform` 上的实现;选「莞易学」时 + 仍然自动识别旧版 / 新版课程页。 +- 以后新增平台:在 `platforms/<名字>.py` 实现 `session` / `login` / `list_courses` / `discover` / + `study` 并注册,下拉里就会多一个选项。 + +### 怎么测 + +1. 打开「添加账号」,确认最上面能看到「学习平台 / 莞易学」。 +2. 正常添加账号并登录,卡片右上角显示所选平台的 label(当前为「莞易学」)。 +3. 用一个已有账号点「刷新课程」「开始学习」,行为应与改动前一致(旧版 / 新版都能跑)。 + +### 如果没生效 + +- 下拉是空的:`GET /api/platforms` 应返回 `[{id, label}]`;检查 `platforms/__init__.py` 的 + `load_builtin()` 是否导入了平台模块。 +- 登录报「平台 xxx 还没有实现登录」:该平台的 `Platform.login` 没注册或 id 对不上。 +- 老库启动报 `no such column: platform`:删掉 `data/study.db` 重启(当前账号数据为空), + 或确认 `store._ensure_columns()` 已执行。 + ## 新旧平台合并为「莞易学」 **状态**:已实现,待实测确认。 diff --git a/README.md b/README.md index 951ca6b..62480e1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 莞易学多账号学习控制台 +# 学习控制台 莞易学(`jspx.dgjy.net` / `study.dgjy.net`,新旧版课程页自动识别)的多账号挂机控制台。账号、会话、课程缓存、运行日志、系统设置全部存在服务端 SQLite,浏览器只是界面,换电脑、远程打开都在。 @@ -100,7 +100,7 @@ pnpm typecheck ## 用法 -1. 右上角「添加账号」,填账号密码(存进服务端 SQLite)。 +1. 右上角「添加账号」→ 选「学习平台」(当前只有莞易学)→ 填账号密码(存进服务端 SQLite)。 2. 点「登录」→ 自动读 `/admin/main.action` 的「在学课程」。 3. 勾选课程 → 「开始学习」→ 卡片底部「课程日志」展开看实时进度。 4. 「自动交反馈表」默认开;「自动交测验」默认关(答题正确率无法保证)。 @@ -148,7 +148,7 @@ src/study_tool/ app.py 组装:FastAPI、鉴权中间件、页面 / health、启动 main() webapp.py FastAPI 实例(路由模块从这里注册,避免循环导入) runtime.py 运行状态 + 统一日志源(控制台 / 内存 / SQLite) - config.py 常量、环境变量、根目录定位(data / static / desenc.js) + config.py 常量、环境变量、根目录定位(data / static / script) store.py SQLite3:账号 / 设置 / 登录记录 / 运行日志 / 状态 / 缓存 / 快照 models.py HTTP 请求模型 settings_store.py 系统设置读写 @@ -169,7 +169,9 @@ src/study_tool/ logs.py /api/log、/api/runs web/ 前端源码(React 19 + TypeScript + Vite + Tailwind CSS v4) static/ 前端构建产物(index.html + assets/ + favicon.svg) -des.js desenc.js DES 加密(登录表单 rsa 字段,站点原版算法) +script/des.js 服务端 DES 加密(登录表单 rsa 字段,站点原版算法) +script/desenc.js DES 命令行封装(Node 调用,config.py 里定位) +script/reference/ 不参与运行的参考脚本:油猴 dgjy-toolkit.user.js、study-axios.mjs start.bat 一键启动(Windows) Dockerfile Docker 镜像(python:3.12-slim + nodejs + chromium) docker-compose.yml Docker 编排:端口、数据卷、AUTH_TOKEN、健康检查 @@ -178,11 +180,11 @@ requirements.txt 依赖 data/study.db SQLite 库(账号/设置/日志/快照) docs/architecture.md 分层说明 + 平台插件怎么加 study_video.py 独立命令行工具:按 trainCourseId 直接刷视频课时(会话也存 study.db) -dgjy-toolkit.user.js 浏览器油猴脚本(独立使用,与网页端无关) ``` 分层与插件契约见 [docs/architecture.md](docs/architecture.md):引擎只按 `course["platform"]` -从注册表取平台实现;平台用 `entries` 声明登录 / 学习入口,新增平台不用改 engine / 路由 / 前端。 +从注册表取平台实现;平台用 `entries` 声明登录 / 学习入口,并可按需实现 `login` / `list_courses` / +`discover` 等账号级入口;「添加账号」选的平台存进账号记录,登录与课程发现按它分发,新增平台不用改 engine / 路由 / 前端。 日志统一从 `runtime.log()` 出:控制台、页面卡片「课程日志」(按账号 id)、右上角「系统日志」(key=system) 看到的是同一份;新增日志不要再自己 `print()`。 diff --git a/docs/architecture.md b/docs/architecture.md index 7cb1207..a06d363 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -10,7 +10,7 @@ src/study_tool/ __main__.py python -m study_tool 入口 app.py 组装:FastAPI、鉴权中间件、页面 / health、启动 main() webapp.py FastAPI 实例(路由模块从这里注册,避免循环导入) - config.py 常量 / 环境变量 / 根目录定位(data、static、desenc.js) + config.py 常量 / 环境变量 / 根目录定位(data、static、script) runtime.py 运行状态 RUNS + 统一日志 log() store.py SQLite:账号 / 设置 / 日志 / 状态 / 缓存 / 快照 models.py HTTP 请求模型(Pydantic) @@ -32,7 +32,8 @@ src/study_tool/ logs.py /api/log、/api/runs web/ 前端源码(React 19 + TypeScript + Vite + Tailwind CSS v4) static/ 前端构建产物(index.html + assets/ + favicon.svg,提交进仓库) -des*.js 服务端 DES 加密脚本(Node 调用) +script/ 服务端 JS 脚本:des.js、desenc.js(Node 调用) +script/reference/ 不参与运行的参考脚本:dgjy-toolkit.user.js、study-axios.mjs ``` ## 分层 @@ -63,11 +64,20 @@ class Platform: label: str # 日志 / 界面展示名,如「莞易学」 study: Callable # (key, s, d, **opts) -> None entries: tuple[str, ...] # 登录入口 / 学习入口的 URL 片段 + # 账号级能力:添加账号时选中的平台决定登录 / 刷新课程 / 发现课程走哪套实现 + session: Callable # (cookies) -> requests.Session + dump_cookies: Callable # (session) -> [cookie] + login: Callable # (username, password) -> (session, user) + list_courses: Callable # (session) -> [course] + discover: Callable # (session, plan_id, project_id, name) -> 课程描述 + renew_session: Callable # (session) -> bool,无密码续期 + profile: Callable # (session) -> 显示名 ``` -`registry.detect(url, html)` 按 `entries` 命中平台;课程发现时把平台 id 写进 -`course["platform"]`,把页面代际写进 `course["generation"]`(`legacy` / `spa`)。 -引擎按平台分发,平台内部再按代际选择学习实现。 +`registry.detect(url, html)` 按 `entries` 命中平台;「添加账号」时选择的平台写进 +`accounts.platform`,之后登录 / 刷新课程 / 发现课程都用 `registry.get(account["platform"])` +取实现。课程发现时把平台 id 写进 `course["platform"]`,把页面代际写进 +`course["generation"]`(`legacy` / `spa`);引擎按平台分发,平台内部再按代际选择学习实现。 `opts` 固定包含:`workers / cap / enable_quiz / enable_feedback / mode / parallel / quiz_key / cookies / plan / project / name`。插件可以只取自己需要的。 @@ -100,16 +110,18 @@ quiz_key / cookies / plan / project / name`。插件可以只取自己需要的 PLATFORM = registry.register(Platform( id="<平台 id>", label="展示名", study=_study, entries=("<登录入口域名>", "<学习入口域名>"), + session=, dump_cookies=, login=, + list_courses=, discover=, )) ``` 2. 在 `platforms/__init__.py` 的 `load_builtin()` 里加一行 `from study_tool.platforms import <名字>`。 -3. 平台自己的登录 / 发现流程把 `course["platform"]` 写成该 id 后,引擎自动分发; - `registry.detect()` 用登录 / 学习入口识别平台,不需要改前端。 +3. 平台注册后会自动出现在「添加账号」的平台下拉框;账号选了该平台,登录 / 刷新课程 / + 发现课程 / 学习都走它的实现,不需要改路由或前端。 -现阶段登录与课程发现仍由莞易学模块承担(SSO 只有一套);接入第二个平台时, -在账号登录 / 发现入口按 `Platform.entries` 命中结果选择对应实现即可。 +现阶段登录与课程发现由莞易学模块承担(SSO 只有一套);`accounts.platform` 已经是平台分发的 +依据,接入第二个平台时在 `platforms/<平台>.py` 里实现上面的入口即可。 ## 前端 diff --git a/docs/progress/todo.md b/docs/progress/todo.md index e2ed24c..2dc7be6 100644 --- a/docs/progress/todo.md +++ b/docs/progress/todo.md @@ -1,7 +1,7 @@ # 后续待办 -- 接入第二个学习平台时,把该平台的登录、课程发现实现放进 `platforms/<平台>.py`, - 登录 / 发现入口用 `Platform.entries` + `registry.detect()` 选择;目前登录与发现仍由莞易学模块承担。 -- 前端补一条自动化回归(Playwright):空态、账号卡片、测验弹窗、设置保存。 +- 接入第二个学习平台时,在 `platforms/<平台>.py` 里实现 `session` / `login` / `list_courses` / + `discover` / `study` 并注册;账号在「添加账号」里选平台后即可用,登录与课程发现不需要再改路由。 +- 前端补一条自动化回归(Playwright):空态、账号卡片、测验弹窗、设置保存、平台下拉。 - 构建检查进 CI:`cd web && pnpm install --frozen-lockfile && pnpm typecheck && pnpm build`, 并校验 `static/` 与源码同步。 diff --git a/des.js b/script/des.js similarity index 100% rename from des.js rename to script/des.js diff --git a/desenc.js b/script/desenc.js similarity index 91% rename from desenc.js rename to script/desenc.js index 225a955..4d55f94 100644 --- a/desenc.js +++ b/script/desenc.js @@ -1,5 +1,5 @@ // Compute the site's strEnc(data, k1, k2, k3) using the original des.js. -// usage: node desenc.js [k1] [k2] [k3] +// usage: node script/desenc.js [k1] [k2] [k3] const fs = require('fs'); const path = require('path'); const vm = require('vm'); diff --git a/dgjy-toolkit.user.js b/script/reference/dgjy-toolkit.user.js similarity index 100% rename from dgjy-toolkit.user.js rename to script/reference/dgjy-toolkit.user.js diff --git a/js/study-axios.mjs b/script/reference/study-axios.mjs similarity index 95% rename from js/study-axios.mjs rename to script/reference/study-axios.mjs index ae10be0..db3951c 100644 --- a/js/study-axios.mjs +++ b/script/reference/study-axios.mjs @@ -7,10 +7,10 @@ * * 用法: * MIDDLE_TOKEN='' \ - * node js/study-axios.mjs status 123456 + * node script/reference/study-axios.mjs status 123456 * - * MIDDLE_TOKEN=... node js/study-axios.mjs watch 123456 - * MIDDLE_TOKEN=... node js/study-axios.mjs watch 123456 --beat 2 --limit 900 + * MIDDLE_TOKEN=... node script/reference/study-axios.mjs watch 123456 + * MIDDLE_TOKEN=... node script/reference/study-axios.mjs watch 123456 --beat 2 --limit 900 * * 依赖:axios(npm i axios),Node >= 18。 */ @@ -206,7 +206,7 @@ try { if (cmd === 'status') await status(id); else if (cmd === 'watch') await watch(id, opts); else { - console.log('用法:node js/study-axios.mjs [--beat 2] [--limit 900]'); + console.log('用法:node script/reference/study-axios.mjs [--beat 2] [--limit 900]'); process.exit(2); } } catch (e) { diff --git a/src/study_tool/config.py b/src/study_tool/config.py index 9899f06..1498418 100644 --- a/src/study_tool/config.py +++ b/src/study_tool/config.py @@ -6,7 +6,7 @@ import os import re import shutil -# 包内路径 -> 项目根目录:data / static / des*.js 这些运行时资源都留在仓库根 +# 包内路径 -> 项目根目录:data / static / script 这些运行时资源都留在仓库根 HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.dirname(os.path.dirname(HERE)) DATA = os.path.join(ROOT, "data") @@ -26,7 +26,7 @@ def _find_node(): NODE = _find_node() -DESENC = os.path.join(ROOT, "desenc.js") +DESENC = os.path.join(ROOT, "script", "desenc.js") UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36 Edg/154.0.0.0") diff --git a/src/study_tool/engine.py b/src/study_tool/engine.py index 0bba7b9..2927d4f 100644 --- a/src/study_tool/engine.py +++ b/src/study_tool/engine.py @@ -8,6 +8,7 @@ import time from concurrent.futures import ThreadPoolExecutor, as_completed +from study_tool import store from study_tool.config import * from study_tool.platforms import registry from study_tool.platforms.jspx import * @@ -158,28 +159,33 @@ def study_worker(key, username, cookies, courses, workers, cap, quiz_key, def run_one_course(key, username, cookies, plan, project, workers, cap, quiz_key, enable_quiz=False, enable_feedback=True, name="", password="", mode="fast", parallel=2): - s = new_session(cookies) + # 账号添加时选的平台决定登录 / 发现走哪套实现;新增平台不用改这里 + account = store.account_get(key) or {} + adapter = registry.get(account.get("platform")) + if adapter is None or adapter.discover is None: + raise RuntimeError("平台 %s 没有可用的课程发现实现" % (account.get("platform") or "?")) + s = (adapter.session or new_session)(cookies) try: - d = discover(s, plan, project, name) + d = adapter.discover(s, plan, project, name) except SessionExpired: # 先试无密码续期(CASTGC 通常还有效),不行再用浏览器里存的账号密码重登 - log(key, "会话失效,尝试用 SSO 票据续期…") - renewed = ensure_jspx_session(s) + log(key, "会话失效,尝试无密码续期…") + renewed = adapter.renew_session(s) if adapter.renew_session else False d = None if renewed: try: - d = discover(s, plan, project, name) + d = adapter.discover(s, plan, project, name) except SessionExpired: d = None if d is None: - if not password: + if not password or adapter.login is None: raise - log(key, "SSO 票据已过期,用账号密码重新登录…") - s, _ = login(username, password) - d = discover(s, plan, project, name) + log(key, "续期失败,用账号密码重新登录…") + s, _ = adapter.login(username, password) + d = adapter.discover(s, plan, project, name) # 新平台可能刚在 discover 里换到 study.dgjy.net 的会话(Middle-Token),存回去给后续课程用 set_state(key, course=d["course"], progress=d["progress"], user=d["user"], - cookies=dump_cookies(s)) + cookies=(adapter.dump_cookies or dump_cookies)(s)) log(key, "课程:%s | 进度 %s | %s" % (d["course"], d["progress"], d["info"])) pf = registry.get(d.get("platform")) gen = d.get("generation") diff --git a/src/study_tool/models.py b/src/study_tool/models.py index 988b0ac..f4105b1 100644 --- a/src/study_tool/models.py +++ b/src/study_tool/models.py @@ -7,6 +7,7 @@ class LoginIn(BaseModel): username: str = "" password: str = "" account_id: str = "" # 只给账号 id 时,用户名/密码从 SQLite 里取,密码不出库 + platform: str = "guanyixue" # 没传 account_id 时按它选平台 class AccountsIn(BaseModel): @@ -16,6 +17,7 @@ class AccountsIn(BaseModel): class AccountIn(BaseModel): id: str = "" username: str = "" + platform: str = "guanyixue" # 添加账号时选的平台 password: str | None = None # 不传 = 保留库里已有的密码 note: str = "" user: str = "" @@ -33,6 +35,7 @@ class AccountIn(BaseModel): class CookiesIn(BaseModel): cookies: list + platform: str = "guanyixue" class DiscoverIn(BaseModel): @@ -40,6 +43,7 @@ class DiscoverIn(BaseModel): plan_id: str project_id: str name: str = "" + platform: str = "guanyixue" class StudyIn(BaseModel): @@ -72,6 +76,7 @@ class QuizIn(BaseModel): plan_id: str = "" project_id: str = "" name: str = "" + platform: str = "guanyixue" # retake=True:交卷后点「再考一次」,让平台生成新答卷(消耗一次机会) retake: bool = False period_id: str = "" # 指定要重考/查看的课时(不传就按原逻辑挑第一个) diff --git a/src/study_tool/platforms/base.py b/src/study_tool/platforms/base.py index 73446d5..ba3ed8c 100644 --- a/src/study_tool/platforms/base.py +++ b/src/study_tool/platforms/base.py @@ -26,6 +26,14 @@ class Platform: label: str # 日志 / 界面里的展示名 study: Optional[Callable] = None # 学一门课;None = 这个平台还没实现 entries: tuple = () # 登录 / 学习入口 URL 片段,用于识别平台 + # 账号级能力:添加账号时选了哪个平台,登录 / 发现 / 刷新课程就走哪个平台的实现 + session: Optional[Callable] = None # (cookies) -> requests.Session + dump_cookies: Optional[Callable] = None # (session) -> [cookie] + login: Optional[Callable] = None # (username, password) -> (session, user) + list_courses: Optional[Callable] = None # (session) -> [course] + discover: Optional[Callable] = None # (session, plan_id, project_id, name) -> 课程描述 + renew_session: Optional[Callable] = None # (session) -> bool,无密码续期 + profile: Optional[Callable] = None # (session) -> 显示名 def matches(self, url="", html=""): """登录入口或学习入口命中任意片段,就认为页面属于本平台。""" diff --git a/src/study_tool/platforms/guanyixue.py b/src/study_tool/platforms/guanyixue.py index 49cd69a..eeae652 100644 --- a/src/study_tool/platforms/guanyixue.py +++ b/src/study_tool/platforms/guanyixue.py @@ -1,8 +1,9 @@ """莞易学平台:jspx.dgjy.net(登录入口)与 study.dgjy.net(学习入口)是同一个平台。 -课程页有两代前端,`discover` 会把代际写进 `course["generation"]`(legacy / spa), -这里按代际分发到对应的学习实现。新增其他平台时,照本文件写一个模块: -在 `Platform.entries` 声明登录 / 学习入口,注册表就能按入口识别平台。 +账号在「添加账号」里选择平台(`accounts.platform`),登录 / 刷新课程 / 发现课程都会 +走这里的 `login` / `list_courses` / `discover`;学习时 `discover` 会把页面代际写进 +`course["generation"]`(legacy / spa),由 `_study` 分发到对应实现。 +新增其他平台时,照本文件写一个模块并在 `Platform.entries` 声明登录 / 学习入口。 """ from study_tool.platforms import jspx, registry, study from study_tool.platforms.base import Platform @@ -13,10 +14,19 @@ LABEL = "莞易学" ENTRIES = ("jspx.dgjy.net", "study.dgjy.net", "dgjy.net") +def _profile(s): + return jspx.whoami(jspx.fetch_admin(s)) + + def _study(key, s, d, **opts): if d.get("generation") == "spa": return study._study(key, s, d, **opts) return jspx._study(key, s, d, **opts) -PLATFORM = registry.register(Platform(id=ID, label=LABEL, study=_study, entries=ENTRIES)) +PLATFORM = registry.register(Platform( + id=ID, label=LABEL, study=_study, entries=ENTRIES, + session=jspx.new_session, dump_cookies=jspx.dump_cookies, + login=jspx.login, list_courses=jspx.scrape_courses, discover=jspx.discover, + renew_session=jspx.ensure_jspx_session, profile=_profile, +)) diff --git a/src/study_tool/quiz.py b/src/study_tool/quiz.py index 9fd3d83..2a850c5 100644 --- a/src/study_tool/quiz.py +++ b/src/study_tool/quiz.py @@ -10,6 +10,7 @@ from study_tool.config import * from study_tool.engine import * from study_tool.llm import * from study_tool.models import * +from study_tool.platforms import registry from study_tool.runtime import log # ------------------------------------------------------------------ quiz @@ -246,9 +247,12 @@ def api_quiz(b: QuizIn): """取一次测验的题目(含选项),供页面表格展示。""" if not b.cookies: return {"ok": False, "code": "no_cookie", "error": "尚未登录"} - s = new_session(b.cookies) + pf = registry.get(b.platform) + if pf is None or pf.discover is None: + return {"ok": False, "error": "平台「%s」还没有实现课程发现" % b.platform} + s = (pf.session or new_session)(b.cookies) try: - d = discover(s, b.plan_id, b.project_id, b.name) + d = pf.discover(s, b.plan_id, b.project_id, b.name) except SessionExpired as e: return {"ok": False, "code": "session_expired", "error": str(e)[:300]} except Exception as e: diff --git a/src/study_tool/routes/accounts.py b/src/study_tool/routes/accounts.py index 032b8f6..6d484b0 100644 --- a/src/study_tool/routes/accounts.py +++ b/src/study_tool/routes/accounts.py @@ -1,13 +1,16 @@ """账号 / 登录 / 登录记录接口。""" import time +from fastapi.responses import JSONResponse + from study_tool.webapp import app from study_tool import store from study_tool.config import * from study_tool.models import * +from study_tool.platforms import registry from study_tool.platforms.jspx import * -from study_tool.runtime import log +from study_tool.runtime import RUNS, RUNS_LOCK, log def _log_login(username, ok, code, error, elapsed, stage=""): """每次登录尝试:统一日志 + login_log 表(登录记录页用)。""" @@ -37,8 +40,14 @@ def api_login(b: LoginIn): _log_login(username or b.account_id, False, "no_credential", err, time.time() - t0, "LoginIn") return JSONResponse({"ok": False, "code": "no_credential", "error": err}, status_code=200) + pf = registry.get((acc or {}).get("platform") or b.platform) + if pf is None or pf.login is None: + err = "平台「%s」还没有实现登录,请换一个平台或先在 platforms/ 里补上实现" % ( + (acc or {}).get("platform") or b.platform) + _log_login(username, False, "no_platform", err, time.time() - t0, "LoginIn") + return JSONResponse({"ok": False, "code": "no_platform", "error": err}, status_code=200) try: - s, user = login(username, password) + s, user = pf.login(username, password) except Exception as e: err = str(e)[:300] _log_login(username, False, "login_failed", err, time.time() - t0, type(e).__name__) @@ -49,10 +58,10 @@ def api_login(b: LoginIn): return JSONResponse({"ok": False, "code": "login_failed", "error": err}, status_code=200) warn = "" try: - courses = scrape_courses(s) + courses = pf.list_courses(s) if pf.list_courses else [] except Exception as e: courses, warn = [], str(e)[:200] - cookies = dump_cookies(s) + cookies = (pf.dump_cookies or dump_cookies)(s) _log_login(username, True, "ok", warn, time.time() - t0, "user=%s" % user) if acc: store.account_save_login(acc["id"], user, cookies, courses) diff --git a/src/study_tool/routes/misc.py b/src/study_tool/routes/misc.py index 8514c93..a1b1879 100644 --- a/src/study_tool/routes/misc.py +++ b/src/study_tool/routes/misc.py @@ -65,13 +65,18 @@ def api_courses(b: CookiesIn): if not b.cookies: return JSONResponse({"ok": False, "code": "no_cookie", "error": "本机没有该账号的会话 cookie,请先点「登录」"}, status_code=200) - s = new_session(b.cookies) + pf = registry.get(b.platform) + if pf is None or pf.list_courses is None: + return JSONResponse({"ok": False, "code": "no_platform", + "error": "平台「%s」还没有实现刷新课程,请先在 platforms/ 里补上" + % b.platform}, status_code=200) + s = (pf.session or new_session)(b.cookies) if not s.cookies: return JSONResponse({"ok": False, "code": "no_cookie", "error": "保存的 cookie 全部被过滤(domain 不含 dgjy),请重新登录"}, status_code=200) try: - courses = scrape_courses(s) + courses = pf.list_courses(s) except SessionExpired as e: return JSONResponse({"ok": False, "code": "session_expired", "error": str(e)[:300]}, status_code=200) except Exception as e: @@ -81,21 +86,25 @@ def api_courses(b: CookiesIn): "error": "登录态有效,但该账号名下三个板块(在学/助学/督学)" "的进行中、未开始、已结束里都没有课程"}, status_code=200) try: - user = whoami(fetch_admin(s)) + user = pf.profile(s) if pf.profile else "" except Exception: user = "" return {"ok": True, "courses": courses, "user": user, "in_study": len([c for c in courses if c["in_study"]]), - # 补 jspx 会话时 cookie 会换新(JSESSIONID/route),回传让前端写回 IndexedDB - "cookies": dump_cookies(s)} + # 补 jspx 会话时 cookie 会换新(JSESSIONID/route),回传让前端写回 + "cookies": (pf.dump_cookies or dump_cookies)(s)} @app.post("/api/discover") def api_discover(b: DiscoverIn): - s = new_session(b.cookies) + pf = registry.get(b.platform) + if pf is None or pf.discover is None: + return JSONResponse({"ok": False, "code": "no_platform", + "error": "平台「%s」还没有实现课程发现" % b.platform}, status_code=200) + s = (pf.session or new_session)(b.cookies) try: - d = discover(s, b.plan_id, b.project_id, b.name) - return {"ok": True, **d, "cookies": dump_cookies(s)} + d = pf.discover(s, b.plan_id, b.project_id, b.name) + return {"ok": True, **d, "cookies": (pf.dump_cookies or dump_cookies)(s)} except Exception as e: return JSONResponse({"ok": False, "error": str(e)[:300]}, status_code=200) diff --git a/src/study_tool/store.py b/src/study_tool/store.py index 1c52045..0a2198d 100644 --- a/src/study_tool/store.py +++ b/src/study_tool/store.py @@ -59,6 +59,7 @@ CREATE TABLE IF NOT EXISTS kv ( CREATE TABLE IF NOT EXISTS accounts ( id TEXT PRIMARY KEY, username TEXT, + platform TEXT DEFAULT 'guanyixue', password TEXT, note TEXT, user TEXT, @@ -145,6 +146,7 @@ def conn(): with _lock: if not _ready: c.executescript(SCHEMA) + _ensure_columns(c) c.commit() _migrate(c) _ready = True @@ -189,6 +191,13 @@ def db_info(): # ------------------------------------------------------------------ 迁移 +def _ensure_columns(c): + """SQLite 没有 ADD COLUMN IF NOT EXISTS;老库缺字段时补上。""" + cols = {r["name"] for r in c.execute("PRAGMA table_info(accounts)")} + if "platform" not in cols: + c.execute("ALTER TABLE accounts ADD COLUMN platform TEXT DEFAULT 'guanyixue'") + + def _migrate(c): """把旧的文件式存储导入 SQLite;成功后把原文件改名成 *.imported。""" # 1) data/settings.json -> settings @@ -284,6 +293,7 @@ def _acc_row(r): return { "id": r["id"], "username": r["username"] or "", + "platform": r["platform"] or "guanyixue", "note": r["note"] or "", "user": r["user"] or "", "cookies": loads(r["cookies"], []) or [], @@ -336,14 +346,16 @@ def account_upsert(rec): pwd = rec.get("password") if pwd is not None: pwd = str(pwd) + platform = (rec.get("platform") or "").strip() or None selected = loads(dumps(rec.get("selected") or []), []) or [] write( """INSERT INTO accounts - (id, username, password, note, user, cookies, courses, selected, status, + (id, username, platform, password, note, user, cookies, courses, selected, status, last_error, last_error_at, opt_quiz, opt_feedback, login_at, created, updated) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET username = excluded.username, + platform = COALESCE(excluded.platform, accounts.platform), password = COALESCE(excluded.password, accounts.password), note = excluded.note, user = excluded.user, @@ -357,7 +369,7 @@ def account_upsert(rec): opt_feedback = excluded.opt_feedback, login_at = excluded.login_at, updated = excluded.updated""", - (aid, rec.get("username") or "", pwd, rec.get("note") or "", rec.get("user") or "", + (aid, rec.get("username") or "", platform, pwd, rec.get("note") or "", rec.get("user") or "", dumps(rec.get("cookies") or []), dumps(rec.get("courses") or []), dumps(selected), rec.get("status") or "idle", rec.get("lastError") or "", float(rec.get("lastErrorAt") or 0), diff --git a/static/assets/index-BubgUKHl.css b/static/assets/index-BubgUKHl.css new file mode 100644 index 0000000..f0841f3 --- /dev/null +++ b/static/assets/index-BubgUKHl.css @@ -0,0 +1 @@ +/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:"Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, "Microsoft YaHei", sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-sky-50:oklch(97.7% .013 236.62);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-600:oklch(58.8% .158 241.966);--color-sky-700:oklch(50% .134 242.749);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-xl:36rem;--container-3xl:48rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-brand-50:#eef4ff;--color-brand-100:#dbe7ff;--color-brand-200:#bfd4ff;--color-brand-500:#2f6bff;--color-brand-600:#1f55e0;--color-brand-700:#1a46bd;--color-line:#e6eaf2}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{color-scheme:light;scroll-behavior:smooth}body{min-height:100vh;color:var(--color-slate-900);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:var(--font-sans);background-color:#f5f7fb}::selection{background:#2f6bff2e}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.top-0{top:0}.top-1\/2{top:50%}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-0{right:0}.right-2\.5{right:calc(var(--spacing) * 2.5)}.-bottom-0\.5{bottom:calc(var(--spacing) * -.5)}.bottom-7{bottom:calc(var(--spacing) * 7)}.bottom-10{bottom:calc(var(--spacing) * 10)}.left-1\/2{left:50%}.left-2\.5{left:calc(var(--spacing) * 2.5)}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.z-\[60\]{z-index:60}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mr-1{margin-right:var(--spacing)}.mr-auto{margin-right:auto}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-1{margin-left:var(--spacing)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-16{height:calc(var(--spacing) * 16)}.h-\[60vh\]{height:60vh}.h-full{height:100%}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-\[196px\]{max-height:196px}.max-h-\[calc\(100vh-2rem\)\]{max-height:calc(100vh - 2rem)}.min-h-0{min-height:0}.min-h-24{min-height:calc(var(--spacing) * 24)}.min-h-\[70px\]{min-height:70px}.min-h-screen{min-height:100vh}.w-9{width:calc(var(--spacing) * 9)}.w-40{width:calc(var(--spacing) * 40)}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[50\%\]{max-width:50%}.max-w-\[85vw\]{max-width:85vw}.max-w-\[320px\]{max-width:320px}.max-w-\[1320px\]{max-width:1320px}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-180{rotate:180deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.scrollbar-thin{scrollbar-width:thin}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1\.5{row-gap:calc(var(--spacing) * 1.5)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-brand-100{border-color:var(--color-brand-100)}.border-brand-500{border-color:var(--color-brand-500)}.border-emerald-200{border-color:var(--color-emerald-200)}.border-line{border-color:var(--color-line)}.border-line\/70{border-color:#e6eaf2b3}@supports (color:color-mix(in lab,red,red)){.border-line\/70{border-color:color-mix(in oklab,var(--color-line) 70%,transparent)}}.border-line\/80{border-color:#e6eaf2cc}@supports (color:color-mix(in lab,red,red)){.border-line\/80{border-color:color-mix(in oklab,var(--color-line) 80%,transparent)}}.border-red-200{border-color:var(--color-red-200)}.border-slate-300{border-color:var(--color-slate-300)}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-brand-50{background-color:var(--color-brand-50)}.bg-brand-500{background-color:var(--color-brand-500)}.bg-current{background-color:currentColor}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-50\/80{background-color:#fef2f2cc}@supports (color:color-mix(in lab,red,red)){.bg-red-50\/80{background-color:color-mix(in oklab,var(--color-red-50) 80%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-sky-50{background-color:var(--color-sky-50)}.bg-sky-500{background-color:var(--color-sky-500)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-50\/70{background-color:#f8fafcb3}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/70{background-color:color-mix(in oklab,var(--color-slate-50) 70%,transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-300{background-color:var(--color-slate-300)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/40{background-color:#0f172b66}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/40{background-color:color-mix(in oklab,var(--color-slate-900) 40%,transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-slate-950\/95{background-color:#020618f2}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/95{background-color:color-mix(in oklab,var(--color-slate-950) 95%,transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab,red,red)){.bg-white\/85{background-color:color-mix(in oklab,var(--color-white) 85%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-brand-50{--tw-gradient-from:var(--color-brand-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-brand-500{--tw-gradient-from:var(--color-brand-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-sky-50{--tw-gradient-to:var(--color-sky-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-sky-400{--tw-gradient-to:var(--color-sky-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-0{padding:0}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-16{padding-block:calc(var(--spacing) * 16)}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-1{padding-top:var(--spacing)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pl-7{padding-left:calc(var(--spacing) * 7)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[17px\]{font-size:17px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-brand-500{color:var(--color-brand-500)}.text-brand-600{color:var(--color-brand-600)}.text-brand-700{color:var(--color-brand-700)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-emerald-800{color:var(--color-emerald-800)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-sky-600{color:var(--color-sky-600)}.text-sky-700{color:var(--color-sky-700)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.accent-brand-500{accent-color:var(--color-brand-500)}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-brand-500\/25{--tw-shadow-color:#2f6bff40}@supports (color:color-mix(in lab,red,red)){.shadow-brand-500\/25{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-brand-500) 25%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-brand-500\/30{--tw-shadow-color:#2f6bff4d}@supports (color:color-mix(in lab,red,red)){.shadow-brand-500\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-brand-500) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-900\/10{--tw-shadow-color:#0f172b1a}@supports (color:color-mix(in lab,red,red)){.shadow-slate-900\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-900) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-900\/20{--tw-shadow-color:#0f172b33}@supports (color:color-mix(in lab,red,red)){.shadow-slate-900\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-900) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-amber-100{--tw-ring-color:var(--color-amber-100)}.ring-brand-100{--tw-ring-color:var(--color-brand-100)}.ring-emerald-100{--tw-ring-color:var(--color-emerald-100)}.ring-line{--tw-ring-color:var(--color-line)}.ring-red-100{--tw-ring-color:var(--color-red-100)}.ring-sky-100{--tw-ring-color:var(--color-sky-100)}.ring-slate-200{--tw-ring-color:var(--color-slate-200)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ring-inset{--tw-ring-inset:inset}.placeholder\:text-slate-400::placeholder{color:var(--color-slate-400)}@media(hover:hover){.hover\:border-brand-200:hover{border-color:var(--color-brand-200)}.hover\:border-brand-600:hover{border-color:var(--color-brand-600)}.hover\:border-line:hover{border-color:var(--color-line)}.hover\:border-slate-300:hover{border-color:var(--color-slate-300)}.hover\:border-slate-300\/80:hover{border-color:#cad5e2cc}@supports (color:color-mix(in lab,red,red)){.hover\:border-slate-300\/80:hover{border-color:color-mix(in oklab,var(--color-slate-300) 80%,transparent)}}.hover\:bg-brand-50:hover{background-color:var(--color-brand-50)}.hover\:bg-brand-100:hover{background-color:var(--color-brand-100)}.hover\:bg-brand-600:hover{background-color:var(--color-brand-600)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:text-slate-600:hover{color:var(--color-slate-600)}}.focus\:border-brand-500:focus{border-color:var(--color-brand-500)}.focus\:ring-3:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-brand-500\/15:focus{--tw-ring-color:#2f6bff26}@supports (color:color-mix(in lab,red,red)){.focus\:ring-brand-500\/15:focus{--tw-ring-color:color-mix(in oklab, var(--color-brand-500) 15%, transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-3:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-brand-500\/20:focus-visible{--tw-ring-color:#2f6bff33}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-brand-500\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-brand-500) 20%, transparent)}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-50:disabled{background-color:var(--color-slate-50)}.disabled\:text-slate-400:disabled{color:var(--color-slate-400)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:40rem){.sm\:inline{display:inline}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:64rem){.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.scrollbar-thin{scrollbar-width:thin;scrollbar-color:#c9d2e3 transparent}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-thumb{background:#c9d2e3;border-radius:999px}.card-shadow{box-shadow:0 1px 2px #1018280a,0 18px 36px -24px #10182838}.animate-toast-in{animation:.24s cubic-bezier(.2,.8,.2,1) toast-in}}@keyframes toast-in{0%{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}} diff --git a/static/assets/index-CkxeZCl8.js b/static/assets/index-CkxeZCl8.js deleted file mode 100644 index 4ff536f..0000000 --- a/static/assets/index-CkxeZCl8.js +++ /dev/null @@ -1,228 +0,0 @@ -var Sh=Object.defineProperty;var Th=(r,E,z)=>E in r?Sh(r,E,{enumerable:!0,configurable:!0,writable:!0,value:z}):r[E]=z;var Li=(r,E,z)=>Th(r,typeof E!="symbol"?E+"":E,z);(function(){const E=document.createElement("link").relList;if(E&&E.supports&&E.supports("modulepreload"))return;for(const C of document.querySelectorAll('link[rel="modulepreload"]'))d(C);new MutationObserver(C=>{for(const B of C)if(B.type==="childList")for(const M of B.addedNodes)M.tagName==="LINK"&&M.rel==="modulepreload"&&d(M)}).observe(document,{childList:!0,subtree:!0});function z(C){const B={};return C.integrity&&(B.integrity=C.integrity),C.referrerPolicy&&(B.referrerPolicy=C.referrerPolicy),C.crossOrigin==="use-credentials"?B.credentials="include":C.crossOrigin==="anonymous"?B.credentials="omit":B.credentials="same-origin",B}function d(C){if(C.ep)return;C.ep=!0;const B=z(C);fetch(C.href,B)}})();var As={exports:{}},dn={};/** - * @license React - * react-jsx-runtime.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var sm;function Nh(){if(sm)return dn;sm=1;var r=Symbol.for("react.transitional.element"),E=Symbol.for("react.fragment");function z(d,C,B){var M=null;if(B!==void 0&&(M=""+B),C.key!==void 0&&(M=""+C.key),"key"in C){B={};for(var ut in C)ut!=="key"&&(B[ut]=C[ut])}else B=C;return C=B.ref,{$$typeof:r,type:d,key:M,ref:C!==void 0?C:null,props:B}}return dn.Fragment=E,dn.jsx=z,dn.jsxs=z,dn}var rm;function Eh(){return rm||(rm=1,As.exports=Nh()),As.exports}var f=Eh(),js={exports:{}},nt={};/** - * @license React - * react.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var om;function zh(){if(om)return nt;om=1;var r=Symbol.for("react.transitional.element"),E=Symbol.for("react.portal"),z=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),C=Symbol.for("react.profiler"),B=Symbol.for("react.consumer"),M=Symbol.for("react.context"),ut=Symbol.for("react.forward_ref"),tt=Symbol.for("react.suspense"),V=Symbol.for("react.memo"),R=Symbol.for("react.lazy"),T=Symbol.for("react.activity"),Z=Symbol.for("react.view_transition"),$=Symbol.iterator;function it(o){return o===null||typeof o!="object"?null:(o=$&&o[$]||o["@@iterator"],typeof o=="function"?o:null)}var Ut={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Y=Object.assign,vt={};function pt(o,N,w){this.props=o,this.context=N,this.refs=vt,this.updater=w||Ut}pt.prototype.isReactComponent={},pt.prototype.setState=function(o,N){if(typeof o!="object"&&typeof o!="function"&&o!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,o,N,"setState")},pt.prototype.forceUpdate=function(o){this.updater.enqueueForceUpdate(this,o,"forceUpdate")};function Ct(){}Ct.prototype=pt.prototype;function Ft(o,N,w){this.props=o,this.context=N,this.refs=vt,this.updater=w||Ut}var St=Ft.prototype=new Ct;St.constructor=Ft,Y(St,pt.prototype),St.isPureReactComponent=!0;var J=Array.isArray;function K(){}var k={H:null,A:null,T:null,S:null},_t=Object.prototype.hasOwnProperty;function qt(o,N,w){var G=w.ref;return{$$typeof:r,type:o,key:N,ref:G!==void 0?G:null,props:w}}function Zt(o,N){return qt(o.type,N,o.props)}function Tt(o){return typeof o=="object"&&o!==null&&o.$$typeof===r}function Jt(o){var N={"=":"=0",":":"=2"};return"$"+o.replace(/[=:]/g,function(w){return N[w]})}var al=/\/+/g;function Qt(o,N){return typeof o=="object"&&o!==null&&o.key!=null?Jt(""+o.key):N.toString(36)}function U(o){switch(o.status){case"fulfilled":return o.value;case"rejected":throw o.reason;default:switch(typeof o.status=="string"?o.then(K,K):(o.status="pending",o.then(function(N){o.status==="pending"&&(o.status="fulfilled",o.value=N)},function(N){o.status==="pending"&&(o.status="rejected",o.reason=N)})),o.status){case"fulfilled":return o.value;case"rejected":throw o.reason}}throw o}function F(o,N,w,G,ot){var x=typeof o;(x==="undefined"||x==="boolean")&&(o=null);var j=!1;if(o===null)j=!0;else switch(x){case"bigint":case"string":case"number":j=!0;break;case"object":switch(o.$$typeof){case r:case E:j=!0;break;case R:return j=o._init,F(j(o._payload),N,w,G,ot)}}if(j)return ot=ot(o),j=G===""?"."+Qt(o,0):G,J(ot)?(w="",j!=null&&(w=j.replace(al,"$&/")+"/"),F(ot,N,w,"",function(lt){return lt})):ot!=null&&(Tt(ot)&&(ot=Zt(ot,w+(ot.key==null||o&&o.key===ot.key?"":(""+ot.key).replace(al,"$&/")+"/")+j)),N.push(ot)),1;j=0;var p=G===""?".":G+":";if(J(o))for(var A=0;A>>1,H=U[gt];if(0>>1;gtC(Bt,I))oC(N,Bt)?(U[gt]=N,U[o]=I,gt=o):(U[gt]=Bt,U[st]=I,gt=st);else if(oC(N,I))U[gt]=N,U[o]=I,gt=o;else break t}}return F}function C(U,F){var I=U.sortIndex-F.sortIndex;return I!==0?I:U.id-F.id}if(r.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var B=performance;r.unstable_now=function(){return B.now()}}else{var M=Date,ut=M.now();r.unstable_now=function(){return M.now()-ut}}var tt=[],V=[],R=1,T=null,Z=3,$=!1,it=!1,Ut=!1,Y=!1,vt=typeof setTimeout=="function"?setTimeout:null,pt=typeof clearTimeout=="function"?clearTimeout:null,Ct=typeof setImmediate<"u"?setImmediate:null;function Ft(U){for(var F=z(V);F!==null;){if(F.callback===null)d(V);else if(F.startTime<=U)d(V),F.sortIndex=F.expirationTime,E(tt,F);else break;F=z(V)}}function St(U){if(Ut=!1,Ft(U),!it)if(z(tt)!==null)it=!0,J||(J=!0,Tt());else{var F=z(V);F!==null&&Qt(St,F.startTime-U)}}var J=!1,K=-1,k=5,_t=-1;function qt(){return Y?!0:!(r.unstable_now()-_tU&&qt());){var gt=T.callback;if(typeof gt=="function"){T.callback=null,Z=T.priorityLevel;var H=gt(T.expirationTime<=U);if(U=r.unstable_now(),typeof H=="function"){T.callback=H,Ft(U),F=!0;break l}T===z(tt)&&d(tt),Ft(U)}else d(tt);T=z(tt)}if(T!==null)F=!0;else{var at=z(V);at!==null&&Qt(St,at.startTime-U),F=!1}}break t}finally{T=null,Z=I,$=!1}F=void 0}}finally{F?Tt():J=!1}}}var Tt;if(typeof Ct=="function")Tt=function(){Ct(Zt)};else if(typeof MessageChannel<"u"){var Jt=new MessageChannel,al=Jt.port2;Jt.port1.onmessage=Zt,Tt=function(){al.postMessage(null)}}else Tt=function(){vt(Zt,0)};function Qt(U,F){K=vt(function(){U(r.unstable_now())},F)}r.unstable_IdlePriority=5,r.unstable_ImmediatePriority=1,r.unstable_LowPriority=4,r.unstable_NormalPriority=3,r.unstable_Profiling=null,r.unstable_UserBlockingPriority=2,r.unstable_cancelCallback=function(U){U.callback=null},r.unstable_forceFrameRate=function(U){0>U||125gt?(U.sortIndex=I,E(V,U),z(tt)===null&&U===z(V)&&(Ut?(pt(K),K=-1):Ut=!0,Qt(St,I-gt))):(U.sortIndex=H,E(tt,U),it||$||(it=!0,J||(J=!0,Tt()))),U},r.unstable_shouldYield=qt,r.unstable_wrapCallback=function(U){var F=Z;return function(){var I=Z;Z=F;try{return U.apply(this,arguments)}finally{Z=I}}}})(Ds)),Ds}var ym;function Oh(){return ym||(ym=1,Cs.exports=_h()),Cs.exports}var Us={exports:{}},yl={};/** - * @license React - * react-dom.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var hm;function Ah(){if(hm)return yl;hm=1;var r=qs();function E(R){var T="https://react.dev/errors/"+R;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(r)}catch(E){console.error(E)}}return r(),Us.exports=Ah(),Us.exports}/** - * @license React - * react-dom-client.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var gm;function Mh(){if(gm)return mn;gm=1;var r=Oh(),E=qs(),z=jh();function d(t){var l="https://react.dev/errors/"+t;if(1q||(t.current=P[q],P[q]=null,q--)}function Nt(t,l){q++,P[q]=t.current,t.current=l}var te=Yt(null),gu=Yt(null),je=Yt(null),hn=Yt(null);function vn(t,l){switch(Nt(je,l),Nt(gu,t),Nt(te,null),l.nodeType){case 9:case 11:t=(t=l.documentElement)&&(t=t.namespaceURI)?b0(t):0;break;default:if(t=l.tagName,l=l.namespaceURI)l=b0(l),t=x0(l,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}Rt(te),Nt(te,t)}function Oa(){Rt(te),Rt(gu),Rt(je)}function Ji(t){var l=t.memoizedState;l!==null&&(yu._currentValue=l.memoizedState,Nt(hn,t)),l=te.current;var e=x0(l,t.type);l!==e&&(Nt(gu,t),Nt(te,e))}function gn(t){gu.current===t&&(Rt(te),Rt(gu)),hn.current===t&&(Rt(hn),yu._currentValue=lt)}var ki,Ys;function Me(t){if(ki===void 0)try{throw Error()}catch(e){var l=e.stack.trim().match(/\n( *(at )?)/);ki=l&&l[1]||"",Ys=-1)":-1u||s[a]!==v[u]){var S=` -`+s[a].replace(" at new "," at ");return t.displayName&&S.includes("")&&(S=S.replace("",t.displayName)),S}while(1<=a&&0<=u);break}}}finally{$i=!1,Error.prepareStackTrace=e}return(e=t?t.displayName||t.name:"")?Me(e):""}function zm(t,l){switch(t.tag){case 26:case 27:case 5:return Me(t.type);case 16:return Me("Lazy");case 13:return t.child!==l&&l!==null?Me("Suspense Fallback"):Me("Suspense");case 19:return Me("SuspenseList");case 0:case 15:return Fi(t.type,!1);case 11:return Fi(t.type.render,!1);case 1:return Fi(t.type,!0);case 31:return Me("Activity");case 30:return Me("ViewTransition");default:return""}}function ws(t){try{var l="",e=null;do l+=zm(t,e),e=t,t=t.return;while(t);return l}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var Wi=Object.prototype.hasOwnProperty,Ii=r.unstable_scheduleCallback,Pi=r.unstable_cancelCallback,_m=r.unstable_shouldYield,Om=r.unstable_requestPaint,Ol=r.unstable_now,Am=r.unstable_getCurrentPriorityLevel,Gs=r.unstable_ImmediatePriority,Qs=r.unstable_UserBlockingPriority,bn=r.unstable_NormalPriority,jm=r.unstable_LowPriority,Xs=r.unstable_IdlePriority,Mm=r.log,Cm=r.unstable_setDisableYieldValue,bu=null,Al=null;function Ce(t){if(typeof Mm=="function"&&Cm(t),Al&&typeof Al.setStrictMode=="function")try{Al.setStrictMode(bu,t)}catch{}}var jl=Math.clz32?Math.clz32:Rm,Dm=Math.log,Um=Math.LN2;function Rm(t){return t>>>=0,t===0?32:31-(Dm(t)/Um|0)|0}var xn=256,pn=262144,Sn=4194304;function ua(t){var l=t&42;if(l!==0)return l;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&-t;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function Tn(t,l,e){var a=t.pendingLanes;if(a===0)return 0;var u=0,n=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var c=a&134217727;return c!==0?(a=c&~n,a!==0?u=ua(a):(i&=c,i!==0?u=ua(i):e||(e=c&~t,e!==0&&(u=ua(e))))):(c=a&~n,c!==0?u=ua(c):i!==0?u=ua(i):e||(e=a&~t,e!==0&&(u=ua(e)))),u===0?0:l!==0&&l!==u&&(l&n)===0&&(n=u&-u,e=l&-l,n>=e||n===32&&(e&4194048)!==0)?l:u}function xu(t,l){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&l)===0}function Vs(t,l){(l&8)!==0&&(l|=l&32);var e=t.entangledLanes;if(e!==0)for(t=t.entanglements,e&=l;0e;e++)l.push(t);return l}function pu(t,l){t.pendingLanes|=l,l!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function qm(t,l,e,a,u,n){var i=t.pendingLanes;t.pendingLanes=e,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=e,t.entangledLanes&=e,t.errorRecoveryDisabledLanes&=e,t.shellSuspendCounter=0;var c=t.entanglements,s=t.expirationTimes,v=t.hiddenUpdates;for(e=i&~e;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),rc=!1;if(he)try{var Eu={};Object.defineProperty(Eu,"passive",{get:function(){rc=!0}}),window.addEventListener("test",Eu,Eu),window.removeEventListener("test",Eu,Eu)}catch{rc=!1}var De=null,oc=null,An=null;function mr(){if(An)return An;var t,l=oc,e=l.length,a,u="value"in De?De.value:De.textContent,n=u.length;for(t=0;t=Ou),xr=" ",pr=!1;function Sr(t,l){switch(t){case"keyup":return b1.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Tr(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var qa=!1;function p1(t,l){switch(t){case"compositionend":return Tr(l);case"keypress":return l.which!==32?null:(pr=!0,xr);case"textInput":return t=l.data,t===xr&&pr?null:t;default:return null}}function S1(t,l){if(qa)return t==="compositionend"||!vc&&Sr(t,l)?(t=mr(),An=oc=De=null,qa=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1"u")return null;try{return t.activeElement||t.body}catch{return t.body}}function Mr(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function Cr(t,l){var e=Mr(t);t=0;for(var a;e;){if(e.nodeType===3){if(a=t+e.textContent.length,t<=l&&a>=l)return{node:e,offset:l-t};t=a}t:{for(;e;){if(e.nextSibling){e=e.nextSibling;break t}e=e.parentNode}e=void 0}e=Mr(e)}}function Dr(t,l){return t&&l?t===l?!0:t&&t.nodeType===3?!1:l&&l.nodeType===3?Dr(t,l.parentNode):"contains"in t?t.contains(l):t.compareDocumentPosition?!!(t.compareDocumentPosition(l)&16):!1:!1}function Ur(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var l=xc(t.document);l instanceof t.HTMLIFrameElement;){try{var e=typeof l.contentWindow.location.href=="string"}catch{e=!1}if(e)t=l.contentWindow;else break;l=xc(t.document)}return l}function pc(t){var l=t&&t.nodeName&&t.nodeName.toLowerCase();return l&&(l==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||l==="textarea"||t.contentEditable==="true")}var j1=he&&"documentMode"in document&&11>=document.documentMode,Ba=null,Sc=null,Cu=null,Tc=!1;function Rr(t,l,e){var a=e.window===e?e.document:e.nodeType===9?e:e.ownerDocument;Tc||Ba==null||Ba!==xc(a)||(a=Ba,"selectionStart"in a&&pc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Cu&&Mu(Cu,a)||(Cu=a,a=Ui(Sc,"onSelect"),0>=i,u-=i,ee=1<<32-jl(l)+u|e<et?(ll=W,W=null):ll=W.sibling;var bt=y(h,W,g[et],_);if(bt===null){W===null&&(W=ll);break}t&&W&&bt.alternate===null&&l(h,W),m=n(bt,m,et),ht===null?Q=bt:ht.sibling=bt,ht=bt,W=ll}if(et===g.length)return e(h,W),rt&&xe(h,et),Q;if(W===null){for(;etet?(ll=W,W=null):ll=W.sibling;var aa=y(h,W,bt.value,_);if(aa===null){W===null&&(W=ll);break}t&&W&&aa.alternate===null&&l(h,W),m=n(aa,m,et),ht===null?Q=aa:ht.sibling=aa,ht=aa,W=ll}if(bt.done)return e(h,W),rt&&xe(h,et),Q;if(W===null){for(;!bt.done;et++,bt=g.next())bt=O(h,bt.value,_),bt!==null&&(m=n(bt,m,et),ht===null?Q=bt:ht.sibling=bt,ht=bt);return rt&&xe(h,et),Q}for(W=a(W);!bt.done;et++,bt=g.next())bt=b(W,h,et,bt.value,_),bt!==null&&(t&&(ll=bt.alternate,ll!==null&&W.delete(ll.key===null?et:ll.key)),m=n(bt,m,et),ht===null?Q=bt:ht.sibling=bt,ht=bt);return t&&W.forEach(function(ph){return l(h,ph)}),rt&&xe(h,et),Q}function ft(h,m,g,_){if(typeof g=="object"&&g!==null&&g.type===Zt&&g.key===null&&g.props.ref===void 0&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case _t:t:{for(var Q=g.key;m!==null;){if(m.key===Q){if(Q=g.type,Q===Zt){if(m.tag===7){e(h,m.sibling),_=u(m,g.props.children),Ye(_,g),_.return=h,h=_;break t}}else if(m.elementType===Q||typeof Q=="object"&&Q!==null&&Q.$$typeof===H&&ga(Q)===m.type){e(h,m.sibling),_=u(m,g.props),Ye(_,g),_.return=h,h=_;break t}e(h,m);break}else l(h,m);m=m.sibling}g.type===Zt?(_=ra(g.props.children,h.mode,_,g.key),Ye(_,g),_.return=h,h=_):(_=Yn(g.type,g.key,g.props,null,h.mode,_),Ye(_,g),_.return=h,h=_)}return i(h);case qt:t:{for(Q=g.key;m!==null;){if(m.key===Q)if(m.tag===4&&m.stateNode.containerInfo===g.containerInfo&&m.stateNode.implementation===g.implementation){e(h,m.sibling),_=u(m,g.children||[]),_.return=h,h=_;break t}else{e(h,m);break}else l(h,m);m=m.sibling}_=jc(g,h.mode,_),_.return=h,h=_}return i(h);case H:return g=ga(g),ft(h,m,g,_)}if(j(g))return D(h,m,g,_);if(G(g)){if(Q=G(g),typeof Q!="function")throw Error(d(150));return g=Q.call(g),L(h,m,g,_)}if(typeof g.then=="function")return ft(h,m,kn(g),_);if(g.$$typeof===Qt)return ft(h,m,Zn(h,g),_);$n(h,g)}return typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint"?(g=""+g,m!==null&&m.tag===6?(e(h,m.sibling),_=u(m,g),_.return=h,h=_):(e(h,m),_=Ac(g,h.mode,_),_.return=h,h=_),i(h)):e(h,m)}return function(h,m,g,_){try{Bu=0;var Q=ft(h,m,g,_);return Ka=null,Q}catch(W){if(W===La||W===Kn)throw W;var ht=Tl(29,W,null,h.mode);return ht.lanes=_,ht.return=h,ht}finally{}}}var xa=uo(!0),no=uo(!1),we=!1;function wc(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Gc(t,l){t=t.updateQueue,l.updateQueue===t&&(l.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Ge(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Qe(t,l,e){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(Et&2)!==0){var u=a.pending;return u===null?l.next=l:(l.next=u.next,u.next=l),a.pending=l,l=Bn(t),Xr(t,null,e),l}return qn(t,a,l,e),Bn(t)}function Yu(t,l,e){if(l=l.updateQueue,l!==null&&(l=l.shared,(e&4194048)!==0)){var a=l.lanes;a&=t.pendingLanes,e|=a,l.lanes=e,Ks(t,e)}}function Qc(t,l){var e=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,e===a)){var u=null,n=null;if(e=e.firstBaseUpdate,e!==null){do{var i={lane:e.lane,tag:e.tag,payload:e.payload,callback:null,next:null};n===null?u=n=i:n=n.next=i,e=e.next}while(e!==null);n===null?u=n=l:n=n.next=l}else u=n=l;e={baseState:a.baseState,firstBaseUpdate:u,lastBaseUpdate:n,shared:a.shared,callbacks:a.callbacks},t.updateQueue=e;return}t=e.lastBaseUpdate,t===null?e.firstBaseUpdate=l:t.next=l,e.lastBaseUpdate=l}var Xc=!1;function wu(){if(Xc){var t=Za;if(t!==null)throw t}}function Gu(t,l,e,a){Xc=!1;var u=t.updateQueue;we=!1;var n=u.firstBaseUpdate,i=u.lastBaseUpdate,c=u.shared.pending;if(c!==null){u.shared.pending=null;var s=c,v=s.next;s.next=null,i===null?n=v:i.next=v,i=s;var S=t.alternate;S!==null&&(S=S.updateQueue,c=S.lastBaseUpdate,c!==i&&(c===null?S.firstBaseUpdate=v:c.next=v,S.lastBaseUpdate=s))}if(n!==null){var O=u.baseState;i=0,S=v=s=null,c=n;do{var y=c.lane&-536870913,b=y!==c.lane;if(b?(yt&y)===y:(a&y)===y){y!==0&&y===ha&&(Xc=!0),S!==null&&(S=S.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});t:{var D=t,L=c;y=l;var ft=e;switch(L.tag){case 1:if(D=L.payload,typeof D=="function"){O=D.call(ft,O,y);break t}O=D;break t;case 3:D.flags=D.flags&-65537|128;case 0:if(D=L.payload,y=typeof D=="function"?D.call(ft,O,y):D,y==null)break t;O=K({},O,y);break t;case 2:we=!0}}y=c.callback,y!==null&&(t.flags|=64,b&&(t.flags|=8192),b=u.callbacks,b===null?u.callbacks=[y]:b.push(y))}else b={lane:y,tag:c.tag,payload:c.payload,callback:c.callback,next:null},S===null?(v=S=b,s=O):S=S.next=b,i|=y;if(c=c.next,c===null){if(c=u.shared.pending,c===null)break;b=c,c=b.next,b.next=null,u.lastBaseUpdate=b,u.shared.pending=null}}while(!0);S===null&&(s=O),u.baseState=s,u.firstBaseUpdate=v,u.lastBaseUpdate=S,n===null&&(u.shared.lanes=0),ke|=i,t.lanes=i,t.memoizedState=O}}function io(t,l){if(typeof t!="function")throw Error(d(191,t));t.call(l)}function co(t,l){var e=t.callbacks;if(e!==null)for(t.callbacks=null,t=0;tn?n:8;var i=p.T,c={};c.types=i!==null?i.types:null,p.T=c,sf(t,!1,l,e);try{var s=u(),v=p.S;if(v!==null&&v(c,s),s!==null&&typeof s=="object"&&typeof s.then=="function"){var S=G1(s,a);Zu(t,l,S,ql(t))}else Zu(t,l,a,ql(t))}catch(O){Zu(t,l,{then:function(){},status:"rejected",reason:O},ql())}finally{A.p=n,i!==null&&c.types!==null&&(i.types=c.types),p.T=i}}function K1(){}function cf(t,l,e,a){if(t.tag!==5)throw Error(d(476));var u=Go(t).queue;wo(t,u,l,lt,e===null?K1:function(){return Qo(t),e(a)})}function Go(t){var l=t.memoizedState;if(l!==null)return l;l={memoizedState:lt,baseState:lt,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ne,lastRenderedState:lt},next:null};var e={};return l.next={memoizedState:e,baseState:e,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ne,lastRenderedState:e},next:null},t.memoizedState=l,t=t.alternate,t!==null&&(t.memoizedState=l),l}function Qo(t){var l=Go(t);l.next===null&&(l=t.alternate.memoizedState),Zu(t,l.next.queue,{},ql())}function ff(){return sl(yu)}function Xo(){return Wt().memoizedState}function Vo(){return Wt().memoizedState}function J1(t){for(var l=t.return;l!==null;){switch(l.tag){case 24:case 3:var e=ql();t=Ge(e);var a=Qe(l,t,e);a!==null&&(_l(a,l,e),Yu(a,l,e)),l={cache:Hc()},t.payload=l;return}l=l.return}}function k1(t,l,e){var a=ql();e={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null},ni(t)?Lo(l,e):(e=_c(t,l,e,a),e!==null&&(_l(e,t,a),Ko(e,l,a)))}function Zo(t,l,e){var a=ql();Zu(t,l,e,a)}function Zu(t,l,e,a){var u={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null};if(ni(t))Lo(l,u);else{var n=t.alternate;if(t.lanes===0&&(n===null||n.lanes===0)&&(n=l.lastRenderedReducer,n!==null))try{var i=l.lastRenderedState,c=n(i,e);if(u.hasEagerState=!0,u.eagerState=c,Cl(c,i))return qn(t,l,u,0),Ht===null&&Hn(),!1}catch{}finally{}if(e=_c(t,l,u,a),e!==null)return _l(e,t,a),Ko(e,l,a),!0}return!1}function sf(t,l,e,a){if(a={lane:2,revertLane:Pf(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},ni(t)){if(l)throw Error(d(479))}else l=_c(t,e,a,2),l!==null&&_l(l,t,2)}function ni(t){var l=t.alternate;return t===ct||l!==null&&l===ct}function Lo(t,l){Ja=In=!0;var e=t.pending;e===null?l.next=l:(l.next=e.next,e.next=l),t.pending=l}function Ko(t,l,e){if((e&4194048)!==0){var a=l.lanes;a&=t.pendingLanes,e|=a,l.lanes=e,Ks(t,e)}}var ii={readContext:sl,use:li,useCallback:kt,useContext:kt,useEffect:kt,useImperativeHandle:kt,useLayoutEffect:kt,useInsertionEffect:kt,useMemo:kt,useReducer:kt,useRef:kt,useState:kt,useDebugValue:kt,useDeferredValue:kt,useTransition:kt,useSyncExternalStore:kt,useId:kt,useHostTransitionStatus:kt,useFormState:kt,useActionState:kt,useOptimistic:kt,useMemoCache:kt,useCacheRefresh:kt,useEffectEvent:kt},Jo={readContext:sl,use:li,useCallback:function(t,l){return bl().memoizedState=[t,l===void 0?null:l],t},useContext:sl,useEffect:Mo,useImperativeHandle:function(t,l,e){e=e!=null?e.concat([t]):null,ai(4194308,4,Ro.bind(null,l,t),e)},useLayoutEffect:function(t,l){return ai(4194308,4,t,l)},useInsertionEffect:function(t,l){ai(4,2,t,l)},useMemo:function(t,l){var e=bl();l=l===void 0?null:l;var a=t();if(pa){Ce(!0);try{t()}finally{Ce(!1)}}return e.memoizedState=[a,l],a},useReducer:function(t,l,e){var a=bl();if(e!==void 0){var u=e(l);if(pa){Ce(!0);try{e(l)}finally{Ce(!1)}}}else u=l;return a.memoizedState=a.baseState=u,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:u},a.queue=t,t=t.dispatch=k1.bind(null,ct,t),[a.memoizedState,t]},useRef:function(t){var l=bl();return t={current:t},l.memoizedState=t},useState:function(t){t=lf(t);var l=t.queue,e=Zo.bind(null,ct,l);return l.dispatch=e,[t.memoizedState,e]},useDebugValue:uf,useDeferredValue:function(t,l){var e=bl();return nf(e,t,l)},useTransition:function(){var t=lf(!1);return t=wo.bind(null,ct,t.queue,!0,!1),bl().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,l,e){var a=ct,u=bl();if(rt){if(e===void 0)throw Error(d(407));e=e()}else{if(e=l(),Ht===null)throw Error(d(349));(yt&127)!==0||yo(a,l,e)}u.memoizedState=e;var n={value:e,getSnapshot:l};return u.queue=n,Mo(vo.bind(null,a,n,t),[t]),a.flags|=2048,$a(9,{destroy:void 0},ho.bind(null,a,n,e,l),null),e},useId:function(){var t=bl(),l=Ht.identifierPrefix;if(rt){var e=ae,a=ee;e=(a&~(1<<32-jl(a)-1)).toString(32)+e,l="_"+l+"R_"+e,e=Pn++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?n.multiple=!0:a.size&&(n.size=a.size);break;default:n=typeof a.is=="string"?i.createElement(u,{is:a.is}):i.createElement(u)}}n[fl]=l,n[Sl]=a;t:for(i=l.child;i!==null;){if(i.tag===5||i.tag===6)n.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===l)break t;for(;i.sibling===null;){if(i.return===null||i.return===l)break t;i=i.return}i.sibling.return=i.return,i=i.sibling}l.stateNode=n;t:switch(ml(n,u,a),u){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&ze(l)}}return Gt(l),l.subtreeFlags&=-33554433,Tf(l,l.type,t===null?null:t.memoizedProps,l.pendingProps,e),null;case 6:if(t&&l.stateNode!=null)t.memoizedProps!==a&&ze(l);else{if(typeof a!="string"&&l.stateNode===null)throw Error(d(166));if(t=je.current,Va(l)){if(t=l.stateNode,e=l.memoizedProps,a=null,u=nl,u!==null)switch(u.tag){case 27:case 5:a=u.memoizedProps}t[fl]=l,t=!!(t.nodeValue===e||a!==null&&a.suppressHydrationWarning===!0||v0(t.nodeValue,e)),t||qe(l,!0)}else t=an(t).createTextNode(a),t[fl]=l,l.stateNode=t}return Gt(l),null;case 31:if(e=l.memoizedState,t===null||t.memoizedState!==null){if(a=Va(l),e!==null){if(t===null){if(!a)throw Error(d(318));if(t=l.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(d(557));t[fl]=l}else oa(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Gt(l),t=!1}else e=Dc(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=e),t=!0;if(!t)return l.flags&256?(Dl(l),l):(Dl(l),null);if((l.flags&128)!==0)throw Error(d(558))}return Gt(l),null;case 13:if(a=l.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(u=Va(l),a!==null&&a.dehydrated!==null){if(t===null){if(!u)throw Error(d(318));if(u=l.memoizedState,u=u!==null?u.dehydrated:null,!u)throw Error(d(317));u[fl]=l}else oa(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Gt(l),u=!1}else u=Dc(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=u),u=!0;if(!u)return l.flags&256?(Dl(l),l):(Dl(l),null)}return Dl(l),(l.flags&128)!==0?(l.lanes=e,l):(e=a!==null,t=t!==null&&t.memoizedState!==null,e&&(a=l.child,u=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(u=a.alternate.memoizedState.cachePool.pool),n=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(n=a.memoizedState.cachePool.pool),n!==u&&(a.flags|=2048)),e!==t&&e&&(l.child.flags|=8192),di(l,l.updateQueue),Gt(l),null);case 4:return Oa(),t===null&&as(l.stateNode.containerInfo),l.flags|=67108864,Gt(l),null;case 10:return Se(l.type),Gt(l),null;case 19:if(Kc(l),a=l.memoizedState,a===null)return Gt(l),null;if(u=(l.flags&128)!==0,n=a.rendering,n===null)if(u)Ku(a,!1);else{if($t!==0||t!==null&&(t.flags&128)!==0)for(t=l.child;t!==null;){if(n=Wn(t),n!==null){for(l.flags|=128,Ku(a,!1),t=n.updateQueue,l.updateQueue=t,di(l,t),l.subtreeFlags=0,t=e,e=l.child;e!==null;)Vr(e,t),e=e.sibling;return Qu(l,ol.current&1|2),rt&&xe(l,a.treeForkCount),l.child}t=t.sibling}a.tail!==null&&Ol()>Ei&&(l.flags|=128,u=!0,Ku(a,!1),l.lanes=4194304)}else{if(!u)if(t=Wn(n),t!==null){if(l.flags|=128,u=!0,t=t.updateQueue,l.updateQueue=t,di(l,t),Ku(a,!0),a.tail===null&&a.tailMode!=="collapsed"&&a.tailMode!=="visible"&&!n.alternate&&!rt)return Gt(l),null}else 2*Ol()-a.renderingStartTime>Ei&&e!==536870912&&(l.flags|=128,u=!0,Ku(a,!1),l.lanes=4194304);a.isBackwards?(n.sibling=l.child,l.child=n):(t=a.last,t!==null?t.sibling=n:l.child=n,a.last=n)}if(a.tail!==null){t=a.tail;t:{for(e=t;e!==null;){if(e.alternate!==null){e=!1;break t}e=e.sibling}e=!0}return a.rendering=t,a.tail=t.sibling,a.renderingStartTime=Ol(),t.sibling=null,n=ol.current,n=u?n&1|2:n&1,a.tailMode==="visible"||a.tailMode==="collapsed"||!e||rt?Qu(l,n):(e=n,Nt(rl,l),Nt(ol,e),hl===null&&(hl=l)),rt&&xe(l,a.treeForkCount),t}return Gt(l),null;case 22:case 23:return Dl(l),Zc(),a=l.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(l.flags|=8192):a&&(l.flags|=8192),a?(e&536870912)!==0&&(l.flags&128)===0&&(Gt(l),l.subtreeFlags&6&&(l.flags|=8192)):Gt(l),e=l.updateQueue,e!==null&&di(l,e.retryQueue),e=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(e=t.memoizedState.cachePool.pool),a=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(a=l.memoizedState.cachePool.pool),a!==e&&(l.flags|=2048),t!==null&&Rt(va),null;case 24:return e=null,t!==null&&(e=t.memoizedState.cache),l.memoizedState.cache!==e&&(l.flags|=2048),Se(It),Gt(l),null;case 25:return null;case 30:return l.flags|=33554432,Gt(l),null}throw Error(d(156,l.tag))}function ly(t,l){switch(Mc(l),l.tag){case 1:return t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 3:return Se(It),Oa(),t=l.flags,(t&65536)!==0&&(t&128)===0?(l.flags=t&-65537|128,l):null;case 26:case 27:case 5:return gn(l),null;case 31:if(l.memoizedState!==null){if(Dl(l),l.alternate===null)throw Error(d(340));oa()}return t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 13:if(Dl(l),t=l.memoizedState,t!==null&&t.dehydrated!==null){if(l.alternate===null)throw Error(d(340));oa()}return t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 19:return Kc(l),t=l.flags,t&65536?(l.flags=t&-65537|128,t=l.memoizedState,t!==null&&(t.rendering=null,t.tail=null),l.flags|=4,l):null;case 4:return Oa(),null;case 10:return Se(l.type),null;case 22:case 23:return Dl(l),Zc(),t!==null&&Rt(va),t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 24:return Se(It),null;case 25:return null;default:return null}}function bd(t,l){switch(Mc(l),l.tag){case 3:Se(It),Oa();break;case 26:case 27:case 5:gn(l);break;case 4:Oa();break;case 31:l.memoizedState!==null&&Dl(l);break;case 13:Dl(l);break;case 19:Kc(l);break;case 10:Se(l.type);break;case 22:case 23:Dl(l),Zc(),t!==null&&Rt(va);break;case 24:Se(It)}}function Ju(t,l){try{var e=l.updateQueue,a=e!==null?e.lastEffect:null;if(a!==null){var u=a.next;e=u;do{if((e.tag&t)===t){a=void 0;var n=e.create,i=e.inst;a=n(),i.destroy=a}e=e.next}while(e!==u)}}catch(c){jt(l,l.return,c)}}function Le(t,l,e){try{var a=l.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var n=u.next;a=n;do{if((a.tag&t)===t){var i=a.inst,c=i.destroy;if(c!==void 0){i.destroy=void 0,u=l;var s=e,v=c;try{v()}catch(S){jt(u,s,S)}}}a=a.next}while(a!==n)}}catch(S){jt(l,l.return,S)}}function xd(t){var l=t.updateQueue;if(l!==null){var e=t.stateNode;try{co(l,e)}catch(a){jt(t,t.return,a)}}}function pd(t,l,e){e.props=Sa(t.type,t.memoizedProps),e.state=t.memoizedState;try{e.componentWillUnmount()}catch(a){jt(t,l,a)}}function ue(t,l){try{var e=t.ref;if(e!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:var u=t.stateNode,n=ve(t.memoizedProps,u);(u.ref===null||u.ref.name!==n)&&(u.ref=O0(n)),a=u.ref;break;case 7:if(t.stateNode===null){var i=new Bl(t);T(t.child,!1,Ly,i,void 0,void 0),t.stateNode=i}a=t.stateNode;break;default:a=t.stateNode}typeof e=="function"?t.refCleanup=e(a):e.current=a}}catch(c){jt(t,l,c)}}function dl(t,l){var e=t.ref,a=t.refCleanup;if(e!==null)if(typeof a=="function")try{a()}catch(u){jt(t,l,u)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof e=="function")try{e(null)}catch(u){jt(t,l,u)}else e.current=null}function mi(t,l){if((t.tag===5||t.tag===27||t.tag===6)&&t.alternate===null&&l!==null)for(var e=0;e title"))),ml(a,l,e),a[fl]=t,ul(a),l=a;break t;case"link":if(n=Z0("link","href",u).get(l+(e.href||""))){for(i=0;ift&&(i=ft,ft=L,L=i);var h=Cr(c,L),m=Cr(c,ft);if(h&&m&&(b.rangeCount!==1||b.anchorNode!==h.node||b.anchorOffset!==h.offset||b.focusNode!==m.node||b.focusOffset!==m.offset)){var g=O.createRange();g.setStart(h.node,h.offset),b.removeAllRanges(),L>ft?(b.addRange(g),b.extend(m.node,m.offset)):(g.setEnd(m.node,m.offset),b.addRange(g))}}}}for(O=[],b=c;b=b.parentNode;)b.nodeType===1&&O.push({element:b,left:b.scrollLeft,top:b.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;ce?32:e,p.T=null,e=Vf,Vf=null;var n=Wl,i=re;if(Lt=0,za=Wl=null,re=0,(Et&6)!==0)throw Error(d(331));var c=Et;if(Et|=4,Vd(n.current),Gd(n,n.current,i,e),Et=c,tn(0,!1),Al&&typeof Al.onPostCommitFiberRoot=="function")try{Al.onPostCommitFiberRoot(bu,n)}catch{}return!0}finally{A.p=u,p.T=a,u0(t,l)}}function n0(t,l,e){l=Gl(e,l),l=df(t.stateNode,l,2),t=Qe(t,l,2),t!==null&&(pu(t,2),oe(t))}function jt(t,l,e){if(t.tag===3)n0(t,t,e);else for(;l!==null;){if(l.tag===3){n0(l,t,e);break}else if(l.tag===1){var a=l.stateNode;if(typeof l.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&($e===null||!$e.has(a))){t=Gl(e,t),e=ld(2),a=Qe(l,e,2),a!==null&&(ed(e,a,l,t),pu(a,2),oe(a));break}}l=l.return}}function Ff(t,l,e){var a=t.pingCache;if(a===null){a=t.pingCache=new ny;var u=new Set;a.set(l,u)}else u=a.get(l),u===void 0&&(u=new Set,a.set(l,u));u.has(e)||(Gf=!0,u.add(e),t=my.bind(null,t,l,e),l.then(t,t))}function my(t,l,e){var a=t.pingCache;a!==null&&a.delete(l),t.pingedLanes|=t.suspendedLanes&e,t.warmLanes&=~e,Ht===t&&(yt&e)===e&&(($t===4||$t===3&&(yt&62914560)===yt&&300>Ol()-Ni)&&(Et&2)===0?iu(t,0):Ti|=e,lu===yt&&(lu=0)),oe(t)}function i0(t,l){l===0&&(l=Zs()),t=sa(t,l),t!==null&&(pu(t,l),oe(t))}function yy(t){var l=t.memoizedState,e=0;l!==null&&(e=l.retryLane),i0(t,e)}function hy(t,l){var e=0;switch(t.tag){case 31:case 13:var a=t.stateNode,u=t.memoizedState;u!==null&&(e=u.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(d(314))}a!==null&&a.delete(l),i0(t,e)}function vy(t,l){return Ii(t,l)}var fu=null,su=null,Wf=!1,Ci=!1,If=!1,We=0;function oe(t){t!==su&&t.next===null&&(su===null?fu=su=t:su=su.next=t),Ci=!0,Wf||(Wf=!0,by())}function tn(t,l){if(!If&&Ci){If=!0;do for(var e=!1,a=fu;a!==null;){if(t!==0){var u=a.pendingLanes;if(u===0)var n=0;else{var i=a.suspendedLanes,c=a.pingedLanes;n=(1<<31-jl(42|t)+1)-1,n&=u&~(i&~c),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(e=!0,r0(a,n))}else n=yt,n=Tn(a,a===Ht?n:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(n&3)===0||xu(a,n)||(e=!0,r0(a,n));a=a.next}while(e);If=!1}}function gy(){c0()}function c0(){Ci=Wf=!1;var t=0;We!==0&&jy()&&(t=We);for(var l=Ol(),e=null,a=fu;a!==null;){var u=a.next,n=f0(a,l);n===0?(a.next=null,e===null?fu=u:e.next=u,u===null&&(su=e)):(e=a,(t!==0||(n&3)!==0)&&(Ci=!0)),a=u}Lt!==0&&Lt!==5||tn(t),We!==0&&(We=0)}function f0(t,l){for(var e=t.suspendedLanes,a=t.pingedLanes,u=t.expirationTimes,n=t.pendingLanes&-62914561;0c)break;var S=s.transferSize,O=s.initiatorType;S&&g0(O)&&(s=s.responseEnd,i+=S*(sqi){L.length=D;break}g=new Promise(Hy.bind(g)),L.push(g)}}}if(0"u"?null:document;function G0(t,l,e){var a=ou;if(a&&typeof l=="string"&&l){var u=Yl(l);u='link[rel="'+t+'"][href="'+u+'"]',typeof e=="string"&&(u+='[crossorigin="'+e+'"]'),w0.has(u)||(w0.add(u),t={rel:t,crossOrigin:e,href:l},a.querySelector(u)===null&&(l=a.createElement("link"),ml(l,"link",t),ul(l),a.head.appendChild(l)))}}function th(t){Oe.D(t),G0("dns-prefetch",t,null)}function lh(t,l){Oe.C(t,l),G0("preconnect",t,l)}function eh(t,l,e){Oe.L(t,l,e);var a=ou;if(a&&t&&l){var u='link[rel="preload"][as="'+Yl(l)+'"]';l==="image"&&e&&e.imageSrcSet?(u+='[imagesrcset="'+Yl(e.imageSrcSet)+'"]',typeof e.imageSizes=="string"&&(u+='[imagesizes="'+Yl(e.imageSizes)+'"]')):u+='[href="'+Yl(t)+'"]';var n=u;switch(l){case"style":n=du(t);break;case"script":n=mu(t)}if(!(Kl.has(n)||(t=K({rel:"preload",href:l==="image"&&e&&e.imageSrcSet?void 0:t,as:l},e),Kl.set(n,t),a.querySelector(u)!==null||l==="style"&&a.querySelector(nn(n))||l==="script"&&a.querySelector(cn(n))))){var i=a.createElement("link");ml(i,"link",t),l==="style"&&(i[Nn]=!0,i.onload=i.onerror=function(){Is(i)}),ul(i),a.head.appendChild(i)}}}function ah(t,l){Oe.m(t,l);var e=ou;if(e&&t){var a=l&&typeof l.as=="string"?l.as:"script",u='link[rel="modulepreload"][as="'+Yl(a)+'"][href="'+Yl(t)+'"]',n=u;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=mu(t)}if(!Kl.has(n)&&(t=K({rel:"modulepreload",href:t},l),Kl.set(n,t),e.querySelector(u)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(e.querySelector(cn(n)))return}a=e.createElement("link"),ml(a,"link",t),ul(a),e.head.appendChild(a)}}}function uh(t,l,e){Oe.S(t,l,e);var a=ou;if(a&&t){var u=Ma(a).hoistableStyles,n=du(t);l=l||"default";var i=u.get(n);if(!i){var c={loading:0,preload:null};if(i=a.querySelector(nn(n)))c.loading=5;else{t=K({rel:"stylesheet",href:t,"data-precedence":l},e),(e=Kl.get(n))&&xs(t,e);var s=i=a.createElement("link");ul(s),ml(s,"link",t),s._p=new Promise(function(v,S){s.onload=v,s.onerror=S}),s.addEventListener("load",function(){c.loading|=1}),s.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Ri(i,l,a)}i={type:"stylesheet",instance:i,count:1,state:c},u.set(n,i)}}}function nh(t,l){Oe.X(t,l);var e=ou;if(e&&t){var a=Ma(e).hoistableScripts,u=mu(t),n=a.get(u);n||(n=e.querySelector(cn(u)),n||(t=K({src:t,async:!0},l),(l=Kl.get(u))&&ps(t,l),n=e.createElement("script"),ul(n),ml(n,"link",t),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function ih(t,l){Oe.M(t,l);var e=ou;if(e&&t){var a=Ma(e).hoistableScripts,u=mu(t),n=a.get(u);n||(n=e.querySelector(cn(u)),n||(t=K({src:t,async:!0,type:"module"},l),(l=Kl.get(u))&&ps(t,l),n=e.createElement("script"),ul(n),ml(n,"link",t),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Q0(t,l,e,a){var u=(u=je.current)?un(u):null;if(!u)throw Error(d(446));switch(t){case"meta":case"title":return null;case"style":return typeof e.precedence=="string"&&typeof e.href=="string"?(e=du(e.href),l=Ma(u).hoistableStyles,a=l.get(e),a||(a={type:"style",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(e.rel==="stylesheet"&&typeof e.href=="string"&&typeof e.precedence=="string"){t=du(e.href);var n=Ma(u).hoistableStyles,i=n.get(t);if(i||(u=u.ownerDocument||u,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(t,i),(n=u.querySelector(nn(t)))?n._p||(i.instance=n,i.state.loading=5):(n=Kl.get(t),n||(n={rel:"preload",as:"style",href:e.href,crossOrigin:e.crossOrigin,integrity:e.integrity,media:e.media,hrefLang:e.hrefLang,referrerPolicy:e.referrerPolicy},Kl.set(t,n)),ch(u,t,n,i.state))),l&&a===null)throw Error(d(528,""));return i}if(l&&a!==null)throw Error(d(529,""));return null;case"script":return l=e.async,e=e.src,typeof e=="string"&&l&&typeof l!="function"&&typeof l!="symbol"?(e=mu(e),l=Ma(u).hoistableScripts,a=l.get(e),a||(a={type:"script",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(d(444,t))}}function du(t){return'href="'+Yl(t)+'"'}function nn(t){return'link[rel="stylesheet"]['+t+"]"}function X0(t){return K({},t,{"data-precedence":t.precedence,precedence:null})}function ch(t,l,e,a){if(l=t.querySelector('link[rel="preload"][as="style"]['+l+"]")){if(l[Nn]!==!0){a.loading=1;return}}else l=t.createElement("link"),l[Nn]=!0,l.onload=l.onerror=Is.bind(null,l),ml(l,"link",e),ul(l),t.head.appendChild(l);a.preload=l,l.addEventListener("load",function(){return a.loading|=1}),l.addEventListener("error",function(){return a.loading|=2})}function mu(t){return'[src="'+Yl(t)+'"]'}function cn(t){return"script[async]"+t}function V0(t,l,e){if(l.count++,l.instance===null)switch(l.type){case"style":var a=t.querySelector('style[data-href~="'+Yl(e.href)+'"]');if(a)return l.instance=a,ul(a),a;var u=K({},e,{"data-href":e.href,"data-precedence":e.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),ul(a),ml(a,"style",u),Ri(a,e.precedence,t),l.instance=a;case"stylesheet":u=du(e.href);var n=t.querySelector(nn(u));if(n)return l.state.loading|=4,l.instance=n,ul(n),n;a=X0(e),(u=Kl.get(u))&&xs(a,u),n=(t.ownerDocument||t).createElement("link"),ul(n);var i=n;return i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),ml(n,"link",a),l.state.loading|=4,Ri(n,e.precedence,t),l.instance=n;case"script":return n=mu(e.src),(u=t.querySelector(cn(n)))?(l.instance=u,ul(u),u):(a=e,(u=Kl.get(n))&&(a=K({},e),ps(a,u)),t=t.ownerDocument||t,u=t.createElement("script"),ul(u),ml(u,"link",a),t.head.appendChild(u),l.instance=u);case"void":return null;default:throw Error(d(443,l.type))}else l.type==="stylesheet"&&(l.state.loading&4)===0&&(a=l.instance,l.state.loading|=4,Ri(a,e.precedence,t));return l.instance}function Ri(t,l,e){for(var a=e.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),u=a.length?a[a.length-1]:null,n=u,i=0;i title"):null)}function fh(t,l,e){if(e===1||l.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof l.precedence!="string"||typeof l.href!="string"||l.href==="")break;return!0;case"link":if(typeof l.rel!="string"||typeof l.href!="string"||l.href===""||l.onLoad||l.onError)break;switch(l.rel){case"stylesheet":return t=l.disabled,typeof l.precedence=="string"&&t==null;default:return!0}case"script":if(l.async&&typeof l.async!="function"&&typeof l.async!="symbol"&&!l.onLoad&&!l.onError&&l.src&&typeof l.src=="string")return!0}return!1}function L0(t,l){return t==="img"&&l.src!=null&&l.src!==""&&l.onLoad==null&&l.loading!=="lazy"}function K0(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function J0(t){return(t.width||100)*(t.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function k0(t,l){typeof l.decode=="function"&&(t.imgCount++,l.complete||(t.imgBytes+=J0(l),t.suspenseyImages.push(l)),t=oh.bind(t),l.decode().then(t,t))}function sh(t,l,e,a){if(e.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(e.state.loading&4)===0){if(e.instance===null){var u=du(a.href),n=l.querySelector(nn(u));if(n){l=n._p,l!==null&&typeof l=="object"&&typeof l.then=="function"&&(t.count++,t=fn.bind(t),l.then(t,t)),e.state.loading|=4,e.instance=n,ul(n);return}n=l.ownerDocument||l,a=X0(a),(u=Kl.get(u))&&xs(a,u),n=n.createElement("link"),ul(n);var i=n;i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),ml(n,"link",a),e.instance=n}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(e,l),(l=e.state.preload)&&(e.state.loading&3)===0&&(t.count++,e=fn.bind(t),l.addEventListener("load",e),l.addEventListener("error",e))}}var qi=0;function rh(t,l){return t.stylesheets&&t.count===0&&Yi(t,t.stylesheets),0qi?50:800)+l);return t.unsuspend=e,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(u)}}:null}function $0(t){if(t.count===0&&(t.imgCount===0||!t.waitingForImages)){if(t.stylesheets)Yi(t,t.stylesheets);else if(t.unsuspend){var l=t.unsuspend;t.unsuspend=null,l()}}}function fn(){this.count--,$0(this)}function oh(){this.imgCount--,$0(this)}var Bi=null;function Yi(t,l){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Bi=new Map,l.forEach(dh,t),Bi=null,fn.call(t))}function dh(t,l){if(!(l.state.loading&4)){var e=Bi.get(t);if(e)var a=e.get(null);else{e=new Map,Bi.set(t,e);for(var u=t.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(r)}catch(E){console.error(E)}}return r(),Ms.exports=Mh(),Ms.exports}var Dh=Ch();/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Uh=r=>r.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),pm=(...r)=>r.filter((E,z,d)=>!!E&&E.trim()!==""&&d.indexOf(E)===z).join(" ").trim();/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */var Rh={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Hh=X.forwardRef(({color:r="currentColor",size:E=24,strokeWidth:z=2,absoluteStrokeWidth:d,className:C="",children:B,iconNode:M,...ut},tt)=>X.createElement("svg",{ref:tt,...Rh,width:E,height:E,stroke:r,strokeWidth:d?Number(z)*24/Number(E):z,className:pm("lucide",C),...ut},[...M.map(([V,R])=>X.createElement(V,R)),...Array.isArray(B)?B:[B]]));/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const zt=(r,E)=>{const z=X.forwardRef(({className:d,...C},B)=>X.createElement(Hh,{ref:B,iconNode:E,className:pm(`lucide-${Uh(r)}`,d),...C}));return z.displayName=`${r}`,z};/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const qh=zt("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Bh=zt("Bot",[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Yh=zt("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const wh=zt("CircleAlert",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Gh=zt("CircleCheck",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Qh=zt("CircleStop",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["rect",{x:"9",y:"9",width:"6",height:"6",rx:"1",key:"1ssd4o"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Xh=zt("ClipboardCheck",[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1",key:"tgr4d6"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2",key:"116196"}],["path",{d:"m9 14 2 2 4-4",key:"df797q"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Vh=zt("Cpu",[["rect",{width:"16",height:"16",x:"4",y:"4",rx:"2",key:"14l7u7"}],["rect",{width:"6",height:"6",x:"9",y:"9",rx:"1",key:"5aljv4"}],["path",{d:"M15 2v2",key:"13l42r"}],["path",{d:"M15 20v2",key:"15mkzm"}],["path",{d:"M2 15h2",key:"1gxd5l"}],["path",{d:"M2 9h2",key:"1bbxkp"}],["path",{d:"M20 15h2",key:"19e6y8"}],["path",{d:"M20 9h2",key:"19tzq7"}],["path",{d:"M9 2v2",key:"165o2o"}],["path",{d:"M9 20v2",key:"i2bqo8"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Zh=zt("Ellipsis",[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Lh=zt("Gauge",[["path",{d:"m12 14 4-4",key:"9kzdfg"}],["path",{d:"M3.34 19a10 10 0 1 1 17.32 0",key:"19p75a"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Kh=zt("GraduationCap",[["path",{d:"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z",key:"j76jl0"}],["path",{d:"M22 10v6",key:"1lu8f3"}],["path",{d:"M6 12.5V16a6 3 0 0 0 12 0v-3.5",key:"1r8lef"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Jh=zt("Info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const kh=zt("KeyRound",[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const $h=zt("ListVideo",[["path",{d:"M12 12H3",key:"18klou"}],["path",{d:"M16 6H3",key:"1wxfjs"}],["path",{d:"M12 18H3",key:"11ftsu"}],["path",{d:"m16 12 5 3-5 3v-6Z",key:"zpskkp"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Fh=zt("LoaderCircle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Wh=zt("LogIn",[["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4",key:"u53s6r"}],["polyline",{points:"10 17 15 12 10 7",key:"1ail0h"}],["line",{x1:"15",x2:"3",y1:"12",y2:"12",key:"v6grx8"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Ih=zt("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Sm=zt("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Bs=zt("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Ph=zt("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const tv=zt("ScrollText",[["path",{d:"M15 12h-5",key:"r7krc0"}],["path",{d:"M15 8h-5",key:"1khuty"}],["path",{d:"M19 17V5a2 2 0 0 0-2-2H4",key:"zz82l3"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3",key:"1ph1d7"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const lv=zt("Send",[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",key:"1ffxy3"}],["path",{d:"m21.854 2.147-10.94 10.939",key:"12cjpa"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const ev=zt("ServerCog",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5",key:"tn8das"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5",key:"1g2pve"}],["path",{d:"M6 6h.01",key:"1utrut"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"m15.7 13.4-.9-.3",key:"1jwmzr"}],["path",{d:"m9.2 10.9-.9-.3",key:"qapnim"}],["path",{d:"m10.6 15.7.3-.9",key:"quwk0k"}],["path",{d:"m13.6 15.7-.4-1",key:"cb9xp7"}],["path",{d:"m10.8 9.3-.4-1",key:"1uaiz5"}],["path",{d:"m8.3 13.6 1-.4",key:"s6srou"}],["path",{d:"m14.7 10.8 1-.4",key:"4d31cq"}],["path",{d:"m13.4 8.3-.3.9",key:"1bm987"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const av=zt("Settings2",[["path",{d:"M20 7h-9",key:"3s1dr2"}],["path",{d:"M14 17H5",key:"gfn3mx"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const uv=zt("ShieldCheck",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const nv=zt("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const iv=zt("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Tm=zt("Users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75",key:"1da9ce"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const cv=zt("Video",[["path",{d:"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5",key:"ftymec"}],["rect",{x:"2",y:"6",width:"14",height:"12",rx:"2",key:"158x01"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const fv=zt("WifiOff",[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}],["path",{d:"M5 12.859a10 10 0 0 1 5.17-2.69",key:"1dl1wf"}],["path",{d:"M19 12.859a10 10 0 0 0-2.007-1.523",key:"4k23kn"}],["path",{d:"M2 8.82a15 15 0 0 1 4.177-2.643",key:"1grhjp"}],["path",{d:"M22 8.82a15 15 0 0 0-11.288-3.764",key:"z3jwby"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);/** - * @license lucide-react v0.468.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const sv=zt("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);function Nm(r){var E,z,d="";if(typeof r=="string"||typeof r=="number")d+=r;else if(typeof r=="object")if(Array.isArray(r)){var C=r.length;for(E=0;Erv(r),Pl="w-full rounded-lg border border-line bg-white px-3 py-2 text-[13px] text-slate-900 placeholder:text-slate-400 transition focus:border-brand-500 focus:outline-none focus:ring-3 focus:ring-brand-500/15 disabled:cursor-not-allowed disabled:bg-slate-50";function xm(r){if(!r)return"—";const E=Math.floor((Date.now()-r)/6e4);return E<1?"刚刚":E<60?`${E} 分钟前`:`${Math.floor(E/60)} 小时前`}function Rs(r=[]){return{total:r.length,studyable:r.filter(E=>E.in_study!==!1).length}}function yn(r){return String(r||"").split("#").filter(Boolean)}const ov={"01":"单选","02":"多选","03":"判断","04":"问答"};function de(r){return r instanceof Error?r.message:String(r)}const dv={neutral:"bg-slate-100 text-slate-600 ring-slate-200",brand:"bg-brand-50 text-brand-700 ring-brand-100",success:"bg-emerald-50 text-emerald-700 ring-emerald-100",warning:"bg-amber-50 text-amber-700 ring-amber-100",danger:"bg-red-50 text-red-700 ring-red-100",running:"bg-sky-50 text-sky-700 ring-sky-100"};function Hs({tone:r="neutral",children:E,dot:z=!1,className:d}){return f.jsxs("span",{className:vl("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[11px] font-medium ring-1 ring-inset",dv[r],d),children:[z&&f.jsx("span",{className:"size-1.5 rounded-full bg-current opacity-70"}),E]})}const mv={primary:"border-brand-500 bg-brand-500 text-white shadow-sm shadow-brand-500/25 hover:border-brand-600 hover:bg-brand-600",secondary:"border-line bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50",ghost:"border-transparent bg-transparent text-slate-600 hover:bg-slate-100",danger:"border-transparent bg-transparent text-red-600 hover:bg-red-50",soft:"border-brand-100 bg-brand-50 text-brand-700 hover:border-brand-200 hover:bg-brand-100"},yv={sm:"h-8 gap-1.5 rounded-lg px-2.5 text-xs",md:"h-9 gap-1.5 rounded-lg px-3.5 text-[13px]",icon:"h-9 w-9 rounded-lg"};function Kt({variant:r="secondary",size:E="md",loading:z=!1,icon:d,className:C,children:B,disabled:M,type:ut="button",...tt}){return f.jsxs("button",{type:ut,disabled:M||z,className:vl("inline-flex shrink-0 items-center justify-center border font-medium transition","focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-brand-500/20","disabled:cursor-not-allowed disabled:opacity-50",mv[r],yv[E],C),...tt,children:[z?f.jsx(Fh,{className:"size-3.5 animate-spin"}):d,B]})}function hv(r,E){var B,M;const z=E==="login"||r.status==="logging"||((B=r.run)==null?void 0:B.status)==="logging"?"logging":((M=r.run)==null?void 0:M.status)||r.status||"idle",C={discovering:{label:"发现课程中",tone:"running",pulse:!0},studying:{label:"学习中",tone:"running",pulse:!0},finished:{label:"已完成",tone:"success"},stopped:{label:"已停止",tone:"warning"},error:{label:"出错",tone:"danger"},interrupted:{label:"已中断",tone:"warning"},logging:{label:"登录中",tone:"running",pulse:!0},logged_in:{label:"已登录",tone:"success"},login_failed:{label:"登录失败",tone:"danger"},idle:{label:"未登录",tone:"neutral"}}[z]||{label:z,tone:"neutral"};return{label:C.label,tone:C.tone,pulse:!!C.pulse}}function vv({account:r,course:E,disabled:z,onToggle:d}){var B;const C=(B=r.selected)==null?void 0:B.includes(E.plan_id);return f.jsxs("label",{className:vl("flex cursor-pointer items-start gap-2.5 rounded-lg border border-transparent px-2 py-1.5 transition","hover:border-line hover:bg-slate-50",z&&"pointer-events-none opacity-60"),children:[f.jsx("input",{type:"checkbox",className:"mt-0.5 size-3.5 shrink-0 accent-brand-500",checked:!!C,disabled:z,onChange:M=>d(E.plan_id,M.target.checked)}),f.jsxs("span",{className:"min-w-0 flex-1",children:[f.jsx("span",{className:"block truncate text-[12.5px] font-medium text-slate-700",children:E.name||E.plan_id}),f.jsx("span",{className:"mt-0.5 block truncate text-[11px] text-slate-400",children:[E.section,E.status_label,E.info].filter(Boolean).join(" · ")||"—"})]}),f.jsx("span",{className:"shrink-0 pt-0.5 text-[11px] tabular-nums text-slate-500",children:E.progress||""})]})}function gv({account:r,platformLabel:E,pending:z,openLog:d,logLines:C,onToggleLog:B,onLogin:M,onRefresh:ut,onStudy:tt,onStop:V,onCapture:R,onStopCapture:T,onQuiz:Z,onDelete:$,onToggleCourse:it,onSelectAll:Ut,onClearSelection:Y,onToggleOption:vt}){var gt,H,at,st,Bt,o,N,w,G,ot,x,j,p,A,lt,P;const[pt,Ct]=X.useState(!1),Ft=X.useRef(null),St=X.useRef(null),J=X.useRef(!0);X.useEffect(()=>{if(!pt)return;const q=Yt=>{var Rt;(Rt=Ft.current)!=null&&Rt.contains(Yt.target)||Ct(!1)};return document.addEventListener("pointerdown",q),()=>document.removeEventListener("pointerdown",q)},[pt]),X.useEffect(()=>{const q=St.current;q&&J.current&&(q.scrollTop=q.scrollHeight)},[C,d]);const K=hv(r,z),k=!!z||r.status==="logging"||((gt=r.run)==null?void 0:gt.status)==="logging",_t=r.courses||[],qt=_t.filter(q=>q.in_study!==!1),Zt=_t.filter(q=>q.in_study===!1),Tt=Rs(_t),Jt=((H=r.run)==null?void 0:H.done)||0,al=((at=r.run)==null?void 0:at.total)||0,Qt=al?Math.round(Jt/al*100):0,U=["discovering","studying"].includes(((st=r.run)==null?void 0:st.status)||""),F=((Bt=r.selected)==null?void 0:Bt.length)||0,I=F>0&&(((o=r.cookies)==null?void 0:o.length)||0)>0;return f.jsxs("article",{"data-id":r.id,className:"card-shadow flex min-w-0 flex-col rounded-2xl border border-line bg-white transition-colors hover:border-slate-300/80",children:[f.jsxs("header",{className:"flex items-start gap-3 px-4 pt-4",children:[f.jsxs("div",{className:"relative mt-0.5 grid size-10 shrink-0 place-items-center rounded-xl bg-gradient-to-br from-brand-50 to-sky-50 text-[13px] font-semibold text-brand-700 ring-1 ring-brand-100",children:[(r.user||r.username||"?").slice(0,1).toUpperCase(),f.jsx("span",{className:vl("absolute -bottom-0.5 -right-0.5 size-3 rounded-full border-2 border-white",K.tone==="success"?"bg-emerald-500":K.tone==="danger"?"bg-red-500":K.tone==="running"?"bg-sky-500":K.tone==="warning"?"bg-amber-500":"bg-slate-300",K.pulse&&"animate-pulse")})]}),f.jsxs("div",{className:"min-w-0 flex-1",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx("h2",{className:"truncate text-[13.5px] font-semibold text-slate-900",children:r.user||r.username}),f.jsx(Hs,{tone:K.tone,dot:!0,children:K.label})]}),f.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] text-slate-400",children:[f.jsx("span",{className:"truncate",children:r.username}),r.note&&f.jsxs("span",{className:"truncate",children:["· ",r.note]}),f.jsxs("span",{children:["· ",xm(r.updated||r.loginAt)]})]})]}),f.jsx(Hs,{tone:"brand",className:"mt-0.5 shrink-0",children:E})]}),f.jsxs("div",{className:"px-4 pt-3",children:[f.jsxs("div",{className:"flex items-center justify-between gap-2",children:[f.jsxs("div",{className:"text-[11.5px] text-slate-500",children:["共 ",f.jsx("b",{className:"font-semibold text-slate-700",children:Tt.total})," 门 · 可学"," ",f.jsx("b",{className:"font-semibold text-slate-700",children:Tt.studyable}),Zt.length>0&&f.jsxs("span",{className:"text-slate-400",children:[" · 已完成 ",Zt.length]})]}),qt.length>0&&f.jsxs("div",{className:"flex items-center gap-1",children:[f.jsx("button",{type:"button",disabled:k,className:"rounded px-1.5 py-0.5 text-[11px] text-brand-600 transition hover:bg-brand-50 disabled:opacity-40",onClick:Ut,children:"全选"}),f.jsx("button",{type:"button",disabled:k||F===0,className:"rounded px-1.5 py-0.5 text-[11px] text-slate-500 transition hover:bg-slate-100 disabled:opacity-40",onClick:Y,children:"清空"})]})]}),f.jsx("div",{className:"scrollbar-thin mt-1.5 max-h-[196px] min-h-[70px] overflow-y-auto pr-0.5",children:_t.length===0?f.jsx("div",{className:"grid min-h-[70px] place-items-center rounded-lg border border-dashed border-line text-[12px] text-slate-400",children:"还没有课程,先登录或刷新课程"}):f.jsxs(f.Fragment,{children:[qt.map(q=>f.jsx(vv,{account:r,course:q,disabled:k,onToggle:it},q.plan_id)),Zt.length>0&&f.jsx("div",{className:"mt-1 border-t border-dashed border-line pt-1",children:Zt.map(q=>f.jsxs("div",{className:"flex items-start gap-2.5 rounded-lg px-2 py-1.5 text-slate-400",children:[f.jsx("span",{className:"mt-0.5 grid size-3.5 shrink-0 place-items-center rounded-full bg-emerald-50 text-[9px] text-emerald-600",children:"✓"}),f.jsxs("span",{className:"min-w-0 flex-1",children:[f.jsx("span",{className:"block truncate text-[12px]",children:q.name||q.plan_id}),f.jsx("span",{className:"mt-0.5 block truncate text-[10.5px] opacity-80",children:[q.section,q.info].filter(Boolean).join(" · ")})]}),f.jsx("span",{className:"shrink-0 text-[10.5px]",children:q.status_label||"已结束"})]},q.plan_id))})]})})]}),f.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-x-4 gap-y-1.5 border-t border-line/70 px-4 py-2.5",children:[f.jsxs("label",{className:"flex cursor-pointer items-center gap-1.5 text-[11.5px] text-slate-600",children:[f.jsx("input",{type:"checkbox",className:"size-3.5 accent-brand-500",checked:r.optQuiz===!0,disabled:k,onChange:q=>vt("quiz",q.target.checked)}),"自动交测验"]}),f.jsxs("label",{className:"flex cursor-pointer items-center gap-1.5 text-[11.5px] text-slate-600",children:[f.jsx("input",{type:"checkbox",className:"size-3.5 accent-brand-500",checked:r.optFeedback!==!1,disabled:k,onChange:q=>vt("feedback",q.target.checked)}),"自动交反馈表"]}),f.jsx("div",{className:"flex-1"}),f.jsx("span",{className:"text-[11px] tabular-nums text-slate-400",children:F>0?`已选 ${F} 门`:"未选择课程"})]}),f.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 border-t border-line/70 px-4 py-2.5",children:[f.jsx(Kt,{size:"sm",variant:"soft",loading:z==="login"||r.status==="logging"||((N=r.run)==null?void 0:N.status)==="logging",disabled:k,icon:f.jsx(Wh,{className:"size-3.5"}),onClick:M,children:(w=r.cookies)!=null&&w.length?"重新登录":"登录"}),f.jsx(Kt,{size:"sm",loading:z==="refresh",disabled:k||!((G=r.cookies)!=null&&G.length),icon:f.jsx(Bs,{className:"size-3.5"}),onClick:ut,children:"刷新课程"}),f.jsx(Kt,{size:"sm",variant:"primary",loading:z==="study",disabled:k||!I,icon:f.jsx(Ih,{className:"size-3.5"}),onClick:tt,children:"开始学习"}),f.jsx("div",{className:"flex-1"}),U&&f.jsx(Kt,{size:"icon",variant:"danger",loading:z==="stop",onClick:V,title:"停止学习","aria-label":"停止学习",children:f.jsx(Qh,{className:"size-4"})}),f.jsxs("div",{className:"relative",ref:Ft,children:[f.jsx(Kt,{size:"icon",variant:"ghost",onClick:()=>Ct(q=>!q),"aria-label":"更多操作",title:"更多操作",children:f.jsx(Zh,{className:"size-4"})}),pt&&f.jsx("div",{className:"absolute bottom-10 right-0 z-20 w-40 overflow-hidden rounded-xl border border-line bg-white py-1 shadow-xl shadow-slate-900/10",children:[{label:"课程日志",icon:$h,action:B},{label:"打开测验",icon:Xh,action:Z},(ot=r.run)!=null&&ot.capturing?{label:"停止抓包",icon:nv,action:T}:{label:"抓包 10 分钟",icon:cv,action:R},{label:"删除账号",icon:iv,action:$,danger:!0}].map(q=>f.jsxs("button",{type:"button",className:vl("flex w-full items-center gap-2 px-3 py-2 text-left text-[12px] transition hover:bg-slate-50",q.danger?"text-red-600":"text-slate-700"),onClick:()=>{Ct(!1),q.action()},children:[f.jsx(q.icon,{className:"size-3.5 opacity-70"}),q.label]},q.label))})]})]}),(al>0||((x=r.run)==null?void 0:x.error))&&f.jsxs("div",{className:"border-t border-line/70 px-4 py-3",children:[f.jsxs("div",{className:"mb-1.5 flex items-center justify-between gap-2 text-[11px] text-slate-500",children:[f.jsx("span",{className:"truncate",children:((j=r.run)==null?void 0:j.course)||((p=r.run)==null?void 0:p.status)||"学习进度"}),f.jsxs("span",{className:"shrink-0 tabular-nums",children:[Jt," / ",al,al>0&&f.jsxs("span",{className:"ml-1 text-slate-400",children:["(",Qt,"%)"]})]})]}),f.jsx("div",{className:"h-1.5 overflow-hidden rounded-full bg-slate-100",children:f.jsx("div",{className:vl("h-full rounded-full transition-all duration-500",((A=r.run)==null?void 0:A.status)==="error"?"bg-red-500":((lt=r.run)==null?void 0:lt.status)==="finished"?"bg-emerald-500":"bg-gradient-to-r from-brand-500 to-sky-400"),style:{width:`${Math.min(100,Qt)}%`}})}),((P=r.run)==null?void 0:P.error)&&f.jsx("p",{className:"mt-2 rounded-lg bg-red-50 px-2.5 py-1.5 text-[11px] leading-relaxed text-red-700",children:r.run.error})]}),r.lastError&&f.jsx("div",{className:"border-t border-line/70 px-4 py-2.5",children:f.jsxs("p",{className:"rounded-lg bg-red-50/80 px-2.5 py-1.5 text-[11px] leading-relaxed text-red-700",children:[r.lastError,r.lastErrorAt?f.jsxs("span",{className:"ml-1 text-red-400",children:["· ",xm(r.lastErrorAt)]}):null]})}),f.jsxs("div",{className:vl("border-t border-line/70",d?"block":"hidden"),children:[f.jsxs("div",{className:"flex items-center gap-2 px-4 pt-2.5 text-[11px] text-slate-400",children:[f.jsx("span",{className:"font-medium text-slate-500",children:"课程日志"}),f.jsxs("span",{className:"tabular-nums",children:["(",C.length,")"]}),f.jsx("div",{className:"flex-1"}),f.jsx("button",{type:"button",onClick:B,className:"rounded px-1.5 py-0.5 text-[11px] text-slate-500 transition hover:bg-slate-100",children:"收起"})]}),f.jsx("pre",{ref:St,onScroll:q=>{const Yt=q.currentTarget;J.current=Yt.scrollHeight-Yt.scrollTop-Yt.clientHeight<24},className:vl("scrollbar-thin mx-4 mb-3 mt-2 max-h-56 overflow-auto rounded-lg bg-slate-950/95 p-3","font-mono text-[11px] leading-relaxed text-slate-300",C.length===0&&"text-slate-500"),children:C.length?C.join(` -`):"暂无日志 · 开始学习后这里会实时显示"})]}),f.jsxs("button",{type:"button",onClick:B,className:"flex items-center justify-center gap-1 border-t border-line/70 py-1.5 text-[10.5px] text-slate-400 transition hover:bg-slate-50 hover:text-slate-600","aria-expanded":d,children:[f.jsx(Yh,{className:vl("size-3 transition-transform",d&&"rotate-180")}),d?"收起课程日志":"展开课程日志"]})]})}const bv={md:"max-w-xl",lg:"max-w-3xl",xl:"max-w-6xl"};function Ki({open:r,onClose:E,title:z,subtitle:d,size:C="md",footer:B,children:M,bodyClassName:ut}){return X.useEffect(()=>{if(!r)return;const tt=R=>{R.key==="Escape"&&E()};window.addEventListener("keydown",tt);const V=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{window.removeEventListener("keydown",tt),document.body.style.overflow=V}},[r,E]),r?f.jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:[f.jsx("div",{className:"absolute inset-0 bg-slate-900/40 backdrop-blur-[2px]",onClick:E}),f.jsxs("div",{role:"dialog","aria-modal":"true",className:vl("relative flex max-h-[calc(100vh-2rem)] w-full flex-col overflow-hidden rounded-2xl","border border-line bg-white shadow-2xl shadow-slate-900/20",bv[C]),children:[f.jsxs("header",{className:"flex items-start gap-3 border-b border-line px-5 py-4",children:[f.jsxs("div",{className:"min-w-0 flex-1",children:[f.jsx("h2",{className:"truncate text-[15px] font-semibold text-slate-900",children:z}),d&&f.jsx("p",{className:"mt-0.5 truncate text-xs text-slate-500",children:d})]}),f.jsx("button",{type:"button",onClick:E,className:"-mr-1 rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600","aria-label":"关闭",children:f.jsx(sv,{className:"size-4"})})]}),f.jsx("div",{className:vl("min-h-0 flex-1 overflow-auto px-5 py-4",ut),children:M}),B&&f.jsx("footer",{className:"flex flex-wrap items-center justify-end gap-2 border-t border-line bg-slate-50/70 px-5 py-3",children:B})]})]}):null}function xv({open:r,onClose:E,onSubmit:z}){const[d,C]=X.useState(""),[B,M]=X.useState(""),[ut,tt]=X.useState(""),[V,R]=X.useState(!1),[T,Z]=X.useState("");X.useEffect(()=>{r&&(C(""),M(""),tt(""),Z(""),R(!1))},[r]);async function $(){if(!d.trim()||!B){Z("请填写账号和密码");return}R(!0),Z("");try{await z({username:d.trim(),password:B,note:ut.trim()}),E()}catch(it){Z(it instanceof Error?it.message:String(it))}finally{R(!1)}}return f.jsx(Ki,{open:r,onClose:E,title:"添加账号",subtitle:"账号密码保存在本机 SQLite,用于会话失效时自动重新登录",footer:f.jsxs(f.Fragment,{children:[f.jsx(Kt,{onClick:E,disabled:V,children:"取消"}),f.jsx(Kt,{variant:"primary",loading:V,onClick:$,children:"保存并登录"})]}),children:f.jsxs("div",{className:"space-y-4",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:"登录账号"}),f.jsx("input",{className:Pl,value:d,autoFocus:!0,placeholder:"手机号 / 身份证号 / 教师账号",onChange:it=>C(it.target.value),onKeyDown:it=>it.key==="Enter"&&$()})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:"密码"}),f.jsx("input",{className:Pl,type:"password",value:B,autoComplete:"off",placeholder:"平台登录密码",onChange:it=>M(it.target.value),onKeyDown:it=>it.key==="Enter"&&$()})]}),f.jsxs("div",{children:[f.jsxs("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:["备注 ",f.jsx("span",{className:"font-normal text-slate-400",children:"(可选)"})]}),f.jsx("input",{className:Pl,value:ut,placeholder:"例如:张三 · 语文",onChange:it=>tt(it.target.value)})]}),f.jsx("p",{className:"rounded-lg border border-line bg-slate-50 px-3 py-2 text-[11.5px] leading-relaxed text-slate-500",children:"保存后会自动尝试登录一次。若密码错误或需要验证码,卡片上会保留「登录」按钮,可手动重试。"}),T&&f.jsx("p",{className:"rounded-lg bg-red-50 px-3 py-2 text-[12px] text-red-700",children:T})]})})}class Ae extends Error{constructor(z,d={}){super(z);Li(this,"offline",!1);Li(this,"status");Li(this,"code");this.name="ApiError",Object.assign(this,d)}}async function Vt(r,E={}){let z;try{z=await fetch(r,{...E,headers:{"Content-Type":"application/json",...E.headers||{}}})}catch{throw new Ae("后端未连接",{offline:!0})}if(z.status===401)throw new Ae("需要访问令牌:请用 /?token= 打开一次",{status:401});if(!z.ok)throw new Ae(`HTTP ${z.status}`,{status:z.status});return await z.json()}async function pv(r,E,z){let d;try{d=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(E)})}catch{throw new Ae("后端未连接",{offline:!0})}if(d.status===401)throw new Ae("需要访问令牌:请用 /?token= 打开一次");if(!d.ok)throw new Ae(`HTTP ${d.status}`);if(!d.body)throw new Ae("浏览器不支持流式响应");const C=d.body.getReader(),B=new TextDecoder;let M="";for(;;){const{value:ut,done:tt}=await C.read();if(tt)break;M+=B.decode(ut,{stream:!0});const V=M.split(` - -`);M=V.pop()||"";for(const R of V){const T=R.trim();if(T.startsWith("data:"))try{z(JSON.parse(T.slice(5).trim()))}catch{}}}}function Sv(r){const E=String((r==null?void 0:r.text)||"").replace(/\s+/g," ").trim();return E.length>24?`${E.slice(0,24)}…`:E}function Tv({open:r,account:E,course:z,onClose:d,notify:C,onSubmitted:B}){const[M,ut]=X.useState(null),[tt,V]=X.useState({}),[R,T]=X.useState(!1),[Z,$]=X.useState(!1),[it,Ut]=X.useState(!1),[Y,vt]=X.useState(!1),[pt,Ct]=X.useState(""),[Ft,St]=X.useState("info"),J=X.useRef(0);async function K(H=!1){if(!E||!z)return!1;T(!0),Ct(H?"正在生成新答卷…":"取题中…"),St("info");try{const at={cookies:E.cookies,plan_id:z.plan_id,project_id:z.project_id,name:z.name||""};H&&(at.retake=!0,at.period_id=(M==null?void 0:M.period_id)||"");const st=await Vt("/api/quiz",{method:"POST",body:JSON.stringify(at)});if(!st.ok)return ut(null),Ct(st.error||"取题失败"),St("error"),!1;ut(st),V(Object.fromEntries((st.questions||[]).map(o=>[o.no,o.picked||""])));const Bt=[];if(st.done){const o=st.surplus_exam_count;o!=null?Bt.push(`剩 ${o} 次`):st.allow_exam_count&&Bt.push(`共 ${st.allow_exam_count} 次`),st.show_answers?Bt.push("已显示标准答案"):st.exam_after_watch_answer==="0"&&Bt.push("本测验不开放答案"),Ct(`已交卷${Bt.length?` · ${Bt.join(" · ")}`:""}`),St("success")}else Ct(st.started?"已自动创建答卷(限时考试已开始计时)":""),St("info");return!0}catch(at){return Ct(at instanceof Error?at.message:"取题失败"),St("error"),!1}finally{T(!1)}}if(X.useEffect(()=>{!r||!E||!z||(ut(null),V({}),vt(!1),K(!1))},[r,E==null?void 0:E.id,z==null?void 0:z.plan_id]),!E||!z)return null;const k=(M==null?void 0:M.questions)||[],_t=!!(M!=null&&M.done),qt=!!(M!=null&&M.show_answers),Zt=!!(M!=null&&M.can_retake),Tt=M==null?void 0:M.surplus_exam_count,Jt=_t||R||Z||Y;function al(H,at){V(st=>({...st,[H]:at}))}function Qt(H,at,st){V(Bt=>{const o=yn(Bt[H]),N=st?[...o,at]:o.filter(w=>w!==at);return N.sort(),{...Bt,[H]:N.join("#")}})}async function U(){if(!M||!E)return;const H=k.filter(at=>!tt[at.no]).length;if(!(H&&!window.confirm(`还有 ${H} 题没作答,确定提交?`))){$(!0),Ct("提交中…"),St("info");try{const at=await Vt("/api/quiz/submit",{method:"POST",body:JSON.stringify({cookies:E.cookies,plan_id:M.plan_id,object_id:M.object_id,generation:M.generation||"legacy",result_id:M.result_id||"",answers:tt})});if(!at.ok){at.code==="already_finished"&&await K(),Ct(at.error||"提交失败"),St("error");return}C({message:`测验已提交${at.score?`,得分 ${at.score}`:""}`,tone:"success"}),await K(),B()}catch(at){Ct(at instanceof Error?at.message:"提交失败"),St("error")}finally{$(!1)}}}async function F(){if(!M)return;if(!M.can_retake){C({message:"没有剩余考试机会",tone:"error"});return}const H=Tt!=null?`(剩余 ${Tt} 次)`:"";if(window.confirm(`再考一次会消耗 1 次机会${H};限时考试会立即开始计时,确定?`)){Ut(!0);try{await K(!0)&&C({message:"已生成新答卷,可以重新答题了",tone:"success"})}finally{Ut(!1)}}}async function I(){if(!M||!E)return;if(M.done){C({message:"已交卷,点「再考一次」生成新答卷后再 AI 答题",tone:"error"});return}vt(!0),J.current=0;const H=Date.now();let at=0,st="";const Bt=window.setInterval(()=>{Ct(`AI 答题中… ${Math.round((Date.now()-H)/1e3)}s · 已填 ${J.current}/${k.length} 题`),St("info")},1e3);Ct(`AI 答题中… 已填 0/${k.length} 题`);try{await pv("/api/quiz/answer",{questions:M.questions,account_id:E.id},o=>{const N=o.answers;if(N&&typeof N=="object"){const w=Object.keys(N).length;w&&(J.current+=w,V(G=>({...G,...N})))}o.error&&(st=String(o.error)),o.done&&typeof o.failed=="number"&&(at=o.failed)}),J.current?at?(Ct(`AI 已填 ${J.current} 题,${at} 题失败${st?`:${st}`:""}`),St("error")):(Ct(`AI 已填 ${J.current} 题`),St("success")):(Ct(st?`AI 答题失败:${st}`:"AI 没有返回答案"),St("error"))}catch(o){Ct(o instanceof Error?o.message:"AI 答题失败"),St("error")}finally{window.clearInterval(Bt),vt(!1)}}const gt=Zt?`再考一次${Tt!=null?`(剩 ${Tt} 次)`:""}`:Tt===0?"考试机会已用完":"再考一次";return f.jsx(Ki,{open:r,onClose:d,title:`测验 · ${z.name||z.plan_id}`,subtitle:pt||"取题后可手动作答,或让大模型逐批填写",size:"xl",footer:f.jsxs(f.Fragment,{children:[f.jsx("span",{className:vl("mr-auto max-w-[50%] truncate text-[11.5px]",Ft==="error"?"text-red-600":Ft==="success"?"text-emerald-600":"text-slate-500"),children:pt}),_t&&f.jsx(Kt,{size:"sm",loading:it,disabled:R||!Zt,icon:f.jsx(Ph,{className:"size-3.5"}),onClick:F,children:gt}),f.jsx(Kt,{size:"sm",onClick:d,children:"关闭"}),f.jsx(Kt,{size:"sm",variant:"soft",loading:Y,disabled:Jt||!k.length,icon:f.jsx(Bh,{className:"size-3.5"}),onClick:I,children:"AI 答题"}),f.jsx(Kt,{size:"sm",variant:"primary",loading:Z,disabled:Jt||!k.length,icon:f.jsx(lv,{className:"size-3.5"}),onClick:U,children:"提交"})]}),children:R&&!k.length?f.jsx("div",{className:"py-16 text-center text-[13px] text-slate-400",children:"正在打开课程页取题…"}):k.length?f.jsx("div",{className:"space-y-2.5",children:k.map(H=>{const at=H.options||[],st=tt[H.no]||"",Bt=H.type==="02",o=at.length>0;return f.jsxs("div",{className:"rounded-xl border border-line px-3.5 py-3",children:[f.jsxs("div",{className:"flex items-start gap-2",children:[f.jsx("span",{className:"mt-0.5 grid size-5 shrink-0 place-items-center rounded-md bg-slate-100 text-[10.5px] font-semibold tabular-nums text-slate-500",children:H.no}),f.jsx(Hs,{tone:"neutral",className:"mt-0.5 shrink-0",children:ov[H.type||""]||"题目"}),f.jsx("p",{className:"min-w-0 flex-1 text-[13px] leading-relaxed text-slate-800",children:H.title||`第 ${H.no} 题`}),qt&&H.is_correct!==void 0&&f.jsx("span",{className:vl("shrink-0 text-[12px] font-semibold",H.is_correct?"text-emerald-600":"text-red-500"),children:H.is_correct?"✓":"✗"})]}),o&&f.jsx("div",{className:"mt-2 flex flex-wrap gap-1.5 pl-7",children:at.map(N=>{const w=qt&&yn(H.correct).includes(N.key),G=qt&&yn(H.picked).includes(N.key)&&!yn(H.correct).includes(N.key);return f.jsxs("span",{className:vl("max-w-full rounded-lg border px-2 py-1 text-[11.5px] leading-snug",w?"border-emerald-200 bg-emerald-50 text-emerald-800":G?"border-red-200 bg-red-50 text-red-700":"border-line bg-slate-50/70 text-slate-600"),children:[f.jsx("b",{className:"mr-1 font-semibold",children:N.key}),Sv(N)]},N.key)})}),f.jsxs("div",{className:"mt-2.5 flex flex-wrap items-center gap-2 pl-7",children:[Bt?f.jsx("div",{className:"flex flex-wrap gap-1.5",children:at.map(N=>{const w=yn(st);return f.jsxs("label",{title:`${N.key}. ${N.text||""}`,className:vl("flex cursor-pointer items-center gap-1 rounded-lg border px-2 py-1 text-[11.5px] transition",w.includes(N.key)?"border-brand-300 bg-brand-50 text-brand-700":"border-line text-slate-600 hover:border-slate-300",Jt&&"pointer-events-none opacity-60"),children:[f.jsx("input",{type:"checkbox",className:"size-3 accent-brand-500",checked:w.includes(N.key),disabled:Jt,onChange:G=>Qt(H.no,N.key,G.target.checked)}),N.key]},N.key)})}):o?f.jsxs("select",{className:"h-8 w-full max-w-[320px] rounded-lg border border-line bg-white px-2 text-[12px] text-slate-700 focus:border-brand-500 focus:outline-none disabled:bg-slate-50 disabled:text-slate-400",value:st,disabled:Jt,onChange:N=>al(H.no,N.target.value),children:[f.jsx("option",{value:"",children:"未选"}),at.map(N=>f.jsxs("option",{value:N.key,children:[N.key,". ",N.text||""]},N.key))]}):f.jsx("input",{className:"h-8 w-full max-w-[320px] rounded-lg border border-line bg-white px-2 text-[12px] text-slate-700 focus:border-brand-500 focus:outline-none disabled:bg-slate-50 disabled:text-slate-400",value:st,placeholder:"填写答案",disabled:Jt,onChange:N=>al(H.no,N.target.value)}),qt&&H.correct&&f.jsxs("span",{className:"text-[11.5px] text-slate-500",children:["标准答案:",f.jsx("b",{className:"font-semibold text-slate-700",children:H.correct})]})]}),qt&&H.analysis&&f.jsxs("p",{className:"mt-2 rounded-lg bg-slate-50 px-2.5 py-1.5 text-[11.5px] leading-relaxed text-slate-500",children:["解析:",H.analysis]})]},H.no)})}):f.jsx("div",{className:"py-16 text-center text-[13px] text-red-600",children:pt||"没有题目"})})}function Nv({open:r,onClose:E,notify:z}){const[d,C]=X.useState(!1),[B,M]=X.useState(!1),[ut,tt]=X.useState(!1),[V,R]=X.useState({base_url:"",api_key:"",model:"",temperature:"0.2",timeout:"120",prompt:"",study_mode:"fast",study_parallel:"2"}),[T,Z]=X.useState("sk-...");X.useEffect(()=>{r&&(C(!0),Vt("/api/settings").then(Y=>{const vt=Y.llm||{},pt=Y.study||{};R({base_url:vt.base_url||"",api_key:"",model:vt.model||"",temperature:String(vt.temperature??.2),timeout:String(vt.timeout??120),prompt:vt.prompt||"",study_mode:pt.mode||"fast",study_parallel:String(pt.parallel||2)}),Z(vt.has_key?`已保存 ${vt.key_hint||""},留空不修改`:"sk-...")}).catch(Y=>z({message:`读取设置失败:${Y.message}`,tone:"error"})).finally(()=>C(!1)))},[r,z]);function $(Y,vt){R(pt=>({...pt,[Y]:vt}))}async function it(){M(!0);try{await Vt("/api/settings",{method:"POST",body:JSON.stringify({base_url:V.base_url.trim(),api_key:V.api_key.trim(),model:V.model.trim(),temperature:Number.parseFloat(V.temperature)||.2,timeout:Number.parseInt(V.timeout,10)||120,prompt:V.prompt,study_mode:V.study_mode,study_parallel:Number.parseInt(V.study_parallel,10)||0})}),z({message:"设置已保存",tone:"success"}),E()}catch(Y){z({message:`保存失败:${Y instanceof Error?Y.message:Y}`,tone:"error"})}finally{M(!1)}}async function Ut(){tt(!0);try{const Y=await Vt("/api/llm/test",{method:"POST",body:JSON.stringify({base_url:V.base_url.trim(),api_key:V.api_key.trim(),model:V.model.trim()})});z({message:Y.ok?`连接正常(${Y.ms} ms):${Y.reply||""}`:`连接失败:${Y.error||"未知错误"}`,tone:Y.ok?"success":"error"})}catch(Y){z({message:`连接失败:${Y instanceof Error?Y.message:Y}`,tone:"error"})}finally{tt(!1)}}return f.jsx(Ki,{open:r,onClose:E,title:"系统设置",subtitle:"大模型接口、答题提示词与学习模式",size:"lg",footer:f.jsxs(f.Fragment,{children:[f.jsx(Kt,{loading:ut,onClick:Ut,icon:f.jsx(Vh,{className:"size-3.5"}),children:"测试连接"}),f.jsx(Kt,{onClick:E,disabled:B,children:"取消"}),f.jsx(Kt,{variant:"primary",loading:B,onClick:it,disabled:d,children:"保存"})]}),children:d?f.jsx("div",{className:"py-10 text-center text-[12.5px] text-slate-400",children:"读取设置…"}):f.jsxs("div",{className:"space-y-6",children:[f.jsxs("section",{children:[f.jsxs("div",{className:"mb-3 flex items-center gap-2 text-[12.5px] font-semibold text-slate-700",children:[f.jsx(ev,{className:"size-4 text-brand-500"}),"大模型(OpenAI 兼容)"]}),f.jsxs("div",{className:"space-y-3",children:[f.jsxs("div",{children:[f.jsxs("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:["接口地址 ",f.jsx("span",{className:"text-slate-400",children:"(写到 /v1 为止)"})]}),f.jsx("input",{className:Pl,value:V.base_url,placeholder:"https://api.openai.com/v1",onChange:Y=>$("base_url",Y.target.value)})]}),f.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"API Key"}),f.jsxs("div",{className:"relative",children:[f.jsx(kh,{className:"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-slate-400"}),f.jsx("input",{className:`${Pl} pl-8`,type:"password",autoComplete:"off",value:V.api_key,placeholder:T,onChange:Y=>$("api_key",Y.target.value)})]})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"模型"}),f.jsx("input",{className:Pl,value:V.model,placeholder:"gpt-4o-mini / deepseek-chat / qwen-plus",onChange:Y=>$("model",Y.target.value)})]})]}),f.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"温度"}),f.jsx("input",{className:Pl,type:"number",min:0,max:2,step:.1,value:V.temperature,onChange:Y=>$("temperature",Y.target.value)})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"超时(秒)"}),f.jsx("input",{className:Pl,type:"number",min:10,max:600,value:V.timeout,onChange:Y=>$("timeout",Y.target.value)})]})]}),f.jsxs("div",{children:[f.jsxs("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:["答题提示词 ",f.jsx("span",{className:"text-slate-400",children:"(留空使用内置)"})]}),f.jsx("textarea",{className:`${Pl} min-h-24 resize-y`,value:V.prompt,placeholder:'只输出 JSON {"answers":{"题号":"答案"}}',onChange:Y=>$("prompt",Y.target.value)})]})]})]}),f.jsxs("section",{className:"border-t border-line pt-5",children:[f.jsxs("div",{className:"mb-3 flex items-center gap-2 text-[12.5px] font-semibold text-slate-700",children:[f.jsx(Lh,{className:"size-4 text-brand-500"}),"学习模式"]}),f.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"模式"}),f.jsxs("select",{className:Pl,value:V.study_mode,onChange:Y=>$("study_mode",Y.target.value),children:[f.jsx("option",{value:"fast",children:"快速学习(只调接口上报)"}),f.jsx("option",{value:"normal",children:"常规学习(真实播放视频)"})]})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"常规模式并发数"}),f.jsx("input",{className:Pl,type:"number",min:1,max:5,value:V.study_parallel,onChange:Y=>$("study_parallel",Y.target.value)})]})]}),f.jsxs("p",{className:"mt-3 rounded-lg bg-slate-50 px-3 py-2 text-[11.5px] leading-relaxed text-slate-500",children:["常规学习会开多个无头浏览器同时播视频;平台若按课节顺序放行,会被弹回并自动降为 1 路。快速学习只调用 ",f.jsx("code",{className:"rounded bg-white px-1 ring-1 ring-line",children:"period/study/log"}),",不启动浏览器。"]})]})]})})}function Ev({accounts:r}){const E=r.filter(M=>{var ut;return((ut=M.cookies)==null?void 0:ut.length)>0||["logged_in","studying"].includes(M.status||"")}).length,z=r.filter(M=>{var ut;return["discovering","studying"].includes(((ut=M.run)==null?void 0:ut.status)||"")}).length,d=r.reduce((M,ut)=>{var tt;return M+(((tt=ut.run)==null?void 0:tt.done)||0)},0),C=r.reduce((M,ut)=>{var tt;return M+(((tt=ut.run)==null?void 0:tt.total)||0)},0),B=[{label:"账号",value:r.length,hint:"已添加",icon:Tm,tone:"text-brand-600 bg-brand-50"},{label:"已登录",value:E,hint:r.length?`共 ${r.length} 个`:"等待添加",icon:uv,tone:"text-emerald-600 bg-emerald-50"},{label:"学习中",value:z,hint:z?"正在跑课":"空闲",icon:qh,tone:"text-sky-600 bg-sky-50"},{label:"课程进度",value:C?`${d}/${C}`:"—",hint:C?`${Math.round(d/C*100)}%`:"暂无任务",icon:Kh,tone:"text-amber-600 bg-amber-50"}];return f.jsx("section",{className:"grid grid-cols-2 gap-3 lg:grid-cols-4",children:B.map(M=>f.jsxs("div",{className:"flex items-center gap-3 rounded-xl border border-line bg-white px-4 py-3",children:[f.jsx("span",{className:`grid size-9 shrink-0 place-items-center rounded-lg ${M.tone}`,children:f.jsx(M.icon,{className:"size-4"})}),f.jsxs("div",{className:"min-w-0",children:[f.jsx("div",{className:"text-[11px] text-slate-400",children:M.label}),f.jsxs("div",{className:"flex items-baseline gap-1.5",children:[f.jsx("span",{className:"text-[17px] font-semibold tabular-nums leading-tight text-slate-900",children:M.value}),f.jsx("span",{className:"truncate text-[10.5px] text-slate-400",children:M.hint})]})]})]},M.label))})}function zv({open:r,onClose:E}){const[z,d]=X.useState([]),[C,B]=X.useState(!1),M=X.useRef(null),ut=X.useRef(!0);X.useEffect(()=>{if(!r)return;let V=!0;const R=async()=>{try{const Z=await Vt("/api/log/history?key=system&tail=500");V&&d(Z.lines||[])}catch{}};d([]),R();const T=window.setInterval(()=>{document.hidden||R()},2500);return()=>{V=!1,window.clearInterval(T)}},[r]),X.useEffect(()=>{const V=M.current;V&&ut.current&&(V.scrollTop=V.scrollHeight)},[z,r]);async function tt(){B(!0);try{await Vt("/api/log/history?key=system",{method:"DELETE"}),d([])}finally{B(!1)}}return f.jsx(Ki,{open:r,onClose:E,title:"系统日志",subtitle:"全局事件与系统级错误,实时刷新",size:"xl",footer:f.jsxs(f.Fragment,{children:[f.jsxs("span",{className:"mr-auto text-[11px] text-slate-400",children:["共 ",z.length," 行 · 保留最近 500 行"]}),f.jsx(Kt,{variant:"danger",size:"sm",loading:C,onClick:tt,children:"清空"}),f.jsx(Kt,{size:"sm",onClick:E,children:"关闭"})]}),bodyClassName:"bg-slate-950 p-0",children:f.jsx("pre",{ref:M,onScroll:V=>{const R=V.currentTarget;ut.current=R.scrollHeight-R.scrollTop-R.clientHeight<24},className:"scrollbar-thin h-[60vh] overflow-auto whitespace-pre-wrap break-words p-4 font-mono text-[11.5px] leading-relaxed text-slate-300",children:z.length?z.join(` -`):"暂无系统日志"})})}function _v({toast:r}){if(!r)return null;const E=r.tone||"info",z=E==="error"?wh:E==="success"?Gh:Jh;return f.jsxs("div",{role:"status",className:vl("animate-toast-in fixed bottom-7 left-1/2 z-[60] flex max-w-[85vw] -translate-x-1/2 items-center gap-2","rounded-xl px-4 py-2.5 text-[12.5px] font-medium shadow-xl shadow-slate-900/20",E==="error"?"bg-red-600 text-white":E==="success"?"bg-emerald-600 text-white":"bg-slate-900 text-white"),children:[f.jsx(z,{className:"size-4 shrink-0 opacity-90"}),f.jsx("span",{className:"break-words",children:r.message})]})}function Ov({refreshing:r,onRefresh:E,onSettings:z,onSystemLog:d,onAdd:C}){return f.jsx("header",{className:"sticky top-0 z-30 border-b border-line/80 bg-white/85 backdrop-blur-xl",children:f.jsxs("div",{className:"mx-auto flex h-16 max-w-[1320px] items-center gap-3 px-4 sm:px-6",children:[f.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[f.jsx("div",{className:"grid size-9 shrink-0 place-items-center rounded-xl bg-gradient-to-br from-brand-500 to-sky-400 text-[15px] font-bold text-white shadow-md shadow-brand-500/30",children:"学"}),f.jsxs("div",{className:"min-w-0",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx("h1",{className:"truncate text-[15px] font-semibold tracking-tight text-slate-900",children:"莞易学"}),f.jsx("span",{className:"hidden rounded-md bg-slate-100 px-1.5 py-0.5 text-[10px] font-medium text-slate-500 sm:inline",children:"多账号学习控制台"})]}),f.jsx("p",{className:"truncate text-[11.5px] text-slate-500",children:"东莞市教师培训平台 · 新旧版课程自动识别"})]})]}),f.jsx("div",{className:"flex-1"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx(Kt,{variant:"ghost",size:"icon",onClick:E,loading:r,title:"刷新列表","aria-label":"刷新列表",children:f.jsx(Bs,{className:"size-4"})}),f.jsx(Kt,{variant:"ghost",size:"icon",onClick:d,title:"系统日志","aria-label":"系统日志",children:f.jsx(tv,{className:"size-4"})}),f.jsx(Kt,{variant:"ghost",size:"icon",onClick:z,title:"系统设置","aria-label":"系统设置",children:f.jsx(av,{className:"size-4"})}),f.jsx(Kt,{variant:"primary",className:"ml-1",icon:f.jsx(Sm,{className:"size-4"}),onClick:C,children:f.jsx("span",{className:"hidden sm:inline",children:"添加账号"})})]})]})})}const Em="guanyixue.inlineLogsOpen";function Av(){try{const r=JSON.parse(localStorage.getItem(Em)||"[]");return new Set(Array.isArray(r)?r.filter(E=>typeof E=="string"):[])}catch{return new Set}}function jv(r){try{localStorage.setItem(Em,JSON.stringify([...r]))}catch{}}function Mv(r){return{id:r.id,username:r.username,note:r.note||"",user:r.user||"",cookies:r.cookies||[],courses:r.courses||[],selected:r.selected||[],status:r.status||"idle",lastError:r.lastError||"",lastErrorAt:r.lastErrorAt||0,optQuiz:r.optQuiz===!0,optFeedback:r.optFeedback!==!1,loginAt:r.loginAt||0}}function Cv(){const[r,E]=X.useState([]),z=X.useRef(r),[d,C]=X.useState({guanyixue:"莞易学"}),[B,M]=X.useState(!1),[ut,tt]=X.useState(null),[V,R]=X.useState({}),[T,Z]=X.useState(!1),[$,it]=X.useState(null),[Ut,Y]=X.useState(()=>Av()),vt=X.useRef(Ut),[pt,Ct]=X.useState({}),Ft=X.useRef(pt),St=X.useRef(void 0);X.useEffect(()=>{z.current=r},[r]),X.useEffect(()=>{Ft.current=pt},[pt]),X.useEffect(()=>{vt.current=Ut,jv(Ut)},[Ut]),X.useEffect(()=>()=>window.clearTimeout(St.current),[]);const J=X.useCallback(x=>{tt(x),window.clearTimeout(St.current),St.current=window.setTimeout(()=>tt(null),3800)},[]),K=X.useCallback(async x=>{const j=await Vt("/api/accounts",{method:"POST",body:JSON.stringify(Mv(x))});if(j.ok===!1)throw new Error(j.error||"保存失败");return j},[]),k=X.useCallback(x=>{E(j=>{const A=j.some(lt=>lt.id===x.id)?j.map(lt=>lt.id===x.id?x:lt):[...j,x];return z.current=A,A})},[]),_t=X.useCallback(async(x=!0)=>{var j;try{const[p,A]=await Promise.all([Vt("/api/runs"),Vt("/api/accounts")]),lt=(A.accounts||[]).map(P=>({...P,run:p[P.id]||null})).sort((P,q)=>(P.created||0)-(q.created||0));E(lt),z.current=lt,M(!1);for(const P of lt){const q=(j=P.run)==null?void 0:j.cookies;if(q&&q.length&&JSON.stringify(q)!==JSON.stringify(P.cookies||[])){const Yt={...P,cookies:q};P.cookies=q,K(Yt).catch(()=>{})}}}catch(p){p instanceof Ae&&p.offline?M(!0):x||J({message:`读取账号失败:${de(p)}`,tone:"error"})}},[J,K]);X.useEffect(()=>{_t();const x=window.setInterval(()=>{document.hidden||_t()},5e3);return()=>window.clearInterval(x)},[_t]),X.useEffect(()=>{Vt("/api/platforms").then(x=>{const j={};for(const p of x.platforms||[])j[p.id]=p.label;Object.keys(j).length&&C(j)}).catch(()=>{})},[]);const qt=X.useCallback(async x=>{var lt;const j=Ft.current[x]||{lines:[],since:0,busy:!1,historyTried:!1};if(j.busy)return;const p={...j,busy:!0},A=P=>{Ft.current={...Ft.current,[x]:P},Ct(q=>({...q,[x]:P}))};A(p);try{let P=await Vt(`/api/log?key=${encodeURIComponent(x)}&since=${p.since}`);typeof P.next=="number"&&P.nextNt.id===x);if(Rt&&JSON.stringify(Rt.cookies||[])!==JSON.stringify(Yt)){const Nt={...Rt,cookies:Yt};k(Nt),K(Nt).catch(()=>{})}}}catch{}finally{p.busy=!1,A(p)}},[k,K]);X.useEffect(()=>{const x=window.setInterval(()=>{document.hidden||vt.current.forEach(j=>void qt(j))},1500);return()=>window.clearInterval(x)},[qt]);const Zt=X.useCallback((x,j)=>{const p=j===void 0?!vt.current.has(x):j,A=new Set(vt.current);p?A.add(x):A.delete(x),vt.current=A,Y(A),p&&qt(x)},[qt]);async function Tt(x,j,p){R(A=>({...A,[x]:j}));try{return await p()}finally{R(A=>{const lt={...A};return delete lt[x],lt})}}async function Jt(x,j=!1){return Tt(x.id,"login",async()=>{k({...x,status:"logging",lastError:""});try{await K({...x,status:"logging",lastError:""});const p=await Vt("/api/login",{method:"POST",body:JSON.stringify({account_id:x.id})});if(!p.ok){const P={...x,status:"login_failed",lastError:p.error||`HTTP ${p.code||"失败"}`,lastErrorAt:Date.now(),run:null};return k(P),await K(P).catch(()=>{}),j||J({message:`登录失败:${P.lastError}`,tone:"error"}),!1}const A=p.courses||[],lt={...x,status:"logged_in",cookies:p.cookies||[],user:p.user||x.user||"",courses:A,selected:(x.selected||[]).filter(P=>A.some(q=>q.plan_id===P)),loginAt:Date.now(),updated:Date.now(),lastError:"",lastErrorAt:0,run:null};return k(lt),await K(lt).catch(()=>{}),j||J({message:p.warn?`登录成功,但课程读取异常:${p.warn}`:`登录成功:${lt.user||lt.username},读到 ${Rs(A).total} 门`,tone:p.warn?"info":"success"}),_t(),!0}catch(p){const A={...x,status:"login_failed",lastError:de(p),lastErrorAt:Date.now()};return k(A),await K(A).catch(()=>{}),j||J({message:`登录失败:${A.lastError}`,tone:"error"}),p instanceof Ae&&p.offline&&M(!0),!1}})}async function al(x){return Tt(x.id,"refresh",async()=>{var j;try{let p=await Vt("/api/courses",{method:"POST",body:JSON.stringify({cookies:x.cookies})});if(!p.ok&&p.code==="session_expired"){if(J({message:"会话已失效,正在自动重新登录…"}),!await Jt(x,!0))return;const P=z.current.find(q=>q.id===x.id);if(!P)return;p=await Vt("/api/courses",{method:"POST",body:JSON.stringify({cookies:P.cookies})})}if(!p.ok){J({message:`读取失败:${p.error||p.code||"未知错误"}`,tone:"error"});return}const A=z.current.find(P=>P.id===x.id)||x,lt={...A,courses:p.courses||[],user:p.user||A.user,cookies:(j=p.cookies)!=null&&j.length?p.cookies:A.cookies,status:"logged_in",updated:Date.now(),lastError:"",lastErrorAt:0};k(lt),await K(lt).catch(()=>{}),J({message:`已刷新,读到 ${Rs(lt.courses).total} 门`,tone:"success"})}catch(p){J({message:`读取失败:${de(p)}`,tone:"error"})}})}async function Qt(x){var A;const j=x.selected||[],p=(x.courses||[]).filter(lt=>j.includes(lt.plan_id)&<.in_study!==!1);if(!p.length){J({message:"请先勾选要学习的课程",tone:"error"});return}if(!((A=x.cookies)!=null&&A.length)){J({message:"请先登录",tone:"error"});return}return Tt(x.id,"study",async()=>{var lt,P;try{const q=await Vt("/api/study",{method:"POST",body:JSON.stringify({key:x.id,username:x.user||x.username,cookies:x.cookies,courses:p,workers:40,cap_minutes:90,enable_quiz:x.optQuiz===!0,enable_feedback:x.optFeedback!==!1})});if(!q.ok){J({message:`启动失败:${q.error||"未知错误"}`,tone:"error"});return}const Yt=((lt=q.study)==null?void 0:lt.mode)==="normal"?`常规真播 ${((P=q.study)==null?void 0:P.parallel)||1} 路并发`:"快速模式(只调接口)";J({message:`已开始 ${p.length} 门课程 · ${Yt}${x.optQuiz?" · 含自动答题":" · 测验需手动作答"}`,tone:"success"}),Zt(x.id,!0),_t()}catch(q){J({message:`启动失败:${de(q)}`,tone:"error"})}})}async function U(x){return Tt(x.id,"stop",async()=>{try{await Vt("/api/stop",{method:"POST",body:JSON.stringify({key:x.id})}),J({message:"已请求停止"}),_t()}catch(j){J({message:`停止失败:${de(j)}`,tone:"error"})}})}async function F(x){var j;if(!((j=x.cookies)!=null&&j.length)){J({message:"请先登录",tone:"error"});return}return Tt(x.id,"capture",async()=>{try{const p=await Vt("/api/capture",{method:"POST",body:JSON.stringify({key:x.id,cookies:x.cookies,minutes:10})});if(!p.ok){J({message:`抓包失败:${p.error||"未知错误"}`,tone:"error"});return}J({message:"已打开浏览器,请手动走一遍课程页;最多记录 10 分钟",tone:"success"})}catch(p){J({message:`抓包失败:${de(p)}`,tone:"error"})}})}async function I(x){return Tt(x.id,"capture",async()=>{try{await Vt("/api/capture/stop",{method:"POST",body:JSON.stringify({key:x.id})}),J({message:"已请求停止抓包"}),_t()}catch(j){J({message:`停止抓包失败:${de(j)}`,tone:"error"})}})}async function gt(x){if(window.confirm(`删除账号「${x.user||x.username}」?课程缓存和日志不会自动清理。`))try{await Vt(`/api/accounts/${encodeURIComponent(x.id)}`,{method:"DELETE"}),E(j=>{const p=j.filter(A=>A.id!==x.id);return z.current=p,p}),J({message:"账号已删除"})}catch(j){J({message:`删除失败:${de(j)}`,tone:"error"})}}async function H(x,j){const p={...x,selected:j};k(p);try{await K(p)}catch(A){J({message:`保存勾选失败:${de(A)}`,tone:"error"})}}function at(x,j,p){const A=x.selected||[];H(x,p?[...new Set([...A,j])]:A.filter(lt=>lt!==j))}function st(x){const j=(x.courses||[]).filter(p=>p.in_study!==!1).map(p=>p.plan_id);H(x,[...new Set([...x.selected||[],...j])])}async function Bt(x,j,p){const A=j==="quiz"?{...x,optQuiz:p}:{...x,optFeedback:p};k(A);try{await K(A),J({message:j==="quiz"?p?"已开启自动交测验(注意正确率)":"已关闭自动交测验":p?"已开启自动交反馈表":"已关闭自动交反馈表"})}catch(lt){J({message:`保存失败:${de(lt)}`,tone:"error"})}}async function o(x){const j=await Vt("/api/accounts",{method:"POST",body:JSON.stringify({username:x.username,password:x.password,note:x.note,cookies:[],courses:[],selected:[],status:"idle",created:Date.now()})});if(j.ok===!1)throw new Error(j.error||"保存失败");const p=await Vt("/api/accounts"),A=j.account||(p.accounts||[]).find(q=>q.username===x.username);if(!A){J({message:"已保存,但列表里没有找到新账号,请刷新页面",tone:"error"}),await _t();return}J({message:"已保存,正在尝试首次登录…"});const lt=await Jt(A,!0),P=z.current.find(q=>q.id===A.id);J(lt?{message:`登录成功:${(P==null?void 0:P.user)||x.username}`,tone:"success"}:{message:`登录失败:${(P==null?void 0:P.lastError)||"未知原因"}(请手动点击「登录」重试)`,tone:"error"}),await _t()}async function N(){Z(!0);try{await _t(!1)}finally{Z(!1)}}function w(x){var p;const j=(p=(x.courses||[]).find(A=>A.platform))==null?void 0:p.platform;return j&&d[j]||"莞易学"}const G=($==null?void 0:$.type)==="quiz"&&r.find(x=>x.id===$.accountId)||null,ot=($==null?void 0:$.type)==="quiz"?(G==null?void 0:G.courses.find(x=>x.plan_id===$.course.plan_id))||$.course:null;return f.jsxs("div",{className:"min-h-screen",children:[f.jsx(Ov,{refreshing:T,onRefresh:()=>void N(),onSettings:()=>it({type:"settings"}),onSystemLog:()=>it({type:"system"}),onAdd:()=>it({type:"add"})}),f.jsxs("main",{className:"mx-auto max-w-[1320px] px-4 pb-16 pt-5 sm:px-6",children:[B&&f.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2.5 rounded-xl border border-red-200 bg-red-50 px-4 py-2.5 text-[12.5px] text-red-700",children:[f.jsx(fv,{className:"size-4 shrink-0"}),f.jsx("span",{className:"font-medium",children:"后端未连接"}),f.jsx("span",{className:"text-red-500",children:"页面显示的是上一次数据,请确认服务已启动、端口没有变化。"}),f.jsx("div",{className:"flex-1"}),f.jsx(Kt,{size:"sm",variant:"secondary",loading:T,onClick:()=>void N(),children:"重试"})]}),f.jsx(Ev,{accounts:r}),f.jsxs("div",{className:"mb-3 mt-6 flex items-end justify-between gap-3",children:[f.jsxs("div",{children:[f.jsx("h2",{className:"text-[14px] font-semibold text-slate-900",children:"账号列表"}),f.jsx("p",{className:"mt-0.5 text-[11.5px] text-slate-400",children:"新旧版课程自动识别为「莞易学」,每 5 秒自动刷新状态"})]}),r.length>0&&f.jsx(Kt,{size:"sm",variant:"secondary",icon:f.jsx(Bs,{className:"size-3.5"}),loading:T,onClick:()=>void N(),children:"刷新"})]}),r.length===0?f.jsxs("div",{className:"card-shadow grid place-items-center rounded-2xl border border-dashed border-slate-300 bg-white px-6 py-16 text-center",children:[f.jsx("div",{className:"grid size-12 place-items-center rounded-2xl bg-brand-50 text-brand-600",children:f.jsx(Tm,{className:"size-6"})}),f.jsx("h3",{className:"mt-4 text-[14px] font-semibold text-slate-800",children:"还没有账号"}),f.jsx("p",{className:"mt-1.5 max-w-md text-[12.5px] leading-relaxed text-slate-500",children:"添加东莞市教师培训平台账号后,可自动读取课程、勾选学习、提交反馈表与测验。 新旧版课程页会统一识别为「莞易学」。"}),f.jsx(Kt,{variant:"primary",className:"mt-5",icon:f.jsx(Sm,{className:"size-4"}),onClick:()=>it({type:"add"}),children:"添加第一个账号"})]}):f.jsx("div",{className:"grid items-start gap-4 md:grid-cols-2 xl:grid-cols-3",children:r.map(x=>{var j;return f.jsx(gv,{account:x,platformLabel:w(x),pending:V[x.id],openLog:Ut.has(x.id),logLines:((j=pt[x.id])==null?void 0:j.lines)||[],onToggleLog:()=>Zt(x.id),onLogin:()=>void Jt(x),onRefresh:()=>void al(x),onStudy:()=>void Qt(x),onStop:()=>void U(x),onCapture:()=>void F(x),onStopCapture:()=>void I(x),onDelete:()=>void gt(x),onQuiz:()=>{var lt;const p=(x.courses||[]).filter(P=>P.in_study!==!1),A=p.find(P=>{var q;return(q=x.selected)==null?void 0:q.includes(P.plan_id)})||p[0];if(!A){J({message:"这门课还没有课程数据,先点「刷新课程」",tone:"error"});return}if(!((lt=x.cookies)!=null&<.length)){J({message:"请先登录",tone:"error"});return}it({type:"quiz",accountId:x.id,course:A})},onToggleCourse:(p,A)=>at(x,p,A),onSelectAll:()=>st(x),onClearSelection:()=>void H(x,[]),onToggleOption:(p,A)=>void Bt(x,p,A)},x.id)})})]}),f.jsx("footer",{className:"border-t border-line/70 py-5 text-center text-[11px] text-slate-400",children:"莞易学 · 多账号学习控制台 · 数据保存在本机"}),f.jsx(xv,{open:($==null?void 0:$.type)==="add",onClose:()=>it(null),onSubmit:o}),f.jsx(Nv,{open:($==null?void 0:$.type)==="settings",onClose:()=>it(null),notify:J}),f.jsx(zv,{open:($==null?void 0:$.type)==="system",onClose:()=>it(null)}),f.jsx(Tv,{open:($==null?void 0:$.type)==="quiz"&&!!G,account:G,course:ot,onClose:()=>it(null),notify:J,onSubmitted:()=>void _t()}),f.jsx(_v,{toast:ut})]})}Dh.createRoot(document.getElementById("root")).render(f.jsx(X.StrictMode,{children:f.jsx(Cv,{})})); diff --git a/static/assets/index-Dfv5RNeD.js b/static/assets/index-Dfv5RNeD.js new file mode 100644 index 0000000..b0fbf72 --- /dev/null +++ b/static/assets/index-Dfv5RNeD.js @@ -0,0 +1,228 @@ +var Nh=Object.defineProperty;var Eh=(r,N,E)=>N in r?Nh(r,N,{enumerable:!0,configurable:!0,writable:!0,value:E}):r[N]=E;var Li=(r,N,E)=>Eh(r,typeof N!="symbol"?N+"":N,E);(function(){const N=document.createElement("link").relList;if(N&&N.supports&&N.supports("modulepreload"))return;for(const M of document.querySelectorAll('link[rel="modulepreload"]'))d(M);new MutationObserver(M=>{for(const w of M)if(w.type==="childList")for(const j of w.addedNodes)j.tagName==="LINK"&&j.rel==="modulepreload"&&d(j)}).observe(document,{childList:!0,subtree:!0});function E(M){const w={};return M.integrity&&(w.integrity=M.integrity),M.referrerPolicy&&(w.referrerPolicy=M.referrerPolicy),M.crossOrigin==="use-credentials"?w.credentials="include":M.crossOrigin==="anonymous"?w.credentials="omit":w.credentials="same-origin",w}function d(M){if(M.ep)return;M.ep=!0;const w=E(M);fetch(M.href,w)}})();var As={exports:{}},dn={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var sm;function zh(){if(sm)return dn;sm=1;var r=Symbol.for("react.transitional.element"),N=Symbol.for("react.fragment");function E(d,M,w){var j=null;if(w!==void 0&&(j=""+w),M.key!==void 0&&(j=""+M.key),"key"in M){w={};for(var ut in M)ut!=="key"&&(w[ut]=M[ut])}else w=M;return M=w.ref,{$$typeof:r,type:d,key:j,ref:M!==void 0?M:null,props:w}}return dn.Fragment=N,dn.jsx=E,dn.jsxs=E,dn}var rm;function _h(){return rm||(rm=1,As.exports=zh()),As.exports}var f=_h(),js={exports:{}},nt={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var om;function Oh(){if(om)return nt;om=1;var r=Symbol.for("react.transitional.element"),N=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),M=Symbol.for("react.profiler"),w=Symbol.for("react.consumer"),j=Symbol.for("react.context"),ut=Symbol.for("react.forward_ref"),W=Symbol.for("react.suspense"),V=Symbol.for("react.memo"),q=Symbol.for("react.lazy"),S=Symbol.for("react.activity"),Z=Symbol.for("react.view_transition"),rt=Symbol.iterator;function Xt(o){return o===null||typeof o!="object"?null:(o=rt&&o[rt]||o["@@iterator"],typeof o=="function"?o:null)}var et={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},D=Object.assign,dt={};function tt(o,T,Y){this.props=o,this.context=T,this.refs=dt,this.updater=Y||et}tt.prototype.isReactComponent={},tt.prototype.setState=function(o,T){if(typeof o!="object"&&typeof o!="function"&&o!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,o,T,"setState")},tt.prototype.forceUpdate=function(o){this.updater.enqueueForceUpdate(this,o,"forceUpdate")};function Tt(){}Tt.prototype=tt.prototype;function Ft(o,T,Y){this.props=o,this.context=T,this.refs=dt,this.updater=Y||et}var Mt=Ft.prototype=new Tt;Mt.constructor=Ft,D(Mt,tt.prototype),Mt.isPureReactComponent=!0;var Ht=Array.isArray;function F(){}var C={H:null,A:null,T:null,S:null},At=Object.prototype.hasOwnProperty;function zt(o,T,Y){var Q=Y.ref;return{$$typeof:r,type:o,key:T,ref:Q!==void 0?Q:null,props:Y}}function Nt(o,T){return zt(o.type,T,o.props)}function Ct(o){return typeof o=="object"&&o!==null&&o.$$typeof===r}function Wt(o){var T={"=":"=0",":":"=2"};return"$"+o.replace(/[=:]/g,function(Y){return T[Y]})}var Lt=/\/+/g;function Bt(o,T){return typeof o=="object"&&o!==null&&o.key!=null?Wt(""+o.key):T.toString(36)}function H(o){switch(o.status){case"fulfilled":return o.value;case"rejected":throw o.reason;default:switch(typeof o.status=="string"?o.then(F,F):(o.status="pending",o.then(function(T){o.status==="pending"&&(o.status="fulfilled",o.value=T)},function(T){o.status==="pending"&&(o.status="rejected",o.reason=T)})),o.status){case"fulfilled":return o.value;case"rejected":throw o.reason}}throw o}function k(o,T,Y,Q,mt){var st=typeof o;(st==="undefined"||st==="boolean")&&(o=null);var vt=!1;if(o===null)vt=!0;else switch(st){case"bigint":case"string":case"number":vt=!0;break;case"object":switch(o.$$typeof){case r:case N:vt=!0;break;case q:return vt=o._init,k(vt(o._payload),T,Y,Q,mt)}}if(vt)return mt=mt(o),vt=Q===""?"."+Bt(o,0):Q,Ht(mt)?(Y="",vt!=null&&(Y=vt.replace(Lt,"$&/")+"/"),k(mt,T,Y,"",function(A){return A})):mt!=null&&(Ct(mt)&&(mt=Nt(mt,Y+(mt.key==null||o&&o.key===mt.key?"":(""+mt.key).replace(Lt,"$&/")+"/")+vt)),T.push(mt)),1;vt=0;var y=Q===""?".":Q+":";if(Ht(o))for(var O=0;O>>1,B=H[pt];if(0>>1;ptM(wt,I))oM(T,wt)?(H[pt]=T,H[o]=I,pt=o):(H[pt]=wt,H[it]=I,pt=it);else if(oM(T,I))H[pt]=T,H[o]=I,pt=o;else break t}}return k}function M(H,k){var I=H.sortIndex-k.sortIndex;return I!==0?I:H.id-k.id}if(r.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var w=performance;r.unstable_now=function(){return w.now()}}else{var j=Date,ut=j.now();r.unstable_now=function(){return j.now()-ut}}var W=[],V=[],q=1,S=null,Z=3,rt=!1,Xt=!1,et=!1,D=!1,dt=typeof setTimeout=="function"?setTimeout:null,tt=typeof clearTimeout=="function"?clearTimeout:null,Tt=typeof setImmediate<"u"?setImmediate:null;function Ft(H){for(var k=E(V);k!==null;){if(k.callback===null)d(V);else if(k.startTime<=H)d(V),k.sortIndex=k.expirationTime,N(W,k);else break;k=E(V)}}function Mt(H){if(et=!1,Ft(H),!Xt)if(E(W)!==null)Xt=!0,Ht||(Ht=!0,Ct());else{var k=E(V);k!==null&&Bt(Mt,k.startTime-H)}}var Ht=!1,F=-1,C=5,At=-1;function zt(){return D?!0:!(r.unstable_now()-AtH&&zt());){var pt=S.callback;if(typeof pt=="function"){S.callback=null,Z=S.priorityLevel;var B=pt(S.expirationTime<=H);if(H=r.unstable_now(),typeof B=="function"){S.callback=B,Ft(H),k=!0;break l}S===E(W)&&d(W),Ft(H)}else d(W);S=E(W)}if(S!==null)k=!0;else{var at=E(V);at!==null&&Bt(Mt,at.startTime-H),k=!1}}break t}finally{S=null,Z=I,rt=!1}k=void 0}}finally{k?Ct():Ht=!1}}}var Ct;if(typeof Tt=="function")Ct=function(){Tt(Nt)};else if(typeof MessageChannel<"u"){var Wt=new MessageChannel,Lt=Wt.port2;Wt.port1.onmessage=Nt,Ct=function(){Lt.postMessage(null)}}else Ct=function(){dt(Nt,0)};function Bt(H,k){F=dt(function(){H(r.unstable_now())},k)}r.unstable_IdlePriority=5,r.unstable_ImmediatePriority=1,r.unstable_LowPriority=4,r.unstable_NormalPriority=3,r.unstable_Profiling=null,r.unstable_UserBlockingPriority=2,r.unstable_cancelCallback=function(H){H.callback=null},r.unstable_forceFrameRate=function(H){0>H||125pt?(H.sortIndex=I,N(V,H),E(W)===null&&H===E(V)&&(et?(tt(F),F=-1):et=!0,Bt(Mt,I-pt))):(H.sortIndex=B,N(W,H),Xt||rt||(Xt=!0,Ht||(Ht=!0,Ct()))),H},r.unstable_shouldYield=zt,r.unstable_wrapCallback=function(H){var k=Z;return function(){var I=Z;Z=k;try{return H.apply(this,arguments)}finally{Z=I}}}})(Ds)),Ds}var ym;function jh(){return ym||(ym=1,Cs.exports=Ah()),Cs.exports}var Us={exports:{}},hl={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var hm;function Mh(){if(hm)return hl;hm=1;var r=qs();function N(q){var S="https://react.dev/errors/"+q;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(r)}catch(N){console.error(N)}}return r(),Us.exports=Mh(),Us.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var gm;function Dh(){if(gm)return mn;gm=1;var r=jh(),N=qs(),E=Ch();function d(t){var l="https://react.dev/errors/"+t;if(1U||(t.current=L[U],L[U]=null,U--)}function gt(t,l){U++,L[U]=t.current,t.current=l}var fl=J(null),le=J(null),Me=J(null),hn=J(null);function vn(t,l){switch(gt(Me,l),gt(le,t),gt(fl,null),l.nodeType){case 9:case 11:t=(t=l.documentElement)&&(t=t.namespaceURI)?b0(t):0;break;default:if(t=l.tagName,l=l.namespaceURI)l=b0(l),t=x0(l,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}P(fl),gt(fl,t)}function Aa(){P(fl),P(le),P(Me)}function Ji(t){var l=t.memoizedState;l!==null&&(hu._currentValue=l.memoizedState,gt(hn,t)),l=fl.current;var e=x0(l,t.type);l!==e&&(gt(le,t),gt(fl,e))}function gn(t){le.current===t&&(P(fl),P(le)),hn.current===t&&(P(hn),hu._currentValue=A)}var ki,Ys;function Ce(t){if(ki===void 0)try{throw Error()}catch(e){var l=e.stack.trim().match(/\n( *(at )?)/);ki=l&&l[1]||"",Ys=-1)":-1u||s[a]!==g[u]){var p=` +`+s[a].replace(" at new "," at ");return t.displayName&&p.includes("")&&(p=p.replace("",t.displayName)),p}while(1<=a&&0<=u);break}}}finally{$i=!1,Error.prepareStackTrace=e}return(e=t?t.displayName||t.name:"")?Ce(e):""}function Om(t,l){switch(t.tag){case 26:case 27:case 5:return Ce(t.type);case 16:return Ce("Lazy");case 13:return t.child!==l&&l!==null?Ce("Suspense Fallback"):Ce("Suspense");case 19:return Ce("SuspenseList");case 0:case 15:return Fi(t.type,!1);case 11:return Fi(t.type.render,!1);case 1:return Fi(t.type,!0);case 31:return Ce("Activity");case 30:return Ce("ViewTransition");default:return""}}function ws(t){try{var l="",e=null;do l+=Om(t,e),e=t,t=t.return;while(t);return l}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var Wi=Object.prototype.hasOwnProperty,Ii=r.unstable_scheduleCallback,Pi=r.unstable_cancelCallback,Am=r.unstable_shouldYield,jm=r.unstable_requestPaint,Al=r.unstable_now,Mm=r.unstable_getCurrentPriorityLevel,Gs=r.unstable_ImmediatePriority,Qs=r.unstable_UserBlockingPriority,bn=r.unstable_NormalPriority,Cm=r.unstable_LowPriority,Xs=r.unstable_IdlePriority,Dm=r.log,Um=r.unstable_setDisableYieldValue,bu=null,jl=null;function De(t){if(typeof Dm=="function"&&Um(t),jl&&typeof jl.setStrictMode=="function")try{jl.setStrictMode(bu,t)}catch{}}var Ml=Math.clz32?Math.clz32:qm,Rm=Math.log,Hm=Math.LN2;function qm(t){return t>>>=0,t===0?32:31-(Rm(t)/Hm|0)|0}var xn=256,pn=262144,Sn=4194304;function na(t){var l=t&42;if(l!==0)return l;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&-t;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function Tn(t,l,e){var a=t.pendingLanes;if(a===0)return 0;var u=0,n=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var c=a&134217727;return c!==0?(a=c&~n,a!==0?u=na(a):(i&=c,i!==0?u=na(i):e||(e=c&~t,e!==0&&(u=na(e))))):(c=a&~n,c!==0?u=na(c):i!==0?u=na(i):e||(e=a&~t,e!==0&&(u=na(e)))),u===0?0:l!==0&&l!==u&&(l&n)===0&&(n=u&-u,e=l&-l,n>=e||n===32&&(e&4194048)!==0)?l:u}function xu(t,l){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&l)===0}function Vs(t,l){(l&8)!==0&&(l|=l&32);var e=t.entangledLanes;if(e!==0)for(t=t.entanglements,e&=l;0e;e++)l.push(t);return l}function pu(t,l){t.pendingLanes|=l,l!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function Ym(t,l,e,a,u,n){var i=t.pendingLanes;t.pendingLanes=e,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=e,t.entangledLanes&=e,t.errorRecoveryDisabledLanes&=e,t.shellSuspendCounter=0;var c=t.entanglements,s=t.expirationTimes,g=t.hiddenUpdates;for(e=i&~e;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),rc=!1;if(ve)try{var Eu={};Object.defineProperty(Eu,"passive",{get:function(){rc=!0}}),window.addEventListener("test",Eu,Eu),window.removeEventListener("test",Eu,Eu)}catch{rc=!1}var Ue=null,oc=null,An=null;function mr(){if(An)return An;var t,l=oc,e=l.length,a,u="value"in Ue?Ue.value:Ue.textContent,n=u.length;for(t=0;t=Ou),xr=" ",pr=!1;function Sr(t,l){switch(t){case"keyup":return p1.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Tr(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Ba=!1;function T1(t,l){switch(t){case"compositionend":return Tr(l);case"keypress":return l.which!==32?null:(pr=!0,xr);case"textInput":return t=l.data,t===xr&&pr?null:t;default:return null}}function N1(t,l){if(Ba)return t==="compositionend"||!vc&&Sr(t,l)?(t=mr(),An=oc=Ue=null,Ba=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1"u")return null;try{return t.activeElement||t.body}catch{return t.body}}function Mr(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function Cr(t,l){var e=Mr(t);t=0;for(var a;e;){if(e.nodeType===3){if(a=t+e.textContent.length,t<=l&&a>=l)return{node:e,offset:l-t};t=a}t:{for(;e;){if(e.nextSibling){e=e.nextSibling;break t}e=e.parentNode}e=void 0}e=Mr(e)}}function Dr(t,l){return t&&l?t===l?!0:t&&t.nodeType===3?!1:l&&l.nodeType===3?Dr(t,l.parentNode):"contains"in t?t.contains(l):t.compareDocumentPosition?!!(t.compareDocumentPosition(l)&16):!1:!1}function Ur(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var l=xc(t.document);l instanceof t.HTMLIFrameElement;){try{var e=typeof l.contentWindow.location.href=="string"}catch{e=!1}if(e)t=l.contentWindow;else break;l=xc(t.document)}return l}function pc(t){var l=t&&t.nodeName&&t.nodeName.toLowerCase();return l&&(l==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||l==="textarea"||t.contentEditable==="true")}var C1=ve&&"documentMode"in document&&11>=document.documentMode,Ya=null,Sc=null,Cu=null,Tc=!1;function Rr(t,l,e){var a=e.window===e?e.document:e.nodeType===9?e:e.ownerDocument;Tc||Ya==null||Ya!==xc(a)||(a=Ya,"selectionStart"in a&&pc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Cu&&Mu(Cu,a)||(Cu=a,a=Ui(Sc,"onSelect"),0>=i,u-=i,ae=1<<32-Ml(l)+u|e<lt?(el=$,$=null):el=$.sibling;var St=h(v,$,b[lt],z);if(St===null){$===null&&($=el);break}t&&$&&St.alternate===null&&l(v,$),m=n(St,m,lt),xt===null?X=St:xt.sibling=St,xt=St,$=el}if(lt===b.length)return e(v,$),ot&&pe(v,lt),X;if($===null){for(;ltlt?(el=$,$=null):el=$.sibling;var ua=h(v,$,St.value,z);if(ua===null){$===null&&($=el);break}t&&$&&ua.alternate===null&&l(v,$),m=n(ua,m,lt),xt===null?X=ua:xt.sibling=ua,xt=ua,$=el}if(St.done)return e(v,$),ot&&pe(v,lt),X;if($===null){for(;!St.done;lt++,St=b.next())St=_(v,St.value,z),St!==null&&(m=n(St,m,lt),xt===null?X=St:xt.sibling=St,xt=St);return ot&&pe(v,lt),X}for($=a($);!St.done;lt++,St=b.next())St=x($,v,lt,St.value,z),St!==null&&(t&&(el=St.alternate,el!==null&&$.delete(el.key===null?lt:el.key)),m=n(St,m,lt),xt===null?X=St:xt.sibling=St,xt=St);return t&&$.forEach(function(Th){return l(v,Th)}),ot&&pe(v,lt),X}function ft(v,m,b,z){if(typeof b=="object"&&b!==null&&b.type===Nt&&b.key===null&&b.props.ref===void 0&&(b=b.props.children),typeof b=="object"&&b!==null){switch(b.$$typeof){case At:t:{for(var X=b.key;m!==null;){if(m.key===X){if(X=b.type,X===Nt){if(m.tag===7){e(v,m.sibling),z=u(m,b.props.children),we(z,b),z.return=v,v=z;break t}}else if(m.elementType===X||typeof X=="object"&&X!==null&&X.$$typeof===B&&ba(X)===m.type){e(v,m.sibling),z=u(m,b.props),we(z,b),z.return=v,v=z;break t}e(v,m);break}else l(v,m);m=m.sibling}b.type===Nt?(z=oa(b.props.children,v.mode,z,b.key),we(z,b),z.return=v,v=z):(z=Yn(b.type,b.key,b.props,null,v.mode,z),we(z,b),z.return=v,v=z)}return i(v);case zt:t:{for(X=b.key;m!==null;){if(m.key===X)if(m.tag===4&&m.stateNode.containerInfo===b.containerInfo&&m.stateNode.implementation===b.implementation){e(v,m.sibling),z=u(m,b.children||[]),z.return=v,v=z;break t}else{e(v,m);break}else l(v,m);m=m.sibling}z=jc(b,v.mode,z),z.return=v,v=z}return i(v);case B:return b=ba(b),ft(v,m,b,z)}if(vt(b))return R(v,m,b,z);if(Q(b)){if(X=Q(b),typeof X!="function")throw Error(d(150));return b=X.call(b),K(v,m,b,z)}if(typeof b.then=="function")return ft(v,m,kn(b),z);if(b.$$typeof===Bt)return ft(v,m,Zn(v,b),z);$n(v,b)}return typeof b=="string"&&b!==""||typeof b=="number"||typeof b=="bigint"?(b=""+b,m!==null&&m.tag===6?(e(v,m.sibling),z=u(m,b),z.return=v,v=z):(e(v,m),z=Ac(b,v.mode,z),z.return=v,v=z),i(v)):e(v,m)}return function(v,m,b,z){try{Bu=0;var X=ft(v,m,b,z);return Ja=null,X}catch($){if($===Ka||$===Kn)throw $;var xt=Nl(29,$,null,v.mode);return xt.lanes=z,xt.return=v,xt}finally{}}}var pa=uo(!0),no=uo(!1),Ge=!1;function wc(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Gc(t,l){t=t.updateQueue,l.updateQueue===t&&(l.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Qe(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Xe(t,l,e){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(_t&2)!==0){var u=a.pending;return u===null?l.next=l:(l.next=u.next,u.next=l),a.pending=l,l=Bn(t),Xr(t,null,e),l}return qn(t,a,l,e),Bn(t)}function Yu(t,l,e){if(l=l.updateQueue,l!==null&&(l=l.shared,(e&4194048)!==0)){var a=l.lanes;a&=t.pendingLanes,e|=a,l.lanes=e,Ks(t,e)}}function Qc(t,l){var e=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,e===a)){var u=null,n=null;if(e=e.firstBaseUpdate,e!==null){do{var i={lane:e.lane,tag:e.tag,payload:e.payload,callback:null,next:null};n===null?u=n=i:n=n.next=i,e=e.next}while(e!==null);n===null?u=n=l:n=n.next=l}else u=n=l;e={baseState:a.baseState,firstBaseUpdate:u,lastBaseUpdate:n,shared:a.shared,callbacks:a.callbacks},t.updateQueue=e;return}t=e.lastBaseUpdate,t===null?e.firstBaseUpdate=l:t.next=l,e.lastBaseUpdate=l}var Xc=!1;function wu(){if(Xc){var t=La;if(t!==null)throw t}}function Gu(t,l,e,a){Xc=!1;var u=t.updateQueue;Ge=!1;var n=u.firstBaseUpdate,i=u.lastBaseUpdate,c=u.shared.pending;if(c!==null){u.shared.pending=null;var s=c,g=s.next;s.next=null,i===null?n=g:i.next=g,i=s;var p=t.alternate;p!==null&&(p=p.updateQueue,c=p.lastBaseUpdate,c!==i&&(c===null?p.firstBaseUpdate=g:c.next=g,p.lastBaseUpdate=s))}if(n!==null){var _=u.baseState;i=0,p=g=s=null,c=n;do{var h=c.lane&-536870913,x=h!==c.lane;if(x?(bt&h)===h:(a&h)===h){h!==0&&h===va&&(Xc=!0),p!==null&&(p=p.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});t:{var R=t,K=c;h=l;var ft=e;switch(K.tag){case 1:if(R=K.payload,typeof R=="function"){_=R.call(ft,_,h);break t}_=R;break t;case 3:R.flags=R.flags&-65537|128;case 0:if(R=K.payload,h=typeof R=="function"?R.call(ft,_,h):R,h==null)break t;_=F({},_,h);break t;case 2:Ge=!0}}h=c.callback,h!==null&&(t.flags|=64,x&&(t.flags|=8192),x=u.callbacks,x===null?u.callbacks=[h]:x.push(h))}else x={lane:h,tag:c.tag,payload:c.payload,callback:c.callback,next:null},p===null?(g=p=x,s=_):p=p.next=x,i|=h;if(c=c.next,c===null){if(c=u.shared.pending,c===null)break;x=c,c=x.next,x.next=null,u.lastBaseUpdate=x,u.shared.pending=null}}while(!0);p===null&&(s=_),u.baseState=s,u.firstBaseUpdate=g,u.lastBaseUpdate=p,n===null&&(u.shared.lanes=0),$e|=i,t.lanes=i,t.memoizedState=_}}function io(t,l){if(typeof t!="function")throw Error(d(191,t));t.call(l)}function co(t,l){var e=t.callbacks;if(e!==null)for(t.callbacks=null,t=0;tn?n:8;var i=y.T,c={};c.types=i!==null?i.types:null,y.T=c,sf(t,!1,l,e);try{var s=u(),g=y.S;if(g!==null&&g(c,s),s!==null&&typeof s=="object"&&typeof s.then=="function"){var p=X1(s,a);Zu(t,l,p,Bl(t))}else Zu(t,l,a,Bl(t))}catch(_){Zu(t,l,{then:function(){},status:"rejected",reason:_},Bl())}finally{O.p=n,i!==null&&c.types!==null&&(i.types=c.types),y.T=i}}function k1(){}function cf(t,l,e,a){if(t.tag!==5)throw Error(d(476));var u=Go(t).queue;wo(t,u,l,A,e===null?k1:function(){return Qo(t),e(a)})}function Go(t){var l=t.memoizedState;if(l!==null)return l;l={memoizedState:A,baseState:A,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ee,lastRenderedState:A},next:null};var e={};return l.next={memoizedState:e,baseState:e,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ee,lastRenderedState:e},next:null},t.memoizedState=l,t=t.alternate,t!==null&&(t.memoizedState=l),l}function Qo(t){var l=Go(t);l.next===null&&(l=t.alternate.memoizedState),Zu(t,l.next.queue,{},Bl())}function ff(){return rl(hu)}function Xo(){return It().memoizedState}function Vo(){return It().memoizedState}function $1(t){for(var l=t.return;l!==null;){switch(l.tag){case 24:case 3:var e=Bl();t=Qe(e);var a=Xe(l,t,e);a!==null&&(Ol(a,l,e),Yu(a,l,e)),l={cache:Hc()},t.payload=l;return}l=l.return}}function F1(t,l,e){var a=Bl();e={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null},ni(t)?Lo(l,e):(e=_c(t,l,e,a),e!==null&&(Ol(e,t,a),Ko(e,l,a)))}function Zo(t,l,e){var a=Bl();Zu(t,l,e,a)}function Zu(t,l,e,a){var u={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null};if(ni(t))Lo(l,u);else{var n=t.alternate;if(t.lanes===0&&(n===null||n.lanes===0)&&(n=l.lastRenderedReducer,n!==null))try{var i=l.lastRenderedState,c=n(i,e);if(u.hasEagerState=!0,u.eagerState=c,Dl(c,i))return qn(t,l,u,0),Yt===null&&Hn(),!1}catch{}finally{}if(e=_c(t,l,u,a),e!==null)return Ol(e,t,a),Ko(e,l,a),!0}return!1}function sf(t,l,e,a){if(a={lane:2,revertLane:Pf(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},ni(t)){if(l)throw Error(d(479))}else l=_c(t,e,a,2),l!==null&&Ol(l,t,2)}function ni(t){var l=t.alternate;return t===ct||l!==null&&l===ct}function Lo(t,l){ka=In=!0;var e=t.pending;e===null?l.next=l:(l.next=e.next,e.next=l),t.pending=l}function Ko(t,l,e){if((e&4194048)!==0){var a=l.lanes;a&=t.pendingLanes,e|=a,l.lanes=e,Ks(t,e)}}var ii={readContext:rl,use:li,useCallback:kt,useContext:kt,useEffect:kt,useImperativeHandle:kt,useLayoutEffect:kt,useInsertionEffect:kt,useMemo:kt,useReducer:kt,useRef:kt,useState:kt,useDebugValue:kt,useDeferredValue:kt,useTransition:kt,useSyncExternalStore:kt,useId:kt,useHostTransitionStatus:kt,useFormState:kt,useActionState:kt,useOptimistic:kt,useMemoCache:kt,useCacheRefresh:kt,useEffectEvent:kt},Jo={readContext:rl,use:li,useCallback:function(t,l){return xl().memoizedState=[t,l===void 0?null:l],t},useContext:rl,useEffect:Mo,useImperativeHandle:function(t,l,e){e=e!=null?e.concat([t]):null,ai(4194308,4,Ro.bind(null,l,t),e)},useLayoutEffect:function(t,l){return ai(4194308,4,t,l)},useInsertionEffect:function(t,l){ai(4,2,t,l)},useMemo:function(t,l){var e=xl();l=l===void 0?null:l;var a=t();if(Sa){De(!0);try{t()}finally{De(!1)}}return e.memoizedState=[a,l],a},useReducer:function(t,l,e){var a=xl();if(e!==void 0){var u=e(l);if(Sa){De(!0);try{e(l)}finally{De(!1)}}}else u=l;return a.memoizedState=a.baseState=u,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:u},a.queue=t,t=t.dispatch=F1.bind(null,ct,t),[a.memoizedState,t]},useRef:function(t){var l=xl();return t={current:t},l.memoizedState=t},useState:function(t){t=lf(t);var l=t.queue,e=Zo.bind(null,ct,l);return l.dispatch=e,[t.memoizedState,e]},useDebugValue:uf,useDeferredValue:function(t,l){var e=xl();return nf(e,t,l)},useTransition:function(){var t=lf(!1);return t=wo.bind(null,ct,t.queue,!0,!1),xl().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,l,e){var a=ct,u=xl();if(ot){if(e===void 0)throw Error(d(407));e=e()}else{if(e=l(),Yt===null)throw Error(d(349));(bt&127)!==0||yo(a,l,e)}u.memoizedState=e;var n={value:e,getSnapshot:l};return u.queue=n,Mo(vo.bind(null,a,n,t),[t]),a.flags|=2048,Fa(9,{destroy:void 0},ho.bind(null,a,n,e,l),null),e},useId:function(){var t=xl(),l=Yt.identifierPrefix;if(ot){var e=ue,a=ae;e=(a&~(1<<32-Ml(a)-1)).toString(32)+e,l="_"+l+"R_"+e,e=Pn++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?n.multiple=!0:a.size&&(n.size=a.size);break;default:n=typeof a.is=="string"?i.createElement(u,{is:a.is}):i.createElement(u)}}n[sl]=l,n[Tl]=a;t:for(i=l.child;i!==null;){if(i.tag===5||i.tag===6)n.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===l)break t;for(;i.sibling===null;){if(i.return===null||i.return===l)break t;i=i.return}i.sibling.return=i.return,i=i.sibling}l.stateNode=n;t:switch(yl(n,u,a),u){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&_e(l)}}return Qt(l),l.subtreeFlags&=-33554433,Tf(l,l.type,t===null?null:t.memoizedProps,l.pendingProps,e),null;case 6:if(t&&l.stateNode!=null)t.memoizedProps!==a&&_e(l);else{if(typeof a!="string"&&l.stateNode===null)throw Error(d(166));if(t=Me.current,Za(l)){if(t=l.stateNode,e=l.memoizedProps,a=null,u=nl,u!==null)switch(u.tag){case 27:case 5:a=u.memoizedProps}t[sl]=l,t=!!(t.nodeValue===e||a!==null&&a.suppressHydrationWarning===!0||v0(t.nodeValue,e)),t||Be(l,!0)}else t=an(t).createTextNode(a),t[sl]=l,l.stateNode=t}return Qt(l),null;case 31:if(e=l.memoizedState,t===null||t.memoizedState!==null){if(a=Za(l),e!==null){if(t===null){if(!a)throw Error(d(318));if(t=l.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(d(557));t[sl]=l}else da(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Qt(l),t=!1}else e=Dc(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=e),t=!0;if(!t)return l.flags&256?(Ul(l),l):(Ul(l),null);if((l.flags&128)!==0)throw Error(d(558))}return Qt(l),null;case 13:if(a=l.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(u=Za(l),a!==null&&a.dehydrated!==null){if(t===null){if(!u)throw Error(d(318));if(u=l.memoizedState,u=u!==null?u.dehydrated:null,!u)throw Error(d(317));u[sl]=l}else da(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Qt(l),u=!1}else u=Dc(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=u),u=!0;if(!u)return l.flags&256?(Ul(l),l):(Ul(l),null)}return Ul(l),(l.flags&128)!==0?(l.lanes=e,l):(e=a!==null,t=t!==null&&t.memoizedState!==null,e&&(a=l.child,u=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(u=a.alternate.memoizedState.cachePool.pool),n=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(n=a.memoizedState.cachePool.pool),n!==u&&(a.flags|=2048)),e!==t&&e&&(l.child.flags|=8192),di(l,l.updateQueue),Qt(l),null);case 4:return Aa(),t===null&&as(l.stateNode.containerInfo),l.flags|=67108864,Qt(l),null;case 10:return Te(l.type),Qt(l),null;case 19:if(Kc(l),a=l.memoizedState,a===null)return Qt(l),null;if(u=(l.flags&128)!==0,n=a.rendering,n===null)if(u)Ku(a,!1);else{if($t!==0||t!==null&&(t.flags&128)!==0)for(t=l.child;t!==null;){if(n=Wn(t),n!==null){for(l.flags|=128,Ku(a,!1),t=n.updateQueue,l.updateQueue=t,di(l,t),l.subtreeFlags=0,t=e,e=l.child;e!==null;)Vr(e,t),e=e.sibling;return Qu(l,dl.current&1|2),ot&&pe(l,a.treeForkCount),l.child}t=t.sibling}a.tail!==null&&Al()>Ei&&(l.flags|=128,u=!0,Ku(a,!1),l.lanes=4194304)}else{if(!u)if(t=Wn(n),t!==null){if(l.flags|=128,u=!0,t=t.updateQueue,l.updateQueue=t,di(l,t),Ku(a,!0),a.tail===null&&a.tailMode!=="collapsed"&&a.tailMode!=="visible"&&!n.alternate&&!ot)return Qt(l),null}else 2*Al()-a.renderingStartTime>Ei&&e!==536870912&&(l.flags|=128,u=!0,Ku(a,!1),l.lanes=4194304);a.isBackwards?(n.sibling=l.child,l.child=n):(t=a.last,t!==null?t.sibling=n:l.child=n,a.last=n)}if(a.tail!==null){t=a.tail;t:{for(e=t;e!==null;){if(e.alternate!==null){e=!1;break t}e=e.sibling}e=!0}return a.rendering=t,a.tail=t.sibling,a.renderingStartTime=Al(),t.sibling=null,n=dl.current,n=u?n&1|2:n&1,a.tailMode==="visible"||a.tailMode==="collapsed"||!e||ot?Qu(l,n):(e=n,gt(ol,l),gt(dl,e),vl===null&&(vl=l)),ot&&pe(l,a.treeForkCount),t}return Qt(l),null;case 22:case 23:return Ul(l),Zc(),a=l.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(l.flags|=8192):a&&(l.flags|=8192),a?(e&536870912)!==0&&(l.flags&128)===0&&(Qt(l),l.subtreeFlags&6&&(l.flags|=8192)):Qt(l),e=l.updateQueue,e!==null&&di(l,e.retryQueue),e=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(e=t.memoizedState.cachePool.pool),a=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(a=l.memoizedState.cachePool.pool),a!==e&&(l.flags|=2048),t!==null&&P(ga),null;case 24:return e=null,t!==null&&(e=t.memoizedState.cache),l.memoizedState.cache!==e&&(l.flags|=2048),Te(Pt),Qt(l),null;case 25:return null;case 30:return l.flags|=33554432,Qt(l),null}throw Error(d(156,l.tag))}function ay(t,l){switch(Mc(l),l.tag){case 1:return t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 3:return Te(Pt),Aa(),t=l.flags,(t&65536)!==0&&(t&128)===0?(l.flags=t&-65537|128,l):null;case 26:case 27:case 5:return gn(l),null;case 31:if(l.memoizedState!==null){if(Ul(l),l.alternate===null)throw Error(d(340));da()}return t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 13:if(Ul(l),t=l.memoizedState,t!==null&&t.dehydrated!==null){if(l.alternate===null)throw Error(d(340));da()}return t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 19:return Kc(l),t=l.flags,t&65536?(l.flags=t&-65537|128,t=l.memoizedState,t!==null&&(t.rendering=null,t.tail=null),l.flags|=4,l):null;case 4:return Aa(),null;case 10:return Te(l.type),null;case 22:case 23:return Ul(l),Zc(),t!==null&&P(ga),t=l.flags,t&65536?(l.flags=t&-65537|128,l):null;case 24:return Te(Pt),null;case 25:return null;default:return null}}function bd(t,l){switch(Mc(l),l.tag){case 3:Te(Pt),Aa();break;case 26:case 27:case 5:gn(l);break;case 4:Aa();break;case 31:l.memoizedState!==null&&Ul(l);break;case 13:Ul(l);break;case 19:Kc(l);break;case 10:Te(l.type);break;case 22:case 23:Ul(l),Zc(),t!==null&&P(ga);break;case 24:Te(Pt)}}function Ju(t,l){try{var e=l.updateQueue,a=e!==null?e.lastEffect:null;if(a!==null){var u=a.next;e=u;do{if((e.tag&t)===t){a=void 0;var n=e.create,i=e.inst;a=n(),i.destroy=a}e=e.next}while(e!==u)}}catch(c){Ut(l,l.return,c)}}function Ke(t,l,e){try{var a=l.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var n=u.next;a=n;do{if((a.tag&t)===t){var i=a.inst,c=i.destroy;if(c!==void 0){i.destroy=void 0,u=l;var s=e,g=c;try{g()}catch(p){Ut(u,s,p)}}}a=a.next}while(a!==n)}}catch(p){Ut(l,l.return,p)}}function xd(t){var l=t.updateQueue;if(l!==null){var e=t.stateNode;try{co(l,e)}catch(a){Ut(t,t.return,a)}}}function pd(t,l,e){e.props=Ta(t.type,t.memoizedProps),e.state=t.memoizedState;try{e.componentWillUnmount()}catch(a){Ut(t,l,a)}}function ne(t,l){try{var e=t.ref;if(e!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:var u=t.stateNode,n=ge(t.memoizedProps,u);(u.ref===null||u.ref.name!==n)&&(u.ref=O0(n)),a=u.ref;break;case 7:if(t.stateNode===null){var i=new Yl(t);S(t.child,!1,Jy,i,void 0,void 0),t.stateNode=i}a=t.stateNode;break;default:a=t.stateNode}typeof e=="function"?t.refCleanup=e(a):e.current=a}}catch(c){Ut(t,l,c)}}function ml(t,l){var e=t.ref,a=t.refCleanup;if(e!==null)if(typeof a=="function")try{a()}catch(u){Ut(t,l,u)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof e=="function")try{e(null)}catch(u){Ut(t,l,u)}else e.current=null}function mi(t,l){if((t.tag===5||t.tag===27||t.tag===6)&&t.alternate===null&&l!==null)for(var e=0;e title"))),yl(a,l,e),a[sl]=t,ul(a),l=a;break t;case"link":if(n=Z0("link","href",u).get(l+(e.href||""))){for(i=0;ift&&(i=ft,ft=K,K=i);var v=Cr(c,K),m=Cr(c,ft);if(v&&m&&(x.rangeCount!==1||x.anchorNode!==v.node||x.anchorOffset!==v.offset||x.focusNode!==m.node||x.focusOffset!==m.offset)){var b=_.createRange();b.setStart(v.node,v.offset),x.removeAllRanges(),K>ft?(x.addRange(b),x.extend(m.node,m.offset)):(b.setEnd(m.node,m.offset),x.addRange(b))}}}}for(_=[],x=c;x=x.parentNode;)x.nodeType===1&&_.push({element:x,left:x.scrollLeft,top:x.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;c<_.length;c++){var z=_[c];z.element.scrollLeft=z.left,z.element.scrollTop=z.top}}vu=!!is,cs=is=null}finally{_t=n,O.p=u,y.T=a}}t.current=l,Kt=2}}function Jf(){if(Kt===2){Kt=0;var t=Pl,l=_a,e=(l.flags&8772)!==0;if((l.subtreeFlags&8772)!==0||e){e=y.T,y.T=null;var a=O.p;O.p=2;var u=_t;_t|=4;try{Cd(t,l.alternate,l)}finally{_t=u,O.p=a,y.T=e}}Kt=3}}function kf(){if(Kt===4||Kt===3){Kt=0;var t=au;au=null,jm();var l=Pl,e=_a,a=oe,u=Kd,n=(a&335544064)===a?10262:10256;if((e.subtreeFlags&n)!==0||(e.flags&n)!==0?Kt=5:(Kt=0,_a=Pl=null,u0(l,l.pendingLanes)),n=l.pendingLanes,n===0&&(Fe=null),ec(a),e=e.stateNode,jl&&typeof jl.onCommitFiberRoot=="function")try{jl.onCommitFiberRoot(bu,e,void 0,(e.current.flags&128)===128)}catch{}if(u!==null){e=y.T,n=O.p,O.p=2,y.T=null;try{for(var i=l.onRecoverableError,c=0;ce?32:e,y.T=null,e=Vf,Vf=null;var n=Pl,i=oe;if(Kt=0,_a=Pl=null,oe=0,(_t&6)!==0)throw Error(d(331));var c=_t;if(_t|=4,Vd(n.current),Gd(n,n.current,i,e),_t=c,tn(0,!1),jl&&typeof jl.onPostCommitFiberRoot=="function")try{jl.onPostCommitFiberRoot(bu,n)}catch{}return!0}finally{O.p=u,y.T=a,u0(t,l)}}function n0(t,l,e){l=Ql(e,l),l=df(t.stateNode,l,2),t=Xe(t,l,2),t!==null&&(pu(t,2),de(t))}function Ut(t,l,e){if(t.tag===3)n0(t,t,e);else for(;l!==null;){if(l.tag===3){n0(l,t,e);break}else if(l.tag===1){var a=l.stateNode;if(typeof l.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Fe===null||!Fe.has(a))){t=Ql(e,t),e=ld(2),a=Xe(l,e,2),a!==null&&(ed(e,a,l,t),pu(a,2),de(a));break}}l=l.return}}function Ff(t,l,e){var a=t.pingCache;if(a===null){a=t.pingCache=new cy;var u=new Set;a.set(l,u)}else u=a.get(l),u===void 0&&(u=new Set,a.set(l,u));u.has(e)||(Gf=!0,u.add(e),t=hy.bind(null,t,l,e),l.then(t,t))}function hy(t,l,e){var a=t.pingCache;a!==null&&a.delete(l),t.pingedLanes|=t.suspendedLanes&e,t.warmLanes&=~e,Yt===t&&(bt&e)===e&&(($t===4||$t===3&&(bt&62914560)===bt&&300>Al()-Ni)&&(_t&2)===0?cu(t,0):Ti|=e,eu===bt&&(eu=0)),de(t)}function i0(t,l){l===0&&(l=Zs()),t=ra(t,l),t!==null&&(pu(t,l),de(t))}function vy(t){var l=t.memoizedState,e=0;l!==null&&(e=l.retryLane),i0(t,e)}function gy(t,l){var e=0;switch(t.tag){case 31:case 13:var a=t.stateNode,u=t.memoizedState;u!==null&&(e=u.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(d(314))}a!==null&&a.delete(l),i0(t,e)}function by(t,l){return Ii(t,l)}var su=null,ru=null,Wf=!1,Ci=!1,If=!1,Ie=0;function de(t){t!==ru&&t.next===null&&(ru===null?su=ru=t:ru=ru.next=t),Ci=!0,Wf||(Wf=!0,py())}function tn(t,l){if(!If&&Ci){If=!0;do for(var e=!1,a=su;a!==null;){if(t!==0){var u=a.pendingLanes;if(u===0)var n=0;else{var i=a.suspendedLanes,c=a.pingedLanes;n=(1<<31-Ml(42|t)+1)-1,n&=u&~(i&~c),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(e=!0,r0(a,n))}else n=bt,n=Tn(a,a===Yt?n:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(n&3)===0||xu(a,n)||(e=!0,r0(a,n));a=a.next}while(e);If=!1}}function xy(){c0()}function c0(){Ci=Wf=!1;var t=0;Ie!==0&&Cy()&&(t=Ie);for(var l=Al(),e=null,a=su;a!==null;){var u=a.next,n=f0(a,l);n===0?(a.next=null,e===null?su=u:e.next=u,u===null&&(ru=e)):(e=a,(t!==0||(n&3)!==0)&&(Ci=!0)),a=u}Kt!==0&&Kt!==5||tn(t),Ie!==0&&(Ie=0)}function f0(t,l){for(var e=t.suspendedLanes,a=t.pingedLanes,u=t.expirationTimes,n=t.pendingLanes&-62914561;0c)break;var p=s.transferSize,_=s.initiatorType;p&&g0(_)&&(s=s.responseEnd,i+=p*(sqi){K.length=R;break}b=new Promise(By.bind(b)),K.push(b)}}}if(0"u"?null:document;function G0(t,l,e){var a=du;if(a&&typeof l=="string"&&l){var u=wl(l);u='link[rel="'+t+'"][href="'+u+'"]',typeof e=="string"&&(u+='[crossorigin="'+e+'"]'),w0.has(u)||(w0.add(u),t={rel:t,crossOrigin:e,href:l},a.querySelector(u)===null&&(l=a.createElement("link"),yl(l,"link",t),ul(l),a.head.appendChild(l)))}}function eh(t){Ae.D(t),G0("dns-prefetch",t,null)}function ah(t,l){Ae.C(t,l),G0("preconnect",t,l)}function uh(t,l,e){Ae.L(t,l,e);var a=du;if(a&&t&&l){var u='link[rel="preload"][as="'+wl(l)+'"]';l==="image"&&e&&e.imageSrcSet?(u+='[imagesrcset="'+wl(e.imageSrcSet)+'"]',typeof e.imageSizes=="string"&&(u+='[imagesizes="'+wl(e.imageSizes)+'"]')):u+='[href="'+wl(t)+'"]';var n=u;switch(l){case"style":n=mu(t);break;case"script":n=yu(t)}if(!(Jl.has(n)||(t=F({rel:"preload",href:l==="image"&&e&&e.imageSrcSet?void 0:t,as:l},e),Jl.set(n,t),a.querySelector(u)!==null||l==="style"&&a.querySelector(nn(n))||l==="script"&&a.querySelector(cn(n))))){var i=a.createElement("link");yl(i,"link",t),l==="style"&&(i[Nn]=!0,i.onload=i.onerror=function(){Is(i)}),ul(i),a.head.appendChild(i)}}}function nh(t,l){Ae.m(t,l);var e=du;if(e&&t){var a=l&&typeof l.as=="string"?l.as:"script",u='link[rel="modulepreload"][as="'+wl(a)+'"][href="'+wl(t)+'"]',n=u;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=yu(t)}if(!Jl.has(n)&&(t=F({rel:"modulepreload",href:t},l),Jl.set(n,t),e.querySelector(u)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(e.querySelector(cn(n)))return}a=e.createElement("link"),yl(a,"link",t),ul(a),e.head.appendChild(a)}}}function ih(t,l,e){Ae.S(t,l,e);var a=du;if(a&&t){var u=Ca(a).hoistableStyles,n=mu(t);l=l||"default";var i=u.get(n);if(!i){var c={loading:0,preload:null};if(i=a.querySelector(nn(n)))c.loading=5;else{t=F({rel:"stylesheet",href:t,"data-precedence":l},e),(e=Jl.get(n))&&xs(t,e);var s=i=a.createElement("link");ul(s),yl(s,"link",t),s._p=new Promise(function(g,p){s.onload=g,s.onerror=p}),s.addEventListener("load",function(){c.loading|=1}),s.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Ri(i,l,a)}i={type:"stylesheet",instance:i,count:1,state:c},u.set(n,i)}}}function ch(t,l){Ae.X(t,l);var e=du;if(e&&t){var a=Ca(e).hoistableScripts,u=yu(t),n=a.get(u);n||(n=e.querySelector(cn(u)),n||(t=F({src:t,async:!0},l),(l=Jl.get(u))&&ps(t,l),n=e.createElement("script"),ul(n),yl(n,"link",t),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function fh(t,l){Ae.M(t,l);var e=du;if(e&&t){var a=Ca(e).hoistableScripts,u=yu(t),n=a.get(u);n||(n=e.querySelector(cn(u)),n||(t=F({src:t,async:!0,type:"module"},l),(l=Jl.get(u))&&ps(t,l),n=e.createElement("script"),ul(n),yl(n,"link",t),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Q0(t,l,e,a){var u=(u=Me.current)?un(u):null;if(!u)throw Error(d(446));switch(t){case"meta":case"title":return null;case"style":return typeof e.precedence=="string"&&typeof e.href=="string"?(e=mu(e.href),l=Ca(u).hoistableStyles,a=l.get(e),a||(a={type:"style",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(e.rel==="stylesheet"&&typeof e.href=="string"&&typeof e.precedence=="string"){t=mu(e.href);var n=Ca(u).hoistableStyles,i=n.get(t);if(i||(u=u.ownerDocument||u,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(t,i),(n=u.querySelector(nn(t)))?n._p||(i.instance=n,i.state.loading=5):(n=Jl.get(t),n||(n={rel:"preload",as:"style",href:e.href,crossOrigin:e.crossOrigin,integrity:e.integrity,media:e.media,hrefLang:e.hrefLang,referrerPolicy:e.referrerPolicy},Jl.set(t,n)),sh(u,t,n,i.state))),l&&a===null)throw Error(d(528,""));return i}if(l&&a!==null)throw Error(d(529,""));return null;case"script":return l=e.async,e=e.src,typeof e=="string"&&l&&typeof l!="function"&&typeof l!="symbol"?(e=yu(e),l=Ca(u).hoistableScripts,a=l.get(e),a||(a={type:"script",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(d(444,t))}}function mu(t){return'href="'+wl(t)+'"'}function nn(t){return'link[rel="stylesheet"]['+t+"]"}function X0(t){return F({},t,{"data-precedence":t.precedence,precedence:null})}function sh(t,l,e,a){if(l=t.querySelector('link[rel="preload"][as="style"]['+l+"]")){if(l[Nn]!==!0){a.loading=1;return}}else l=t.createElement("link"),l[Nn]=!0,l.onload=l.onerror=Is.bind(null,l),yl(l,"link",e),ul(l),t.head.appendChild(l);a.preload=l,l.addEventListener("load",function(){return a.loading|=1}),l.addEventListener("error",function(){return a.loading|=2})}function yu(t){return'[src="'+wl(t)+'"]'}function cn(t){return"script[async]"+t}function V0(t,l,e){if(l.count++,l.instance===null)switch(l.type){case"style":var a=t.querySelector('style[data-href~="'+wl(e.href)+'"]');if(a)return l.instance=a,ul(a),a;var u=F({},e,{"data-href":e.href,"data-precedence":e.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),ul(a),yl(a,"style",u),Ri(a,e.precedence,t),l.instance=a;case"stylesheet":u=mu(e.href);var n=t.querySelector(nn(u));if(n)return l.state.loading|=4,l.instance=n,ul(n),n;a=X0(e),(u=Jl.get(u))&&xs(a,u),n=(t.ownerDocument||t).createElement("link"),ul(n);var i=n;return i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),yl(n,"link",a),l.state.loading|=4,Ri(n,e.precedence,t),l.instance=n;case"script":return n=yu(e.src),(u=t.querySelector(cn(n)))?(l.instance=u,ul(u),u):(a=e,(u=Jl.get(n))&&(a=F({},e),ps(a,u)),t=t.ownerDocument||t,u=t.createElement("script"),ul(u),yl(u,"link",a),t.head.appendChild(u),l.instance=u);case"void":return null;default:throw Error(d(443,l.type))}else l.type==="stylesheet"&&(l.state.loading&4)===0&&(a=l.instance,l.state.loading|=4,Ri(a,e.precedence,t));return l.instance}function Ri(t,l,e){for(var a=e.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),u=a.length?a[a.length-1]:null,n=u,i=0;i title"):null)}function rh(t,l,e){if(e===1||l.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof l.precedence!="string"||typeof l.href!="string"||l.href==="")break;return!0;case"link":if(typeof l.rel!="string"||typeof l.href!="string"||l.href===""||l.onLoad||l.onError)break;switch(l.rel){case"stylesheet":return t=l.disabled,typeof l.precedence=="string"&&t==null;default:return!0}case"script":if(l.async&&typeof l.async!="function"&&typeof l.async!="symbol"&&!l.onLoad&&!l.onError&&l.src&&typeof l.src=="string")return!0}return!1}function L0(t,l){return t==="img"&&l.src!=null&&l.src!==""&&l.onLoad==null&&l.loading!=="lazy"}function K0(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function J0(t){return(t.width||100)*(t.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function k0(t,l){typeof l.decode=="function"&&(t.imgCount++,l.complete||(t.imgBytes+=J0(l),t.suspenseyImages.push(l)),t=mh.bind(t),l.decode().then(t,t))}function oh(t,l,e,a){if(e.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(e.state.loading&4)===0){if(e.instance===null){var u=mu(a.href),n=l.querySelector(nn(u));if(n){l=n._p,l!==null&&typeof l=="object"&&typeof l.then=="function"&&(t.count++,t=fn.bind(t),l.then(t,t)),e.state.loading|=4,e.instance=n,ul(n);return}n=l.ownerDocument||l,a=X0(a),(u=Jl.get(u))&&xs(a,u),n=n.createElement("link"),ul(n);var i=n;i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),yl(n,"link",a),e.instance=n}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(e,l),(l=e.state.preload)&&(e.state.loading&3)===0&&(t.count++,e=fn.bind(t),l.addEventListener("load",e),l.addEventListener("error",e))}}var qi=0;function dh(t,l){return t.stylesheets&&t.count===0&&Yi(t,t.stylesheets),0qi?50:800)+l);return t.unsuspend=e,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(u)}}:null}function $0(t){if(t.count===0&&(t.imgCount===0||!t.waitingForImages)){if(t.stylesheets)Yi(t,t.stylesheets);else if(t.unsuspend){var l=t.unsuspend;t.unsuspend=null,l()}}}function fn(){this.count--,$0(this)}function mh(){this.imgCount--,$0(this)}var Bi=null;function Yi(t,l){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Bi=new Map,l.forEach(yh,t),Bi=null,fn.call(t))}function yh(t,l){if(!(l.state.loading&4)){var e=Bi.get(t);if(e)var a=e.get(null);else{e=new Map,Bi.set(t,e);for(var u=t.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(r)}catch(N){console.error(N)}}return r(),Ms.exports=Dh(),Ms.exports}var Rh=Uh();/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Hh=r=>r.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),pm=(...r)=>r.filter((N,E,d)=>!!N&&N.trim()!==""&&d.indexOf(N)===E).join(" ").trim();/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */var qh={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Bh=G.forwardRef(({color:r="currentColor",size:N=24,strokeWidth:E=2,absoluteStrokeWidth:d,className:M="",children:w,iconNode:j,...ut},W)=>G.createElement("svg",{ref:W,...qh,width:N,height:N,stroke:r,strokeWidth:d?Number(E)*24/Number(N):E,className:pm("lucide",M),...ut},[...j.map(([V,q])=>G.createElement(V,q)),...Array.isArray(w)?w:[w]]));/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ot=(r,N)=>{const E=G.forwardRef(({className:d,...M},w)=>G.createElement(Bh,{ref:w,iconNode:N,className:pm(`lucide-${Hh(r)}`,d),...M}));return E.displayName=`${r}`,E};/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Yh=Ot("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const wh=Ot("Bot",[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Sm=Ot("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Gh=Ot("CircleAlert",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Qh=Ot("CircleCheck",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Xh=Ot("CircleStop",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["rect",{x:"9",y:"9",width:"6",height:"6",rx:"1",key:"1ssd4o"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Vh=Ot("ClipboardCheck",[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1",key:"tgr4d6"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2",key:"116196"}],["path",{d:"m9 14 2 2 4-4",key:"df797q"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Zh=Ot("Cpu",[["rect",{width:"16",height:"16",x:"4",y:"4",rx:"2",key:"14l7u7"}],["rect",{width:"6",height:"6",x:"9",y:"9",rx:"1",key:"5aljv4"}],["path",{d:"M15 2v2",key:"13l42r"}],["path",{d:"M15 20v2",key:"15mkzm"}],["path",{d:"M2 15h2",key:"1gxd5l"}],["path",{d:"M2 9h2",key:"1bbxkp"}],["path",{d:"M20 15h2",key:"19e6y8"}],["path",{d:"M20 9h2",key:"19tzq7"}],["path",{d:"M9 2v2",key:"165o2o"}],["path",{d:"M9 20v2",key:"i2bqo8"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Lh=Ot("Ellipsis",[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Kh=Ot("Gauge",[["path",{d:"m12 14 4-4",key:"9kzdfg"}],["path",{d:"M3.34 19a10 10 0 1 1 17.32 0",key:"19p75a"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Tm=Ot("GraduationCap",[["path",{d:"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z",key:"j76jl0"}],["path",{d:"M22 10v6",key:"1lu8f3"}],["path",{d:"M6 12.5V16a6 3 0 0 0 12 0v-3.5",key:"1r8lef"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Jh=Ot("Info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const kh=Ot("KeyRound",[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const $h=Ot("ListVideo",[["path",{d:"M12 12H3",key:"18klou"}],["path",{d:"M16 6H3",key:"1wxfjs"}],["path",{d:"M12 18H3",key:"11ftsu"}],["path",{d:"m16 12 5 3-5 3v-6Z",key:"zpskkp"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Fh=Ot("LoaderCircle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Wh=Ot("LogIn",[["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4",key:"u53s6r"}],["polyline",{points:"10 17 15 12 10 7",key:"1ail0h"}],["line",{x1:"15",x2:"3",y1:"12",y2:"12",key:"v6grx8"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ih=Ot("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Nm=Ot("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Bs=Ot("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ph=Ot("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const tv=Ot("ScrollText",[["path",{d:"M15 12h-5",key:"r7krc0"}],["path",{d:"M15 8h-5",key:"1khuty"}],["path",{d:"M19 17V5a2 2 0 0 0-2-2H4",key:"zz82l3"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3",key:"1ph1d7"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const lv=Ot("Send",[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",key:"1ffxy3"}],["path",{d:"m21.854 2.147-10.94 10.939",key:"12cjpa"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ev=Ot("ServerCog",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5",key:"tn8das"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5",key:"1g2pve"}],["path",{d:"M6 6h.01",key:"1utrut"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"m15.7 13.4-.9-.3",key:"1jwmzr"}],["path",{d:"m9.2 10.9-.9-.3",key:"qapnim"}],["path",{d:"m10.6 15.7.3-.9",key:"quwk0k"}],["path",{d:"m13.6 15.7-.4-1",key:"cb9xp7"}],["path",{d:"m10.8 9.3-.4-1",key:"1uaiz5"}],["path",{d:"m8.3 13.6 1-.4",key:"s6srou"}],["path",{d:"m14.7 10.8 1-.4",key:"4d31cq"}],["path",{d:"m13.4 8.3-.3.9",key:"1bm987"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const av=Ot("Settings2",[["path",{d:"M20 7h-9",key:"3s1dr2"}],["path",{d:"M14 17H5",key:"gfn3mx"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const uv=Ot("ShieldCheck",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const nv=Ot("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const iv=Ot("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Em=Ot("Users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75",key:"1da9ce"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const cv=Ot("Video",[["path",{d:"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5",key:"ftymec"}],["rect",{x:"2",y:"6",width:"14",height:"12",rx:"2",key:"158x01"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const fv=Ot("WifiOff",[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}],["path",{d:"M5 12.859a10 10 0 0 1 5.17-2.69",key:"1dl1wf"}],["path",{d:"M19 12.859a10 10 0 0 0-2.007-1.523",key:"4k23kn"}],["path",{d:"M2 8.82a15 15 0 0 1 4.177-2.643",key:"1grhjp"}],["path",{d:"M22 8.82a15 15 0 0 0-11.288-3.764",key:"z3jwby"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);/** + * @license lucide-react v0.468.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const sv=Ot("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);function zm(r){var N,E,d="";if(typeof r=="string"||typeof r=="number")d+=r;else if(typeof r=="object")if(Array.isArray(r)){var M=r.length;for(N=0;Nrv(r),kl="w-full rounded-lg border border-line bg-white px-3 py-2 text-[13px] text-slate-900 placeholder:text-slate-400 transition focus:border-brand-500 focus:outline-none focus:ring-3 focus:ring-brand-500/15 disabled:cursor-not-allowed disabled:bg-slate-50";function xm(r){if(!r)return"—";const N=Math.floor((Date.now()-r)/6e4);return N<1?"刚刚":N<60?`${N} 分钟前`:`${Math.floor(N/60)} 小时前`}function Rs(r=[]){return{total:r.length,studyable:r.filter(N=>N.in_study!==!1).length}}function yn(r){return String(r||"").split("#").filter(Boolean)}const ov={"01":"单选","02":"多选","03":"判断","04":"问答"};function me(r){return r instanceof Error?r.message:String(r)}const dv={neutral:"bg-slate-100 text-slate-600 ring-slate-200",brand:"bg-brand-50 text-brand-700 ring-brand-100",success:"bg-emerald-50 text-emerald-700 ring-emerald-100",warning:"bg-amber-50 text-amber-700 ring-amber-100",danger:"bg-red-50 text-red-700 ring-red-100",running:"bg-sky-50 text-sky-700 ring-sky-100"};function Hs({tone:r="neutral",children:N,dot:E=!1,className:d}){return f.jsxs("span",{className:gl("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[11px] font-medium ring-1 ring-inset",dv[r],d),children:[E&&f.jsx("span",{className:"size-1.5 rounded-full bg-current opacity-70"}),N]})}const mv={primary:"border-brand-500 bg-brand-500 text-white shadow-sm shadow-brand-500/25 hover:border-brand-600 hover:bg-brand-600",secondary:"border-line bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50",ghost:"border-transparent bg-transparent text-slate-600 hover:bg-slate-100",danger:"border-transparent bg-transparent text-red-600 hover:bg-red-50",soft:"border-brand-100 bg-brand-50 text-brand-700 hover:border-brand-200 hover:bg-brand-100"},yv={sm:"h-8 gap-1.5 rounded-lg px-2.5 text-xs",md:"h-9 gap-1.5 rounded-lg px-3.5 text-[13px]",icon:"h-9 w-9 rounded-lg"};function Jt({variant:r="secondary",size:N="md",loading:E=!1,icon:d,className:M,children:w,disabled:j,type:ut="button",...W}){return f.jsxs("button",{type:ut,disabled:j||E,className:gl("inline-flex shrink-0 items-center justify-center border font-medium transition","focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-brand-500/20","disabled:cursor-not-allowed disabled:opacity-50",mv[r],yv[N],M),...W,children:[E?f.jsx(Fh,{className:"size-3.5 animate-spin"}):d,w]})}function hv(r,N){var w,j;const E=N==="login"||r.status==="logging"||((w=r.run)==null?void 0:w.status)==="logging"?"logging":((j=r.run)==null?void 0:j.status)||r.status||"idle",M={discovering:{label:"发现课程中",tone:"running",pulse:!0},studying:{label:"学习中",tone:"running",pulse:!0},finished:{label:"已完成",tone:"success"},stopped:{label:"已停止",tone:"warning"},error:{label:"出错",tone:"danger"},interrupted:{label:"已中断",tone:"warning"},logging:{label:"登录中",tone:"running",pulse:!0},logged_in:{label:"已登录",tone:"success"},login_failed:{label:"登录失败",tone:"danger"},idle:{label:"未登录",tone:"neutral"}}[E]||{label:E,tone:"neutral"};return{label:M.label,tone:M.tone,pulse:!!M.pulse}}function vv({account:r,course:N,disabled:E,onToggle:d}){var w;const M=(w=r.selected)==null?void 0:w.includes(N.plan_id);return f.jsxs("label",{className:gl("flex cursor-pointer items-start gap-2.5 rounded-lg border border-transparent px-2 py-1.5 transition","hover:border-line hover:bg-slate-50",E&&"pointer-events-none opacity-60"),children:[f.jsx("input",{type:"checkbox",className:"mt-0.5 size-3.5 shrink-0 accent-brand-500",checked:!!M,disabled:E,onChange:j=>d(N.plan_id,j.target.checked)}),f.jsxs("span",{className:"min-w-0 flex-1",children:[f.jsx("span",{className:"block truncate text-[12.5px] font-medium text-slate-700",children:N.name||N.plan_id}),f.jsx("span",{className:"mt-0.5 block truncate text-[11px] text-slate-400",children:[N.section,N.status_label,N.info].filter(Boolean).join(" · ")||"—"})]}),f.jsx("span",{className:"shrink-0 pt-0.5 text-[11px] tabular-nums text-slate-500",children:N.progress||""})]})}function gv({account:r,platformLabel:N,pending:E,openLog:d,logLines:M,onToggleLog:w,onLogin:j,onRefresh:ut,onStudy:W,onStop:V,onCapture:q,onStopCapture:S,onQuiz:Z,onDelete:rt,onToggleCourse:Xt,onSelectAll:et,onClearSelection:D,onToggleOption:dt}){var pt,B,at,it,wt,o,T,Y,Q,mt,st,vt,y,O,A,L;const[tt,Tt]=G.useState(!1),Ft=G.useRef(null),Mt=G.useRef(null),Ht=G.useRef(!0);G.useEffect(()=>{if(!tt)return;const U=J=>{var P;(P=Ft.current)!=null&&P.contains(J.target)||Tt(!1)};return document.addEventListener("pointerdown",U),()=>document.removeEventListener("pointerdown",U)},[tt]),G.useEffect(()=>{const U=Mt.current;U&&Ht.current&&(U.scrollTop=U.scrollHeight)},[M,d]);const F=hv(r,E),C=!!E||r.status==="logging"||((pt=r.run)==null?void 0:pt.status)==="logging",At=r.courses||[],zt=At.filter(U=>U.in_study!==!1),Nt=At.filter(U=>U.in_study===!1),Ct=Rs(At),Wt=((B=r.run)==null?void 0:B.done)||0,Lt=((at=r.run)==null?void 0:at.total)||0,Bt=Lt?Math.round(Wt/Lt*100):0,H=["discovering","studying"].includes(((it=r.run)==null?void 0:it.status)||""),k=((wt=r.selected)==null?void 0:wt.length)||0,I=k>0&&(((o=r.cookies)==null?void 0:o.length)||0)>0;return f.jsxs("article",{"data-id":r.id,className:"card-shadow flex min-w-0 flex-col rounded-2xl border border-line bg-white transition-colors hover:border-slate-300/80",children:[f.jsxs("header",{className:"flex items-start gap-3 px-4 pt-4",children:[f.jsxs("div",{className:"relative mt-0.5 grid size-10 shrink-0 place-items-center rounded-xl bg-gradient-to-br from-brand-50 to-sky-50 text-[13px] font-semibold text-brand-700 ring-1 ring-brand-100",children:[(r.user||r.username||"?").slice(0,1).toUpperCase(),f.jsx("span",{className:gl("absolute -bottom-0.5 -right-0.5 size-3 rounded-full border-2 border-white",F.tone==="success"?"bg-emerald-500":F.tone==="danger"?"bg-red-500":F.tone==="running"?"bg-sky-500":F.tone==="warning"?"bg-amber-500":"bg-slate-300",F.pulse&&"animate-pulse")})]}),f.jsxs("div",{className:"min-w-0 flex-1",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx("h2",{className:"truncate text-[13.5px] font-semibold text-slate-900",children:r.user||r.username}),f.jsx(Hs,{tone:F.tone,dot:!0,children:F.label})]}),f.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] text-slate-400",children:[f.jsx("span",{className:"truncate",children:r.username}),r.note&&f.jsxs("span",{className:"truncate",children:["· ",r.note]}),f.jsxs("span",{children:["· ",xm(r.updated||r.loginAt)]})]})]}),f.jsx(Hs,{tone:"brand",className:"mt-0.5 shrink-0",children:N})]}),f.jsxs("div",{className:"px-4 pt-3",children:[f.jsxs("div",{className:"flex items-center justify-between gap-2",children:[f.jsxs("div",{className:"text-[11.5px] text-slate-500",children:["共 ",f.jsx("b",{className:"font-semibold text-slate-700",children:Ct.total})," 门 · 可学"," ",f.jsx("b",{className:"font-semibold text-slate-700",children:Ct.studyable}),Nt.length>0&&f.jsxs("span",{className:"text-slate-400",children:[" · 已完成 ",Nt.length]})]}),zt.length>0&&f.jsxs("div",{className:"flex items-center gap-1",children:[f.jsx("button",{type:"button",disabled:C,className:"rounded px-1.5 py-0.5 text-[11px] text-brand-600 transition hover:bg-brand-50 disabled:opacity-40",onClick:et,children:"全选"}),f.jsx("button",{type:"button",disabled:C||k===0,className:"rounded px-1.5 py-0.5 text-[11px] text-slate-500 transition hover:bg-slate-100 disabled:opacity-40",onClick:D,children:"清空"})]})]}),f.jsx("div",{className:"scrollbar-thin mt-1.5 max-h-[196px] min-h-[70px] overflow-y-auto pr-0.5",children:At.length===0?f.jsx("div",{className:"grid min-h-[70px] place-items-center rounded-lg border border-dashed border-line text-[12px] text-slate-400",children:"还没有课程,先登录或刷新课程"}):f.jsxs(f.Fragment,{children:[zt.map(U=>f.jsx(vv,{account:r,course:U,disabled:C,onToggle:Xt},U.plan_id)),Nt.length>0&&f.jsx("div",{className:"mt-1 border-t border-dashed border-line pt-1",children:Nt.map(U=>f.jsxs("div",{className:"flex items-start gap-2.5 rounded-lg px-2 py-1.5 text-slate-400",children:[f.jsx("span",{className:"mt-0.5 grid size-3.5 shrink-0 place-items-center rounded-full bg-emerald-50 text-[9px] text-emerald-600",children:"✓"}),f.jsxs("span",{className:"min-w-0 flex-1",children:[f.jsx("span",{className:"block truncate text-[12px]",children:U.name||U.plan_id}),f.jsx("span",{className:"mt-0.5 block truncate text-[10.5px] opacity-80",children:[U.section,U.info].filter(Boolean).join(" · ")})]}),f.jsx("span",{className:"shrink-0 text-[10.5px]",children:U.status_label||"已结束"})]},U.plan_id))})]})})]}),f.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-x-4 gap-y-1.5 border-t border-line/70 px-4 py-2.5",children:[f.jsxs("label",{className:"flex cursor-pointer items-center gap-1.5 text-[11.5px] text-slate-600",children:[f.jsx("input",{type:"checkbox",className:"size-3.5 accent-brand-500",checked:r.optQuiz===!0,disabled:C,onChange:U=>dt("quiz",U.target.checked)}),"自动交测验"]}),f.jsxs("label",{className:"flex cursor-pointer items-center gap-1.5 text-[11.5px] text-slate-600",children:[f.jsx("input",{type:"checkbox",className:"size-3.5 accent-brand-500",checked:r.optFeedback!==!1,disabled:C,onChange:U=>dt("feedback",U.target.checked)}),"自动交反馈表"]}),f.jsx("div",{className:"flex-1"}),f.jsx("span",{className:"text-[11px] tabular-nums text-slate-400",children:k>0?`已选 ${k} 门`:"未选择课程"})]}),f.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 border-t border-line/70 px-4 py-2.5",children:[f.jsx(Jt,{size:"sm",variant:"soft",loading:E==="login"||r.status==="logging"||((T=r.run)==null?void 0:T.status)==="logging",disabled:C,icon:f.jsx(Wh,{className:"size-3.5"}),onClick:j,children:(Y=r.cookies)!=null&&Y.length?"重新登录":"登录"}),f.jsx(Jt,{size:"sm",loading:E==="refresh",disabled:C||!((Q=r.cookies)!=null&&Q.length),icon:f.jsx(Bs,{className:"size-3.5"}),onClick:ut,children:"刷新课程"}),f.jsx(Jt,{size:"sm",variant:"primary",loading:E==="study",disabled:C||!I,icon:f.jsx(Ih,{className:"size-3.5"}),onClick:W,children:"开始学习"}),f.jsx("div",{className:"flex-1"}),H&&f.jsx(Jt,{size:"icon",variant:"danger",loading:E==="stop",onClick:V,title:"停止学习","aria-label":"停止学习",children:f.jsx(Xh,{className:"size-4"})}),f.jsxs("div",{className:"relative",ref:Ft,children:[f.jsx(Jt,{size:"icon",variant:"ghost",onClick:()=>Tt(U=>!U),"aria-label":"更多操作",title:"更多操作",children:f.jsx(Lh,{className:"size-4"})}),tt&&f.jsx("div",{className:"absolute bottom-10 right-0 z-20 w-40 overflow-hidden rounded-xl border border-line bg-white py-1 shadow-xl shadow-slate-900/10",children:[{label:"课程日志",icon:$h,action:w},{label:"打开测验",icon:Vh,action:Z},(mt=r.run)!=null&&mt.capturing?{label:"停止抓包",icon:nv,action:S}:{label:"抓包 10 分钟",icon:cv,action:q},{label:"删除账号",icon:iv,action:rt,danger:!0}].map(U=>f.jsxs("button",{type:"button",className:gl("flex w-full items-center gap-2 px-3 py-2 text-left text-[12px] transition hover:bg-slate-50",U.danger?"text-red-600":"text-slate-700"),onClick:()=>{Tt(!1),U.action()},children:[f.jsx(U.icon,{className:"size-3.5 opacity-70"}),U.label]},U.label))})]})]}),(Lt>0||((st=r.run)==null?void 0:st.error))&&f.jsxs("div",{className:"border-t border-line/70 px-4 py-3",children:[f.jsxs("div",{className:"mb-1.5 flex items-center justify-between gap-2 text-[11px] text-slate-500",children:[f.jsx("span",{className:"truncate",children:((vt=r.run)==null?void 0:vt.course)||((y=r.run)==null?void 0:y.status)||"学习进度"}),f.jsxs("span",{className:"shrink-0 tabular-nums",children:[Wt," / ",Lt,Lt>0&&f.jsxs("span",{className:"ml-1 text-slate-400",children:["(",Bt,"%)"]})]})]}),f.jsx("div",{className:"h-1.5 overflow-hidden rounded-full bg-slate-100",children:f.jsx("div",{className:gl("h-full rounded-full transition-all duration-500",((O=r.run)==null?void 0:O.status)==="error"?"bg-red-500":((A=r.run)==null?void 0:A.status)==="finished"?"bg-emerald-500":"bg-gradient-to-r from-brand-500 to-sky-400"),style:{width:`${Math.min(100,Bt)}%`}})}),((L=r.run)==null?void 0:L.error)&&f.jsx("p",{className:"mt-2 rounded-lg bg-red-50 px-2.5 py-1.5 text-[11px] leading-relaxed text-red-700",children:r.run.error})]}),r.lastError&&f.jsx("div",{className:"border-t border-line/70 px-4 py-2.5",children:f.jsxs("p",{className:"rounded-lg bg-red-50/80 px-2.5 py-1.5 text-[11px] leading-relaxed text-red-700",children:[r.lastError,r.lastErrorAt?f.jsxs("span",{className:"ml-1 text-red-400",children:["· ",xm(r.lastErrorAt)]}):null]})}),f.jsxs("div",{className:gl("border-t border-line/70",d?"block":"hidden"),children:[f.jsxs("div",{className:"flex items-center gap-2 px-4 pt-2.5 text-[11px] text-slate-400",children:[f.jsx("span",{className:"font-medium text-slate-500",children:"课程日志"}),f.jsxs("span",{className:"tabular-nums",children:["(",M.length,")"]}),f.jsx("div",{className:"flex-1"}),f.jsx("button",{type:"button",onClick:w,className:"rounded px-1.5 py-0.5 text-[11px] text-slate-500 transition hover:bg-slate-100",children:"收起"})]}),f.jsx("pre",{ref:Mt,onScroll:U=>{const J=U.currentTarget;Ht.current=J.scrollHeight-J.scrollTop-J.clientHeight<24},className:gl("scrollbar-thin mx-4 mb-3 mt-2 max-h-56 overflow-auto rounded-lg bg-slate-950/95 p-3","font-mono text-[11px] leading-relaxed text-slate-300",M.length===0&&"text-slate-500"),children:M.length?M.join(` +`):"暂无日志 · 开始学习后这里会实时显示"})]}),f.jsxs("button",{type:"button",onClick:w,className:"flex items-center justify-center gap-1 border-t border-line/70 py-1.5 text-[10.5px] text-slate-400 transition hover:bg-slate-50 hover:text-slate-600","aria-expanded":d,children:[f.jsx(Sm,{className:gl("size-3 transition-transform",d&&"rotate-180")}),d?"收起课程日志":"展开课程日志"]})]})}const bv={md:"max-w-xl",lg:"max-w-3xl",xl:"max-w-6xl"};function Ki({open:r,onClose:N,title:E,subtitle:d,size:M="md",footer:w,children:j,bodyClassName:ut}){return G.useEffect(()=>{if(!r)return;const W=q=>{q.key==="Escape"&&N()};window.addEventListener("keydown",W);const V=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{window.removeEventListener("keydown",W),document.body.style.overflow=V}},[r,N]),r?f.jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:[f.jsx("div",{className:"absolute inset-0 bg-slate-900/40 backdrop-blur-[2px]",onClick:N}),f.jsxs("div",{role:"dialog","aria-modal":"true",className:gl("relative flex max-h-[calc(100vh-2rem)] w-full flex-col overflow-hidden rounded-2xl","border border-line bg-white shadow-2xl shadow-slate-900/20",bv[M]),children:[f.jsxs("header",{className:"flex items-start gap-3 border-b border-line px-5 py-4",children:[f.jsxs("div",{className:"min-w-0 flex-1",children:[f.jsx("h2",{className:"truncate text-[15px] font-semibold text-slate-900",children:E}),d&&f.jsx("p",{className:"mt-0.5 truncate text-xs text-slate-500",children:d})]}),f.jsx("button",{type:"button",onClick:N,className:"-mr-1 rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600","aria-label":"关闭",children:f.jsx(sv,{className:"size-4"})})]}),f.jsx("div",{className:gl("min-h-0 flex-1 overflow-auto px-5 py-4",ut),children:j}),w&&f.jsx("footer",{className:"flex flex-wrap items-center justify-end gap-2 border-t border-line bg-slate-50/70 px-5 py-3",children:w})]})]}):null}function xv({open:r,platforms:N,onClose:E,onSubmit:d}){var dt;const[M,w]=G.useState(""),[j,ut]=G.useState(""),[W,V]=G.useState(""),[q,S]=G.useState(((dt=N[0])==null?void 0:dt.id)||"guanyixue"),[Z,rt]=G.useState(!1),[Xt,et]=G.useState("");G.useEffect(()=>{var tt;r&&(w(""),ut(""),V(""),S(((tt=N[0])==null?void 0:tt.id)||"guanyixue"),et(""),rt(!1))},[r,N]);async function D(){if(!M.trim()||!j){et("请填写账号和密码");return}rt(!0),et("");try{await d({username:M.trim(),password:j,note:W.trim(),platform:q}),E()}catch(tt){et(tt instanceof Error?tt.message:String(tt))}finally{rt(!1)}}return f.jsx(Ki,{open:r,onClose:E,title:"添加账号",subtitle:"账号密码保存在本机 SQLite,用于会话失效时自动重新登录",footer:f.jsxs(f.Fragment,{children:[f.jsx(Jt,{onClick:E,disabled:Z,children:"取消"}),f.jsx(Jt,{variant:"primary",loading:Z,onClick:D,children:"保存并登录"})]}),children:f.jsxs("div",{className:"space-y-4",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:"学习平台"}),f.jsxs("div",{className:"relative",children:[f.jsx(Tm,{className:"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-slate-400"}),f.jsx("select",{className:`${kl} appearance-none pl-8 pr-8`,value:q,onChange:tt=>S(tt.target.value),children:N.map(tt=>f.jsx("option",{value:tt.id,children:tt.label},tt.id))}),f.jsx(Sm,{className:"pointer-events-none absolute right-2.5 top-1/2 size-3.5 -translate-y-1/2 text-slate-400"})]}),f.jsx("p",{className:"mt-1.5 text-[11px] leading-relaxed text-slate-400",children:"选「莞易学」后,后台会自动识别旧版 / 新版课程页并按对应实现学习;后续新增的平台会出现在这里。"})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:"登录账号"}),f.jsx("input",{className:kl,value:M,autoFocus:!0,placeholder:"手机号 / 身份证号 / 教师账号",onChange:tt=>w(tt.target.value),onKeyDown:tt=>tt.key==="Enter"&&D()})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:"密码"}),f.jsx("input",{className:kl,type:"password",value:j,autoComplete:"off",placeholder:"平台登录密码",onChange:tt=>ut(tt.target.value),onKeyDown:tt=>tt.key==="Enter"&&D()})]}),f.jsxs("div",{children:[f.jsxs("label",{className:"mb-1.5 block text-[12px] font-medium text-slate-600",children:["备注 ",f.jsx("span",{className:"font-normal text-slate-400",children:"(可选)"})]}),f.jsx("input",{className:kl,value:W,placeholder:"例如:张三 · 语文",onChange:tt=>V(tt.target.value)})]}),f.jsx("p",{className:"rounded-lg border border-line bg-slate-50 px-3 py-2 text-[11.5px] leading-relaxed text-slate-500",children:"保存后会自动尝试登录一次。若密码错误或需要验证码,卡片上会保留「登录」按钮,可手动重试。"}),Xt&&f.jsx("p",{className:"rounded-lg bg-red-50 px-3 py-2 text-[12px] text-red-700",children:Xt})]})})}class je extends Error{constructor(E,d={}){super(E);Li(this,"offline",!1);Li(this,"status");Li(this,"code");this.name="ApiError",Object.assign(this,d)}}async function Zt(r,N={}){let E;try{E=await fetch(r,{...N,headers:{"Content-Type":"application/json",...N.headers||{}}})}catch{throw new je("后端未连接",{offline:!0})}if(E.status===401)throw new je("需要访问令牌:请用 /?token= 打开一次",{status:401});if(!E.ok)throw new je(`HTTP ${E.status}`,{status:E.status});return await E.json()}async function pv(r,N,E){let d;try{d=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(N)})}catch{throw new je("后端未连接",{offline:!0})}if(d.status===401)throw new je("需要访问令牌:请用 /?token= 打开一次");if(!d.ok)throw new je(`HTTP ${d.status}`);if(!d.body)throw new je("浏览器不支持流式响应");const M=d.body.getReader(),w=new TextDecoder;let j="";for(;;){const{value:ut,done:W}=await M.read();if(W)break;j+=w.decode(ut,{stream:!0});const V=j.split(` + +`);j=V.pop()||"";for(const q of V){const S=q.trim();if(S.startsWith("data:"))try{E(JSON.parse(S.slice(5).trim()))}catch{}}}}function Sv(r){const N=String((r==null?void 0:r.text)||"").replace(/\s+/g," ").trim();return N.length>24?`${N.slice(0,24)}…`:N}function Tv({open:r,account:N,course:E,onClose:d,notify:M,onSubmitted:w}){const[j,ut]=G.useState(null),[W,V]=G.useState({}),[q,S]=G.useState(!1),[Z,rt]=G.useState(!1),[Xt,et]=G.useState(!1),[D,dt]=G.useState(!1),[tt,Tt]=G.useState(""),[Ft,Mt]=G.useState("info"),Ht=G.useRef(0);async function F(B=!1){if(!N||!E)return!1;S(!0),Tt(B?"正在生成新答卷…":"取题中…"),Mt("info");try{const at={cookies:N.cookies,platform:N.platform||"guanyixue",plan_id:E.plan_id,project_id:E.project_id,name:E.name||""};B&&(at.retake=!0,at.period_id=(j==null?void 0:j.period_id)||"");const it=await Zt("/api/quiz",{method:"POST",body:JSON.stringify(at)});if(!it.ok)return ut(null),Tt(it.error||"取题失败"),Mt("error"),!1;ut(it),V(Object.fromEntries((it.questions||[]).map(o=>[o.no,o.picked||""])));const wt=[];if(it.done){const o=it.surplus_exam_count;o!=null?wt.push(`剩 ${o} 次`):it.allow_exam_count&&wt.push(`共 ${it.allow_exam_count} 次`),it.show_answers?wt.push("已显示标准答案"):it.exam_after_watch_answer==="0"&&wt.push("本测验不开放答案"),Tt(`已交卷${wt.length?` · ${wt.join(" · ")}`:""}`),Mt("success")}else Tt(it.started?"已自动创建答卷(限时考试已开始计时)":""),Mt("info");return!0}catch(at){return Tt(at instanceof Error?at.message:"取题失败"),Mt("error"),!1}finally{S(!1)}}if(G.useEffect(()=>{!r||!N||!E||(ut(null),V({}),dt(!1),F(!1))},[r,N==null?void 0:N.id,E==null?void 0:E.plan_id]),!N||!E)return null;const C=(j==null?void 0:j.questions)||[],At=!!(j!=null&&j.done),zt=!!(j!=null&&j.show_answers),Nt=!!(j!=null&&j.can_retake),Ct=j==null?void 0:j.surplus_exam_count,Wt=At||q||Z||D;function Lt(B,at){V(it=>({...it,[B]:at}))}function Bt(B,at,it){V(wt=>{const o=yn(wt[B]),T=it?[...o,at]:o.filter(Y=>Y!==at);return T.sort(),{...wt,[B]:T.join("#")}})}async function H(){if(!j||!N)return;const B=C.filter(at=>!W[at.no]).length;if(!(B&&!window.confirm(`还有 ${B} 题没作答,确定提交?`))){rt(!0),Tt("提交中…"),Mt("info");try{const at=await Zt("/api/quiz/submit",{method:"POST",body:JSON.stringify({cookies:N.cookies,plan_id:j.plan_id,object_id:j.object_id,generation:j.generation||"legacy",result_id:j.result_id||"",answers:W})});if(!at.ok){at.code==="already_finished"&&await F(),Tt(at.error||"提交失败"),Mt("error");return}M({message:`测验已提交${at.score?`,得分 ${at.score}`:""}`,tone:"success"}),await F(),w()}catch(at){Tt(at instanceof Error?at.message:"提交失败"),Mt("error")}finally{rt(!1)}}}async function k(){if(!j)return;if(!j.can_retake){M({message:"没有剩余考试机会",tone:"error"});return}const B=Ct!=null?`(剩余 ${Ct} 次)`:"";if(window.confirm(`再考一次会消耗 1 次机会${B};限时考试会立即开始计时,确定?`)){et(!0);try{await F(!0)&&M({message:"已生成新答卷,可以重新答题了",tone:"success"})}finally{et(!1)}}}async function I(){if(!j||!N)return;if(j.done){M({message:"已交卷,点「再考一次」生成新答卷后再 AI 答题",tone:"error"});return}dt(!0),Ht.current=0;const B=Date.now();let at=0,it="";const wt=window.setInterval(()=>{Tt(`AI 答题中… ${Math.round((Date.now()-B)/1e3)}s · 已填 ${Ht.current}/${C.length} 题`),Mt("info")},1e3);Tt(`AI 答题中… 已填 0/${C.length} 题`);try{await pv("/api/quiz/answer",{questions:j.questions,account_id:N.id},o=>{const T=o.answers;if(T&&typeof T=="object"){const Y=Object.keys(T).length;Y&&(Ht.current+=Y,V(Q=>({...Q,...T})))}o.error&&(it=String(o.error)),o.done&&typeof o.failed=="number"&&(at=o.failed)}),Ht.current?at?(Tt(`AI 已填 ${Ht.current} 题,${at} 题失败${it?`:${it}`:""}`),Mt("error")):(Tt(`AI 已填 ${Ht.current} 题`),Mt("success")):(Tt(it?`AI 答题失败:${it}`:"AI 没有返回答案"),Mt("error"))}catch(o){Tt(o instanceof Error?o.message:"AI 答题失败"),Mt("error")}finally{window.clearInterval(wt),dt(!1)}}const pt=Nt?`再考一次${Ct!=null?`(剩 ${Ct} 次)`:""}`:Ct===0?"考试机会已用完":"再考一次";return f.jsx(Ki,{open:r,onClose:d,title:`测验 · ${E.name||E.plan_id}`,subtitle:tt||"取题后可手动作答,或让大模型逐批填写",size:"xl",footer:f.jsxs(f.Fragment,{children:[f.jsx("span",{className:gl("mr-auto max-w-[50%] truncate text-[11.5px]",Ft==="error"?"text-red-600":Ft==="success"?"text-emerald-600":"text-slate-500"),children:tt}),At&&f.jsx(Jt,{size:"sm",loading:Xt,disabled:q||!Nt,icon:f.jsx(Ph,{className:"size-3.5"}),onClick:k,children:pt}),f.jsx(Jt,{size:"sm",onClick:d,children:"关闭"}),f.jsx(Jt,{size:"sm",variant:"soft",loading:D,disabled:Wt||!C.length,icon:f.jsx(wh,{className:"size-3.5"}),onClick:I,children:"AI 答题"}),f.jsx(Jt,{size:"sm",variant:"primary",loading:Z,disabled:Wt||!C.length,icon:f.jsx(lv,{className:"size-3.5"}),onClick:H,children:"提交"})]}),children:q&&!C.length?f.jsx("div",{className:"py-16 text-center text-[13px] text-slate-400",children:"正在打开课程页取题…"}):C.length?f.jsx("div",{className:"space-y-2.5",children:C.map(B=>{const at=B.options||[],it=W[B.no]||"",wt=B.type==="02",o=at.length>0;return f.jsxs("div",{className:"rounded-xl border border-line px-3.5 py-3",children:[f.jsxs("div",{className:"flex items-start gap-2",children:[f.jsx("span",{className:"mt-0.5 grid size-5 shrink-0 place-items-center rounded-md bg-slate-100 text-[10.5px] font-semibold tabular-nums text-slate-500",children:B.no}),f.jsx(Hs,{tone:"neutral",className:"mt-0.5 shrink-0",children:ov[B.type||""]||"题目"}),f.jsx("p",{className:"min-w-0 flex-1 text-[13px] leading-relaxed text-slate-800",children:B.title||`第 ${B.no} 题`}),zt&&B.is_correct!==void 0&&f.jsx("span",{className:gl("shrink-0 text-[12px] font-semibold",B.is_correct?"text-emerald-600":"text-red-500"),children:B.is_correct?"✓":"✗"})]}),o&&f.jsx("div",{className:"mt-2 flex flex-wrap gap-1.5 pl-7",children:at.map(T=>{const Y=zt&&yn(B.correct).includes(T.key),Q=zt&&yn(B.picked).includes(T.key)&&!yn(B.correct).includes(T.key);return f.jsxs("span",{className:gl("max-w-full rounded-lg border px-2 py-1 text-[11.5px] leading-snug",Y?"border-emerald-200 bg-emerald-50 text-emerald-800":Q?"border-red-200 bg-red-50 text-red-700":"border-line bg-slate-50/70 text-slate-600"),children:[f.jsx("b",{className:"mr-1 font-semibold",children:T.key}),Sv(T)]},T.key)})}),f.jsxs("div",{className:"mt-2.5 flex flex-wrap items-center gap-2 pl-7",children:[wt?f.jsx("div",{className:"flex flex-wrap gap-1.5",children:at.map(T=>{const Y=yn(it);return f.jsxs("label",{title:`${T.key}. ${T.text||""}`,className:gl("flex cursor-pointer items-center gap-1 rounded-lg border px-2 py-1 text-[11.5px] transition",Y.includes(T.key)?"border-brand-300 bg-brand-50 text-brand-700":"border-line text-slate-600 hover:border-slate-300",Wt&&"pointer-events-none opacity-60"),children:[f.jsx("input",{type:"checkbox",className:"size-3 accent-brand-500",checked:Y.includes(T.key),disabled:Wt,onChange:Q=>Bt(B.no,T.key,Q.target.checked)}),T.key]},T.key)})}):o?f.jsxs("select",{className:"h-8 w-full max-w-[320px] rounded-lg border border-line bg-white px-2 text-[12px] text-slate-700 focus:border-brand-500 focus:outline-none disabled:bg-slate-50 disabled:text-slate-400",value:it,disabled:Wt,onChange:T=>Lt(B.no,T.target.value),children:[f.jsx("option",{value:"",children:"未选"}),at.map(T=>f.jsxs("option",{value:T.key,children:[T.key,". ",T.text||""]},T.key))]}):f.jsx("input",{className:"h-8 w-full max-w-[320px] rounded-lg border border-line bg-white px-2 text-[12px] text-slate-700 focus:border-brand-500 focus:outline-none disabled:bg-slate-50 disabled:text-slate-400",value:it,placeholder:"填写答案",disabled:Wt,onChange:T=>Lt(B.no,T.target.value)}),zt&&B.correct&&f.jsxs("span",{className:"text-[11.5px] text-slate-500",children:["标准答案:",f.jsx("b",{className:"font-semibold text-slate-700",children:B.correct})]})]}),zt&&B.analysis&&f.jsxs("p",{className:"mt-2 rounded-lg bg-slate-50 px-2.5 py-1.5 text-[11.5px] leading-relaxed text-slate-500",children:["解析:",B.analysis]})]},B.no)})}):f.jsx("div",{className:"py-16 text-center text-[13px] text-red-600",children:tt||"没有题目"})})}function Nv({open:r,onClose:N,notify:E}){const[d,M]=G.useState(!1),[w,j]=G.useState(!1),[ut,W]=G.useState(!1),[V,q]=G.useState({base_url:"",api_key:"",model:"",temperature:"0.2",timeout:"120",prompt:"",study_mode:"fast",study_parallel:"2"}),[S,Z]=G.useState("sk-...");G.useEffect(()=>{r&&(M(!0),Zt("/api/settings").then(D=>{const dt=D.llm||{},tt=D.study||{};q({base_url:dt.base_url||"",api_key:"",model:dt.model||"",temperature:String(dt.temperature??.2),timeout:String(dt.timeout??120),prompt:dt.prompt||"",study_mode:tt.mode||"fast",study_parallel:String(tt.parallel||2)}),Z(dt.has_key?`已保存 ${dt.key_hint||""},留空不修改`:"sk-...")}).catch(D=>E({message:`读取设置失败:${D.message}`,tone:"error"})).finally(()=>M(!1)))},[r,E]);function rt(D,dt){q(tt=>({...tt,[D]:dt}))}async function Xt(){j(!0);try{await Zt("/api/settings",{method:"POST",body:JSON.stringify({base_url:V.base_url.trim(),api_key:V.api_key.trim(),model:V.model.trim(),temperature:Number.parseFloat(V.temperature)||.2,timeout:Number.parseInt(V.timeout,10)||120,prompt:V.prompt,study_mode:V.study_mode,study_parallel:Number.parseInt(V.study_parallel,10)||0})}),E({message:"设置已保存",tone:"success"}),N()}catch(D){E({message:`保存失败:${D instanceof Error?D.message:D}`,tone:"error"})}finally{j(!1)}}async function et(){W(!0);try{const D=await Zt("/api/llm/test",{method:"POST",body:JSON.stringify({base_url:V.base_url.trim(),api_key:V.api_key.trim(),model:V.model.trim()})});E({message:D.ok?`连接正常(${D.ms} ms):${D.reply||""}`:`连接失败:${D.error||"未知错误"}`,tone:D.ok?"success":"error"})}catch(D){E({message:`连接失败:${D instanceof Error?D.message:D}`,tone:"error"})}finally{W(!1)}}return f.jsx(Ki,{open:r,onClose:N,title:"系统设置",subtitle:"大模型接口、答题提示词与学习模式",size:"lg",footer:f.jsxs(f.Fragment,{children:[f.jsx(Jt,{loading:ut,onClick:et,icon:f.jsx(Zh,{className:"size-3.5"}),children:"测试连接"}),f.jsx(Jt,{onClick:N,disabled:w,children:"取消"}),f.jsx(Jt,{variant:"primary",loading:w,onClick:Xt,disabled:d,children:"保存"})]}),children:d?f.jsx("div",{className:"py-10 text-center text-[12.5px] text-slate-400",children:"读取设置…"}):f.jsxs("div",{className:"space-y-6",children:[f.jsxs("section",{children:[f.jsxs("div",{className:"mb-3 flex items-center gap-2 text-[12.5px] font-semibold text-slate-700",children:[f.jsx(ev,{className:"size-4 text-brand-500"}),"大模型(OpenAI 兼容)"]}),f.jsxs("div",{className:"space-y-3",children:[f.jsxs("div",{children:[f.jsxs("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:["接口地址 ",f.jsx("span",{className:"text-slate-400",children:"(写到 /v1 为止)"})]}),f.jsx("input",{className:kl,value:V.base_url,placeholder:"https://api.openai.com/v1",onChange:D=>rt("base_url",D.target.value)})]}),f.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"API Key"}),f.jsxs("div",{className:"relative",children:[f.jsx(kh,{className:"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-slate-400"}),f.jsx("input",{className:`${kl} pl-8`,type:"password",autoComplete:"off",value:V.api_key,placeholder:S,onChange:D=>rt("api_key",D.target.value)})]})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"模型"}),f.jsx("input",{className:kl,value:V.model,placeholder:"gpt-4o-mini / deepseek-chat / qwen-plus",onChange:D=>rt("model",D.target.value)})]})]}),f.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"温度"}),f.jsx("input",{className:kl,type:"number",min:0,max:2,step:.1,value:V.temperature,onChange:D=>rt("temperature",D.target.value)})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"超时(秒)"}),f.jsx("input",{className:kl,type:"number",min:10,max:600,value:V.timeout,onChange:D=>rt("timeout",D.target.value)})]})]}),f.jsxs("div",{children:[f.jsxs("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:["答题提示词 ",f.jsx("span",{className:"text-slate-400",children:"(留空使用内置)"})]}),f.jsx("textarea",{className:`${kl} min-h-24 resize-y`,value:V.prompt,placeholder:'只输出 JSON {"answers":{"题号":"答案"}}',onChange:D=>rt("prompt",D.target.value)})]})]})]}),f.jsxs("section",{className:"border-t border-line pt-5",children:[f.jsxs("div",{className:"mb-3 flex items-center gap-2 text-[12.5px] font-semibold text-slate-700",children:[f.jsx(Kh,{className:"size-4 text-brand-500"}),"学习模式"]}),f.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"模式"}),f.jsxs("select",{className:kl,value:V.study_mode,onChange:D=>rt("study_mode",D.target.value),children:[f.jsx("option",{value:"fast",children:"快速学习(只调接口上报)"}),f.jsx("option",{value:"normal",children:"常规学习(真实播放视频)"})]})]}),f.jsxs("div",{children:[f.jsx("label",{className:"mb-1.5 block text-[12px] text-slate-600",children:"常规模式并发数"}),f.jsx("input",{className:kl,type:"number",min:1,max:5,value:V.study_parallel,onChange:D=>rt("study_parallel",D.target.value)})]})]}),f.jsxs("p",{className:"mt-3 rounded-lg bg-slate-50 px-3 py-2 text-[11.5px] leading-relaxed text-slate-500",children:["常规学习会开多个无头浏览器同时播视频;平台若按课节顺序放行,会被弹回并自动降为 1 路。快速学习只调用 ",f.jsx("code",{className:"rounded bg-white px-1 ring-1 ring-line",children:"period/study/log"}),",不启动浏览器。"]})]})]})})}function Ev({accounts:r}){const N=r.filter(j=>{var ut;return((ut=j.cookies)==null?void 0:ut.length)>0||["logged_in","studying"].includes(j.status||"")}).length,E=r.filter(j=>{var ut;return["discovering","studying"].includes(((ut=j.run)==null?void 0:ut.status)||"")}).length,d=r.reduce((j,ut)=>{var W;return j+(((W=ut.run)==null?void 0:W.done)||0)},0),M=r.reduce((j,ut)=>{var W;return j+(((W=ut.run)==null?void 0:W.total)||0)},0),w=[{label:"账号",value:r.length,hint:"已添加",icon:Em,tone:"text-brand-600 bg-brand-50"},{label:"已登录",value:N,hint:r.length?`共 ${r.length} 个`:"等待添加",icon:uv,tone:"text-emerald-600 bg-emerald-50"},{label:"学习中",value:E,hint:E?"正在跑课":"空闲",icon:Yh,tone:"text-sky-600 bg-sky-50"},{label:"课程进度",value:M?`${d}/${M}`:"—",hint:M?`${Math.round(d/M*100)}%`:"暂无任务",icon:Tm,tone:"text-amber-600 bg-amber-50"}];return f.jsx("section",{className:"grid grid-cols-2 gap-3 lg:grid-cols-4",children:w.map(j=>f.jsxs("div",{className:"flex items-center gap-3 rounded-xl border border-line bg-white px-4 py-3",children:[f.jsx("span",{className:`grid size-9 shrink-0 place-items-center rounded-lg ${j.tone}`,children:f.jsx(j.icon,{className:"size-4"})}),f.jsxs("div",{className:"min-w-0",children:[f.jsx("div",{className:"text-[11px] text-slate-400",children:j.label}),f.jsxs("div",{className:"flex items-baseline gap-1.5",children:[f.jsx("span",{className:"text-[17px] font-semibold tabular-nums leading-tight text-slate-900",children:j.value}),f.jsx("span",{className:"truncate text-[10.5px] text-slate-400",children:j.hint})]})]})]},j.label))})}function zv({open:r,onClose:N}){const[E,d]=G.useState([]),[M,w]=G.useState(!1),j=G.useRef(null),ut=G.useRef(!0);G.useEffect(()=>{if(!r)return;let V=!0;const q=async()=>{try{const Z=await Zt("/api/log/history?key=system&tail=500");V&&d(Z.lines||[])}catch{}};d([]),q();const S=window.setInterval(()=>{document.hidden||q()},2500);return()=>{V=!1,window.clearInterval(S)}},[r]),G.useEffect(()=>{const V=j.current;V&&ut.current&&(V.scrollTop=V.scrollHeight)},[E,r]);async function W(){w(!0);try{await Zt("/api/log/history?key=system",{method:"DELETE"}),d([])}finally{w(!1)}}return f.jsx(Ki,{open:r,onClose:N,title:"系统日志",subtitle:"全局事件与系统级错误,实时刷新",size:"xl",footer:f.jsxs(f.Fragment,{children:[f.jsxs("span",{className:"mr-auto text-[11px] text-slate-400",children:["共 ",E.length," 行 · 保留最近 500 行"]}),f.jsx(Jt,{variant:"danger",size:"sm",loading:M,onClick:W,children:"清空"}),f.jsx(Jt,{size:"sm",onClick:N,children:"关闭"})]}),bodyClassName:"bg-slate-950 p-0",children:f.jsx("pre",{ref:j,onScroll:V=>{const q=V.currentTarget;ut.current=q.scrollHeight-q.scrollTop-q.clientHeight<24},className:"scrollbar-thin h-[60vh] overflow-auto whitespace-pre-wrap break-words p-4 font-mono text-[11.5px] leading-relaxed text-slate-300",children:E.length?E.join(` +`):"暂无系统日志"})})}function _v({toast:r}){if(!r)return null;const N=r.tone||"info",E=N==="error"?Gh:N==="success"?Qh:Jh;return f.jsxs("div",{role:"status",className:gl("animate-toast-in fixed bottom-7 left-1/2 z-[60] flex max-w-[85vw] -translate-x-1/2 items-center gap-2","rounded-xl px-4 py-2.5 text-[12.5px] font-medium shadow-xl shadow-slate-900/20",N==="error"?"bg-red-600 text-white":N==="success"?"bg-emerald-600 text-white":"bg-slate-900 text-white"),children:[f.jsx(E,{className:"size-4 shrink-0 opacity-90"}),f.jsx("span",{className:"break-words",children:r.message})]})}function Ov({refreshing:r,onRefresh:N,onSettings:E,onSystemLog:d,onAdd:M}){return f.jsx("header",{className:"sticky top-0 z-30 border-b border-line/80 bg-white/85 backdrop-blur-xl",children:f.jsxs("div",{className:"mx-auto flex h-16 max-w-[1320px] items-center gap-3 px-4 sm:px-6",children:[f.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[f.jsx("div",{className:"grid size-9 shrink-0 place-items-center rounded-xl bg-gradient-to-br from-brand-500 to-sky-400 text-[15px] font-bold text-white shadow-md shadow-brand-500/30",children:"学"}),f.jsxs("div",{className:"min-w-0",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx("h1",{className:"truncate text-[15px] font-semibold tracking-tight text-slate-900",children:"莞易学"}),f.jsx("span",{className:"hidden rounded-md bg-slate-100 px-1.5 py-0.5 text-[10px] font-medium text-slate-500 sm:inline",children:"多账号学习控制台"})]}),f.jsx("p",{className:"truncate text-[11.5px] text-slate-500",children:"东莞市教师培训平台 · 新旧版课程自动识别"})]})]}),f.jsx("div",{className:"flex-1"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx(Jt,{variant:"ghost",size:"icon",onClick:N,loading:r,title:"刷新列表","aria-label":"刷新列表",children:f.jsx(Bs,{className:"size-4"})}),f.jsx(Jt,{variant:"ghost",size:"icon",onClick:d,title:"系统日志","aria-label":"系统日志",children:f.jsx(tv,{className:"size-4"})}),f.jsx(Jt,{variant:"ghost",size:"icon",onClick:E,title:"系统设置","aria-label":"系统设置",children:f.jsx(av,{className:"size-4"})}),f.jsx(Jt,{variant:"primary",className:"ml-1",icon:f.jsx(Nm,{className:"size-4"}),onClick:M,children:f.jsx("span",{className:"hidden sm:inline",children:"添加账号"})})]})]})})}const _m="guanyixue.inlineLogsOpen";function Av(){try{const r=JSON.parse(localStorage.getItem(_m)||"[]");return new Set(Array.isArray(r)?r.filter(N=>typeof N=="string"):[])}catch{return new Set}}function jv(r){try{localStorage.setItem(_m,JSON.stringify([...r]))}catch{}}function Mv(r){return{id:r.id,username:r.username,platform:r.platform||"guanyixue",note:r.note||"",user:r.user||"",cookies:r.cookies||[],courses:r.courses||[],selected:r.selected||[],status:r.status||"idle",lastError:r.lastError||"",lastErrorAt:r.lastErrorAt||0,optQuiz:r.optQuiz===!0,optFeedback:r.optFeedback!==!1,loginAt:r.loginAt||0}}function Cv(){const[r,N]=G.useState([]),E=G.useRef(r),[d,M]=G.useState({guanyixue:"莞易学"}),[w,j]=G.useState([{id:"guanyixue",label:"莞易学"}]),[ut,W]=G.useState(!1),[V,q]=G.useState(null),[S,Z]=G.useState({}),[rt,Xt]=G.useState(!1),[et,D]=G.useState(null),[dt,tt]=G.useState(()=>Av()),Tt=G.useRef(dt),[Ft,Mt]=G.useState({}),Ht=G.useRef(Ft),F=G.useRef(void 0);G.useEffect(()=>{E.current=r},[r]),G.useEffect(()=>{Ht.current=Ft},[Ft]),G.useEffect(()=>{Tt.current=dt,jv(dt)},[dt]),G.useEffect(()=>()=>window.clearTimeout(F.current),[]);const C=G.useCallback(y=>{q(y),window.clearTimeout(F.current),F.current=window.setTimeout(()=>q(null),3800)},[]),At=G.useCallback(async y=>{const O=await Zt("/api/accounts",{method:"POST",body:JSON.stringify(Mv(y))});if(O.ok===!1)throw new Error(O.error||"保存失败");return O},[]),zt=G.useCallback(y=>{N(O=>{const L=O.some(U=>U.id===y.id)?O.map(U=>U.id===y.id?y:U):[...O,y];return E.current=L,L})},[]),Nt=G.useCallback(async(y=!0)=>{var O;try{const[A,L]=await Promise.all([Zt("/api/runs"),Zt("/api/accounts")]),U=(L.accounts||[]).map(J=>({...J,run:A[J.id]||null})).sort((J,P)=>(J.created||0)-(P.created||0));N(U),E.current=U,W(!1);for(const J of U){const P=(O=J.run)==null?void 0:O.cookies;if(P&&P.length&&JSON.stringify(P)!==JSON.stringify(J.cookies||[])){const gt={...J,cookies:P};J.cookies=P,At(gt).catch(()=>{})}}}catch(A){A instanceof je&&A.offline?W(!0):y||C({message:`读取账号失败:${me(A)}`,tone:"error"})}},[C,At]);G.useEffect(()=>{Nt();const y=window.setInterval(()=>{document.hidden||Nt()},5e3);return()=>window.clearInterval(y)},[Nt]),G.useEffect(()=>{Zt("/api/platforms").then(y=>{const O=y.platforms||[];if(!O.length)return;j(O);const A={};for(const L of O)A[L.id]=L.label;M(A)}).catch(()=>{})},[]);const Ct=G.useCallback(async y=>{var U;const O=Ht.current[y]||{lines:[],since:0,busy:!1,historyTried:!1};if(O.busy)return;const A={...O,busy:!0},L=J=>{Ht.current={...Ht.current,[y]:J},Mt(P=>({...P,[y]:J}))};L(A);try{let J=await Zt(`/api/log?key=${encodeURIComponent(y)}&since=${A.since}`);typeof J.next=="number"&&J.nextle.id===y);if(fl&&JSON.stringify(fl.cookies||[])!==JSON.stringify(gt)){const le={...fl,cookies:gt};zt(le),At(le).catch(()=>{})}}}catch{}finally{A.busy=!1,L(A)}},[zt,At]);G.useEffect(()=>{const y=window.setInterval(()=>{document.hidden||Tt.current.forEach(O=>void Ct(O))},1500);return()=>window.clearInterval(y)},[Ct]);const Wt=G.useCallback((y,O)=>{const A=O===void 0?!Tt.current.has(y):O,L=new Set(Tt.current);A?L.add(y):L.delete(y),Tt.current=L,tt(L),A&&Ct(y)},[Ct]);async function Lt(y,O,A){Z(L=>({...L,[y]:O}));try{return await A()}finally{Z(L=>{const U={...L};return delete U[y],U})}}async function Bt(y,O=!1){return Lt(y.id,"login",async()=>{zt({...y,status:"logging",lastError:""});try{await At({...y,status:"logging",lastError:""});const A=await Zt("/api/login",{method:"POST",body:JSON.stringify({account_id:y.id})});if(!A.ok){const J={...y,status:"login_failed",lastError:A.error||`HTTP ${A.code||"失败"}`,lastErrorAt:Date.now(),run:null};return zt(J),await At(J).catch(()=>{}),O||C({message:`登录失败:${J.lastError}`,tone:"error"}),!1}const L=A.courses||[],U={...y,status:"logged_in",cookies:A.cookies||[],user:A.user||y.user||"",courses:L,selected:(y.selected||[]).filter(J=>L.some(P=>P.plan_id===J)),loginAt:Date.now(),updated:Date.now(),lastError:"",lastErrorAt:0,run:null};return zt(U),await At(U).catch(()=>{}),O||C({message:A.warn?`登录成功,但课程读取异常:${A.warn}`:`登录成功:${U.user||U.username},读到 ${Rs(L).total} 门`,tone:A.warn?"info":"success"}),Nt(),!0}catch(A){const L={...y,status:"login_failed",lastError:me(A),lastErrorAt:Date.now()};return zt(L),await At(L).catch(()=>{}),O||C({message:`登录失败:${L.lastError}`,tone:"error"}),A instanceof je&&A.offline&&W(!0),!1}})}async function H(y){return Lt(y.id,"refresh",async()=>{var O;try{let A=await Zt("/api/courses",{method:"POST",body:JSON.stringify({cookies:y.cookies,platform:y.platform||"guanyixue"})});if(!A.ok&&A.code==="session_expired"){if(C({message:"会话已失效,正在自动重新登录…"}),!await Bt(y,!0))return;const J=E.current.find(P=>P.id===y.id);if(!J)return;A=await Zt("/api/courses",{method:"POST",body:JSON.stringify({cookies:J.cookies})})}if(!A.ok){C({message:`读取失败:${A.error||A.code||"未知错误"}`,tone:"error"});return}const L=E.current.find(J=>J.id===y.id)||y,U={...L,courses:A.courses||[],user:A.user||L.user,cookies:(O=A.cookies)!=null&&O.length?A.cookies:L.cookies,status:"logged_in",updated:Date.now(),lastError:"",lastErrorAt:0};zt(U),await At(U).catch(()=>{}),C({message:`已刷新,读到 ${Rs(U.courses).total} 门`,tone:"success"})}catch(A){C({message:`读取失败:${me(A)}`,tone:"error"})}})}async function k(y){var L;const O=y.selected||[],A=(y.courses||[]).filter(U=>O.includes(U.plan_id)&&U.in_study!==!1);if(!A.length){C({message:"请先勾选要学习的课程",tone:"error"});return}if(!((L=y.cookies)!=null&&L.length)){C({message:"请先登录",tone:"error"});return}return Lt(y.id,"study",async()=>{var U,J;try{const P=await Zt("/api/study",{method:"POST",body:JSON.stringify({key:y.id,username:y.user||y.username,cookies:y.cookies,courses:A,workers:40,cap_minutes:90,enable_quiz:y.optQuiz===!0,enable_feedback:y.optFeedback!==!1})});if(!P.ok){C({message:`启动失败:${P.error||"未知错误"}`,tone:"error"});return}const gt=((U=P.study)==null?void 0:U.mode)==="normal"?`常规真播 ${((J=P.study)==null?void 0:J.parallel)||1} 路并发`:"快速模式(只调接口)";C({message:`已开始 ${A.length} 门课程 · ${gt}${y.optQuiz?" · 含自动答题":" · 测验需手动作答"}`,tone:"success"}),Wt(y.id,!0),Nt()}catch(P){C({message:`启动失败:${me(P)}`,tone:"error"})}})}async function I(y){return Lt(y.id,"stop",async()=>{try{await Zt("/api/stop",{method:"POST",body:JSON.stringify({key:y.id})}),C({message:"已请求停止"}),Nt()}catch(O){C({message:`停止失败:${me(O)}`,tone:"error"})}})}async function pt(y){var O;if(!((O=y.cookies)!=null&&O.length)){C({message:"请先登录",tone:"error"});return}return Lt(y.id,"capture",async()=>{try{const A=await Zt("/api/capture",{method:"POST",body:JSON.stringify({key:y.id,cookies:y.cookies,minutes:10})});if(!A.ok){C({message:`抓包失败:${A.error||"未知错误"}`,tone:"error"});return}C({message:"已打开浏览器,请手动走一遍课程页;最多记录 10 分钟",tone:"success"})}catch(A){C({message:`抓包失败:${me(A)}`,tone:"error"})}})}async function B(y){return Lt(y.id,"capture",async()=>{try{await Zt("/api/capture/stop",{method:"POST",body:JSON.stringify({key:y.id})}),C({message:"已请求停止抓包"}),Nt()}catch(O){C({message:`停止抓包失败:${me(O)}`,tone:"error"})}})}async function at(y){if(window.confirm(`删除账号「${y.user||y.username}」?课程缓存和日志不会自动清理。`))try{await Zt(`/api/accounts/${encodeURIComponent(y.id)}`,{method:"DELETE"}),N(O=>{const A=O.filter(L=>L.id!==y.id);return E.current=A,A}),C({message:"账号已删除"})}catch(O){C({message:`删除失败:${me(O)}`,tone:"error"})}}async function it(y,O){const A={...y,selected:O};zt(A);try{await At(A)}catch(L){C({message:`保存勾选失败:${me(L)}`,tone:"error"})}}function wt(y,O,A){const L=y.selected||[];it(y,A?[...new Set([...L,O])]:L.filter(U=>U!==O))}function o(y){const O=(y.courses||[]).filter(A=>A.in_study!==!1).map(A=>A.plan_id);it(y,[...new Set([...y.selected||[],...O])])}async function T(y,O,A){const L=O==="quiz"?{...y,optQuiz:A}:{...y,optFeedback:A};zt(L);try{await At(L),C({message:O==="quiz"?A?"已开启自动交测验(注意正确率)":"已关闭自动交测验":A?"已开启自动交反馈表":"已关闭自动交反馈表"})}catch(U){C({message:`保存失败:${me(U)}`,tone:"error"})}}async function Y(y){const O=await Zt("/api/accounts",{method:"POST",body:JSON.stringify({username:y.username,platform:y.platform,password:y.password,note:y.note,cookies:[],courses:[],selected:[],status:"idle",created:Date.now()})});if(O.ok===!1)throw new Error(O.error||"保存失败");const A=await Zt("/api/accounts"),L=O.account||(A.accounts||[]).find(P=>P.username===y.username);if(!L){C({message:"已保存,但列表里没有找到新账号,请刷新页面",tone:"error"}),await Nt();return}C({message:"已保存,正在尝试首次登录…"});const U=await Bt(L,!0),J=E.current.find(P=>P.id===L.id);C(U?{message:`登录成功:${(J==null?void 0:J.user)||y.username}`,tone:"success"}:{message:`登录失败:${(J==null?void 0:J.lastError)||"未知原因"}(请手动点击「登录」重试)`,tone:"error"}),await Nt()}async function Q(){Xt(!0);try{await Nt(!1)}finally{Xt(!1)}}function mt(y){var A;const O=y.platform||((A=(y.courses||[]).find(L=>L.platform))==null?void 0:A.platform);return O&&d[O]||"莞易学"}const st=(et==null?void 0:et.type)==="quiz"&&r.find(y=>y.id===et.accountId)||null,vt=(et==null?void 0:et.type)==="quiz"?(st==null?void 0:st.courses.find(y=>y.plan_id===et.course.plan_id))||et.course:null;return f.jsxs("div",{className:"min-h-screen",children:[f.jsx(Ov,{refreshing:rt,onRefresh:()=>void Q(),onSettings:()=>D({type:"settings"}),onSystemLog:()=>D({type:"system"}),onAdd:()=>D({type:"add"})}),f.jsxs("main",{className:"mx-auto max-w-[1320px] px-4 pb-16 pt-5 sm:px-6",children:[ut&&f.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2.5 rounded-xl border border-red-200 bg-red-50 px-4 py-2.5 text-[12.5px] text-red-700",children:[f.jsx(fv,{className:"size-4 shrink-0"}),f.jsx("span",{className:"font-medium",children:"后端未连接"}),f.jsx("span",{className:"text-red-500",children:"页面显示的是上一次数据,请确认服务已启动、端口没有变化。"}),f.jsx("div",{className:"flex-1"}),f.jsx(Jt,{size:"sm",variant:"secondary",loading:rt,onClick:()=>void Q(),children:"重试"})]}),f.jsx(Ev,{accounts:r}),f.jsxs("div",{className:"mb-3 mt-6 flex items-end justify-between gap-3",children:[f.jsxs("div",{children:[f.jsx("h2",{className:"text-[14px] font-semibold text-slate-900",children:"账号列表"}),f.jsx("p",{className:"mt-0.5 text-[11.5px] text-slate-400",children:"新旧版课程自动识别为「莞易学」,每 5 秒自动刷新状态"})]}),r.length>0&&f.jsx(Jt,{size:"sm",variant:"secondary",icon:f.jsx(Bs,{className:"size-3.5"}),loading:rt,onClick:()=>void Q(),children:"刷新"})]}),r.length===0?f.jsxs("div",{className:"card-shadow grid place-items-center rounded-2xl border border-dashed border-slate-300 bg-white px-6 py-16 text-center",children:[f.jsx("div",{className:"grid size-12 place-items-center rounded-2xl bg-brand-50 text-brand-600",children:f.jsx(Em,{className:"size-6"})}),f.jsx("h3",{className:"mt-4 text-[14px] font-semibold text-slate-800",children:"还没有账号"}),f.jsx("p",{className:"mt-1.5 max-w-md text-[12.5px] leading-relaxed text-slate-500",children:"添加东莞市教师培训平台账号后,可自动读取课程、勾选学习、提交反馈表与测验。 新旧版课程页会统一识别为「莞易学」。"}),f.jsx(Jt,{variant:"primary",className:"mt-5",icon:f.jsx(Nm,{className:"size-4"}),onClick:()=>D({type:"add"}),children:"添加第一个账号"})]}):f.jsx("div",{className:"grid items-start gap-4 md:grid-cols-2 xl:grid-cols-3",children:r.map(y=>{var O;return f.jsx(gv,{account:y,platformLabel:mt(y),pending:S[y.id],openLog:dt.has(y.id),logLines:((O=Ft[y.id])==null?void 0:O.lines)||[],onToggleLog:()=>Wt(y.id),onLogin:()=>void Bt(y),onRefresh:()=>void H(y),onStudy:()=>void k(y),onStop:()=>void I(y),onCapture:()=>void pt(y),onStopCapture:()=>void B(y),onDelete:()=>void at(y),onQuiz:()=>{var U;const A=(y.courses||[]).filter(J=>J.in_study!==!1),L=A.find(J=>{var P;return(P=y.selected)==null?void 0:P.includes(J.plan_id)})||A[0];if(!L){C({message:"这门课还没有课程数据,先点「刷新课程」",tone:"error"});return}if(!((U=y.cookies)!=null&&U.length)){C({message:"请先登录",tone:"error"});return}D({type:"quiz",accountId:y.id,course:L})},onToggleCourse:(A,L)=>wt(y,A,L),onSelectAll:()=>o(y),onClearSelection:()=>void it(y,[]),onToggleOption:(A,L)=>void T(y,A,L)},y.id)})})]}),f.jsx("footer",{className:"border-t border-line/70 py-5 text-center text-[11px] text-slate-400",children:"莞易学 · 多账号学习控制台 · 数据保存在本机"}),f.jsx(xv,{open:(et==null?void 0:et.type)==="add",platforms:w,onClose:()=>D(null),onSubmit:Y}),f.jsx(Nv,{open:(et==null?void 0:et.type)==="settings",onClose:()=>D(null),notify:C}),f.jsx(zv,{open:(et==null?void 0:et.type)==="system",onClose:()=>D(null)}),f.jsx(Tv,{open:(et==null?void 0:et.type)==="quiz"&&!!st,account:st,course:vt,onClose:()=>D(null),notify:C,onSubmitted:()=>void Nt()}),f.jsx(_v,{toast:V})]})}Rh.createRoot(document.getElementById("root")).render(f.jsx(G.StrictMode,{children:f.jsx(Cv,{})})); diff --git a/static/assets/index-DiHucQck.css b/static/assets/index-DiHucQck.css deleted file mode 100644 index 2e3cdb7..0000000 --- a/static/assets/index-DiHucQck.css +++ /dev/null @@ -1 +0,0 @@ -/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:"Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, "Microsoft YaHei", sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-sky-50:oklch(97.7% .013 236.62);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-600:oklch(58.8% .158 241.966);--color-sky-700:oklch(50% .134 242.749);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-xl:36rem;--container-3xl:48rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-brand-50:#eef4ff;--color-brand-100:#dbe7ff;--color-brand-200:#bfd4ff;--color-brand-500:#2f6bff;--color-brand-600:#1f55e0;--color-brand-700:#1a46bd;--color-line:#e6eaf2}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{color-scheme:light;scroll-behavior:smooth}body{min-height:100vh;color:var(--color-slate-900);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:var(--font-sans);background-color:#f5f7fb}::selection{background:#2f6bff2e}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.top-0{top:0}.top-1\/2{top:50%}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-0{right:0}.-bottom-0\.5{bottom:calc(var(--spacing) * -.5)}.bottom-7{bottom:calc(var(--spacing) * 7)}.bottom-10{bottom:calc(var(--spacing) * 10)}.left-1\/2{left:50%}.left-2\.5{left:calc(var(--spacing) * 2.5)}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.z-\[60\]{z-index:60}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mr-1{margin-right:var(--spacing)}.mr-auto{margin-right:auto}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-1{margin-left:var(--spacing)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-16{height:calc(var(--spacing) * 16)}.h-\[60vh\]{height:60vh}.h-full{height:100%}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-\[196px\]{max-height:196px}.max-h-\[calc\(100vh-2rem\)\]{max-height:calc(100vh - 2rem)}.min-h-0{min-height:0}.min-h-24{min-height:calc(var(--spacing) * 24)}.min-h-\[70px\]{min-height:70px}.min-h-screen{min-height:100vh}.w-9{width:calc(var(--spacing) * 9)}.w-40{width:calc(var(--spacing) * 40)}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[50\%\]{max-width:50%}.max-w-\[85vw\]{max-width:85vw}.max-w-\[320px\]{max-width:320px}.max-w-\[1320px\]{max-width:1320px}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-180{rotate:180deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.scrollbar-thin{scrollbar-width:thin}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1\.5{row-gap:calc(var(--spacing) * 1.5)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-brand-100{border-color:var(--color-brand-100)}.border-brand-500{border-color:var(--color-brand-500)}.border-emerald-200{border-color:var(--color-emerald-200)}.border-line{border-color:var(--color-line)}.border-line\/70{border-color:#e6eaf2b3}@supports (color:color-mix(in lab,red,red)){.border-line\/70{border-color:color-mix(in oklab,var(--color-line) 70%,transparent)}}.border-line\/80{border-color:#e6eaf2cc}@supports (color:color-mix(in lab,red,red)){.border-line\/80{border-color:color-mix(in oklab,var(--color-line) 80%,transparent)}}.border-red-200{border-color:var(--color-red-200)}.border-slate-300{border-color:var(--color-slate-300)}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-brand-50{background-color:var(--color-brand-50)}.bg-brand-500{background-color:var(--color-brand-500)}.bg-current{background-color:currentColor}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-50\/80{background-color:#fef2f2cc}@supports (color:color-mix(in lab,red,red)){.bg-red-50\/80{background-color:color-mix(in oklab,var(--color-red-50) 80%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-sky-50{background-color:var(--color-sky-50)}.bg-sky-500{background-color:var(--color-sky-500)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-50\/70{background-color:#f8fafcb3}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/70{background-color:color-mix(in oklab,var(--color-slate-50) 70%,transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-300{background-color:var(--color-slate-300)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/40{background-color:#0f172b66}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/40{background-color:color-mix(in oklab,var(--color-slate-900) 40%,transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-slate-950\/95{background-color:#020618f2}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/95{background-color:color-mix(in oklab,var(--color-slate-950) 95%,transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab,red,red)){.bg-white\/85{background-color:color-mix(in oklab,var(--color-white) 85%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-brand-50{--tw-gradient-from:var(--color-brand-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-brand-500{--tw-gradient-from:var(--color-brand-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-sky-50{--tw-gradient-to:var(--color-sky-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-sky-400{--tw-gradient-to:var(--color-sky-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-0{padding:0}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-16{padding-block:calc(var(--spacing) * 16)}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-1{padding-top:var(--spacing)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pl-7{padding-left:calc(var(--spacing) * 7)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[17px\]{font-size:17px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-brand-500{color:var(--color-brand-500)}.text-brand-600{color:var(--color-brand-600)}.text-brand-700{color:var(--color-brand-700)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-emerald-800{color:var(--color-emerald-800)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-sky-600{color:var(--color-sky-600)}.text-sky-700{color:var(--color-sky-700)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.accent-brand-500{accent-color:var(--color-brand-500)}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-brand-500\/25{--tw-shadow-color:#2f6bff40}@supports (color:color-mix(in lab,red,red)){.shadow-brand-500\/25{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-brand-500) 25%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-brand-500\/30{--tw-shadow-color:#2f6bff4d}@supports (color:color-mix(in lab,red,red)){.shadow-brand-500\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-brand-500) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-900\/10{--tw-shadow-color:#0f172b1a}@supports (color:color-mix(in lab,red,red)){.shadow-slate-900\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-900) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-900\/20{--tw-shadow-color:#0f172b33}@supports (color:color-mix(in lab,red,red)){.shadow-slate-900\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-900) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-amber-100{--tw-ring-color:var(--color-amber-100)}.ring-brand-100{--tw-ring-color:var(--color-brand-100)}.ring-emerald-100{--tw-ring-color:var(--color-emerald-100)}.ring-line{--tw-ring-color:var(--color-line)}.ring-red-100{--tw-ring-color:var(--color-red-100)}.ring-sky-100{--tw-ring-color:var(--color-sky-100)}.ring-slate-200{--tw-ring-color:var(--color-slate-200)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ring-inset{--tw-ring-inset:inset}.placeholder\:text-slate-400::placeholder{color:var(--color-slate-400)}@media(hover:hover){.hover\:border-brand-200:hover{border-color:var(--color-brand-200)}.hover\:border-brand-600:hover{border-color:var(--color-brand-600)}.hover\:border-line:hover{border-color:var(--color-line)}.hover\:border-slate-300:hover{border-color:var(--color-slate-300)}.hover\:border-slate-300\/80:hover{border-color:#cad5e2cc}@supports (color:color-mix(in lab,red,red)){.hover\:border-slate-300\/80:hover{border-color:color-mix(in oklab,var(--color-slate-300) 80%,transparent)}}.hover\:bg-brand-50:hover{background-color:var(--color-brand-50)}.hover\:bg-brand-100:hover{background-color:var(--color-brand-100)}.hover\:bg-brand-600:hover{background-color:var(--color-brand-600)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:text-slate-600:hover{color:var(--color-slate-600)}}.focus\:border-brand-500:focus{border-color:var(--color-brand-500)}.focus\:ring-3:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-brand-500\/15:focus{--tw-ring-color:#2f6bff26}@supports (color:color-mix(in lab,red,red)){.focus\:ring-brand-500\/15:focus{--tw-ring-color:color-mix(in oklab, var(--color-brand-500) 15%, transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-3:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-brand-500\/20:focus-visible{--tw-ring-color:#2f6bff33}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-brand-500\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-brand-500) 20%, transparent)}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-50:disabled{background-color:var(--color-slate-50)}.disabled\:text-slate-400:disabled{color:var(--color-slate-400)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:40rem){.sm\:inline{display:inline}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:64rem){.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.scrollbar-thin{scrollbar-width:thin;scrollbar-color:#c9d2e3 transparent}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-thumb{background:#c9d2e3;border-radius:999px}.card-shadow{box-shadow:0 1px 2px #1018280a,0 18px 36px -24px #10182838}.animate-toast-in{animation:.24s cubic-bezier(.2,.8,.2,1) toast-in}}@keyframes toast-in{0%{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}} diff --git a/static/index.html b/static/index.html index 9217ec3..0c04c84 100644 --- a/static/index.html +++ b/static/index.html @@ -6,8 +6,8 @@ 莞易学 · 多账号学习控制台 - - + +
diff --git a/web/src/App.tsx b/web/src/App.tsx index 490726c..f686532 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -75,6 +75,7 @@ function accountPayload(account: Account) { return { id: account.id, username: account.username, + platform: account.platform || 'guanyixue', note: account.note || '', user: account.user || '', cookies: account.cookies || [], @@ -93,6 +94,9 @@ export default function App() { const [accounts, setAccounts] = useState([]) const accountsRef = useRef(accounts) const [platforms, setPlatforms] = useState>({ guanyixue: '莞易学' }) + const [platformList, setPlatformList] = useState([ + { id: 'guanyixue', label: '莞易学' }, + ]) const [offline, setOffline] = useState(false) const [toast, setToast] = useState(null) const [pending, setPending] = useState>({}) @@ -193,9 +197,12 @@ export default function App() { useEffect(() => { api<{ platforms: PlatformInfo[] }>('/api/platforms') .then((response) => { + const list = response.platforms || [] + if (!list.length) return + setPlatformList(list) const map: Record = {} - for (const platform of response.platforms || []) map[platform.id] = platform.label - if (Object.keys(map).length) setPlatforms(map) + for (const platform of list) map[platform.id] = platform.label + setPlatforms(map) }) .catch(() => {}) }, []) @@ -366,7 +373,10 @@ export default function App() { try { let response = await api('/api/courses', { method: 'POST', - body: JSON.stringify({ cookies: account.cookies }), + body: JSON.stringify({ + cookies: account.cookies, + platform: account.platform || 'guanyixue', + }), }) if (!response.ok && response.code === 'session_expired') { notify({ message: '会话已失效,正在自动重新登录…' }) @@ -578,6 +588,7 @@ export default function App() { method: 'POST', body: JSON.stringify({ username: data.username, + platform: data.platform, password: data.password, note: data.note, cookies: [], @@ -621,7 +632,8 @@ export default function App() { } function platformLabel(account: Account) { - const id = (account.courses || []).find((course) => course.platform)?.platform + const id = + account.platform || (account.courses || []).find((course) => course.platform)?.platform return (id && platforms[id]) || '莞易学' } @@ -749,6 +761,7 @@ export default function App() { setDialog(null)} onSubmit={addAccount} /> diff --git a/web/src/components/AddAccountDialog.tsx b/web/src/components/AddAccountDialog.tsx index cb9f416..85f5240 100644 --- a/web/src/components/AddAccountDialog.tsx +++ b/web/src/components/AddAccountDialog.tsx @@ -1,5 +1,7 @@ import { useEffect, useState } from 'react' +import { ChevronDown, GraduationCap } from 'lucide-react' +import type { PlatformInfo } from '../types' import { Modal } from './ui/Modal' import { Button } from './ui/Button' import { inputCls } from '../lib/utils' @@ -8,20 +10,24 @@ export interface NewAccount { username: string password: string note: string + platform: string } export function AddAccountDialog({ open, + platforms, onClose, onSubmit, }: { open: boolean + platforms: PlatformInfo[] onClose: () => void onSubmit: (account: NewAccount) => Promise }) { const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [note, setNote] = useState('') + const [platform, setPlatform] = useState(platforms[0]?.id || 'guanyixue') const [saving, setSaving] = useState(false) const [error, setError] = useState('') @@ -30,9 +36,10 @@ export function AddAccountDialog({ setUsername('') setPassword('') setNote('') + setPlatform(platforms[0]?.id || 'guanyixue') setError('') setSaving(false) - }, [open]) + }, [open, platforms]) async function submit() { if (!username.trim() || !password) { @@ -42,7 +49,7 @@ export function AddAccountDialog({ setSaving(true) setError('') try { - await onSubmit({ username: username.trim(), password, note: note.trim() }) + await onSubmit({ username: username.trim(), password, note: note.trim(), platform }) onClose() } catch (err) { setError(err instanceof Error ? err.message : String(err)) @@ -69,6 +76,27 @@ export function AddAccountDialog({ } >
+
+ +
+ + + +
+

+ 选「莞易学」后,后台会自动识别旧版 / 新版课程页并按对应实现学习;后续新增的平台会出现在这里。 +

+
= { cookies: account.cookies, + platform: account.platform || 'guanyixue', plan_id: course.plan_id, project_id: course.project_id, name: course.name || '', diff --git a/web/src/types.ts b/web/src/types.ts index 6b97fc9..cf27ace 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -37,6 +37,7 @@ export interface RunState { export interface Account { id: string username: string + platform?: string note?: string user?: string cookies: Cookie[]