dscord 0.4.0-alpha.3 → 0.4.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/central/README.md +2 -2
- package/central/avatars.md +8 -6
- package/central/avatars.mjs +5 -2
- package/central/service.mjs +8 -5
- package/central/store.mjs +17 -1
- package/dist/admin/assets/index-BqwnqlFx.css +1 -0
- package/dist/admin/assets/index-mXQNxGvo.js +10 -0
- package/dist/admin/index.html +2 -2
- package/dist/admin/licenses/bundled-dependencies.txt +93 -0
- package/dist/central-admin/assets/index-ByNljbpy.css +1 -0
- package/dist/central-admin/assets/index-CKu96QBX.js +9 -0
- package/dist/central-admin/index.html +2 -2
- package/dist/central-admin/licenses/bundled-dependencies.txt +93 -0
- package/dist/web/assets/index-Cl4X2HbO.js +55 -0
- package/dist/web/assets/index-DUlpYtqe.css +1 -0
- package/dist/web/index.html +3 -3
- package/dist/web/sw.js +269 -68
- package/dsh-connect/KERNEL.md +38 -8
- package/dsh-connect/client.js +428 -150
- package/dsh-connect/controller.mjs +50 -17
- package/dsh-connect/decision-settings.mjs +2 -1
- package/dsh-connect/index.mjs +2 -1
- package/dsh-connect/native-bridge.mjs +30 -13
- package/dsh-connect/native-connections.mjs +5 -3
- package/dsh-connect/native-team.mjs +3 -0
- package/dsh-connect/work-core.mjs +189 -13
- package/dsh-plugin/README.md +2 -2
- package/memory//345/244/215/347/224/250/344/270/216/350/277/220/350/241/214.md +2 -2
- package/memory//345/275/223/345/211/215/344/270/212/344/270/213/346/226/207/344/270/216/345/233/236/351/241/276.md +1 -1
- package/package.json +1 -1
- package/src/admin.mjs +20 -1
- package/src/bot-node.mjs +27 -6
- package/src/conversation-view.mjs +103 -0
- package/src/core/node-routes.mjs +4 -1
- package/src/core/room-routes.mjs +56 -31
- package/src/core.mjs +28 -2
- package/src/decision-provider.mjs +41 -8
- package/src/decision-state.mjs +94 -0
- package/src/front-prompt.mjs +348 -0
- package/src/kernel-control.mjs +2 -1
- package/src/message-context.mjs +0 -40
- package/src/node-store.mjs +47 -0
- package/src/profile-sync.mjs +7 -3
- package/src/push.mjs +51 -14
- package/src/room-reader.mjs +55 -0
- package/src/server-update-control.mjs +41 -0
- package/src/server-update-docker.mjs +70 -0
- package/src/server-update-release.mjs +58 -0
- package/src/server-updater.mjs +323 -0
- package/vendor/ds-bot/UPSTREAM.json +4 -0
- package/vendor/ds-bot/src/host/prompt.js +4 -1
- package//346/250/241/345/236/213/351/205/215/347/275/256/344/270/216/350/277/201/347/247/273.md +7 -3
- package/dist/admin/assets/index-B6oXrmH-.js +0 -10
- package/dist/admin/assets/index-C7fyavkW.css +0 -1
- package/dist/central-admin/assets/index-C-slX89W.css +0 -1
- package/dist/central-admin/assets/index-C06XyvSK.js +0 -9
- package/dist/web/assets/index-C5Owa1w-.js +0 -55
- package/dist/web/assets/index-Cr0sYP4g.css +0 -1
package/README.md
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# DSCord 0.4.0-alpha.
|
|
1
|
+
# DSCord 0.4.0-alpha.4 安装与连接
|
|
2
2
|
|
|
3
3
|
> [!WARNING]
|
|
4
4
|
> **实验性项目。** DSCord 目前是实验性质的项目,接口、数据格式和行为随时可能变化,不保证兼容旧版本。项目不考虑安全问题,因此将别人加入到你的服务器当中的时候,请确认你有线下找他喝茶的能力。
|
|
5
5
|
|
|
6
6
|
DSCord 的 npm 包包含 Core、预构建网页/PWA、Matrix 适配器和 DSCord Bot 内核。完整服务器源码发行包另含 Compose 部署文件;同一部署的 Core、客户端和节点使用同一发行版本。
|
|
7
7
|
|
|
8
|
-
本指南对应预发布版本 0.4.0-alpha.
|
|
8
|
+
本指南对应预发布版本 0.4.0-alpha.4,npm registry 和该版本的 GitHub Release 均提供安装包。Node 支持范围由 [package.json](package.json) 声明为 `>=24.19.0 <25`。Bot 宿主固定使用 DSH `0.2.2-rc.1` 的 SDK 契约,见[内核说明](dsh-connect/KERNEL.md)。Docker 服务器无需在宿主另装 Node。
|
|
9
9
|
|
|
10
10
|
## 安装
|
|
11
11
|
|
|
12
|
-
从发行页下载 `dscord-0.4.0-alpha.
|
|
12
|
+
从发行页下载 `dscord-0.4.0-alpha.4.tgz` 后,可在 DSH 的 `Plugins → Add plugin` 中安装并启用 `dscord`,再登录服务器连接 Bot。发行页同时提供 `SHA256SUMS` 校验文件。[下载发行包](https://github.com/MixGeekers/dscord/releases/tag/ds-group-v0.4.0-alpha.4)
|
|
13
13
|
|
|
14
14
|
全局安装 CLI 用于服务器与独立节点管理。从 npm registry 安装当前版本,安装后核对 `dscord --version`。
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
npm install --global dscord@0.4.0-alpha.
|
|
17
|
+
npm install --global dscord@0.4.0-alpha.4
|
|
18
18
|
dscord --help
|
|
19
19
|
dscord --version
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Core、CLI 和 DSH 插件使用同一发行版本。已有全局安装可用上述命令升级。当前预发布版本使用 `alpha` 标签,也可执行 `npm install --global dscord@alpha` 升级到最新 Alpha。[npm 包页面](https://www.npmjs.com/package/dscord/v/0.4.0-alpha.
|
|
22
|
+
Core、CLI 和 DSH 插件使用同一发行版本。已有全局安装可用上述命令升级。当前预发布版本使用 `alpha` 标签,也可执行 `npm install --global dscord@alpha` 升级到最新 Alpha。[npm 包页面](https://www.npmjs.com/package/dscord/v/0.4.0-alpha.4)
|
|
23
23
|
|
|
24
24
|
从源码构建 npm 包,在 `apps/ds-group/` 中执行:
|
|
25
25
|
|
|
@@ -28,11 +28,11 @@ npm ci --ignore-scripts
|
|
|
28
28
|
npm run npm:pack
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
该版本默认生成 `.local/npm-release/dscord-0.4.0-alpha.
|
|
31
|
+
该版本默认生成 `.local/npm-release/dscord-0.4.0-alpha.4.tgz`,仍应核对命令实际输出的版本、路径与校验值。构建需要开发依赖,运行已提供的预构建包不需要重新构建界面。
|
|
32
32
|
|
|
33
33
|
## 部署服务器
|
|
34
34
|
|
|
35
|
-
完整服务器采用[Compose 部署指南](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.
|
|
35
|
+
完整服务器采用[Compose 部署指南](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.4/apps/ds-group/deploy/README.md),先配置自己的 Matrix 身份域、公开地址和持久存储。npm CLI 不代替 Synapse 或反向代理。需要 `dscord server`、初始化及节点导入等命令时,在各终端保持同一个绝对数据路径:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
38
|
export DS_GROUP_DATA_DIR="$HOME/.local/share/dscord-server"
|
|
@@ -62,7 +62,7 @@ Core 提供的 Matrix 公开地址必须能从节点访问。一个连接页使
|
|
|
62
62
|
|
|
63
63
|
## 升级和已有 Bot
|
|
64
64
|
|
|
65
|
-
先备份服务器数据和各 DSH Bot home,再停止当前工作并升级到同一发行版本。已有 `ds-bot` 插件必须先停用,DSCord 才能在同一目录接管;同时启动两个内核会报冲突。接管会保存迁移快照,保留 Bot 与 Session 身份。[生命周期与迁移](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.
|
|
65
|
+
先备份服务器数据和各 DSH Bot home,再停止当前工作并升级到同一发行版本。已有 `ds-bot` 插件必须先停用,DSCord 才能在同一目录接管;同时启动两个内核会报冲突。接管会保存迁移快照,保留 Bot 与 Session 身份。[生命周期与迁移](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.4/apps/ds-group/deploy/kernel-runtime.md)
|
|
66
66
|
|
|
67
67
|
旧服务器 Bot 可在连接页绑定已有本机 Bot,保留 Matrix 身份;两套独立 Session 或记忆不会自动合并。已有原生绑定的 Bot 应从所属 DSH 连接,导出其配置不能在另一台机器创建身份副本。
|
|
68
68
|
|
|
@@ -100,11 +100,11 @@ dscord service down "$BOT_ACCOUNT"
|
|
|
100
100
|
dscord dsh stop "$BOT_ACCOUNT"
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
每个 Bot 同时运行一个节点,每个独立节点使用自己的数据目录和桥接端口。Linux 常驻服务见 [systemd](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.
|
|
103
|
+
每个 Bot 同时运行一个节点,每个独立节点使用自己的数据目录和桥接端口。Linux 常驻服务见 [systemd](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.4/apps/ds-group/deploy/systemd/README.md)。
|
|
104
104
|
|
|
105
105
|
## 存储与组件
|
|
106
106
|
|
|
107
|
-
附件默认使用 Synapse 本地媒体目录,可选 S3-compatible 后端。[存储配置](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.
|
|
107
|
+
附件默认使用 Synapse 本地媒体目录,可选 S3-compatible 后端。[存储配置](https://github.com/MixGeekers/dscord/blob/ds-group-v0.4.0-alpha.4/apps/ds-group/deploy/storage/README.md)说明远端对象、缓存和备份关系;已有云盘扫描与历史迁移不是自动功能。
|
|
108
108
|
|
|
109
109
|
`dscord server` 运行 Core/PWA,`init` 和 `bootstrap` 初始化服务器,`admin` 管理导出与导入,`node` 运行 Matrix 适配器,`dsh` 管理独立宿主,`service` 管理本机进程,`path` 显示安装目录。
|
|
110
110
|
|
package/central/README.md
CHANGED
|
@@ -39,7 +39,7 @@ npm run central
|
|
|
39
39
|
|
|
40
40
|
## 自定义头像
|
|
41
41
|
|
|
42
|
-
用户可修改自己和名下 Bot
|
|
42
|
+
用户可修改自己和名下 Bot 的头像和名称,Bot 也能改自己的,跨服务器同步,Bot 离线时也可设置。默认复用中央数据卷;入口、配置、备份和接口见[自定义头像](avatars.md)。
|
|
43
43
|
|
|
44
44
|
## 账号格式
|
|
45
45
|
|
|
@@ -61,7 +61,7 @@ npm run central
|
|
|
61
61
|
| `GET /.well-known/jwks.json` | 聊天服务器 | 验证身份令牌的公钥 |
|
|
62
62
|
| `POST /api/register` | 人 | `{username, password, displayName?}` 注册并登录(`registration: open` 时) |
|
|
63
63
|
| `POST /api/login` / `POST /api/logout` | 人 | 密码登录 / 退出当前会话 |
|
|
64
|
-
| `GET /api/me` / `DELETE /api/me` | 人、Bot 节点 / 人 | 查看自己 / 注销(名下还有 Bot 时要先注销 Bot) |
|
|
64
|
+
| `GET /api/me` / `PATCH /api/me` / `DELETE /api/me` | 人、Bot 节点 / 人、Bot 节点 / 人 | 查看自己 / 改自己的显示名称 `{displayName}` / 注销(名下还有 Bot 时要先注销 Bot) |
|
|
65
65
|
| `POST /api/identity-tokens` | 人、Bot 节点 | `{audience, allowNew?}` 为某台聊天服务器(HTTPS origin)签发 5 分钟有效的身份令牌;第一次去某台服务器时要带 `allowNew: true`,否则返回 `GRANT_REQUIRED` |
|
|
66
66
|
| `GET /api/grants` / `DELETE /api/grants/:audience` | 人、Bot 节点 | 查看 / 撤销自己授权过的聊天服务器 |
|
|
67
67
|
| `POST /api/connect-codes` | 人 | 生成 DSH 连接用的一次性代码(10 分钟有效)。聊天服务器网页把它和服务器地址一起编码成连接密钥 |
|
package/central/avatars.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 自定义头像与显示名称
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
用户可以修改自己的头像和显示名称,以及自己名下 Bot 的头像和名称;Bot 也能用前台工具 `update_profile` 改自己的名称和头像,和人一样。头像属于中央账号资料,使用稳定的中央账号 ID;Bot 不需要在线,修改头像不改变 Bot 的运行配置版本、不重启节点或 Session。
|
|
4
4
|
|
|
5
5
|
## 使用
|
|
6
6
|
|
|
7
|
-
- 自己:左下角账号菜单 → 个人设置 →
|
|
7
|
+
- 自己:左下角账号菜单 → 个人设置 → 账号,头像下方是“显示名称”。自己的成员资料卡也提供更换入口。
|
|
8
|
+
- Bot 自己:前台工具 `update_profile`(`name`、`avatar` 本地图片路径、`clear_avatar`),由连接插件用 Bot 自己的中央会话调用下面的 `/api/me` 接口,不经过所属人。
|
|
8
9
|
- Bot:Bot 主页 → 设置,或“我的 Bot”展开对应 Bot 的设置。所属 Bot 的成员资料卡也能修改。
|
|
9
10
|
- 选择 JPG、PNG 或静态 WebP,拖动、缩放并预览,点击“保存头像”。手机支持拖动和双指缩放,键盘可操作缩放及水平/垂直位置滑块。
|
|
10
11
|
- “恢复默认”恢复名字首字占位。占位颜色由稳定身份决定。
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
|
|
40
41
|
## 同步与图片处理
|
|
41
42
|
|
|
42
|
-
Core 每 5 秒按中央账号 ID
|
|
43
|
+
Core 每 5 秒按中央账号 ID 批量核对资料版本。读取到更新后保存到本地账号库(显示名称写入账号的名字),并使用该账号的服务凭据设置本服 Matrix 的 `displayname`,把图片同步至本服 Synapse 并设置 `avatar_url`。改名和换头像共用同一个资料版本:改名时版本加一,头像不变。图片上传成功但资料写入失败时保留 Matrix 媒体回执,后续重试复用该回执。Core 重启后从持久记录继续同步。中央或 Matrix 暂不可用不阻断聊天 API;恢复后继续补齐。
|
|
43
44
|
|
|
44
45
|
头像保存后,当前页面及同源标签页立即更新;其他设备和服务器通过版本轮询更新。无网络时不能保存,无法加载图片时显示占位。跨服务器同步是最终一致的,不要求所有服务器同时在线。
|
|
45
46
|
|
|
@@ -47,17 +48,18 @@ Core 每 5 秒按中央账号 ID 批量核对资料版本。读取到更新后
|
|
|
47
48
|
|
|
48
49
|
服务端使用固定依赖 `sharp@0.35.5`,校验真实图片格式、静态帧、40MP 像素上限与裁剪边界,校正 EXIF 方向,重新编码 WebP 并去除原元数据。安装时保留 npm 的 optional dependencies,Linux amd64/arm64 使用对应平台的预编译 sharp/libvips 包;继续支持 `npm ci --ignore-scripts`。
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
头像图片是公开身份资源,通过无账号令牌的内容版本地址访问,可由浏览器缓存。编辑接口只接受账号本人(人或 Bot 自己的会话)或 Bot 所属人的中央会话,聊天服务器管理员身份不授予全局头像编辑权。
|
|
51
52
|
|
|
52
53
|
## 接口
|
|
53
54
|
|
|
54
55
|
| 中央接口 | 作用 |
|
|
55
56
|
| --- | --- |
|
|
57
|
+
| `PATCH /api/me` | 本人(人或 Bot)修改显示名称:`{displayName}`,最多 80 字,空字符串恢复为用户名;名字未变时不增加版本 |
|
|
56
58
|
| `GET /api/me/avatar` | 读取本人头像、版本及上传上限 |
|
|
57
59
|
| `PUT /api/me/avatar?version=N&left=X&top=Y&size=S` | 上传原图字节,按校正方向后的像素裁剪;裁剪参数可全部省略,使用居中裁剪 |
|
|
58
60
|
| `DELETE /api/me/avatar?version=N` | 恢复默认 |
|
|
59
61
|
| `GET/PUT/DELETE /api/bots/:id/avatar` | 所属人修改对应 Bot,参数同上 |
|
|
60
|
-
| `GET /api/profiles?ids=...` | 读取至多 100 个已知中央账号 ID 或全局 ID
|
|
62
|
+
| `GET /api/profiles?ids=...` | 读取至多 100 个已知中央账号 ID 或全局 ID 的公开资料:显示名称、头像和资料版本 |
|
|
61
63
|
| `GET /avatars/:assetId/:size.webp` | 读取标准化图片 |
|
|
62
64
|
|
|
63
65
|
写入缺少版本返回 400,版本冲突返回 409;格式不支持返回 415,超限返回 413。客户端调用中央时使用既有 `clientOrigins` 跨域配置。
|
package/central/avatars.mjs
CHANGED
|
@@ -15,7 +15,7 @@ export function avatarOptions(input = {}) {
|
|
|
15
15
|
return result;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/**
|
|
18
|
+
/** Public profiles: the display name and identity image. Original uploads and processing directories are never published. */
|
|
19
19
|
export class Avatars {
|
|
20
20
|
constructor({ store, dataRoot, issuer, config }) {
|
|
21
21
|
Object.assign(this, { store, issuer });
|
|
@@ -25,10 +25,13 @@ export class Avatars {
|
|
|
25
25
|
account_id TEXT PRIMARY KEY REFERENCES accounts(id), version INTEGER NOT NULL,
|
|
26
26
|
asset_id TEXT, updated_at INTEGER NOT NULL);`);
|
|
27
27
|
store.profileOf = account => this.profile(account);
|
|
28
|
+
// A name change is a profile change too: the version moves on and the image stays.
|
|
29
|
+
store.profileChanged = account => this.store.db.prepare(`INSERT INTO account_profiles VALUES (?,1,NULL,?) ON CONFLICT(account_id)
|
|
30
|
+
DO UPDATE SET version=version+1,updated_at=excluded.updated_at`).run(account.id, this.store.now());
|
|
28
31
|
}
|
|
29
32
|
profile(account) {
|
|
30
33
|
const row = this.store.db.prepare('SELECT * FROM account_profiles WHERE account_id=?').get(account.id);
|
|
31
|
-
return { id: account.id, globalId: this.store.globalId(account.username), profileVersion: row?.version ?? 0,
|
|
34
|
+
return { id: account.id, globalId: this.store.globalId(account.username), displayName: account.display_name, profileVersion: row?.version ?? 0,
|
|
32
35
|
avatar: row?.asset_id ? { id: row.asset_id, url: `${this.issuer}/avatars/${row.asset_id}/128.webp`,
|
|
33
36
|
sizes: Object.fromEntries(this.options.sizes.map(size => [size, `${this.issuer}/avatars/${row.asset_id}/${size}.webp`])) } : null };
|
|
34
37
|
}
|
package/central/service.mjs
CHANGED
|
@@ -128,9 +128,15 @@ export async function createCentral({ dataRoot = localPath('central'), config, n
|
|
|
128
128
|
});
|
|
129
129
|
router.post('/api/logout', ({ request, send }) => { store.closeSession(signedIn(request).session); send(200, { loggedOut: true }); });
|
|
130
130
|
router.get('/api/me', ({ request, send }) => send(200, { account: store.view(signedIn(request).account) }));
|
|
131
|
+
// People and Bots edit their own profile the same way; a Bot's owner can also rename it from the Bot's settings.
|
|
132
|
+
router.on('PATCH', '/api/me', async ({ request, body, send }) => {
|
|
133
|
+
const { account } = signedIn(request);
|
|
134
|
+
const input = await body();
|
|
135
|
+
send(200, { account: store.view(input.displayName === undefined ? account : store.rename(account, input.displayName)) });
|
|
136
|
+
});
|
|
131
137
|
router.delete('/api/me', ({ request, send }) => { store.closeAccount(person(request).account); send(200, { closed: true }); });
|
|
132
138
|
|
|
133
|
-
// Avatars are public identity images; edits
|
|
139
|
+
// Avatars are public identity images; edits require the account itself (a person or a Bot) or the Bot's owner.
|
|
134
140
|
router.get('/api/profiles', ({ url, response, send }) => {
|
|
135
141
|
response.setHeader('Access-Control-Allow-Origin', '*');
|
|
136
142
|
const ids = (url.searchParams.get('ids') || '').split(',').filter(Boolean);
|
|
@@ -142,10 +148,7 @@ export async function createCentral({ dataRoot = localPath('central'), config, n
|
|
|
142
148
|
});
|
|
143
149
|
router.get(/^\/avatars\/([a-f0-9]{64})\/(\d+)\.webp$/, ({ response }, id, size) => avatars.serve(response, id, size));
|
|
144
150
|
for (const route of ['/api/me/avatar', /^\/api\/bots\/([^/]+)\/avatar$/]) {
|
|
145
|
-
const target = (request, id) =>
|
|
146
|
-
const { account } = person(request);
|
|
147
|
-
return id ? store.ownedBot(account, id) : account;
|
|
148
|
-
};
|
|
151
|
+
const target = (request, id) => id ? store.ownedBot(person(request).account, id) : signedIn(request).account;
|
|
149
152
|
router.get(route, ({ request, send }, id) => send(200, { profile: avatars.profile(target(request, id)), maxUploadBytes: avatars.options.maxUploadBytes }));
|
|
150
153
|
router.on('PUT', route, async ({ request, url, send }, id) => {
|
|
151
154
|
const account = target(request, id);
|
package/central/store.mjs
CHANGED
|
@@ -181,11 +181,27 @@ export class CentralStore {
|
|
|
181
181
|
/** The owner changes a Bot's name or setup; the device that runs it picks the change up the next time it reports. */
|
|
182
182
|
updateBot(owner, bot, { displayName: name, ...input }, { serverOrigin } = {}) {
|
|
183
183
|
const checked = this.checkedSettings(owner, input, serverOrigin);
|
|
184
|
-
if (name !== undefined) this.
|
|
184
|
+
if (name !== undefined) this.rename(bot, name);
|
|
185
185
|
this.writeSettings(bot, { ...this.settingsOf(bot), ...checked });
|
|
186
186
|
return this.account(bot.id);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/**
|
|
190
|
+
* A new display name, set by the account itself (a person on the web, a Bot with its own tool) or by a Bot's
|
|
191
|
+
* owner. It is part of the public profile, so chat servers pick it up with the next profile version.
|
|
192
|
+
*/
|
|
193
|
+
rename(account, name) {
|
|
194
|
+
const value = displayName(name, account.username);
|
|
195
|
+
if (value === this.account(account.id).display_name) return this.account(account.id);
|
|
196
|
+
this.db.exec('BEGIN IMMEDIATE');
|
|
197
|
+
try {
|
|
198
|
+
this.db.prepare('UPDATE accounts SET display_name=? WHERE id=?').run(value, account.id);
|
|
199
|
+
this.profileChanged?.(account);
|
|
200
|
+
this.db.exec('COMMIT');
|
|
201
|
+
} catch (error) { this.db.exec('ROLLBACK'); throw error; }
|
|
202
|
+
return this.account(account.id);
|
|
203
|
+
}
|
|
204
|
+
|
|
189
205
|
/** A Bot as its owner manages it: the account, its setup, and what its device last reported about it. */
|
|
190
206
|
managedBot(bot) {
|
|
191
207
|
const settings = this.settingsOf(bot);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--font-family-ui:-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;--font-family-code:ui-monospace, SFMono-Regular, Consolas, monospace;--font-size-xs:.6875rem;--font-size-sm:.75rem;--font-size-md:.875rem;--font-size-lg:1rem;--font-size-xl:1.25rem;--font-size-2xl:1.5rem;--font-weight-regular:400;--font-weight-medium:550;--font-weight-semibold:650;--font-weight-bold:700;--line-height-tight:1.25;--line-height-compact:1.4;--line-height-body:1.55;--text-display:var(--font-weight-bold) var(--font-size-2xl)/var(--line-height-tight) var(--font-family-ui);--text-title:var(--font-weight-semibold) var(--font-size-xl)/var(--line-height-tight) var(--font-family-ui);--text-heading:var(--font-weight-semibold) var(--font-size-lg)/var(--line-height-compact) var(--font-family-ui);--text-message:var(--font-weight-regular) var(--font-size-lg)/var(--line-height-body) var(--font-family-ui);--text-body-strong:var(--font-weight-medium) var(--font-size-md)/var(--line-height-compact) var(--font-family-ui);--text-body:var(--font-weight-regular) var(--font-size-md)/var(--line-height-body) var(--font-family-ui);--text-label:var(--font-weight-semibold) var(--font-size-sm)/var(--line-height-compact) var(--font-family-ui);--text-caption:var(--font-weight-regular) var(--font-size-sm)/var(--line-height-compact) var(--font-family-ui);--text-micro:var(--font-weight-bold) var(--font-size-xs)/var(--line-height-tight) var(--font-family-ui);--text-code:var(--font-weight-regular) var(--font-size-md)/var(--line-height-body) var(--font-family-code);--opacity-disabled:.45;--space-2xs:2px;--space-xs:4px;--space-sm:8px;--space-md:12px;--space-lg:16px;--space-xl:20px;--space-2xl:24px;--space-3xl:32px;--space-4xl:48px;--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-pill:999px;--radius-round:50%;--size-icon-xs:12px;--size-icon-sm:16px;--size-icon:20px;--size-icon-lg:24px;--size-control-sm:32px;--size-control:38px;--size-check:16px;--size-badge:16px;--size-loading-sm:28px;--size-loading:72px;--size-loading-lg:112px;--height-header:49px;--size-avatar:32px;--size-avatar-message:40px;--width-server-rail:72px;--width-channel-sidebar:240px;--width-member-sidebar:240px;--focus-width:2px;--focus-offset:2px;--focus-ring:calc(var(--focus-width) + var(--focus-offset));--motion-fast:.15s;--motion-panel:.18s;--motion-highlight:3s;--z-message-actions:1;--z-header:2;--z-floating:3;--z-backdrop:5;--z-panel:6;--z-navigation:7;--z-suggestions:12;--z-drop-target:20;--z-toast:50;--z-ui-dialog-backdrop:80;--z-ui-dialog:81;--z-ui-popover:90;--color-bg-canvas:#1e1f22;--color-bg-primary:#313338;--color-bg-secondary:#2b2d31;--color-bg-tertiary:#232428;--color-bg-input:#383a40;--color-bg-hover:#35373c;--color-bg-selected:#404249;--color-bg-message-hover:#2e3035;--color-bg-neutral:#4e5058;--color-bg-neutral-hover:#6d6f78;--color-bg-toast:#111214;--color-text-primary:#f2f3f5;--color-text-normal:#dbdee1;--color-text-secondary:#b5bac1;--color-text-muted:#949ba4;--color-text-on-accent:#fff;--color-document-paper:#fff;--color-icon-muted:#80848e;--color-link:#00a8fc;--color-focus:#00a8fc;--color-border-subtle:#3f4147;--color-border-normal:#45474e;--color-border-strong:#53565f;--color-border-header:#26272c;--color-border-divider:#42444a;--color-border-inset:#25262b;--palette-indigo:#5865f2;--palette-blue:#2563eb;--palette-teal:#0f766e;--palette-rose:#be185d;--palette-amber:#b45309;--color-accent:var(--palette-indigo);--color-accent-hover:#4752c4;--color-status-success:#23a559;--color-status-warning:#f0b232;--color-status-danger:#f23f43;--color-danger-action:#da373c;--color-text-danger:#fa777c;--color-text-danger-soft:#f2a9ab;--color-bg-danger:#5b3335;--color-border-danger:#b74348;--color-text-bot:#82c7b7;--color-code-keyword:#ff7b72;--color-code-string:#a5d6ff;--color-code-comment:#8b949e;--color-code-number:#79c0ff;--color-code-title:#d2a8ff;--color-code-attribute:#ffa657;--color-code-added:#7ee787;--color-code-deleted:#ffa198;--color-quote-border:var(--color-bg-neutral);--color-mention-bg:#5865f24d;--color-mention-text:#c9cdfb;--color-mention-message-bg:#f0b2320c;--color-mention-message-hover:#f0b23215;--color-message-highlight:#5865f259;--color-drop-background:#5865f2ed;--color-drop-border:#b8bfff;--color-file-pdf-border:#da686e;--color-file-image:#95baff;--color-file-text:#8ed8b3;--color-file-text-border:#438b68;--color-avatar-human:#9255a5;--color-avatar-bot:#3b8d7b;--color-avatar-alternate:#5865f2;--color-role-default:#99aab5;--color-scrollbar-thumb:#1a1b1e;--color-overlay:#0007;--color-dialog-overlay:#000a;--shadow-header:0 1px 3px #0002;--shadow-actions:0 2px 5px #0004;--shadow-float:0 3px 10px #0003;--shadow-suggestions:0 6px 24px #0006;--shadow-panel:-5px 0 20px #0004;--shadow-navigation:4px 0 20px #0004;--shadow-dialog:0 12px 48px #0007;--shadow-toast:0 3px 20px #0006;--app-top:0px;--app-bottom:0px;--safe-top:env(safe-area-inset-top,0px);--safe-bottom:env(safe-area-inset-bottom,0px);--app-safe-height:calc(100dvh - var(--app-top) - var(--app-bottom) - var(--safe-top) - var(--safe-bottom));font-family:var(--font-family-ui);color:var(--color-text-normal);background:var(--color-bg-canvas);font-synthesis:none}:root[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-bg-canvas:#e3e5e8;--color-bg-primary:#fff;--color-bg-secondary:#f2f3f5;--color-bg-tertiary:#e7e9ec;--color-bg-input:#ebedef;--color-bg-hover:#e7e9ec;--color-bg-selected:#dce0e5;--color-bg-message-hover:#f2f3f5;--color-bg-neutral:#d4d7dc;--color-bg-neutral-hover:#c7ccd4;--color-bg-toast:#313338;--color-text-primary:#060607;--color-text-normal:#313338;--color-text-secondary:#4e5058;--color-text-muted:#5c6069;--color-icon-muted:#6d6f78;--color-link:#0068a8;--color-focus:#0068a8;--color-border-subtle:#e0e2e6;--color-border-normal:#cdd1d7;--color-border-strong:#a7adb8;--color-border-header:#d7dbe0;--color-border-divider:#dce0e5;--color-border-inset:#d7dbe0;--color-status-success:#008642;--color-status-warning:#997000;--color-status-danger:#d72f36;--color-text-danger:#c92d35;--color-text-danger-soft:#9c2026;--color-bg-danger:#fde7e8;--color-border-danger:#c7474e;--color-text-bot:#1d7562;--color-code-keyword:#cf222e;--color-code-string:#0a3069;--color-code-comment:#6e7781;--color-code-number:#0550ae;--color-code-title:#8250df;--color-code-attribute:#953800;--color-code-added:#116329;--color-code-deleted:#82071e;--color-mention-bg:#5865f224;--color-mention-text:#3b48b4;--color-mention-message-bg:#f0b2321a;--color-mention-message-hover:#f0b2322b;--color-message-highlight:#5865f233;--color-file-pdf-border:#b13036;--color-file-image:#3457ab;--color-file-text:#24754d;--color-file-text-border:#438b68;--color-role-default:#6d6f78;--color-scrollbar-thumb:#c4c9d1;--color-overlay:#0003;--color-dialog-overlay:#0006;--shadow-header:0 1px 3px #00000015;--shadow-actions:0 2px 5px #0002;--shadow-float:0 3px 10px #0002;--shadow-suggestions:0 6px 24px #00000026;--shadow-panel:-5px 0 20px #0002;--shadow-navigation:4px 0 20px #0002;--shadow-dialog:0 12px 48px #0003;--shadow-toast:0 3px 20px #0003}:root[data-accent=blue]{--color-accent:var(--palette-blue)}:root[data-accent=teal]{--color-accent:var(--palette-teal)}:root[data-accent=rose]{--color-accent:var(--palette-rose)}:root[data-accent=amber]{--color-accent:var(--palette-amber)}:root[data-accent]:not([data-accent=indigo]){--color-accent-hover:color-mix(in srgb, var(--color-accent) 80%, black);--color-mention-bg:color-mix(in srgb, var(--color-accent) 30%, transparent);--color-mention-text:color-mix(in srgb, var(--color-accent) 30%, white);--color-message-highlight:color-mix(in srgb, var(--color-accent) 35%, transparent);--color-drop-background:color-mix(in srgb, var(--color-accent) 93%, transparent);--color-drop-border:color-mix(in srgb, var(--color-accent) 35%, white);--color-avatar-alternate:var(--color-accent)}:root[data-theme=light][data-accent]:not([data-accent=indigo]){--color-mention-bg:color-mix(in srgb, var(--color-accent) 14%, transparent);--color-mention-text:color-mix(in srgb, var(--color-accent) 80%, black);--color-message-highlight:color-mix(in srgb, var(--color-accent) 20%, transparent)}@media (prefers-reduced-motion:reduce){:root{--motion-fast:0s;--motion-panel:0s;--motion-highlight:0s}}:root[data-keyboard]{--safe-bottom:0px}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:block))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--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-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--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-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--spacing:.25rem;--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.relative{position:relative}.static{position:static}.sticky{position:sticky}.\!container{width:100%!important}@media (min-width:40rem){.\!container{max-width:40rem!important}}@media (min-width:48rem){.\!container{max-width:48rem!important}}@media (min-width:64rem){.\!container{max-width:64rem!important}}@media (min-width:80rem){.\!container{max-width:80rem!important}}@media (min-width:96rem){.\!container{max-width:96rem!important}}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.block{display:block}.contents{display:contents}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.w-full{width:100%}.min-w-0{min-width:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, )}.resize{resize:both}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.border{border-style:var(--tw-border-style);border-width:1px}.whitespace-nowrap{white-space:nowrap}.shadow{--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)}.filter{filter:var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, )}.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))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";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:"<percentage>";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:"<length>";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-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}*{box-sizing:border-box}body{min-width:320px;font:var(--text-body);color:var(--color-text-primary);background:var(--color-bg-primary);margin:0}button,input,textarea{font:inherit}code,pre{font-family:var(--font-family-code);overflow-wrap:anywhere}h1,h2,h3,p,dl{margin:0}:focus-visible{outline:var(--focus-width) solid var(--color-focus);outline-offset:var(--focus-offset)}.admin-layout{background:var(--color-bg-primary);grid-template-columns:248px minmax(0,1fr);min-height:100dvh;display:grid}.admin-sidebar{min-width:0;height:100dvh;padding:var(--space-xl) var(--space-lg) var(--space-lg);border-right:1px solid var(--color-border-subtle);background:var(--color-bg-secondary);flex-direction:column;display:flex;position:sticky;top:0}.admin-brand{align-items:center;gap:var(--space-md);min-width:0;display:flex}.admin-brand-icon,.admin-login-mark{background:var(--color-text-secondary);display:block;-webkit-mask:url(/assets/mark-128-C4ed4p0U.png) 50%/contain no-repeat;mask:url(/assets/mark-128-C4ed4p0U.png) 50%/contain no-repeat}.admin-brand-icon{flex:0 0 36px;width:36px;height:36px}.admin-brand strong,.admin-brand small{line-height:var(--line-height-compact);display:block}.admin-brand strong{font:var(--text-body-strong)}.admin-brand small{font:var(--text-caption);color:var(--color-text-secondary)}.admin-server-name{font:var(--text-caption);min-height:20px;margin:var(--space-lg) var(--space-md) var(--space-xl);color:var(--color-text-muted);overflow-wrap:anywhere;display:block}.admin-sidebar nav{align-content:start;gap:var(--space-xs);min-height:0;display:grid;overflow-y:auto}.admin-nav-button{font:var(--text-body-strong);align-items:center;gap:var(--space-md);width:100%;min-height:38px;padding:0 var(--space-md);border-radius:var(--radius-md);color:var(--color-text-secondary);cursor:pointer;text-align:left;white-space:nowrap;background:0 0;border:0;display:flex}.admin-nav-button svg{flex:none}.admin-nav-button:hover{background:var(--color-bg-hover);color:var(--color-text-primary)}.admin-nav-button[aria-current=page]{background:var(--color-bg-selected);color:var(--color-text-primary);font-weight:var(--font-weight-semibold)}.admin-nav-button[aria-current=page] svg{color:var(--color-accent)}.admin-account{font:var(--text-body);gap:var(--space-xs);min-width:0;padding:var(--space-lg) var(--space-sm) 0;border-top:1px solid var(--color-border-subtle);margin-top:auto;display:grid}.admin-account span{overflow-wrap:anywhere;min-width:0;color:var(--color-text-secondary)}.admin-account .ds-button{justify-self:start}.admin-main{width:min(100%,1440px);min-width:0;padding:var(--space-2xl) var(--space-3xl) var(--space-3xl);background:var(--color-bg-primary);margin:0 auto}.admin-header{justify-content:space-between;align-items:flex-start;gap:var(--space-xl);margin-bottom:var(--space-xl);display:flex}.admin-page-title{min-width:0}.admin-page-title h1{font:var(--text-display);margin:0;line-height:1.3}.admin-preferences{align-items:flex-end;gap:var(--space-sm);flex-wrap:wrap;display:flex}.admin-preferences .admin-field{width:136px}.admin-field{gap:var(--space-sm);min-width:0;display:grid}.admin-field>label{font:var(--text-body-strong);color:var(--color-text-secondary)}.admin-field .ds-input{width:100%}.admin-actions{align-items:center;gap:var(--space-sm);flex-wrap:wrap;display:flex}.admin-policy-bar,.admin-pending-bar{justify-content:space-between;align-items:center;gap:var(--space-lg);min-width:0;margin-bottom:var(--space-xl);padding:var(--space-md) var(--space-lg);border:1px solid var(--color-border-subtle);border-radius:var(--radius-md);background:var(--color-bg-secondary);display:flex}.admin-policy-summary{align-items:center;gap:var(--space-sm) var(--space-lg);flex-wrap:wrap;min-width:0;display:flex}.admin-state{font:var(--text-body-strong);align-items:center;gap:var(--space-sm);color:var(--color-text-secondary);font-weight:var(--font-weight-semibold);white-space:nowrap;display:inline-flex}.admin-state:before,.admin-status-note:before{content:"";border-radius:var(--radius-round);background:currentColor;flex:0 0 6px;width:6px;height:6px;display:inline-block}.admin-state.is-good,.admin-status-note.is-good{color:var(--color-status-success)}.admin-state.is-warning,.admin-status-note.is-warning{color:var(--color-status-warning)}.admin-state.is-muted{color:var(--color-text-muted)}.admin-status-note{font:var(--text-body);align-items:center;gap:var(--space-sm);color:var(--color-text-secondary);white-space:nowrap;display:inline-flex}.admin-policy-bar .admin-actions{justify-content:flex-end}.admin-pending-bar{border-color:var(--color-status-warning)}.admin-pending-bar>span{align-items:center;gap:var(--space-sm);color:var(--color-status-warning);font-weight:var(--font-weight-semibold);display:flex}.admin-readonly-note{font:var(--text-body);margin:calc(-1 * var(--space-md)) 0 var(--space-lg);color:var(--color-text-secondary)}.admin-error,.admin-notice{font:var(--text-body);align-items:flex-start;gap:var(--space-md);margin-bottom:var(--space-lg);padding:var(--space-md) var(--space-lg);border:1px solid var(--color-border-subtle);border-radius:var(--radius-md);background:var(--color-bg-secondary);overflow-wrap:anywhere;display:flex}.admin-error{border-color:var(--color-border-danger);color:var(--color-status-danger)}.admin-error strong{margin-bottom:var(--space-2xs);display:block}.admin-notice{color:var(--color-status-success)}.admin-error svg,.admin-notice svg{flex:none;margin-top:1px}.admin-panel{border:1px solid var(--color-border-subtle);border-radius:var(--radius-md);background:0 0;min-width:0;overflow:hidden}.admin-panel-heading{justify-content:space-between;align-items:flex-start;gap:var(--space-lg);min-width:0;padding:var(--space-lg) var(--space-xl);border-bottom:1px solid var(--color-border-subtle);display:flex}.admin-panel-heading>div{min-width:0}.admin-panel-heading h2{font:var(--text-heading);margin:0;line-height:1.35}.admin-panel-heading p{font:var(--text-body);max-width:70ch;margin-top:var(--space-sm);color:var(--color-text-secondary);line-height:var(--line-height-compact)}.admin-panel-heading>svg{color:var(--color-text-muted);flex:none}.admin-count{font:var(--text-body-strong);min-width:28px;height:28px;padding-inline:var(--space-sm);border-radius:var(--radius-md);background:var(--color-bg-tertiary);color:var(--color-text-secondary);font-weight:var(--font-weight-semibold);flex:none;place-items:center;display:grid}.admin-empty{font:var(--text-body);padding:var(--space-2xl) var(--space-xl);color:var(--color-text-muted)}.admin-section-layout{align-items:start;gap:var(--space-lg);grid-template-columns:minmax(0,1fr) minmax(340px,390px);display:grid}.admin-section-layout.is-single{grid-template-columns:minmax(0,1fr)}.admin-list{min-width:0}.admin-list-row{min-width:0;padding:var(--space-lg) var(--space-xl);border-bottom:1px solid var(--color-border-subtle)}.admin-list-row:last-child{border-bottom:0}.admin-row-top{justify-content:space-between;align-items:flex-start;gap:var(--space-lg);min-width:0;display:flex}.admin-row-identity{gap:var(--space-xs);min-width:0;display:grid}.admin-row-identity strong{font:var(--text-body-strong);font-weight:var(--font-weight-semibold);overflow-wrap:anywhere}.admin-row-identity code,.admin-row-identity span{font:var(--text-code);color:var(--color-text-secondary);overflow-wrap:anywhere;word-break:break-word}.admin-row-top>.admin-state{margin-top:var(--space-2xs);flex:none}.admin-detail-list{gap:var(--space-sm);margin-top:var(--space-md);display:grid}.admin-detail-list>div{font:var(--text-body);gap:var(--space-md);grid-template-columns:minmax(90px,32%) minmax(0,1fr);min-width:0;display:grid}.admin-detail-list dt{color:var(--color-text-muted)}.admin-detail-list dd{overflow-wrap:anywhere;white-space:pre-wrap;min-width:0;margin:0}.admin-row-actions{align-items:center;gap:var(--space-sm);margin-top:var(--space-md);flex-wrap:wrap;display:flex}.admin-remove-trigger{color:var(--color-text-danger)}.admin-remove-trigger:hover:not(:disabled){color:var(--color-text-danger);background:var(--color-bg-danger)}.admin-confirm{font:var(--text-body);gap:var(--space-md);min-width:0;margin-top:var(--space-md);padding:var(--space-md);border:1px solid var(--color-border-danger);border-radius:var(--radius-md);background:var(--color-bg-danger);color:var(--color-text-danger);display:grid}.admin-confirm p{overflow-wrap:anywhere}.admin-confirm code{margin-top:var(--space-xs);color:var(--color-text-primary);display:block}.admin-invite{align-items:end;gap:var(--space-md);margin-top:var(--space-lg);padding-top:var(--space-lg);border-top:1px solid var(--color-border-subtle);grid-template-columns:minmax(0,1fr) auto;display:grid}.admin-invite .admin-field{min-width:0}.admin-editor{flex-direction:column;display:flex}.admin-form-fields{gap:var(--space-lg);padding:var(--space-xl);display:grid}.admin-form-actions{align-items:center;gap:var(--space-sm);padding:var(--space-lg) var(--space-xl);border-top:1px solid var(--color-border-subtle);flex-wrap:wrap;display:flex}.admin-checkbox{font:var(--text-body);align-items:center;gap:var(--space-sm);width:-moz-fit-content;width:fit-content;color:var(--color-text-primary);cursor:pointer;display:flex}.admin-tools{gap:var(--space-md);min-width:0;padding:var(--space-lg) 0 0;border:0;border-top:1px solid var(--color-border-subtle);grid-template-columns:repeat(2,minmax(0,1fr));margin:0;display:grid}.admin-tools legend{font:var(--text-body-strong);color:var(--color-text-secondary);padding:0}.admin-tools label{font:var(--text-body);align-items:center;gap:var(--space-sm);cursor:pointer;min-width:0;display:flex}.admin-hint{font:var(--text-body);color:var(--color-text-secondary)}.admin-metrics{margin-bottom:var(--space-lg);grid-template-columns:repeat(4,minmax(0,1fr));display:grid}.admin-metric{gap:var(--space-sm);min-width:0;padding:var(--space-xl);border-right:1px solid var(--color-border-subtle);display:grid}.admin-metric:last-child{border-right:0}.admin-metric span{font:var(--text-body);color:var(--color-text-secondary)}.admin-metric strong{font:var(--text-display);line-height:1.2}.admin-overview-grid{align-items:start;gap:var(--space-lg);grid-template-columns:minmax(0,1fr) minmax(0,2fr);display:grid}.admin-primary-value{font:var(--text-body-strong);padding:var(--space-xl);font-weight:var(--font-weight-semibold);overflow-wrap:anywhere;display:block}.admin-application-summary{font:var(--text-body);justify-content:space-between;align-items:center;gap:var(--space-md);padding:var(--space-lg) var(--space-xl);flex-wrap:wrap;display:flex}.admin-inline-error{font:var(--text-body);align-items:flex-start;gap:var(--space-sm);margin:0 var(--space-xl) var(--space-lg);color:var(--color-status-danger);overflow-wrap:anywhere;display:flex}.admin-inline-error svg{flex:none}.admin-application-row{gap:var(--space-sm);padding:var(--space-lg) var(--space-xl);border-top:1px solid var(--color-border-subtle);display:grid}.admin-application-row>.admin-inline-error{margin:0}.admin-storage-grid{align-items:start;gap:var(--space-lg);grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.admin-storage-grid .admin-primary-value{padding-bottom:0}.admin-detail-list-wide{padding:var(--space-lg) var(--space-xl)}.admin-supporting-text{font:var(--text-body);padding:var(--space-lg) var(--space-xl);color:var(--color-text-secondary)}.admin-record-detail{font:var(--text-body);justify-content:space-between;gap:var(--space-md);min-width:0;padding:var(--space-md) var(--space-xl);border-bottom:1px solid var(--color-border-subtle);flex-wrap:wrap;display:flex}.admin-record-detail:last-child{border-bottom:0}.admin-record-detail code{min-width:0}.admin-backup-panel{grid-column:1/-1}.admin-backup-panel .ds-button{margin:0 var(--space-xl) var(--space-xl)}.admin-deployment-panel .admin-panel-heading p{max-width:90ch}.admin-settings-grid{grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.admin-settings-group{align-content:start;gap:var(--space-lg);min-width:0;padding:var(--space-xl);display:grid}.admin-settings-group+.admin-settings-group{border-left:1px solid var(--color-border-subtle)}.admin-settings-group h3{font:var(--text-body-strong);color:var(--color-text-primary);font-weight:var(--font-weight-semibold)}.admin-settings-group .ds-input[readonly]{color:var(--color-text-secondary);background:var(--color-bg-tertiary)}.admin-settings-group form{gap:var(--space-lg);display:grid}.admin-muted{color:var(--color-text-secondary);overflow-wrap:anywhere}.admin-listing-status{white-space:normal;align-items:baseline}.admin-server-number{gap:var(--space-xs);color:var(--color-text-secondary);display:grid}.admin-server-number strong,.admin-invite-code{font:var(--text-display);color:var(--color-text-primary);font-family:var(--font-family-code);letter-spacing:.08em}.admin-deployment-panel+.admin-list-panel{margin-top:var(--space-xl)}.admin-audit .admin-list-row{gap:var(--space-sm);display:grid}.admin-audit time,.admin-audit-meta{font:var(--text-body);color:var(--color-text-secondary)}.admin-audit pre{font:var(--text-code);color:var(--color-text-secondary);white-space:pre-wrap;margin:0}.admin-audit>.ds-button{margin:var(--space-lg) var(--space-xl)}.admin-login{min-height:100dvh;padding:var(--space-2xl);place-items:center;display:grid}.admin-login-panel{width:min(100%,440px);padding:var(--space-2xl);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);background:var(--color-bg-primary)}.admin-login-mark{width:40px;height:40px}.admin-login-panel h1{font:var(--text-title);margin:var(--space-md) 0 var(--space-xs)}.admin-login-panel>p{font:var(--text-body);margin-bottom:var(--space-xl);color:var(--color-text-secondary)}.admin-login-panel>.admin-error{margin-top:var(--space-lg);color:var(--color-status-danger)}.admin-login-panel form{gap:var(--space-lg);display:grid}.admin-login-panel form .ds-button{justify-self:start}.admin-login-panel .admin-preferences{margin-top:var(--space-2xl);padding-top:var(--space-lg);border-top:1px solid var(--color-border-subtle)}@media (max-width:1200px){.admin-section-layout{grid-template-columns:minmax(0,1fr)}.admin-overview-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:920px){.admin-layout{grid-template-columns:minmax(0,1fr)}.admin-sidebar{gap:var(--space-sm);height:auto;padding:var(--space-md) var(--space-lg) 0;border-right:0;border-bottom:1px solid var(--color-border-subtle);grid-template-columns:minmax(0,1fr) auto;display:grid;position:static}.admin-brand{grid-area:1/1}.admin-account{border:0;grid-area:1/2;align-items:center;margin:0;padding:0;display:flex}.admin-account span{display:none}.admin-server-name{min-height:0;margin:0 var(--space-sm);grid-area:2/1/auto/-1}.admin-sidebar nav{gap:var(--space-xs);scrollbar-width:thin;grid-area:3/1/auto/-1;max-width:100%;display:flex;overflow:auto hidden}.admin-nav-button{flex:none;width:auto}.admin-main{padding:var(--space-xl) var(--space-lg) var(--space-3xl)}.admin-policy-bar{flex-direction:column;align-items:flex-start}.admin-policy-bar .admin-actions{justify-content:flex-start}}@media (max-width:640px){.admin-header{gap:var(--space-lg);flex-direction:column}.admin-preferences{width:100%}.admin-preferences .admin-field{width:min(42vw,160px)}.admin-overview-grid,.admin-storage-grid,.admin-settings-grid{grid-template-columns:minmax(0,1fr)}.admin-settings-group+.admin-settings-group{border-left:0;border-top:1px solid var(--color-border-subtle)}.admin-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.admin-metric:nth-child(2){border-right:0}.admin-metric:nth-child(-n+2){border-bottom:1px solid var(--color-border-subtle)}.admin-pending-bar{flex-direction:column;align-items:flex-start}}@media (max-width:480px){.admin-main{padding:var(--space-lg) var(--space-md) var(--space-2xl)}.admin-policy-bar,.admin-pending-bar{padding:var(--space-md)}.admin-panel-heading,.admin-list-row,.admin-form-fields,.admin-form-actions,.admin-settings-group{padding:var(--space-lg)}.admin-invite{grid-template-columns:minmax(0,1fr)}.admin-invite .ds-button{justify-self:start}.admin-row-top{gap:var(--space-sm)}.admin-detail-list>div{gap:var(--space-sm);grid-template-columns:minmax(72px,30%) minmax(0,1fr)}}.admin-update-panels{gap:var(--space-lg);min-width:0;display:grid}.admin-update-panels .admin-panel{overflow-wrap:anywhere;min-width:0;padding:var(--space-xl)}.admin-update-panels form{gap:var(--space-lg);display:grid}.admin-update-panels .admin-settings-grid{gap:var(--space-lg)}.admin-update-panels form>button{justify-self:start}.admin-update-release,.admin-update-progress{margin-block:var(--space-lg);padding:var(--space-lg);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg)}.admin-update-progress{gap:var(--space-sm);display:grid}.admin-update-history{gap:var(--space-lg);padding-inline-start:var(--space-2xl);display:grid}.ds-text-display{font:var(--text-display);color:var(--color-text-primary);margin:0}.ds-text-title{font:var(--text-title);color:var(--color-text-primary);margin:0}.ds-text-heading{font:var(--text-heading);color:var(--color-text-primary);margin:0}.ds-text-body-strong{font:var(--text-body-strong);color:var(--color-text-primary);margin:0}.ds-text-body{font:var(--text-body);color:var(--color-text-normal);margin:0}.ds-text-label{font:var(--text-label);color:var(--color-text-secondary);margin:0}.ds-text-caption{font:var(--text-caption);color:var(--color-text-muted);margin:0}.ds-text-code{font:var(--text-code);color:var(--color-text-normal)}.ds-button{min-height:var(--size-control);padding:0 var(--space-lg);border-radius:var(--radius-md);font:var(--text-body-strong);cursor:pointer;border:1px solid #0000}.ds-button-size-sm{min-height:var(--size-control-sm);padding-inline:var(--space-md)}.ds-button-size-icon{width:var(--size-control);min-height:var(--size-control);padding:0}.ds-button svg{width:var(--size-icon-sm);height:var(--size-icon-sm);stroke-width:2px}.ds-button-size-icon svg{width:var(--size-icon);height:var(--size-icon)}.ds-button-default{background:var(--color-accent);color:var(--color-text-on-accent)}.ds-button-default:hover:not(:disabled){background:var(--color-accent-hover)}.ds-button-secondary{background:var(--color-bg-neutral);color:var(--color-text-primary)}.ds-button-secondary:hover:not(:disabled){background:var(--color-bg-neutral-hover)}.ds-button-ghost{color:var(--color-text-secondary);background:0 0}.ds-button-ghost:hover:not(:disabled){background:var(--color-bg-hover);color:var(--color-text-primary)}.ds-button-destructive{background:var(--color-bg-danger);color:var(--color-text-danger)}.ds-button-destructive:hover:not(:disabled){background:var(--color-border-danger);color:var(--color-text-on-accent)}.ds-button:focus-visible,.ds-input:focus-visible,.ds-select-trigger:focus-visible,.ds-chip:focus-visible,.ds-popover-content:focus-visible,.ds-dialog-content:focus-visible,.ds-checkbox:focus-visible,.ds-radio:focus-visible,.ds-color-input:focus-visible{outline:var(--focus-width) solid var(--color-focus);outline-offset:var(--focus-offset)}.ds-button:disabled,.ds-input:disabled{cursor:default;opacity:var(--opacity-disabled)}.ds-input{min-height:var(--size-control);padding:var(--space-sm) var(--space-md);border:1px solid var(--color-border-normal);border-radius:var(--radius-md);background:var(--color-bg-input);color:var(--color-text-primary);font:var(--text-body)}.ds-input::placeholder{color:var(--color-text-muted)}:is(.ds-input[aria-invalid=true],.ds-input:user-invalid){border-color:var(--color-border-danger)}.ds-textarea{min-height:calc(var(--size-control) * 2.5);resize:vertical}.ds-select-trigger{justify-content:space-between;align-items:center;gap:var(--space-sm);width:100%;min-width:0;min-height:var(--size-control);padding:0 var(--space-sm) 0 var(--space-md);border:1px solid var(--color-border-normal);border-radius:var(--radius-md);background:var(--color-bg-input);color:var(--color-text-primary);font:var(--text-body);text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;margin:0;display:flex}.ds-select-trigger:hover:not([data-disabled]){border-color:var(--color-border-strong)}.ds-select-trigger[data-popup-open]{border-color:var(--color-accent)}.ds-select-trigger[data-disabled]{cursor:default;opacity:var(--opacity-disabled)}.ds-select-trigger[aria-invalid=true]{border-color:var(--color-border-danger)}.ds-select-value{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.ds-select-value[data-placeholder]{color:var(--color-text-muted)}.ds-select-icon{color:var(--color-text-secondary);transition:transform var(--motion-fast);flex:none;place-items:center;display:grid}.ds-select-icon svg{width:var(--size-icon-sm);height:var(--size-icon-sm)}.ds-select-trigger[data-popup-open] .ds-select-icon{transform:rotate(180deg)}.ds-select-positioner{z-index:var(--z-ui-popover);outline:none}.ds-select-popup{min-width:var(--anchor-width);max-width:calc(100vw - var(--space-lg));max-height:min(var(--available-height), calc(var(--size-control) * 8));overscroll-behavior:contain;padding:var(--space-xs);border:1px solid var(--color-border-normal);border-radius:var(--radius-md);background:var(--color-bg-primary);color:var(--color-text-normal);box-shadow:var(--shadow-suggestions);outline:none;overflow-y:auto}.ds-select-item{grid-template-columns:minmax(0, 1fr) var(--size-icon-sm);align-items:center;gap:var(--space-sm);min-height:var(--size-control-sm);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-sm);font:var(--text-body);cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;display:grid}.ds-select-item[data-highlighted]{background:var(--color-bg-hover);color:var(--color-text-primary)}.ds-select-item[data-selected]{color:var(--color-text-primary)}.ds-select-item[data-disabled]{cursor:default;opacity:var(--opacity-disabled)}.ds-select-item-text{min-width:0;display:grid}.ds-select-group+.ds-select-group,.ds-select-item+.ds-select-group{margin-top:var(--space-xs);padding-top:var(--space-xs);border-top:1px solid var(--color-border-subtle)}.ds-select-group-label{padding:var(--space-xs) var(--space-sm);font:var(--text-label);color:var(--color-text-muted)}.ds-select-item-description{font:var(--text-caption);color:var(--color-text-muted)}.ds-select-item-indicator{color:var(--color-accent);place-items:center;display:grid}.ds-select-item-indicator svg{width:var(--size-icon-sm);height:var(--size-icon-sm)}.ds-checkbox,.ds-radio{flex:0 0 var(--size-check);width:var(--size-check);height:var(--size-check);border:1px solid var(--color-border-strong);background:var(--color-bg-input);cursor:pointer;vertical-align:middle;place-items:center;margin:0;padding:0;display:inline-grid}.ds-checkbox{border-radius:var(--radius-sm)}.ds-radio{border-radius:var(--radius-round)}.ds-checkbox[data-checked]{border-color:var(--color-accent);background:var(--color-accent)}.ds-checkbox-indicator{color:var(--color-text-on-accent);place-items:center;display:grid}.ds-checkbox-indicator svg{width:var(--size-icon-xs);height:var(--size-icon-xs)}.ds-radio[data-checked]{border-color:var(--color-accent)}.ds-radio-indicator{width:var(--space-sm);height:var(--space-sm);border-radius:var(--radius-round);background:var(--color-accent)}.ds-checkbox[data-disabled],.ds-radio[data-disabled]{opacity:var(--opacity-disabled);cursor:default}.ds-color-input{width:calc(var(--size-control) * 1.4);min-height:var(--size-control);padding:var(--space-xs);border:1px solid var(--color-border-normal);border-radius:var(--radius-md);background:var(--color-bg-input);cursor:pointer}.ds-color-input:disabled{opacity:var(--opacity-disabled);cursor:default}.ds-field{gap:var(--space-sm);border:0;min-width:0;margin:0;padding:0;display:grid}.ds-field>legend{margin-bottom:var(--space-sm);padding:0}.ds-field-label{align-items:baseline;gap:var(--space-xs);font:var(--text-label);color:var(--color-text-secondary);margin:0;display:flex}.ds-field-optional{font:var(--text-caption);color:var(--color-text-muted)}.ds-field-description{font:var(--text-caption);color:var(--color-text-muted);margin:0}.ds-field-error{font:var(--text-caption);color:var(--color-text-danger);margin:0}.ds-field-group{gap:var(--space-xl);min-width:0;display:grid}.ds-field-row{grid-template-columns:repeat(auto-fit, minmax(calc(var(--size-control) * 5), 1fr));gap:var(--space-lg);display:grid}.ds-choice{grid-template-columns:var(--size-check) minmax(0, 1fr);align-items:start;column-gap:var(--space-md);row-gap:var(--space-2xs);cursor:pointer;display:grid}.ds-choice>.ds-checkbox,.ds-choice>.ds-radio{margin-top:var(--space-2xs)}.ds-choice-label{font:var(--text-body-strong);color:var(--color-text-primary)}.ds-choice-description{font:var(--text-caption);color:var(--color-text-muted);grid-column:2;margin:0}.ds-section{gap:var(--space-lg);min-width:0;display:grid}.ds-section+.ds-section{padding-top:var(--space-2xl);border-top:1px solid var(--color-border-divider)}.ds-section-header{justify-content:space-between;align-items:flex-start;gap:var(--space-sm) var(--space-lg);flex-wrap:wrap;display:flex}.ds-section-heading{gap:var(--space-xs);min-width:0;display:grid}.ds-section-title{font:var(--text-heading);color:var(--color-text-primary);margin:0}.ds-section-description{font:var(--text-caption);color:var(--color-text-muted);margin:0}.ds-section-actions{align-items:center;gap:var(--space-sm);flex-wrap:wrap;display:flex}.ds-section-body{gap:var(--space-lg);min-width:0;display:grid}.ds-info-list{border:1px solid var(--color-border-subtle);border-radius:var(--radius-md);background:var(--color-bg-secondary);grid-template-columns:minmax(0,max-content) minmax(0,1fr);margin:0;display:grid}.ds-info-row{display:contents}.ds-info-label,.ds-info-value{padding:var(--space-md) var(--space-lg);margin:0}.ds-info-row+.ds-info-row>.ds-info-label,.ds-info-row+.ds-info-row>.ds-info-value{border-top:1px solid var(--color-border-subtle)}.ds-info-label{font:var(--text-label);color:var(--color-text-secondary);white-space:nowrap}.ds-info-value{align-items:center;gap:var(--space-sm);min-width:0;font:var(--text-body);color:var(--color-text-normal);display:flex}.ds-info-value-text{overflow-wrap:anywhere;flex:auto;min-width:0}.ds-info-value-code{font:var(--text-code)}.ds-info-value .ds-button{flex:none}@media (max-width:520px){.ds-info-list{grid-template-columns:minmax(0,1fr)}.ds-info-label{padding-bottom:0}.ds-info-value{padding-top:var(--space-xs)}.ds-info-row+.ds-info-row>.ds-info-value{border-top:0}}.ds-chip-group{gap:var(--space-sm);flex-wrap:wrap;min-width:0;display:flex}.ds-chip{align-items:center;gap:var(--space-sm);min-height:var(--size-control-sm);padding:0 var(--space-md);border:1px solid var(--color-border-normal);border-radius:var(--radius-pill);color:var(--color-text-secondary);font:var(--text-body-strong);white-space:nowrap;cursor:pointer;transition:background-color var(--motion-fast), color var(--motion-fast), border-color var(--motion-fast);background:0 0;margin:0;display:inline-flex}.ds-chip:hover:not([data-disabled]){background:var(--color-bg-hover);color:var(--color-text-primary)}.ds-chip[data-pressed]{border-color:var(--color-accent);background:var(--color-accent);color:var(--color-text-on-accent)}.ds-chip[data-disabled]{cursor:default;opacity:var(--opacity-disabled)}.ds-chip-count{min-width:var(--size-badge);padding:0 var(--space-xs);border-radius:var(--radius-pill);background:var(--color-bg-neutral);color:var(--color-text-primary);font:var(--text-micro);line-height:var(--size-badge);text-align:center}.ds-chip[data-pressed] .ds-chip-count{background:var(--color-text-on-accent);color:var(--color-accent)}.ds-chip .ds-avatar-slot{margin-left:calc(-1 * var(--space-xs));place-items:center;display:inline-grid}.ds-empty{justify-items:center;gap:var(--space-sm);padding:var(--space-3xl) var(--space-lg);text-align:center;display:grid}.ds-empty-compact{padding:var(--space-xl) var(--space-lg)}.ds-empty-icon{width:calc(var(--size-icon-lg) * 2);height:calc(var(--size-icon-lg) * 2);margin-bottom:var(--space-xs);border-radius:var(--radius-round);background:var(--color-bg-secondary);color:var(--color-text-muted);place-items:center;display:grid}.ds-empty-icon svg{width:var(--size-icon-lg);height:var(--size-icon-lg)}.ds-empty-title{font:var(--text-body-strong);color:var(--color-text-primary);margin:0}.ds-empty-description{max-width:60ch;font:var(--text-caption);color:var(--color-text-muted);margin:0}.ds-empty-action{margin-top:var(--space-sm)}.ds-scroll-area{overscroll-behavior:contain;min-width:0;min-height:0;padding:var(--space-md);scroll-padding-block:var(--space-md);scrollbar-gutter:stable;overflow:hidden auto}.ds-scroll-area::-webkit-scrollbar{width:var(--space-sm);height:var(--space-sm)}.ds-select-popup::-webkit-scrollbar{width:var(--space-sm);height:var(--space-sm)}.ds-scroll-area::-webkit-scrollbar-track{background:0 0}.ds-select-popup::-webkit-scrollbar-track{background:0 0}.ds-scroll-area::-webkit-scrollbar-thumb{border:var(--space-2xs) solid transparent;border-radius:var(--radius-pill);background:var(--color-scrollbar-thumb);background-clip:padding-box}.ds-select-popup::-webkit-scrollbar-thumb{border:var(--space-2xs) solid transparent;border-radius:var(--radius-pill);background:var(--color-scrollbar-thumb);background-clip:padding-box}.ds-scroll-area::-webkit-scrollbar-thumb:hover{background-color:var(--color-bg-neutral-hover)}.ds-select-popup::-webkit-scrollbar-thumb:hover{background-color:var(--color-bg-neutral-hover)}.ds-scroll-area::-webkit-scrollbar-button{display:none}.ds-select-popup::-webkit-scrollbar-button{display:none}.ds-scroll-area::-webkit-scrollbar-corner{background:0 0}.ds-select-popup::-webkit-scrollbar-corner{background:0 0}.ds-popover-positioner{z-index:var(--z-ui-popover);max-width:calc(100vw - var(--space-lg))}.ds-popover-content{max-height:calc(var(--app-safe-height) - var(--space-2xl));overscroll-behavior:contain;border:1px solid var(--color-border-normal);border-radius:var(--radius-lg);background:var(--color-bg-primary);color:var(--color-text-normal);box-shadow:var(--shadow-suggestions);overflow-y:auto}.ds-dialog-backdrop{z-index:var(--z-ui-dialog-backdrop);background:var(--color-dialog-overlay);position:fixed;inset:0}.ds-dialog-content{top:calc(var(--app-top) + var(--safe-top) + var(--app-safe-height) / 2);z-index:var(--z-ui-dialog);max-height:calc(var(--app-safe-height) - var(--space-3xl));overscroll-behavior:contain;border:1px solid var(--color-border-normal);border-radius:var(--radius-lg);background:var(--color-bg-primary);color:var(--color-text-normal);box-shadow:var(--shadow-dialog);position:fixed;left:50%;overflow:hidden;transform:translate(-50%,-50%)}.ds-dialog-content[data-open]{flex-direction:column;display:flex}@media (max-width:480px){.ds-dialog-content{width:calc(100vw - var(--space-lg));max-height:calc(var(--app-safe-height) - var(--space-lg))}}.ds-loading{padding:var(--space-lg);color:var(--color-accent);justify-content:center;align-items:center;display:flex}.ds-loading-sm{vertical-align:middle;padding:0;display:inline-flex}.ds-loading-lg{padding:var(--space-3xl)}.ds-loading-stage{width:var(--size-loading);height:var(--size-loading);animation:.32s cubic-bezier(.34,1.56,.64,1) both ds-loading-in;display:block;position:relative}.ds-loading-sm .ds-loading-stage{width:var(--size-loading-sm);height:var(--size-loading-sm)}.ds-loading-lg .ds-loading-stage{width:var(--size-loading-lg);height:var(--size-loading-lg)}.ds-loading-mark{position:absolute;inset:23%}.ds-loading-whale,.ds-loading-human,.ds-loading-body,.ds-loading-eyes{position:absolute;inset:0}.ds-loading-whale{z-index:1;transform-origin:45.07% 37.97%;animation:3.2s linear infinite ds-loading-whale}.ds-loading-human{transform-origin:65.27% 72.43%;animation:3.2s linear infinite ds-loading-human}.ds-loading-body,.ds-loading-eyes{-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.ds-loading-body{background:currentColor}.ds-loading-eyes{background:var(--color-text-on-accent)}.ds-loading-whale .ds-loading-eyes{transform-origin:48.4% 32.6%;animation:3.2s linear infinite ds-loading-whale-eyes}.ds-loading-human .ds-loading-eyes{transform-origin:66.8% 67.8%;animation:3.2s linear infinite ds-loading-human-eyes}.ds-loading-label{clip:rect(0, 0, 0, 0);white-space:nowrap;width:1px;height:1px;margin:-1px;position:absolute;overflow:hidden}@keyframes ds-loading-in{0%{opacity:0;transform:scale(.4)}to{opacity:1;transform:scale(1)}}@keyframes ds-loading-whale{0%{transform:translate(0%)rotate(0)scale(1)}3.25%{transform:translate(-.05%,-.08%)rotate(.05deg)scale(1)}3.75%{transform:translate(-.39%,-.67%)rotate(.39deg)scale(.98)}4.5%{transform:translate(-1.43%,-2.43%)rotate(1.29deg)scale(.92)}5.25%{transform:translate(-2.89%,-4.93%)rotate(2.11deg)scale(.84)}6%{transform:translate(-4.57%,-7.79%)rotate(2.17deg)scale(.75)}6.5%{transform:translate(-5.7%,-9.72%)rotate(1.57deg)scale(.69)}7%{transform:translate(-6.76%,-11.54%)rotate(.42deg)scale(.63)}7.75%{transform:translate(-8.11%,-13.83%)rotate(-2.11deg)scale(.38,.56)}8.25%{transform:translate(-8.74%,-14.91%)rotate(-4.03deg)scale(.2,.52)}8.75%{transform:translate(-9.08%,-15.5%)rotate(-5.82deg)scale(.04,.5)}9.25%{transform:translate(-9.06%,-15.62%)rotate(-7.2deg)scale(-.12,.5)}9.75%{transform:translate(-8.54%,-15.92%)rotate(-8.2deg)scale(-.27,.5)}10.25%{transform:translate(-7.51%,-16.49%)rotate(-8.81deg)scale(-.42,.5)}10.75%{transform:translate(-5.98%,-17.29%)rotate(-9deg)scale(-.5,.5)}11.25%{transform:translate(-3.96%,-18.27%)rotate(-8.75deg)scale(-.5,.5)}11.75%{transform:translate(-1.46%,-19.34%)rotate(-8.08deg)scale(-.5,.5)}12.5%{transform:translate(3.2%,-20.99%)rotate(-6.36deg)scale(-.5,.5)}13.25%{transform:translate(8.89%,-22.43%)rotate(-3.96deg)scale(-.5,.5)}14%{transform:translate(15.52%,-23.35%)rotate(-1.13deg)scale(-.5,.5)}14.75%{transform:translate(22.95%,-23.47%)rotate(1.83deg)scale(-.5,.5)}15.25%{transform:translate(28.23%,-22.98%)rotate(3.7deg)scale(-.5,.5)}15.75%{transform:translate(33.7%,-21.95%)rotate(5.4deg)scale(-.5,.5)}16.25%{transform:translate(39.25%,-20.32%)rotate(6.84deg)scale(-.5,.5)}16.75%{transform:translate(44.78%,-18.07%)rotate(7.95deg)scale(-.5,.5)}17.25%{transform:translate(50.19%,-15.18%)rotate(8.68deg)scale(-.5,.5)}17.75%{transform:translate(55.37%,-11.66%)rotate(8.99deg)scale(-.5,.5)}18.25%{transform:translate(60.22%,-7.52%)rotate(8.87deg)scale(-.5,.5)}18.75%{transform:translate(64.63%,-2.83%)rotate(8.31deg)scale(-.5,.5)}19.25%{transform:translate(68.51%,2.37%)rotate(7.36deg)scale(-.5,.5)}19.75%{transform:translate(71.8%,7.98%)rotate(6.06deg)scale(-.5,.5)}20.25%{transform:translate(74.44%,13.91%)rotate(4.46deg)scale(-.5,.5)}20.75%{transform:translate(76.38%,20.05%)rotate(2.65deg)scale(-.35,.5)}21.25%{transform:translate(77.62%,26.3%)rotate(.71deg)scale(-.19,.5)}21.75%{transform:translate(78.17%,32.54%)rotate(-1.27deg)scale(-.04,.5)}22.25%{transform:translate(78.05%,38.68%)rotate(-3.18deg)scale(.12,.5)}22.75%{transform:translate(77.31%,44.6%)rotate(-4.94deg)scale(.27,.5)}23.25%{transform:translate(76.01%,50.24%)rotate(-6.46deg)scale(.42,.5)}24%{transform:translate(73.21%,57.99%)rotate(-8.14deg)scale(.5)}24.75%{transform:translate(69.65%,64.76%)rotate(-8.95deg)scale(.5)}25.25%{transform:translate(67.03%,68.68%)rotate(-8.95deg)scale(.5)}25.75%{transform:translate(64.31%,72.12%)rotate(-8.51deg)scale(.5)}26.25%{transform:translate(61.6%,75.08%)rotate(-7.67deg)scale(.5)}27%{transform:translate(57.75%,78.66%)rotate(-5.74deg)scale(.5)}27.75%{transform:translate(54.4%,81.3%)rotate(-3.18deg)scale(.5)}28.5%{transform:translate(51.79%,83.1%)rotate(-.28deg)scale(.5)}29.25%{transform:translate(50.12%,84.15%)rotate(2.65deg)scale(.5)}29.75%{transform:translate(49.6%,84.46%)rotate(4.46deg)scale(.5)}30.25%{transform:translate(49.49%,84.42%)rotate(6.04deg)scale(.5)}30.75%{transform:translate(49.15%,83.85%)rotate(7.22deg)scale(.51)}31.25%{transform:translate(48.52%,82.77%)rotate(7.88deg)scale(.52)}31.75%{transform:translate(47.63%,81.26%)rotate(7.99deg)scale(.53)}32.25%{transform:translate(46.53%,79.37%)rotate(7.59deg)scale(.55)}33%{transform:translate(44.55%,75.99%)rotate(6.2deg)scale(.58)}34.25%{transform:translate(40.72%,69.46%)rotate(2.93deg)scale(.64)}35.25%{transform:translate(37.53%,64.03%)rotate(.69deg)scale(.69)}36%{transform:translate(35.29%,60.2%)rotate(-.29deg)scale(.72)}36.75%{transform:translate(33.3%,56.82%)rotate(-.62deg)scale(.75)}37.5%{transform:translate(31.72%,54.12%)rotate(-.47deg)scale(.78)}38.25%{transform:translate(30.68%,52.34%)rotate(-.16deg)scale(.79)}38.75%{transform:translate(30.34%,51.76%)rotate(-.02deg)scale(.8)}53.25%{transform:translate(30.3%,51.68%)rotate(-.05deg)scale(.8)}54.25%{transform:translate(30.19%,51.5%)rotate(-.96deg)scale(.77)}55.25%{transform:translate(29.99%,51.17%)rotate(-2.11deg)scale(.71)}56%{transform:translate(29.82%,50.86%)rotate(-2.17deg)scale(.65)}56.5%{transform:translate(29.7%,50.66%)rotate(-1.57deg)scale(.61)}57%{transform:translate(29.58%,50.47%)rotate(-.42deg)scale(.58)}57.75%{transform:translate(29.44%,50.22%)rotate(2.11deg)scale(.53)}58.75%{transform:translate(29.34%,50.05%)rotate(5.82deg)scale(.5)}59.5%{transform:translate(29.07%,50.19%)rotate(7.75deg)scale(.5)}60%{transform:translate(28.29%,50.63%)rotate(8.56deg)scale(.5)}60.5%{transform:translate(27.01%,51.33%)rotate(8.96deg)scale(.5)}61%{transform:translate(25.24%,52.22%)rotate(8.93deg)scale(.5)}61.75%{transform:translate(21.66%,53.8%)rotate(8.08deg)scale(.5)}62.5%{transform:translate(17%,55.45%)rotate(6.36deg)scale(.5)}63.25%{transform:translate(11.31%,56.89%)rotate(3.96deg)scale(.5)}64%{transform:translate(4.68%,57.81%)rotate(1.13deg)scale(.5)}64.75%{transform:translate(-2.75%,57.93%)rotate(-1.83deg)scale(.5)}65.25%{transform:translate(-8.03%,57.44%)rotate(-3.7deg)scale(.5)}65.75%{transform:translate(-13.5%,56.41%)rotate(-5.4deg)scale(.5)}66.25%{transform:translate(-19.05%,54.78%)rotate(-6.84deg)scale(.5)}66.75%{transform:translate(-24.58%,52.53%)rotate(-7.95deg)scale(.5)}67.25%{transform:translate(-29.99%,49.64%)rotate(-8.68deg)scale(.5)}67.75%{transform:translate(-35.17%,46.12%)rotate(-8.99deg)scale(.5)}68.25%{transform:translate(-40.02%,41.98%)rotate(-8.87deg)scale(.5)}68.75%{transform:translate(-44.43%,37.29%)rotate(-8.31deg)scale(.5)}69.25%{transform:translate(-48.31%,32.09%)rotate(-7.36deg)scale(.5)}69.75%{transform:translate(-51.6%,26.48%)rotate(-6.06deg)scale(.5)}70.25%{transform:translate(-54.24%,20.55%)rotate(-4.46deg)scale(.5)}70.75%{transform:translate(-56.18%,14.41%)rotate(-2.65deg)scale(.35,.5)}71.25%{transform:translate(-57.42%,8.16%)rotate(-.71deg)scale(.19,.5)}71.75%{transform:translate(-57.97%,1.92%)rotate(1.27deg)scale(.04,.5)}72.25%{transform:translate(-57.85%,-4.22%)rotate(3.18deg)scale(-.12,.5)}72.75%{transform:translate(-57.11%,-10.14%)rotate(4.94deg)scale(-.27,.5)}73.25%{transform:translate(-55.81%,-15.78%)rotate(6.46deg)scale(-.42,.5)}74%{transform:translate(-53.01%,-23.53%)rotate(8.14deg)scale(-.5,.5)}74.75%{transform:translate(-49.45%,-30.3%)rotate(8.95deg)scale(-.5,.5)}75.25%{transform:translate(-46.83%,-34.22%)rotate(8.95deg)scale(-.5,.5)}75.75%{transform:translate(-44.11%,-37.66%)rotate(8.51deg)scale(-.5,.5)}76.25%{transform:translate(-41.4%,-40.62%)rotate(7.67deg)scale(-.5,.5)}77%{transform:translate(-37.55%,-44.2%)rotate(5.74deg)scale(-.35,.5)}77.75%{transform:translate(-34.2%,-46.84%)rotate(3.18deg)scale(-.12,.5)}78.5%{transform:translate(-31.59%,-48.64%)rotate(.28deg)scale(.12,.5)}79.25%{transform:translate(-29.92%,-49.69%)rotate(-2.65deg)scale(.35,.5)}79.75%{transform:translate(-29.4%,-50%)rotate(-4.46deg)scale(.5)}80.25%{transform:translate(-29.26%,-49.92%)rotate(-6.04deg)scale(.5)}80.75%{transform:translate(-28.75%,-49.05%)rotate(-7.22deg)scale(.51)}81.25%{transform:translate(-27.79%,-47.41%)rotate(-7.88deg)scale(.53)}81.75%{transform:translate(-26.44%,-45.1%)rotate(-7.99deg)scale(.55)}82.25%{transform:translate(-24.75%,-42.22%)rotate(-7.59deg)scale(.58)}83%{transform:translate(-21.73%,-37.06%)rotate(-6.2deg)scale(.63)}84%{transform:translate(-17.1%,-29.17%)rotate(-3.59deg)scale(.71)}85%{transform:translate(-12.23%,-20.87%)rotate(-1.16deg)scale(.79)}85.75%{transform:translate(-8.71%,-14.86%)rotate(.04deg)scale(.85)}86.5%{transform:translate(-5.53%,-9.44%)rotate(.58deg)scale(.91)}87%{transform:translate(-3.7%,-6.31%)rotate(.61deg)scale(.94)}87.5%{transform:translate(-2.17%,-3.71%)rotate(.47deg)scale(.96)}88%{transform:translate(-1.01%,-1.72%)rotate(.26deg)scale(.98)}88.5%{transform:translate(-.26%,-.45%)rotate(.08deg)scale(1)}89%{transform:translate(0%)rotate(0)scale(1)}to{transform:translate(0%)rotate(0)scale(1)}}@keyframes ds-loading-whale-eyes{0%{transform:translate(2.53%,4.31%)scale(1)}3.75%{transform:translate(2.58%,4.41%)scale(1)}5.5%{transform:translate(3.11%,5.31%)scale(1)}6.25%{transform:translate(3.52%,6%)scale(1)}8.75%{transform:translate(3.54%,6.04%)scale(1)}9%{transform:translate(-3.54%,6.04%)scale(1)}11%{transform:translate(-3.05%,6.3%)scale(1)}13%{transform:translate(-1.61%,6.81%)scale(1)}15.25%{transform:translate(.97%,6.93%)scale(1)}17%{transform:translate(3.3%,6.18%)scale(1)}18.75%{transform:translate(5.36%,4.5%)scale(1)}20.25%{transform:translate(6.55%,2.48%)scale(1)}21.75%{transform:translate(7%,.23%)scale(1)}22%{transform:translate(-7%,-.14%)scale(1)}23.75%{transform:translate(-6.52%,-2.54%)scale(1)}25.75%{transform:translate(-5.32%,-4.55%)scale(1)}27.75%{transform:translate(-4.13%,-5.65%)scale(1)}29.75%{transform:translate(-3.55%,-6.03%)scale(1)}36%{transform:translate(-3.5%,-5.97%)scale(1)}38.75%{transform:translate(-3.16%,-5.4%)scale(1)}45%{transform:translate(-3.16%,-5.39%)scale(1)}46%{transform:translate(-3.16%,-5.39%)scaleY(.14)}46.75%{transform:translate(-3.16%,-5.39%)scaleY(.27)}47.5%{transform:translate(-3.16%,-5.39%)scale(1)}53.75%{transform:translate(-3.21%,-5.48%)scale(1)}55.5%{transform:translate(-3.54%,-6.04%)scale(1)}60%{transform:translate(-3.41%,-6.11%)scale(1)}61.75%{transform:translate(-2.61%,-6.49%)scale(1)}63.75%{transform:translate(-.84%,-6.95%)scale(1)}65.75%{transform:translate(1.63%,-6.81%)scale(1)}67.5%{transform:translate(3.94%,-5.79%)scale(1)}69.25%{transform:translate(5.83%,-3.87%)scale(1)}70.75%{transform:translate(6.78%,-1.74%)scale(1)}71.75%{transform:translate(7%,-.23%)scale(1)}72%{transform:translate(-7%,.14%)scale(1)}73.75%{transform:translate(-6.52%,2.54%)scale(1)}75.75%{transform:translate(-5.32%,4.55%)scale(1)}77.75%{transform:translate(-4.13%,5.65%)scale(1)}78%{transform:translate(-4.01%,5.74%)scale(1)}78.25%{transform:translate(3.91%,5.81%)scale(1)}80.25%{transform:translate(3.54%,6.04%)scale(1)}84.25%{transform:translate(3.47%,5.92%)scale(1)}86.5%{transform:translate(2.79%,4.76%)scale(1)}89%{transform:translate(2.53%,4.31%)scale(1)}95%{transform:translate(2.53%,4.31%)scale(1)}96%{transform:translate(2.53%,4.31%)scaleY(.14)}96.75%{transform:translate(2.53%,4.31%)scaleY(.27)}97.5%{transform:translate(2.53%,4.31%)scale(1)}to{transform:translate(2.53%,4.31%)scale(1)}}@keyframes ds-loading-human{0%{opacity:1;transform:translate(0%)scale(1)}25.75%{opacity:1;transform:translate(0%)scale(1.1,.89)}28%{opacity:1;transform:translate(0%)scale(1)}29.75%{opacity:.13;transform:translate(0%)scale(.13)}30%{opacity:0;transform:translate(-20.2%,-34.46%)scale(0)}30.5%{opacity:1;transform:translate(-20.2%,-34.46%)scale(.42)}31.75%{opacity:1;transform:translate(-20.2%,-34.46%)scale(1.12)}48%{opacity:1;transform:translate(-20.2%,-34.46%)scale(1)}75.75%{opacity:1;transform:translate(-20.2%,-34.46%)scale(1.1,.89)}78%{opacity:1;transform:translate(-20.2%,-34.46%)scale(1)}79.75%{opacity:.13;transform:translate(-20.2%,-34.46%)scale(.13)}80%{opacity:0;transform:translate(0%)scale(0)}80.5%{opacity:1;transform:translate(0%)scale(.42)}81.5%{opacity:1;transform:translate(0%)scale(1.06)}84.25%{opacity:1;transform:translate(0%)scale(.99)}to{opacity:1;transform:translate(0%)scale(1)}}@keyframes ds-loading-human-eyes{0%{transform:translate(-2.53%,-4.31%)scale(1)}10%{transform:translate(-2.44%,-4.36%)scale(1)}12.25%{transform:translate(-1.61%,-4.73%)scale(1)}14.75%{transform:translate(.24%,-4.99%)scale(1)}16.75%{transform:translate(2.12%,-4.53%)scale(1)}18.75%{transform:translate(3.83%,-3.21%)scale(1)}20.75%{transform:translate(4.84%,-1.24%)scale(1)}22.5%{transform:translate(4.96%,.62%)scale(1)}25%{transform:translate(4.15%,2.79%)scale(1)}27.25%{transform:translate(3.14%,3.9%)scale(1)}29.75%{transform:translate(2.53%,4.31%)scale(1)}38%{transform:translate(2.53%,4.31%)scale(1)}39%{transform:translate(2.53%,4.31%)scaleY(.14)}39.75%{transform:translate(2.53%,4.31%)scaleY(.27)}40.5%{transform:translate(2.53%,4.31%)scale(1)}60%{transform:translate(2.44%,4.36%)scale(1)}62.25%{transform:translate(1.61%,4.73%)scale(1)}64.75%{transform:translate(-.24%,4.99%)scale(1)}66.75%{transform:translate(-2.12%,4.53%)scale(1)}68.75%{transform:translate(-3.83%,3.21%)scale(1)}70.75%{transform:translate(-4.84%,1.24%)scale(1)}72.5%{transform:translate(-4.96%,-.62%)scale(1)}75%{transform:translate(-4.15%,-2.79%)scale(1)}77.25%{transform:translate(-3.14%,-3.9%)scale(1)}79.75%{transform:translate(-2.53%,-4.31%)scale(1)}88%{transform:translate(-2.53%,-4.31%)scale(1)}89%{transform:translate(-2.53%,-4.31%)scaleY(.14)}89.75%{transform:translate(-2.53%,-4.31%)scaleY(.27)}90.5%{transform:translate(-2.53%,-4.31%)scale(1)}to{transform:translate(-2.53%,-4.31%)scale(1)}}@media (prefers-reduced-motion:reduce){.ds-loading-stage,.ds-loading-whale,.ds-loading-human,.ds-loading-eyes{animation:none}}
|