dsh-cuigengji-plugin 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1 -1
  3. package/cordis.patch.yml +3 -3
  4. package/docs/CHANGELOG.md +15 -0
  5. package/docs/agent-installation.md +19 -12
  6. package/docs/architecture.md +74 -74
  7. package/docs/desktop-migration-20260930.md +26 -26
  8. package/docs/development.md +7 -3
  9. package/docs/getting-started.md +17 -7
  10. package/docs/layout-progress.md +31 -31
  11. package/docs/market-listing.md +5 -3
  12. package/docs/npm-publishing.md +35 -11
  13. package/docs/package-name-migration.md +3 -3
  14. package/docs/planning-board.md +44 -44
  15. package/docs/presets.md +24 -24
  16. package/docs/release-process.md +45 -10
  17. package/docs/tavern-compatibility-audit-20261001.md +109 -109
  18. package/docs/test-report.md +139 -129
  19. package/docs/upgrade.md +3 -1
  20. package/docs/usage-review.md +13 -13
  21. package/lib/client.js +19 -14
  22. package/package.json +19 -14
  23. package/skills/cuigengji-maintenance/SKILL.md +2 -2
  24. package/src/adapters/dsh/prompt.js +36 -36
  25. package/src/adapters/dsh/rpc.js +96 -96
  26. package/src/adapters/dsh/skills.js +17 -17
  27. package/src/adapters/mcp/actions.js +6 -6
  28. package/src/adapters/mcp/client.js +172 -172
  29. package/src/adapters/mcp/server.js +40 -40
  30. package/src/application/bindings/session.js +72 -72
  31. package/src/application/queries/context.js +15 -15
  32. package/src/application/store.js +412 -412
  33. package/src/client/features/chapters/clipboard.ts +27 -27
  34. package/src/client/features/chapters/history.ts +11 -11
  35. package/src/client/features/chapters/index.jsx +118 -118
  36. package/src/client/features/chapters/sync.ts +155 -155
  37. package/src/client/features/chapters/useChapterSync.ts +39 -39
  38. package/src/client/features/context/index.jsx +22 -22
  39. package/src/client/features/memory/index.jsx +73 -73
  40. package/src/client/features/planning/Decorations.tsx +1 -1
  41. package/src/client/features/planning/Pages.tsx +11 -11
  42. package/src/client/features/planning/data.js +16 -16
  43. package/src/client/index.tsx +130 -130
  44. package/src/client/launcher.tsx +78 -78
  45. package/src/client/shared/creation.tsx +34 -34
  46. package/src/client/shared/detail-page.tsx +61 -61
  47. package/src/client/shared/drafts.js +17 -17
  48. package/src/client/shared/evidence.jsx +11 -11
  49. package/src/client/shared/groups.tsx +34 -34
  50. package/src/client/shared/preferences.tsx +104 -104
  51. package/src/client/shared/select-style.ts +25 -25
  52. package/src/client/shared/state.js +95 -95
  53. package/src/client/shared/ui.jsx +19 -19
  54. package/src/client/shared/workspace.tsx +11 -11
  55. package/src/client/style.ts +274 -274
  56. package/src/client/visual.ts +190 -190
  57. package/src/contracts/actions.js +19 -19
  58. package/src/contracts/planning.ts +52 -52
  59. package/src/domain/manuscript.ts +4 -4
  60. package/src/domain/planning/index.ts +113 -113
  61. package/src/domain/planning/model.ts +59 -59
  62. package/src/domain/preset/index.js +89 -89
  63. package/src/index.js +91 -91
  64. package/src/infrastructure/migrations/legacy.js +96 -96
  65. package/src/infrastructure/migrations/tavern.js +78 -78
  66. package/src/infrastructure/persistence/atomic-store.ts +80 -80
  67. package/src/infrastructure/persistence/project-layout.ts +1 -1
