@heycys/gallery 0.1.0 → 0.1.1
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/THIRD-PARTY-NOTICES.md +51 -1
- package/browser/editor/components/callout/index.mjs +40 -15
- package/browser/editor/components/columns/page.mjs +41 -28
- package/browser/editor/components/details/index.mjs +2 -1
- package/browser/editor/components/dialog/index.mjs +2 -1
- package/browser/editor/components/dialog/page.mjs +0 -18
- package/browser/editor/components/divider/index.mjs +1 -1
- package/browser/editor/components/figure/page.mjs +10 -1
- package/browser/editor/components/file/page.mjs +2 -2
- package/browser/editor/components/flowchart/add.mjs +2 -2
- package/browser/editor/components/heading/index.mjs +2 -0
- package/browser/editor/components/heading/page.mjs +6 -0
- package/browser/editor/components/highlight/index.mjs +4 -20
- package/browser/editor/components/icons.mjs +5 -2
- package/browser/editor/components/image/page.mjs +2 -2
- package/browser/editor/components/installed/index.mjs +71 -25
- package/browser/editor/components/installed/page.mjs +122 -21
- package/browser/editor/components/kit.mjs +3 -0
- package/browser/editor/components/media/page.mjs +44 -14
- package/browser/editor/components/pages.mjs +2 -2
- package/browser/editor/components/registry.mjs +56 -30
- package/browser/editor/components/section/index.mjs +2 -1
- package/browser/editor/components/set-apart.mjs +24 -0
- package/browser/editor/components/table/index.mjs +5 -3
- package/browser/editor/components/table/page.mjs +29 -18
- package/browser/editor/page/annotate/anchors.mjs +4 -3
- package/browser/editor/page/annotate/index.mjs +61 -34
- package/browser/editor/page/autosave.mjs +50 -4
- package/browser/editor/page/beside.mjs +5 -5
- package/browser/editor/page/block-menu/colors.mjs +3 -1
- package/browser/editor/page/block-menu/index.mjs +8 -6
- package/browser/editor/page/blocks.mjs +16 -7
- package/browser/editor/page/caret.mjs +4 -1
- package/browser/editor/page/changes/bar.mjs +102 -0
- package/browser/editor/page/changes/ghost.mjs +206 -0
- package/browser/editor/page/changes/gone-words.mjs +94 -0
- package/browser/editor/page/changes/index.mjs +447 -0
- package/browser/editor/page/changes/words.mjs +27 -0
- package/browser/editor/page/clipboard/import/colors.mjs +3 -3
- package/browser/editor/page/clipboard/index.mjs +32 -13
- package/browser/editor/page/clipboard/own/blocks.mjs +14 -5
- package/browser/editor/page/clipboard/own/describe.mjs +16 -7
- package/browser/editor/page/clipboard/own/export.mjs +6 -6
- package/browser/editor/page/clipboard/own/selection.mjs +2 -2
- package/browser/editor/page/clipboard/own/writers.mjs +0 -11
- package/browser/editor/page/columns/index.mjs +1 -1
- package/browser/editor/page/commit.mjs +19 -4
- package/browser/editor/page/conflicts.mjs +6 -26
- package/browser/editor/page/convert.mjs +8 -7
- package/browser/editor/page/core.mjs +55 -17
- package/browser/editor/page/drag/index.mjs +40 -24
- package/browser/editor/page/drag/preview.mjs +9 -4
- package/browser/editor/page/editor.mjs +70 -15
- package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
- package/browser/editor/page/emoji-picker/grid.mjs +7 -5
- package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
- package/browser/editor/page/emoji-picker/icons.mjs +0 -1
- package/browser/editor/page/emoji-picker/index.mjs +11 -9
- package/browser/editor/page/emoji-picker/styles.mjs +161 -2
- package/browser/editor/page/emoji-picker/support.mjs +6 -4
- package/browser/editor/page/emoji-picker/upload.mjs +12 -11
- package/browser/editor/page/fills.mjs +5 -3
- package/browser/editor/page/fold/index.mjs +348 -0
- package/browser/editor/page/fold/rule.mjs +125 -0
- package/browser/editor/page/folded.mjs +23 -0
- package/browser/editor/page/format-bar/bar.mjs +2 -1
- package/browser/editor/page/format-bar/index.mjs +1 -1
- package/browser/editor/page/geometry.mjs +8 -6
- package/browser/editor/page/handle/index.mjs +17 -6
- package/browser/editor/page/hints/index.mjs +1 -1
- package/browser/editor/page/insert/index.mjs +30 -17
- package/browser/editor/page/long-runs.mjs +75 -0
- package/browser/editor/page/look.mjs +15 -3
- package/browser/editor/page/margin.mjs +45 -24
- package/browser/editor/page/menu.mjs +69 -25
- package/browser/editor/page/merge.mjs +24 -0
- package/browser/editor/page/notices.mjs +1 -1
- package/browser/editor/page/offered.mjs +1 -1
- package/browser/editor/page/outline/folds.mjs +11 -10
- package/browser/editor/page/outline/index.mjs +131 -45
- package/browser/editor/page/outline/list.mjs +23 -11
- package/browser/editor/page/outline/read.mjs +1 -1
- package/browser/editor/page/outline/strip.mjs +7 -1
- package/browser/editor/page/panel.mjs +5 -4
- package/browser/editor/page/resize/index.mjs +1 -1
- package/browser/editor/page/selection/delete.mjs +8 -6
- package/browser/editor/page/selection/index.mjs +10 -3
- package/browser/editor/page/session.mjs +54 -3
- package/browser/editor/page/table/cell-bar.mjs +4 -1
- package/browser/editor/page/table/cells.mjs +1 -1
- package/browser/editor/page/table/icons.mjs +1 -1
- package/browser/editor/page/table/index.mjs +13 -8
- package/browser/editor/page/table/widths.mjs +9 -4
- package/browser/editor/page/text-select/index.mjs +18 -3
- package/browser/editor/page/tooltip.mjs +1 -1
- package/browser/editor/page/type-grid.mjs +4 -3
- package/browser/editor/page/typing/code-edges.mjs +63 -17
- package/browser/editor/page/typing/index.mjs +12 -6
- package/browser/editor/page/typing/leave.mjs +1 -1
- package/browser/shared/annotations.mjs +8 -10
- package/browser/shared/code-folds.mjs +5 -1
- package/browser/shared/colors.mjs +15 -13
- package/browser/shared/component-catalog.mjs +24 -10
- package/browser/shared/components/callout.mjs +4 -2
- package/browser/shared/components/index.mjs +61 -7
- package/browser/shared/components/installed.mjs +75 -5
- package/browser/shared/components/page.mjs +10 -1
- package/browser/shared/components/table.mjs +1 -1
- package/browser/shared/components/text.mjs +2 -2
- package/browser/shared/document-look.mjs +178 -0
- package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
- package/browser/shared/emoji/data/README.md +4 -2
- package/browser/shared/emoji/data/categories.json +1 -1
- package/browser/shared/emoji/data/keywords-en.json +1 -1
- package/browser/shared/emoji/data/keywords-zh.json +1 -1
- package/browser/shared/emoji/data/names.json +1 -1
- package/browser/shared/emoji/data/positions.json +1 -1
- package/browser/shared/emoji/data/twemoji-index.json +1 -1
- package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
- package/browser/shared/emoji/data.mjs +10 -12
- package/browser/shared/emoji/emoji.mjs +8 -7
- package/browser/shared/emoji/icon-value.mjs +4 -3
- package/browser/shared/html-tree.mjs +11 -5
- package/browser/shared/i18n/en.mjs +67 -8
- package/browser/shared/long-runs.mjs +39 -0
- package/browser/shared/new-names.mjs +5 -2
- package/browser/shared/outline.mjs +194 -0
- package/browser/shared/preferences.mjs +10 -4
- package/browser/shared/session.mjs +5 -4
- package/browser/shared/workspace-look.mjs +91 -0
- package/browser/shared/zoom.mjs +5 -5
- package/dist/chunk-3HIRPVLU.mjs +2 -0
- package/dist/chunk-4FS7Z7WR.mjs +2 -0
- package/dist/{chunk-LHTFLRB6.mjs → chunk-5MHMDLZD.mjs} +2 -2
- package/dist/{chunk-YXAUQPVK.mjs → chunk-5ZKJ3H4P.mjs} +3 -3
- package/dist/{chunk-ZBIM6ARY.mjs → chunk-64K7IPLO.mjs} +55 -16
- package/dist/{chunk-QYKCJ7FG.mjs → chunk-6QXGZM36.mjs} +1 -1
- package/dist/chunk-6RGJOMJP.mjs +16 -0
- package/dist/{chunk-EUX7IC5J.mjs → chunk-7DTINW6U.mjs} +2 -2
- package/dist/{chunk-6CYG3Z4V.mjs → chunk-AJ73XJF3.mjs} +1 -1
- package/dist/chunk-AUZGSZJH.mjs +13 -0
- package/dist/{chunk-7QQBR7PB.mjs → chunk-BFE45AKL.mjs} +1 -1
- package/dist/chunk-BGGDRNYQ.mjs +10 -0
- package/dist/{chunk-L4DVONOG.mjs → chunk-BXO2ZY5P.mjs} +1 -1
- package/dist/chunk-CEH4MRCC.mjs +2 -0
- package/dist/chunk-CY2FNNAB.mjs +16 -0
- package/dist/{chunk-LC7YNQFG.mjs → chunk-DFUDV4LX.mjs} +1 -1
- package/dist/chunk-DKXG4XDG.mjs +2 -0
- package/dist/chunk-E7LWZRXY.mjs +4 -0
- package/dist/chunk-EZQ34M3F.mjs +124 -0
- package/dist/chunk-FDLXYYG4.mjs +4 -0
- package/dist/chunk-FUKQNOQS.mjs +9 -0
- package/dist/{chunk-DB4WKGYF.mjs → chunk-GB5SOYQJ.mjs} +2 -2
- package/dist/{chunk-ACOPDCNB.mjs → chunk-IVDLMMBD.mjs} +1 -1
- package/dist/chunk-JPOSLGOC.mjs +6 -0
- package/dist/chunk-JVHHHGEA.mjs +3 -0
- package/dist/chunk-L3QKH4OK.mjs +26 -0
- package/dist/{chunk-B3VTYBYR.mjs → chunk-LCTHTZIL.mjs} +2 -2
- package/dist/chunk-LEF6DRCK.mjs +59 -0
- package/dist/chunk-LS4F7JUM.mjs +2 -0
- package/dist/chunk-NO5NJCHO.mjs +2 -0
- package/dist/{chunk-UNUEWH4S.mjs → chunk-NQPVAU63.mjs} +1 -1
- package/dist/chunk-O35FIXRB.mjs +2 -0
- package/dist/chunk-PL6GHLGD.mjs +15 -0
- package/dist/{chunk-G7TOXONE.mjs → chunk-QJIR2BLP.mjs} +1 -1
- package/dist/chunk-QUPLVPB2.mjs +7 -0
- package/dist/chunk-R7BNENLY.mjs +4 -0
- package/dist/chunk-S6O4UHLC.mjs +2 -0
- package/dist/{chunk-HMHK3EQ6.mjs → chunk-SGJWQKEI.mjs} +1 -1
- package/dist/chunk-SYGN7GLU.mjs +2 -0
- package/dist/chunk-TYK6VNAB.mjs +10 -0
- package/dist/{chunk-EVJ3BX3M.mjs → chunk-U6KNPJPR.mjs} +1 -1
- package/dist/{chunk-YZ5Z6H4W.mjs → chunk-UALRNVSE.mjs} +1 -1
- package/dist/chunk-UMHUSOPJ.mjs +2 -0
- package/dist/chunk-V3HXVQEM.mjs +2 -0
- package/dist/{chunk-UXUK4PMC.mjs → chunk-V5JTW2LH.mjs} +1 -1
- package/dist/chunk-V5VXUJKG.mjs +2 -0
- package/dist/chunk-VBXMADMP.mjs +2 -0
- package/dist/chunk-VNV55RUA.mjs +2 -0
- package/dist/chunk-VPD2PS35.mjs +2 -0
- package/dist/chunk-W3BGBJQW.mjs +2 -0
- package/dist/chunk-W4VKN3GF.mjs +7 -0
- package/dist/chunk-W5BXXPDJ.mjs +3 -0
- package/dist/{chunk-Z52HTUW7.mjs → chunk-XNROSH2T.mjs} +2 -2
- package/dist/chunk-XUNHRCOG.mjs +6 -0
- package/dist/{chunk-6U2SLSDN.mjs → chunk-Y6RLRPG3.mjs} +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/math.js +18 -2
- package/kit/report.css +248 -137
- package/kit/runtime.js +126 -51
- package/kit/tables.js +51 -1
- package/kit/ui.js +97 -0
- package/package.json +1 -1
- package/release.json +8 -8
- package/sdk/doc-kit.d.ts +9 -3
- package/skill/SKILL.md +22 -10
- package/skill/references/building-components.md +46 -6
- package/skill/references/example-report.html +1 -1
- package/skill/references/writing-html.md +4 -4
- package/skill/sdk/doc-kit.d.ts +9 -3
- package/web/assets/index-Bh74DfsV.css +1 -0
- package/web/assets/index-UW0RyFFt.js +13 -0
- package/web/index.html +2 -2
- package/browser/editor/components/callout/page.mjs +0 -13
- package/dist/chunk-2PBALTR3.mjs +0 -57
- package/dist/chunk-3LA3EMDE.mjs +0 -15
- package/dist/chunk-5FRMCDPY.mjs +0 -16
- package/dist/chunk-5LEK2CBS.mjs +0 -2
- package/dist/chunk-5OFN5AHC.mjs +0 -2
- package/dist/chunk-5SIYS5HN.mjs +0 -2
- package/dist/chunk-5TEK3RAD.mjs +0 -2
- package/dist/chunk-7GHT2UCA.mjs +0 -15
- package/dist/chunk-ATCJYAR4.mjs +0 -2
- package/dist/chunk-C7HWOBIF.mjs +0 -2
- package/dist/chunk-E7VYDG2X.mjs +0 -2
- package/dist/chunk-FQGQH4KM.mjs +0 -2
- package/dist/chunk-GPF4YWWB.mjs +0 -9
- package/dist/chunk-GYQV7Y4J.mjs +0 -120
- package/dist/chunk-HQQMJCQJ.mjs +0 -10
- package/dist/chunk-IERUOGC3.mjs +0 -6
- package/dist/chunk-ITNLYXXV.mjs +0 -3
- package/dist/chunk-NFIBI4IP.mjs +0 -26
- package/dist/chunk-O52JMOCZ.mjs +0 -2
- package/dist/chunk-QMQUXTU4.mjs +0 -12
- package/dist/chunk-QVWVFC5K.mjs +0 -6
- package/dist/chunk-QZY6Q64C.mjs +0 -2
- package/dist/chunk-TDQP3DKQ.mjs +0 -10
- package/dist/chunk-V4CPWKMZ.mjs +0 -2
- package/dist/chunk-VACRB2NE.mjs +0 -3
- package/dist/chunk-W63L7367.mjs +0 -7
- package/dist/chunk-W7CXPCRV.mjs +0 -6
- package/dist/chunk-XINNG4F2.mjs +0 -4
- package/dist/chunk-YL2DPWVS.mjs +0 -4
- package/web/assets/index-B6Ai3wsa.js +0 -13
- package/web/assets/index-SYPC3EZy.css +0 -1
package/skill/SKILL.md
CHANGED
|
@@ -9,14 +9,14 @@ Create a self-contained HTML document whose claims, numbers, and visual encoding
|
|
|
9
9
|
|
|
10
10
|
## Before anything: the gallery command
|
|
11
11
|
|
|
12
|
-
This skill holds the instructions; the tools are the npm package `@heycys/gallery`, the `gallery` command. This skill needs `@heycys/gallery` ^0.1.
|
|
12
|
+
This skill holds the instructions; the tools are the npm package `@heycys/gallery`, the `gallery` command. This skill needs `@heycys/gallery` ^0.1.1: a version npm's range `^0.1.1` takes, 0.1.1 or a later 0.1.x.
|
|
13
13
|
|
|
14
14
|
1. Run `gallery --version`. When it prints such a version, go on to step 3.
|
|
15
|
-
2. When `gallery` is not found, or prints a version older than `^0.1.
|
|
16
|
-
- When it prints a version newer than `^0.1.
|
|
15
|
+
2. When `gallery` is not found, or prints a version older than `^0.1.1` takes, install it with `npm i -g @heycys/gallery@^0.1.1`, then run `gallery --version` again. When the user has already said to install it (in this request or earlier in the conversation), run it without asking again; otherwise ask the user before you install anything: say that Gallery's command is missing (or which version it is) and that you would run that command, and run it once they agree.
|
|
16
|
+
- When it prints a version newer than `^0.1.1` takes, install nothing (that would take Gallery back to an older version): tell the user this skill is older than their Gallery and ask them to run `gallery skill install` (with `--project` when the skill is the project's, in its `.claude/skills/`), then to start a new Agent session, which reads the new skill.
|
|
17
17
|
- No Node, or `node --version` older than 22.13: tell the user to install the current LTS from https://nodejs.org (or with their system's package manager), then start again.
|
|
18
|
-
- npm says `EACCES` (macOS and Linux, where npm's global folder belongs to the system): never use `sudo`. Tell the user, and offer either of these: give npm a folder of their own (`npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH` in their shell profile, open a new terminal, install again); or run every command as `npx -y @heycys/gallery@^0.1.
|
|
19
|
-
- Use `npx -y @heycys/gallery@^0.1.
|
|
18
|
+
- npm says `EACCES` (macOS and Linux, where npm's global folder belongs to the system): never use `sudo`. Tell the user, and offer either of these: give npm a folder of their own (`npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH` in their shell profile, open a new terminal, install again); or run every command as `npx -y @heycys/gallery@^0.1.1 <command> …` instead of `gallery <command> …`.
|
|
19
|
+
- Use `npx -y @heycys/gallery@^0.1.1 <command> …` likewise wherever a global install is not allowed (a sandbox, CI). It is slower: a few seconds more per command.
|
|
20
20
|
- On Windows, `gallery` works in PowerShell right after the install, in the same terminal. Only when PowerShell says running scripts is disabled (`gallery.ps1`): run `gallery.cmd` with the same arguments, or ask the user to run `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` once.
|
|
21
21
|
- After an upgrade, run `gallery open --no-browser` once: the server of the version before stops by itself, and this starts the new one. Tell the user that `gallery skill install` brings this skill to the new version too (an Agent session started after it reads it).
|
|
22
22
|
3. The documents live in a workspace, a folder: `--workspace <dir>` (every command takes it), else `GALLERY_WORKSPACE`, else the nearest folder up from the current one holding `gallery.json`, else `Gallery` in the user's Documents folder, `~/Documents/Gallery` (made on first use; on Windows the Documents folder Explorer shows, OneDrive's when OneDrive backs it up). `gallery new`, `gallery import`, `gallery list` and `gallery open` print it as `工作区:<path>`. When a command prints `Cannot write the workspace <path> (…)` (a sandbox that allows writes only in the project, or a system that has not let the terminal into Documents), ask the user to allow Gallery to write there, or pass `--workspace <a folder in the project>` to every command.
|
|
@@ -27,16 +27,17 @@ This skill holds the instructions; the tools are the npm package `@heycys/galler
|
|
|
27
27
|
|
|
28
28
|
A document has one writer at a time: never let two Agents, or an Agent and a script, write the same `doc.html` at once. The user may edit it in the browser meanwhile; Gallery merges their edits with yours.
|
|
29
29
|
|
|
30
|
-
A document is the folder `<workspace>/<slug>/`: `doc.html`, the page you write, and `doc.json`, its title and description. Documents link to each other by ordinary relative links between these files (`../<slug>/doc.html`: writing-html.md). A document made before Gallery 0.1 has `report.html` and `report.json` instead: write those (Gallery reads and writes them under their names; never rename them). Below, `doc.html` and `doc.json` stand for either.
|
|
30
|
+
A document is the folder `<workspace>/<slug>/`: `doc.html`, the page you write, and `doc.json`, its title and description (and the reader's 字体与布局 as `look`, which you keep when you rewrite it, as you keep the workspace's default `look` in `gallery.json`: writing-html.md). Documents link to each other by ordinary relative links between these files (`../<slug>/doc.html`: writing-html.md). A document made before Gallery 0.1 has `report.html` and `report.json` instead: write those (Gallery reads and writes them under their names; never rename them). Below, `doc.html` and `doc.json` stand for either.
|
|
31
31
|
|
|
32
32
|
## Workflow
|
|
33
33
|
|
|
34
34
|
1. Read 写作偏好 before anything else. When `<workspace>/preferences.md` is not there yet, `gallery new` (step 2) makes it from Gallery's defaults and prints its path (`gallery import` and `gallery list` print it too; `gallery open` does not): read it then, before you write. When `gallery new` prints `写作偏好:空`, the user emptied it: write from the request, this skill and the materials, and leave the file as it is.
|
|
35
35
|
2. Create the document as soon as you know its title: `gallery new <slug> "<title>" "<description>"` (a lowercase kebab-case slug).
|
|
36
|
+
- Its place in the sidebar's tree ([Organizing documents](#organizing-documents)): where the user says, with `--under <document>` or `--after <document>`; when they say none and the workspace has documents, run `gallery list --tree` first and put it under the document whose topic it belongs to; at the top level when none fits.
|
|
36
37
|
- It prints where it wrote, the workspace, the path of 写作偏好 and the next steps, starts the browser service (or uses the one running), and ends with its `交给用户` line: the address where the user watches and edits the document (step 3). The line before it, the page alone, is yours.
|
|
37
38
|
- If the server could not start, it says why; once that is fixed, `gallery open <slug>` starts it and prints the address.
|
|
38
39
|
- The page renders straight from `doc.html`, reloads on every save, notes failing checks at its bottom left, and lets the user edit the document in place ([Revising a document](#revising-a-document)).
|
|
39
|
-
- When 写作偏好 asks for another title or description than the ones you gave, change them
|
|
40
|
+
- When 写作偏好 asks for another title or description than the ones you gave, change them with `gallery set <slug> --title "…" --description "…"`.
|
|
40
41
|
- When the material is a file to be turned into the document (Markdown, HTML, Word, PDF, CSV, EPUB, or a ZIP of pages), create it with `gallery import <file> [<slug> ["<title>"]]` instead (it says the same, and what of the file it could not bring, by line), then edit what it made.
|
|
41
42
|
3. Now, before you read further, send the user the address from the `交给用户` line in a message of its own, in the user's language: they watch the document being written there. In a cloud sandbox they cannot reach, skip it.
|
|
42
43
|
4. Write `<workspace>/<slug>/doc.html` as ordinary HTML, replacing the starter section.
|
|
@@ -71,13 +72,15 @@ Paths are absolute, as this system writes them: use them as they are.
|
|
|
71
72
|
| `This workspace's Gallery server runs on port …` | the server started or reused: nothing to wait for or keep running |
|
|
72
73
|
| `Preview: not started …` | no server, so no `交给用户` address: run `gallery open <slug> --no-browser` and give the user the address it prints (not in a cloud sandbox they cannot reach) |
|
|
73
74
|
| `Next: …`, `Hand in: …` | the steps after `gallery new` or `gallery import`: follow them |
|
|
75
|
+
| `Placed it …`, `Moved …`, `位置:…` | where `gallery new --under`/`--after` or `gallery move` put the document in the sidebar's tree, and where a document is (`gallery list`): say it in the handoff |
|
|
76
|
+
| `Set <slug>:` and its lines | what `gallery set` changed; re-read the files its `Re-read` line names before you edit them |
|
|
74
77
|
| `Cannot write the workspace <path> (…)` | ask the user to allow it, or pass `--workspace <a folder you may write>` |
|
|
75
78
|
| `FAIL <slug>: N problems` | the checks failed, nothing exported (exit 1): fix each |
|
|
76
79
|
| `OK <slug>`, `Checked N documents: …` | `gallery check`'s tally: those passed |
|
|
77
80
|
| `fix …` | act on it (a path of this machine, a heavy picture) |
|
|
78
81
|
| `note …` | advice, never a failure |
|
|
79
82
|
| `note … kept by the script: .x` | your script selects that block by these names, so the user cannot delete or convert it: rename a class or id the script does not select it by |
|
|
80
|
-
| `icon … the page's header none` |
|
|
83
|
+
| `icon … the page's header none` | `gallery set <slug> --icon <that icon>` writes it in the header too, `--icon none` takes it out of both |
|
|
81
84
|
| `Re-read <files> …` | the tools wrote these: re-read exactly them before editing |
|
|
82
85
|
| `preview …`, `annotations …` | said once: which of your plain HTML the browser page made the kit's markup (never the user's edits); 批注 Gallery's server deleted, their words gone from the blocks they are on (`gallery export`, `gallery check` and `gallery qa` say it right after the write) |
|
|
83
86
|
| `交给用户(离线文件):<path>` | the deliverable (the export's last line; qa's last lines, after its verdict) |
|
|
@@ -92,7 +95,7 @@ Paths are absolute, as this system writes them: use them as they are.
|
|
|
92
95
|
|
|
93
96
|
## Revising a document
|
|
94
97
|
|
|
95
|
-
When the user names a document by its title or topic, find it with `gallery list <words>` (words of its title or topic; `gallery list` alone lists every document, the one edited last first): it prints each document's slug, title, description, address, last edit and file. An address the user gives (`http://127.0.0.1:<port>/#<title words>-<page id>`, the workbench's address bar or 复制块链接, `/<block id>` after it for a block) names its document by the id at its end, and the words before it may be out of date: `gallery list <address>` prints that document, or says it is in the trash, and every command that takes a slug takes the address, or the link after its `#`, as well. The id comes from the folder's name, so an address from another workspace can name this workspace's folder of that name: before you change anything, compare the title `gallery list <address>` prints, and its `工作区:` line, with what the user means. A path the user gives (the workbench's 复制底稿路径 copies one) is that document's `doc.html`; its folder's name is its slug, the folder holding it the workspace (pass it as `--workspace` when it is not the one the commands find).
|
|
98
|
+
When the user names a document by its title or topic, find it with `gallery list <words>` (words of its title or topic; those whose title, description or slug holds them come first, then those whose text does, with `正文:` and the first place; `gallery list` alone lists every document, the one edited last first): it prints each document's slug, title, description, place in the tree, address, last edit and file. A search of the `doc.html` files themselves (grep) is fine too. An address the user gives (`http://127.0.0.1:<port>/#<title words>-<page id>`, the workbench's address bar or 复制块链接, `/<block id>` after it for a block) names its document by the id at its end, and the words before it may be out of date: `gallery list <address>` prints that document, or says it is in the trash, and every command that takes a slug takes the address, or the link after its `#`, as well. The id comes from the folder's name, so an address from another workspace can name this workspace's folder of that name: before you change anything, compare the title `gallery list <address>` prints, and its `工作区:` line, with what the user means. A path the user gives (the workbench's 复制底稿路径 copies one) is that document's `doc.html`; its folder's name is its slug, the folder holding it the workspace (pass it as `--workspace` when it is not the one the commands find).
|
|
96
99
|
|
|
97
100
|
Before you change anything, run `gallery open <slug> --no-browser` and give the user the address on its `交给用户` line, even when they say the page is open: it reuses the running server without opening another tab, and it keeps the document as it stands so that the first `gallery qa` pictures what you change. It prints no `写作偏好` line: read `<workspace>/preferences.md` before you change anything.
|
|
98
101
|
|
|
@@ -108,7 +111,15 @@ Write a block you add or convert as [the example](references/example-report.html
|
|
|
108
111
|
- A change that takes several edits (blocks wrapped in a disclosure, a section moved, a Sheet area's tabs and panels): make them one right after another. The browser page waits until the file is whole again before it shows it or merges the user's edits into it. A script as above may make a move in one write, cutting and pasting, when every span it cuts and every anchor it pastes at appears once in the file.
|
|
109
112
|
- A revision may need changes the user did not name: a term defined where it now first appears, a reference to what was renamed. You may make them; name each in the handoff.
|
|
110
113
|
- When the change touches data, recheck the summary, charts, units and denominators using it. A summary made simpler still rests each comparison on a number the document shows, and keeps what each number is (a range, a basin, one seed's value, a mean), not only the number. Then export and run `gallery qa`; name the changed blocks in the handoff.
|
|
111
|
-
- The user's 批注 on a document are in `<workspace>/<slug>/annotations.json` (also what the workbench's 复制批注 hands over): `items`, each `{ id, text, anchor: { blocks, quote, … } }`, `text` the user's suggestion
|
|
114
|
+
- The user's 批注 on a document are in `<workspace>/<slug>/annotations.json` (also what the workbench's 复制批注 hands over): `items`, each `{ id, text, anchor: { blocks, quote, … } }`, `text` the user's suggestion, `quote` the words it is on. When the user asks you to work through them, carry out each `text` where it is anchored; leave one that does not fit its words and ask about it in the handoff; where one conflicts with the request, the request wins: name it. Never edit `annotations.json`. Gallery's server deletes a 批注 whose words are gone, whether the page is open or not: its words must stay in the blocks it is on (`anchor.blocks`), and words moved into another block, a new callout for one, are gone for it (only a 批注 whose blocks are all gone, a block replaced whole, follows its words to where they appear once in the document). `gallery export`, `gallery check` and `gallery qa` list each deleted, once, right after the write that deleted it; run `gallery check <slug>` once more right before the handoff. One you carried out whose words remain stays until the user deletes it. In the handoff, say which you carried out (those still shown, for the user to delete), which you left and which went with their words.
|
|
115
|
+
|
|
116
|
+
## Organizing documents
|
|
117
|
+
|
|
118
|
+
The workbench's sidebar shows the documents as a tree: a document may sit under another. `gallery list --tree` prints it as the sidebar shows it (`gallery list --tree <document>`: that one and those under it); `gallery list` prints a `位置:` line for a document under another. A document is named as every command names one: its slug, its link or the user's address.
|
|
119
|
+
|
|
120
|
+
- A new document goes where the user says: `gallery new <slug> "<title>" "<description>" --under <document>` (last under it; `--first`, first) or `--after <document>` (right after it, at its level). When they name no place, run `gallery list --tree` first when the workspace has documents, and put it under the document whose topic it belongs to (a week's notes under their project); at the top level when none fits. Say in the handoff where it went.
|
|
121
|
+
- Move documents only when the user asks you to organize them: `gallery move <document> --under <document>` (or `--top`), `--after <document>` or `--first` for its place there, each with the documents under it. No file changes, and links between documents still work. Name every move in the handoff.
|
|
122
|
+
- Change a document's title, page icon or description with `gallery set <document> --title "…" --icon <emoji, or none> --description "…"` (any of them): it writes the header of `doc.html` and `doc.json` in step, and the open page and the sidebar show it. Never edit `doc.json`'s title or icon, or the header, by hand for that. Re-read `doc.html` after it before you edit it.
|
|
112
123
|
|
|
113
124
|
## Output contract
|
|
114
125
|
|
|
@@ -122,6 +133,7 @@ In the handoff, give:
|
|
|
122
133
|
- the deliverable: the path on the `交给用户(离线文件):` line that `gallery export` prints last and `gallery qa` prints after its verdict, copied whole (no `…`, never rebuilt in another folder); and the address on the `交给用户` line of `gallery new` or `gallery open` again (you sent it at the start), where the user edits the document (not in a cloud sandbox they cannot reach). The export holds the document as of your last export: an edit after it, the user's in the browser included, needs another export;
|
|
123
134
|
- what `gallery qa` flagged and what you fixed, and the pictures you opened, by name (never a width or a block whose pictures you did not open); or that it could not run;
|
|
124
135
|
- the sentences that are your own inference and not stated by the materials, with where they are;
|
|
136
|
+
- where a document you made sits in the sidebar's tree when you chose its place, and every move you made;
|
|
125
137
|
- for a revision, the blocks you changed, the changes the user did not name, what a conversion dropped, and what a change of structure left side by side (two headings of one name, one right after the other, after a move).
|
|
126
138
|
|
|
127
139
|
Before you hand over, do the review 写作偏好 asks for before handing in (a reading by a subagent, a check of the numbers), when it asks for one.
|
|
@@ -11,7 +11,7 @@ The interface is experimental in Gallery 0.x: what this page says may change bet
|
|
|
11
11
|
When the user wants a document that uses the block too, the document comes first: `gallery new`, its address sent, its skeleton written (SKILL.md, Workflow steps 1–4). Then make the package as below, and write the instance in its section at step 6.
|
|
12
12
|
|
|
13
13
|
1. `gallery component list` first: what the workspace has now, each with its version, whether the menus can insert it, and what is there and cannot be used, with why. When one does what the user asks, use it: `gallery component show <id>` prints its parts, how to write it and its example.
|
|
14
|
-
2. `gallery component new <id>`: a new package in `<workspace>/components/<scope>/<name>/`, its `id` being `<scope>/<name>`, the scope `local` when you name none. It writes a block that passes the check, for you to replace. Add `--script` only when the block must do something when a reader uses it: a static block runs no code, is the one to start with, and is all most blocks need.
|
|
14
|
+
2. `gallery component new <id>`: a new package in `<workspace>/components/<scope>/<name>/`, its `id` being `<scope>/<name>`, the scope `local` when you name none. It writes a block that passes the check, for you to replace. Add `--script` only when the block must do something when a reader uses it: a static block runs no code, is the one to start with, and is all most blocks need. Add `--flow` when it holds blocks of the document's own under its markup (a card around any content): a slot, `body` (Slots, below).
|
|
15
15
|
3. Write its files (below): the manifest, `template.html`, `example.html`, its style and, with `--script`, `kit.js`, then what a writer needs to know.
|
|
16
16
|
4. `gallery component check <id>`, until it prints `OK`. It says each problem at its file and line; one with no line is of that file, or of the page, as a whole. Then open `overview-light.png` and `overview-dark.png` in the folder it prints, each the pictures of 360, 736 and 1024px wide of a theme side by side, `example.html` above the line and `template.html` below it, then at full size each width where they show something to fix, and `edit-1024-light.png` and `edit-360-light.png`, as the editing page draws it, `context.canEdit()` true: what the block draws only where a reader can edit (a handle, a button), which an export leaves out. A block that draws nothing more there gives the export's pictures again, and the check says so. It has run them and looked at nothing for you. In the handoff name the pictures you opened.
|
|
17
17
|
5. Try each gesture a reader makes, in the page, with `gallery component try`, one command for each: `--drag <selector> --to <selector>` (a card dragged to another column or place), `--press <selector>` (a dot, a button) or `--key <selector> <key>` (Enter, Space or an arrow on a control the block draws), as `gallery component try <slug> --drag .kanban-card --to ".kanban-column:nth-child(3)"`. Write the instance into the document first, where step 6 puts it (when the user wants no document, into one of its own made with `gallery new`, named in the handoff), and copy `doc.html`; name the instance after the slug by its `data-block-id` when the document holds more than one. Each selector is the first element of the instance that it finds, as `kit.js` draws it: `Nothing in the instance is …` lists the classes the instance shows. The command opens the document's page alone, editable, in a Chrome or Edge of its own, headless, makes the gesture there with the pointer or the keys (a drag in steps, released as it comes onto its target), waits until `doc.html` has it, and prints what it wrote: `Wrote: tasks (-1 +1 of its 8 lines); nothing outside the instance changed (data-block-id aside)`, each part with the lines the gesture took out and put in. Then it presses Ctrl+Z once and says `Undone: one Ctrl+Z, and doc.html is as it was (data-block-id aside)`: the document is left as it was, and `--keep` leaves the write instead. Open the picture its `Picture of the instance after the …` line names. A `note` line asks what the check's notes ask (a write that lays a part out anew: change the write as Writing back says). Exit 1 is a problem to fix in the package: a gesture that wrote nothing says what came of it (no `context.edit` came of it, the page refused one and the console says why, an HTML5 drag was dropped nowhere: a list a card is dropped on cancels `dragenter` as well as `dragover`), and an undo that did not give the file back says what still differs; fix it, run `gallery component check <id>`, and try the gesture again. A `FAIL` that says `doc.html` holds what the gesture wrote is a trial cut off after its write (the page offline, a card held for the reader, a load of its own): that write is yours to put back, `doc.html` read again first, as the next paragraph says, before you try again. Exit 2 is a mistake in the command. Exit 3 (`UNVERIFIED`) is a trial not seen through that left nothing of the gesture in `doc.html`, its line saying what the file holds, what someone else wrote meanwhile included, which stays: run it once more. Each try shows on every page open on the document, the user's at the address you sent too: the write, then the undo. Say so in the handoff when the user may have watched it.
|
|
@@ -26,7 +26,7 @@ Tell the user the component's name and where it is. A change to a package reache
|
|
|
26
26
|
| File | What it is |
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| `component.json` | the manifest, plain data: all that Gallery itself reads of the package |
|
|
29
|
-
| `template.html` | what "/" puts in a document: one instance, with what a new one holds. `gallery component check` requires it: with none, or one a new block cannot be, no menu offers the block, and `gallery component list` and 设置 ›
|
|
29
|
+
| `template.html` | what "/" puts in a document: one instance, with what a new one holds. `gallery component check` requires it: with none, or one a new block cannot be, no menu offers the block, and `gallery component list` and 设置 › 组件列表 say so |
|
|
30
30
|
| `example.html` | an instance as a writer would fill it: what `gallery component show` prints and what `gallery component check` runs |
|
|
31
31
|
| writing.md | how to write it, for an Agent: what it is for, when to use it, what goes in each part. `gallery component show` prints it |
|
|
32
32
|
| `style.css` | its look, optional |
|
|
@@ -89,6 +89,7 @@ Each part is counted across the instance on its own: the check does not hold the
|
|
|
89
89
|
| `text` | words the user types in, in the browser. It holds words and marks alone (`strong`, `em`, `b`, `i`, `u`, `s`, `code`, `a`, `sub`, `sup`, `br`): a heading, a paragraph, a label. With anything else in it, a block, a field, a picture, a comment, an element it does not close, the editor leaves it read-only, and the check fails it |
|
|
90
90
|
| `none` | the component's: read it, draw from it. The user changes it through the source alone |
|
|
91
91
|
| `data` | what a script reads its data from and writes back to (a table, a `<script type="application/json">`): the component's alone, written by `context.edit` and by nothing else, told to it when it changes |
|
|
92
|
+
| `flow` | a slot: blocks of the document's own in the instance, a `<div data-doc-slot="<name>">` of its markup and no `at` (Slots, below) |
|
|
92
93
|
|
|
93
94
|
What stands in an instance belongs by region:
|
|
94
95
|
|
|
@@ -97,12 +98,51 @@ What stands in an instance belongs by region:
|
|
|
97
98
|
| a `text` part | the editor's: Enter, Backspace, undo and the selection work as in any text |
|
|
98
99
|
| a `data` part | the component's, and only `context.edit` changes its content. A `text` part in one, or around one, is no text part: the file holds one or the other there |
|
|
99
100
|
| what the manifest's `runtime` names, and all else in the instance | the component's: the editor leaves its clicks and keys alone |
|
|
101
|
+
| a slot, a `flow` part, and what it holds | the editor's: any block, as in the page; the component reads it and never writes in it |
|
|
100
102
|
| the instance as a whole, its handle | Gallery's: moving, copying and deleting it |
|
|
101
103
|
|
|
102
|
-
In the page the user types words in the text parts, and moves, copies or deletes the instance whole; a component changes its data parts by `context.edit` on a gesture of the reader's, a drag or a press, and nothing else of it changes there. No item of a repeated group of text parts is added or taken out on the page, its text parts being the file's words: an item more or fewer is a change of the source, so say so in writing.md. A component whose items come and go keeps them in a data part, where a control of its own adds, renames or removes one by `context.edit`, as a move is written.
|
|
104
|
+
In the page the user types words in the text parts, edits the blocks of a slot as any, and moves, copies or deletes the instance whole; a component changes its data parts by `context.edit` on a gesture of the reader's, a drag or a press, and nothing else of it changes there. No item of a repeated group of text parts is added or taken out on the page, its text parts being the file's words: an item more or fewer is a change of the source, so say so in writing.md. A component whose items come and go keeps them in a data part, where a control of its own adds, renames or removes one by `context.edit`, as a move is written.
|
|
103
105
|
|
|
104
106
|
A component reads a text part and never writes one: what a user types there is the file's, and a script that writes it on the `source` signal hears itself without end. It draws in what is its own, and writes a data part by `context.edit` alone: a change made straight to the part stands on that page and may end up anywhere, or nowhere.
|
|
105
107
|
|
|
108
|
+
## Slots
|
|
109
|
+
|
|
110
|
+
A slot is where an instance holds blocks of the document's own under its own markup: a card with a title over any content, a frame around a few paragraphs and a table. Its part is edited as `flow`, with no `at`, `min` or `max`, a name of lowercase letters, digits and hyphens, and `"optional": true` when an instance may have none:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
"parts": {
|
|
114
|
+
"title": { "at": ":scope > h3", "edit": "text" },
|
|
115
|
+
"body": { "edit": "flow" }
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
In the markup it is a `<div>` or `<section>` of the instance's own, marked with that name, once in an instance, never the instance itself and with no `data-block-id`:
|
|
120
|
+
|
|
121
|
+
<!-- the file holds -->
|
|
122
|
+
```html
|
|
123
|
+
<div class="brief" data-doc-component="local/brief">
|
|
124
|
+
<h3>本周要点</h3>
|
|
125
|
+
<div class="brief-body" data-doc-slot="body">
|
|
126
|
+
<p>上线了新的导出流程。</p>
|
|
127
|
+
<ul>
|
|
128
|
+
<li>导出更快</li>
|
|
129
|
+
<li>离线文件更小</li>
|
|
130
|
+
</ul>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`gallery component new <id> --flow` writes one, `body`, in place of the text paragraph. What a slot holds is written as anywhere in the document ([writing-html.md](writing-html.md)): paragraphs, headings, lists, tables, formulas, code, a chart card, pictures, a disclosure, columns, another instance; no section and no tab area. Gallery converts, spaces and draws it as it does the page's. `template.html` gives it what a new instance starts with, an empty paragraph (`<p></p>`) where the reader starts typing; `example.html` some blocks a writer would put there.
|
|
136
|
+
|
|
137
|
+
On the page the reader edits a slot's blocks as any of the page's: types in them, splits and turns them, moves them in and out by their handles, adds blocks there with "/", undoes. Where the package is missing, turned off or fails, the slot is still the document's and still editable; the rest of the instance shows as it stands.
|
|
138
|
+
|
|
139
|
+
The slot is the reader's, not the component's:
|
|
140
|
+
|
|
141
|
+
- `context.part("body")` gives the slot element, to read: its height, its words, its headings. A change of what it holds comes as `source`, whoever made it.
|
|
142
|
+
- A component never writes in it, moves it or takes it off: what it holds is the reader's words, and a page would take a change there for the reader's, and save it. It draws outside the slot, in what its manifest's `runtime` names, as `local/brief` draws its count of words under it. `gallery component check` fails a script that changes what a slot holds or where it stands, as it mounts, as it is put back and as its example makes its edit. `context.edit` on a slot throws.
|
|
143
|
+
- Its style reaches no block in the slot: a selector that goes down from the instance by a blank (`[data-doc-component="local/brief"] p`) styles the slot's paragraphs too, which read as the page's. Write each step with `>` (`[data-doc-component="local/brief"] > h3`), or wrap the rules in `@scope ([data-doc-component="local/brief"]) to ([data-doc-slot]) { … }`; the check gives a note on each that goes down.
|
|
144
|
+
- With `"markdown": "parts"` a slot is written as its blocks, in its place among the parts; with `"text"`, its words.
|
|
145
|
+
|
|
106
146
|
## Writing an instance
|
|
107
147
|
|
|
108
148
|
<!-- the file holds -->
|
|
@@ -116,7 +156,7 @@ A component reads a text part and never writes one: what a user types there is t
|
|
|
116
156
|
</div>
|
|
117
157
|
```
|
|
118
158
|
|
|
119
|
-
An instance is a `<div>` or `<section>` naming its package, straight in the page or in anything that holds blocks. Classes and attributes of your own are free in it; `doc-*` and `data-doc-*` are the kit's. Nothing of Gallery's goes into an instance: no conversion, no spacing, no formula, no other component's script. Write no `data-block-id` in `template.html`: every block gets its own.
|
|
159
|
+
An instance is a `<div>` or `<section>` naming its package, straight in the page or in anything that holds blocks. Classes and attributes of your own are free in it; `doc-*` and `data-doc-*` are the kit's. Nothing of Gallery's goes into an instance: no conversion, no spacing, no formula, no other component's script, but in its slots, which are the document's. Write no `data-block-id` in `template.html`: every block gets its own.
|
|
120
160
|
|
|
121
161
|
`template.html` is one instance and nothing around it, closed by its own end tag, with as many of each part as the manifest says. Write what shows well when nothing is filled in yet: the user's first look at the block is this. Nothing in it runs or leaves its block: no script but data (`<script type="application/json">`), no `on…` attribute or address of code, no `<style>`, `<link>` or `<iframe>`, no `style` that positions it `fixed`, `absolute` or `sticky`, nothing of the editor's (`data-ge-*`). No menu offers a template that breaks this, and the check fails it at its line. `example.html` may hold several, and blocks around them.
|
|
122
162
|
|
|
@@ -165,8 +205,8 @@ Its manifest says what that draws: `"runtime": { "generated": [".metrics-drawn"]
|
|
|
165
205
|
- Whatever it adds to an instance is named in the manifest's `runtime`, `generated` for the nodes it makes and `attrs` for the marks it sets, or taken off in `dehydrate(host)`. A selector there goes down from the instance, and `:scope` is the instance itself (`"attrs": { ":scope": ["aria-busy"] }`). `dehydrate` may be given a host with nothing on it.
|
|
166
206
|
- A component draws in its instance, with ordinary elements. Nothing goes on `document.body` or in the head, and no attribute on what stands around the instance: what must stand elsewhere for a while (a tooltip, a popover) `destroy` takes away, and a listener outside the instance ends with `context.signal`. `gallery component check` names what piles up outside. A shadow root is not forbidden, but `gallery qa` and `gallery component check` do not look into one and the kit's theme stops at it, so what stands there goes unchecked.
|
|
167
207
|
- No `alert`, `confirm`, `prompt` or `window.open`: a dialog stops a reader's page until it is answered, and the check fails it.
|
|
168
|
-
- `on` lists the signals `update(reason)` hears: `source` (a text or data part changed, whoever changed it: an undo too), `editable` (`context.canEdit()` has just become true), `resize`, `theme`, `viewport`, `fonts`, `reveal`, `layout` (a card's size changed where widths do not tell: a resize in the editor), `content` (a change inside the instance, heard only with `owns: false`, for a component that leaves what it draws to the kit to watch). `owns` (default true): the kit watches nothing the component draws, only its parts.
|
|
169
|
-
- `context.part(name)` is a part of this instance, `context.state({ version, defaults })` its reading state, of no other instance, `context.frame(draw)` draws in the kit's frame, `context.signal` ends with the instance (give it to `addEventListener`), `context.fail(error)` says it failed, `context.canEdit()` and `context.edit(name, change)` write back: below.
|
|
208
|
+
- `on` lists the signals `update(reason)` hears: `source` (a text or data part changed, or what a slot holds, whoever changed it: an undo too), `editable` (`context.canEdit()` has just become true), `resize`, `theme`, `viewport`, `fonts`, `reveal`, `layout` (a card's size changed where widths do not tell: a resize in the editor), `content` (a change inside the instance, heard only with `owns: false`, for a component that leaves what it draws to the kit to watch). `owns` (default true): the kit watches nothing the component draws, only its parts.
|
|
209
|
+
- `context.part(name)` is a part of this instance (of a slot, its element, to read), `context.state({ version, defaults })` its reading state, of no other instance, `context.frame(draw)` draws in the kit's frame, `context.signal` ends with the instance (give it to `addEventListener`), `context.fail(error)` says it failed, `context.canEdit()` and `context.edit(name, change)` write back: below.
|
|
170
210
|
- A component that throws fails that instance alone: it shows what it holds, read-only, its text parts too, until the page is loaded again.
|
|
171
211
|
- `kit.js` is type-checked against `sdk/` as strict TypeScript would: a syntax error, a name nothing defines and what the SDK does not say fail the check, and any other word of the types is a note. A part and a draft are typed `HTMLElement`, and `querySelector` gives an `Element`: name what it is, `/** @type {HTMLTableElement} */ (table)`, or test it (`node instanceof HTMLElement`), and guard what can be null (`event.dataTransfer`, `context.part(…)`).
|
|
172
212
|
- An export blocks the network: no `fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`, `sendBeacon` or `import()`, and no `eval`. `gallery component check` refuses them, and `localStorage`: what a reader chooses goes in `context.state`.
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
|
|
105
105
|
<h3>引用、提示、高亮与折叠</h3>
|
|
106
106
|
<blockquote><p>引用块:照录的原话。</p></blockquote>
|
|
107
|
-
<div class="doc-callout"><strong>提示块:</strong>风险、口径的变化,读者要留意的事。</div>
|
|
107
|
+
<div class="doc-callout"><p><strong>提示块:</strong>风险、口径的变化,读者要留意的事。</p></div>
|
|
108
108
|
<aside>
|
|
109
109
|
<div class="doc-icon">💡</div>
|
|
110
110
|
<p>高亮块:浅色底上的一组块,和提示块一样少用。</p>
|
|
@@ -24,7 +24,7 @@ Each block by the name Gallery's menu gives it (the user's word for it), what yo
|
|
|
24
24
|
| 表格 | `<table>`, its title a `<caption>` | `div.doc-table-wrap` › `table.doc-table`, the caption a `p.doc-note` above it | Tables |
|
|
25
25
|
| 图片 | `<figure><img src="assets/…"><figcaption>`, or a lone `<img>` | `figure.doc-image` | Pictures |
|
|
26
26
|
| 小字 | `<p class="doc-note">`, `span.doc-tab` at its right | | Kit blocks |
|
|
27
|
-
| 提示块, 高亮块 | `div.doc-callout
|
|
27
|
+
| 提示块, 高亮块 | `div.doc-callout` holding `<p>`; `<aside>` | `aside.doc-panel` (one made in the preview a `div.doc-panel`, the same block) | Kit blocks |
|
|
28
28
|
| 步骤流程图 | `ol.doc-flow`, a step `<li><p><strong>…</strong></p>…</li>` | | Kit blocks |
|
|
29
29
|
| 选项卡 | `<section data-doc-sheets="name">` holding a `<section>` per tab, starting with its heading, the tab's name | `section.doc-sheet-shell`: its row of tabs, a `div[data-doc-sheet]` per tab | Kit blocks |
|
|
30
30
|
| 分栏 | `div.doc-columns` | | Kit blocks |
|
|
@@ -42,8 +42,8 @@ Each block by the name Gallery's menu gives it (the user's word for it), what yo
|
|
|
42
42
|
`gallery new` writes the head, the header with the title, and a starter section, which you replace; the source line and the opening summary are yours to write.
|
|
43
43
|
|
|
44
44
|
- `data-doc-id` is the slug, `<html lang>` the page's language.
|
|
45
|
-
- `doc.json`, beside the page, holds its `title`, `description` and `type` (free text naming the kind of document; `gallery new`'s `report` is fine), and may hold `source`: the most precise locator of the dataset, experiment report, document or query the materials come from (say so when that is only a supplied draft or example).
|
|
46
|
-
- The header holds the title, an icon before it if any (`.doc-icon`,
|
|
45
|
+
- `doc.json`, beside the page, holds its `title`, `description` and `type` (free text naming the kind of document; `gallery new`'s `report` is fine), and may hold `source`: the most precise locator of the dataset, experiment report, document or query the materials come from (say so when that is only a supplied draft or example). Its `title`, `icon` and `description` are the sidebar's; the title and icon are the page's header's too. Change any of them with `gallery set <slug> --title "…" --icon <emoji, or none> --description "…"` (SKILL.md, "Organizing documents"), which writes the header and `doc.json` in step; never by hand in either. It may also hold `look`, the reader's 字体与布局 (the page's font, text size, spacing and column width, chosen in Gallery's 更多 menu: `{ "font": "serif" | "mixed", "size": "small" | "large", "spacing": "compact" | "loose", "width": "narrow" | "wide" }`, where `"font": "sans"` or `"size"`, `"spacing"`, `"width": "default"` say a default chosen over the workspace's). The workspace's `gallery.json` may hold a `look` of the same shape too, the reader's default for every document (字体与布局's 应用到全部文档), which a document's own choices override one by one; a new document has none of its own and shows it. Both are the reader's: keep them as they are whenever you rewrite `doc.json`, never write either into the page, and add or change them only when the user asks (`gallery check` takes either).
|
|
46
|
+
- The header holds the title, an icon before it if any (`.doc-icon`, which `gallery set --icon` writes), and at most one line of small text, the source line. The source line says in words a reader elsewhere understands where the materials come from (组内项目 X 的论文终稿与 rebuttal 材料), or names a file of `materials/`; never a path of this machine (`D:\…`, `C:\Users\…`, `/home/…`), which the checks make a `fix` line. The same holds for a scope line's 来源. Nothing else goes between the title and the opening summary.
|
|
47
47
|
- The opening summary comes right after the header, before the first section: `<section class="doc-summary" aria-label="概括">` (a 写作偏好 written before may write `aria-label="报告概括"`: the same block; keep the label 写作偏好 gives), a few headings as paragraphs of bold words (no `h2`–`h6`), each followed by a paragraph or a list. 写作偏好 may say what it holds; when it says nothing, a document written from materials still has one, unless the user asks for another structure or you convert a finished report. Its headings are short noun phrases that fit the kind of report (实验背景, 用途, 展区与展品 …); 写作偏好 says which.
|
|
48
48
|
- A section groups a chapter and draws nothing: its title is the heading in it, an `<hr>` at its top a line above it. That `<hr>` is a block of its own, with its id: the first section after the summary has none, each after it one. To reorder sections, move the `<hr>` elements themselves, ids and all, so that this still holds; never delete one and write another. Sections are optional; a short document may put its text straight in `main`.
|
|
49
49
|
- The document's own CSS goes in one inline `<style>` using the kit's variables: colors, which follow the dark theme (`--doc-text`, `--doc-muted`, `--doc-border`, `--doc-grid`, `--doc-surface`, `--doc-bg`, `--doc-accent`, `--doc-series-1` … `-6`), and fonts and sizes (`--doc-font`, the text's; `--doc-mono` or `--doc-code-font`, monospace, a code block's the second; `--doc-body-font-size`, 16px; `--doc-small-font-size`, 13px, small text). Use only the `--doc-*` names this page gives: another may name nothing, and its `var()` then quietly falls back (`--doc-mono-font` names nothing). Its code goes in one inline `<script>` at the end of `body`; the kit's own tags are added when the page is shown or exported. The checks read the script as strict TypeScript would: a type error is a note (guard a value where it can really be null), a syntax error or a name nothing defines a failure. Write JavaScript, a type in JSDoc if any (`/** @type {…} */`), never `: number`.
|
|
@@ -84,7 +84,7 @@ The blocks HTML has no element for, written with the kit's classes as the exampl
|
|
|
84
84
|
|
|
85
85
|
**Small text** (`p.doc-note`): a short label, unit or scope note, such as a table's scope line right above it. A scope note may say how a number counts (口径:一条意见写到三家,各算一次). `span.doc-tab` puts the rest of the line at its right end.
|
|
86
86
|
|
|
87
|
-
**Callout** (`div.doc-callout`): a risk, warning, state or caveat, set apart from the text;
|
|
87
|
+
**Callout** (`div.doc-callout`): a risk, warning, state or caveat, set apart from the text; its words in a `<p>` in it, and a list or a code block after that where it needs one (`<div class="doc-callout"><p>…</p></div>`). **Highlight panel** (`<aside>`): blocks set apart on a light fill, an icon first if any; as rare as a callout.
|
|
88
88
|
|
|
89
89
|
**A block's color** (颜色): a class on the block, never a `style`, of the colors gray, brown, orange, yellow, green, blue, purple, pink and red. A paragraph, a heading, a list item or a flowchart step takes its words' color (`doc-text-<color>`), a fill (`doc-highlight-<color>`) or both; a disclosure, a code block (on its `<pre>`), a callout or a highlight panel a fill only; a table cell one of the two. Words in a line take theirs from `<mark>` or a `<span style>`.
|
|
90
90
|
|
package/skill/sdk/doc-kit.d.ts
CHANGED
|
@@ -3,7 +3,8 @@ import type { DocState } from "./doc-state.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* What an instance can hear (`on`). `editable`: `context.canEdit()` has just become true, for one mounted before the page came to edit.
|
|
5
5
|
* `content`: a change inside the instance, heard only with `owns: false`, as what a component owns the
|
|
6
|
-
* kit does not watch; a change of what the file says of it is `source`, whatever it owns
|
|
6
|
+
* kit does not watch; a change of what the file says of it is `source`, whatever it owns: of a part edited
|
|
7
|
+
* as text or data, or of the blocks a slot holds (a part edited as flow), typed, moved in or out, undone.
|
|
7
8
|
*/
|
|
8
9
|
export type DocComponentSignal = "source" | "resize" | "theme" | "layout" | "viewport" | "fonts" | "content" | "reveal" | "editable";
|
|
9
10
|
|
|
@@ -41,7 +42,12 @@ export interface DocComponentContext {
|
|
|
41
42
|
frame(draw: () => void): void;
|
|
42
43
|
/** Say this instance failed: it ends there, even as `mount` runs, and shows what it holds, read-only. */
|
|
43
44
|
fail(error: unknown): void;
|
|
44
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* The first element of a part of the manifest in this instance's own markup, or null. A part edited as
|
|
47
|
+
* flow gives its slot (data-doc-slot), whose blocks are the document's, the reader's: read it (its
|
|
48
|
+
* height, its words, its headings), and never write in it, move it or take it off. A name the manifest
|
|
49
|
+
* does not have throws.
|
|
50
|
+
*/
|
|
45
51
|
part(name: string): HTMLElement | null;
|
|
46
52
|
/** This instance's reading state, of no other instance of the package: the same object at every mount. */
|
|
47
53
|
state<T extends Record<string, unknown>>(options: DocComponentStateOptions<T>): DocState<T>;
|
|
@@ -59,7 +65,7 @@ export interface DocComponentContext {
|
|
|
59
65
|
* draft, or leaves what a file cannot hold (a script, a handler, an element that does not read back as
|
|
60
66
|
* itself, its own tag changed): nothing has happened then, and the console says why. Undo puts the
|
|
61
67
|
* part back and `source` tells you, like any change of it. A name the manifest does not have, or a
|
|
62
|
-
* part not edited as data, throws. A list of names changes those parts in one write, one undo step (a
|
|
68
|
+
* part not edited as data (a text part, a slot), throws. A list of names changes those parts in one write, one undo step (a
|
|
63
69
|
* gesture that moves a card and counts the move): `change` is handed a draft of each, by its name, and
|
|
64
70
|
* two that are one element, or one in the other, throw.
|
|
65
71
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--font:ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI", Helvetica, "PingFang SC", "Microsoft YaHei", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--mono:"SFMono-Regular", Menlo, Consolas, "PT Mono", "Liberation Mono", Courier, monospace;--sb-w:270px;--dur:.2s;--texPri:#2c2c2b;--texSec:#7d7a75;--texTer:#a19e99;--texAcc:#5f5e59;--texDis:#bcbab6;--icoPri:#5c5a55;--icoSec:#8e8b86;--sidIco:#91918e;--borPri:#e6e5e3;--borSec:#f0efed;--borPriTra:#1c13011c;--borStrTra:#1b150030;--crumbSep:#d4d3cf;--bacPri:#fff;--bacSec:#f9f8f7;--bacEle:#fff;--popBac:#fff;--sidBac:#f3f2ef;--pageBac:#fff;--bacIntTra:#211b170d;--bacTerTra:#2a1c0012;--inputBac:#f2f1ee99;--codeBg:#f9f8f7;--blue:#2383e2;--blueLine:#2383e291;--blueBg:#2383e224;--bluBacIntTra:#0079e413;--select:#2383e224;--red:#eb5757;--star:#cb912f;--overlay:#0f0f0f99;--tipBg:#0f0f0f;--tipTex:#f0efed;--tipSub:#a19e99;--scrollThumb:#2a1c0024;--shaOutLg:0px 20px 24px 0px #1919190d, 0px 5px 8px 0px #19191907, 0px 0px 0px 1px #2a1c0012;--gra-tx:#7d7a75;--gra-sw:#f0efed;--gra-bg:#2a1c0012;--gra-bd:#1c13011c;--bro-tx:#9f765a;--bro-sw:#f5ede9;--bro-bg:#8b2e0016;--bro-bd:#7f330028;--ora-tx:#d27b2d;--ora-sw:#fbebde;--ora-bg:#e0650121;--ora-bd:#c4580034;--yel-tx:#cb9434;--yel-sw:#f9f3dc;--yel-bg:#d3a80023;--yel-bd:#d19c0048;--gre-tx:#50946e;--gre-sw:#e8f1ec;--gre-bg:#00642d17;--gre-bd:#00602628;--blu-tx:#387dc9;--blu-sw:#e5f2fc;--blu-bg:#007cd718;--blu-bd:#0076d934;--pur-tx:#9a6bb4;--pur-sw:#f3ebf9;--pur-bg:#6600b214;--pur-bd:#5c00a324;--pin-tx:#c14c8a;--pin-sw:#fae9f1;--pin-bg:#c5005d16;--pin-bd:#b7004e27;--red-tx:#cf5148;--red-sw:#fce9e7;--red-bg:#df160018;--red-bd:#ce18002a;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--texPri:#f0efed;--texSec:#ada9a3;--texTer:#7d7a75;--texAcc:#bcbab6;--texDis:#5f5e59;--icoPri:#a9a69e;--icoSec:#ada9a3;--sidIco:#9b9b9b;--borPri:#383836;--borSec:#2c2c2b;--borPriTra:#ffffeb1a;--borStrTra:#fffceb4e;--crumbSep:#383836;--bacPri:#191919;--bacSec:#202020;--bacEle:#202020;--popBac:#252525;--sidBac:#141413;--pageBac:#181818;--bacIntTra:#ffffff0e;--bacTerTra:#fffff315;--bluBacIntTra:#4499ff1e;--inputBac:#ffffff0e;--codeBg:#ffffff08;--star:#d99e35;--overlay:#0f0f0fcc;--tipBg:#2f2f2f;--tipTex:#f0efed;--tipSub:#9b9b9b;--scrollThumb:#fffff324;--shaOutLg:0px 0px 0px 1px #383836, 0px 14px 28px -6px #19191933, 0px 2px 4px -1px #1919191e;--gra-sw:#383836;--gra-bg:#ffffeb1a;--gra-bd:#ffffeb1a;--bro-sw:#45362d;--bro-bg:#ffb18131;--bro-bd:#ffb18131;--ora-sw:#53361f;--ora-bg:#ff934b47;--ora-bd:#ff934b47;--yel-sw:#504425;--yel-bg:#ffcd4b3d;--yel-bd:#ffcd4b3d;--gre-sw:#263d30;--gre-bg:#6cffac28;--gre-bd:#6cffac28;--blu-sw:#233850;--blu-bg:#439bff3d;--blu-bd:#439bff3d;--pur-sw:#3c2d47;--pur-bg:#c87dff33;--pur-bd:#c87dff33;--pin-sw:#4e2b3c;--pin-bg:#ff67b13b;--pin-bd:#ff67b13b;--red-sw:#502c29;--red-bg:#ff685c3d;--red-bd:#ff685c3d;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}}:root[data-theme=dark]{--texPri:#f0efed;--texSec:#ada9a3;--texTer:#7d7a75;--texAcc:#bcbab6;--texDis:#5f5e59;--icoPri:#a9a69e;--icoSec:#ada9a3;--sidIco:#9b9b9b;--borPri:#383836;--borSec:#2c2c2b;--borPriTra:#ffffeb1a;--borStrTra:#fffceb4e;--crumbSep:#383836;--bacPri:#191919;--bacSec:#202020;--bacEle:#202020;--popBac:#252525;--sidBac:#141413;--pageBac:#181818;--bacIntTra:#ffffff0e;--bacTerTra:#fffff315;--bluBacIntTra:#4499ff1e;--inputBac:#ffffff0e;--codeBg:#ffffff08;--star:#d99e35;--overlay:#0f0f0fcc;--tipBg:#2f2f2f;--tipTex:#f0efed;--tipSub:#9b9b9b;--scrollThumb:#fffff324;--shaOutLg:0px 0px 0px 1px #383836, 0px 14px 28px -6px #19191933, 0px 2px 4px -1px #1919191e;--gra-sw:#383836;--gra-bg:#ffffeb1a;--gra-bd:#ffffeb1a;--bro-sw:#45362d;--bro-bg:#ffb18131;--bro-bd:#ffb18131;--ora-sw:#53361f;--ora-bg:#ff934b47;--ora-bd:#ff934b47;--yel-sw:#504425;--yel-bg:#ffcd4b3d;--yel-bd:#ffcd4b3d;--gre-sw:#263d30;--gre-bg:#6cffac28;--gre-bd:#6cffac28;--blu-sw:#233850;--blu-bg:#439bff3d;--blu-bd:#439bff3d;--pur-sw:#3c2d47;--pur-bg:#c87dff33;--pur-bd:#c87dff33;--pin-sw:#4e2b3c;--pin-bg:#ff67b13b;--pin-bd:#ff67b13b;--red-sw:#502c29;--red-bg:#ff685c3d;--red-bd:#ff685c3d;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}html{scrollbar-color:var(--scrollThumb) transparent}body{font-family:var(--font);background:var(--bacPri);color:var(--texPri);-webkit-font-smoothing:antialiased;font-size:16px;line-height:1.5;overflow:hidden}button{font:inherit;color:inherit;cursor:pointer;text-align:inherit;background:0 0;border:0;margin:0;padding:0}svg{fill:none;stroke:currentColor;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round;width:100%;height:100%;display:block}svg.fill{fill:currentColor;stroke:none}svg.solid{fill:currentColor}svg.lu{stroke-width:1.75px}.ic{display:contents}body.preload *{transition:none!important}@keyframes pop-in{0%{opacity:0;transform:translateY(-2px)}}.app{height:100dvh;font-size:14px;display:flex}.main{background:var(--bacPri);flex-direction:column;flex:1;min-width:0;font-size:16px;display:flex;position:relative}.icon-btn{width:28px;height:28px;color:var(--icoSec);border-radius:6px;flex:none;justify-content:center;align-items:center;transition:background 20ms ease-in;display:inline-flex}.icon-btn svg{width:20px;height:20px}.icon-btn svg.lu{width:18px;height:18px}.icon-btn:hover{background:var(--bacIntTra)}.ghost-btn{height:28px;color:var(--texTer);white-space:nowrap;border-radius:6px;align-items:center;gap:6px;padding:0 8px;font-size:14px;display:inline-flex}.ghost-btn svg{width:16px;height:16px}.ghost-btn:hover{background:var(--bacIntTra)}.ghost-btn.sm{height:24px}.row-act{width:20px;height:20px;color:var(--icoSec);border-radius:4px;flex:none;justify-content:center;align-items:center;display:flex}.row-act svg{width:16px;height:16px}.row-act:hover{background:var(--bacTerTra)}.pg-icon{width:20px;height:20px;color:var(--sidIco);flex:none;justify-content:center;align-items:center;font-size:16px;line-height:1;display:inline-flex}.pg-icon svg.lu{width:18px;height:18px}.pg-icon .page-icon{object-fit:cover;border-radius:3px;width:18px;height:18px;display:block}.pg-icon .glyph-icon{background:currentColor;width:18px;height:18px;display:block;-webkit-mask:none 50%/contain no-repeat;mask:none 50%/contain no-repeat}.glyph-icon[data-icon$=_gray\.svg]{color:var(--lightningcss-light,#55534e)var(--lightningcss-dark,#d3d3d3)}.glyph-icon[data-icon$=_lightgray\.svg]{color:var(--lightningcss-light,#a6a299)var(--lightningcss-dark,#7f7f7f)}.glyph-icon[data-icon$=_brown\.svg]{color:var(--lightningcss-light,#9f6b53)var(--lightningcss-dark,#aa755f)}.glyph-icon[data-icon$=_yellow\.svg]{color:var(--lightningcss-light,#cb912f)var(--lightningcss-dark,#ca8e1b)}.glyph-icon[data-icon$=_orange\.svg]{color:var(--lightningcss-light,#d9730d)var(--lightningcss-dark,#d87620)}.glyph-icon[data-icon$=_green\.svg]{color:var(--lightningcss-light,#448361)var(--lightningcss-dark,#2d9964)}.glyph-icon[data-icon$=_blue\.svg]{color:var(--lightningcss-light,#337ea9)var(--lightningcss-dark,#2e7cd1)}.glyph-icon[data-icon$=_purple\.svg]{color:var(--lightningcss-light,#9065b0)var(--lightningcss-dark,#8d5bc1)}.glyph-icon[data-icon$=_pink\.svg]{color:var(--lightningcss-light,#c14c8a)var(--lightningcss-dark,#c94079)}.glyph-icon[data-icon$=_red\.svg]{color:var(--lightningcss-light,#d44c47)var(--lightningcss-dark,#cd4945)}.menu{z-index:1000;background:var(--popBac);min-width:240px;max-width:320px;box-shadow:var(--shaOutLg);-webkit-user-select:none;user-select:none;border-radius:10px;outline:none;padding:6px 0;font-size:14px;line-height:1.2;animation:.12s ease-out pop-in;position:fixed;top:0;left:0}.menu-head{color:var(--texSec);padding:6px 12px;font-size:12px;font-weight:500;line-height:14px}.menu-item{cursor:pointer;height:28px;color:var(--texPri);border-radius:6px;align-items:center;gap:8px;margin:0 4px 1px;padding:0 8px;display:flex}.menu:not(.controlled) .menu-item:hover,.menu-item.active{background:var(--bacIntTra)}.menu-item.danger:hover,.menu-item.danger.active{color:var(--red)}.menu-item.off,.menu-item.off:hover,.menu-item.off .mi-icon,.menu-item.off:hover .mi-icon{color:var(--texDis);cursor:default}.menu:not(.controlled) .menu-item.off:hover{background:0 0}.menu-item.danger:not(.off):hover .mi-icon,.menu-item.danger:not(.off).active .mi-icon{color:var(--red)}.mi-icon{width:20px;height:20px;color:var(--icoPri);flex:none;justify-content:center;align-items:center;display:flex}.mi-icon svg{width:18px;height:18px}.mi-icon svg.lu{width:16px;height:16px}.mi-label{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.mi-line{text-overflow:ellipsis;display:block;overflow:hidden}.mi-detail{color:var(--texTer);margin-top:2px;font-size:12px}.mi-kbd{max-width:45%;color:var(--texTer);white-space:nowrap;text-overflow:ellipsis;flex:none;margin-left:8px;font-size:12px;overflow:hidden}.mi-kbd:empty{display:none}.mi-arrow{width:16px;height:16px;color:var(--texTer);flex:none}.mi-arrow svg{stroke-width:1.6px}.mi-check{width:16px;height:16px;color:var(--texPri);flex:none}.mi-check svg{stroke-width:1.8px}.mi-switch{box-sizing:border-box;background:#8783784d;border-radius:44px;flex:none;align-items:center;width:28px;height:16px;margin-left:8px;padding:2px;transition:background .2s;display:flex;position:relative}.mi-switch.on{background:var(--blue)}.mi-switch>span{background:#fff;border-radius:50%;flex:none;width:12px;height:12px;transition:transform .2s ease-out;box-shadow:0 1px 2px #0f0f0f33}.mi-switch.on>span{transform:translate(12px)}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .mi-switch:not(.on){background:#caccce4d}}:root[data-theme=dark] .mi-switch:not(.on){background:#caccce4d}.menu-sep{background:var(--bacTerTra);height:1px;margin:3px 12px 4px}.menu-foot{color:var(--texTer);padding:4px 12px 2px;font-size:12px;line-height:1.6}.menu-note{color:var(--texSec);padding:4px 12px 8px;font-size:13px;line-height:1.6}.menu-empty{color:var(--texTer);padding:8px 12px;font-size:13px}.menu-sub{min-width:180px}.menu-wide{width:320px}.pop-search{padding:2px 8px 6px}.pop-input{border:1px solid var(--borPriTra);background:var(--inputBac);width:100%;height:28px;color:var(--texPri);font:inherit;border-radius:6px;outline:none;padding:0 8px;font-size:14px}.pop-input:focus{border-color:var(--blue);box-shadow:0 0 0 1px var(--blue)}.pop-list{max-height:320px;overflow-y:auto}.trash-item{border-radius:6px;align-items:center;gap:8px;height:30px;margin:0 4px;padding:0 4px 0 8px;display:flex}.trash-item:hover{background:var(--bacIntTra)}.trash-item .t{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.tip{z-index:3000;pointer-events:none;background:var(--tipBg);max-width:260px;color:var(--tipTex);box-shadow:var(--shaOutLg);opacity:0;border-radius:6px;padding:4px 8px;font-size:12px;font-weight:500;line-height:1.45;transition:opacity .1s;position:fixed;top:0;left:0}.tip.show{opacity:1}.tip .sub{color:var(--tipSub);font-weight:400}.toast{z-index:2500;background:var(--tipBg);width:fit-content;max-width:min(640px,100vw - 32px);color:var(--tipTex);box-shadow:var(--shaOutLg);opacity:0;pointer-events:none;border-radius:8px;align-items:center;gap:10px;margin:0 auto;padding:8px 14px;font-size:14px;transition:opacity .18s,transform .18s;display:flex;position:fixed;bottom:24px;left:0;right:0;transform:translateY(10px)}.toast.show{opacity:1;transform:none}.toast.show button{pointer-events:auto}.toast.error:before{content:"";background:#ff6b6b;border-radius:50%;flex:none;width:6px;height:6px}.toast button{white-space:nowrap;color:#5ea8f2;border-radius:4px;flex:none;margin-right:-6px;padding:2px 6px;font-weight:500}.toast button:hover{background:#ffffff14}.dialog-overlay{align-items:flex-start;padding-top:18vh}.dialog{background:var(--popBac);width:min(420px,100%);box-shadow:var(--shaOutLg);border-radius:12px;padding:20px 20px 16px;animation:.12s ease-out pop-in}.dialog-title{color:var(--texPri);font-size:16px;font-weight:600;line-height:1.4}.dialog-message{color:var(--texSec);margin-top:8px;font-size:14px;line-height:1.6}.dialog-actions{justify-content:flex-end;gap:8px;margin-top:18px;display:flex}.dialog-btn{height:32px;box-shadow:inset 0 0 0 1px var(--borPriTra);color:var(--texPri);border-radius:6px;padding:0 14px;font-size:14px}.dialog-btn:hover{background:var(--bacIntTra)}.dialog-btn.primary{background:var(--blue);color:#fff;box-shadow:none}.dialog-btn.primary:hover{background:#1d74cc}.dialog-btn.danger.primary{background:var(--red)}.dialog-btn:focus-visible{outline:2px solid var(--blue);outline-offset:2px}.modal{z-index:1500;background:var(--overlay);justify-content:center;align-items:flex-start;padding:12vh 16px 0;display:flex;position:fixed;inset:0}.search-panel{background:var(--popBac);width:min(620px,100%);box-shadow:var(--shaOutLg);border-radius:12px;animation:.12s ease-out pop-in;overflow:hidden}.search-bar{border-bottom:1px solid var(--borSec);align-items:center;gap:10px;height:52px;padding:0 16px;display:flex}.search-bar svg{width:20px;height:20px;color:var(--icoSec);flex:none}.search-bar input{min-width:0;color:var(--texPri);font:inherit;background:0 0;border:0;outline:0;flex:1;font-size:16px}.search-bar input::placeholder{color:var(--texTer)}.search-list{max-height:60vh;padding:4px 0 8px;overflow-y:auto}.search-item{cursor:pointer;border-radius:6px;align-items:center;gap:10px;height:36px;margin:0 6px;padding:0 10px;display:flex}.search-item.active{background:var(--bacIntTra)}.search-item .t{white-space:nowrap;text-overflow:ellipsis;flex:none;max-width:60%;overflow:hidden}.search-item .path{text-align:right;min-width:0;color:var(--texTer);white-space:nowrap;text-overflow:ellipsis;flex:1;font-size:12px;overflow:hidden}.search-main{flex-direction:column;flex:1;gap:1px;min-width:0;display:flex}.search-line{align-items:center;gap:10px;min-width:0;display:flex}.search-item.with-hit{align-items:flex-start;height:auto;min-height:36px;padding-top:6px;padding-bottom:6px}.search-item.with-hit .pg-icon{margin-top:1px}.search-snippet{min-width:0;color:var(--texSec);white-space:nowrap;text-overflow:ellipsis;font-size:13px;line-height:18px;overflow:hidden}.search-item.more{align-items:center;height:28px;min-height:0;padding:0 10px 0 40px}.search-item mark{color:var(--texPri);background:0 0;font-weight:600}.search-note{color:var(--texTer);padding:6px 16px 2px;font-size:12px}.report-view{flex:1;min-height:0;position:relative}.report-frame{background:var(--pageBac);border:0;width:100%;height:100%;display:block}body.dragging iframe,body.resizing iframe{pointer-events:none}.report-state{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:6px;min-height:0;padding:24px;display:flex}.report-state h2{margin:0;font-size:20px;font-weight:600}.report-state p{max-width:460px;color:var(--texSec);margin:0;font-size:14px;line-height:1.6}.report-state .muted{color:var(--texTer)}.report-state-actions{gap:8px;margin-top:10px;display:flex}.report-frame[data-pending]{opacity:0;pointer-events:none;position:absolute;inset:0}.card-underlay{z-index:900;background:var(--overlay);animation:.16s ease-out card-underlay-fade;position:fixed;inset:0}body.card-open .sb-resizer,body.card-open .sb-edge{pointer-events:none}@keyframes card-underlay-fade{0%{opacity:0}}@media (prefers-reduced-motion:reduce){.card-underlay{animation:none}}.xf-overlay{z-index:1500;background:var(--overlay);justify-content:center;align-items:center;padding:16px;display:flex;position:fixed;inset:0}.xf-export,.xf-import{background:var(--popBac);box-shadow:var(--shaOutLg);color:var(--texPri);border-radius:12px;animation:.12s ease-out pop-in}.xf-export{width:320px;max-width:100%;padding:24px;font-size:14px}.xf-row{justify-content:space-between;align-items:center;height:28px;display:flex}.xf-label{color:var(--texTer);white-space:nowrap;margin-inline-end:auto;line-height:21px}.xf-select{white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none;height:28px;color:var(--texPri);border-radius:6px;align-items:center;gap:6px;margin-inline-end:-6px;padding:0 8px;line-height:1.2;transition:background 20ms ease-in;display:flex}.xf-select:hover,.xf-select.open{background:var(--bacIntTra)}.xf-select svg{width:14px;height:14px;color:var(--icoSec);stroke-width:1.6px}.xf-select:focus-visible,.xf-btn:focus-visible,.xf-switch:focus-visible,.xf-choose:focus-visible{outline:2px solid var(--blue);outline-offset:1px}.xf-scale-row{height:32px}.xf-scale{background:var(--inputBac);width:60px;height:28px;box-shadow:0 0 0 1px var(--borPriTra);color:var(--texPri);font:inherit;text-align:end;border:none;border-radius:6px;outline:none;padding:4px 10px;font-size:14px}.xf-scale:focus{box-shadow:0 0 0 1px var(--blue) inset, 0 0 0 1px var(--blue)}.xf-error{min-height:32px;color:var(--red);align-items:center;padding:4px 0;font-size:12px;line-height:16px;display:flex}.xf-switch-row{height:32px}.xf-switch-row .xf-label{line-height:20px}.xf-switch{box-sizing:content-box;cursor:pointer;background:#8783784d;border-radius:44px;flex-shrink:0;width:26px;height:14px;padding:2px;transition:background .2s,box-shadow .2s;display:flex;position:relative}.xf-switch.on{background:var(--blue)}.xf-switch>span{background:#fff;border-radius:44px;width:14px;height:14px;transition:transform .2s ease-out,background .2s ease-out}.xf-switch.on>span{transform:translate(12px)}.xf-switch.disabled{opacity:.4;cursor:default}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .xf-switch:not(.on){background:#caccce4d}}:root[data-theme=dark] .xf-switch:not(.on){background:#caccce4d}.xf-actions{justify-content:flex-end;align-items:center;gap:8px;margin-top:16px;display:flex}.xf-btn{white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;justify-content:center;align-items:center;height:28px;padding:0 8px;font-size:14px;line-height:1.2;transition:background 20ms ease-in;display:inline-flex}.xf-btn.gray{color:var(--texSec)}.xf-btn.gray:hover{background:var(--bacIntTra)}.xf-btn.blue{background:var(--blue);color:#fff;font-weight:500}.xf-btn.blue:hover{filter:brightness(.92)}.xf-btn[aria-disabled=true]{opacity:.4;pointer-events:none}.menu.menu-select{z-index:1600;width:180px;min-width:180px}.menu-select .mi-icon:empty{display:none}.xf-import{flex-direction:column;gap:14px;width:min(460px,100vw - 32px);padding:20px 20px 18px;font-size:14px;display:flex}.xf-import-head{flex-direction:column;gap:2px;min-width:0;display:flex}.xf-import-title{font-size:16px;font-weight:600;line-height:1.4}.xf-import-where{color:var(--texSec);white-space:nowrap;text-overflow:ellipsis;font-size:13px;line-height:1.5;overflow:hidden}.xf-drop{border:1px dashed var(--borStrTra);color:var(--texPri);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:10px;flex-direction:column;align-items:center;gap:6px;padding:30px 16px 26px;transition:background .12s,border-color .12s;display:flex}.xf-drop:hover{background:var(--bacIntTra)}.xf-drop.dragging{border-color:var(--blue);background:var(--bluBacIntTra)}.xf-drop:focus-visible{outline:2px solid var(--blue);outline-offset:2px}.xf-drop svg{width:28px;height:28px;color:var(--icoSec);stroke-width:1.4px;margin-bottom:4px;transition:color .12s}.xf-drop.dragging svg{color:var(--blue)}.xf-drop-main{line-height:20px}.xf-choose{color:var(--blue);margin-inline-start:2px}.xf-drop-kinds,.xf-import-note{color:var(--texTer);font-size:12px;line-height:16px}.pref-overlay{z-index:1500;background:var(--overlay);justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.pref-dialog{background:var(--bacPri);width:min(880px,100%);height:min(86vh,900px);box-shadow:var(--shaOutLg);border-radius:12px;flex-direction:column;animation:.12s ease-out pop-in;display:flex;overflow:hidden}.pref-head{border-bottom:1px solid var(--borSec);flex:none;align-items:center;gap:10px;height:48px;padding:0 12px 0 20px;display:flex}.pref-title{color:var(--texPri);flex:none;font-size:14px;font-weight:600}.pref-sub{white-space:nowrap;text-overflow:ellipsis;min-width:0;color:var(--texSec);flex:1;font-size:13px;overflow:hidden}.pref-actions{flex:none;align-items:center;gap:4px;display:flex}.pref-save{height:28px;color:var(--texPri);white-space:nowrap;border-radius:6px;flex:none;padding:0 10px;font-size:14px}.pref-save:hover:not(:disabled){background:var(--bacIntTra)}.pref-save:disabled{color:var(--texTer);cursor:default}.pref-note{border-bottom:1px solid var(--borSec);background:var(--bacSec);color:var(--texSec);overflow-wrap:anywhere;flex:none;padding:8px 20px;font-size:13px;line-height:1.5}.pref-body{background:var(--bacPri);flex:1;min-height:0;position:relative}.pref-frame{background:var(--pageBac);border:0;width:100%;height:100%;position:absolute;inset:0}.pref-frame[data-pending]{opacity:0;pointer-events:none}.pref-loading{opacity:0;height:2px;animation:.2s ease-out .3s forwards pref-loading-in;position:absolute;top:0;left:0;right:0;overflow:hidden}.pref-loading:before{content:"";background:var(--borStrTra);border-radius:1px;width:24%;animation:1.6s ease-in-out infinite pref-loading-pass;position:absolute;top:0;bottom:0;left:0}@keyframes pref-loading-in{to{opacity:1}}@keyframes pref-loading-pass{0%{transform:translate(-100%)}to{transform:translate(417%)}}@media (prefers-reduced-motion:reduce){.pref-loading:before{width:100%;animation:none}}.comp-dialog{width:min(640px,100%);height:min(86vh,720px)}.comp-body{flex:1;min-height:0;padding:4px 20px 20px;overflow-y:auto}.comp-group{color:var(--texPri);margin:16px 0 4px;font-size:14px;font-weight:600}.comp-lead,.comp-empty{color:var(--texSec);padding:4px 0 8px;font-size:13px;line-height:1.5}.comp-problem{color:var(--texPri);margin-top:12px;font-size:13px;line-height:1.5}.comp-row{border-top:1px solid var(--borSec);align-items:center;gap:16px;padding:8px 0;display:flex}.comp-row.comp-block{gap:8px;padding:6px 0}.comp-icon{width:20px;height:20px;color:var(--icoPri);flex:none;justify-content:center;align-items:center;display:flex}.comp-icon svg{stroke-width:1.25px;width:20px;height:20px}.comp-text{flex:1;min-width:0}.comp-name{min-width:0;color:var(--texPri);overflow-wrap:anywhere;flex:1;font-size:14px;line-height:20px}.comp-meta{max-width:100%;color:var(--texTer);margin-left:8px;font-size:12px;display:inline-block}.comp-note{color:var(--texSec);overflow-wrap:anywhere;font-size:13px;line-height:18px}.comp-state{color:var(--texTer)}.comp-toggles{flex:none;align-items:center;gap:12px;display:flex}.comp-toggle{height:24px;color:var(--texSec);cursor:pointer;background:0 0;flex:none;align-items:center;gap:6px;padding:0;font-size:13px;display:flex}.comp-toggle .mi-switch{margin:0}.comp-toggle[aria-disabled=true]{cursor:default;opacity:.5}.present{z-index:2000;background:var(--bacPri);position:fixed;inset:0}.present-frame{background:var(--pageBac);transform-origin:0 0;border:0;width:100%;height:100%;position:absolute;top:0;left:0}.present-ink{pointer-events:none;touch-action:none;width:100%;height:100%;position:absolute;inset:0}.present:is([data-tool=laser],[data-tool=pen],[data-tool=marker],[data-tool=eraser]) .present-ink{pointer-events:auto}.present[data-tool=laser] .present-ink{cursor:none}.present[data-tool=pen] .present-ink{cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='4' fill='%23e03e3e' stroke='white' stroke-width='1.5'/%3E%3C/svg%3E") 8 8,crosshair}.present[data-tool=marker] .present-ink{cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22'%3E%3Crect x='3' y='3' width='16' height='16' rx='5' fill='rgba(255,204,0,.55)' stroke='rgba(120,90,0,.55)' stroke-width='1'/%3E%3C/svg%3E") 11 11,crosshair}.present[data-tool=eraser] .present-ink{cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='12' cy='12' r='10' fill='rgba(140,140,140,.28)' stroke='rgba(110,110,110,.9)' stroke-width='1.5'/%3E%3C/svg%3E") 12 12,default}.present-notice{background:var(--tipBg);color:var(--tipTex);box-shadow:var(--shaOutLg);white-space:nowrap;pointer-events:none;border-radius:8px;padding:8px 14px;font-size:14px;position:absolute;bottom:24px;left:50%;transform:translate(-50%)}.present-bar{background:var(--popBac);box-shadow:var(--shaOutLg);border-radius:10px;align-items:center;gap:2px;padding:4px;transition:opacity .3s;display:flex;position:absolute;bottom:16px;left:16px}.present-bar.idle{opacity:.25}.present-btn{width:32px;height:32px;color:var(--icoPri);border-radius:6px;justify-content:center;align-items:center;display:flex}.present-btn:hover{background:var(--bacIntTra)}.present-btn[aria-pressed=true]{background:var(--bacTerTra);color:var(--texPri)}.present-btn:disabled{opacity:.35;pointer-events:none}.present-btn svg{width:18px;height:18px}.present-sep{background:var(--borSec);flex:none;width:1px;height:18px;margin:0 4px}.present-zoom{min-width:48px;height:32px;color:var(--texPri);font-variant-numeric:tabular-nums;text-align:center;border-radius:6px;flex:none;padding:0 4px;font-size:13px}.present-zoom:hover{background:var(--bacIntTra)}.present-ink{mix-blend-mode:multiply}:root[data-theme=dark] .present-ink{mix-blend-mode:screen}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .present-ink{mix-blend-mode:screen}}body:has(.present) .toast{display:none}.sb-container{z-index:20;width:var(--sb-w);background:var(--sidBac);transition:width var(--dur) ease;flex:none;position:relative}.sb-container.collapsed{width:0}.sb-anchor{z-index:9;width:0;position:absolute;top:0;bottom:0;left:0}.sidebar{width:var(--sb-w);height:100%;transition-property:width,opacity,transform,visibility;transition-duration:var(--dur);flex-direction:column;transition-timing-function:ease;display:flex;position:relative}.sidebar .float-bg{z-index:-1;background:var(--sidBac);box-shadow:var(--shaOutLg);border-radius:0 14px 14px 0;display:none;position:absolute;inset:0}.sb-inner{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.sidebar.floating{height:calc(100vh - 91px);transform:translateX(calc(20px - var(--sb-w))) translateY(59px);opacity:0;visibility:hidden;pointer-events:none}.sidebar.floating .float-bg{display:block}.sidebar.floating .sb-inner{border-radius:0 14px 14px 0}.sidebar.floating:before{content:"";height:15px;position:absolute;top:-15px;left:0;right:0}.sidebar.floating.peek{opacity:1;visibility:visible;pointer-events:auto;transform:translate(0)translateY(59px)}.sidebar.mobile{height:auto;width:min(var(--sb-w), 86vw);visibility:hidden;pointer-events:none;position:fixed;top:0;bottom:0;left:0;transform:translate(-100%)}.sidebar.mobile .float-bg{display:block}.sidebar.mobile .sb-inner{border-radius:0 14px 14px 0}.sidebar.mobile.mobile-open{visibility:visible;pointer-events:auto;transform:none}.sb-backdrop{z-index:1;background:var(--overlay);display:none;position:fixed;inset:0}.sb-backdrop.show{display:block}.sb-edge{z-index:8;width:32px;display:none;position:fixed;top:44px;bottom:0;left:0}.app.peekable .sb-edge{display:block}.sb-resizer{cursor:col-resize;z-index:10;width:12px;position:absolute;top:0;bottom:0;right:-11px}.sb-resizer:after{content:"";background:0 0;width:2px;transition:background .15s;position:absolute;top:0;bottom:0;left:-1px}.sb-resizer:hover:after,body.resizing .sb-resizer:after{background:var(--borStrTra)}body.resizing,body.resizing *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}body.resizing .sb-container,body.resizing .sidebar{transition:none!important}.sb-head{flex-direction:column;flex:none;gap:1px;padding:8px 8px 4px;transition:box-shadow .15s;display:flex}.sb-head.scrolled{box-shadow:0 1px 0 var(--borSec)}.sb-top{align-items:center;gap:5px;height:28px;margin-bottom:7px;padding-left:5px;display:flex}.sidebar.floating .sb-top{display:none}.sb-brand{white-space:nowrap;min-width:0;color:var(--texPri);cursor:default;-webkit-user-select:none;user-select:none;font-family:Iowan Old Style,Palatino Linotype,Palatino,Book Antiqua,Georgia,serif;font-size:19px;font-weight:400;line-height:28px;overflow:hidden}.sb-act{min-width:0;height:30px;color:var(--texSec);text-align:left;border-radius:6px;align-items:center;gap:8px;padding:0 8px;font-size:14px;font-weight:500;transition:background 20ms ease-in;display:flex}.sb-act:hover{background:var(--bacIntTra)}.sb-act-icon{width:22px;height:20px;color:var(--sidIco);flex:none;justify-content:center;align-items:center;display:flex}.sb-act-icon svg{width:18px;height:18px}.sb-act-label{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.sb-scroll{scrollbar-width:thin;scrollbar-color:var(--scrollThumb) transparent;flex:1;min-height:0;padding:6px 0 12px;position:relative;overflow:hidden auto}.section{margin:0 8px 4px}.section.expanded{padding-bottom:12px}.sec-head{-webkit-user-select:none;user-select:none;align-items:center;height:30px;padding:0 2px;display:flex}.sec-toggle{border-radius:6px;align-items:center;gap:2px;height:22px;padding:0 4px 0 6px;display:inline-flex}.sec-toggle:hover,.sec-head.menu-open .sec-toggle{background:var(--bacIntTra)}.sec-label{color:var(--texTer);white-space:nowrap;font-size:12px;font-weight:500;line-height:16px}.sec-chev{width:12px;height:12px;color:var(--texTer);opacity:0;transition:opacity .1s}.sec-chev svg{stroke-width:1.8px;transition:transform .2s ease-out}.section.expanded .sec-chev svg{transform:rotate(90deg)}.sec-toggle:hover .sec-chev,.sec-head.menu-open .sec-chev{opacity:1}.tree{margin-top:1px}.row{height:30px;padding:5px 8px 5px calc(8px + var(--depth,0) * 8px);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--texAcc);border-radius:6px;align-items:center;margin-bottom:1px;font-size:14px;display:flex;position:relative}.row:hover,.row.menu-open{background:var(--bacIntTra)}.row.selected{background:var(--bacIntTra);color:var(--texPri)}.row.selected:hover,.row.selected.menu-open{background:var(--bacTerTra)}.row-icon{flex:none;justify-content:center;align-items:center;width:22px;height:20px;margin-right:8px;display:flex;position:relative}.row-chevron{width:20px;height:20px;color:var(--texTer);opacity:0;border-radius:4px;justify-content:center;align-items:center;display:flex;position:absolute;top:0;left:1px}.row-chevron svg{stroke-width:1.8px;width:12px;height:12px;transition:transform .2s ease-out}.node.open>.row .row-chevron svg{transform:rotate(90deg)}.row.has-kids:hover .row-chevron{opacity:1}.row.has-kids:hover .pg-icon{opacity:0}.row-chevron:hover{background:var(--bacTerTra)}.row-title{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;line-height:21px;overflow:hidden}.row-actions{flex:none;align-items:center;gap:2px;margin-left:4px;display:none}.row:hover .row-actions,.row.menu-open .row-actions{display:flex}.row.renaming{cursor:default}.row.renaming .row-actions{display:none}.row-rename{background:var(--inputBac);min-width:0;height:24px;color:var(--texPri);font:inherit;box-shadow:inset 0 0 0 1px var(--blueLine), 0 0 0 2px var(--blueBg);border:0;border-radius:4px;outline:none;flex:1;margin:0 -2px 0 -6px;padding:0 6px;font-size:14px}@media (hover:none){.row.has-kids .row-chevron{opacity:1}.row.has-kids .pg-icon{opacity:0}}body.dragging,body.dragging *{cursor:grabbing!important;-webkit-user-select:none!important;user-select:none!important}body.dragging .row:not(.selected):hover{background:0 0}body.dragging .row-actions{display:none!important}body.dragging .row:hover .row-chevron{opacity:0}body.dragging .row:hover .pg-icon{opacity:1}.row.drag-src{opacity:.4}.row.drop-inside{background:var(--blueBg)!important}.drop-line{background:var(--blueLine);pointer-events:none;z-index:5;border-radius:2px;height:3px;display:none;position:absolute}.drop-line.show{display:block}.drag-ghost{z-index:3000;pointer-events:none;background:var(--popBac);height:30px;color:var(--texPri);box-shadow:var(--shaOutLg);opacity:.9;white-space:nowrap;border-radius:6px;align-items:center;gap:8px;padding:0 10px 0 8px;font-size:14px;display:flex;position:fixed;top:0;left:0;overflow:hidden}.drag-ghost .t{text-overflow:ellipsis;overflow:hidden}.sb-foot{flex:none;align-items:center;gap:4px;height:44px;padding:0 8px;display:flex}.ws-btn{min-width:0;height:28px;color:var(--texSec);text-align:left;border-radius:6px;flex:1;align-items:center;gap:8px;padding:0 6px 0 8px;font-size:14px;font-weight:500;display:flex}.ws-btn svg{width:18px;height:18px;color:var(--sidIco);flex:none}.ws-btn:hover,.ws-btn.menu-open{background:var(--bacIntTra)}.ws-name{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}@media (width<=768px){.sb-resizer{display:none}}.sb-note{color:var(--texTer);margin:4px 16px;font-size:13px}.sb-note.inset{margin:2px 8px 4px;padding-left:8px}.ws-dot{background:var(--texDis);border-radius:50%;flex:none;width:7px;height:7px}.ws-dot.ready{background:var(--gre-tx)}.ws-dot.loading{background:var(--yel-tx)}.ws-dot.offline,.ws-dot.error{background:var(--red-tx)}.tb-right .icon-btn.annot-open,.tb-right .icon-btn.annot-open:hover{background:var(--bacTerTra)}.menu.annot-list{width:320px;margin-top:4px}.annot-list .menu-scroll{max-height:384px;overflow-y:auto}.annot-list .menu-scroll .menu-item{height:44px}.annot-list .menu-scroll .mi-icon{display:none}.topbar{background:var(--bacPri);z-index:5;flex:none;align-items:center;gap:8px;height:44px;padding:0 12px;display:flex;position:relative}.tb-left{flex:1;align-items:center;min-width:0;display:flex}.tb-menu{color:var(--icoPri);margin:0 4px 0 1px;display:none}.app.sb-collapsed .tb-menu{display:inline-flex}.crumbs{align-items:center;min-width:0;display:flex;overflow:hidden}.crumb-wrap{display:contents}.crumb{white-space:nowrap;min-width:0;max-width:220px;height:24px;color:var(--texPri);border-radius:6px;align-items:center;gap:6px;padding:2px 6px;font-size:14px;display:inline-flex}.crumb:hover{background:var(--bacIntTra)}.crumb .t{text-overflow:ellipsis;overflow:hidden}.crumb .emoji{font-size:14px;line-height:1}.crumb-sep{color:var(--crumbSep);-webkit-user-select:none;user-select:none;flex:none;margin:0 1px;font-size:13px}.crumb-pop{z-index:1000;background:var(--popBac);width:180px;max-height:calc(100vh - 16px);box-shadow:var(--shaOutLg);-webkit-user-select:none;user-select:none;scrollbar-width:thin;scrollbar-color:var(--scrollThumb) transparent;border-radius:10px;flex-direction:column;gap:1px;padding:4px;font-size:14px;line-height:1.2;display:flex;position:fixed;top:0;left:0;overflow-y:auto}.crumb-pop-head{color:var(--texSec);white-space:nowrap;flex:none;margin:6px 0 8px;padding:0 8px;font-size:12px;font-weight:500}.crumb-pop-item{cursor:pointer;height:28px;color:var(--texPri);border-radius:6px;flex:none;align-items:center;gap:8px;padding:0 8px;display:flex}.crumb-pop-item:hover,.crumb-pop-item.open,.crumb-pop-item.trigger{background:var(--bacIntTra)}.crumb-pop-item.current{background:var(--bluBacIntTra)}.crumb-pop-item .t{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.crumb-pop-item.more{color:var(--texSec)}.crumb-pop-arrow{width:16px;height:16px;color:var(--texDis);flex:none}.crumb-pop-arrow svg{stroke-width:1.8px}.tb-right{flex:none;align-items:center;gap:2px;display:flex}.tb-right .icon-btn{color:var(--icoPri)}.tb-right .icon-btn.on{color:var(--star)}.tb-right .icon-btn.menu-open{background:var(--bacIntTra)}.edited{color:var(--texTer);white-space:nowrap;margin-right:8px;font-size:14px}@media (width<=1000px){.edited{display:none}}.session-badge{white-space:nowrap;border-radius:10px;flex:none;margin-left:8px;padding:1px 8px;font-size:12px;line-height:20px}.session-badge.muted{color:var(--texTer)}.session-badge.warn{color:var(--ora-tx);background:var(--ora-bg)}.session-badge.danger{color:var(--red-tx);background:var(--red-bg)}.menu.look-menu{width:224px;max-width:none;padding-bottom:8px}.look-fonts,.look-row{gap:4px;padding:0 8px;display:flex}.look-fonts{margin-bottom:4px}.look-font,.look-option{min-width:0;color:var(--texPri);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:1 1 0;transition:background 20ms ease-in}.look-font{flex-direction:column;align-items:center;padding:8px 4px 6px;display:flex}.look-glyph{white-space:nowrap;height:30px;font-size:24px;line-height:30px}.look-caption{color:var(--texSec);white-space:nowrap;text-overflow:ellipsis;max-width:100%;margin-top:2px;font-size:12px;line-height:16px;overflow:hidden}.look-option{white-space:nowrap;justify-content:center;align-items:center;height:28px;padding:0 4px;font-size:14px;display:flex}.look-font:hover,.look-option:hover{background:var(--bacIntTra)}.look-font.on .look-glyph,.look-option.on{color:var(--blue)}.look-font:focus-visible,.look-option:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}.look-menu .menu-sep{margin:8px 12px 4px}
|