nx-sk 0.28.0 → 0.29.0
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/CHANGELOG.md +22 -0
- package/assets/nx-sk/references/15-special-fields.md +25 -1
- package/dist/core/fields/behaviors/shortcut.js +41 -0
- package/dist/core/fields/registry.js +2 -0
- package/dist/core/fields/seal/index.js +1 -0
- package/dist/core/fields.js +33 -0
- package/dist/shared/blockLayout.js +3 -2
- package/dist/shared/fields/types.js +2 -1
- package/dist/shared/shortcut.js +196 -0
- package/dist/web/public/assets/{files-DDDN-GbJ.js → files-BYzv5zCz.js} +1 -1
- package/dist/web/public/assets/{index-DDEmDb0K.css → index-Cj8L_sM4.css} +1 -1
- package/dist/web/public/assets/{index-BpUTnBjj.js → index-j1zkCXw9.js} +2 -2
- package/dist/web/public/assets/view---Z6RLHC.js +46 -0
- package/dist/web/public/assets/{view-C6I3Vf9F.js → view-D1AQI5qu.js} +1 -1
- package/dist/web/public/assets/{view-TJPSoVht.js → view-Do1fJzAq.js} +1 -1
- package/dist/web/public/assets/{view-DOpzNX1y.js → view-WSb7GgJa.js} +1 -1
- package/dist/web/public/assets/{view-ClLIweOz.js → view-ZBbb0ceb.js} +1 -1
- package/dist/web/public/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/public/assets/view-BgznDLss.js +0 -46
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
本文件格式参考 [Keep a Changelog](https://keepachangelog.com/),中文正文。
|
|
4
4
|
|
|
5
|
+
## 0.29.0 (2026-11-10)
|
|
6
|
+
|
|
7
|
+
**新增 `shortcut` 字段与 `peek` 三态外壳;`source` 迁到同一外壳。三种形态、焦点与 reduced-motion 均经真实浏览器走查(57 项断言全过,控制台/网络 0 错误)。**
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **快捷键字段(`shortcut`)**:值按「组 → 条目 → 按键」三层存;折叠条只报组数/条数,
|
|
12
|
+
点「详细」打开键位面板(默认全屏,可切侧边/居中)——左侧分组目录、右侧说明表、底部键盘图,
|
|
13
|
+
录入时直接按组合键、悬停条目点亮对应键。`combo` 存 `KeyboardEvent.code`,写入接受
|
|
14
|
+
`"Ctrl+R"` / `["Ctrl","R"]` / `[{code,label}]` 三种写法。
|
|
15
|
+
- **`peek` 三态外壳**:同一份内容可在 side / center / fullpage 之间切换。center/fullpage 补遮罩、
|
|
16
|
+
`aria-modal`、焦点陷阱、Esc 关闭与 reduced-motion;side 保持原右侧栏的宽度、断点与动画不变。
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- 原始资料(`source`)迁移到 `peek` 外壳:默认仍是原来的右侧栏,视觉与交互不变,新增三态切换按钮。
|
|
21
|
+
|
|
22
|
+
### 说明
|
|
23
|
+
|
|
24
|
+
- 走查修掉三处问题:三态选择器与 JSX 类名不一致导致面板尺寸/定位全部失效;点遮罩关闭后焦点掉到
|
|
25
|
+
`body`(现先 `preventDefault` 再关);窄栏下快捷键表格逐字换行、全屏下表格与键盘图之间留大片空洞。
|
|
26
|
+
|
|
5
27
|
## 0.28.0 (2026-11-10)
|
|
6
28
|
|
|
7
29
|
**全量 TypeScript 化:后端与前端源码统一为 `.ts/.tsx`;字段与模块改为注册表驱动。对外行为不变。**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
大多数字段的值是标量(一行字、一个数字、一个日期)。这一篇只讲**值不是标量**的字段,
|
|
4
4
|
以及它们各自的规则、写入时的体检、空值与默认值怎么处理:
|
|
5
5
|
|
|
6
|
-
`table`(表格)· `entrylist`(结构清单)· `md`(图文)· `file`(附件)· `source`(原始资料袋)· `secret`(密文)
|
|
6
|
+
`table`(表格)· `entrylist`(结构清单)· `md`(图文)· `file`(附件)· `source`(原始资料袋)· `shortcut`(快捷键)· `secret`(密文)
|
|
7
7
|
|
|
8
8
|
> 为什么要单独一篇:这些字段的**值形状**决定了怎么读、怎么写、怎么在面板上编。
|
|
9
9
|
> 把它们当普通字符串塞进去,最常见的后果不是报错,而是「存进去了但面板看不见」——
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
| `md` | 一段 markdown 字符串 | — | 图文编辑器(Ctrl+V 贴图) | `entry get`(图片还原成路径) |
|
|
19
19
|
| `file` | `[附件id, …]` | 字段字典的 `kind` / `maxItems` | 附件选择器(上传 / 从库里选) | `entry get`(附件名 + 物理路径) |
|
|
20
20
|
| `source` | `[{id, kind, name, text\|fileId\|url, addedAt, …}]` | 内置(每个栏目自带一个) | 底部折叠条 → 右侧侧边栏 | `source get` |
|
|
21
|
+
| `shortcut` | `[{id, name, shortcuts:[{id, combo:[{code,label}], description, condition?}]}]` | 数据自己(组 → 条目 → 按键) | 折叠条只报组数/条数;`详细` 打开键位面板(默认全屏,可切侧边/居中) | `entry get` |
|
|
21
22
|
| `secret` | 一个字符串(落盘是密文) | — | 输入框 | `key get` / `entry get` |
|
|
22
23
|
|
|
23
24
|
共同点:**写入即校验**(不合法就整条拒绝,不会存半条)、**空值有明确语义**、
|
|
@@ -190,6 +191,29 @@
|
|
|
190
191
|
普通文字本来就是合法 markdown,老数据不用迁移。
|
|
191
192
|
- 不计完整度(`fill: optional`);袋里是明文,**敏感内容不要进袋**。
|
|
192
193
|
|
|
194
|
+
## `shortcut` 快捷键
|
|
195
|
+
|
|
196
|
+
- 值 = **组 → 条目 → 按键**三层:`[{ name, shortcuts: [{ combo, description, condition? }] }]`。
|
|
197
|
+
组是目录,条目是「这条快捷键做什么」,`condition` 写生效范围(不写 = 全局)。
|
|
198
|
+
- `combo` 存 `KeyboardEvent.code`(物理键位),不是 `key`——换键盘布局/输入法不会让快捷键错位。
|
|
199
|
+
- 写入时三种写法等价(都会归一成同一种形状):
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# 1) 最省事的字符串
|
|
203
|
+
nx-sk entry add --section demo --title 快捷键示例 \
|
|
204
|
+
--set 'keys=[{"name":"全局","shortcuts":[{"combo":"Ctrl+Shift+R","description":"刷新"}]}]'
|
|
205
|
+
|
|
206
|
+
# 2) 键名数组
|
|
207
|
+
--set 'keys=[{"name":"列表","shortcuts":[{"combo":["J"],"description":"下一条"}]}]'
|
|
208
|
+
|
|
209
|
+
# 3) 面板存下来的按键对象(精确控制左右修饰键)
|
|
210
|
+
--set 'keys=[{"name":"全局","shortcuts":[{"combo":[{"code":"ControlLeft","label":"Ctrl"},{"code":"KeyK","label":"K"}],"description":"命令面板"}]}]'
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
- 每条必须有 `description`;键位认不出(例如 `Ctrl+?`)会整条拒绝并指出是第几组第几条。
|
|
214
|
+
- 面板里点 `详细` 打开键位图:悬停条目点亮对应键;`新增` 后直接按组合键即可录入。
|
|
215
|
+
- 不能当表格列(`cell: false`);不引用附件,没有子密文。
|
|
216
|
+
|
|
193
217
|
## `secret` 密文
|
|
194
218
|
|
|
195
219
|
- 值是一个字符串,落盘 AES-256-GCM 密文;读出来默认原文,`--mask` 打码。
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { badInput } from "../../errors.js";
|
|
2
|
+
import { normalizeShortcutGroups, comboLabel } from "../../../shared/shortcut.js";
|
|
3
|
+
import { identityRemap, identityReveal, isSensitiveDef, noRefs, noSubFields } from "./common.js";
|
|
4
|
+
/**
|
|
5
|
+
* 快捷键(分组):值 = [{ name, shortcuts: [{ combo, description, condition? }] }]。
|
|
6
|
+
*
|
|
7
|
+
* 为什么不做成普通 `tags`:快捷键是「组 → 条目 → 按键」三层,条目要带说明和生效条件,
|
|
8
|
+
* 面板要按组渲染、点击条目高亮键盘图;字符串数组撑不起这些。
|
|
9
|
+
* combo 支持 `"Ctrl+R"`、`["Ctrl","R"]` 和 `[{code,label}]` 三种写法(见 shared/shortcut.ts)。
|
|
10
|
+
*/
|
|
11
|
+
export const shortcutBehavior = {
|
|
12
|
+
cell: false,
|
|
13
|
+
normalizeDef: () => { },
|
|
14
|
+
coerce(def, raw) {
|
|
15
|
+
try {
|
|
16
|
+
return normalizeShortcutGroups(raw);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
throw badInput(`字段「${def.label}」的快捷键有问题:${e.message}`);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
reveal: identityReveal,
|
|
23
|
+
refs: noRefs,
|
|
24
|
+
remap: identityRemap,
|
|
25
|
+
format: (_def, value) => {
|
|
26
|
+
if (!Array.isArray(value) || !value.length)
|
|
27
|
+
return null;
|
|
28
|
+
const lines = [];
|
|
29
|
+
for (const group of value) {
|
|
30
|
+
const shortcuts = Array.isArray(group?.shortcuts) ? group.shortcuts : [];
|
|
31
|
+
lines.push(`[${group?.name || '未命名'}] ${shortcuts.length} 条`);
|
|
32
|
+
for (const s of shortcuts) {
|
|
33
|
+
const condition = s?.condition ? `(${s.condition})` : '';
|
|
34
|
+
lines.push(` ${comboLabel(s?.combo)} ${s?.description || ''}${condition}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return lines;
|
|
38
|
+
},
|
|
39
|
+
sensitive: isSensitiveDef,
|
|
40
|
+
subFields: noSubFields,
|
|
41
|
+
};
|
|
@@ -20,6 +20,7 @@ import { tagsBehavior } from "./behaviors/tags.js";
|
|
|
20
20
|
import { entrylistBehavior } from "./behaviors/entrylist.js";
|
|
21
21
|
import { tableBehavior } from "./behaviors/table.js";
|
|
22
22
|
import { sourceBehavior } from "./behaviors/source.js";
|
|
23
|
+
import { shortcutBehavior } from "./behaviors/shortcut.js";
|
|
23
24
|
import { secretBehavior } from "./behaviors/secret.js";
|
|
24
25
|
import { fileBehavior } from "./behaviors/file.js";
|
|
25
26
|
import { mdBehavior } from "./behaviors/md.js";
|
|
@@ -35,6 +36,7 @@ export const FIELD_BEHAVIOR = {
|
|
|
35
36
|
entrylist: entrylistBehavior,
|
|
36
37
|
table: tableBehavior,
|
|
37
38
|
source: sourceBehavior,
|
|
39
|
+
shortcut: shortcutBehavior,
|
|
38
40
|
secret: secretBehavior,
|
|
39
41
|
file: fileBehavior,
|
|
40
42
|
md: mdBehavior,
|
package/dist/core/fields.js
CHANGED
|
@@ -366,6 +366,7 @@ const DEMO_FIELDS = [
|
|
|
366
366
|
}),
|
|
367
367
|
// —— 富内容 ——
|
|
368
368
|
f('note', '图文笔记', 'md', 'rich', { hint: 'markdown 正文:标题 / 列表 / 代码块都能渲染;直接 Ctrl+V 贴截图(自动进附件库);待办勾选就是改正文本身' }),
|
|
369
|
+
f('keys', '快捷键', 'shortcut', 'rich', { hint: '快捷键:按组整理(组 → 条目 → 按键)。折叠条只报组数/条数,点「详细」打开键位面板;录入时直接按组合键,键位图会点亮' }),
|
|
369
370
|
f('docs', '附件', 'file', 'rich', { kind: 'doc', hint: '附件字段:值是附件 id 的列表(不是路径)。在这里直接上传,或从附件库选' }),
|
|
370
371
|
f('apikey', '密钥', 'secret', 'rich', { hint: '密文字段:值以 AES-256-GCM 落盘,读出来默认原文,--mask 才打码' }),
|
|
371
372
|
];
|
|
@@ -606,6 +607,38 @@ export function seedEntries(at) {
|
|
|
606
607
|
'- [ ] 截图直接 Ctrl+V 粘进来(自动进附件库,正文里插入引用)',
|
|
607
608
|
'- [ ] 勾选待办就是改正文本身,没有第二份勾选状态',
|
|
608
609
|
].join('\n'),
|
|
610
|
+
keys: [
|
|
611
|
+
{
|
|
612
|
+
id: 'g1',
|
|
613
|
+
name: '全局',
|
|
614
|
+
shortcuts: [
|
|
615
|
+
{
|
|
616
|
+
id: 's1-1',
|
|
617
|
+
combo: [{ code: 'ControlLeft', label: 'Ctrl', isModifier: true }, { code: 'KeyK', label: 'K' }],
|
|
618
|
+
description: '打开命令面板',
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
id: 's1-2',
|
|
622
|
+
combo: [
|
|
623
|
+
{ code: 'ControlLeft', label: 'Ctrl', isModifier: true },
|
|
624
|
+
{ code: 'ShiftLeft', label: 'Shift', isModifier: true },
|
|
625
|
+
{ code: 'KeyF', label: 'F' },
|
|
626
|
+
],
|
|
627
|
+
description: '全库搜索',
|
|
628
|
+
condition: '工作台',
|
|
629
|
+
},
|
|
630
|
+
],
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
id: 'g2',
|
|
634
|
+
name: '列表',
|
|
635
|
+
shortcuts: [
|
|
636
|
+
{ id: 's2-1', combo: [{ code: 'KeyJ', label: 'J' }], description: '下一条' },
|
|
637
|
+
{ id: 's2-2', combo: [{ code: 'KeyK', label: 'K' }], description: '上一条' },
|
|
638
|
+
{ id: 's2-3', combo: [{ code: 'Enter', label: 'Enter' }], description: '打开当前条目' },
|
|
639
|
+
],
|
|
640
|
+
},
|
|
641
|
+
],
|
|
609
642
|
};
|
|
610
643
|
return [{
|
|
611
644
|
id: newId('e'),
|
|
@@ -42,11 +42,11 @@ export function blockHeightPx(rows) {
|
|
|
42
42
|
return h * ROW_HEIGHT + (h - 1) * MARGIN[1];
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* 这些类型的字段**天然要一整行**:多行文本、附件、图文、清单、表格、资料袋、快捷键——
|
|
46
46
|
* 压成半列只会让内容挤成一条缝。其余(单行输入 / 下拉 / 日期 / 勾选)默认半列,
|
|
47
47
|
* 两个并排刚好,也才有「把单列变成多列」的余地。
|
|
48
48
|
*/
|
|
49
|
-
const WIDE_TYPES = new Set(['textarea', 'file', 'md', 'entrylist', 'table', 'source']);
|
|
49
|
+
const WIDE_TYPES = new Set(['textarea', 'file', 'md', 'entrylist', 'table', 'source', 'shortcut']);
|
|
50
50
|
/**
|
|
51
51
|
* 各类型的**默认最小高度(px)**——不是「固定高度」:内容比它高就按内容长(见
|
|
52
52
|
* web 端 blockBoard 的测量逻辑),删掉内容再缩回这个高度。所以这里估的是
|
|
@@ -67,6 +67,7 @@ const DEFAULT_PX = {
|
|
|
67
67
|
entrylist: 150,
|
|
68
68
|
table: 200,
|
|
69
69
|
source: 90,
|
|
70
|
+
shortcut: 90,
|
|
70
71
|
};
|
|
71
72
|
const DEFAULT_H = Object.fromEntries(Object.entries(DEFAULT_PX).map(([type, px]) => [type, rowsForPx(px)]));
|
|
72
73
|
const clampInt = (v, lo, hi, def) => {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/** 字段类型清单。**顺序是可见行为的一部分**(bootstrap 原样下发,面板下拉框照此排序)。 */
|
|
11
11
|
export const FIELD_TYPES = [
|
|
12
12
|
'text', 'textarea', 'number', 'date', 'month', 'bool', 'select', 'tags',
|
|
13
|
-
'entrylist', 'table', 'source', 'secret', 'file', 'md',
|
|
13
|
+
'entrylist', 'table', 'source', 'secret', 'file', 'md', 'shortcut',
|
|
14
14
|
];
|
|
15
15
|
/**
|
|
16
16
|
* 类型的人读标签 —— 只用于**面板下拉框**。
|
|
@@ -30,6 +30,7 @@ export const FIELD_TYPE_LABELS = {
|
|
|
30
30
|
entrylist: '结构清单(变长行)',
|
|
31
31
|
table: '表格(勾选/下拉/计算)',
|
|
32
32
|
source: '原始资料(乱入后整理)',
|
|
33
|
+
shortcut: '快捷键(分组)',
|
|
33
34
|
secret: '密文',
|
|
34
35
|
file: '附件',
|
|
35
36
|
md: '图文(可贴图)',
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const MODIFIERS = {
|
|
2
|
+
ctrl: { code: 'ControlLeft', label: 'Ctrl' },
|
|
3
|
+
control: { code: 'ControlLeft', label: 'Ctrl' },
|
|
4
|
+
shift: { code: 'ShiftLeft', label: 'Shift' },
|
|
5
|
+
alt: { code: 'AltLeft', label: 'Alt' },
|
|
6
|
+
option: { code: 'AltLeft', label: 'Alt' },
|
|
7
|
+
opt: { code: 'AltLeft', label: 'Alt' },
|
|
8
|
+
meta: { code: 'MetaLeft', label: 'Meta' },
|
|
9
|
+
cmd: { code: 'MetaLeft', label: 'Meta' },
|
|
10
|
+
command: { code: 'MetaLeft', label: 'Meta' },
|
|
11
|
+
win: { code: 'MetaLeft', label: 'Meta' },
|
|
12
|
+
super: { code: 'MetaLeft', label: 'Meta' },
|
|
13
|
+
};
|
|
14
|
+
/** 常用键的中文/口语别名 → KeyboardEvent.code。 */
|
|
15
|
+
const KEY_ALIASES = {
|
|
16
|
+
esc: 'Escape', escape: 'Escape',
|
|
17
|
+
enter: 'Enter', return: 'Enter',
|
|
18
|
+
space: 'Space', spacebar: 'Space',
|
|
19
|
+
tab: 'Tab',
|
|
20
|
+
backspace: 'Backspace', back: 'Backspace',
|
|
21
|
+
delete: 'Delete', del: 'Delete',
|
|
22
|
+
insert: 'Insert', ins: 'Insert',
|
|
23
|
+
home: 'Home', end: 'End',
|
|
24
|
+
pageup: 'PageUp', pgup: 'PageUp',
|
|
25
|
+
pagedown: 'PageDown', pgdn: 'PageDown', pgdown: 'PageDown',
|
|
26
|
+
up: 'ArrowUp', arrowup: 'ArrowUp',
|
|
27
|
+
down: 'ArrowDown', arrowdown: 'ArrowDown',
|
|
28
|
+
left: 'ArrowLeft', arrowleft: 'ArrowLeft',
|
|
29
|
+
right: 'ArrowRight', arrowright: 'ArrowRight',
|
|
30
|
+
comma: 'Comma', period: 'Period', dot: 'Period',
|
|
31
|
+
slash: 'Slash', backslash: 'Backslash',
|
|
32
|
+
semicolon: 'Semicolon', quote: 'Quote',
|
|
33
|
+
bracketleft: 'BracketLeft', bracketright: 'BracketRight',
|
|
34
|
+
minus: 'Minus', equal: 'Equal', backquote: 'Backquote',
|
|
35
|
+
capslock: 'CapsLock', contextmenu: 'ContextMenu',
|
|
36
|
+
};
|
|
37
|
+
const MODIFIER_ORDER = ['ControlLeft', 'ControlRight', 'ShiftLeft', 'ShiftRight', 'AltLeft', 'AltRight', 'MetaLeft', 'MetaRight'];
|
|
38
|
+
export function isModifierCode(code) {
|
|
39
|
+
return MODIFIER_ORDER.includes(code);
|
|
40
|
+
}
|
|
41
|
+
/** 把一个 code 变成展示名(KeyR → R,Digit1 → 1,NumpadAdd → Num +)。 */
|
|
42
|
+
export function labelOfCode(code) {
|
|
43
|
+
if (/^Key[A-Z]$/.test(code))
|
|
44
|
+
return code.slice(3);
|
|
45
|
+
if (/^Digit\d$/.test(code))
|
|
46
|
+
return code.slice(5);
|
|
47
|
+
if (/^Numpad/.test(code)) {
|
|
48
|
+
const tail = code.slice(6);
|
|
49
|
+
return tail ? `Num ${tail}` : 'Num';
|
|
50
|
+
}
|
|
51
|
+
if (/^F\d{1,2}$/.test(code))
|
|
52
|
+
return code;
|
|
53
|
+
for (const m of Object.values(MODIFIERS))
|
|
54
|
+
if (m.code === code)
|
|
55
|
+
return m.label;
|
|
56
|
+
const alias = Object.entries(KEY_ALIASES).find(([, v]) => v === code);
|
|
57
|
+
if (alias)
|
|
58
|
+
return alias[0].replace(/^./, (c) => c.toUpperCase());
|
|
59
|
+
return code;
|
|
60
|
+
}
|
|
61
|
+
function strokeFromToken(token) {
|
|
62
|
+
const raw = token.trim();
|
|
63
|
+
if (!raw)
|
|
64
|
+
throw new Error('组合键里有空键位');
|
|
65
|
+
const lower = raw.toLowerCase();
|
|
66
|
+
const mod = MODIFIERS[lower];
|
|
67
|
+
if (mod)
|
|
68
|
+
return { ...mod, isModifier: true };
|
|
69
|
+
const aliased = KEY_ALIASES[lower];
|
|
70
|
+
if (aliased)
|
|
71
|
+
return { code: aliased, label: labelOfCode(aliased) };
|
|
72
|
+
if (/^[a-z]$/.test(lower))
|
|
73
|
+
return { code: `Key${lower.toUpperCase()}`, label: lower.toUpperCase() };
|
|
74
|
+
if (/^\d$/.test(lower))
|
|
75
|
+
return { code: `Digit${lower}`, label: lower };
|
|
76
|
+
if (/^f\d{1,2}$/.test(lower))
|
|
77
|
+
return { code: lower.toUpperCase(), label: lower.toUpperCase() };
|
|
78
|
+
// 已经写成 code 的(KeyR / ArrowUp / Numpad1 …)原样收下
|
|
79
|
+
if (/^(Key|Digit|Numpad|Arrow|F\d)[A-Za-z0-9]+$/.test(raw)) {
|
|
80
|
+
return { code: raw, label: labelOfCode(raw) };
|
|
81
|
+
}
|
|
82
|
+
throw new Error(`认不出键位「${raw}」`);
|
|
83
|
+
}
|
|
84
|
+
function sortCombo(strokes) {
|
|
85
|
+
const rank = (s) => {
|
|
86
|
+
const i = MODIFIER_ORDER.indexOf(s.code);
|
|
87
|
+
return i >= 0 ? i : MODIFIER_ORDER.length;
|
|
88
|
+
};
|
|
89
|
+
return [...strokes].sort((a, b) => rank(a) - rank(b));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 接受三种写法,统一成 stroke 数组:
|
|
93
|
+
* - `"Ctrl+Shift+R"`(CLI --set 最省事)
|
|
94
|
+
* - `["Ctrl", "R"]`
|
|
95
|
+
* - `[{ code: "KeyR", label: "R" }, ...]`(面板存下来的形态)
|
|
96
|
+
*/
|
|
97
|
+
export function parseCombo(raw) {
|
|
98
|
+
if (raw === null || raw === undefined)
|
|
99
|
+
throw new Error('缺少 combo(组合键)');
|
|
100
|
+
let tokens;
|
|
101
|
+
if (typeof raw === 'string') {
|
|
102
|
+
tokens = raw.split('+');
|
|
103
|
+
}
|
|
104
|
+
else if (Array.isArray(raw)) {
|
|
105
|
+
tokens = raw;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
tokens = [raw];
|
|
109
|
+
}
|
|
110
|
+
const strokes = tokens.map((token) => {
|
|
111
|
+
if (typeof token === 'string')
|
|
112
|
+
return strokeFromToken(token);
|
|
113
|
+
if (!token || typeof token !== 'object')
|
|
114
|
+
throw new Error('combo 里有一项不是字符串或按键对象');
|
|
115
|
+
const code = String(token.code || '').trim();
|
|
116
|
+
if (!code)
|
|
117
|
+
throw new Error('combo 里有一项缺少 code');
|
|
118
|
+
const label = String(token.label || '').trim() || labelOfCode(code);
|
|
119
|
+
const isModifier = token.isModifier ?? isModifierCode(code);
|
|
120
|
+
return { code, label, ...(isModifier ? { isModifier: true } : {}) };
|
|
121
|
+
});
|
|
122
|
+
if (!strokes.length)
|
|
123
|
+
throw new Error('combo 不能为空');
|
|
124
|
+
const codes = strokes.map((s) => s.code);
|
|
125
|
+
if (new Set(codes).size !== codes.length)
|
|
126
|
+
throw new Error('combo 里有重复键位');
|
|
127
|
+
return sortCombo(strokes);
|
|
128
|
+
}
|
|
129
|
+
/** `Ctrl+Shift+R` 这种给人看的写法。 */
|
|
130
|
+
export function comboLabel(combo) {
|
|
131
|
+
if (!Array.isArray(combo) || !combo.length)
|
|
132
|
+
return '';
|
|
133
|
+
return combo.map((s) => String(s?.label || s?.code || '')).filter(Boolean).join('+');
|
|
134
|
+
}
|
|
135
|
+
function normalizeItem(raw, groupIndex, itemIndex) {
|
|
136
|
+
if (!raw || typeof raw !== 'object') {
|
|
137
|
+
throw new Error(`第 ${groupIndex + 1} 组第 ${itemIndex + 1} 条不是对象`);
|
|
138
|
+
}
|
|
139
|
+
const combo = parseCombo(raw.combo ?? raw.keys);
|
|
140
|
+
const description = String(raw.description ?? raw.desc ?? '').trim();
|
|
141
|
+
if (!description) {
|
|
142
|
+
throw new Error(`第 ${groupIndex + 1} 组第 ${itemIndex + 1} 条缺少 description(写清这条快捷键做什么)`);
|
|
143
|
+
}
|
|
144
|
+
const condition = String(raw.condition ?? '').trim();
|
|
145
|
+
const id = typeof raw.id === 'string' && raw.id.trim() ? raw.id.trim() : `s${groupIndex + 1}-${itemIndex + 1}`;
|
|
146
|
+
const createdAt = Number.isFinite(raw.createdAt) ? Number(raw.createdAt) : undefined;
|
|
147
|
+
return {
|
|
148
|
+
id,
|
|
149
|
+
combo,
|
|
150
|
+
description,
|
|
151
|
+
...(condition ? { condition } : {}),
|
|
152
|
+
...(createdAt ? { createdAt } : {}),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* 值的归一:接受数组、`{ groups: [...] }`、JSON 字符串。
|
|
157
|
+
* 错误信息带「第几组第几条」,CLI 直接能看懂该改哪里。
|
|
158
|
+
*/
|
|
159
|
+
export function normalizeShortcutGroups(raw) {
|
|
160
|
+
if (raw === null || raw === undefined)
|
|
161
|
+
return [];
|
|
162
|
+
let data = raw;
|
|
163
|
+
if (typeof data === 'string') {
|
|
164
|
+
const text = data.trim();
|
|
165
|
+
if (!text)
|
|
166
|
+
return [];
|
|
167
|
+
try {
|
|
168
|
+
data = JSON.parse(text);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
throw new Error('需要一个 JSON 数组,每项形如 { "name": "全局", "shortcuts": [{ "combo": "Ctrl+R", "description": "刷新" }] }');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
let groupsRaw = data;
|
|
175
|
+
if (!Array.isArray(data) && data && typeof data === 'object' && Array.isArray(data.groups)) {
|
|
176
|
+
groupsRaw = data.groups;
|
|
177
|
+
}
|
|
178
|
+
if (!Array.isArray(groupsRaw)) {
|
|
179
|
+
throw new Error('需要一个数组:[{ "name": "全局", "shortcuts": [...] }]');
|
|
180
|
+
}
|
|
181
|
+
const groups = [];
|
|
182
|
+
groupsRaw.forEach((g, gi) => {
|
|
183
|
+
if (!g || typeof g !== 'object')
|
|
184
|
+
throw new Error(`第 ${gi + 1} 组不是对象`);
|
|
185
|
+
const name = String(g.name ?? g.title ?? '').trim();
|
|
186
|
+
if (!name)
|
|
187
|
+
throw new Error(`第 ${gi + 1} 组缺少 name`);
|
|
188
|
+
const itemsRaw = Array.isArray(g.shortcuts) ? g.shortcuts : (Array.isArray(g.items) ? g.items : null);
|
|
189
|
+
if (!itemsRaw)
|
|
190
|
+
throw new Error(`组「${name}」缺少 shortcuts 数组`);
|
|
191
|
+
const shortcuts = itemsRaw.map((it, si) => normalizeItem(it, gi, si));
|
|
192
|
+
const id = typeof g.id === 'string' && g.id.trim() ? g.id.trim() : `g${gi + 1}`;
|
|
193
|
+
groups.push({ id, name, shortcuts });
|
|
194
|
+
});
|
|
195
|
+
return groups;
|
|
196
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as l}from"./index-
|
|
1
|
+
import{a as l}from"./index-j1zkCXw9.js";let n=null,o=0;const u=1500;function c(t=!1){return!t&&n&&Date.now()-o<u||(o=Date.now(),n=l("/api/files").then(e=>e).catch(e=>{throw n=null,e})),n}function d(){return n=null,c(!0)}function h(t,e){const a=Array.isArray(t)?t:[],r=(Array.isArray(e)?e:[]).filter(Boolean);if(!r.length)return a;const s=new Set(r.map(i=>i.id));return[...r,...a.filter(i=>!s.has(i.id))]}function m(t){return new Promise((e,a)=>{const r=new FileReader;r.onload=()=>e(r.result),r.onerror=()=>a(new Error("读取文件失败")),r.readAsDataURL(t)})}export{m as f,c as l,h as m,d as r};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--ink: #14161a;--paper: #fff;--soft: #f5f6f7;--soft-2: #ebedf0;--mid: #8b9096;--danger: #b3261e;--line: rgba(20, 22, 26, .085);--line-strong: rgba(20, 22, 26, .14);--border: 1px solid var(--line);--row-h: 28px;--btn-h: 32px;--fs-core: 12px;--radius-btn: 8px;--radius-box: 10px;--hover: rgba(20, 22, 26, .028);--shadow-relief: -1px -1px 2px rgba(255, 255, 255, .85), 2px 2px 6px rgba(20, 22, 26, .07);--shadow-relief-press: inset 1px 1px 2px rgba(20, 22, 26, .1), inset -1px -1px 2px rgba(255, 255, 255, .7);--shadow-relief-inset: inset 1px 1px 2px rgba(20, 22, 26, .06), inset -1px -1px 2px rgba(255, 255, 255, .9);--shadow-float: 0 6px 24px rgba(20, 22, 26, .12), 0 1px 2px rgba(20, 22, 26, .06)}*{box-sizing:border-box}html,body,#root{height:100%}body{margin:0;background:var(--paper);color:var(--ink);font-family:system-ui,-apple-system,Segoe UI,Microsoft YaHei,sans-serif;font-size:var(--fs-core);line-height:1.5;-webkit-font-smoothing:antialiased}.mono,code,.path,.cli-cmd{font-family:ui-monospace,Consolas,Courier New,monospace}.muted{color:var(--mid)}.bad{color:var(--danger)}.nowrap{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pad{padding:10px 14px}.rowgap{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.grow{flex:1;min-width:0}.right{margin-left:auto}.app{display:flex;flex-direction:column;height:100%;min-height:0}header.top{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 14px;border-bottom:var(--border);flex-shrink:0}header.top .brand{font-size:15px;font-weight:700;letter-spacing:.2px;line-height:1;display:inline-flex;align-items:center;gap:8px}header.top .brand img{width:22px;height:22px;border-radius:6px;display:block}header.top .tagline{color:var(--mid);font-size:11px}header.top .ver{font-size:10px;color:var(--mid);background:var(--soft);border:var(--border);border-radius:999px;padding:1px 8px;line-height:1.7}header.top .store{display:inline-flex;align-items:center;gap:6px;min-width:0;font-size:11px;color:var(--mid)}header.top .store .store-label{color:var(--mid)}header.top .store .copyable{max-width:30ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nav.tabs{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:6px 14px;border-bottom:var(--border);flex-shrink:0}.tabs-sep{width:1px;height:18px;background:var(--soft-2);margin:0 4px}.tab-group{position:relative;display:inline-flex}.tab-group .caret{width:0;height:0;margin-left:1px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid var(--mid)}.tab-group .tab.active .caret{border-top-color:var(--ink)}.tab-group .caret{transition:transform .12s ease}.tab-group .tab[aria-expanded=true] .caret{border-top-color:var(--ink);transform:rotate(180deg)}@media(prefers-reduced-motion:reduce){.tab-group .caret{transition:none}}.tab-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:40;min-width:172px;padding:4px;display:flex;flex-direction:column;gap:2px;background:var(--paper);border:var(--border);border-radius:var(--radius-btn);box-shadow:var(--shadow-float)}.tab-menu:before{content:"";position:absolute;left:0;right:0;top:-5px;height:5px}.tab-menu-row{display:flex;align-items:center;gap:10px;width:100%;height:var(--row-h);padding:0 8px;border:0;border-radius:6px;background:none;color:var(--ink);font:inherit;font-size:var(--fs-core);text-align:left;cursor:pointer}.tab-menu-row:hover{background:var(--soft)}.tab-menu-row.current{font-weight:600}.tab-menu-row .count{color:var(--mid);font-size:10px;font-variant-numeric:tabular-nums}main.body{flex:1;min-height:0;overflow:auto}.tab{font:inherit;font-size:var(--fs-core);height:var(--btn-h);padding:0 12px;border:0;border-radius:var(--radius-btn);background:transparent;color:var(--mid);cursor:pointer;display:inline-flex;align-items:center;gap:7px;transition:background .12s,color .12s}.tab:hover{background:var(--soft);color:var(--ink)}.tab .count{color:var(--mid);font-size:10px;font-variant-numeric:tabular-nums}.tab.active{background:var(--soft);color:var(--ink);font-weight:600}.btn{font:inherit;font-size:var(--fs-core);cursor:pointer;height:var(--btn-h);padding:0 12px;border:0;border-radius:var(--radius-btn);background:var(--ink);color:var(--paper);display:inline-flex;align-items:center;gap:4px;transition:background .12s,transform .08s,opacity .12s}.btn:hover:not(:disabled){background:#2b2f36}.btn:active:not(:disabled){transform:translateY(1px)}.btn:disabled{background:var(--soft);color:var(--mid);cursor:not-allowed}.btn.ghost{background:transparent;color:var(--ink)}.btn.ghost:hover:not(:disabled){background:var(--soft)}.btn.danger{background:var(--danger);color:#fff}.btn.small{height:22px;padding:0 8px;font-size:11px;border-radius:6px}input,select,textarea{font:inherit;font-size:var(--fs-core);color:var(--ink);background:var(--soft);border:1px solid transparent;border-radius:8px;padding:0 8px;transition:background .12s,border-color .12s}input,select{height:var(--row-h)}textarea{padding:5px 8px;resize:vertical;min-height:56px;line-height:1.5}input:hover,select:hover,textarea:hover{background:var(--soft-2)}input:focus,select:focus,textarea:focus{outline:none;background:var(--paper);border-color:var(--line-strong);box-shadow:none}label.inline{display:inline-flex;align-items:center;gap:6px}.card{border-bottom:var(--border)}.card:last-child{border-bottom:0}.card>.colhead{display:flex;align-items:center;gap:8px;height:var(--row-h);padding:0 14px;border-bottom:var(--border);font-size:13px;font-weight:600}.card>.colbody{padding:0}.row{display:flex;align-items:center;gap:8px;min-height:var(--row-h);padding:0 14px;border-bottom:var(--border);font-size:var(--fs-core);transition:background .12s}.row:hover{background:var(--soft)}.row:last-child{border-bottom:0}.row .name{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row .desc{color:var(--mid);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row .acts{margin-left:auto;display:flex;align-items:center;gap:6px;flex-shrink:0}.row.selectable{cursor:pointer}.row.selected{background:var(--soft);box-shadow:inset 2px 0 0 var(--ink)}.tag{display:inline-flex;align-items:center;height:22px;padding:0 7px;border-radius:999px;background:var(--soft);color:var(--mid);font-size:11px;white-space:nowrap}.tag.strong{background:var(--ink);color:var(--paper)}.tag.bad{background:#fbeae9;color:var(--danger)}.copyable{cursor:copy;border-radius:4px;padding:0 3px}.copyable:hover{background:var(--soft)}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:0 14px}.field{border-bottom:var(--border);padding:5px 0;min-width:0}.field>.flabel{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--mid)}.field>.flabel .fkey{font-family:ui-monospace,Consolas,monospace;font-size:10px;color:var(--soft-2)}.field>.fctrl{margin-top:3px}.field input,.field select,.field textarea{width:100%}.field.wide{grid-column:1 / -1}.group-title{display:flex;align-items:center;gap:8px;height:var(--row-h);padding:0 14px;border-bottom:var(--border);background:var(--soft);font-size:11px;color:var(--mid);letter-spacing:.5px}.board{padding-bottom:6px}.board-bar{display:flex;align-items:center;gap:8px;padding:0 14px 8px;font-size:11px;color:var(--mid)}.board-tip{min-width:0}.board-bar .right{opacity:.35;transition:opacity .12s}.board:hover .board-bar .right{opacity:1}.panel{margin-bottom:6px}.panel-head{display:flex;align-items:center;gap:4px;min-height:28px;padding:0 8px;border-radius:8px;font-size:11px;color:var(--mid);cursor:grab;-webkit-user-select:none;user-select:none;transition:background .12s}.panel-head:hover{background:var(--soft)}.panel-head:active{cursor:grabbing}.panel-grip{color:var(--mid);opacity:.45;transition:opacity .12s}.panel-head:hover .panel-grip{opacity:1}.panel-head .panel-title{color:var(--ink);font-weight:600;font-size:12px;letter-spacing:.2px}.panel-count{color:var(--mid);font-size:10px;font-variant-numeric:tabular-nums}.panel-acts{opacity:0;transition:opacity .12s}.panel:hover .panel-acts,.panel:focus-within .panel-acts{opacity:1}.panel-toggle{border:0;background:none;padding:0 2px;color:var(--soft-2);font-size:11px;cursor:pointer}.panel:hover .panel-toggle{color:var(--mid)}.panel-toggle:hover{color:var(--ink)}.panel.dragging{opacity:.5}.panel.drop-before{box-shadow:inset 0 2px 0 var(--ink)}.panel.drop-after{box-shadow:inset 0 -2px 0 var(--ink)}.panel-body{padding:0 6px}.blk-grid{min-height:4px}.blk-cell{height:100%}.blk-cell.dragging{opacity:.45}.blk-cell.drop-before{box-shadow:inset 0 2px 0 var(--ink)}.blk-cell.drop-after{box-shadow:inset 0 -2px 0 var(--ink)}.blk{display:flex;flex-direction:column;min-width:0;height:100%;padding:0 4px;border-radius:var(--radius-box);overflow:hidden}.blk-head{display:flex;align-items:center;gap:6px;min-height:26px;padding:0 4px;border-radius:8px;font-size:11px;color:var(--mid);cursor:grab;-webkit-user-select:none;user-select:none;transition:background .12s}.blk-head:hover{background:var(--soft)}.blk-head:active{cursor:grabbing}.blk-label{color:var(--mid)}.blk-head:hover .blk-label{color:var(--ink)}.blk-key{margin-left:auto;font-size:10px;color:var(--soft-2);opacity:0;transition:opacity .12s}.blk-head:hover .blk-key{opacity:1}.blk-grip{color:var(--mid);opacity:.45;transition:opacity .12s}.blk-head:hover .blk-grip{opacity:1}.blk-body{flex:1;min-height:0;font-size:13px}.blk-body input,.blk-body select,.blk-body textarea{width:100%;font-size:13px}.react-grid-item.react-draggable-dragging .blk,.react-grid-item.resizing .blk{background:var(--paper);box-shadow:var(--shadow-float)}.react-grid-item.react-grid-placeholder{background:var(--soft-2);border-radius:var(--radius-box);opacity:.5}.react-grid-item>.react-resizable-handle:after{right:2px;bottom:50%;width:2px;height:14px;margin-bottom:-7px;border:0;border-radius:2px;background:var(--line-strong)}.react-grid-item>.react-resizable-handle.react-resizable-handle-w:after{left:2px;right:auto}.entry-title{display:flex;align-items:baseline;gap:8px;padding-bottom:6px}.entry-title-label{color:var(--mid);font-size:11px;flex-shrink:0}.entry-title-input{flex:1;min-width:0;height:32px;padding:0 6px;font-size:16px;font-weight:600;background:transparent;border-color:transparent;border-radius:8px}.entry-title-input:hover{background:var(--soft)}.entry-title-input:focus{background:var(--paper);border-color:var(--line-strong)}.quick-add{padding:0 14px 8px;font-size:11px;color:var(--mid)}.quick-add>summary{list-style:none;width:fit-content;padding:2px 4px;border-radius:6px;cursor:pointer}.quick-add>summary::-webkit-details-marker{display:none}.quick-add>summary:hover{color:var(--ink);background:var(--soft)}.quick-add[open]>summary{margin-bottom:6px}.cli-hint{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 14px;color:var(--mid);font-size:11px;border-top:var(--border)}.cli-hint-label{margin-right:4px}.cli-hint-sep{color:var(--soft-2)}.cli-cmd{color:var(--ink)}.toasts{position:fixed;right:14px;bottom:14px;display:flex;flex-direction:column;gap:6px;z-index:70}.toast{background:var(--ink);color:var(--paper);padding:7px 12px;border-radius:8px;font-size:var(--fs-core);box-shadow:var(--shadow-float);max-width:420px}.toast.bad{background:var(--danger)}.mask{position:fixed;top:0;right:0;bottom:0;left:0;background:#14161a47;display:flex;align-items:center;justify-content:center;z-index:50;padding:20px}.dialog{background:var(--paper);border-radius:8px;min-width:320px;max-width:min(880px,92vw);max-height:86vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 10px 40px #14161a2e}.dialog-title{display:flex;align-items:center;gap:8px;height:var(--row-h);padding:0 14px;border-bottom:var(--border);font-size:13px;font-weight:600;flex-shrink:0}.dialog-body{padding:10px 14px;overflow:auto;min-height:0}.dialog-foot{display:flex;gap:8px;justify-content:flex-end;padding:8px 14px;border-top:var(--border);flex-shrink:0}pre.block{margin:0;padding:10px 14px;background:var(--soft);border-radius:8px;font-family:ui-monospace,Consolas,monospace;font-size:11px;line-height:1.55;white-space:pre-wrap;word-break:break-word;max-height:60vh;overflow:auto}.hint{color:var(--mid);font-size:11px}.stack{display:flex;flex-direction:column;gap:10px}.toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.cols{display:flex;gap:14px;align-items:flex-start;padding:0 14px 14px}.col{flex:1;min-width:0}.desc{color:var(--mid)}.cols>.col>.card{border:var(--border);border-radius:4px}.files-page{min-height:100%;position:relative}.files-page.drag-over{outline:2px dashed var(--ink);outline-offset:-8px;background:var(--soft)}.tab.small{height:22px;padding:0 8px;font-size:11px;border-radius:6px}.file-filters{padding-top:4px;padding-bottom:4px}.drop-hint{margin:0 14px;padding:18px;text-align:center;border:1px dashed var(--ink);border-radius:8px;background:var(--paper);font-weight:600}.file-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px}.file-card{display:flex;flex-direction:column;border:var(--border);border-radius:8px;overflow:hidden;background:var(--paper)}.file-thumb{display:flex;align-items:center;justify-content:center;height:120px;background:var(--soft);border-bottom:var(--border)}.file-thumb img{max-width:100%;max-height:100%;object-fit:contain}.ext-badge{font-size:22px;font-weight:700;letter-spacing:1px;color:var(--mid);font-family:ui-monospace,Consolas,monospace}.file-meta{padding:8px 10px 4px;display:flex;flex-direction:column;gap:4px}a.file-name{color:var(--ink);font-weight:600;text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}a.file-name:hover{text-decoration:underline}.file-acts{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:6px 10px 8px;margin-top:auto}.btn.ghost.danger-ghost{color:var(--danger)}.file-picker{display:flex;flex-direction:column;gap:4px}.file-picker.drag{outline:2px dashed var(--ink);outline-offset:-4px;background:var(--soft)}.file-picker .file-pick-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.file-preview{display:flex;align-items:center;gap:8px;border:var(--border);border-radius:6px;padding:4px 8px;background:var(--soft)}.file-preview img{width:40px;height:40px;object-fit:cover;border-radius:4px;border:var(--border);background:#fff}.file-preview .file-preview-name{color:var(--ink);text-decoration:none;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-preview .file-preview-name:hover{text-decoration:underline}.file-pick-panel{border:var(--border);border-radius:8px;background:var(--paper);overflow:hidden}.file-pick-search{display:flex;align-items:center;gap:6px;padding:6px 8px;border-bottom:var(--border);background:var(--soft)}.file-pick-search input{flex:1;min-width:0}.file-pick-list{max-height:260px;overflow:auto}.file-pick-item{display:flex;align-items:center;gap:8px;width:100%;padding:4px 8px;border:0;border-bottom:var(--border);background:var(--paper);color:var(--ink);font:inherit;font-size:var(--fs-core);text-align:left;cursor:pointer}.file-pick-item:last-child{border-bottom:0}.file-pick-item:hover{background:var(--soft)}.file-pick-item img{width:28px;height:28px;object-fit:cover;border-radius:4px;border:var(--border);background:#fff}.file-pick-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card>.colhead.sticky-head{position:sticky;top:0;z-index:5;height:auto;min-height:var(--row-h);padding:4px 14px;background:var(--paper);box-shadow:0 1px 0 var(--soft-2)}.grip{width:10px;height:14px;flex:0 0 auto;cursor:grab;background-image:radial-gradient(circle,var(--mid) 1px,transparent 1px);background-size:4px 4px;opacity:.5}.grip:active{cursor:grabbing}.nav-title{font:inherit;font-size:var(--fs-core);font-weight:600;min-width:12ch;padding:2px 0;background:none;border:0;border-bottom:1px dashed var(--soft-2)}.nav-title:focus{outline:none;border-bottom-color:var(--ink)}.nav-group .colhead{display:flex;align-items:center;gap:8px}.nav-pool{padding:8px 10px;background:var(--paper);border:var(--border);border-radius:8px}.nav-pool.drop-target,.nav-group.drop-target{outline:2px dashed var(--ink);outline-offset:-2px;background:var(--soft)}.nav-row.dragging{opacity:.45}.nav-row.ins-before{box-shadow:inset 0 2px 0 var(--ink)}.nav-row.ins-after{box-shadow:inset 0 -2px 0 var(--ink)}.nav-row.is-hidden .name{color:var(--mid)}.nav-list{display:flex;flex-direction:column}.nav-group .colhead.drop-target{background:var(--soft)}.nav-hidden .colhead,.nav-hidden .row .name{color:var(--mid)}.md-field{display:flex;flex-direction:column;gap:8px;border-radius:var(--radius-btn)}.md-field.drag{outline:1px dashed var(--mid);outline-offset:4px}.md-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.md-tools select{max-width:220px}.md-tools .hint code{background:var(--soft-2);border-radius:4px;padding:0 4px}.md-preview{padding:10px 12px;background:var(--soft);border-radius:var(--radius-btn);overflow:auto;font-size:12.5px;line-height:1.6}.md-field.reading .md-tools{opacity:0;transition:opacity .12s}.md-field.reading:hover .md-tools,.md-field.reading:focus-within .md-tools{opacity:1}.md-preview.reading{max-height:none;background:transparent;padding:0}.source-draft-preview{display:flex;flex-direction:column;gap:3px}.source-draft-md{max-height:220px;background:var(--paper);border:1px solid var(--soft-2)}.md-body{min-width:0;word-break:break-word}.md-body>:first-child{margin-top:0}.md-body>:last-child{margin-bottom:0}.md-body p{margin:0 0 8px}.md-body h1,.md-body h2,.md-body h3,.md-body h4,.md-body h5,.md-body h6{margin:14px 0 6px;font-weight:600;line-height:1.35}.md-body h1{font-size:17px}.md-body h2{font-size:15px}.md-body h3{font-size:13.5px}.md-body h4,.md-body h5,.md-body h6{font-size:12.5px;color:var(--mid)}.md-body ul,.md-body ol{margin:0 0 8px;padding-left:20px}.md-body li{margin:2px 0}.md-body li>p{margin:0}.md-body li>p+ul,.md-body li>p+ol{margin-top:2px}.md-body ul.contains-task-list,.md-body ul.contains-task-list>li.task-list-item{list-style:none}.md-body input.md-task{width:13px;height:13px;margin:0 6px 0 0;vertical-align:-2px;cursor:pointer;accent-color:var(--ink)}.md-body input.md-task:disabled{cursor:default}.md-body code{background:var(--soft-2);border-radius:4px;padding:0 4px;font-size:11.5px}.md-body pre{margin:0 0 8px;padding:8px 10px;background:var(--paper);border:var(--border);border-radius:6px;overflow:auto}.md-body pre code{background:none;padding:0;font-size:11.5px}.md-body blockquote{margin:0 0 8px;padding:2px 0 2px 10px;border-left:2px solid var(--soft-2);color:var(--mid)}.md-body hr{border:0;border-top:var(--border);margin:10px 0}.md-body strong{font-weight:600}.md-body del{color:var(--mid)}.md-table{margin:0 0 8px;overflow-x:auto}.md-body table{border-collapse:collapse;font-size:11.5px}.md-body th,.md-body td{border:var(--border);padding:3px 8px;text-align:left;vertical-align:top}.md-body th{background:var(--soft-2);font-weight:600}.md-link-dead{color:inherit}.md-body .md-copy{font-family:ui-monospace,Consolas,Courier New,monospace;padding:0 3px;border:0;border-bottom:1px dashed var(--mid);border-radius:3px;background:none;color:var(--ink);cursor:copy;word-break:break-all}.md-body .md-copy:hover{background:var(--soft-2);border-bottom-color:var(--ink)}.md-body .md-copy:focus-visible{outline:1px solid var(--mid);outline-offset:1px}.md-inline{display:block;max-width:100%;max-height:260px;margin:6px 0;border-radius:6px;cursor:zoom-in}.md-missing{color:var(--danger);font-size:12px}.md-link{color:var(--ink);text-decoration:underline;text-decoration-color:var(--mid);text-underline-offset:2px;border-radius:3px;cursor:pointer;word-break:break-all}.md-link:hover{text-decoration-color:var(--ink);background:var(--soft-2)}.md-link:focus-visible{outline:1px solid var(--mid);outline-offset:1px}.md-gallery{display:flex;flex-direction:column;gap:6px}.md-gallery-head{display:flex;align-items:baseline;gap:8px;font-size:12px}.md-thumbs{display:flex;gap:8px;flex-wrap:wrap}.md-thumb{width:104px;padding:0;border:var(--border);border-radius:var(--radius-btn);background:var(--paper);overflow:hidden;cursor:zoom-in;display:flex;flex-direction:column;text-align:left}.md-thumb:hover{border-color:var(--mid)}.md-thumb img{width:100%;height:66px;object-fit:cover;display:block;background:var(--soft)}.md-thumb-name{padding:3px 6px;font-size:11px;color:var(--mid);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.md-thumb.missing{width:44px;height:44px;align-items:center;justify-content:center;color:var(--danger);cursor:default;font-size:12px}.lightbox{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;background:#14161ae0;display:flex;flex-direction:column;padding:10px 14px 6px}.lightbox-bar{display:flex;align-items:center;gap:8px;color:var(--paper);font-size:12px;padding-bottom:8px}.lightbox-bar .grow{min-width:0;overflow:hidden;text-overflow:ellipsis}.lightbox-bar .btn.ghost{background:#ffffff29;color:var(--paper)}.lightbox-bar .btn.ghost:hover{background:#ffffff3d}.lightbox-bar .muted{color:#fff9}.lightbox-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;overflow:hidden;cursor:grab;touch-action:none}.lightbox-stage:active{cursor:grabbing}.lightbox-stage img{max-width:100%;max-height:100%;transform-origin:center center;-webkit-user-select:none;user-select:none}.lightbox-tip{color:#ffffff8c;font-size:11.5px;text-align:center;padding:8px 0 4px}.more{position:relative;display:inline-block}.more>summary{list-style:none}.more>summary::-webkit-details-marker{display:none}.more[open]>summary{background:var(--soft-2)}.more-menu{position:absolute;right:0;top:calc(100% + 4px);z-index:45;min-width:208px;padding:4px;background:var(--paper);border:var(--border);border-radius:var(--radius-btn);box-shadow:0 6px 20px #14161a1f}.more-menu button{display:block;width:100%;padding:7px 10px;border:0;border-radius:6px;background:transparent;color:var(--ink);font:inherit;text-align:left;cursor:pointer}.more-menu button:hover{background:var(--soft)}.row .pick{flex:0 0 auto;margin:0 2px 0 0;cursor:pointer}.colhead .pickall{display:inline-flex;align-items:center;gap:6px;cursor:pointer}.colhead .right{display:inline-flex;align-items:center;gap:8px}.tp-headacts{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}.tp-headacts .pw{width:132px}@media(max-width:720px){.tp-headacts{width:100%;justify-content:flex-start}.tp-headacts .pw{width:100%}}.tp-tip{margin:2px 0 0;line-height:1.7}.tp-grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:0}.tp-col{padding:12px 14px;display:flex;flex-direction:column;gap:10px;min-width:0}.tp-col+.tp-col{border-left:1px solid var(--soft-2)}.tp-colhead{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600}.tp-step{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;border-radius:999px;background:var(--soft-2);color:var(--ink);font-size:11px;font-weight:700}@media(max-width:900px){.tp-grid{grid-template-columns:1fr}.tp-col+.tp-col{border-left:0;border-top:1px solid var(--soft-2)}}.sec-strip{display:flex;flex-wrap:wrap;gap:6px}.sec-chip{display:inline-flex;align-items:baseline;gap:6px;max-width:100%;padding:5px 11px;border:var(--border);border-radius:999px;background:var(--paper);color:var(--mid);font:inherit;font-size:12.5px;cursor:pointer;transition:border-color .12s ease,background .12s ease}.sec-chip:hover{border-color:var(--mid)}.sec-chip.on{background:var(--soft-2);color:var(--ink);border-color:var(--ink)}.sec-chip.picked{color:var(--ink)}.sec-chip.picked .chip-name,.sec-chip.picked .chip-meta{font-weight:600}.sec-chip .chip-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sec-chip .chip-meta{flex:0 0 auto;font-size:11.5px}@media(prefers-reduced-motion:reduce){.sec-chip{transition:none}}.entry-panel{border:var(--border);border-radius:var(--radius-btn);overflow:hidden}.entry-head{display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--soft);border-bottom:1px solid var(--soft-2);font-size:12.5px}.entry-head .pickall{display:inline-flex;align-items:center;gap:6px;cursor:pointer}.entry-list{max-height:260px;overflow:auto;padding:4px 0}.entry-row{display:flex;align-items:center;gap:8px;padding:4px 10px;cursor:pointer}.entry-row:hover{background:var(--soft)}.entry-row .name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.entry-row .hint{margin-left:auto}.export-opts{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;padding:8px 10px;border:1px dashed var(--soft-2);border-radius:var(--radius-btn)}.export-opts .opt-group{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.export-opts .pw{width:148px}.export-opts .hint{flex-basis:100%}.tp-note{display:flex;flex-direction:column;gap:4px}.tp-list{margin:0;padding-left:18px;color:var(--mid);font-size:12px;line-height:1.7}.conflict-list{max-height:220px;overflow:auto}.conflict-row{display:flex;align-items:baseline;gap:8px;padding:4px 0;border-bottom:1px dashed var(--soft-2);font-size:12.5px}.conflict-row:last-child{border-bottom:0}.conflict-row .sec{color:var(--mid);min-width:64px}.conflict-row .title{font-weight:600}.conflict-row .ok{color:var(--ink)}.drop-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:55;display:flex;align-items:center;justify-content:center;background:#14161a61;pointer-events:none}.drop-mask>div{padding:18px 28px;border-radius:12px;background:var(--paper);border:var(--border);font-size:14px}.drop-box{display:flex;flex-direction:column;align-items:center;gap:4px;padding:18px 14px;border:1px dashed var(--soft-2);border-radius:var(--radius-btn);background:var(--soft);cursor:pointer;text-align:center}.drop-box:hover,.drop-box.over{border-color:var(--mid);background:var(--soft-2)}.transfer-sec-row{display:flex;align-items:center;gap:8px;padding:3px 0;border-bottom:1px dashed var(--soft-2)}.transfer-sec-row:last-child{border-bottom:0}.crumb{cursor:copy;display:inline-flex;align-items:center;gap:6px;min-width:0}.crumb:hover .crumb-ent{text-decoration:underline}.crumb-sec,.crumb-sep{color:var(--mid)}.crumb-ent{font-weight:600}.crumb-copy{color:var(--mid);font-size:11px}.crumb:hover .crumb-copy{color:var(--ink)}.row-copy{border:0;background:transparent;cursor:copy;color:var(--mid);font-size:11px;padding:0 4px;opacity:0;transition:opacity .12s}.row.selectable:hover .row-copy{opacity:1}.row-copy:hover{color:var(--ink)}.entrylist{display:flex;flex-direction:column;gap:3px}.entrylist-head,.entrylist-row{display:grid;gap:5px;align-items:center}.entrylist-head{font-size:11px;color:var(--mid)}.entrylist-head .entrylist-col{display:inline-flex;align-items:center;gap:4px;min-width:0}.entrylist-head .entrylist-col .tag{font-size:10px;padding:0 4px}.entrylist-row input{padding:3px 6px;font-size:12px}.entrylist-acts{display:flex;align-items:center;justify-content:flex-end;gap:1px}.entrylist-add{display:flex;align-items:center;gap:8px;margin-top:2px}.tree-search{width:190px}.tree-batch{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:6px 14px;border-top:var(--border);border-bottom:var(--border);background:var(--soft)}.tree-batch .pickall{font-weight:600}.tree{border:var(--border);border-radius:var(--radius-btn);overflow:hidden}.tree-head{display:flex;align-items:center;gap:6px;padding:3px 10px 3px 34px;font-size:11px;color:var(--mid);border-bottom:var(--border);background:var(--paper)}.tree-col-name{flex:1;min-width:0}.tree-col-meta{width:118px;text-align:right;flex-shrink:0}.tree-col-acts{width:156px;text-align:right;flex-shrink:0}.tree-row{display:flex;align-items:center;gap:6px;min-height:var(--row-h);padding:2px 10px;border-bottom:1px solid var(--soft-2)}.tree-row:last-child{border-bottom:0}.tree-sec:hover,.tree-ent:hover{background:var(--soft)}.tree-sec.on,.tree-ent.on{background:var(--soft-2)}.tree-ent{padding-left:34px}.tree-chev{width:18px;height:18px;padding:0;flex-shrink:0;border:0;border-radius:4px;background:transparent;color:var(--mid);font-size:11px;line-height:1;cursor:pointer}.tree-chev:hover{background:var(--soft-2);color:var(--ink)}.tree-check{flex-shrink:0;margin:0;cursor:pointer;accent-color:var(--ink)}.tree-title{flex:1;min-width:0;display:flex;align-items:center;gap:6px}.tree-link{border:0;background:transparent;padding:0;margin:0;font:inherit;font-weight:600;color:inherit;text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.tree-link:hover{text-decoration:underline}.tree-id{font-size:11px;flex-shrink:0}.tree-desc{font-size:11px;color:var(--mid);min-width:0}.tree-meta{width:118px;flex-shrink:0;text-align:right;font-size:11px;color:var(--mid);font-variant-numeric:tabular-nums}.tree-acts{width:156px;flex-shrink:0;display:flex;gap:2px;justify-content:flex-end}.tree-empty{padding:5px 10px 6px 34px;border-bottom:1px solid var(--soft-2)}.tablefield{display:flex;flex-direction:column;gap:6px}.tf-scroll{overflow-x:auto;border:var(--border);border-radius:var(--radius-box);background:var(--paper)}.tf-body{display:flex;flex-direction:column;width:100%;font-size:13px}.tf-row{display:grid;align-items:stretch;border-bottom:var(--border);position:relative}.tf-row:last-of-type{border-bottom:0}.tf-row:not(.tf-head):not(.tf-total):hover{background:var(--soft)}.tf-row.dragging{opacity:.45}.tf-gutter{position:relative;display:flex;align-items:center;justify-content:center;gap:1px;border-right:var(--border);color:var(--mid);font-size:10px}.tf-th,.tf-td{border-left:var(--border)}.tf-gutter+.tf-th,.tf-gutter+.tf-td{border-left:0}.tf-gutter-head{background:var(--paper)}.tf-rownum{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;color:var(--mid);font-variant-numeric:tabular-nums}.tf-gutter .tf-row-more,.tf-gutter .tf-grip,.tf-row:hover .tf-rownum{opacity:0}.tf-row:hover .tf-row-more,.tf-row:hover .tf-grip,.tf-row-more:focus-visible,.tf-grip:focus-visible{opacity:1}.tf-rownum,.tf-row-more,.tf-grip{font-size:10px;line-height:1}.tf-head{background:var(--paper);border-bottom:1px solid var(--line-strong)}.tf-th{display:flex;align-items:center;gap:5px;min-width:0;height:32px;padding:0 4px 0 8px;color:var(--mid);font-size:12px;cursor:grab}.tf-th:active{cursor:grabbing}.tf-th:hover{background:var(--soft)}.tf-glyph{flex-shrink:0;width:14px;color:var(--soft-2);font-size:10px;text-align:center}.tf-glyph.calc{color:var(--mid)}.tf-glyph.large{width:20px;font-size:13px;color:var(--mid)}.tf-th-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tf-th.right .tf-th-label{flex:1;text-align:right}.tf-th:hover .tf-th-label{color:var(--ink)}.tf-th.center{justify-content:center}.tf-unit{flex-shrink:0;color:var(--soft-2);font-size:10px}.tf-badge{flex-shrink:0;padding:0 4px;border-radius:999px;background:var(--soft-2);color:var(--mid);font-size:10px;line-height:1.6}.tf-badge.bad{color:var(--danger)}.tf-th-add{display:flex;align-items:center;justify-content:center;border-left:var(--border)}.tf-th-add-btn{width:100%;height:100%;padding:0;border:0;background:transparent;color:var(--soft-2);font-size:12px;cursor:pointer}.tf-th-add-btn:hover{background:var(--soft);color:var(--ink)}.tf-td-add{border-left:var(--border)}.tf-th-more,.tf-row-more{flex-shrink:0;width:16px;height:18px;padding:0;line-height:1;font-size:11px;color:var(--mid);background:transparent;border:0;border-radius:4px;cursor:pointer;opacity:0;transition:opacity .12s}.tf-th:hover .tf-th-more,.tf-th-more:focus-visible{opacity:1}.tf-th-more:hover{background:var(--soft-2);color:var(--ink)}.tf-td{display:flex;align-items:center;min-width:0;padding:0}.tf-td.right{justify-content:flex-end}.tf-td.center{justify-content:center}.tf-input{width:100%;min-width:0;min-height:32px;height:100%;padding:4px 8px;font:inherit;font-size:13px;color:inherit;background:transparent;border:0;border-radius:0}.tf-input:hover{background:transparent}.tf-input:focus{outline:none;background:var(--paper);box-shadow:inset 0 0 0 1px var(--line-strong)}.tf-input.num,.tf-td.right .tf-input{text-align:right;font-variant-numeric:tabular-nums}.tf-input::-webkit-outer-spin-button,.tf-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.tf-input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}.tf-select{padding-right:2px}.tf-bool{display:flex;align-items:center;justify-content:center;width:100%;min-height:32px;cursor:pointer}.tf-bool input{margin:0;cursor:pointer;accent-color:var(--ink)}.tf-check{width:15px;height:15px;min-height:0;margin:0;padding:0;accent-color:var(--ink);cursor:pointer}.tf-bar input[type=checkbox],.tf-pop-check input[type=checkbox]{width:14px;height:14px;margin:0;accent-color:var(--ink)}.tf-calc{padding:4px 8px;background:var(--soft);color:var(--ink);font-variant-numeric:tabular-nums}.tf-td.has-err{background:#fdf3f2}.tf-err{color:var(--danger);font-variant-numeric:normal}.tf-total{border-top:1px solid var(--line-strong);background:var(--paper);font-weight:600}.tf-total .tf-td{padding:5px 8px;font-variant-numeric:tabular-nums}.tf-sum-label{color:var(--mid);font-weight:600;margin-right:6px}.tf-sum-label+.tf-sum-val{color:var(--ink)}.tf-addrow{display:grid;align-items:center;width:100%;height:32px;padding:0;border:0;border-top:var(--border);background:transparent;color:var(--mid);font:inherit;font-size:12px;text-align:left;cursor:pointer}.tf-addrow:hover{background:var(--soft);color:var(--ink)}.tf-addrow .tf-gutter{height:100%}.tf-plus{color:var(--mid);font-size:12px}.tf-addrow-label{padding:0 8px}.tf-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.tf-errors{display:flex;flex-direction:column;gap:1px}.tf-empty{padding:10px 12px;border:1px dashed var(--soft-2);border-radius:var(--radius-btn)}.btn.ghost.on{background:var(--soft-2);color:var(--ink)}.tf-mini{width:19px;height:19px;padding:0;line-height:1;font-size:11px;color:var(--mid);background:transparent;border:0;border-radius:4px;cursor:pointer}.tf-mini:hover:not(:disabled){background:var(--soft-2);color:var(--ink)}.tf-mini:disabled{opacity:.28;cursor:default}.tablefield .tf-mini,.entrylist .tf-mini{width:16px;height:16px;font-size:10px}.tf-acts .tf-mini,.entrylist-acts .tf-mini{opacity:0;transition:opacity .12s}.tf-row:hover .tf-acts .tf-mini,.entrylist-row:hover .entrylist-acts .tf-mini,.tf-acts .tf-mini:focus-visible,.entrylist-acts .tf-mini:focus-visible{opacity:1}.tf-grip{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:14px;height:17px;font-size:11px;line-height:1;color:var(--soft-2);border-radius:3px;cursor:grab;-webkit-user-select:none;user-select:none}.tf-grip:hover{color:var(--ink);background:var(--soft-2)}.tf-grip:active{cursor:grabbing}.tf-row,.tf-th,.entrylist-row{position:relative}.tf-row.drop-before:before,.tf-row.drop-after:after,.entrylist-row.drop-before:before,.entrylist-row.drop-after:after{content:"";position:absolute;left:0;right:0;height:2px;background:var(--ink);z-index:4;pointer-events:none}.tf-row.drop-before:before,.entrylist-row.drop-before:before{top:-1px}.tf-row.drop-after:after,.entrylist-row.drop-after:after{bottom:-1px}.tf-th.drop-before:before,.tf-th.drop-after:after{content:"";position:absolute;top:0;bottom:0;width:2px;background:var(--ink);z-index:4;pointer-events:none}.tf-th.drop-before:before{left:-1px}.tf-th.drop-after:after{right:-1px}.tf-pop{position:fixed;z-index:80;overflow:auto;display:flex;flex-direction:column;gap:6px;padding:8px;background:var(--paper);border:var(--border);border-radius:var(--radius-box);box-shadow:var(--shadow-float);font-size:12px}.tf-pop-head{display:flex;align-items:center;gap:6px}.tf-pop-title{flex:1;min-width:0;height:26px;padding:0 4px;font-size:13px;font-weight:600;background:transparent;border-color:transparent}.tf-pop-title:hover,.tf-pop-title:focus{background:var(--soft)}.tf-pop-type{width:132px;flex-shrink:0;font-size:11px}.tf-pop-field{display:flex;align-items:center;gap:6px;min-width:0}.tf-pop-field.tight{flex:1;min-width:0}.tf-pop-field input,.tf-pop-field select{flex:1;min-width:0;height:26px;font-size:11px}.tf-pop-key{width:44px;flex-shrink:0;color:var(--mid);font-size:10px}.tf-pop-row{display:flex;gap:8px;align-items:flex-end}.tf-pop-row .tf-pop-field.tight:first-child{flex:0 0 96px}.tf-pop-check{display:inline-flex;align-items:center;gap:4px;color:var(--mid);font-size:11px;white-space:nowrap}.tf-pop-check input{accent-color:var(--ink)}.tf-pop-sep{height:1px;margin:2px -8px;background:var(--line)}.tf-pop-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px}.tf-pop-grid.one{grid-template-columns:1fr}.tf-pop-item{display:flex;align-items:center;gap:6px;padding:5px 6px;border:0;border-radius:6px;background:transparent;color:var(--ink);font:inherit;font-size:12px;text-align:left;cursor:pointer}.tf-pop-item:hover:not(:disabled){background:var(--soft)}.tf-pop-item:disabled{opacity:.35;cursor:default}.tf-pop-item.danger{color:var(--danger)}.tf-pop-glyph{flex-shrink:0;width:14px;text-align:center;color:var(--mid);font-size:11px}.tf-pop-item.danger .tf-pop-glyph{color:var(--danger)}.tf-pop-foot{color:var(--mid);font-size:10px;line-height:1.5}.col-splitter{flex:0 0 14px;margin:0 -14px;align-self:stretch;cursor:col-resize;position:relative;z-index:1;border-radius:3px;min-width:0}.col-splitter:hover,.col-splitter.active{background:var(--soft-2)}body.col-resizing,body.col-resizing *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.source-field{display:flex;flex-direction:column;gap:4px}.source-strip{display:flex;align-items:center;gap:6px;width:100%;min-height:var(--row-h);padding:3px 8px;background:var(--soft);border:var(--border);border-radius:var(--radius-btn);cursor:pointer;text-align:left;font:inherit;color:inherit;transition:background .15s ease}.source-strip:hover{background:var(--soft-2)}.source-strip-label{font-weight:600}.source-strip-preview{color:var(--mid);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:42%}.source-caret{color:var(--mid)}.source-drawer.side{position:fixed;top:0;right:0;bottom:0;z-index:45;width:min(720px,46vw);box-shadow:var(--shadow-float);animation:side-in .16s ease-out}@keyframes side-in{0%{transform:translate(18px);opacity:.5}to{transform:none;opacity:1}}@media(max-width:900px){.source-drawer.side{width:94vw}}@media(prefers-reduced-motion:reduce){.source-drawer.side{animation:none}}.source-drawer{background:var(--paper);border-left:var(--border);width:min(760px,94vw);height:100%;display:flex;flex-direction:column;overflow:hidden}.source-drawer-head{display:flex;align-items:center;gap:8px;height:36px;padding:0 12px;border-bottom:var(--border);flex-shrink:0}.source-drawer-body{display:flex;flex:1;min-height:0}.source-list-pane{width:264px;flex-shrink:0;border-right:var(--border);display:flex;flex-direction:column;min-height:0}.source-list-pane.drag{outline:2px dashed var(--mid);outline-offset:-4px;background:var(--soft)}.source-list-tools{display:flex;align-items:center;gap:6px;padding:8px;border-bottom:var(--border);flex-wrap:wrap}.source-paste{display:flex;flex-direction:column;gap:4px;padding:8px;border-bottom:var(--border)}.source-paste textarea{font:inherit;resize:vertical}.source-paste.drag{outline:2px dashed var(--mid);outline-offset:-3px;background:var(--soft)}.source-items{flex:1;overflow:auto;min-height:0}.source-item{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:0;border-bottom:1px solid var(--soft-2);background:transparent;cursor:pointer;text-align:left;font:inherit;color:inherit;transition:background .15s ease}.source-item:hover{background:var(--soft)}.source-item.sel{background:var(--soft-2)}.source-item-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.source-view-pane{flex:1;min-width:0;display:flex;flex-direction:column}.source-view-head{display:flex;align-items:center;gap:8px;padding:6px 12px;border-bottom:var(--border)}.source-view-body{flex:1;overflow:auto;padding:12px;min-height:0}.source-preview-img{max-width:100%;border:var(--border);border-radius:4px}.source-drawer :focus-visible{outline:2px solid var(--ink);outline-offset:1px;border-radius:3px}@media(prefers-reduced-motion:reduce){.source-strip,.source-item{transition:none}}.source-item.old{opacity:.62}.source-item.old:hover{opacity:1}.source-item-time{margin-left:auto;color:var(--mid);font-size:10px;white-space:nowrap}.source-old-toggle{display:block;width:100%;text-align:left;padding:4px 8px;border:0;border-bottom:1px solid var(--soft-2);background:var(--soft);color:var(--mid);cursor:pointer;font:inherit;font-size:11px;transition:background .15s ease}.source-old-toggle:hover{background:var(--soft-2);color:var(--ink)}.file-picker-list{display:flex;flex-direction:column;gap:4px;max-height:266px;overflow-y:auto;overflow-x:hidden;padding-right:2px;scrollbar-width:thin}.file-picker-list.expanded{max-height:none}.file-picker-list .file-preview{flex-shrink:0}
|
|
1
|
+
:root{--ink: #14161a;--paper: #fff;--soft: #f5f6f7;--soft-2: #ebedf0;--mid: #8b9096;--danger: #b3261e;--line: rgba(20, 22, 26, .085);--line-strong: rgba(20, 22, 26, .14);--border: 1px solid var(--line);--row-h: 28px;--btn-h: 32px;--fs-core: 12px;--radius-btn: 8px;--radius-box: 10px;--hover: rgba(20, 22, 26, .028);--shadow-relief: -1px -1px 2px rgba(255, 255, 255, .85), 2px 2px 6px rgba(20, 22, 26, .07);--shadow-relief-press: inset 1px 1px 2px rgba(20, 22, 26, .1), inset -1px -1px 2px rgba(255, 255, 255, .7);--shadow-relief-inset: inset 1px 1px 2px rgba(20, 22, 26, .06), inset -1px -1px 2px rgba(255, 255, 255, .9);--shadow-float: 0 6px 24px rgba(20, 22, 26, .12), 0 1px 2px rgba(20, 22, 26, .06)}*{box-sizing:border-box}html,body,#root{height:100%}body{margin:0;background:var(--paper);color:var(--ink);font-family:system-ui,-apple-system,Segoe UI,Microsoft YaHei,sans-serif;font-size:var(--fs-core);line-height:1.5;-webkit-font-smoothing:antialiased}.mono,code,.path,.cli-cmd{font-family:ui-monospace,Consolas,Courier New,monospace}.muted{color:var(--mid)}.bad{color:var(--danger)}.nowrap{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pad{padding:10px 14px}.rowgap{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.grow{flex:1;min-width:0}.right{margin-left:auto}.app{display:flex;flex-direction:column;height:100%;min-height:0}header.top{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 14px;border-bottom:var(--border);flex-shrink:0}header.top .brand{font-size:15px;font-weight:700;letter-spacing:.2px;line-height:1;display:inline-flex;align-items:center;gap:8px}header.top .brand img{width:22px;height:22px;border-radius:6px;display:block}header.top .tagline{color:var(--mid);font-size:11px}header.top .ver{font-size:10px;color:var(--mid);background:var(--soft);border:var(--border);border-radius:999px;padding:1px 8px;line-height:1.7}header.top .store{display:inline-flex;align-items:center;gap:6px;min-width:0;font-size:11px;color:var(--mid)}header.top .store .store-label{color:var(--mid)}header.top .store .copyable{max-width:30ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nav.tabs{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:6px 14px;border-bottom:var(--border);flex-shrink:0}.tabs-sep{width:1px;height:18px;background:var(--soft-2);margin:0 4px}.tab-group{position:relative;display:inline-flex}.tab-group .caret{width:0;height:0;margin-left:1px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid var(--mid)}.tab-group .tab.active .caret{border-top-color:var(--ink)}.tab-group .caret{transition:transform .12s ease}.tab-group .tab[aria-expanded=true] .caret{border-top-color:var(--ink);transform:rotate(180deg)}@media(prefers-reduced-motion:reduce){.tab-group .caret{transition:none}}.tab-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:40;min-width:172px;padding:4px;display:flex;flex-direction:column;gap:2px;background:var(--paper);border:var(--border);border-radius:var(--radius-btn);box-shadow:var(--shadow-float)}.tab-menu:before{content:"";position:absolute;left:0;right:0;top:-5px;height:5px}.tab-menu-row{display:flex;align-items:center;gap:10px;width:100%;height:var(--row-h);padding:0 8px;border:0;border-radius:6px;background:none;color:var(--ink);font:inherit;font-size:var(--fs-core);text-align:left;cursor:pointer}.tab-menu-row:hover{background:var(--soft)}.tab-menu-row.current{font-weight:600}.tab-menu-row .count{color:var(--mid);font-size:10px;font-variant-numeric:tabular-nums}main.body{flex:1;min-height:0;overflow:auto}.tab{font:inherit;font-size:var(--fs-core);height:var(--btn-h);padding:0 12px;border:0;border-radius:var(--radius-btn);background:transparent;color:var(--mid);cursor:pointer;display:inline-flex;align-items:center;gap:7px;transition:background .12s,color .12s}.tab:hover{background:var(--soft);color:var(--ink)}.tab .count{color:var(--mid);font-size:10px;font-variant-numeric:tabular-nums}.tab.active{background:var(--soft);color:var(--ink);font-weight:600}.btn{font:inherit;font-size:var(--fs-core);cursor:pointer;height:var(--btn-h);padding:0 12px;border:0;border-radius:var(--radius-btn);background:var(--ink);color:var(--paper);display:inline-flex;align-items:center;gap:4px;transition:background .12s,transform .08s,opacity .12s}.btn:hover:not(:disabled){background:#2b2f36}.btn:active:not(:disabled){transform:translateY(1px)}.btn:disabled{background:var(--soft);color:var(--mid);cursor:not-allowed}.btn.ghost{background:transparent;color:var(--ink)}.btn.ghost:hover:not(:disabled){background:var(--soft)}.btn.danger{background:var(--danger);color:#fff}.btn.small{height:22px;padding:0 8px;font-size:11px;border-radius:6px}input,select,textarea{font:inherit;font-size:var(--fs-core);color:var(--ink);background:var(--soft);border:1px solid transparent;border-radius:8px;padding:0 8px;transition:background .12s,border-color .12s}input,select{height:var(--row-h)}textarea{padding:5px 8px;resize:vertical;min-height:56px;line-height:1.5}input:hover,select:hover,textarea:hover{background:var(--soft-2)}input:focus,select:focus,textarea:focus{outline:none;background:var(--paper);border-color:var(--line-strong);box-shadow:none}label.inline{display:inline-flex;align-items:center;gap:6px}.card{border-bottom:var(--border)}.card:last-child{border-bottom:0}.card>.colhead{display:flex;align-items:center;gap:8px;height:var(--row-h);padding:0 14px;border-bottom:var(--border);font-size:13px;font-weight:600}.card>.colbody{padding:0}.row{display:flex;align-items:center;gap:8px;min-height:var(--row-h);padding:0 14px;border-bottom:var(--border);font-size:var(--fs-core);transition:background .12s}.row:hover{background:var(--soft)}.row:last-child{border-bottom:0}.row .name{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row .desc{color:var(--mid);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row .acts{margin-left:auto;display:flex;align-items:center;gap:6px;flex-shrink:0}.row.selectable{cursor:pointer}.row.selected{background:var(--soft);box-shadow:inset 2px 0 0 var(--ink)}.tag{display:inline-flex;align-items:center;height:22px;padding:0 7px;border-radius:999px;background:var(--soft);color:var(--mid);font-size:11px;white-space:nowrap}.tag.strong{background:var(--ink);color:var(--paper)}.tag.bad{background:#fbeae9;color:var(--danger)}.copyable{cursor:copy;border-radius:4px;padding:0 3px}.copyable:hover{background:var(--soft)}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:0 14px}.field{border-bottom:var(--border);padding:5px 0;min-width:0}.field>.flabel{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--mid)}.field>.flabel .fkey{font-family:ui-monospace,Consolas,monospace;font-size:10px;color:var(--soft-2)}.field>.fctrl{margin-top:3px}.field input,.field select,.field textarea{width:100%}.field.wide{grid-column:1 / -1}.group-title{display:flex;align-items:center;gap:8px;height:var(--row-h);padding:0 14px;border-bottom:var(--border);background:var(--soft);font-size:11px;color:var(--mid);letter-spacing:.5px}.board{padding-bottom:6px}.board-bar{display:flex;align-items:center;gap:8px;padding:0 14px 8px;font-size:11px;color:var(--mid)}.board-tip{min-width:0}.board-bar .right{opacity:.35;transition:opacity .12s}.board:hover .board-bar .right{opacity:1}.panel{margin-bottom:6px}.panel-head{display:flex;align-items:center;gap:4px;min-height:28px;padding:0 8px;border-radius:8px;font-size:11px;color:var(--mid);cursor:grab;-webkit-user-select:none;user-select:none;transition:background .12s}.panel-head:hover{background:var(--soft)}.panel-head:active{cursor:grabbing}.panel-grip{color:var(--mid);opacity:.45;transition:opacity .12s}.panel-head:hover .panel-grip{opacity:1}.panel-head .panel-title{color:var(--ink);font-weight:600;font-size:12px;letter-spacing:.2px}.panel-count{color:var(--mid);font-size:10px;font-variant-numeric:tabular-nums}.panel-acts{opacity:0;transition:opacity .12s}.panel:hover .panel-acts,.panel:focus-within .panel-acts{opacity:1}.panel-toggle{border:0;background:none;padding:0 2px;color:var(--soft-2);font-size:11px;cursor:pointer}.panel:hover .panel-toggle{color:var(--mid)}.panel-toggle:hover{color:var(--ink)}.panel.dragging{opacity:.5}.panel.drop-before{box-shadow:inset 0 2px 0 var(--ink)}.panel.drop-after{box-shadow:inset 0 -2px 0 var(--ink)}.panel-body{padding:0 6px}.blk-grid{min-height:4px}.blk-cell{height:100%}.blk-cell.dragging{opacity:.45}.blk-cell.drop-before{box-shadow:inset 0 2px 0 var(--ink)}.blk-cell.drop-after{box-shadow:inset 0 -2px 0 var(--ink)}.blk{display:flex;flex-direction:column;min-width:0;height:100%;padding:0 4px;border-radius:var(--radius-box);overflow:hidden}.blk-head{display:flex;align-items:center;gap:6px;min-height:26px;padding:0 4px;border-radius:8px;font-size:11px;color:var(--mid);cursor:grab;-webkit-user-select:none;user-select:none;transition:background .12s}.blk-head:hover{background:var(--soft)}.blk-head:active{cursor:grabbing}.blk-label{color:var(--mid)}.blk-head:hover .blk-label{color:var(--ink)}.blk-key{margin-left:auto;font-size:10px;color:var(--soft-2);opacity:0;transition:opacity .12s}.blk-head:hover .blk-key{opacity:1}.blk-grip{color:var(--mid);opacity:.45;transition:opacity .12s}.blk-head:hover .blk-grip{opacity:1}.blk-body{flex:1;min-height:0;font-size:13px}.blk-body input,.blk-body select,.blk-body textarea{width:100%;font-size:13px}.react-grid-item.react-draggable-dragging .blk,.react-grid-item.resizing .blk{background:var(--paper);box-shadow:var(--shadow-float)}.react-grid-item.react-grid-placeholder{background:var(--soft-2);border-radius:var(--radius-box);opacity:.5}.react-grid-item>.react-resizable-handle:after{right:2px;bottom:50%;width:2px;height:14px;margin-bottom:-7px;border:0;border-radius:2px;background:var(--line-strong)}.react-grid-item>.react-resizable-handle.react-resizable-handle-w:after{left:2px;right:auto}.entry-title{display:flex;align-items:baseline;gap:8px;padding-bottom:6px}.entry-title-label{color:var(--mid);font-size:11px;flex-shrink:0}.entry-title-input{flex:1;min-width:0;height:32px;padding:0 6px;font-size:16px;font-weight:600;background:transparent;border-color:transparent;border-radius:8px}.entry-title-input:hover{background:var(--soft)}.entry-title-input:focus{background:var(--paper);border-color:var(--line-strong)}.quick-add{padding:0 14px 8px;font-size:11px;color:var(--mid)}.quick-add>summary{list-style:none;width:fit-content;padding:2px 4px;border-radius:6px;cursor:pointer}.quick-add>summary::-webkit-details-marker{display:none}.quick-add>summary:hover{color:var(--ink);background:var(--soft)}.quick-add[open]>summary{margin-bottom:6px}.cli-hint{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 14px;color:var(--mid);font-size:11px;border-top:var(--border)}.cli-hint-label{margin-right:4px}.cli-hint-sep{color:var(--soft-2)}.cli-cmd{color:var(--ink)}.toasts{position:fixed;right:14px;bottom:14px;display:flex;flex-direction:column;gap:6px;z-index:70}.toast{background:var(--ink);color:var(--paper);padding:7px 12px;border-radius:8px;font-size:var(--fs-core);box-shadow:var(--shadow-float);max-width:420px}.toast.bad{background:var(--danger)}.mask{position:fixed;top:0;right:0;bottom:0;left:0;background:#14161a47;display:flex;align-items:center;justify-content:center;z-index:50;padding:20px}.dialog{background:var(--paper);border-radius:8px;min-width:320px;max-width:min(880px,92vw);max-height:86vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 10px 40px #14161a2e}.dialog-title{display:flex;align-items:center;gap:8px;height:var(--row-h);padding:0 14px;border-bottom:var(--border);font-size:13px;font-weight:600;flex-shrink:0}.dialog-body{padding:10px 14px;overflow:auto;min-height:0}.dialog-foot{display:flex;gap:8px;justify-content:flex-end;padding:8px 14px;border-top:var(--border);flex-shrink:0}pre.block{margin:0;padding:10px 14px;background:var(--soft);border-radius:8px;font-family:ui-monospace,Consolas,monospace;font-size:11px;line-height:1.55;white-space:pre-wrap;word-break:break-word;max-height:60vh;overflow:auto}.hint{color:var(--mid);font-size:11px}.stack{display:flex;flex-direction:column;gap:10px}.toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.cols{display:flex;gap:14px;align-items:flex-start;padding:0 14px 14px}.col{flex:1;min-width:0}.desc{color:var(--mid)}.cols>.col>.card{border:var(--border);border-radius:4px}.files-page{min-height:100%;position:relative}.files-page.drag-over{outline:2px dashed var(--ink);outline-offset:-8px;background:var(--soft)}.tab.small{height:22px;padding:0 8px;font-size:11px;border-radius:6px}.file-filters{padding-top:4px;padding-bottom:4px}.drop-hint{margin:0 14px;padding:18px;text-align:center;border:1px dashed var(--ink);border-radius:8px;background:var(--paper);font-weight:600}.file-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px}.file-card{display:flex;flex-direction:column;border:var(--border);border-radius:8px;overflow:hidden;background:var(--paper)}.file-thumb{display:flex;align-items:center;justify-content:center;height:120px;background:var(--soft);border-bottom:var(--border)}.file-thumb img{max-width:100%;max-height:100%;object-fit:contain}.ext-badge{font-size:22px;font-weight:700;letter-spacing:1px;color:var(--mid);font-family:ui-monospace,Consolas,monospace}.file-meta{padding:8px 10px 4px;display:flex;flex-direction:column;gap:4px}a.file-name{color:var(--ink);font-weight:600;text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}a.file-name:hover{text-decoration:underline}.file-acts{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:6px 10px 8px;margin-top:auto}.btn.ghost.danger-ghost{color:var(--danger)}.file-picker{display:flex;flex-direction:column;gap:4px}.file-picker.drag{outline:2px dashed var(--ink);outline-offset:-4px;background:var(--soft)}.file-picker .file-pick-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.file-preview{display:flex;align-items:center;gap:8px;border:var(--border);border-radius:6px;padding:4px 8px;background:var(--soft)}.file-preview img{width:40px;height:40px;object-fit:cover;border-radius:4px;border:var(--border);background:#fff}.file-preview .file-preview-name{color:var(--ink);text-decoration:none;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-preview .file-preview-name:hover{text-decoration:underline}.file-pick-panel{border:var(--border);border-radius:8px;background:var(--paper);overflow:hidden}.file-pick-search{display:flex;align-items:center;gap:6px;padding:6px 8px;border-bottom:var(--border);background:var(--soft)}.file-pick-search input{flex:1;min-width:0}.file-pick-list{max-height:260px;overflow:auto}.file-pick-item{display:flex;align-items:center;gap:8px;width:100%;padding:4px 8px;border:0;border-bottom:var(--border);background:var(--paper);color:var(--ink);font:inherit;font-size:var(--fs-core);text-align:left;cursor:pointer}.file-pick-item:last-child{border-bottom:0}.file-pick-item:hover{background:var(--soft)}.file-pick-item img{width:28px;height:28px;object-fit:cover;border-radius:4px;border:var(--border);background:#fff}.file-pick-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card>.colhead.sticky-head{position:sticky;top:0;z-index:5;height:auto;min-height:var(--row-h);padding:4px 14px;background:var(--paper);box-shadow:0 1px 0 var(--soft-2)}.grip{width:10px;height:14px;flex:0 0 auto;cursor:grab;background-image:radial-gradient(circle,var(--mid) 1px,transparent 1px);background-size:4px 4px;opacity:.5}.grip:active{cursor:grabbing}.nav-title{font:inherit;font-size:var(--fs-core);font-weight:600;min-width:12ch;padding:2px 0;background:none;border:0;border-bottom:1px dashed var(--soft-2)}.nav-title:focus{outline:none;border-bottom-color:var(--ink)}.nav-group .colhead{display:flex;align-items:center;gap:8px}.nav-pool{padding:8px 10px;background:var(--paper);border:var(--border);border-radius:8px}.nav-pool.drop-target,.nav-group.drop-target{outline:2px dashed var(--ink);outline-offset:-2px;background:var(--soft)}.nav-row.dragging{opacity:.45}.nav-row.ins-before{box-shadow:inset 0 2px 0 var(--ink)}.nav-row.ins-after{box-shadow:inset 0 -2px 0 var(--ink)}.nav-row.is-hidden .name{color:var(--mid)}.nav-list{display:flex;flex-direction:column}.nav-group .colhead.drop-target{background:var(--soft)}.nav-hidden .colhead,.nav-hidden .row .name{color:var(--mid)}.md-field{display:flex;flex-direction:column;gap:8px;border-radius:var(--radius-btn)}.md-field.drag{outline:1px dashed var(--mid);outline-offset:4px}.md-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.md-tools select{max-width:220px}.md-tools .hint code{background:var(--soft-2);border-radius:4px;padding:0 4px}.md-preview{padding:10px 12px;background:var(--soft);border-radius:var(--radius-btn);overflow:auto;font-size:12.5px;line-height:1.6}.md-field.reading .md-tools{opacity:0;transition:opacity .12s}.md-field.reading:hover .md-tools,.md-field.reading:focus-within .md-tools{opacity:1}.md-preview.reading{max-height:none;background:transparent;padding:0}.source-draft-preview{display:flex;flex-direction:column;gap:3px}.source-draft-md{max-height:220px;background:var(--paper);border:1px solid var(--soft-2)}.md-body{min-width:0;word-break:break-word}.md-body>:first-child{margin-top:0}.md-body>:last-child{margin-bottom:0}.md-body p{margin:0 0 8px}.md-body h1,.md-body h2,.md-body h3,.md-body h4,.md-body h5,.md-body h6{margin:14px 0 6px;font-weight:600;line-height:1.35}.md-body h1{font-size:17px}.md-body h2{font-size:15px}.md-body h3{font-size:13.5px}.md-body h4,.md-body h5,.md-body h6{font-size:12.5px;color:var(--mid)}.md-body ul,.md-body ol{margin:0 0 8px;padding-left:20px}.md-body li{margin:2px 0}.md-body li>p{margin:0}.md-body li>p+ul,.md-body li>p+ol{margin-top:2px}.md-body ul.contains-task-list,.md-body ul.contains-task-list>li.task-list-item{list-style:none}.md-body input.md-task{width:13px;height:13px;margin:0 6px 0 0;vertical-align:-2px;cursor:pointer;accent-color:var(--ink)}.md-body input.md-task:disabled{cursor:default}.md-body code{background:var(--soft-2);border-radius:4px;padding:0 4px;font-size:11.5px}.md-body pre{margin:0 0 8px;padding:8px 10px;background:var(--paper);border:var(--border);border-radius:6px;overflow:auto}.md-body pre code{background:none;padding:0;font-size:11.5px}.md-body blockquote{margin:0 0 8px;padding:2px 0 2px 10px;border-left:2px solid var(--soft-2);color:var(--mid)}.md-body hr{border:0;border-top:var(--border);margin:10px 0}.md-body strong{font-weight:600}.md-body del{color:var(--mid)}.md-table{margin:0 0 8px;overflow-x:auto}.md-body table{border-collapse:collapse;font-size:11.5px}.md-body th,.md-body td{border:var(--border);padding:3px 8px;text-align:left;vertical-align:top}.md-body th{background:var(--soft-2);font-weight:600}.md-link-dead{color:inherit}.md-body .md-copy{font-family:ui-monospace,Consolas,Courier New,monospace;padding:0 3px;border:0;border-bottom:1px dashed var(--mid);border-radius:3px;background:none;color:var(--ink);cursor:copy;word-break:break-all}.md-body .md-copy:hover{background:var(--soft-2);border-bottom-color:var(--ink)}.md-body .md-copy:focus-visible{outline:1px solid var(--mid);outline-offset:1px}.md-inline{display:block;max-width:100%;max-height:260px;margin:6px 0;border-radius:6px;cursor:zoom-in}.md-missing{color:var(--danger);font-size:12px}.md-link{color:var(--ink);text-decoration:underline;text-decoration-color:var(--mid);text-underline-offset:2px;border-radius:3px;cursor:pointer;word-break:break-all}.md-link:hover{text-decoration-color:var(--ink);background:var(--soft-2)}.md-link:focus-visible{outline:1px solid var(--mid);outline-offset:1px}.md-gallery{display:flex;flex-direction:column;gap:6px}.md-gallery-head{display:flex;align-items:baseline;gap:8px;font-size:12px}.md-thumbs{display:flex;gap:8px;flex-wrap:wrap}.md-thumb{width:104px;padding:0;border:var(--border);border-radius:var(--radius-btn);background:var(--paper);overflow:hidden;cursor:zoom-in;display:flex;flex-direction:column;text-align:left}.md-thumb:hover{border-color:var(--mid)}.md-thumb img{width:100%;height:66px;object-fit:cover;display:block;background:var(--soft)}.md-thumb-name{padding:3px 6px;font-size:11px;color:var(--mid);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.md-thumb.missing{width:44px;height:44px;align-items:center;justify-content:center;color:var(--danger);cursor:default;font-size:12px}.lightbox{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;background:#14161ae0;display:flex;flex-direction:column;padding:10px 14px 6px}.lightbox-bar{display:flex;align-items:center;gap:8px;color:var(--paper);font-size:12px;padding-bottom:8px}.lightbox-bar .grow{min-width:0;overflow:hidden;text-overflow:ellipsis}.lightbox-bar .btn.ghost{background:#ffffff29;color:var(--paper)}.lightbox-bar .btn.ghost:hover{background:#ffffff3d}.lightbox-bar .muted{color:#fff9}.lightbox-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;overflow:hidden;cursor:grab;touch-action:none}.lightbox-stage:active{cursor:grabbing}.lightbox-stage img{max-width:100%;max-height:100%;transform-origin:center center;-webkit-user-select:none;user-select:none}.lightbox-tip{color:#ffffff8c;font-size:11.5px;text-align:center;padding:8px 0 4px}.more{position:relative;display:inline-block}.more>summary{list-style:none}.more>summary::-webkit-details-marker{display:none}.more[open]>summary{background:var(--soft-2)}.more-menu{position:absolute;right:0;top:calc(100% + 4px);z-index:45;min-width:208px;padding:4px;background:var(--paper);border:var(--border);border-radius:var(--radius-btn);box-shadow:0 6px 20px #14161a1f}.more-menu button{display:block;width:100%;padding:7px 10px;border:0;border-radius:6px;background:transparent;color:var(--ink);font:inherit;text-align:left;cursor:pointer}.more-menu button:hover{background:var(--soft)}.row .pick{flex:0 0 auto;margin:0 2px 0 0;cursor:pointer}.colhead .pickall{display:inline-flex;align-items:center;gap:6px;cursor:pointer}.colhead .right{display:inline-flex;align-items:center;gap:8px}.tp-headacts{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}.tp-headacts .pw{width:132px}@media(max-width:720px){.tp-headacts{width:100%;justify-content:flex-start}.tp-headacts .pw{width:100%}}.tp-tip{margin:2px 0 0;line-height:1.7}.tp-grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:0}.tp-col{padding:12px 14px;display:flex;flex-direction:column;gap:10px;min-width:0}.tp-col+.tp-col{border-left:1px solid var(--soft-2)}.tp-colhead{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600}.tp-step{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;border-radius:999px;background:var(--soft-2);color:var(--ink);font-size:11px;font-weight:700}@media(max-width:900px){.tp-grid{grid-template-columns:1fr}.tp-col+.tp-col{border-left:0;border-top:1px solid var(--soft-2)}}.sec-strip{display:flex;flex-wrap:wrap;gap:6px}.sec-chip{display:inline-flex;align-items:baseline;gap:6px;max-width:100%;padding:5px 11px;border:var(--border);border-radius:999px;background:var(--paper);color:var(--mid);font:inherit;font-size:12.5px;cursor:pointer;transition:border-color .12s ease,background .12s ease}.sec-chip:hover{border-color:var(--mid)}.sec-chip.on{background:var(--soft-2);color:var(--ink);border-color:var(--ink)}.sec-chip.picked{color:var(--ink)}.sec-chip.picked .chip-name,.sec-chip.picked .chip-meta{font-weight:600}.sec-chip .chip-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sec-chip .chip-meta{flex:0 0 auto;font-size:11.5px}@media(prefers-reduced-motion:reduce){.sec-chip{transition:none}}.entry-panel{border:var(--border);border-radius:var(--radius-btn);overflow:hidden}.entry-head{display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--soft);border-bottom:1px solid var(--soft-2);font-size:12.5px}.entry-head .pickall{display:inline-flex;align-items:center;gap:6px;cursor:pointer}.entry-list{max-height:260px;overflow:auto;padding:4px 0}.entry-row{display:flex;align-items:center;gap:8px;padding:4px 10px;cursor:pointer}.entry-row:hover{background:var(--soft)}.entry-row .name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.entry-row .hint{margin-left:auto}.export-opts{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;padding:8px 10px;border:1px dashed var(--soft-2);border-radius:var(--radius-btn)}.export-opts .opt-group{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.export-opts .pw{width:148px}.export-opts .hint{flex-basis:100%}.tp-note{display:flex;flex-direction:column;gap:4px}.tp-list{margin:0;padding-left:18px;color:var(--mid);font-size:12px;line-height:1.7}.conflict-list{max-height:220px;overflow:auto}.conflict-row{display:flex;align-items:baseline;gap:8px;padding:4px 0;border-bottom:1px dashed var(--soft-2);font-size:12.5px}.conflict-row:last-child{border-bottom:0}.conflict-row .sec{color:var(--mid);min-width:64px}.conflict-row .title{font-weight:600}.conflict-row .ok{color:var(--ink)}.drop-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:55;display:flex;align-items:center;justify-content:center;background:#14161a61;pointer-events:none}.drop-mask>div{padding:18px 28px;border-radius:12px;background:var(--paper);border:var(--border);font-size:14px}.drop-box{display:flex;flex-direction:column;align-items:center;gap:4px;padding:18px 14px;border:1px dashed var(--soft-2);border-radius:var(--radius-btn);background:var(--soft);cursor:pointer;text-align:center}.drop-box:hover,.drop-box.over{border-color:var(--mid);background:var(--soft-2)}.transfer-sec-row{display:flex;align-items:center;gap:8px;padding:3px 0;border-bottom:1px dashed var(--soft-2)}.transfer-sec-row:last-child{border-bottom:0}.crumb{cursor:copy;display:inline-flex;align-items:center;gap:6px;min-width:0}.crumb:hover .crumb-ent{text-decoration:underline}.crumb-sec,.crumb-sep{color:var(--mid)}.crumb-ent{font-weight:600}.crumb-copy{color:var(--mid);font-size:11px}.crumb:hover .crumb-copy{color:var(--ink)}.row-copy{border:0;background:transparent;cursor:copy;color:var(--mid);font-size:11px;padding:0 4px;opacity:0;transition:opacity .12s}.row.selectable:hover .row-copy{opacity:1}.row-copy:hover{color:var(--ink)}.entrylist{display:flex;flex-direction:column;gap:3px}.entrylist-head,.entrylist-row{display:grid;gap:5px;align-items:center}.entrylist-head{font-size:11px;color:var(--mid)}.entrylist-head .entrylist-col{display:inline-flex;align-items:center;gap:4px;min-width:0}.entrylist-head .entrylist-col .tag{font-size:10px;padding:0 4px}.entrylist-row input{padding:3px 6px;font-size:12px}.entrylist-acts{display:flex;align-items:center;justify-content:flex-end;gap:1px}.entrylist-add{display:flex;align-items:center;gap:8px;margin-top:2px}.tree-search{width:190px}.tree-batch{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:6px 14px;border-top:var(--border);border-bottom:var(--border);background:var(--soft)}.tree-batch .pickall{font-weight:600}.tree{border:var(--border);border-radius:var(--radius-btn);overflow:hidden}.tree-head{display:flex;align-items:center;gap:6px;padding:3px 10px 3px 34px;font-size:11px;color:var(--mid);border-bottom:var(--border);background:var(--paper)}.tree-col-name{flex:1;min-width:0}.tree-col-meta{width:118px;text-align:right;flex-shrink:0}.tree-col-acts{width:156px;text-align:right;flex-shrink:0}.tree-row{display:flex;align-items:center;gap:6px;min-height:var(--row-h);padding:2px 10px;border-bottom:1px solid var(--soft-2)}.tree-row:last-child{border-bottom:0}.tree-sec:hover,.tree-ent:hover{background:var(--soft)}.tree-sec.on,.tree-ent.on{background:var(--soft-2)}.tree-ent{padding-left:34px}.tree-chev{width:18px;height:18px;padding:0;flex-shrink:0;border:0;border-radius:4px;background:transparent;color:var(--mid);font-size:11px;line-height:1;cursor:pointer}.tree-chev:hover{background:var(--soft-2);color:var(--ink)}.tree-check{flex-shrink:0;margin:0;cursor:pointer;accent-color:var(--ink)}.tree-title{flex:1;min-width:0;display:flex;align-items:center;gap:6px}.tree-link{border:0;background:transparent;padding:0;margin:0;font:inherit;font-weight:600;color:inherit;text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.tree-link:hover{text-decoration:underline}.tree-id{font-size:11px;flex-shrink:0}.tree-desc{font-size:11px;color:var(--mid);min-width:0}.tree-meta{width:118px;flex-shrink:0;text-align:right;font-size:11px;color:var(--mid);font-variant-numeric:tabular-nums}.tree-acts{width:156px;flex-shrink:0;display:flex;gap:2px;justify-content:flex-end}.tree-empty{padding:5px 10px 6px 34px;border-bottom:1px solid var(--soft-2)}.tablefield{display:flex;flex-direction:column;gap:6px}.tf-scroll{overflow-x:auto;border:var(--border);border-radius:var(--radius-box);background:var(--paper)}.tf-body{display:flex;flex-direction:column;width:100%;font-size:13px}.tf-row{display:grid;align-items:stretch;border-bottom:var(--border);position:relative}.tf-row:last-of-type{border-bottom:0}.tf-row:not(.tf-head):not(.tf-total):hover{background:var(--soft)}.tf-row.dragging{opacity:.45}.tf-gutter{position:relative;display:flex;align-items:center;justify-content:center;gap:1px;border-right:var(--border);color:var(--mid);font-size:10px}.tf-th,.tf-td{border-left:var(--border)}.tf-gutter+.tf-th,.tf-gutter+.tf-td{border-left:0}.tf-gutter-head{background:var(--paper)}.tf-rownum{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;color:var(--mid);font-variant-numeric:tabular-nums}.tf-gutter .tf-row-more,.tf-gutter .tf-grip,.tf-row:hover .tf-rownum{opacity:0}.tf-row:hover .tf-row-more,.tf-row:hover .tf-grip,.tf-row-more:focus-visible,.tf-grip:focus-visible{opacity:1}.tf-rownum,.tf-row-more,.tf-grip{font-size:10px;line-height:1}.tf-head{background:var(--paper);border-bottom:1px solid var(--line-strong)}.tf-th{display:flex;align-items:center;gap:5px;min-width:0;height:32px;padding:0 4px 0 8px;color:var(--mid);font-size:12px;cursor:grab}.tf-th:active{cursor:grabbing}.tf-th:hover{background:var(--soft)}.tf-glyph{flex-shrink:0;width:14px;color:var(--soft-2);font-size:10px;text-align:center}.tf-glyph.calc{color:var(--mid)}.tf-glyph.large{width:20px;font-size:13px;color:var(--mid)}.tf-th-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tf-th.right .tf-th-label{flex:1;text-align:right}.tf-th:hover .tf-th-label{color:var(--ink)}.tf-th.center{justify-content:center}.tf-unit{flex-shrink:0;color:var(--soft-2);font-size:10px}.tf-badge{flex-shrink:0;padding:0 4px;border-radius:999px;background:var(--soft-2);color:var(--mid);font-size:10px;line-height:1.6}.tf-badge.bad{color:var(--danger)}.tf-th-add{display:flex;align-items:center;justify-content:center;border-left:var(--border)}.tf-th-add-btn{width:100%;height:100%;padding:0;border:0;background:transparent;color:var(--soft-2);font-size:12px;cursor:pointer}.tf-th-add-btn:hover{background:var(--soft);color:var(--ink)}.tf-td-add{border-left:var(--border)}.tf-th-more,.tf-row-more{flex-shrink:0;width:16px;height:18px;padding:0;line-height:1;font-size:11px;color:var(--mid);background:transparent;border:0;border-radius:4px;cursor:pointer;opacity:0;transition:opacity .12s}.tf-th:hover .tf-th-more,.tf-th-more:focus-visible{opacity:1}.tf-th-more:hover{background:var(--soft-2);color:var(--ink)}.tf-td{display:flex;align-items:center;min-width:0;padding:0}.tf-td.right{justify-content:flex-end}.tf-td.center{justify-content:center}.tf-input{width:100%;min-width:0;min-height:32px;height:100%;padding:4px 8px;font:inherit;font-size:13px;color:inherit;background:transparent;border:0;border-radius:0}.tf-input:hover{background:transparent}.tf-input:focus{outline:none;background:var(--paper);box-shadow:inset 0 0 0 1px var(--line-strong)}.tf-input.num,.tf-td.right .tf-input{text-align:right;font-variant-numeric:tabular-nums}.tf-input::-webkit-outer-spin-button,.tf-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.tf-input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}.tf-select{padding-right:2px}.tf-bool{display:flex;align-items:center;justify-content:center;width:100%;min-height:32px;cursor:pointer}.tf-bool input{margin:0;cursor:pointer;accent-color:var(--ink)}.tf-check{width:15px;height:15px;min-height:0;margin:0;padding:0;accent-color:var(--ink);cursor:pointer}.tf-bar input[type=checkbox],.tf-pop-check input[type=checkbox]{width:14px;height:14px;margin:0;accent-color:var(--ink)}.tf-calc{padding:4px 8px;background:var(--soft);color:var(--ink);font-variant-numeric:tabular-nums}.tf-td.has-err{background:#fdf3f2}.tf-err{color:var(--danger);font-variant-numeric:normal}.tf-total{border-top:1px solid var(--line-strong);background:var(--paper);font-weight:600}.tf-total .tf-td{padding:5px 8px;font-variant-numeric:tabular-nums}.tf-sum-label{color:var(--mid);font-weight:600;margin-right:6px}.tf-sum-label+.tf-sum-val{color:var(--ink)}.tf-addrow{display:grid;align-items:center;width:100%;height:32px;padding:0;border:0;border-top:var(--border);background:transparent;color:var(--mid);font:inherit;font-size:12px;text-align:left;cursor:pointer}.tf-addrow:hover{background:var(--soft);color:var(--ink)}.tf-addrow .tf-gutter{height:100%}.tf-plus{color:var(--mid);font-size:12px}.tf-addrow-label{padding:0 8px}.tf-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.tf-errors{display:flex;flex-direction:column;gap:1px}.tf-empty{padding:10px 12px;border:1px dashed var(--soft-2);border-radius:var(--radius-btn)}.btn.ghost.on{background:var(--soft-2);color:var(--ink)}.tf-mini{width:19px;height:19px;padding:0;line-height:1;font-size:11px;color:var(--mid);background:transparent;border:0;border-radius:4px;cursor:pointer}.tf-mini:hover:not(:disabled){background:var(--soft-2);color:var(--ink)}.tf-mini:disabled{opacity:.28;cursor:default}.tablefield .tf-mini,.entrylist .tf-mini{width:16px;height:16px;font-size:10px}.tf-acts .tf-mini,.entrylist-acts .tf-mini{opacity:0;transition:opacity .12s}.tf-row:hover .tf-acts .tf-mini,.entrylist-row:hover .entrylist-acts .tf-mini,.tf-acts .tf-mini:focus-visible,.entrylist-acts .tf-mini:focus-visible{opacity:1}.tf-grip{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:14px;height:17px;font-size:11px;line-height:1;color:var(--soft-2);border-radius:3px;cursor:grab;-webkit-user-select:none;user-select:none}.tf-grip:hover{color:var(--ink);background:var(--soft-2)}.tf-grip:active{cursor:grabbing}.tf-row,.tf-th,.entrylist-row{position:relative}.tf-row.drop-before:before,.tf-row.drop-after:after,.entrylist-row.drop-before:before,.entrylist-row.drop-after:after{content:"";position:absolute;left:0;right:0;height:2px;background:var(--ink);z-index:4;pointer-events:none}.tf-row.drop-before:before,.entrylist-row.drop-before:before{top:-1px}.tf-row.drop-after:after,.entrylist-row.drop-after:after{bottom:-1px}.tf-th.drop-before:before,.tf-th.drop-after:after{content:"";position:absolute;top:0;bottom:0;width:2px;background:var(--ink);z-index:4;pointer-events:none}.tf-th.drop-before:before{left:-1px}.tf-th.drop-after:after{right:-1px}.tf-pop{position:fixed;z-index:80;overflow:auto;display:flex;flex-direction:column;gap:6px;padding:8px;background:var(--paper);border:var(--border);border-radius:var(--radius-box);box-shadow:var(--shadow-float);font-size:12px}.tf-pop-head{display:flex;align-items:center;gap:6px}.tf-pop-title{flex:1;min-width:0;height:26px;padding:0 4px;font-size:13px;font-weight:600;background:transparent;border-color:transparent}.tf-pop-title:hover,.tf-pop-title:focus{background:var(--soft)}.tf-pop-type{width:132px;flex-shrink:0;font-size:11px}.tf-pop-field{display:flex;align-items:center;gap:6px;min-width:0}.tf-pop-field.tight{flex:1;min-width:0}.tf-pop-field input,.tf-pop-field select{flex:1;min-width:0;height:26px;font-size:11px}.tf-pop-key{width:44px;flex-shrink:0;color:var(--mid);font-size:10px}.tf-pop-row{display:flex;gap:8px;align-items:flex-end}.tf-pop-row .tf-pop-field.tight:first-child{flex:0 0 96px}.tf-pop-check{display:inline-flex;align-items:center;gap:4px;color:var(--mid);font-size:11px;white-space:nowrap}.tf-pop-check input{accent-color:var(--ink)}.tf-pop-sep{height:1px;margin:2px -8px;background:var(--line)}.tf-pop-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px}.tf-pop-grid.one{grid-template-columns:1fr}.tf-pop-item{display:flex;align-items:center;gap:6px;padding:5px 6px;border:0;border-radius:6px;background:transparent;color:var(--ink);font:inherit;font-size:12px;text-align:left;cursor:pointer}.tf-pop-item:hover:not(:disabled){background:var(--soft)}.tf-pop-item:disabled{opacity:.35;cursor:default}.tf-pop-item.danger{color:var(--danger)}.tf-pop-glyph{flex-shrink:0;width:14px;text-align:center;color:var(--mid);font-size:11px}.tf-pop-item.danger .tf-pop-glyph{color:var(--danger)}.tf-pop-foot{color:var(--mid);font-size:10px;line-height:1.5}.col-splitter{flex:0 0 14px;margin:0 -14px;align-self:stretch;cursor:col-resize;position:relative;z-index:1;border-radius:3px;min-width:0}.col-splitter:hover,.col-splitter.active{background:var(--soft-2)}body.col-resizing,body.col-resizing *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.source-field{display:flex;flex-direction:column;gap:4px}.source-strip{display:flex;align-items:center;gap:6px;width:100%;min-height:var(--row-h);padding:3px 8px;background:var(--soft);border:var(--border);border-radius:var(--radius-btn);cursor:pointer;text-align:left;font:inherit;color:inherit;transition:background .15s ease}.source-strip:hover{background:var(--soft-2)}.source-strip-label{font-weight:600}.source-strip-preview{color:var(--mid);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:42%}.source-caret{color:var(--mid)}.peek{position:fixed;z-index:45;background:var(--paper);display:flex;flex-direction:column;overflow:hidden;outline:none}.peek-side{top:0;right:0;bottom:0;width:min(720px,46vw);border-left:var(--border);box-shadow:var(--shadow-float);animation:side-in .16s ease-out}.peek-center{top:50%;left:50%;transform:translate(-50%,-50%);width:min(900px,92vw);height:min(86vh,980px);border:var(--border);border-radius:8px;box-shadow:var(--shadow-float);animation:peek-pop .16s ease-out}.peek-fullpage{top:0;right:0;bottom:0;left:0;width:100%;height:100%;animation:peek-fade .16s ease-out}.peek-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:44;background:#00000047;animation:peek-fade .16s ease-out}@keyframes side-in{0%{transform:translate(18px);opacity:.5}to{transform:none;opacity:1}}@keyframes peek-pop{0%{transform:translate(-50%,-48%) scale(.985);opacity:.5}to{transform:translate(-50%,-50%) scale(1);opacity:1}}@keyframes peek-fade{0%{opacity:.6}to{opacity:1}}.peek-head{display:flex;align-items:center;gap:8px;height:36px;padding:0 12px;border-bottom:var(--border);flex-shrink:0}.peek-modes{display:flex;align-items:center;gap:2px}.peek-modes .btn.on{background:var(--soft-2);color:var(--ink)}.peek-body{display:flex;flex-direction:column;flex:1;min-height:0}@media(max-width:900px){.peek-side{width:94vw}.peek-center{width:96vw;height:92vh}}@media(prefers-reduced-motion:reduce){.peek-side,.peek-center,.peek-fullpage,.peek-backdrop{animation:none}}.source-drawer-body{display:flex;flex:1;min-height:0}.source-list-pane{width:264px;flex-shrink:0;border-right:var(--border);display:flex;flex-direction:column;min-height:0}.source-list-pane.drag{outline:2px dashed var(--mid);outline-offset:-4px;background:var(--soft)}.source-list-tools{display:flex;align-items:center;gap:6px;padding:8px;border-bottom:var(--border);flex-wrap:wrap}.source-paste{display:flex;flex-direction:column;gap:4px;padding:8px;border-bottom:var(--border)}.source-paste textarea{font:inherit;resize:vertical}.source-paste.drag{outline:2px dashed var(--mid);outline-offset:-3px;background:var(--soft)}.source-items{flex:1;overflow:auto;min-height:0}.source-item{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:0;border-bottom:1px solid var(--soft-2);background:transparent;cursor:pointer;text-align:left;font:inherit;color:inherit;transition:background .15s ease}.source-item:hover{background:var(--soft)}.source-item.sel{background:var(--soft-2)}.source-item-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.source-view-pane{flex:1;min-width:0;display:flex;flex-direction:column}.source-view-head{display:flex;align-items:center;gap:8px;padding:6px 12px;border-bottom:var(--border)}.source-view-body{flex:1;overflow:auto;padding:12px;min-height:0}.source-preview-img{max-width:100%;border:var(--border);border-radius:4px}.peek :focus-visible{outline:2px solid var(--ink);outline-offset:1px;border-radius:3px}@media(prefers-reduced-motion:reduce){.source-strip,.source-item{transition:none}}.shortcut-field{border:var(--border);border-radius:4px;overflow:hidden}.shortcut-strip{display:flex;align-items:center;gap:6px;padding:4px 8px}.shortcut-strip-main{display:flex;align-items:center;gap:6px;flex:1;min-width:0;border:0;background:transparent;color:inherit;font:inherit;padding:0;text-align:left;cursor:pointer}.shortcut-groups{color:var(--mid);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:52%}.shortcut-panel-body{display:flex;flex:1;min-height:0}.shortcut-groups-pane{width:200px;flex-shrink:0;border-right:var(--border);display:flex;flex-direction:column;min-height:0}.peek-side .shortcut-groups-pane{width:168px}.peek-side .sckb-nav{display:none}.shortcut-groups-list{flex:0 1 auto;overflow:auto;min-height:0}.shortcut-group-item{display:flex;align-items:center;gap:6px;width:100%;padding:6px 10px;border:0;border-bottom:1px solid var(--soft-2);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.shortcut-group-item:hover{background:var(--soft)}.shortcut-group-item.sel{background:var(--soft-2)}.shortcut-group-add{display:flex;gap:4px;padding:8px;border-top:var(--border);flex-shrink:0}.shortcut-group-add input{flex:1;min-width:0}.shortcut-main{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}.shortcut-main-head{display:flex;align-items:center;gap:8px;padding:6px 12px;border-bottom:var(--border);flex-shrink:0}.shortcut-group-name{font:inherit;font-weight:600;min-width:120px;padding:2px 4px;border:1px solid transparent;border-radius:3px;background:transparent}.shortcut-group-name:hover,.shortcut-group-name:focus{border-color:var(--border);background:var(--paper)}.shortcut-table-wrap{flex:0 1 auto;overflow:auto;min-height:0}.shortcut-table{width:100%;min-width:420px;border-collapse:collapse;font-size:12px}.shortcut-table th{position:sticky;top:0;z-index:1;background:var(--paper);text-align:left;font-weight:600;color:var(--mid);padding:6px 8px;border-bottom:var(--border)}.shortcut-table td{padding:5px 8px;border-bottom:1px solid var(--soft-2);vertical-align:middle}.shortcut-table td input{width:100%;min-width:90px;font:inherit}.shortcut-table th:nth-child(1),.shortcut-table td:nth-child(1){white-space:nowrap;min-width:104px}.shortcut-table th:nth-child(2),.shortcut-table td:nth-child(2){min-width:110px}.shortcut-table th:nth-child(3),.shortcut-table td:nth-child(3){white-space:nowrap;min-width:62px}.shortcut-table tr.on td{background:var(--soft)}.shortcut-ops{width:84px;white-space:nowrap}.shortcut-ops .btn{padding:1px 5px}.shortcut-error{display:block;margin-top:2px;color:#b42318;font-size:11px;line-height:1.3}.shortcut-combo{display:inline-flex;gap:3px;flex-wrap:wrap}.shortcut-kbd{display:inline-block;min-width:18px;padding:1px 5px;border:1px solid var(--border);border-bottom-width:2px;border-radius:3px;background:var(--paper);font-size:11px;text-align:center}.shortcut-canvas{border-top:var(--border);padding:10px 12px 14px;flex-shrink:0}.shortcut-canvas-title{color:var(--mid);font-size:11px;margin-bottom:6px}.sckb{display:flex;gap:10px;align-items:flex-start}.sckb-rows{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.sckb-nav{width:150px;flex-shrink:0;display:flex;flex-direction:column;gap:4px}.sckb-row{display:flex;gap:4px;height:22px}.sckb-key{display:flex;align-items:center;justify-content:center;min-width:0;border:1px solid var(--border);border-bottom-width:2px;border-radius:3px;background:var(--soft);color:var(--mid);font-size:10px;overflow:hidden}.sckb-key.on{background:var(--ink);border-color:var(--ink);color:var(--paper)}.sckb-ghost{visibility:hidden}.shortcut-empty{padding:24px}@media(max-width:900px){.shortcut-groups-pane{width:150px}.sckb-nav{display:none}}.source-item.old{opacity:.62}.source-item.old:hover{opacity:1}.source-item-time{margin-left:auto;color:var(--mid);font-size:10px;white-space:nowrap}.source-old-toggle{display:block;width:100%;text-align:left;padding:4px 8px;border:0;border-bottom:1px solid var(--soft-2);background:var(--soft);color:var(--mid);cursor:pointer;font:inherit;font-size:11px;transition:background .15s ease}.source-old-toggle:hover{background:var(--soft-2);color:var(--ink)}.file-picker-list{display:flex;flex-direction:column;gap:4px;max-height:266px;overflow-y:auto;overflow-x:hidden;padding-right:2px;scrollbar-width:thin}.file-picker-list.expanded{max-height:none}.file-picker-list .file-preview{flex-shrink:0}
|