@@ -1,161 +1,161 @@
1
- /** The approved reading-first design. Host tokens retain light/dark integration. */
2
- export const visualStyles = `
3
- .cuigengji { --cg-paper:var(--dsw-alias-bg-base,#ffffff); --cg-ink:var(--dsw-alias-label-primary,#252936); --cg-muted:var(--dsw-alias-label-secondary,#737780); --cg-line:var(--dsw-alias-border-l1,#dde0e6); --cg-accent:var(--dsw-alias-state-business-primary,#4d6bfe); --cg-wash:color-mix(in srgb,var(--cg-accent) 7%,var(--cg-paper)); --dsw-focus-ring-color:var(--cg-accent); color:var(--cg-ink); }
4
- .cuigengji:not(dialog) { background:var(--cg-paper); }
5
- .cuigengji button,.cuigengji summary,.cuigengji select { transition:background 120ms,border-color 120ms,color 120ms; }
6
- .cuigengji button,.cuigengji input,.cuigengji textarea,.cuigengji select {border-color:var(--cg-line);}
7
- .cuigengji button:not(:disabled):hover,.cuigengji .menu>summary:hover {background:var(--cg-wash);}
8
- .cuigengji button.primary:hover {background:var(--cg-accent);}
9
- .cuigengji .primary {background:var(--cg-accent);color:var(--dsw-alias-label-on-color,#fff);}
10
- .cuigengji .workbench-header {display:flex;align-items:center;gap:24px;padding:8px 24px;flex-wrap:wrap;}
11
- .cuigengji .identity {flex:1;min-width:230px;padding:0;}
12
- .cuigengji .workbench-header nav {order:2;width:100%;}
13
- .cuigengji nav button {padding:9px 6px;}
14
- .cuigengji .book-picker {font-size:16px;max-width:280px;}
15
- .cuigengji .app-actions {display:flex;margin-left:auto;gap:4px;}
16
- .cuigengji .app-actions button {border:0;background:none;color:var(--cg-muted);font-size:12px;}
17
- .cuigengji .module-heading {padding:16px 24px 12px;}
18
- .cuigengji .module-toolbar {display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
19
- .cuigengji .module-toolbar h2 {margin:0;font-size:17px;font-weight:600;}
20
- .cuigengji .module-search {width:180px;min-width:90px;max-width:280px;flex:1;margin-left:auto;border-color:transparent;background:transparent;font-size:12px;}
21
- .cuigengji .module-search:focus {border-color:var(--cg-line);}
22
- .cuigengji .module-toolbar>.primary {white-space:nowrap;}
23
- .cuigengji .module-toolbar .segmented {font-size:12px;}
24
- .cuigengji .filter-strip {display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px;}
25
- .cuigengji .group-toolbar {display:contents;}
26
- .cuigengji .filter-control {position:relative;display:flex;align-items:center;gap:8px;border:1px solid var(--cg-line);border-radius:7px;background:var(--cg-paper);padding:0 10px;height:36px;min-width:0;margin:0;color:var(--cg-muted);max-width:260px;}
27
- .cuigengji .filter-control:focus-within {outline:2px solid var(--cg-accent);outline-offset:2px;}
28
- .cuigengji .filter-control.is-active {background:var(--cg-wash);border-color:color-mix(in srgb,var(--cg-accent) 45%,var(--cg-line));color:var(--cg-accent);}
29
- .cuigengji .filter-prefix {font-size:10px;border-right:1px solid var(--cg-line);padding-right:8px;white-space:nowrap;}
30
- .cuigengji .filter-control select {appearance:none;background:transparent;color:inherit;border:0;border-radius:0;outline:none;font-size:12px;padding:0 20px 0 0;height:100%;max-width:150px;min-width:0;text-overflow:ellipsis;}
31
- .cuigengji .filter-control option {background:var(--cg-paper);color:var(--cg-ink);}
32
- .cuigengji .filter-chevron {position:absolute;right:12px;width:5px;height:5px;border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:rotate(45deg);pointer-events:none;margin-top:-3px;}
33
- .cuigengji .group-new {color:var(--cg-accent);border-color:transparent;background:transparent;font-size:12px;white-space:nowrap;}
34
- .cuigengji .scope-count {color:var(--cg-muted);font-size:11px;margin-left:auto;}
35
- .cuigengji .clear-filter {border:0;font-size:11px;color:var(--cg-accent);padding:4px;background:transparent;}
36
- .cuigengji .memory-workspace {flex:1;display:flex;flex-direction:column;min-height:0;position:relative;}
37
- .cuigengji .memory-layout {flex:1;min-height:0;gap:0;}
38
- .cuigengji .memory-overview {display:flex;flex-direction:column;min-height:0;}
39
- .cuigengji .library-list,.cuigengji .planning-list {padding:12px 28px 32px;overflow:auto;flex:1;}
40
- .cuigengji .library-entry {display:block;width:100%;text-align:left;border:0;border-bottom:1px solid var(--cg-line);border-radius:0;background:transparent;padding:22px 2px;}
41
- .cuigengji .entry-heading {display:flex;align-items:center;gap:12px;justify-content:space-between;}
42
- .cuigengji .library-entry strong,.cuigengji .planning-list .planning-title {font-size:17px;font-weight:600;}
43
- .cuigengji .library-entry small {font-size:11px;color:var(--cg-muted);}
44
- .cuigengji .library-entry p,.cuigengji .planning-list .card>p {font-size:13px;color:var(--cg-muted);line-height:1.8;margin:8px 0 0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
45
- .cuigengji .planning-list .card {padding:20px 2px;}
46
- .cuigengji .planning-list .planning-title {padding:0;min-height:28px;}
47
- .cuigengji .planning-directory {display:none;}
48
- .cuigengji .overview-page {display:flex;flex-direction:column;flex:1;min-height:0;min-width:0;overflow:hidden;}
49
- .cuigengji .overview-page[hidden] {display:none;}
50
- .cuigengji .detail-page {display:flex;flex-direction:column;flex:1;min-height:0;min-width:0;width:100%;overflow:hidden;animation:cg-arrive 150ms ease-out;}
51
- .cuigengji .detail-bar {display:flex;align-items:center;gap:12px;padding:10px 24px;flex:none;border-bottom:1px solid var(--cg-line);}
52
- .cuigengji .detail-back {border:0;background:none;font-size:12px;color:var(--cg-muted);margin:0;padding-left:0;}
53
- .cuigengji .detail-actions {display:flex;align-items:center;gap:8px;margin-left:auto;}
54
- .cuigengji .detail-actions button {font-size:12px;}
55
- .cuigengji .detail-scroll {flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding:24px clamp(24px,5cqw,64px) 48px;}
56
- .cuigengji .detail-document {max-width:680px;margin-inline:auto;}
57
- .cuigengji .library-entry.selected,.cuigengji .planning-list .card.selected {background:var(--cg-wash);}
58
- .cuigengji .chapter-main .manuscript {max-width:none;margin-inline:0;}
59
- .cuigengji .planning-detail h2,.cuigengji .memory-detail h2 {font-family:Georgia,'Noto Serif SC','SimSun',serif;font-size:28px;letter-spacing:.025em;font-weight:600;line-height:1.5;}
60
- .cuigengji .document-summary {color:var(--cg-muted);font-size:15px;line-height:1.9;white-space:pre-wrap;margin:20px 0 30px;}
61
- .cuigengji .document-summary:empty {display:none;}
62
- .cuigengji .document-body {white-space:pre-wrap;overflow-wrap:anywhere;font-size:16px;line-height:1.95;padding:0;margin:0 0 32px;}
63
- .cuigengji .document-fields>label {font-size:12px;color:var(--cg-muted);margin:18px 0;}
64
- .cuigengji .document-fields>label:has(input),.cuigengji .document-fields>label:has(textarea) {gap:12px;}
65
- .cuigengji .document-fields input,.cuigengji .document-fields textarea {border:0;border-radius:0;background:transparent;color:var(--cg-ink);padding:4px 0;box-shadow:none;}
66
- .cuigengji .document-fields input {font-family:Georgia,'Noto Serif SC','SimSun',serif;font-size:27px;font-weight:600;}
67
- .cuigengji .document-fields textarea {font-size:15px;min-height:80px;line-height:1.95;}
68
- .cuigengji .document-fields textarea.prose {font-size:17px;min-height:320px;}
69
- .cuigengji .document-fields small {font-weight:400;opacity:.7;}
70
- .cuigengji .document-fields input:focus-visible,.cuigengji .document-fields textarea:focus-visible {outline:0;box-shadow:-3px 0 0 -1px var(--cg-accent);padding-left:10px;}
71
- .cuigengji .flow-context {background:transparent;border-top:1px solid var(--cg-line);padding:20px 0;margin-top:28px;}
72
- .cuigengji .section-fold {font-size:12px;border-color:var(--cg-line);}
73
- .cuigengji .section-fold>summary {font-weight:500;color:var(--cg-muted);}
74
- .cuigengji .related-entry {display:flex;flex-wrap:wrap;align-items:center;gap:8px;border-top:1px solid var(--cg-line);padding:10px 0;}
75
- .cuigengji .related-entry button {border:0;background:transparent;font-size:12px;}
76
- .cuigengji .related-entry button:last-child {margin-left:auto;}
77
- .cuigengji .related-entry small {color:var(--cg-muted);}
78
- .cuigengji .related-entry p {flex-basis:100%;font-size:12px;line-height:1.8;margin:0;}
79
- .cuigengji .canvas-tools {padding:6px 24px;gap:6px;margin:0;background:var(--cg-paper);}
80
- .cuigengji .canvas-tools button,.cuigengji .canvas-tools summary {font-size:12px;background:transparent;}
81
- .cuigengji .zoom-controls {display:flex;margin-left:auto;gap:2px;}
82
- .cuigengji .zoom-controls button {border:0;min-width:30px;}
83
- .cuigengji .planning-canvas-scroll {background-color:var(--cg-paper);background-image:radial-gradient(circle,color-mix(in srgb,var(--cg-muted) 22%,transparent) 1px,transparent 1px);background-size:24px 24px;}
84
- .cuigengji .planning-card {width:224px;height:156px;border:1px solid var(--cg-line);border-radius:9px;padding:12px 14px;box-shadow:0 3px 10px #00000005;background:var(--cg-paper);}
85
- .cuigengji .planning-card .planning-title {font-size:15px;padding:4px 0;}
86
- .cuigengji .planning-card p {display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;line-height:1.7;color:var(--cg-muted);}
87
- .cuigengji .planning-card .drag-handle {font-size:10px;height:14px;}
88
- .cuigengji .drag-handle span {visibility:hidden;}
89
- .cuigengji .planning-card:hover .drag-handle span {visibility:visible;}
90
- .cuigengji .planning-card.selected,.cuigengji .planning-card.connect-source {outline:1px solid var(--cg-accent);background:var(--cg-wash);}
91
- .cuigengji .planning-state {font-size:10px;margin-top:6px;}
92
- .cuigengji .planning-group-frame {border-color:color-mix(in srgb,var(--cg-accent) 18%,transparent);background:color-mix(in srgb,var(--cg-accent) 2%,transparent);}
93
- .cuigengji .relation-label {position:absolute;width:180px;z-index:2;padding:6px 10px;border-radius:7px;background:var(--cg-paper);font-size:11px;text-align:center;}
94
- .cuigengji .relation-label .edge-label-content {border:0;padding:0;min-height:0;display:block;width:100%;font-size:11px;background:none;}
95
- .cuigengji .relation-label strong {display:block;font-size:11px;font-weight:500;color:var(--cg-accent);}
96
- .cuigengji .relation-label span {display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.6;color:var(--cg-muted);}
97
- .cuigengji .relation-label.expanded {z-index:4;box-shadow:0 5px 20px #0002;}
98
- .cuigengji .relation-label.expanded span {-webkit-line-clamp:unset;max-height:240px;overflow:auto;white-space:pre-wrap;}
99
- .cuigengji .relation-label .expand-edge {border:0;min-height:20px;padding:0;font-size:10px;color:var(--cg-accent);}
100
- .cuigengji .creation {display:flex;flex-direction:column;flex:1;min-height:0;animation:cg-arrive 150ms ease-out;}
101
- .cuigengji .creation-bar {display:flex;align-items:center;gap:12px;padding:14px 24px;border-bottom:1px solid var(--cg-line);flex:none;}
102
- .cuigengji .creation-bar>button:first-child {border:0;background:none;}
103
- .cuigengji .creation-scroll {flex:1;min-height:0;overflow:auto;padding:32px 32px 60px;}
104
- .cuigengji .creation-document {max-width:680px;margin:auto;}
105
- .cuigengji .creation-context {border-left:2px solid var(--cg-accent);padding-left:12px;color:var(--cg-accent);font-size:12px;}
106
- .cuigengji .creation-settings {display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-bottom:12px;border-bottom:1px solid var(--cg-line);}
107
- .cuigengji .creation-settings label {display:flex;align-items:center;gap:8px;font-size:12px;min-width:0;}
108
- .cuigengji .creation-settings select {max-width:240px;border:0;}
109
- .cuigengji .creation-settings button {border:0;color:var(--cg-accent);background:none;font-size:12px;}
110
- .cuigengji .chapter-directory {background:color-mix(in srgb,var(--cg-ink) 2%,var(--cg-paper));}
111
- .cuigengji .manuscript {line-height:var(--prose-leading,1.95);}
112
- .cuigengji .directory-foot {border-top:1px solid var(--cg-line);font-size:11px;color:var(--cg-muted);padding:16px 8px;margin-top:18px;}
113
- .cuigengji .utility-modal {color:var(--cg-ink);width:min(600px,calc(100vw - 32px));max-height:calc(100dvh - 40px);padding:0;border:1px solid var(--cg-line);border-radius:12px;background:var(--cg-paper);box-shadow:0 18px 60px #0003;overflow:auto;overscroll-behavior:contain;container:cg-utility / inline-size;-webkit-app-region:no-drag;}
114
- .cuigengji .utility-modal::backdrop {background:#17203355;backdrop-filter:blur(2px);}
115
- .cuigengji .utility-head {position:sticky;top:0;background:var(--cg-paper);display:flex;align-items:center;justify-content:space-between;padding:18px 28px 14px;border-bottom:1px solid var(--cg-line);z-index:1;}
116
- .cuigengji .utility-head h2 {margin:0;font-size:22px;}
117
- .cuigengji .utility-head button {border:0;background:none;font-size:24px;width:40px;height:40px;padding:0;flex:none;-webkit-app-region:no-drag;}
118
- .cuigengji .utility-content {padding:4px 28px 24px;}
119
- .cuigengji .preference-section {padding:16px 0;border-bottom:1px solid var(--cg-line);}
120
- .cuigengji .preference-section h3 {font-size:13px;margin:0 0 12px;}
121
- .cuigengji .preference-section .split {grid-template-columns:1fr 1fr;}
122
- .cuigengji .reading-preview {padding:18px 20px;border-radius:8px;background:var(--cg-wash);}
123
- .cuigengji .reading-preview small {color:var(--cg-muted);font-size:10px;}
124
- .cuigengji .reading-preview p {margin:10px 0 0;}
125
- .cuigengji .preference-row {display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:44px;font-size:13px;}
126
- .cuigengji .preference-row select {width:154px;max-width:52%;}
127
- .cuigengji .utility-footer {display:flex;align-items:center;gap:16px;padding-top:20px;flex-wrap:wrap;}
128
- .cuigengji .utility-footer button {border:0;background:none;color:var(--cg-accent);}
129
- .cuigengji .utility-footer small {color:var(--cg-muted);font-size:11px;}
130
- .cuigengji .about-overview {display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:18px 24px;align-items:center;padding:26px 0;}
131
- .cuigengji .about-identity {display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
132
- .cuigengji .about-identity h2 {font-size:28px;margin:0;}
133
- .cuigengji .about-version {font-size:11px;color:var(--cg-muted);border:1px solid var(--cg-line);border-radius:6px;padding:2px 6px;white-space:nowrap;}
134
- .cuigengji .about-tagline {font-size:17px;line-height:1.7;margin:12px 0 0;max-width:17em;}
135
- .cuigengji .about-sticker {display:block;width:100%;height:auto;aspect-ratio:1;object-fit:contain;border-radius:14px;background:#fff;}
136
- .cuigengji .about-description {grid-column:1 / -1;font-size:13px;color:var(--cg-muted);line-height:1.9;margin:0;}
137
- .cuigengji .about-contacts {border-top:1px solid var(--cg-line);}
138
- .cuigengji .about-contact {display:grid;grid-template-columns:64px minmax(0,1fr) 20px;gap:12px;align-items:center;min-height:58px;width:100%;padding:14px 4px;border:0;border-bottom:1px solid var(--cg-line);border-radius:0;background:none;color:var(--cg-ink);font:inherit;text-align:left;text-decoration:none;transition:background 120ms;}
139
- .cuigengji .about-contact:hover {background:var(--cg-wash);}
140
- .cuigengji .about-contact:focus-visible {outline:2px solid var(--cg-accent);outline-offset:2px;border-radius:4px;}
141
- .cuigengji .about-contact-label {font-size:12px;color:var(--cg-muted);}
142
- .cuigengji .about-contact strong {font-size:14px;font-weight:500;overflow-wrap:anywhere;}
143
- .cuigengji .about-contact-mark {font-size:17px;color:var(--cg-accent);text-align:center;}
144
- .cuigengji .about-copy-status {min-height:18px;margin:8px 4px 0;font-size:11px;color:var(--cg-accent);}
145
- .cuigengji .about-welcome {padding:8px 0 0;}
146
- .cuigengji .about-welcome p {font-size:12px;color:var(--cg-muted);line-height:1.9;margin:0;}
147
- .cuigengji .about-welcome p:first-child {color:var(--cg-ink);margin-bottom:4px;}
148
- .cuigengji .chapter-settings-panel {width:min(230px,76vw);}
149
- .cuigengji .chapter-settings-panel label {margin:4px 4px 10px;font-size:12px;color:var(--cg-muted);}
150
- .cuigengji .chapter-settings-panel select {width:100%;color:var(--cg-ink);}
151
- .cuigengji .chapter-settings-panel button {border:0;background:none;}
152
- @container cg-utility (max-width:420px){.cuigengji .about-overview {grid-template-columns:minmax(0,1fr) 88px;gap:18px 12px;padding:22px 0;}.cuigengji .about-identity {gap:8px;}.cuigengji .about-identity h2 {font-size:26px;}.cuigengji .about-tagline {font-size:15px;margin-top:10px;}.cuigengji .about-contact {grid-template-columns:52px minmax(0,1fr) 16px;gap:10px;}.cuigengji .about-contact strong {font-size:13px;}}
153
- @container(min-width:760px){.cuigengji .workbench-header {display:grid;grid-template-columns:minmax(130px,1fr) auto auto;gap:20px;padding:8px 24px;}.cuigengji .identity,.cuigengji .header-row {display:contents;}.cuigengji .book-picker {grid-column:1;grid-row:1;width:100%;}.cuigengji .workbench-header nav {grid-column:2;grid-row:1;width:auto;gap:20px;order:0;}.cuigengji .workbench-header nav button {min-width:64px;}.cuigengji .header-row>.menu {grid-column:3;grid-row:1;justify-self:start;}.cuigengji .app-actions {grid-column:3;grid-row:1;padding-left:32px;}.cuigengji .workbench-header .header-row>.menu {z-index:3;}}
154
- @container(max-width:599px){.cuigengji .workbench-header {padding:6px 16px;gap:6px;}.cuigengji .module-heading {padding:12px 16px;}.cuigengji .module-toolbar {gap:6px;}.cuigengji .module-toolbar h2 {font-size:15px;}.cuigengji .module-search {order:5;flex-basis:100%;max-width:none;margin:0;}.cuigengji .module-toolbar>.primary,.cuigengji .module-toolbar>.menu:has(.primary) {margin-left:auto;}.cuigengji .filter-prefix {display:none;}.cuigengji .filter-strip {gap:6px;}.cuigengji .filter-control select {max-width:110px;font-size:11px;}.cuigengji .group-new {font-size:11px;padding:4px;}.cuigengji .scope-count {display:none;}.cuigengji .detail-scroll {padding:20px 24px 40px;}.cuigengji .detail-bar {padding:8px 16px;}.cuigengji .creation-scroll {padding:24px;}.cuigengji .creation-bar {padding:12px 16px;}.cuigengji .canvas-tools {padding:6px 16px;}.cuigengji .creation-settings select {max-width:170px;}.cuigengji .utility-head {padding:16px 20px 12px;}.cuigengji .utility-content {padding:4px 20px 20px;}}
1
+ /** The approved reading-first design. Host tokens retain light/dark integration. */
2
+ export const visualStyles = `
3
+ .cuigengji { --cg-paper:var(--dsw-alias-bg-base,#ffffff); --cg-ink:var(--dsw-alias-label-primary,#252936); --cg-muted:var(--dsw-alias-label-secondary,#737780); --cg-line:var(--dsw-alias-border-l1,#dde0e6); --cg-accent:var(--dsw-alias-state-business-primary,#4d6bfe); --cg-wash:color-mix(in srgb,var(--cg-accent) 7%,var(--cg-paper)); --dsw-focus-ring-color:var(--cg-accent); color:var(--cg-ink); }
4
+ .cuigengji:not(dialog) { background:var(--cg-paper); }
5
+ .cuigengji button,.cuigengji summary,.cuigengji select { transition:background 120ms,border-color 120ms,color 120ms; }
6
+ .cuigengji button,.cuigengji input,.cuigengji textarea,.cuigengji select {border-color:var(--cg-line);}
7
+ .cuigengji button:not(:disabled):hover,.cuigengji .menu>summary:hover {background:var(--cg-wash);}
8
+ .cuigengji button.primary:hover {background:var(--cg-accent);}
9
+ .cuigengji .primary {background:var(--cg-accent);color:var(--dsw-alias-label-on-color,#fff);}
10
+ .cuigengji .workbench-header {display:flex;align-items:center;gap:24px;padding:8px 24px;flex-wrap:wrap;}
11
+ .cuigengji .identity {flex:1;min-width:230px;padding:0;}
12
+ .cuigengji .workbench-header nav {order:2;width:100%;}
13
+ .cuigengji nav button {padding:9px 6px;}
14
+ .cuigengji .book-picker {font-size:16px;max-width:280px;}
15
+ .cuigengji .app-actions {display:flex;margin-left:auto;gap:4px;}
16
+ .cuigengji .app-actions button {border:0;background:none;color:var(--cg-muted);font-size:12px;}
17
+ .cuigengji .module-heading {padding:16px 24px 12px;}
18
+ .cuigengji .module-toolbar {display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
19
+ .cuigengji .module-toolbar h2 {margin:0;font-size:17px;font-weight:600;}
20
+ .cuigengji .module-search {width:180px;min-width:90px;max-width:280px;flex:1;margin-left:auto;border-color:transparent;background:transparent;font-size:12px;}
21
+ .cuigengji .module-search:focus {border-color:var(--cg-line);}
22
+ .cuigengji .module-toolbar>.primary {white-space:nowrap;}
23
+ .cuigengji .module-toolbar .segmented {font-size:12px;}
24
+ .cuigengji .filter-strip {display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px;}
25
+ .cuigengji .group-toolbar {display:contents;}
26
+ .cuigengji .filter-control {position:relative;display:flex;align-items:center;gap:8px;border:1px solid var(--cg-line);border-radius:7px;background:var(--cg-paper);padding:0 10px;height:36px;min-width:0;margin:0;color:var(--cg-muted);max-width:260px;}
27
+ .cuigengji .filter-control:focus-within {outline:2px solid var(--cg-accent);outline-offset:2px;}
28
+ .cuigengji .filter-control.is-active {background:var(--cg-wash);border-color:color-mix(in srgb,var(--cg-accent) 45%,var(--cg-line));color:var(--cg-accent);}
29
+ .cuigengji .filter-prefix {font-size:10px;border-right:1px solid var(--cg-line);padding-right:8px;white-space:nowrap;}
30
+ .cuigengji .filter-control select {appearance:none;background:transparent;color:inherit;border:0;border-radius:0;outline:none;font-size:12px;padding:0 20px 0 0;height:100%;max-width:150px;min-width:0;text-overflow:ellipsis;}
31
+ .cuigengji .filter-control option {background:var(--cg-paper);color:var(--cg-ink);}
32
+ .cuigengji .filter-chevron {position:absolute;right:12px;width:5px;height:5px;border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:rotate(45deg);pointer-events:none;margin-top:-3px;}
33
+ .cuigengji .group-new {color:var(--cg-accent);border-color:transparent;background:transparent;font-size:12px;white-space:nowrap;}
34
+ .cuigengji .scope-count {color:var(--cg-muted);font-size:11px;margin-left:auto;}
35
+ .cuigengji .clear-filter {border:0;font-size:11px;color:var(--cg-accent);padding:4px;background:transparent;}
36
+ .cuigengji .memory-workspace {flex:1;display:flex;flex-direction:column;min-height:0;position:relative;}
37
+ .cuigengji .memory-layout {flex:1;min-height:0;gap:0;}
38
+ .cuigengji .memory-overview {display:flex;flex-direction:column;min-height:0;}
39
+ .cuigengji .library-list,.cuigengji .planning-list {padding:12px 28px 32px;overflow:auto;flex:1;}
40
+ .cuigengji .library-entry {display:block;width:100%;text-align:left;border:0;border-bottom:1px solid var(--cg-line);border-radius:0;background:transparent;padding:22px 2px;}
41
+ .cuigengji .entry-heading {display:flex;align-items:center;gap:12px;justify-content:space-between;}
42
+ .cuigengji .library-entry strong,.cuigengji .planning-list .planning-title {font-size:17px;font-weight:600;}
43
+ .cuigengji .library-entry small {font-size:11px;color:var(--cg-muted);}
44
+ .cuigengji .library-entry p,.cuigengji .planning-list .card>p {font-size:13px;color:var(--cg-muted);line-height:1.8;margin:8px 0 0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
45
+ .cuigengji .planning-list .card {padding:20px 2px;}
46
+ .cuigengji .planning-list .planning-title {padding:0;min-height:28px;}
47
+ .cuigengji .planning-directory {display:none;}
48
+ .cuigengji .overview-page {display:flex;flex-direction:column;flex:1;min-height:0;min-width:0;overflow:hidden;}
49
+ .cuigengji .overview-page[hidden] {display:none;}
50
+ .cuigengji .detail-page {display:flex;flex-direction:column;flex:1;min-height:0;min-width:0;width:100%;overflow:hidden;animation:cg-arrive 150ms ease-out;}
51
+ .cuigengji .detail-bar {display:flex;align-items:center;gap:12px;padding:10px 24px;flex:none;border-bottom:1px solid var(--cg-line);}
52
+ .cuigengji .detail-back {border:0;background:none;font-size:12px;color:var(--cg-muted);margin:0;padding-left:0;}
53
+ .cuigengji .detail-actions {display:flex;align-items:center;gap:8px;margin-left:auto;}
54
+ .cuigengji .detail-actions button {font-size:12px;}
55
+ .cuigengji .detail-scroll {flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding:24px clamp(24px,5cqw,64px) 48px;}
56
+ .cuigengji .detail-document {max-width:680px;margin-inline:auto;}
57
+ .cuigengji .library-entry.selected,.cuigengji .planning-list .card.selected {background:var(--cg-wash);}
58
+ .cuigengji .chapter-main .manuscript {max-width:none;margin-inline:0;}
59
+ .cuigengji .planning-detail h2,.cuigengji .memory-detail h2 {font-family:Georgia,'Noto Serif SC','SimSun',serif;font-size:28px;letter-spacing:.025em;font-weight:600;line-height:1.5;}
60
+ .cuigengji .document-summary {color:var(--cg-muted);font-size:15px;line-height:1.9;white-space:pre-wrap;margin:20px 0 30px;}
61
+ .cuigengji .document-summary:empty {display:none;}
62
+ .cuigengji .document-body {white-space:pre-wrap;overflow-wrap:anywhere;font-size:16px;line-height:1.95;padding:0;margin:0 0 32px;}
63
+ .cuigengji .document-fields>label {font-size:12px;color:var(--cg-muted);margin:18px 0;}
64
+ .cuigengji .document-fields>label:has(input),.cuigengji .document-fields>label:has(textarea) {gap:12px;}
65
+ .cuigengji .document-fields input,.cuigengji .document-fields textarea {border:0;border-radius:0;background:transparent;color:var(--cg-ink);padding:4px 0;box-shadow:none;}
66
+ .cuigengji .document-fields input {font-family:Georgia,'Noto Serif SC','SimSun',serif;font-size:27px;font-weight:600;}
67
+ .cuigengji .document-fields textarea {font-size:15px;min-height:80px;line-height:1.95;}
68
+ .cuigengji .document-fields textarea.prose {font-size:17px;min-height:320px;}
69
+ .cuigengji .document-fields small {font-weight:400;opacity:.7;}
70
+ .cuigengji .document-fields input:focus-visible,.cuigengji .document-fields textarea:focus-visible {outline:0;box-shadow:-3px 0 0 -1px var(--cg-accent);padding-left:10px;}
71
+ .cuigengji .flow-context {background:transparent;border-top:1px solid var(--cg-line);padding:20px 0;margin-top:28px;}
72
+ .cuigengji .section-fold {font-size:12px;border-color:var(--cg-line);}
73
+ .cuigengji .section-fold>summary {font-weight:500;color:var(--cg-muted);}
74
+ .cuigengji .related-entry {display:flex;flex-wrap:wrap;align-items:center;gap:8px;border-top:1px solid var(--cg-line);padding:10px 0;}
75
+ .cuigengji .related-entry button {border:0;background:transparent;font-size:12px;}
76
+ .cuigengji .related-entry button:last-child {margin-left:auto;}
77
+ .cuigengji .related-entry small {color:var(--cg-muted);}
78
+ .cuigengji .related-entry p {flex-basis:100%;font-size:12px;line-height:1.8;margin:0;}
79
+ .cuigengji .canvas-tools {padding:6px 24px;gap:6px;margin:0;background:var(--cg-paper);}
80
+ .cuigengji .canvas-tools button,.cuigengji .canvas-tools summary {font-size:12px;background:transparent;}
81
+ .cuigengji .zoom-controls {display:flex;margin-left:auto;gap:2px;}
82
+ .cuigengji .zoom-controls button {border:0;min-width:30px;}
83
+ .cuigengji .planning-canvas-scroll {background-color:var(--cg-paper);background-image:radial-gradient(circle,color-mix(in srgb,var(--cg-muted) 22%,transparent) 1px,transparent 1px);background-size:24px 24px;}
84
+ .cuigengji .planning-card {width:224px;height:156px;border:1px solid var(--cg-line);border-radius:9px;padding:12px 14px;box-shadow:0 3px 10px #00000005;background:var(--cg-paper);}
85
+ .cuigengji .planning-card .planning-title {font-size:15px;padding:4px 0;}
86
+ .cuigengji .planning-card p {display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;line-height:1.7;color:var(--cg-muted);}
87
+ .cuigengji .planning-card .drag-handle {font-size:10px;height:14px;}
88
+ .cuigengji .drag-handle span {visibility:hidden;}
89
+ .cuigengji .planning-card:hover .drag-handle span {visibility:visible;}
90
+ .cuigengji .planning-card.selected,.cuigengji .planning-card.connect-source {outline:1px solid var(--cg-accent);background:var(--cg-wash);}
91
+ .cuigengji .planning-state {font-size:10px;margin-top:6px;}
92
+ .cuigengji .planning-group-frame {border-color:color-mix(in srgb,var(--cg-accent) 18%,transparent);background:color-mix(in srgb,var(--cg-accent) 2%,transparent);}
93
+ .cuigengji .relation-label {position:absolute;width:180px;z-index:2;padding:6px 10px;border-radius:7px;background:var(--cg-paper);font-size:11px;text-align:center;}
94
+ .cuigengji .relation-label .edge-label-content {border:0;padding:0;min-height:0;display:block;width:100%;font-size:11px;background:none;}
95
+ .cuigengji .relation-label strong {display:block;font-size:11px;font-weight:500;color:var(--cg-accent);}
96
+ .cuigengji .relation-label span {display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.6;color:var(--cg-muted);}
97
+ .cuigengji .relation-label.expanded {z-index:4;box-shadow:0 5px 20px #0002;}
98
+ .cuigengji .relation-label.expanded span {-webkit-line-clamp:unset;max-height:240px;overflow:auto;white-space:pre-wrap;}
99
+ .cuigengji .relation-label .expand-edge {border:0;min-height:20px;padding:0;font-size:10px;color:var(--cg-accent);}
100
+ .cuigengji .creation {display:flex;flex-direction:column;flex:1;min-height:0;animation:cg-arrive 150ms ease-out;}
101
+ .cuigengji .creation-bar {display:flex;align-items:center;gap:12px;padding:14px 24px;border-bottom:1px solid var(--cg-line);flex:none;}
102
+ .cuigengji .creation-bar>button:first-child {border:0;background:none;}
103
+ .cuigengji .creation-scroll {flex:1;min-height:0;overflow:auto;padding:32px 32px 60px;}
104
+ .cuigengji .creation-document {max-width:680px;margin:auto;}
105
+ .cuigengji .creation-context {border-left:2px solid var(--cg-accent);padding-left:12px;color:var(--cg-accent);font-size:12px;}
106
+ .cuigengji .creation-settings {display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-bottom:12px;border-bottom:1px solid var(--cg-line);}
107
+ .cuigengji .creation-settings label {display:flex;align-items:center;gap:8px;font-size:12px;min-width:0;}
108
+ .cuigengji .creation-settings select {max-width:240px;border:0;}
109
+ .cuigengji .creation-settings button {border:0;color:var(--cg-accent);background:none;font-size:12px;}
110
+ .cuigengji .chapter-directory {background:color-mix(in srgb,var(--cg-ink) 2%,var(--cg-paper));}
111
+ .cuigengji .manuscript {line-height:var(--prose-leading,1.95);}
112
+ .cuigengji .directory-foot {border-top:1px solid var(--cg-line);font-size:11px;color:var(--cg-muted);padding:16px 8px;margin-top:18px;}
113
+ .cuigengji .utility-modal {color:var(--cg-ink);width:min(600px,calc(100vw - 32px));max-height:calc(100dvh - 40px);padding:0;border:1px solid var(--cg-line);border-radius:12px;background:var(--cg-paper);box-shadow:0 18px 60px #0003;overflow:auto;overscroll-behavior:contain;container:cg-utility / inline-size;-webkit-app-region:no-drag;}
114
+ .cuigengji .utility-modal::backdrop {background:#17203355;backdrop-filter:blur(2px);}
115
+ .cuigengji .utility-head {position:sticky;top:0;background:var(--cg-paper);display:flex;align-items:center;justify-content:space-between;padding:18px 28px 14px;border-bottom:1px solid var(--cg-line);z-index:1;}
116
+ .cuigengji .utility-head h2 {margin:0;font-size:22px;}
117
+ .cuigengji .utility-head button {border:0;background:none;font-size:24px;width:40px;height:40px;padding:0;flex:none;-webkit-app-region:no-drag;}
118
+ .cuigengji .utility-content {padding:4px 28px 24px;}
119
+ .cuigengji .preference-section {padding:16px 0;border-bottom:1px solid var(--cg-line);}
120
+ .cuigengji .preference-section h3 {font-size:13px;margin:0 0 12px;}
121
+ .cuigengji .preference-section .split {grid-template-columns:1fr 1fr;}
122
+ .cuigengji .reading-preview {padding:18px 20px;border-radius:8px;background:var(--cg-wash);}
123
+ .cuigengji .reading-preview small {color:var(--cg-muted);font-size:10px;}
124
+ .cuigengji .reading-preview p {margin:10px 0 0;}
125
+ .cuigengji .preference-row {display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:44px;font-size:13px;}
126
+ .cuigengji .preference-row select {width:154px;max-width:52%;}
127
+ .cuigengji .utility-footer {display:flex;align-items:center;gap:16px;padding-top:20px;flex-wrap:wrap;}
128
+ .cuigengji .utility-footer button {border:0;background:none;color:var(--cg-accent);}
129
+ .cuigengji .utility-footer small {color:var(--cg-muted);font-size:11px;}
130
+ .cuigengji .about-overview {display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:18px 24px;align-items:center;padding:26px 0;}
131
+ .cuigengji .about-identity {display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
132
+ .cuigengji .about-identity h2 {font-size:28px;margin:0;}
133
+ .cuigengji .about-version {font-size:11px;color:var(--cg-muted);border:1px solid var(--cg-line);border-radius:6px;padding:2px 6px;white-space:nowrap;}
134
+ .cuigengji .about-tagline {font-size:17px;line-height:1.7;margin:12px 0 0;max-width:17em;}
135
+ .cuigengji .about-sticker {display:block;width:100%;height:auto;aspect-ratio:1;object-fit:contain;border-radius:14px;background:#fff;}
136
+ .cuigengji .about-description {grid-column:1 / -1;font-size:13px;color:var(--cg-muted);line-height:1.9;margin:0;}
137
+ .cuigengji .about-contacts {border-top:1px solid var(--cg-line);}
138
+ .cuigengji .about-contact {display:grid;grid-template-columns:64px minmax(0,1fr) 20px;gap:12px;align-items:center;min-height:58px;width:100%;padding:14px 4px;border:0;border-bottom:1px solid var(--cg-line);border-radius:0;background:none;color:var(--cg-ink);font:inherit;text-align:left;text-decoration:none;transition:background 120ms;}
139
+ .cuigengji .about-contact:hover {background:var(--cg-wash);}
140
+ .cuigengji .about-contact:focus-visible {outline:2px solid var(--cg-accent);outline-offset:2px;border-radius:4px;}
141
+ .cuigengji .about-contact-label {font-size:12px;color:var(--cg-muted);}
142
+ .cuigengji .about-contact strong {font-size:14px;font-weight:500;overflow-wrap:anywhere;}
143
+ .cuigengji .about-contact-mark {font-size:17px;color:var(--cg-accent);text-align:center;}
144
+ .cuigengji .about-copy-status {min-height:18px;margin:8px 4px 0;font-size:11px;color:var(--cg-accent);}
145
+ .cuigengji .about-welcome {padding:8px 0 0;}
146
+ .cuigengji .about-welcome p {font-size:12px;color:var(--cg-muted);line-height:1.9;margin:0;}
147
+ .cuigengji .about-welcome p:first-child {color:var(--cg-ink);margin-bottom:4px;}
148
+ .cuigengji .chapter-settings-panel {width:min(230px,76vw);}
149
+ .cuigengji .chapter-settings-panel label {margin:4px 4px 10px;font-size:12px;color:var(--cg-muted);}
150
+ .cuigengji .chapter-settings-panel select {width:100%;color:var(--cg-ink);}
151
+ .cuigengji .chapter-settings-panel button {border:0;background:none;}
152
+ @container cg-utility (max-width:420px){.cuigengji .about-overview {grid-template-columns:minmax(0,1fr) 88px;gap:18px 12px;padding:22px 0;}.cuigengji .about-identity {gap:8px;}.cuigengji .about-identity h2 {font-size:26px;}.cuigengji .about-tagline {font-size:15px;margin-top:10px;}.cuigengji .about-contact {grid-template-columns:52px minmax(0,1fr) 16px;gap:10px;}.cuigengji .about-contact strong {font-size:13px;}}
153
+ @container(min-width:760px){.cuigengji .workbench-header {display:grid;grid-template-columns:minmax(130px,1fr) auto auto;gap:20px;padding:8px 24px;}.cuigengji .identity,.cuigengji .header-row {display:contents;}.cuigengji .book-picker {grid-column:1;grid-row:1;width:100%;}.cuigengji .workbench-header nav {grid-column:2;grid-row:1;width:auto;gap:20px;order:0;}.cuigengji .workbench-header nav button {min-width:64px;}.cuigengji .header-row>.menu {grid-column:3;grid-row:1;justify-self:start;}.cuigengji .app-actions {grid-column:3;grid-row:1;padding-left:32px;}.cuigengji .workbench-header .header-row>.menu {z-index:3;}}
154
+ @container(max-width:599px){.cuigengji .workbench-header {padding:6px 16px;gap:6px;}.cuigengji .module-heading {padding:12px 16px;}.cuigengji .module-toolbar {gap:6px;}.cuigengji .module-toolbar h2 {font-size:15px;}.cuigengji .module-search {order:5;flex-basis:100%;max-width:none;margin:0;}.cuigengji .module-toolbar>.primary,.cuigengji .module-toolbar>.menu:has(.primary) {margin-left:auto;}.cuigengji .filter-prefix {display:none;}.cuigengji .filter-strip {gap:6px;}.cuigengji .filter-control select {max-width:110px;font-size:11px;}.cuigengji .group-new {font-size:11px;padding:4px;}.cuigengji .scope-count {display:none;}.cuigengji .detail-scroll {padding:20px 24px 40px;}.cuigengji .detail-bar {padding:8px 16px;}.cuigengji .creation-scroll {padding:24px;}.cuigengji .creation-bar {padding:12px 16px;}.cuigengji .canvas-tools {padding:6px 16px;}.cuigengji .creation-settings select {max-width:170px;}.cuigengji .utility-head {padding:16px 20px 12px;}.cuigengji .utility-content {padding:4px 20px 20px;}}
155
155
  /* A modal reaches the desktop title bar; its controls must override Electron drag regions. */
156
156
  .cuigengji .directory-drawer {inset:0 auto 0 0;margin:0;width:min(330px,calc(100vw - 36px));max-width:none;height:100dvh;max-height:100dvh;padding:0;border:0;border-right:1px solid var(--cg-line);background:var(--cg-paper);color:var(--cg-ink);overflow:hidden;-webkit-app-region:no-drag;}
157
- .cuigengji .directory-drawer[open] {display:flex;flex-direction:column;}
158
- .cuigengji .drawer-header {display:flex;justify-content:flex-end;flex:none;padding:4px 8px;background:var(--cg-paper);}
157
+ .cuigengji .directory-drawer[open] {display:flex;flex-direction:column;}
158
+ .cuigengji .drawer-header {display:flex;justify-content:flex-end;flex:none;padding:4px 8px;background:var(--cg-paper);}
159
159
  .cuigengji .directory-drawer::backdrop {background:#17203355;}
160
160
  .cuigengji .chapter-item {position:relative;gap:8px;user-select:none;touch-action:pan-y;}
161
161
  .cuigengji .chapter-item>.chapter-grip {flex:none;width:12px;color:var(--cg-muted);font-size:17px;line-height:1;opacity:.3;cursor:grab;touch-action:none;transition:opacity 120ms;}
@@ -169,39 +169,39 @@ export const visualStyles = `
169
169
  .cuigengji .chapter-drag-preview>span {color:var(--cg-accent);font-size:17px;}
170
170
  .cuigengji .directory-sort-note {display:block;margin-top:4px;color:var(--cg-accent);}
171
171
  .cuigengji .directory-sort-error {font-size:12px;line-height:1.7;color:var(--cg-muted);}
172
- /* A clipped live region still affects scrollable overflow. Anchor it inside the directory. */
173
- .cuigengji .chapter-sort-live {position:absolute;top:0;left:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
174
- .cuigengji .directory-drawer .chapter-directory {display:block;width:100%;min-height:0;flex:1;overflow:auto;border:0;background:transparent;padding-top:8px;}
175
- .cuigengji .drawer-close span {pointer-events:none;}
172
+ /* A clipped live region still affects scrollable overflow. Anchor it inside the directory. */
173
+ .cuigengji .chapter-sort-live {position:absolute;top:0;left:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
174
+ .cuigengji .directory-drawer .chapter-directory {display:block;width:100%;min-height:0;flex:1;overflow:auto;border:0;background:transparent;padding-top:8px;}
175
+ .cuigengji .drawer-close span {pointer-events:none;}
176
176
  .cuigengji .drawer-close {display:grid;place-items:center;flex:none;width:44px;height:44px;min-height:44px;padding:0;border:0;background:none;font-size:24px;line-height:1;cursor:pointer;touch-action:manipulation;-webkit-app-region:no-drag;}
177
177
  .cuigengji .drawer-close:hover {background:var(--cg-wash);}
178
- @container(max-width:759px){.cuigengji .show-directory .chapter-main {display:flex;}.cuigengji .directory-drawer .chapter-directory .directory-heading>.icon-button {display:none;}}
179
- .cuigengji .chapter-item {padding:10px 8px;border-radius:8px;}
180
- .cuigengji .chapter-item .chapter-open {display:flex;flex-direction:column;align-items:flex-start;gap:3px;flex:1;min-width:0;border:0;background:none;padding:0;text-align:left;font-size:13px;line-height:1.55;}
181
- .cuigengji .chapter-open>span {overflow-wrap:anywhere;}
182
- .cuigengji .chapter-open>small {font-size:11px;color:var(--cg-muted);}
183
- .cuigengji .chapter-item .chapter-row-action {flex:none;display:grid;place-items:center;width:30px;height:32px;min-height:32px;padding:5px;border:0;background:none;color:var(--cg-muted);opacity:0;transition:opacity 120ms;}
184
- .cuigengji .chapter-row-action svg {width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
185
- .cuigengji .chapter-item:hover .chapter-row-action,.cuigengji .chapter-item:focus-within .chapter-row-action,.cuigengji .chapter-item.selected .chapter-row-action,.cuigengji .chapter-item.is-deleted .chapter-row-action {opacity:1;}
186
- .cuigengji .chapter-row-action:hover {color:var(--cg-accent);background:var(--cg-wash);}
187
- .cuigengji .directory-foot {display:flex;align-items:center;justify-content:space-between;gap:8px;}
188
- .cuigengji .recycle-entry {display:flex;align-items:center;gap:6px;padding:4px 6px;min-height:30px;border:0;background:none;color:var(--cg-muted);font-size:12px;}
189
- .cuigengji .recycle-entry[aria-pressed=true] {color:var(--cg-accent);background:var(--cg-wash);}
190
- .cuigengji .directory-undo {display:flex;align-items:center;gap:6px;padding:8px;border-radius:8px;background:var(--cg-wash);font-size:12px;}
191
- .cuigengji .directory-undo>span {flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
192
- .cuigengji .directory-undo>button {border:0;background:none;color:var(--cg-accent);padding:4px 6px;min-height:28px;font-size:12px;}
193
- .cuigengji .inline-title h2 {margin:0;}
194
- .cuigengji .inline-title-display {display:flex;align-items:center;gap:10px;width:100%;border:0;background:none;text-align:left;color:inherit;padding:4px 0;min-height:0;font:inherit;line-height:inherit;}
195
- .cuigengji .inline-title-display>span {min-width:0;overflow-wrap:anywhere;}
196
- .cuigengji .inline-title-display:hover {background:none;}
197
- .cuigengji .inline-title-display svg {flex:none;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.4;opacity:0;}
198
- .cuigengji .inline-title-display:hover svg,.cuigengji .inline-title-display:focus-visible svg {opacity:.5;}
199
- .cuigengji .inline-title>input {width:100%;padding:4px 0;border:0;border-bottom:1px solid var(--cg-accent);border-radius:0;background:none;font-family:Georgia,'Noto Serif SC','SimSun',serif;font-size:26px;font-weight:600;line-height:1.5;}
200
- .cuigengji .inline-title-error {font-size:12px;color:var(--cg-muted);margin-top:4px;}
201
- .cuigengji .inline-title-error button {font-size:12px;padding:3px 6px;}
202
- @media(pointer:coarse){.cuigengji .chapter-item .chapter-row-action {opacity:1;min-width:40px;min-height:40px;}}
203
- @container(max-width:759px){.cuigengji .directory-drawer .directory-heading>.icon-button[aria-label="返回章节目录"] {display:block;}}
204
- @keyframes cg-arrive {from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
205
- .cuigengji[data-motion=reduce] *,.cuigengji[data-motion=reduce] *::before,.cuigengji[data-motion=reduce] *::after {animation:none!important;transition:none!important;scroll-behavior:auto!important;}
206
- @media(prefers-reduced-motion:reduce){.cuigengji *,.cuigengji *::before,.cuigengji *::after {animation:none!important;transition:none!important;scroll-behavior:auto!important;}}
207
- `;
178
+ @container(max-width:759px){.cuigengji .show-directory .chapter-main {display:flex;}.cuigengji .directory-drawer .chapter-directory .directory-heading>.icon-button {display:none;}}
179
+ .cuigengji .chapter-item {padding:10px 8px;border-radius:8px;}
180
+ .cuigengji .chapter-item .chapter-open {display:flex;flex-direction:column;align-items:flex-start;gap:3px;flex:1;min-width:0;border:0;background:none;padding:0;text-align:left;font-size:13px;line-height:1.55;}
181
+ .cuigengji .chapter-open>span {overflow-wrap:anywhere;}
182
+ .cuigengji .chapter-open>small {font-size:11px;color:var(--cg-muted);}
183
+ .cuigengji .chapter-item .chapter-row-action {flex:none;display:grid;place-items:center;width:30px;height:32px;min-height:32px;padding:5px;border:0;background:none;color:var(--cg-muted);opacity:0;transition:opacity 120ms;}
184
+ .cuigengji .chapter-row-action svg {width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
185
+ .cuigengji .chapter-item:hover .chapter-row-action,.cuigengji .chapter-item:focus-within .chapter-row-action,.cuigengji .chapter-item.selected .chapter-row-action,.cuigengji .chapter-item.is-deleted .chapter-row-action {opacity:1;}
186
+ .cuigengji .chapter-row-action:hover {color:var(--cg-accent);background:var(--cg-wash);}
187
+ .cuigengji .directory-foot {display:flex;align-items:center;justify-content:space-between;gap:8px;}
188
+ .cuigengji .recycle-entry {display:flex;align-items:center;gap:6px;padding:4px 6px;min-height:30px;border:0;background:none;color:var(--cg-muted);font-size:12px;}
189
+ .cuigengji .recycle-entry[aria-pressed=true] {color:var(--cg-accent);background:var(--cg-wash);}
190
+ .cuigengji .directory-undo {display:flex;align-items:center;gap:6px;padding:8px;border-radius:8px;background:var(--cg-wash);font-size:12px;}
191
+ .cuigengji .directory-undo>span {flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
192
+ .cuigengji .directory-undo>button {border:0;background:none;color:var(--cg-accent);padding:4px 6px;min-height:28px;font-size:12px;}
193
+ .cuigengji .inline-title h2 {margin:0;}
194
+ .cuigengji .inline-title-display {display:flex;align-items:center;gap:10px;width:100%;border:0;background:none;text-align:left;color:inherit;padding:4px 0;min-height:0;font:inherit;line-height:inherit;}
195
+ .cuigengji .inline-title-display>span {min-width:0;overflow-wrap:anywhere;}
196
+ .cuigengji .inline-title-display:hover {background:none;}
197
+ .cuigengji .inline-title-display svg {flex:none;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.4;opacity:0;}
198
+ .cuigengji .inline-title-display:hover svg,.cuigengji .inline-title-display:focus-visible svg {opacity:.5;}
199
+ .cuigengji .inline-title>input {width:100%;padding:4px 0;border:0;border-bottom:1px solid var(--cg-accent);border-radius:0;background:none;font-family:Georgia,'Noto Serif SC','SimSun',serif;font-size:26px;font-weight:600;line-height:1.5;}
200
+ .cuigengji .inline-title-error {font-size:12px;color:var(--cg-muted);margin-top:4px;}
201
+ .cuigengji .inline-title-error button {font-size:12px;padding:3px 6px;}
202
+ @media(pointer:coarse){.cuigengji .chapter-item .chapter-row-action {opacity:1;min-width:40px;min-height:40px;}}
203
+ @container(max-width:759px){.cuigengji .directory-drawer .directory-heading>.icon-button[aria-label="返回章节目录"] {display:block;}}
204
+ @keyframes cg-arrive {from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
205
+ .cuigengji[data-motion=reduce] *,.cuigengji[data-motion=reduce] *::before,.cuigengji[data-motion=reduce] *::after {animation:none!important;transition:none!important;scroll-behavior:auto!important;}
206
+ @media(prefers-reduced-motion:reduce){.cuigengji *,.cuigengji *::before,.cuigengji *::after {animation:none!important;transition:none!important;scroll-behavior:auto!important;}}
207
+ `;
@@ -1,22 +1,22 @@
1
- // Shared capability contract. Actor policy remains in the host and Store.
2
- export const isReadAction = action => /\.(get|read|list|groups|pages|decorations|history|search|changes|handoff)$/.test(action);
3
- export const changesProse = (action, args) => ['chapter.restore', 'chapter.delete'].includes(action)
4
- || (action === 'volume.delete' && args.chapterPolicy === 'delete')
5
- || (['chapter.create', 'chapter.update'].includes(action)
6
- && ['content', 'append', 'patch'].some(key => args[key] !== undefined));
7
- export const TOOL_ACTIONS = Object.freeze({
8
- cuigengji_project: Object.freeze(['novel.get','novel.handoff','volume.list','volume.create','volume.update','volume.delete','chapter.list','chapter.search','chapter.create','chapter.get','chapter.update','chapter.delete','chapter.history','chapter.restore']),
1
+ // Shared capability contract. Actor policy remains in the host and Store.
2
+ export const isReadAction = action => /\.(get|read|list|groups|pages|decorations|history|search|changes|handoff)$/.test(action);
3
+ export const changesProse = (action, args) => ['chapter.restore', 'chapter.delete'].includes(action)
4
+ || (action === 'volume.delete' && args.chapterPolicy === 'delete')
5
+ || (['chapter.create', 'chapter.update'].includes(action)
6
+ && ['content', 'append', 'patch'].some(key => args[key] !== undefined));
7
+ export const TOOL_ACTIONS = Object.freeze({
8
+ cuigengji_project: Object.freeze(['novel.get','novel.handoff','volume.list','volume.create','volume.update','volume.delete','chapter.list','chapter.search','chapter.create','chapter.get','chapter.update','chapter.delete','chapter.history','chapter.restore']),
9
9
  cuigengji_memory: Object.freeze(['graph.list','graph.get','graph.groups','graph.group.create','graph.group.update','graph.group.delete','graph.move','graph.layout','graph.continue','graph.duplicate','graph.remove','graph.create','graph.update','graph.delete','edge.list','edge.get','edge.create','edge.update','edge.delete','edge.disconnect']),
10
- cuigengji_plan: Object.freeze(['planning.pages','planning.page.create','planning.page.update','planning.page.delete','planning.decorations','planning.list','planning.search','planning.get','planning.continue','planning.groups','planning.group.create','planning.group.update','planning.group.delete','planning.changes','planning.history','planning.apply','planning.revert']),
11
- cuigengji_context: Object.freeze(['context.get','binding.get','preset.read']),
12
- });
13
- export const MEMORY_ACTIONS = Object.freeze([...TOOL_ACTIONS.cuigengji_memory, 'context.get']);
14
- export const HUMAN_ACTIONS = Object.freeze([...new Set([
15
- ...Object.values(TOOL_ACTIONS).flat(), 'novel.list','novel.create','novel.import',
16
- 'novel.export','novel.update','novel.archive','novel.restore','novel.purge','binding.set','settings.get','legacy.preview','tavern.preview','tavern.import',
10
+ cuigengji_plan: Object.freeze(['planning.pages','planning.page.create','planning.page.update','planning.page.delete','planning.decorations','planning.list','planning.search','planning.get','planning.continue','planning.groups','planning.group.create','planning.group.update','planning.group.delete','planning.changes','planning.history','planning.apply','planning.revert']),
11
+ cuigengji_context: Object.freeze(['context.get','binding.get','preset.read']),
12
+ });
13
+ export const MEMORY_ACTIONS = Object.freeze([...TOOL_ACTIONS.cuigengji_memory, 'context.get']);
14
+ export const HUMAN_ACTIONS = Object.freeze([...new Set([
15
+ ...Object.values(TOOL_ACTIONS).flat(), 'novel.list','novel.create','novel.import',
16
+ 'novel.export','novel.update','novel.archive','novel.restore','novel.purge','binding.set','settings.get','legacy.preview','tavern.preview','tavern.import',
17
17
  'preset.get','preset.preview','preset.set',
18
18
  'chapter.move',
19
- 'workspace.status','workspace.export','workspace.preview','workspace.import',
20
- 'transfer.catalog','transfer.inspect','transfer.preview','transfer.import','transfer.exportPreview','transfer.export',
21
- 'maintenance.status','maintenance.verify',
22
- ])]);
19
+ 'workspace.status','workspace.export','workspace.preview','workspace.import',
20
+ 'transfer.catalog','transfer.inspect','transfer.preview','transfer.import','transfer.exportPreview','transfer.export',
21
+ 'maintenance.status','maintenance.verify',
22
+ ])]);
@@ -1,36 +1,36 @@
1
- export interface Point { x: number; y: number }
2
- export interface PlanningNode {
3
- id: string; revision: number; title: string; summary: string; content: string;
4
- scope: 'long' | 'phase' | 'near' | 'unspecified';
5
- status: 'idea' | 'selected' | 'written' | 'dropped';
6
- parentId: string | null; groupId?: string | null; pageId?: string | null; position?: Point | null;
7
- threads: string[]; chapterRefs: { chapterId: string; revision: number }[]; memoryRefs: string[];
8
- deleted: boolean; updatedAt: string; lastSequence?: number;
9
- actor?: { kind: string; sessionId?: string | null };
10
- }
11
- export interface PlanningEdge { id: string; revision: number; from: string; to: string; type: 'next' | 'requires' | 'alternative'; label: string; deleted: boolean }
12
- export interface PlanningGroup { id: string; revision: number; name: string; summary: string; deleted?: boolean }
13
- export interface PlanningPage extends PlanningGroup {}
14
- export interface Decoration {
15
- id:string; revision:number; pageId:string|null; kind:'note'|'frame'; title:string; content:string;
16
- position:Point; width:number; height:number; color:'neutral'|'sand'|'sage'|'sky'|'rose';
1
+ export interface Point { x: number; y: number }
2
+ export interface PlanningNode {
3
+ id: string; revision: number; title: string; summary: string; content: string;
4
+ scope: 'long' | 'phase' | 'near' | 'unspecified';
5
+ status: 'idea' | 'selected' | 'written' | 'dropped';
6
+ parentId: string | null; groupId?: string | null; pageId?: string | null; position?: Point | null;
7
+ threads: string[]; chapterRefs: { chapterId: string; revision: number }[]; memoryRefs: string[];
8
+ deleted: boolean; updatedAt: string; lastSequence?: number;
9
+ actor?: { kind: string; sessionId?: string | null };
10
+ }
11
+ export interface PlanningEdge { id: string; revision: number; from: string; to: string; type: 'next' | 'requires' | 'alternative'; label: string; deleted: boolean }
12
+ export interface PlanningGroup { id: string; revision: number; name: string; summary: string; deleted?: boolean }
13
+ export interface PlanningPage extends PlanningGroup {}
14
+ export interface Decoration {
15
+ id:string; revision:number; pageId:string|null; kind:'note'|'frame'; title:string; content:string;
16
+ position:Point; width:number; height:number; color:'neutral'|'sand'|'sage'|'sky'|'rose';
17
17
  fontSize:number; fontFamily:'sans'|'serif'; moveContents?:boolean; deleted:boolean;
18
- }
19
- export type NodeIndex = Omit<PlanningNode, 'content'>;
20
- export type PlanningEntity = PlanningNode | PlanningEdge | PlanningGroup | PlanningPage | Decoration;
21
- export type Collection = 'nodes' | 'edges' | 'groups' | 'pages' | 'decorations';
22
- export interface Change { collection: Collection; id: string; before: PlanningEntity | null; after: PlanningEntity }
23
- export interface Transaction { id: string; sequence: number; lastSequence: number; updatedAt: string; actor: {kind: string; sessionId: string | null}; reason: string; changes: Change[] }
24
- export interface Board {
25
- formatVersion: number; nodes: Record<string, PlanningNode>; edges: Record<string, PlanningEdge>;
26
- groups: Record<string, PlanningGroup>; sequence: number; transactions: Transaction[];
27
- pages:Record<string,PlanningPage>; decorations:Record<string,Decoration>;
28
- legacy?: LegacyPlan;
29
- }
30
- export interface LegacyPlan { id: string; revision: number; content: string; updatedAt?: string; approved: boolean }
18
+ }
19
+ export type NodeIndex = Omit<PlanningNode, 'content'>;
20
+ export type PlanningEntity = PlanningNode | PlanningEdge | PlanningGroup | PlanningPage | Decoration;
21
+ export type Collection = 'nodes' | 'edges' | 'groups' | 'pages' | 'decorations';
22
+ export interface Change { collection: Collection; id: string; before: PlanningEntity | null; after: PlanningEntity }
23
+ export interface Transaction { id: string; sequence: number; lastSequence: number; updatedAt: string; actor: {kind: string; sessionId: string | null}; reason: string; changes: Change[] }
24
+ export interface Board {
25
+ formatVersion: number; nodes: Record<string, PlanningNode>; edges: Record<string, PlanningEdge>;
26
+ groups: Record<string, PlanningGroup>; sequence: number; transactions: Transaction[];
27
+ pages:Record<string,PlanningPage>; decorations:Record<string,Decoration>;
28
+ legacy?: LegacyPlan;
29
+ }
30
+ export interface LegacyPlan { id: string; revision: number; content: string; updatedAt?: string; approved: boolean }
31
31
  export interface PlanningNovel {
32
- planning?: Board; plan?: LegacyPlan | null;
33
- chapters: Record<string, {versions: {revision: number}[]}>; nodes: Record<string, unknown>;
32
+ planning?: Board; plan?: LegacyPlan | null;
33
+ chapters: Record<string, {versions: {revision: number}[]}>; nodes: Record<string, unknown>;
34
34
  }
35
35
  export const PLANNING_OPERATIONS = [
36
36
  'page.create','page.update','page.delete',
@@ -40,25 +40,25 @@ export const PLANNING_OPERATIONS = [
40
40
  'group.create','group.update','group.delete',
41
41
  ] as const;
42
42
  export type Operation =
43
- | {op:'page.create';ref?:string;value:Pick<PlanningPage,'name'> & Partial<PlanningPage>}
44
- | {op:'page.update';id:string;expectedRevision:number;value:Partial<PlanningPage>}
45
- | {op:'page.delete';id:string;expectedRevision:number;confirm?:boolean}
46
- | {op:'decoration.create';ref?:string;value:Partial<Decoration>}
47
- | {op:'decoration.update';id:string;expectedRevision:number;value:Partial<Decoration>}
48
- | {op:'decoration.delete';id:string;expectedRevision:number;confirm?:boolean}
49
- | {op:'node.create';ref?:string;value?:Partial<PlanningNode>}
50
- | {op:'node.update';id:string;expectedRevision:number;value:Partial<PlanningNode>}
51
- | {op:'node.delete';id:string;expectedRevision:number;confirm?:boolean;childPolicy?:'detach'|'subtree'}
52
- | {op:'edge.create';value:Pick<PlanningEdge,'from'|'to'> & Partial<PlanningEdge>}
53
- | {op:'edge.update';id:string;expectedRevision:number;value:Partial<PlanningEdge>}
54
- | {op:'edge.delete';id:string;expectedRevision:number;confirm?:boolean}
55
- | {op:'group.create';ref?:string;value:Pick<PlanningGroup,'name'> & Partial<PlanningGroup>}
56
- | {op:'group.update';id:string;expectedRevision:number;value:Partial<PlanningGroup>}
57
- | {op:'group.delete';id:string;expectedRevision:number;confirm?:boolean};
58
- export interface PlanningArgs {
59
- value?: Partial<PlanningNode>;
60
- requestId?:string; expectedSequence?:number; transactionId?:string; operations?:Operation[]; reason?:string;
61
- nodeId?:string;groupId?:string|null;pageId?:string|null;name?:string;summary?:string;expectedRevision?:number;confirm?:boolean;
62
- query?:string;includeDeleted?:boolean;parentId?:string|null;status?:string;thread?:string;
43
+ | {op:'page.create';ref?:string;value:Pick<PlanningPage,'name'> & Partial<PlanningPage>}
44
+ | {op:'page.update';id:string;expectedRevision:number;value:Partial<PlanningPage>}
45
+ | {op:'page.delete';id:string;expectedRevision:number;confirm?:boolean}
46
+ | {op:'decoration.create';ref?:string;value:Partial<Decoration>}
47
+ | {op:'decoration.update';id:string;expectedRevision:number;value:Partial<Decoration>}
48
+ | {op:'decoration.delete';id:string;expectedRevision:number;confirm?:boolean}
49
+ | {op:'node.create';ref?:string;value?:Partial<PlanningNode>}
50
+ | {op:'node.update';id:string;expectedRevision:number;value:Partial<PlanningNode>}
51
+ | {op:'node.delete';id:string;expectedRevision:number;confirm?:boolean;childPolicy?:'detach'|'subtree'}
52
+ | {op:'edge.create';value:Pick<PlanningEdge,'from'|'to'> & Partial<PlanningEdge>}
53
+ | {op:'edge.update';id:string;expectedRevision:number;value:Partial<PlanningEdge>}
54
+ | {op:'edge.delete';id:string;expectedRevision:number;confirm?:boolean}
55
+ | {op:'group.create';ref?:string;value:Pick<PlanningGroup,'name'> & Partial<PlanningGroup>}
56
+ | {op:'group.update';id:string;expectedRevision:number;value:Partial<PlanningGroup>}
57
+ | {op:'group.delete';id:string;expectedRevision:number;confirm?:boolean};
58
+ export interface PlanningArgs {
59
+ value?: Partial<PlanningNode>;
60
+ requestId?:string; expectedSequence?:number; transactionId?:string; operations?:Operation[]; reason?:string;
61
+ nodeId?:string;groupId?:string|null;pageId?:string|null;name?:string;summary?:string;expectedRevision?:number;confirm?:boolean;
62
+ query?:string;includeDeleted?:boolean;parentId?:string|null;status?:string;thread?:string;
63
63
  after?:number;offset?:number;limit?:number;side?:'in'|'out';
64
- }
64
+ }
@@ -1,4 +1,4 @@
1
- /** Display count: Unicode characters including punctuation, excluding whitespace. */
2
- export function countManuscript(content: string): number {
3
- return Array.from(content.replace(/\s/gu, '')).length;
4
- }
1
+ /** Display count: Unicode characters including punctuation, excluding whitespace. */
2
+ export function countManuscript(content: string): number {
3
+ return Array.from(content.replace(/\s/gu, '')).length;
4
+ }