wendang-react 0.0.0-stage → 0.5.5

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 (548) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +381 -0
  3. package/README.md +469 -2
  4. package/dist/bindings/yjs.js +5 -0
  5. package/dist/chunks/AnchoredPanel-D3nte06T.js +68 -0
  6. package/dist/chunks/MindMapCanvas-VWrxTy5Q.js +2070 -0
  7. package/dist/chunks/MindMapViewer-DqKu_Kuz.js +180 -0
  8. package/dist/chunks/SpreadsheetViewer-DN_QQGud.js +157 -0
  9. package/dist/chunks/code-highlight-BmaqTe1m.js +30 -0
  10. package/dist/chunks/code-highlight-engine-BFDzDPzy.js +40 -0
  11. package/dist/chunks/comment-hint-DN7LKJAn.js +296 -0
  12. package/dist/chunks/composition-state-Bl-U1R_2.js +40 -0
  13. package/dist/chunks/extensions-B-CVVQhp.js +4210 -0
  14. package/dist/chunks/fuzzy-match-DYQR-4w2.js +89 -0
  15. package/dist/chunks/hooks-C53Dp0pr.js +35 -0
  16. package/dist/chunks/host-C-V688Rq.js +197 -0
  17. package/dist/chunks/index-Ii536CFG.js +720 -0
  18. package/dist/chunks/katex-WjrodtTU.js +71 -0
  19. package/dist/chunks/mind-map-controller-B6SxK3GZ.js +479 -0
  20. package/dist/chunks/mind-map-delete-CVsxdXfs.js +31 -0
  21. package/dist/chunks/mind-map-input-CEWRz_t6.js +43 -0
  22. package/dist/chunks/mind-topic-text-BBNTbFSe.js +446 -0
  23. package/dist/chunks/nodes-iKqTGr_N.js +291 -0
  24. package/dist/chunks/popover-placement-D3xVYdkt.js +47 -0
  25. package/dist/chunks/worksheet-engine-TJ54m0KC.js +125 -0
  26. package/dist/chunks/worksheet-preview-DsDVWxIM.js +129 -0
  27. package/dist/document/viewer.js +287 -0
  28. package/dist/document.js +3620 -0
  29. package/dist/index.js +8 -0
  30. package/dist/mindmap/viewer.js +6 -0
  31. package/dist/mindmap.js +123 -0
  32. package/dist/shared.js +52 -0
  33. package/dist/spreadsheet/viewer.js +5 -0
  34. package/dist/spreadsheet/xlsx.js +299 -0
  35. package/dist/spreadsheet.js +120 -0
  36. package/dist/styles/callout.css +34 -0
  37. package/dist/styles/code-block.css +58 -0
  38. package/dist/styles/content-style.css +619 -0
  39. package/dist/styles/editor-interaction.css +621 -0
  40. package/dist/styles/file-video.css +12 -0
  41. package/dist/styles/image-preview.css +103 -0
  42. package/dist/styles/mind-map-block.css +14 -0
  43. package/dist/styles/mind-map-canvas.css +80 -0
  44. package/dist/styles/mind-map-comments.css +93 -0
  45. package/dist/styles/mind-map-details.css +7 -0
  46. package/dist/styles/mind-map-preview.css +7 -0
  47. package/dist/styles/mind-map-topic.css +112 -0
  48. package/dist/styles/page-picker.css +47 -0
  49. package/dist/styles/renderer.css +45 -0
  50. package/dist/styles/spreadsheet-editor.css +3 -0
  51. package/dist/styles/tokens.css +153 -0
  52. package/dist/styles/video-dialog.css +41 -0
  53. package/dist/styles/video-embed.css +35 -0
  54. package/dist/styles.css +2614 -0
  55. package/dist/types/bindings/yjs.d.ts +3 -0
  56. package/dist/types/document/viewer.d.ts +3 -0
  57. package/dist/types/document.d.ts +7 -0
  58. package/dist/types/editor/BlockAffordance.d.ts +47 -0
  59. package/dist/types/editor/CalloutView.d.ts +2 -0
  60. package/dist/types/editor/CodeBlockView.d.ts +9 -0
  61. package/dist/types/editor/DocumentColorPanel.d.ts +8 -0
  62. package/dist/types/editor/DocumentEditor.d.ts +71 -0
  63. package/dist/types/editor/ImagePreview.d.ts +10 -0
  64. package/dist/types/editor/LinkPopover.d.ts +21 -0
  65. package/dist/types/editor/PagePicker.d.ts +7 -0
  66. package/dist/types/editor/SelectionToolbar.d.ts +11 -0
  67. package/dist/types/editor/SlashMenu.d.ts +30 -0
  68. package/dist/types/editor/TableControls.d.ts +9 -0
  69. package/dist/types/editor/VideoEmbedDialog.d.ts +6 -0
  70. package/dist/types/editor/document-gestures.d.ts +13 -0
  71. package/dist/types/editor/extensions.d.ts +29 -0
  72. package/dist/types/editor/nodes.d.ts +20 -0
  73. package/dist/types/editor/same-document.d.ts +2 -0
  74. package/dist/types/engine/collab/presence.d.ts +1 -0
  75. package/dist/types/engine/editor/block-commands.d.ts +35 -0
  76. package/dist/types/engine/editor/block-conversion.d.ts +12 -0
  77. package/dist/types/engine/editor/block-drag.d.ts +16 -0
  78. package/dist/types/engine/editor/block-menu-placement.d.ts +16 -0
  79. package/dist/types/engine/editor/callout-commands.d.ts +4 -0
  80. package/dist/types/engine/editor/collab-change-origin.d.ts +2 -0
  81. package/dist/types/engine/editor/delete-block.d.ts +2 -0
  82. package/dist/types/engine/editor/extensions/block-format.d.ts +19 -0
  83. package/dist/types/engine/editor/extensions/block-handle.d.ts +17 -0
  84. package/dist/types/engine/editor/extensions/block-menu-highlight.d.ts +4 -0
  85. package/dist/types/engine/editor/extensions/block-selection.d.ts +117 -0
  86. package/dist/types/engine/editor/extensions/code-highlight.d.ts +2 -0
  87. package/dist/types/engine/editor/extensions/collab-cursor.d.ts +13 -0
  88. package/dist/types/engine/editor/extensions/ime-guard.d.ts +8 -0
  89. package/dist/types/engine/editor/extensions/inline-comments.d.ts +15 -0
  90. package/dist/types/engine/editor/extensions/paste-sanitizer.d.ts +4 -0
  91. package/dist/types/engine/editor/extensions/slash.d.ts +16 -0
  92. package/dist/types/engine/editor/extensions/table-interaction.d.ts +9 -0
  93. package/dist/types/engine/editor/extensions/upload-placeholder.d.ts +48 -0
  94. package/dist/types/engine/editor/image-preview-gesture.d.ts +3 -0
  95. package/dist/types/engine/editor/ime/composition-state.d.ts +9 -0
  96. package/dist/types/engine/editor/insert-block.d.ts +6 -0
  97. package/dist/types/engine/editor/insert-picker-logic.d.ts +13 -0
  98. package/dist/types/engine/editor/link-edit.d.ts +10 -0
  99. package/dist/types/engine/editor/mind-map-controller.d.ts +63 -0
  100. package/dist/types/engine/editor/mind-map-delete.d.ts +7 -0
  101. package/dist/types/engine/editor/mind-map-drag.d.ts +16 -0
  102. package/dist/types/engine/editor/mind-map-input.d.ts +16 -0
  103. package/dist/types/engine/editor/mind-map-selection.d.ts +11 -0
  104. package/dist/types/engine/editor/nodes/columns.d.ts +6 -0
  105. package/dist/types/engine/editor/nodes/file-nodeview.d.ts +4 -0
  106. package/dist/types/engine/editor/nodes/file.d.ts +2 -0
  107. package/dist/types/engine/editor/nodes/image-gallery.d.ts +2 -0
  108. package/dist/types/engine/editor/nodes/image-nodeview.d.ts +4 -0
  109. package/dist/types/engine/editor/nodes/image.d.ts +1 -0
  110. package/dist/types/engine/editor/nodes/inline-style.d.ts +4 -0
  111. package/dist/types/engine/editor/nodes/math-nodeview.d.ts +2 -0
  112. package/dist/types/engine/editor/nodes/math.d.ts +3 -0
  113. package/dist/types/engine/editor/nodes/mention.d.ts +2 -0
  114. package/dist/types/engine/editor/nodes/mind-map-schema.d.ts +6 -0
  115. package/dist/types/engine/editor/nodes/page-link.d.ts +2 -0
  116. package/dist/types/engine/editor/nodes/table-cell.d.ts +4 -0
  117. package/dist/types/engine/editor/nodes/video-embed-schema.d.ts +2 -0
  118. package/dist/types/engine/editor/popover-placement.d.ts +35 -0
  119. package/dist/types/engine/editor/table-clipboard.d.ts +3 -0
  120. package/dist/types/engine/editor/table-commands.d.ts +20 -0
  121. package/dist/types/engine/editor/table-geometry.d.ts +34 -0
  122. package/dist/types/engine/editor/table-menu-placement.d.ts +30 -0
  123. package/dist/types/engine/editor/tracked-target.d.ts +8 -0
  124. package/dist/types/engine/editor/trailing-paragraph.d.ts +2 -0
  125. package/dist/types/engine/host.d.ts +2 -0
  126. package/dist/types/engine/renderer/attachments.d.ts +11 -0
  127. package/dist/types/engine/renderer/katex.d.ts +7 -0
  128. package/dist/types/engine/renderer/lazy-visible.d.ts +11 -0
  129. package/dist/types/engine/shared/callout.d.ts +1 -0
  130. package/dist/types/engine/shared/code-block.d.ts +1 -0
  131. package/dist/types/engine/shared/code-highlight-engine.d.ts +2 -0
  132. package/dist/types/engine/shared/code-highlight.d.ts +8 -0
  133. package/dist/types/engine/shared/comment-hint-position.d.ts +20 -0
  134. package/dist/types/engine/shared/comment-hint.d.ts +2 -0
  135. package/dist/types/engine/shared/document-colors.d.ts +1 -0
  136. package/dist/types/engine/shared/fuzzy-match.d.ts +13 -0
  137. package/dist/types/engine/shared/image-gallery.d.ts +1 -0
  138. package/dist/types/engine/shared/inline-comments.d.ts +1 -0
  139. package/dist/types/engine/shared/mind-map-phase2.d.ts +1 -0
  140. package/dist/types/engine/shared/mind-map.d.ts +1 -0
  141. package/dist/types/engine/shared/mind-topic-text.d.ts +1 -0
  142. package/dist/types/engine/shared/modal-stack.d.ts +6 -0
  143. package/dist/types/engine/shared/page-candidates.d.ts +6 -0
  144. package/dist/types/engine/shared/pinyin.d.ts +6 -0
  145. package/dist/types/engine/shared/preview-items.d.ts +10 -0
  146. package/dist/types/engine/shared/safe-href.d.ts +1 -0
  147. package/dist/types/engine/shared/table-cell-format.d.ts +1 -0
  148. package/dist/types/engine/shared/table-layout.d.ts +1 -0
  149. package/dist/types/engine/shared/video-embed.d.ts +1 -0
  150. package/dist/types/engine/shared/video-feedback.d.ts +1 -0
  151. package/dist/types/engine/shared/workbook.d.ts +1 -0
  152. package/dist/types/engine/worksheets/worksheet-engine.d.ts +16 -0
  153. package/dist/types/engine/worksheets/worksheet-format.d.ts +20 -0
  154. package/dist/types/engine/worksheets/worksheet-preview.d.ts +17 -0
  155. package/dist/types/engine/worksheets/worksheet-xlsx.d.ts +21 -0
  156. package/dist/types/engine/wui/core/dialog.d.ts +5 -0
  157. package/dist/types/engine/wui/core/listbox.d.ts +8 -0
  158. package/dist/types/engine/wui/core/placement.d.ts +40 -0
  159. package/dist/types/hooks.d.ts +7 -0
  160. package/dist/types/host-types.d.ts +58 -0
  161. package/dist/types/host.d.ts +24 -0
  162. package/dist/types/index.d.ts +5 -0
  163. package/dist/types/mindmap/Comments.d.ts +9 -0
  164. package/dist/types/mindmap/Details.d.ts +13 -0
  165. package/dist/types/mindmap/Field.d.ts +10 -0
  166. package/dist/types/mindmap/MindMapCanvas.d.ts +19 -0
  167. package/dist/types/mindmap/MindMapEditor.d.ts +30 -0
  168. package/dist/types/mindmap/MindMapViewer.d.ts +23 -0
  169. package/dist/types/mindmap/TopicLabel.d.ts +4 -0
  170. package/dist/types/mindmap/viewer.d.ts +2 -0
  171. package/dist/types/mindmap.d.ts +4 -0
  172. package/dist/types/renderer/CodeToolbar.d.ts +10 -0
  173. package/dist/types/renderer/DocumentViewer.d.ts +23 -0
  174. package/dist/types/renderer/media.d.ts +33 -0
  175. package/dist/types/shared.d.ts +12 -0
  176. package/dist/types/spreadsheet/SpreadsheetEditor.d.ts +23 -0
  177. package/dist/types/spreadsheet/SpreadsheetViewer.d.ts +13 -0
  178. package/dist/types/spreadsheet/viewer.d.ts +2 -0
  179. package/dist/types/spreadsheet/xlsx.d.ts +2 -0
  180. package/dist/types/spreadsheet.d.ts +3 -0
  181. package/dist/types/wui/AnchoredPanel.d.ts +14 -0
  182. package/dist/types/wui/Dropdown.d.ts +18 -0
  183. package/dist/types/wui/Icon.d.ts +7 -0
  184. package/dist/types/wui/Tooltip.d.ts +5 -0
  185. package/dist/types/wui/index.d.ts +69 -0
  186. package/package.json +122 -3
  187. package/third-party-notices/@fast-csv__format@4.3.5-LICENSE.txt +21 -0
  188. package/third-party-notices/@fast-csv__parse@4.3.6-LICENSE.txt +21 -0
  189. package/third-party-notices/@flatten-js__interval-tree@1.1.3-LICENSE.txt +21 -0
  190. package/third-party-notices/@floating-ui__core@1.8.0-LICENSE.txt +20 -0
  191. package/third-party-notices/@floating-ui__dom@1.8.0-LICENSE.txt +20 -0
  192. package/third-party-notices/@floating-ui__react-dom@2.1.9-LICENSE.txt +20 -0
  193. package/third-party-notices/@floating-ui__utils@0.2.12-LICENSE.txt +20 -0
  194. package/third-party-notices/@grpc__grpc-js@1.14.6-LICENSE.txt +201 -0
  195. package/third-party-notices/@grpc__proto-loader@0.8.1-LICENSE.txt +201 -0
  196. package/third-party-notices/@js-sdsl__ordered-map@4.4.2-LICENSE.txt +21 -0
  197. package/third-party-notices/@protobufjs__aspromise@1.1.2-LICENSE.txt +26 -0
  198. package/third-party-notices/@protobufjs__base64@1.1.2-LICENSE.txt +26 -0
  199. package/third-party-notices/@protobufjs__codegen@2.0.5-LICENSE.txt +26 -0
  200. package/third-party-notices/@protobufjs__eventemitter@1.1.1-LICENSE.txt +26 -0
  201. package/third-party-notices/@protobufjs__fetch@1.1.1-LICENSE.txt +26 -0
  202. package/third-party-notices/@protobufjs__float@1.0.2-LICENSE.txt +26 -0
  203. package/third-party-notices/@protobufjs__path@1.1.2-LICENSE.txt +26 -0
  204. package/third-party-notices/@protobufjs__pool@1.1.0-LICENSE.txt +26 -0
  205. package/third-party-notices/@protobufjs__utf8@1.1.2-LICENSE.txt +26 -0
  206. package/third-party-notices/@radix-ui__primitive@1.2.0-LICENSE.txt +21 -0
  207. package/third-party-notices/@radix-ui__react-arrow@1.1.17-LICENSE.txt +21 -0
  208. package/third-party-notices/@radix-ui__react-collection@1.2.0-LICENSE.txt +21 -0
  209. package/third-party-notices/@radix-ui__react-compose-refs@1.1.5-LICENSE.txt +21 -0
  210. package/third-party-notices/@radix-ui__react-context@1.3.0-LICENSE.txt +21 -0
  211. package/third-party-notices/@radix-ui__react-dialog@1.3.1-LICENSE.txt +21 -0
  212. package/third-party-notices/@radix-ui__react-direction@1.2.0-LICENSE.txt +21 -0
  213. package/third-party-notices/@radix-ui__react-dismissable-layer@1.2.1-LICENSE.txt +21 -0
  214. package/third-party-notices/@radix-ui__react-dropdown-menu@2.2.1-LICENSE.txt +21 -0
  215. package/third-party-notices/@radix-ui__react-focus-guards@1.2.0-LICENSE.txt +21 -0
  216. package/third-party-notices/@radix-ui__react-focus-scope@1.3.1-LICENSE.txt +21 -0
  217. package/third-party-notices/@radix-ui__react-hover-card@1.2.1-LICENSE.txt +21 -0
  218. package/third-party-notices/@radix-ui__react-id@1.1.4-LICENSE.txt +21 -0
  219. package/third-party-notices/@radix-ui__react-menu@2.2.1-LICENSE.txt +21 -0
  220. package/third-party-notices/@radix-ui__react-popover@1.3.1-LICENSE.txt +21 -0
  221. package/third-party-notices/@radix-ui__react-popper@1.4.0-LICENSE.txt +21 -0
  222. package/third-party-notices/@radix-ui__react-portal@1.2.0-LICENSE.txt +21 -0
  223. package/third-party-notices/@radix-ui__react-presence@1.1.11-LICENSE.txt +21 -0
  224. package/third-party-notices/@radix-ui__react-primitive@2.2.0-LICENSE.txt +21 -0
  225. package/third-party-notices/@radix-ui__react-roving-focus@1.2.1-LICENSE.txt +21 -0
  226. package/third-party-notices/@radix-ui__react-separator@1.2.0-LICENSE.txt +21 -0
  227. package/third-party-notices/@radix-ui__react-slot@1.5.0-LICENSE.txt +21 -0
  228. package/third-party-notices/@radix-ui__react-use-callback-ref@1.1.5-LICENSE.txt +21 -0
  229. package/third-party-notices/@radix-ui__react-use-controllable-state@1.3.0-LICENSE.txt +21 -0
  230. package/third-party-notices/@radix-ui__react-use-effect-event@0.0.5-LICENSE.txt +21 -0
  231. package/third-party-notices/@radix-ui__react-use-is-hydrated@0.1.3-LICENSE.txt +21 -0
  232. package/third-party-notices/@radix-ui__react-use-layout-effect@1.1.4-LICENSE.txt +21 -0
  233. package/third-party-notices/@radix-ui__react-use-rect@1.1.4-LICENSE.txt +21 -0
  234. package/third-party-notices/@radix-ui__react-use-size@1.1.5-LICENSE.txt +21 -0
  235. package/third-party-notices/@radix-ui__rect@1.1.3-LICENSE.txt +21 -0
  236. package/third-party-notices/@tiptap__core@3.31.4-LICENSE.md.txt +21 -0
  237. package/third-party-notices/@tiptap__extension-blockquote@3.31.4-LICENSE.md.txt +21 -0
  238. package/third-party-notices/@tiptap__extension-bold@3.31.4-LICENSE.md.txt +21 -0
  239. package/third-party-notices/@tiptap__extension-bullet-list@3.31.4-LICENSE.md.txt +21 -0
  240. package/third-party-notices/@tiptap__extension-code-block@3.31.4-LICENSE.md.txt +21 -0
  241. package/third-party-notices/@tiptap__extension-code@3.31.4-LICENSE.md.txt +21 -0
  242. package/third-party-notices/@tiptap__extension-collaboration@3.31.4-LICENSE.md.txt +21 -0
  243. package/third-party-notices/@tiptap__extension-document@3.31.4-LICENSE.md.txt +21 -0
  244. package/third-party-notices/@tiptap__extension-dropcursor@3.31.4-LICENSE.md.txt +21 -0
  245. package/third-party-notices/@tiptap__extension-gapcursor@3.31.4-LICENSE.md.txt +21 -0
  246. package/third-party-notices/@tiptap__extension-hard-break@3.31.4-LICENSE.md.txt +21 -0
  247. package/third-party-notices/@tiptap__extension-heading@3.31.4-LICENSE.md.txt +21 -0
  248. package/third-party-notices/@tiptap__extension-horizontal-rule@3.31.4-LICENSE.md.txt +21 -0
  249. package/third-party-notices/@tiptap__extension-image@3.31.4-LICENSE.md.txt +21 -0
  250. package/third-party-notices/@tiptap__extension-italic@3.31.4-LICENSE.md.txt +21 -0
  251. package/third-party-notices/@tiptap__extension-link@3.31.4-LICENSE.md.txt +21 -0
  252. package/third-party-notices/@tiptap__extension-list-item@3.31.4-LICENSE.md.txt +21 -0
  253. package/third-party-notices/@tiptap__extension-list-keymap@3.31.4-LICENSE.md.txt +21 -0
  254. package/third-party-notices/@tiptap__extension-list@3.31.4-LICENSE.md.txt +21 -0
  255. package/third-party-notices/@tiptap__extension-ordered-list@3.31.4-LICENSE.md.txt +21 -0
  256. package/third-party-notices/@tiptap__extension-paragraph@3.31.4-LICENSE.md.txt +21 -0
  257. package/third-party-notices/@tiptap__extension-placeholder@3.31.4-LICENSE.md.txt +21 -0
  258. package/third-party-notices/@tiptap__extension-strike@3.31.4-LICENSE.md.txt +21 -0
  259. package/third-party-notices/@tiptap__extension-table-cell@3.31.4-LICENSE.md.txt +21 -0
  260. package/third-party-notices/@tiptap__extension-table-header@3.31.4-LICENSE.md.txt +21 -0
  261. package/third-party-notices/@tiptap__extension-table-row@3.31.4-LICENSE.md.txt +21 -0
  262. package/third-party-notices/@tiptap__extension-table@3.31.4-LICENSE.md.txt +21 -0
  263. package/third-party-notices/@tiptap__extension-task-item@3.31.4-LICENSE.md.txt +21 -0
  264. package/third-party-notices/@tiptap__extension-task-list@3.31.4-LICENSE.md.txt +21 -0
  265. package/third-party-notices/@tiptap__extension-text@3.31.4-LICENSE.md.txt +21 -0
  266. package/third-party-notices/@tiptap__extension-underline@3.31.4-LICENSE.md.txt +21 -0
  267. package/third-party-notices/@tiptap__extensions@3.31.4-LICENSE.md.txt +21 -0
  268. package/third-party-notices/@tiptap__pm@3.31.4-LICENSE.txt +21 -0
  269. package/third-party-notices/@tiptap__starter-kit@3.31.4-LICENSE.md.txt +21 -0
  270. package/third-party-notices/@tiptap__y-tiptap@3.0.7-LICENSE.txt +22 -0
  271. package/third-party-notices/@types__hast@3.0.5-LICENSE.txt +21 -0
  272. package/third-party-notices/@types__node@14.18.63-LICENSE.txt +21 -0
  273. package/third-party-notices/@types__node@26.6.2-LICENSE.txt +21 -0
  274. package/third-party-notices/@types__react-dom@19.3.0-LICENSE.txt +21 -0
  275. package/third-party-notices/@types__react@19.3.0-LICENSE.txt +21 -0
  276. package/third-party-notices/@types__unist@3.0.3-LICENSE.txt +21 -0
  277. package/third-party-notices/@univerjs__core@1.1.0-LICENSE.txt +176 -0
  278. package/third-party-notices/@univerjs__design@1.1.0-LICENSE.txt +176 -0
  279. package/third-party-notices/@univerjs__docs-ui@1.1.0-LICENSE.txt +176 -0
  280. package/third-party-notices/@univerjs__docs@1.1.0-LICENSE.txt +176 -0
  281. package/third-party-notices/@univerjs__drawing@1.1.0-LICENSE.txt +176 -0
  282. package/third-party-notices/@univerjs__engine-formula@1.1.0-LICENSE.txt +176 -0
  283. package/third-party-notices/@univerjs__engine-render@1.1.0-LICENSE.txt +176 -0
  284. package/third-party-notices/@univerjs__icons@1.46.0-LICENSE.txt +21 -0
  285. package/third-party-notices/@univerjs__network@1.1.0-LICENSE.txt +176 -0
  286. package/third-party-notices/@univerjs__preset-sheets-core@1.1.0-LICENSE.txt +176 -0
  287. package/third-party-notices/@univerjs__preset-sheets-filter@1.1.0-LICENSE.txt +176 -0
  288. package/third-party-notices/@univerjs__preset-sheets-sort@1.1.0-LICENSE.txt +176 -0
  289. package/third-party-notices/@univerjs__presets@1.1.0-LICENSE.txt +176 -0
  290. package/third-party-notices/@univerjs__rpc@1.1.0-LICENSE.txt +176 -0
  291. package/third-party-notices/@univerjs__sheets-filter-ui@1.1.0-LICENSE.txt +176 -0
  292. package/third-party-notices/@univerjs__sheets-filter@1.1.0-LICENSE.txt +176 -0
  293. package/third-party-notices/@univerjs__sheets-formula-ui@1.1.0-LICENSE.txt +176 -0
  294. package/third-party-notices/@univerjs__sheets-formula@1.1.0-LICENSE.txt +176 -0
  295. package/third-party-notices/@univerjs__sheets-numfmt-ui@1.1.0-LICENSE.txt +176 -0
  296. package/third-party-notices/@univerjs__sheets-numfmt@1.1.0-LICENSE.txt +176 -0
  297. package/third-party-notices/@univerjs__sheets-sort-ui@1.1.0-LICENSE.txt +176 -0
  298. package/third-party-notices/@univerjs__sheets-sort@1.1.0-LICENSE.txt +176 -0
  299. package/third-party-notices/@univerjs__sheets-ui@1.1.0-LICENSE.txt +176 -0
  300. package/third-party-notices/@univerjs__sheets@1.1.0-LICENSE.txt +176 -0
  301. package/third-party-notices/@univerjs__telemetry@1.1.0-LICENSE.txt +176 -0
  302. package/third-party-notices/@univerjs__themes@1.1.0-LICENSE.txt +176 -0
  303. package/third-party-notices/@univerjs__ui@1.1.0-LICENSE.txt +176 -0
  304. package/third-party-notices/@wendellhu__redi@1.1.3-LICENSE.txt +7 -0
  305. package/third-party-notices/ansi-regex@5.0.1-license.txt +9 -0
  306. package/third-party-notices/ansi-styles@4.3.0-license.txt +9 -0
  307. package/third-party-notices/archiver-utils@2.1.0-LICENSE.txt +22 -0
  308. package/third-party-notices/archiver-utils@3.0.4-LICENSE.txt +22 -0
  309. package/third-party-notices/archiver@5.3.2-LICENSE.txt +22 -0
  310. package/third-party-notices/aria-hidden@1.2.6-LICENSE.txt +21 -0
  311. package/third-party-notices/array-buffer-byte-length@1.0.2-LICENSE.txt +21 -0
  312. package/third-party-notices/arraybuffer.prototype.slice@1.0.4-LICENSE.txt +21 -0
  313. package/third-party-notices/async-function@1.0.0-LICENSE.txt +21 -0
  314. package/third-party-notices/async-lock@1.4.1-LICENSE.txt +22 -0
  315. package/third-party-notices/async@3.2.6-LICENSE.txt +19 -0
  316. package/third-party-notices/available-typed-arrays@1.0.7-LICENSE.txt +21 -0
  317. package/third-party-notices/balanced-match@1.0.2-LICENSE.md.txt +21 -0
  318. package/third-party-notices/base64-js@1.5.1-LICENSE.txt +21 -0
  319. package/third-party-notices/big-integer@1.6.52-LICENSE.txt +24 -0
  320. package/third-party-notices/bl@4.1.0-LICENSE.md.txt +13 -0
  321. package/third-party-notices/bluebird@3.4.7-LICENSE.txt +21 -0
  322. package/third-party-notices/brace-expansion@1.1.21-LICENSE.txt +21 -0
  323. package/third-party-notices/brace-expansion@2.1.7-LICENSE.txt +21 -0
  324. package/third-party-notices/buffer-crc32@0.2.13-LICENSE.txt +19 -0
  325. package/third-party-notices/buffer-indexof-polyfill@1.0.2-LICENSE.txt +22 -0
  326. package/third-party-notices/buffer@5.7.1-LICENSE.txt +21 -0
  327. package/third-party-notices/call-bind-apply-helpers@1.0.2-LICENSE.txt +21 -0
  328. package/third-party-notices/call-bind@1.0.9-LICENSE.txt +21 -0
  329. package/third-party-notices/call-bound@1.0.4-LICENSE.txt +21 -0
  330. package/third-party-notices/class-variance-authority@0.7.1-LICENSE.txt +190 -0
  331. package/third-party-notices/cliui@8.0.1-LICENSE.txt.txt +14 -0
  332. package/third-party-notices/clsx@2.1.1-license.txt +9 -0
  333. package/third-party-notices/cmdk@1.1.1-LICENSE.md.txt +21 -0
  334. package/third-party-notices/collapse-white-space@2.1.0-license.txt +22 -0
  335. package/third-party-notices/color-convert@2.0.1-LICENSE.txt +21 -0
  336. package/third-party-notices/color-name@1.1.4-LICENSE.txt +8 -0
  337. package/third-party-notices/commander@15.0.0-LICENSE.txt +22 -0
  338. package/third-party-notices/compress-commons@4.1.2-LICENSE.txt +22 -0
  339. package/third-party-notices/concat-map@0.0.1-LICENSE.txt +18 -0
  340. package/third-party-notices/core-util-is@1.0.3-LICENSE.txt +19 -0
  341. package/third-party-notices/crc-32@1.2.2-LICENSE.txt +201 -0
  342. package/third-party-notices/crc32-stream@4.0.3-LICENSE.txt +22 -0
  343. package/third-party-notices/csstype@3.2.3-LICENSE.txt +19 -0
  344. package/third-party-notices/data-view-buffer@1.0.2-LICENSE.txt +21 -0
  345. package/third-party-notices/data-view-byte-length@1.0.2-LICENSE.txt +21 -0
  346. package/third-party-notices/data-view-byte-offset@1.0.1-LICENSE.txt +21 -0
  347. package/third-party-notices/dayjs@1.11.23-LICENSE.txt +21 -0
  348. package/third-party-notices/decimal.js@10.6.0-LICENCE.md.txt +23 -0
  349. package/third-party-notices/define-data-property@1.1.4-LICENSE.txt +21 -0
  350. package/third-party-notices/define-properties@1.2.1-LICENSE.txt +21 -0
  351. package/third-party-notices/dequal@2.0.3-license.txt +21 -0
  352. package/third-party-notices/detect-node-es@1.1.0-LICENSE.txt +21 -0
  353. package/third-party-notices/devlop@1.1.0-license.txt +22 -0
  354. package/third-party-notices/dunder-proto@1.0.1-LICENSE.txt +21 -0
  355. package/third-party-notices/duplexer2@0.1.4-LICENSE.md.txt +26 -0
  356. package/third-party-notices/end-of-stream@1.4.5-LICENSE.txt +21 -0
  357. package/third-party-notices/es-abstract-get@1.0.0-LICENSE.txt +21 -0
  358. package/third-party-notices/es-abstract@1.24.2-LICENSE.txt +21 -0
  359. package/third-party-notices/es-define-property@1.0.1-LICENSE.txt +21 -0
  360. package/third-party-notices/es-errors@1.3.0-LICENSE.txt +21 -0
  361. package/third-party-notices/es-object-atoms@1.1.2-LICENSE.txt +21 -0
  362. package/third-party-notices/es-set-tostringtag@2.1.0-LICENSE.txt +21 -0
  363. package/third-party-notices/es-to-primitive@1.3.4-LICENSE.txt +22 -0
  364. package/third-party-notices/escalade@3.2.0-license.txt +9 -0
  365. package/third-party-notices/exceljs@4.4.0-LICENSE.txt +22 -0
  366. package/third-party-notices/fast-csv@4.3.6-LICENSE.txt +21 -0
  367. package/third-party-notices/fast-diff@1.3.0-LICENSE.txt +201 -0
  368. package/third-party-notices/for-each@0.3.5-LICENSE.txt +22 -0
  369. package/third-party-notices/fs-constants@1.0.0-LICENSE.txt +21 -0
  370. package/third-party-notices/fs.realpath@1.0.0-LICENSE.txt +43 -0
  371. package/third-party-notices/fstream@1.0.12-LICENSE.txt +15 -0
  372. package/third-party-notices/function-bind@1.1.2-LICENSE.txt +20 -0
  373. package/third-party-notices/function.prototype.name@1.2.0-LICENSE.txt +21 -0
  374. package/third-party-notices/functions-have-names@1.2.3-LICENSE.txt +21 -0
  375. package/third-party-notices/generator-function@2.0.1-LICENSE.md.txt +7 -0
  376. package/third-party-notices/get-caller-file@2.0.5-LICENSE.md.txt +6 -0
  377. package/third-party-notices/get-intrinsic@1.3.0-LICENSE.txt +21 -0
  378. package/third-party-notices/get-nonce@1.0.1-LICENSE.txt +21 -0
  379. package/third-party-notices/get-proto@1.0.1-LICENSE.txt +21 -0
  380. package/third-party-notices/get-symbol-description@1.1.0-LICENSE.txt +21 -0
  381. package/third-party-notices/glob@7.2.3-LICENSE.txt +21 -0
  382. package/third-party-notices/globalthis@1.0.4-LICENSE.txt +21 -0
  383. package/third-party-notices/gopd@1.2.0-LICENSE.txt +21 -0
  384. package/third-party-notices/graceful-fs@4.2.11-LICENSE.txt +15 -0
  385. package/third-party-notices/has-bigints@1.1.0-LICENSE.txt +21 -0
  386. package/third-party-notices/has-property-descriptors@1.0.2-LICENSE.txt +21 -0
  387. package/third-party-notices/has-proto@1.2.0-LICENSE.txt +21 -0
  388. package/third-party-notices/has-symbols@1.1.0-LICENSE.txt +21 -0
  389. package/third-party-notices/has-tostringtag@1.0.2-LICENSE.txt +21 -0
  390. package/third-party-notices/hasown@2.0.4-LICENSE.txt +21 -0
  391. package/third-party-notices/highlight.js@11.11.2-LICENSE.txt +29 -0
  392. package/third-party-notices/ieee754@1.2.1-LICENSE.txt +11 -0
  393. package/third-party-notices/immediate@3.0.6-LICENSE.txt.txt +20 -0
  394. package/third-party-notices/inflight@1.0.6-LICENSE.txt +15 -0
  395. package/third-party-notices/inherits@2.0.4-LICENSE.txt +16 -0
  396. package/third-party-notices/internal-slot@1.1.0-LICENSE.txt +21 -0
  397. package/third-party-notices/is-array-buffer@3.0.5-LICENSE.txt +21 -0
  398. package/third-party-notices/is-async-function@2.1.1-LICENSE.txt +20 -0
  399. package/third-party-notices/is-bigint@1.1.0-LICENSE.txt +21 -0
  400. package/third-party-notices/is-boolean-object@1.2.2-LICENSE.txt +22 -0
  401. package/third-party-notices/is-callable@1.2.7-LICENSE.txt +22 -0
  402. package/third-party-notices/is-data-view@1.0.2-LICENSE.txt +21 -0
  403. package/third-party-notices/is-date-object@1.1.0-LICENSE.txt +22 -0
  404. package/third-party-notices/is-document.all@1.0.0-LICENSE.txt +21 -0
  405. package/third-party-notices/is-finalizationregistry@1.1.1-LICENSE.txt +21 -0
  406. package/third-party-notices/is-fullwidth-code-point@3.0.0-license.txt +9 -0
  407. package/third-party-notices/is-generator-function@1.1.2-LICENSE.txt +20 -0
  408. package/third-party-notices/is-map@2.0.3-LICENSE.txt +21 -0
  409. package/third-party-notices/is-negative-zero@2.0.3-LICENSE.txt +20 -0
  410. package/third-party-notices/is-number-object@1.1.1-LICENSE.txt +22 -0
  411. package/third-party-notices/is-regex@1.2.1-LICENSE.txt +20 -0
  412. package/third-party-notices/is-set@2.0.3-LICENSE.txt +21 -0
  413. package/third-party-notices/is-shared-array-buffer@1.0.4-LICENSE.txt +21 -0
  414. package/third-party-notices/is-string@1.1.1-LICENSE.txt +22 -0
  415. package/third-party-notices/is-symbol@1.1.1-LICENSE.txt +22 -0
  416. package/third-party-notices/is-typed-array@1.1.15-LICENSE.txt +22 -0
  417. package/third-party-notices/is-weakmap@2.0.2-LICENSE.txt +21 -0
  418. package/third-party-notices/is-weakref@1.1.1-LICENSE.txt +21 -0
  419. package/third-party-notices/is-weakset@2.0.4-LICENSE.txt +21 -0
  420. package/third-party-notices/isarray@2.0.5-LICENSE.txt +21 -0
  421. package/third-party-notices/isomorphic.js@0.2.5-LICENSE.txt +21 -0
  422. package/third-party-notices/jszip@3.10.2-LICENSE.markdown.txt +651 -0
  423. package/third-party-notices/katex@0.18.9-LICENSE.txt +21 -0
  424. package/third-party-notices/kdbush@4.1.0-LICENSE.txt +15 -0
  425. package/third-party-notices/lazystream@1.0.1-LICENSE.txt +23 -0
  426. package/third-party-notices/lib0@0.2.119-LICENSE.txt +21 -0
  427. package/third-party-notices/lie@3.3.0-license.md.txt +7 -0
  428. package/third-party-notices/linkifyjs@4.3.3-LICENSE.txt +19 -0
  429. package/third-party-notices/listenercount@1.0.1-LICENSE.md.txt +5 -0
  430. package/third-party-notices/lodash-es@4.18.1-LICENSE.txt +47 -0
  431. package/third-party-notices/lodash.camelcase@4.3.0-LICENSE.txt +47 -0
  432. package/third-party-notices/lodash.defaults@4.2.0-LICENSE.txt +47 -0
  433. package/third-party-notices/lodash.difference@4.5.0-LICENSE.txt +47 -0
  434. package/third-party-notices/lodash.escaperegexp@4.1.2-LICENSE.txt +47 -0
  435. package/third-party-notices/lodash.flatten@4.4.0-LICENSE.txt +47 -0
  436. package/third-party-notices/lodash.groupby@4.6.0-LICENSE.txt +47 -0
  437. package/third-party-notices/lodash.isboolean@3.0.3-LICENSE.txt +22 -0
  438. package/third-party-notices/lodash.isequal@4.5.0-LICENSE.txt +47 -0
  439. package/third-party-notices/lodash.isfunction@3.0.9-LICENSE.txt +47 -0
  440. package/third-party-notices/lodash.isnil@4.0.0-LICENSE.txt +22 -0
  441. package/third-party-notices/lodash.isplainobject@4.0.6-LICENSE.txt +47 -0
  442. package/third-party-notices/lodash.isundefined@3.0.1-LICENSE.txt.txt +22 -0
  443. package/third-party-notices/lodash.union@4.6.0-LICENSE.txt +47 -0
  444. package/third-party-notices/lodash.uniq@4.5.0-LICENSE.txt +47 -0
  445. package/third-party-notices/long@5.3.2-LICENSE.txt +202 -0
  446. package/third-party-notices/lowlight@3.3.0-license.txt +22 -0
  447. package/third-party-notices/math-intrinsics@1.1.0-LICENSE.txt +21 -0
  448. package/third-party-notices/minimatch@3.1.5-LICENSE.txt +15 -0
  449. package/third-party-notices/minimatch@5.1.9-LICENSE.txt +15 -0
  450. package/third-party-notices/minimist@1.2.8-LICENSE.txt +18 -0
  451. package/third-party-notices/mkdirp@0.5.6-LICENSE.txt +21 -0
  452. package/third-party-notices/n-gram@2.0.2-license.txt +22 -0
  453. package/third-party-notices/normalize-path@3.0.0-LICENSE.txt +21 -0
  454. package/third-party-notices/numfmt@4.0.1-LICENSE.txt +19 -0
  455. package/third-party-notices/object-inspect@1.13.4-LICENSE.txt +21 -0
  456. package/third-party-notices/object-keys@1.1.1-LICENSE.txt +21 -0
  457. package/third-party-notices/object.assign@4.1.7-LICENSE.txt +21 -0
  458. package/third-party-notices/once@1.4.0-LICENSE.txt +15 -0
  459. package/third-party-notices/orderedmap@2.1.1-LICENSE.txt +19 -0
  460. package/third-party-notices/own-keys@1.0.2-LICENSE.txt +21 -0
  461. package/third-party-notices/pako@1.0.11-LICENSE.txt +21 -0
  462. package/third-party-notices/path-is-absolute@1.0.1-license.txt +21 -0
  463. package/third-party-notices/possible-typed-array-names@1.1.0-LICENSE.txt +21 -0
  464. package/third-party-notices/process-nextick-args@2.0.1-license.md.txt +19 -0
  465. package/third-party-notices/prosemirror-changeset@2.4.4-LICENSE.txt +19 -0
  466. package/third-party-notices/prosemirror-commands@1.7.2-LICENSE.txt +19 -0
  467. package/third-party-notices/prosemirror-dropcursor@1.8.4-LICENSE.txt +19 -0
  468. package/third-party-notices/prosemirror-gapcursor@1.4.1-LICENSE.txt +19 -0
  469. package/third-party-notices/prosemirror-history@1.5.1-LICENSE.txt +19 -0
  470. package/third-party-notices/prosemirror-inputrules@1.5.1-LICENSE.txt +19 -0
  471. package/third-party-notices/prosemirror-keymap@1.2.3-LICENSE.txt +19 -0
  472. package/third-party-notices/prosemirror-model@1.25.12-LICENSE.txt +19 -0
  473. package/third-party-notices/prosemirror-schema-list@1.5.1-LICENSE.txt +19 -0
  474. package/third-party-notices/prosemirror-state@1.4.4-LICENSE.txt +19 -0
  475. package/third-party-notices/prosemirror-tables@1.8.5-LICENSE.txt +19 -0
  476. package/third-party-notices/prosemirror-transform@1.12.2-LICENSE.txt +19 -0
  477. package/third-party-notices/prosemirror-view@1.42.6-LICENSE.txt +19 -0
  478. package/third-party-notices/protobufjs@7.6.6-LICENSE.txt +39 -0
  479. package/third-party-notices/quickselect@3.0.0-LICENSE.txt +15 -0
  480. package/third-party-notices/rbush@4.0.1-LICENSE.txt +21 -0
  481. package/third-party-notices/react-dom@19.3.1-LICENSE.txt +21 -0
  482. package/third-party-notices/react-remove-scroll@2.7.2-LICENSE.txt +21 -0
  483. package/third-party-notices/react-style-singleton@2.2.3-LICENSE.txt +21 -0
  484. package/third-party-notices/react@19.3.1-LICENSE.txt +21 -0
  485. package/third-party-notices/readable-stream@2.3.8-LICENSE.txt +47 -0
  486. package/third-party-notices/readable-stream@3.6.2-LICENSE.txt +47 -0
  487. package/third-party-notices/readdir-glob@1.1.3-LICENSE.txt +201 -0
  488. package/third-party-notices/reflect.getprototypeof@1.0.10-LICENSE.txt +21 -0
  489. package/third-party-notices/regexp.prototype.flags@1.5.4-LICENSE.txt +22 -0
  490. package/third-party-notices/require-directory@2.1.1-LICENSE.txt +22 -0
  491. package/third-party-notices/rimraf@2.7.1-LICENSE.txt +15 -0
  492. package/third-party-notices/rope-sequence@1.3.4-LICENSE.txt +19 -0
  493. package/third-party-notices/rxjs@7.8.2-LICENSE.txt.txt +202 -0
  494. package/third-party-notices/safe-array-concat@1.1.4-LICENSE.txt +21 -0
  495. package/third-party-notices/safe-buffer@5.1.2-LICENSE.txt +21 -0
  496. package/third-party-notices/safe-buffer@5.2.1-LICENSE.txt +21 -0
  497. package/third-party-notices/safe-push-apply@1.0.0-LICENSE.txt +21 -0
  498. package/third-party-notices/safe-regex-test@1.1.0-LICENSE.txt +21 -0
  499. package/third-party-notices/scheduler@0.28.0-LICENSE.txt +21 -0
  500. package/third-party-notices/set-function-length@1.2.2-LICENSE.txt +21 -0
  501. package/third-party-notices/set-function-name@2.0.2-LICENSE.txt +21 -0
  502. package/third-party-notices/set-proto@1.0.0-LICENSE.txt +21 -0
  503. package/third-party-notices/setimmediate@1.0.5-LICENSE.txt.txt +20 -0
  504. package/third-party-notices/side-channel-list@1.0.1-LICENSE.txt +21 -0
  505. package/third-party-notices/side-channel-map@1.0.1-LICENSE.txt +21 -0
  506. package/third-party-notices/side-channel-weakmap@1.0.2-LICENSE.txt +21 -0
  507. package/third-party-notices/side-channel@1.1.1-LICENSE.txt +21 -0
  508. package/third-party-notices/sonner@2.0.8-LICENSE.md.txt +21 -0
  509. package/third-party-notices/stop-iteration-iterator@1.1.0-LICENSE.txt +21 -0
  510. package/third-party-notices/string-width@4.2.3-license.txt +9 -0
  511. package/third-party-notices/string.prototype.trim@1.2.11-LICENSE.txt +21 -0
  512. package/third-party-notices/string.prototype.trimend@1.0.10-LICENSE.txt +21 -0
  513. package/third-party-notices/string.prototype.trimstart@1.0.8-LICENSE.txt +21 -0
  514. package/third-party-notices/string_decoder@1.1.1-LICENSE.txt +48 -0
  515. package/third-party-notices/string_decoder@1.3.0-LICENSE.txt +48 -0
  516. package/third-party-notices/strip-ansi@6.0.1-license.txt +9 -0
  517. package/third-party-notices/tar-stream@2.2.0-LICENSE.txt +21 -0
  518. package/third-party-notices/tiny-pinyin@1.3.2-LICENSE.txt +21 -0
  519. package/third-party-notices/tmp@0.2.7-LICENSE.txt +21 -0
  520. package/third-party-notices/traverse@0.3.10-LICENSE.txt +21 -0
  521. package/third-party-notices/trigram-utils@2.0.1-license.txt +22 -0
  522. package/third-party-notices/tslib@2.8.1-LICENSE.txt.txt +12 -0
  523. package/third-party-notices/typed-array-buffer@1.0.3-LICENSE.txt +21 -0
  524. package/third-party-notices/typed-array-byte-length@1.0.3-LICENSE.txt +21 -0
  525. package/third-party-notices/typed-array-byte-offset@1.0.5-LICENSE.txt +21 -0
  526. package/third-party-notices/typed-array-length@1.0.8-LICENSE.txt +21 -0
  527. package/third-party-notices/typedarray.prototype.slice@1.0.6-LICENSE.txt +21 -0
  528. package/third-party-notices/unbox-primitive@1.1.0-LICENSE.txt +21 -0
  529. package/third-party-notices/undici-types@8.9.0-LICENSE.txt +21 -0
  530. package/third-party-notices/unzipper@0.10.14-LICENSE.txt +25 -0
  531. package/third-party-notices/use-callback-ref@1.3.3-LICENSE.txt +21 -0
  532. package/third-party-notices/use-sidecar@1.1.3-LICENSE.txt +21 -0
  533. package/third-party-notices/util-deprecate@1.0.2-LICENSE.txt +24 -0
  534. package/third-party-notices/uuid@8.3.2-LICENSE.md.txt +9 -0
  535. package/third-party-notices/w3c-keyname@2.2.8-LICENSE.txt +19 -0
  536. package/third-party-notices/which-boxed-primitive@1.1.1-LICENSE.txt +21 -0
  537. package/third-party-notices/which-builtin-type@1.2.1-LICENSE.txt +21 -0
  538. package/third-party-notices/which-collection@1.0.2-LICENSE.txt +21 -0
  539. package/third-party-notices/which-typed-array@1.1.24-LICENSE.txt +22 -0
  540. package/third-party-notices/wrap-ansi@7.0.0-license.txt +9 -0
  541. package/third-party-notices/wrappy@1.0.2-LICENSE.txt +15 -0
  542. package/third-party-notices/xmlchars@2.2.0-LICENSE.txt +18 -0
  543. package/third-party-notices/y-protocols@1.0.7-LICENSE.txt +21 -0
  544. package/third-party-notices/y18n@5.0.8-LICENSE.txt +13 -0
  545. package/third-party-notices/yargs-parser@21.1.1-LICENSE.txt.txt +14 -0
  546. package/third-party-notices/yargs@17.7.3-LICENSE.txt +21 -0
  547. package/third-party-notices/yjs@13.6.33-LICENSE.txt +23 -0
  548. package/third-party-notices/zip-stream@4.1.1-LICENSE.txt +22 -0
@@ -0,0 +1,2614 @@
1
+ .wendang {
2
+ --color-bg: #f6f8fc; --color-surface: #fff; --color-surface-subtle: #f5f7fa;
3
+ --color-text: #1f2937; --color-text-muted: #667085; --color-text-faint: #7c8798;
4
+ --color-border: #dce2eb; --color-border-strong: #b9c3d2;
5
+ --color-accent: var(--wendang-accent, #2f6feb); --color-accent-soft: #eaf1ff;
6
+ --color-danger: #cf3d48; --color-success: #21814b; --color-warning: #ad6b12;
7
+ /*
8
+ * 行内评论标记色:**同一黄色系的三档**,不引入第二种色相。
9
+ *
10
+ * 早先"有回复"的评论用蓝色区分,用户反馈蓝色与黄色差别太大、容易误读成
11
+ * 两类不同的东西("可以搞多色,但是不要影响用户心智")。现在三档都在黄色
12
+ * 家族里,靠**深浅**表达强弱:
13
+ * - 普通评论:亮黄底 + 深琥珀下划线;
14
+ * - 有回复:底色加深一档(表示这里更"热");
15
+ * - 当前激活:再深一档。
16
+ * 下划线取深琥珀(#d48806)而不是亮黄:底色变亮后,浅色下划线在浅蓝/白
17
+ * 背景上都看不清(用户反馈"这个看不清,底部和背景色")。
18
+ */
19
+ --comment-mark-bg: #ffe58f; --comment-mark-line: #d48806;
20
+ --comment-mark-bg-reply: #ffd66688; --comment-mark-line-reply: #ff9900;
21
+ --comment-mark-bg-active: #ffc53d; --comment-mark-line-active: #ad6800;
22
+ --content-font-size: 16px; --content-line-height: 1.75; --content-text-color: var(--color-text);
23
+ --content-width: 100%; --shadow-pop: 0 10px 32px #14284a20;
24
+ /*
25
+ * 内容排版 token(表格、标题、间距、媒体)。
26
+ *
27
+ * 这些变量原先只存在于 YWiki 的 web/src/styles/global.css,抽成 SDK 时
28
+ * 消费方(shared/content-style.css)留下了、定义方漏掉了。CSS 变量取到
29
+ * 无效值会让整条声明在计算值阶段失效,于是表格边框变成 none、表头背景
30
+ * 变透明、段落与标题的间距塌成 0。颜色用绝对值,间距跟随 --content-font-size。
31
+ */
32
+ --content-heading-color: #101828;
33
+ --content-table-header-bg: #edf3fc;
34
+ --content-table-grid-color: #d5dfed;
35
+ --content-table-font-size: calc(var(--content-font-size) * 13 / 14);
36
+ --content-table-line-height: 1.5;
37
+ --content-media-radius: 8px;
38
+ --content-scroll-offset: 80px;
39
+ /**
40
+ * 块间距(段落之间)。
41
+ *
42
+ * 从 `3/7`(16px 字号下 6.86px)调到 `5/7`(11.43px)。原因有两个:
43
+ * 1. 6.86px 对中文正文偏紧,段与段之间读起来粘连(用户反馈"行间距处理下");
44
+ * 2. 块选中时会沿块上下各外扩一段做高亮带,而外扩必须给相邻块之间保留
45
+ * 可见的白缝——间距太小时这段预算不够,两个块的底色会糊成一整块
46
+ * (用户实测:"带了选中背景后上下间距没了")。
47
+ */
48
+ --space-block: calc(var(--content-font-size) * 5 / 7);
49
+ --space-module: calc(var(--content-font-size) * 9 / 7);
50
+ --space-heading-top: calc(var(--content-font-size) * 2);
51
+ --space-heading-bottom: calc(var(--content-font-size) * 5 / 7);
52
+ --space-list-item: calc(var(--content-font-size) * 0.25);
53
+ --space-list-block: calc(var(--content-font-size) * 0.5);
54
+ --space-divider: calc(var(--content-font-size) * 2);
55
+ --color-code-bg: #f1f5fa;
56
+ color: var(--color-text); background: var(--color-surface);
57
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", sans-serif;
58
+ min-width: 0; min-height: 0;
59
+ }
60
+ .wendang[data-wendang-theme="dark"] {
61
+ --color-bg: #17191e; --color-surface: #202329; --color-surface-subtle: #292d35;
62
+ --color-text: #e5e9f0; --color-text-muted: #b2bdcd; --color-text-faint: #8f9cb0;
63
+ --color-border: #3b4350; --color-border-strong: #606c7e; --color-accent-soft: #243653;
64
+ --content-text-color: #e8e8ec;
65
+ --content-heading-color: #f0f0f3;
66
+ --content-table-header-bg: #2a2e38;
67
+ --content-table-grid-color: #424753;
68
+ --color-code-bg: #20242c;
69
+ /* 深色底上用低明度琥珀底 + 高明度下划线,保持同一黄色系的三档深浅 */
70
+ --comment-mark-bg: #4a3a12; --comment-mark-line: #e8b923;
71
+ --comment-mark-bg-reply: #5c4813; --comment-mark-line-reply: #ffc53d;
72
+ --comment-mark-bg-active: #6b5416; --comment-mark-line-active: #ffc53d;
73
+ }
74
+ .wendang-root { min-height: 0; min-width: 0; height: 100%; }
75
+ /**
76
+ * 浮层挂载根。必须建层叠上下文:正文 `.tiptap` 自己是 `position: relative`,
77
+ * 若 portal 没有 z-index,它会被正文里的图片等元素盖住——实测拖拽插入线
78
+ * 就因此完全看不见(mouse 命中的是图片)。
79
+ */
80
+ .wendang-portal {
81
+ position: relative;
82
+ z-index: 1000;
83
+ }
84
+ /*
85
+ * 基础元素样式同时作用于 `.wendang` 正文与 `.wendang-popup-scope` 弹层内容。
86
+ *
87
+ * 弹层(对话框、右键菜单)teleport 到 body 后不在 `.wendang` 内,只带了一份
88
+ * token 副本;如果这些规则只写在 `.wendang` 下,弹层里的 input 会退回浏览器
89
+ * 默认样式、`.muted`/`.small`/`.error-banner` 全部失效。用 `:is()` 让两处共用
90
+ * 同一组声明,避免再复制一遍。
91
+ */
92
+ :is(.wendang, .wendang-popup-scope) :where(button, input, textarea) { font: inherit; box-sizing: border-box; }
93
+ :is(.wendang, .wendang-popup-scope) :where(a) { color: var(--color-accent); }
94
+ :is(.wendang, .wendang-popup-scope) :where(button) { cursor: pointer; }
95
+ :is(.wendang, .wendang-popup-scope) .muted { color: var(--color-text-muted); }
96
+ :is(.wendang, .wendang-popup-scope) .small { font-size: 12px; }
97
+ :is(.wendang, .wendang-popup-scope) :where(input:not([type=checkbox]):not([type=radio]), textarea):not(.worksheet-grid *) {
98
+ background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border);
99
+ border-radius: 6px; padding: 6px 8px;
100
+ }
101
+ :is(.wendang, .wendang-popup-scope) :where(.error-banner, .error) { color: var(--color-danger); }
102
+ :is(.wendang, .wendang-popup-scope) :where(.notice) { color: var(--color-text-muted); }
103
+
104
+ /* 文档调色板:与存储值分开,切换主题不会改写正文或触发保存。 */
105
+ .wendang {
106
+ --doc-text-gray: #646a73;
107
+ --doc-text-red: #d92c2c;
108
+ --doc-text-orange: #b95d0b;
109
+ --doc-text-yellow: #8a6c0a;
110
+ --doc-text-green: #237b35;
111
+ --doc-text-blue: #1971c2;
112
+ --doc-text-purple: #7048e8;
113
+ --doc-highlight-gray-soft: #f1f3f5;
114
+ --doc-highlight-red: #ffe3e3;
115
+ --doc-highlight-orange: #fff0db;
116
+ --doc-highlight-yellow: #fff3bf;
117
+ --doc-highlight-green: #d3f9d8;
118
+ --doc-highlight-blue: #d0ebff;
119
+ --doc-highlight-purple: #e5dbff;
120
+ --doc-highlight-gray: #dee2e6;
121
+ --doc-highlight-gray-strong: #ced4da;
122
+ --doc-highlight-red-strong: #ffc9c9;
123
+ --doc-highlight-orange-strong: #ffd8a8;
124
+ --doc-highlight-yellow-strong: #ffec99;
125
+ --doc-highlight-green-strong: #b2f2bb;
126
+ --doc-highlight-blue-strong: #a5d8ff;
127
+ --doc-highlight-purple-strong: #d0bfff;
128
+ }
129
+
130
+ .wendang[data-wendang-theme='dark'] {
131
+ --doc-text-gray: #b8beca;
132
+ --doc-text-red: #ff9b9b;
133
+ --doc-text-orange: #ffc078;
134
+ --doc-text-yellow: #f6d37a;
135
+ --doc-text-green: #8ce99a;
136
+ --doc-text-blue: #91caff;
137
+ --doc-text-purple: #d0bfff;
138
+ --doc-highlight-gray-soft: #32353d;
139
+ --doc-highlight-red: #563138;
140
+ --doc-highlight-orange: #523a2a;
141
+ --doc-highlight-yellow: #4a4226;
142
+ --doc-highlight-green: #294737;
143
+ --doc-highlight-blue: #293f5b;
144
+ --doc-highlight-purple: #42335b;
145
+ --doc-highlight-gray: #424650;
146
+ --doc-highlight-gray-strong: #555b66;
147
+ --doc-highlight-red-strong: #713f47;
148
+ --doc-highlight-orange-strong: #6a4b31;
149
+ --doc-highlight-yellow-strong: #635732;
150
+ --doc-highlight-green-strong: #355c44;
151
+ --doc-highlight-blue-strong: #355476;
152
+ --doc-highlight-purple-strong: #554273;
153
+ }
154
+ /**
155
+ * 只读渲染器**专属**样式。
156
+ *
157
+ * 说明:内容排版(标题/列表/表格/代码/引用/高亮块/行内元素……)已收敛到
158
+ * `@/shared/content-style.css` 的单一真源,编辑端与只读端共用;本文件只保留
159
+ * **只有只读端才有**的东西:图片懒加载占位、公式占位/错误、附件卡片。
160
+ *
161
+ * 历史教训:曾因渲染器从 .vue 迁为 .ts 而丢失整个样式文件,排版静默退回浏览器
162
+ * 默认——结构正常、观感没生效,是很容易漏掉的回归。因此这里显式 import。
163
+ */
164
+ /* One shell for the editor node view and the read-only renderer. */
165
+ .ywiki-content .ywiki-code-panel {
166
+ --code-bg:#ffffff;--code-header:#f7f8fa;--code-border:#e2e5e9;--code-text:#303640;--code-muted:#8a9099;
167
+ --code-keyword:#d13b52;--code-string:#2e8764;--code-number:#a66e12;--code-title:#8250b5;--code-property:#476f9c;--code-comment:#8a9099;--code-tag:#bf3c51;
168
+ position:relative;min-width:0;max-width:100%;border:1px solid var(--code-border);border-radius:7px;
169
+ background:var(--code-bg);color:var(--code-text);isolation:isolate;
170
+ }
171
+ .ywiki-content .ywiki-code-panel.code-theme-soft {
172
+ --code-bg:#f5f8fc;--code-header:#edf2f8;--code-border:#dce4ef;--code-text:#34445b;--code-muted:#8492a7;
173
+ --code-keyword:#3478bd;--code-string:#318b6d;--code-number:#9b7a1e;--code-title:#9851c4;--code-property:#516c9f;--code-comment:#8492a7;--code-tag:#b14c6c;
174
+ }
175
+ [data-wendang-theme='dark'] .ywiki-content .ywiki-code-panel.code-theme-auto,
176
+ .ywiki-content .ywiki-code-panel.code-theme-night {
177
+ --code-bg:#20242c;--code-header:#272c35;--code-border:#373e49;--code-text:#d7dde7;--code-muted:#929cac;
178
+ --code-keyword:#f58196;--code-string:#a5cf8b;--code-number:#efbc82;--code-title:#c6a0ee;--code-property:#89b9ee;--code-comment:#919cab;--code-tag:#f08a9d;
179
+ }
180
+ .code-toolbar {display:flex;align-items:center;gap:7px;min-height:38px;padding:4px 9px;background:var(--code-header);border-bottom:1px solid var(--code-border);border-radius:6px 6px 0 0;font:12px/1.5 var(--font-sans,system-ui,sans-serif);color:var(--code-muted);user-select:none;}
181
+ .code-toolbar-host {position:relative;z-index:2;}
182
+ .code-toolbar-actions {display:flex;align-items:center;gap:7px;margin-left:auto;min-width:0;}
183
+ .code-toolbar-summary {font-size:11px;font-variant-numeric:tabular-nums;white-space:nowrap;}
184
+ /*
185
+ * 语言选择器在代码块的深色标题栏里,必须把 wui 的语义变量改指向代码块色板,
186
+ * 否则会是一块白底控件。面板本身渲染在 portal 根(正文之外),不继承这些
187
+ * 变量,因此下拉列表仍是普通的浅色菜单 —— 与其它菜单一致。
188
+ */
189
+ .code-language-select {width:146px;font-size:12px;--w-surface:var(--code-header);--w-text:var(--code-text);--w-text-faint:var(--code-muted);--w-border-strong:var(--code-border);--w-border:var(--code-border);--w-surface-subtle:color-mix(in srgb,var(--code-text) 10%,transparent);}
190
+ .code-language-label {max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;}
191
+ .code-toolbar-divider {height:15px;border-left:1px solid var(--code-border);margin:0 2px;}
192
+ .code-toolbar .code-copy-button,.code-toolbar .code-settings-button,.code-toolbar .code-fold-button {color:var(--code-muted);background:transparent;}
193
+ .code-toolbar .code-copy-button {min-width:86px;}
194
+ .code-toolbar .code-copy-button:hover,.code-toolbar .code-settings-button:hover,.code-toolbar .code-fold-button:hover {color:var(--code-text);background:color-mix(in srgb,var(--code-text) 6%,transparent);}
195
+ .code-copy-button svg {vertical-align:middle;}
196
+ .code-copy-announcement {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);}
197
+ .code-option-check {float:right;margin-left:24px;}
198
+ .code-theme-swatch {display:inline-block;width:13px;height:13px;vertical-align:-2px;margin-right:8px;border:1px solid #c7ccd4;border-radius:3px;background:#fff;}
199
+ .code-theme-swatch[data-code-swatch='auto'] {background:linear-gradient(90deg,#fff 50%,#303743 50%);}
200
+ .code-theme-swatch[data-code-swatch='soft'] {background:#e6effa;}
201
+ .code-theme-swatch[data-code-swatch='night'] {background:#272c35;}
202
+ .ywiki-content .ywiki-code-panel .code-scroll {display:flex;align-items:stretch;position:relative;overflow:auto;max-height:464px;border-radius:0 0 6px 6px;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--code-muted) 45%,transparent) transparent;background:var(--code-bg);}
203
+ .ywiki-content .ywiki-code-panel .code-scroll[hidden] {display:none;}
204
+ .ywiki-content .ywiki-code-panel.is-unlimited .code-scroll {max-height:none;}
205
+ .ywiki-content .ywiki-code-panel .code-line-numbers,
206
+ .ywiki-content .ywiki-code-panel pre.doc-code {font:13px/22px ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono',monospace;font-variant-ligatures:none;tab-size:2;white-space:pre;}
207
+ .ywiki-content .ywiki-code-panel .code-line-numbers {position:sticky;left:0;z-index:1;align-self:stretch;flex:0 0 auto;min-width:42px;box-sizing:border-box;padding:12px 10px 12px 12px;text-align:right;color:var(--code-muted);background:var(--code-bg);border-right:1px solid color-mix(in srgb,var(--code-border) 65%,transparent);user-select:none;pointer-events:none;}
208
+ .ywiki-content .ywiki-code-panel pre.doc-code {flex:1 0 auto;min-width:0;max-width:none;margin:0!important;padding:12px 16px;border:0;border-radius:0;background:var(--code-bg);color:var(--code-text);overflow:visible;}
209
+ .ywiki-content .ywiki-code-panel pre.doc-code code {display:block;margin:0;padding:0;border:0;background:none;color:var(--code-text);font:inherit;white-space:inherit;tab-size:inherit;border-radius:0;}
210
+ .ywiki-content .ywiki-code-panel.is-collapsed .code-toolbar {border-bottom:0;border-radius:6px;}
211
+ .ywiki-content .ywiki-code-panel:focus-within {border-color:color-mix(in srgb,var(--color-accent) 45%,var(--code-border));}
212
+ .ywiki-content .ywiki-code-panel .code-scroll:focus-visible {outline:2px solid var(--color-accent);outline-offset:-2px;}
213
+ .ywiki-content .ywiki-code-panel :where(.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-meta) {color:var(--code-keyword);}
214
+ .ywiki-content .ywiki-code-panel :where(.hljs-string,.hljs-regexp,.hljs-addition,.hljs-attribute) {color:var(--code-string);}
215
+ .ywiki-content .ywiki-code-panel :where(.hljs-number,.hljs-symbol,.hljs-bullet,.hljs-variable,.hljs-template-variable) {color:var(--code-number);}
216
+ .ywiki-content .ywiki-code-panel :where(.hljs-title,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-type) {color:var(--code-title);}
217
+ .ywiki-content .ywiki-code-panel :where(.hljs-built_in,.hljs-attr,.hljs-property) {color:var(--code-property);}
218
+ .ywiki-content .ywiki-code-panel :where(.hljs-comment,.hljs-quote) {color:var(--code-comment);font-style:normal;}
219
+ .ywiki-content .ywiki-code-panel :where(.hljs-tag,.hljs-name,.hljs-deletion) {color:var(--code-tag);}
220
+ @media(max-width:600px){.code-toolbar{gap:4px;padding-inline:6px}.code-toolbar-actions{gap:4px}.code-language-select{width:108px}.code-toolbar-summary{display:none}.code-toolbar-divider{margin:0}.code-language-label{max-width:100px}.code-copy-button{min-width:72px!important}}
221
+ @media print{.ywiki-content .ywiki-code-panel .code-scroll{max-height:none!important;overflow:visible!important;display:flex!important}.code-toolbar-actions,.code-fold-button{display:none!important}.ywiki-content .ywiki-code-panel{break-inside:avoid}.ywiki-content .ywiki-code-panel pre.doc-code{white-space:pre-wrap;overflow-wrap:anywhere;flex-shrink:1}}
222
+ /* Tokens are document presentation; saved attributes never contain free CSS values. */
223
+ [data-wendang-theme] {
224
+ --callout-border-gray:#c7cbd1;--callout-border-red:#f0a2a2;--callout-border-orange:#ffc078;--callout-border-yellow:#e3ca71;
225
+ --callout-border-green:#91d4a0;--callout-border-blue:#9ac5ef;--callout-border-purple:#c0a4ed;
226
+ }
227
+ [data-wendang-theme='dark'] {
228
+ --callout-border-gray:#697181;--callout-border-red:#a7606b;--callout-border-orange:#a97843;--callout-border-yellow:#97844a;
229
+ --callout-border-green:#5c8b6c;--callout-border-blue:#587fa9;--callout-border-purple:#8667af;
230
+ }
231
+ .ywiki-content .doc-callout {
232
+ --callout-first-line-height:calc(var(--content-font-size) * var(--content-line-height));
233
+ position:relative;display:grid;grid-template-columns:30px minmax(0,1fr);column-gap:12px;align-items:start;
234
+ border:1px solid var(--callout-border,var(--callout-border-blue));border-radius:9px;
235
+ background:var(--callout-fill,var(--doc-highlight-blue));color:var(--callout-text,var(--content-text-color));
236
+ padding:16px 18px;
237
+ }
238
+ .ywiki-content .doc-callout[data-icon-hidden='true'] {grid-template-columns:minmax(0,1fr);}
239
+ .callout-controls-host {display:contents;}
240
+ .ywiki-content .doc-callout-content {grid-column:2;grid-row:1;min-width:0;color:inherit;}
241
+ .ywiki-content .doc-callout[data-icon-hidden='true']>.doc-callout-content {grid-column:1;}
242
+ .ywiki-content .doc-callout .callout-icon {
243
+ grid-column:1;grid-row:1;align-self:start;display:inline-flex;align-items:center;justify-content:center;
244
+ width:30px;min-width:30px;height:var(--callout-first-line-height);min-height:0;padding:0;
245
+ font-size:22px;line-height:1;user-select:none;color:inherit;
246
+ }
247
+ /* A heading on the first line has its own size and leading; later paragraphs do not move the icon. */
248
+ .ywiki-content .doc-callout:has(>.doc-callout-content>h1:first-child){--callout-first-line-height:calc(var(--content-font-size) * 1.625 * 1.3);}
249
+ .ywiki-content .doc-callout:has(>.doc-callout-content>h2:first-child){--callout-first-line-height:calc(var(--content-font-size) * 1.375 * 1.3);}
250
+ .ywiki-content .doc-callout:has(>.doc-callout-content>h3:first-child){--callout-first-line-height:calc(var(--content-font-size) * 1.125 * 1.3);}
251
+ .ywiki-content .doc-callout:has(>.doc-callout-content>:is(h4,h5,h6):first-child){--callout-first-line-height:calc(var(--content-font-size) * 1.3);}
252
+ .ywiki-content .doc-callout>.doc-callout-content>:first-child {margin-top:0;}
253
+ .ywiki-content .doc-callout>.doc-callout-content>:last-child {margin-bottom:0;}
254
+ .ywiki-content .doc-callout-content :where(h1,h2,h3,h4,h5,h6) {color:inherit;}
255
+ @media(max-width:600px){.ywiki-content .doc-callout{padding:12px;column-gap:9px;}}
256
+
257
+ /**
258
+ * 内容排版**单一真源**。
259
+ *
260
+ * 为什么单独一个文件(对齐《Wiki好用技术方案》1.1 的「单一 schema 真源」):
261
+ * 正文的观感必须在**编辑态与只读态完全一致**。此前编辑端样式写在
262
+ * `EditorPane.vue` 的 `.ywiki-prose`、只读端写在 `renderer/renderer.css`
263
+ * 的 `.doc-renderer`,两份各改各的——实测已经漂移(标题上间距 1.2em vs 1.6em、
264
+ * h5/h6 两端都没定义)。这里收敛为一份,两端只在根元素上带同一个类
265
+ * `ywiki-content`:
266
+ * - 编辑端:`editorProps.attributes.class = 'ywiki-prose ywiki-content'`
267
+ * - 只读端:`DocRenderer` 根节点 `class="doc-renderer ywiki-content"`
268
+ *
269
+ * 只保留「只有一端才有」的规则在各自文件里(如编辑端的块手柄、只读端的
270
+ * 图片懒加载占位)。凡是两端都会渲染的元素,样式只写在这里。
271
+ *
272
+ * 尺度以 docs/Wiki内容区域规范.md 为准;数值是 YWiki 的产品基线。
273
+ * 块间距由文件末尾的 flow 规则统一处理,容器结构使用 :where(),确保编辑根
274
+ * 与阅读根以及兼容 .doc-body 容器的选择器优先级相同。元素规则不再各自声明纵向 margin。
275
+ */
276
+
277
+ /* ---------------------------------------------------------------- 根与节奏 */
278
+ .ywiki-content {
279
+ min-width: 0;
280
+ container-type: inline-size;
281
+ container-name: wiki-content;
282
+ font-size: var(--content-font-size);
283
+ line-height: var(--content-line-height);
284
+ color: var(--content-text-color);
285
+ /* 标点空白裁剪(支持的浏览器生效);不修改正文中的中英文空格。 */
286
+ text-spacing-trim: space-all;
287
+ overflow-wrap: anywhere;
288
+ word-break: normal;
289
+ }
290
+
291
+ /* reset 与 flow 都只有 .ywiki-content 的一份 class 权重。
292
+ 避免 p/ul/pre 的 margin: 0 压过编辑端的相邻块间距。 */
293
+ .ywiki-content :where(p, h1, h2, h3, h4, h5, h6, ul, ol, blockquote, pre, table, hr, img) {
294
+ margin-block: 0;
295
+ }
296
+ /* 用户输入的空段落也必须在阅读端保留一行,不能只在编辑端占高度。 */
297
+ .ywiki-content p:empty {
298
+ min-height: calc(1em * var(--content-line-height));
299
+ }
300
+ .ywiki-content :where(h1, h2, h3, h4, h5, h6):empty {
301
+ min-height: 1.3em;
302
+ }
303
+
304
+ /* ---------------------------------------------------------------- 标题层级
305
+ 标题字号随正文 token 等比缩放。
306
+ 字重统一 600(原 650 偏重),标题带轻微负字距更像正文排版而非 UI 文本。 */
307
+ .ywiki-content h1,
308
+ .ywiki-content h2,
309
+ .ywiki-content h3,
310
+ .ywiki-content h4,
311
+ .ywiki-content h5,
312
+ .ywiki-content h6 {
313
+ font-weight: 600;
314
+ color: var(--content-heading-color);
315
+ line-height: 1.3;
316
+ letter-spacing: -0.01em;
317
+ /* 目录跳转时留出顶部空间,避免标题被页头挡住 */
318
+ scroll-margin-top: var(--content-scroll-offset);
319
+ }
320
+ .ywiki-content h1 { font-size: calc(var(--content-font-size) * 1.625); }
321
+ .ywiki-content h2 { font-size: calc(var(--content-font-size) * 1.375); }
322
+ .ywiki-content h3 { font-size: calc(var(--content-font-size) * 1.125); }
323
+ .ywiki-content h4 { font-size: var(--content-font-size); }
324
+ .ywiki-content h5 { font-size: var(--content-font-size); }
325
+ .ywiki-content h6 {
326
+ font-size: var(--content-font-size);
327
+ color: var(--color-text-muted);
328
+ letter-spacing: 0;
329
+ }
330
+
331
+ /* ---------------------------------------------------------------- 列表 */
332
+ .ywiki-content ul,
333
+ .ywiki-content ol {
334
+ padding-left: 1.5em;
335
+ }
336
+ .ywiki-content ul { list-style: disc; }
337
+ .ywiki-content ol { list-style: decimal; }
338
+ /* 层级用不同符号区分,长嵌套下更容易看清层级。 */
339
+ .ywiki-content ul ul { list-style: circle; }
340
+ .ywiki-content ul ul ul { list-style: square; }
341
+ .ywiki-content li + li { margin-top: var(--space-list-item); }
342
+ .ywiki-content li::marker { color: var(--color-text-muted); }
343
+ /* 列表项段落的 reset 与内部间距同样由 flow 规则提供。 */
344
+
345
+ /* 待办列表:编辑端是 ul[data-type='taskList'],只读端是 ul.doc-task-list。
346
+ 勾选框与正文左缘齐平、且与首行文字垂直居中(此前水平缩进 4px、垂直偏低约 5px,
347
+ 用户反馈"不对齐")。刻意不用普通列表的 1.5em 缩进——待办项希望勾选框与
348
+ 上方段落左对齐,读起来是一条直线。 */
349
+ .ywiki-content ul.doc-task-list,
350
+ .ywiki-content ul[data-type='taskList'] {
351
+ list-style: none;
352
+ padding-left: 0;
353
+ }
354
+ .ywiki-content li.doc-task-item,
355
+ .ywiki-content ul[data-type='taskList'] > li {
356
+ display: flex;
357
+ gap: 0.5em;
358
+ align-items: flex-start;
359
+ line-height: var(--content-line-height);
360
+ }
361
+ .ywiki-content li.doc-task-item > input[type='checkbox'],
362
+ .ywiki-content ul[data-type='taskList'] > li > label > input[type='checkbox'] {
363
+ flex: none;
364
+ font: inherit;
365
+ width: 1em;
366
+ height: 1em;
367
+ margin: 0;
368
+ accent-color: var(--color-accent);
369
+ }
370
+ /* 阅读端的 input 直接参与任务项布局,用上边距对齐首行。
371
+ 编辑端由首行等高的 label 居中,不能再给 input 叠加这段偏移。 */
372
+ .ywiki-content li.doc-task-item > input[type='checkbox'] {
373
+ margin-top: calc((var(--content-line-height) - 1) * 0.5em);
374
+ }
375
+ .ywiki-content li.doc-task-item > span,
376
+ .ywiki-content ul[data-type='taskList'] > li > div {
377
+ min-width: 0;
378
+ flex: 1;
379
+ }
380
+
381
+ /* ---------------------------------------------------------------- 引用 */
382
+ .ywiki-content blockquote {
383
+ border-left: 3px solid var(--color-border-strong);
384
+ padding: 0.1em 0 0.1em 1em;
385
+ color: var(--color-text-muted);
386
+ }
387
+
388
+ /* 代码块外观由 code-block.css 统一;裸 pre 用于兼容内容。 */
389
+ .ywiki-content pre { overflow:auto; padding:12px 16px; border:1px solid var(--color-border); border-radius:6px; background:var(--color-code-bg); font:13px/22px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
390
+ .ywiki-content code { background:var(--color-surface-subtle);border:1px solid var(--color-border);border-radius:4px;padding:.1em .35em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.875em; }
391
+
392
+ /* ---------------- 编辑端:公式就地编辑(nodeView) ---------------- */
393
+ .math-node { cursor: pointer; }
394
+ /* 渲染结果就位后,把它包在带淡底的容器里,提示"这是一段可点击编辑的公式" */
395
+ .math-node .math-render { border-radius: 4px; }
396
+ .math-node:hover .math-render {
397
+ background: color-mix(in srgb, var(--color-accent) 10%, transparent);
398
+ }
399
+ .math-node.is-editing .math-render { display: none; }
400
+ .math-latex-input {
401
+ width: 100%;
402
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
403
+ font-size: 0.875em;
404
+ padding: 2px 6px;
405
+ border: 1px solid var(--color-accent);
406
+ border-radius: 4px;
407
+ background: var(--color-surface);
408
+ color: var(--color-text);
409
+ }
410
+ /* ---------------------------------------------------------------- 表格
411
+ 文档网格:白色内容区、浅色表头、圆角外框;读写端共用。 */
412
+ .ywiki-content table,
413
+ .ywiki-content .doc-table {
414
+ --table-grid-color: var(--content-table-grid-color);
415
+ --table-header-bg: var(--content-table-header-bg);
416
+ border-collapse: separate;
417
+ border-spacing: 0;
418
+ /* 无显式列宽时按内容分配,避免说明列与短标签列被强制等分。
419
+ 有 colwidth 的表格仍通过两端共同的 colgroup + 表宽保留作者尺寸。 */
420
+ table-layout: auto;
421
+ width: 100%;
422
+ font-size: var(--content-table-font-size);
423
+ background: var(--color-surface);
424
+ border: 1px solid var(--table-grid-color);
425
+ border-radius: 6px;
426
+ overflow: hidden;
427
+ }
428
+ .ywiki-content :where(.doc-table-wrap, .tableWrapper) {
429
+ overflow-x: auto;
430
+ scrollbar-width: thin;
431
+ scrollbar-color: var(--color-border-strong) transparent;
432
+ }
433
+ .ywiki-content th,
434
+ .ywiki-content td {
435
+ border: none;
436
+ border-right: 1px solid var(--table-grid-color);
437
+ border-bottom: 1px solid var(--table-grid-color);
438
+ padding: 6px 8px;
439
+ line-height: var(--content-table-line-height);
440
+ min-width: 60px;
441
+ text-align: left;
442
+ vertical-align: top;
443
+ overflow-wrap: anywhere;
444
+ }
445
+ .ywiki-content th {
446
+ background: var(--table-header-bg);
447
+ color: var(--content-heading-color);
448
+ font-weight: 600;
449
+ }
450
+ .ywiki-content tr:last-child > :where(td, th) { border-bottom: none; }
451
+ .ywiki-content tr > :where(td, th):last-child { border-right: none; }
452
+ .ywiki-content tr:first-child > :where(td, th):first-child { border-top-left-radius: 5px; }
453
+ .ywiki-content tr:first-child > :where(td, th):last-child { border-top-right-radius: 5px; }
454
+ .ywiki-content tr:last-child > :where(td, th):first-child { border-bottom-left-radius: 5px; }
455
+ .ywiki-content tr:last-child > :where(td, th):last-child { border-bottom-right-radius: 5px; }
456
+
457
+ /* ---------------------------------------------------------------- 分割线 */
458
+ .ywiki-content hr {
459
+ border: none;
460
+ border-top: 1px solid var(--color-border);
461
+ }
462
+
463
+ /* ---------------------------------------------------------------- 图片 */
464
+ /* 图注(阅读端由 DocRenderer 渲染在图片下方) */
465
+ .ywiki-content .doc-image-caption {
466
+ margin-top: 6px;
467
+ color: var(--color-text-muted);
468
+ font-size: 12px;
469
+ line-height: 1.5;
470
+ text-align: center;
471
+ overflow: hidden;
472
+ text-overflow: ellipsis;
473
+ white-space: nowrap;
474
+ }
475
+ .ywiki-content .doc-image-gallery {
476
+ display: flex;
477
+ flex-wrap: wrap;
478
+ align-items: flex-start;
479
+ gap: 8px;
480
+ width: 100%;
481
+ }
482
+ .ywiki-content .doc-image-gallery > .doc-image[data-sized] {
483
+ /* 图库内的图由容器统一排布,忽略作者对单图设置的宽度。 */
484
+ margin-inline: 0;
485
+ }
486
+ /**
487
+ * 图片行:按比例铺满整行(与编辑态同一口径)。
488
+ *
489
+ * 列宽由 `flex-grow: 比例` 分配,高度由 `aspect-ratio` 自动产生,
490
+ * 因此同行几乎等高、右侧没有空白。
491
+ */
492
+ .ywiki-content .doc-image-gallery {
493
+ gap: 12px;
494
+ align-items: flex-start;
495
+ }
496
+ .ywiki-content .doc-image-gallery > .doc-image {
497
+ flex: 1 1 0;
498
+ min-width: 0;
499
+ width: auto;
500
+ height: auto;
501
+ max-width: none;
502
+ margin: 0;
503
+ aspect-ratio: var(--doc-image-aspect-ratio, 1.3333);
504
+ object-fit: contain;
505
+ /* 权重 = 原始比例 × 用户拖角设定的相对缩放 */
506
+ flex-grow: calc(var(--doc-image-aspect-ratio, 1) * var(--doc-image-weight, 1));
507
+ }
508
+ /**
509
+ * 带图注的图片在图片行里被一层 `<figure>` 包住,因此 **figure 才是 flex 子项**。
510
+ *
511
+ * 缺了这条规则时 figure 用默认 `flex: 0 1 auto`,按内部图片的固有宽度占位,
512
+ * 整行被挤成多行(实测两张 4:3 图变成上下两行、右侧留白),与"按比例铺满"
513
+ * 的口径不一致。变量由渲染器同时写到 figure 上(见 DocRenderer 的 galleryVars)。
514
+ */
515
+ .ywiki-content .doc-image-gallery > .doc-image-figure {
516
+ flex: 1 1 0;
517
+ min-width: 0;
518
+ margin: 0;
519
+ flex-grow: calc(var(--doc-image-aspect-ratio, 1) * var(--doc-image-weight, 1));
520
+ }
521
+ .ywiki-content .doc-image-gallery > .doc-image-figure > .doc-image {
522
+ /* 图注容器已按比例分到列宽,图片铺满容器即可。 */
523
+ width: 100%;
524
+ max-width: 100%;
525
+ margin: 0;
526
+ }
527
+ .ywiki-content .doc-image-gallery > .doc-image-figure > .doc-image-caption {
528
+ /* 行内已有 12px 列间距,图注不再额外缩进,跟随图片列宽。 */
529
+ margin-inline: 0;
530
+ }
531
+ .ywiki-content img,
532
+ .ywiki-content .doc-image {
533
+ display: block;
534
+ margin-inline: auto;
535
+ max-width: 100%;
536
+ height: auto;
537
+ border-radius: var(--content-media-radius);
538
+ }
539
+
540
+ /**
541
+ * 图片读取中:**渐变沿边框流动**的加载指示。
542
+ *
543
+ * ## 为什么不再用"整块灰底 + 微光"
544
+ *
545
+ * 静态灰块在浅色页面上几乎看不出是在加载,看起来更像"图丢了"或"这里是一块
546
+ * 空白"(用户多轮反馈)。改成一条沿边框奔跑的渐变——像贪吃蛇那样顺着圆角
547
+ * 绕圈,既明确表达"正在取",又不会往图片区域里填任何东西。
548
+ *
549
+ * ## 实现要点
550
+ *
551
+ * 1. **conic-gradient + 遮罩挖空**:整块铺一个锥形渐变,再用
552
+ * `mask-composite: exclude` 把中间挖掉,只留 2px 的一圈。
553
+ * `<img>` 是替换元素、`::before` 不渲染,所以不能像普通元素那样做双层。
554
+ * 2. **旋转靠 `@property` 注册角度变量**:conic-gradient 的 `from` 角度是离散值,
555
+ * 只有注册成 `<angle>` 类型才能被 `@keyframes` 平滑插值。不支持 `@property`
556
+ * 的浏览器会停在静态渐变上(仍有边框,只是不转)。
557
+ * 3. **加载完成时 `data-loading` 消失** → 遮罩一并移除,图片正常显示,
558
+ * 不会因为残留的 mask 把图片裁掉。
559
+ */
560
+ @property --ywiki-image-flow-angle {
561
+ syntax: '<angle>';
562
+ initial-value: 0deg;
563
+ inherits: false;
564
+ }
565
+
566
+ .ywiki-content .doc-image[data-loading] {
567
+ box-sizing: border-box;
568
+ /* 这 3px 就是"边框"的厚度:遮罩只保留它,中间透明 */
569
+ padding: 3px;
570
+ border-radius: var(--content-media-radius);
571
+ background-image: conic-gradient(
572
+ from var(--ywiki-image-flow-angle),
573
+ color-mix(in srgb, var(--color-accent) 14%, var(--color-surface-subtle)) 0turn 55%,
574
+ color-mix(in srgb, var(--color-accent) 55%, transparent) 78%,
575
+ var(--color-accent) 92%,
576
+ color-mix(in srgb, var(--color-accent) 14%, var(--color-surface-subtle)) 100%
577
+ );
578
+ -webkit-mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0);
579
+ -webkit-mask-clip: content-box, border-box;
580
+ -webkit-mask-composite: xor;
581
+ mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0);
582
+ mask-clip: content-box, border-box;
583
+ mask-composite: exclude;
584
+ animation: ywiki-image-flow 1.4s linear infinite;
585
+ /* 独立图片没有 aspect-ratio 可撑高:给一个最小高度,否则框不可见 */
586
+ min-height: 120px;
587
+ }
588
+ /* 图片行内的高度由 aspect-ratio 决定,不要再叠加最小高度(会把行撑高) */
589
+ .ywiki-content .doc-image-gallery > .doc-image[data-loading] {
590
+ min-height: 0;
591
+ }
592
+ @keyframes ywiki-image-flow {
593
+ to { --ywiki-image-flow-angle: 360deg; }
594
+ }
595
+ /**
596
+ * 加载失败:一条很淡的实线边框 + 极浅底色,**不流动**。
597
+ *
598
+ * 与"加载中"靠"有没有在转"区分:正在转 = 还在取,静止 = 取不到。不需要图标
599
+ * 或文字(它们在大块图片里比图片本身还抢眼,用户实测反馈更丑)。
600
+ * 不用虚线:虚线在缩略图上会碎成一段段,看起来像边框画错了。
601
+ */
602
+ .ywiki-content .doc-image[data-image-error] {
603
+ box-sizing: border-box;
604
+ min-height: 72px;
605
+ background-color: color-mix(in srgb, var(--color-surface-subtle) 70%, var(--color-border));
606
+ border-radius: var(--content-media-radius);
607
+ outline: 1px solid color-mix(in srgb, var(--color-border-strong) 55%, transparent);
608
+ outline-offset: -1px;
609
+ /*
610
+ * 破图图标不在这里处理:组件在失败时给 `<img>` 换上透明像素(见
611
+ * `LazyAttachmentImage` 的 `TRANSPARENT_PIXEL`)。CSS 侧的 `content: ''`、
612
+ * `text-indent`、`font-size: 0` 都盖不住浏览器为失败图片绘制的那个图标。
613
+ */
614
+ }
615
+ .ywiki-content .doc-image-gallery > .doc-image[data-image-error] {
616
+ min-height: 0;
617
+ }
618
+ @media (prefers-reduced-motion: reduce) {
619
+ /* 减少动效:保留渐变的光段,只是不再旋转 */
620
+ .ywiki-content .doc-image[data-loading] {
621
+ animation: none;
622
+ }
623
+ }
624
+
625
+ /*
626
+ * 作者显式缩放过的图片(data-sized):**左对齐**,宽度即作者设定值。
627
+ * 与编辑端同一口径(EditorPane 的 .ywiki-image-frame[data-sized]):
628
+ * 缩放锚点固定在左缘,编辑端与阅读端观感一致;未缩放的图仍居中。
629
+ */
630
+ .ywiki-content .doc-image[data-sized] {
631
+ margin-left: 0;
632
+ margin-right: auto;
633
+ }
634
+
635
+ /*
636
+ * 图片工具条设置的显式对齐(data-align)优先于上面的默认规则。
637
+ * 三端共用同一语义:编辑端用 flex 对齐容器,阅读端用 margin 对齐图片。
638
+ */
639
+ .ywiki-content .doc-image[data-align='left'] { margin-left: 0; margin-right: auto; }
640
+ .ywiki-content .doc-image[data-align='center'] { margin-left: auto; margin-right: auto; }
641
+ .ywiki-content .doc-image[data-align='right'] { margin-left: auto; margin-right: 0; }
642
+
643
+ /* ---------------------------------------------------------------- 链接与行内 chip */
644
+ .ywiki-content a,
645
+ .ywiki-content .doc-link {
646
+ color: var(--color-accent);
647
+ text-decoration: none;
648
+ }
649
+ .ywiki-content a:hover,
650
+ .ywiki-content .doc-link:hover { text-decoration: underline; }
651
+
652
+ /* 页面引用:蓝色文字 + 淡下划线。 */
653
+ .ywiki-content .doc-page-link {
654
+ color: var(--color-accent);
655
+ text-decoration: none;
656
+ border-bottom: 1px solid color-mix(in srgb, var(--color-accent) 40%, transparent);
657
+ }
658
+ .ywiki-content .doc-page-link:hover {
659
+ border-bottom-color: var(--color-accent);
660
+ text-decoration: none;
661
+ }
662
+ .ywiki-content .doc-page-link-plain { color: var(--color-text); }
663
+
664
+ /* @提及:蓝色药丸 */
665
+ .ywiki-content .doc-mention {
666
+ color: var(--color-accent);
667
+ background: var(--color-accent-soft);
668
+ border-radius: 4px;
669
+ padding: 0.05em 0.35em;
670
+ font-size: 0.95em;
671
+ font-weight: 500;
672
+ white-space: nowrap;
673
+ }
674
+
675
+ /* 文字高亮:无自定义颜色时的默认底色(自定义色走内联 style 覆盖) */
676
+ .ywiki-content mark,
677
+ .ywiki-content .doc-mark-highlight {
678
+ background: color-mix(in srgb, var(--color-warning) 30%, transparent);
679
+ border-radius: 2px;
680
+ padding: 0.05em 0.1em;
681
+ color: inherit;
682
+ }
683
+
684
+ /* ---------------------------------------------------------------- 分栏 */
685
+ .ywiki-content .doc-columns {
686
+ display: flex;
687
+ gap: 16px;
688
+ align-items: flex-start;
689
+ }
690
+ .ywiki-content .doc-column { flex: 1 1 0; min-width: 0; }
691
+ .ywiki-content .doc-column > *:first-child { margin-top: 0; }
692
+ @media (max-width: 560px) {
693
+ .ywiki-content .doc-columns { flex-direction: column; gap: 10px; }
694
+ }
695
+ @container wiki-content (max-width: 560px) {
696
+ .ywiki-content .doc-columns { flex-direction: column; gap: 10px; }
697
+ }
698
+
699
+ /* ---------------------------------------------------------------- 公式 */
700
+ .ywiki-content .doc-math-inline { display: inline-block; vertical-align: middle; }
701
+ .ywiki-content .doc-math-block {
702
+ display: block;
703
+ overflow-x: auto;
704
+ padding: 8px 0;
705
+ text-align: center;
706
+ }
707
+ .doc-math-pending {
708
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
709
+ font-size: 0.875em;
710
+ color: var(--color-text-muted);
711
+ }
712
+ .doc-math-error {
713
+ border: 1px dashed color-mix(in srgb, var(--color-danger) 50%, transparent);
714
+ border-radius: 4px;
715
+ padding: 0 4px;
716
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
717
+ font-size: 0.875em;
718
+ color: var(--color-danger);
719
+ }
720
+ .doc-math-error-hint { margin-left: 6px; font-size: 0.85em; opacity: 0.8; }
721
+
722
+ /* ---------------------------------------------------------------- 文件与媒体
723
+ 编辑 NodeView 与阅读卡片的结构类不同,盒模型与正文均由这一份样式提供。 */
724
+ .ywiki-content :where(.doc-file, .doc-file-attachment) {
725
+ border: 1px solid var(--color-border);
726
+ border-radius: 8px;
727
+ padding: 10px 12px;
728
+ background: var(--color-surface-subtle);
729
+ font-size: 14px;
730
+ color: var(--color-text-muted);
731
+ }
732
+ .ywiki-content .doc-file-head { display: flex; align-items: center; gap: 8px; }
733
+ .ywiki-content .doc-file-icon { flex: none; }
734
+ .ywiki-content .doc-file-name {
735
+ flex: 1;
736
+ min-width: 0;
737
+ overflow: hidden;
738
+ text-overflow: ellipsis;
739
+ white-space: nowrap;
740
+ }
741
+ .ywiki-content .doc-file-size { flex: none; font-size: 12px; color: var(--color-text-faint); }
742
+ .ywiki-content .doc-file-action {
743
+ flex: none;
744
+ border: 1px solid var(--color-border);
745
+ background: var(--color-surface);
746
+ border-radius: 6px;
747
+ padding: 2px 10px;
748
+ font-size: 12px;
749
+ color: var(--color-text-muted);
750
+ cursor: pointer;
751
+ }
752
+ .ywiki-content .doc-file-action:hover { color: var(--color-accent); border-color: var(--color-accent); }
753
+ .ywiki-content video.doc-file-video {
754
+ display: block;
755
+ width: 100%;
756
+ max-height: 420px;
757
+ margin-top: 8px;
758
+ border-radius: 6px;
759
+ background: #000;
760
+ }
761
+ .ywiki-content img.doc-file-image {
762
+ display: block;
763
+ max-width: 100%;
764
+ margin: 8px 0 0;
765
+ border-radius: 6px;
766
+ }
767
+
768
+ /* ---------------------------------------------------------------- 行内评论高亮
769
+ 编辑端与只读端共用同一套观感。
770
+
771
+ ## 同一黄色系三档,靠深浅表达强弱
772
+
773
+ 早先用 `--color-warning`(偏橙棕)叠 22%,是脏橘色、与正文高亮分不清;
774
+ 后来改淡米黄又太浅("看不到评论的选中区");再后来"有回复"用蓝色区分,
775
+ 用户反馈与黄色差别太大、容易误读成两类东西("可以搞多色,但是不要影响
776
+ 用户心智")。
777
+
778
+ 现在三档都在黄色家族里:普通评论亮黄底 + 深琥珀下划线,有回复加深一档,
779
+ 激活再深一档。下划线用深琥珀而不是亮黄——底色变亮后,浅色下划线在浅蓝
780
+ 或白色背景上都看不清(用户反馈"这个看不清,底部和背景色")。
781
+
782
+ ## 方角,不用圆角
783
+
784
+ `border-radius: 0`(用户明确要求)。标记是"文字底下的一条色带",
785
+ 圆角会让它在行内显得像按钮。
786
+
787
+ ## 提示不用原生 title
788
+
789
+ `title` 由浏览器绘制、样式不可控,这里由 `shared/comment-hint.ts` 自绘。 */
790
+ .ywiki-content .doc-inline-comment {
791
+ background: var(--comment-mark-bg, #ffe58f);
792
+ border-bottom: 2px solid var(--comment-mark-line, #d48806);
793
+ border-radius: 0;
794
+ /* 让底色与文字之间留一点空隙,读起来像"标记"而不是"文字被染色" */
795
+ padding-bottom: 1px;
796
+ cursor: pointer;
797
+ }
798
+ .ywiki-content .doc-inline-comment.has-replies {
799
+ background: var(--comment-mark-bg-reply, #ffd666);
800
+ border-bottom-color: var(--comment-mark-line-reply, #ad6800);
801
+ }
802
+ .ywiki-content .doc-inline-comment.is-active {
803
+ background: var(--comment-mark-bg-active, #ffc53d);
804
+ border-bottom-color: var(--comment-mark-line-active, #ad6800);
805
+ /* 激活项加一圈同色细边:与"有评论"区分开,一眼看出当前在看哪条 */
806
+ outline: 1px solid var(--comment-mark-line-active, #ad6800);
807
+ outline-offset: 1px;
808
+ }
809
+ /* 原文被改动:零宽落点用左侧竖线标记,避免伪装成正常高亮 */
810
+ .ywiki-content .doc-inline-comment.is-shifted {
811
+ border-left: 2px solid var(--color-danger);
812
+ padding-left: 1px;
813
+ background: transparent;
814
+ }
815
+
816
+ /* ---------------------------------------------------------------- 块流
817
+ 两端的结构路径放进 :where(),统一为 (0,1,0) 权重。规则放在元素 reset 之后,
818
+ 不以 !important 或逐个给 h/p 添加 class 来补偿 DOM 包装差异。
819
+ 引用、高亮块、分栏、单元格内部使用同一节奏,首尾不产生额外空白。 */
820
+ .ywiki-content > * + *,
821
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column, td, th) > * + * {
822
+ margin-top: var(--space-block);
823
+ }
824
+ .ywiki-content > :where(h1, h2, h3, h4, h5, h6),
825
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column, td, th) > :where(h1, h2, h3, h4, h5, h6) {
826
+ margin-top: var(--space-heading-top);
827
+ }
828
+ /* 标题与其后的内容是一组,连续标题也保持紧凑。 */
829
+ .ywiki-content > :where(h1, h2, h3, h4, h5, h6) + *,
830
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column, td, th) > :where(h1, h2, h3, h4, h5, h6) + * {
831
+ margin-top: var(--space-heading-bottom);
832
+ }
833
+ /* 待办项的 label 和内容容器横向排列,不在二者之间加纵向块间距。 */
834
+ /* TaskItem 的编辑 node view 没有 data-type,必须根据父 taskList 识别。 */
835
+ .ywiki-content :where(li:not(.doc-task-item):not(ul[data-type='taskList'] > li), li > div, li > span) > * + * {
836
+ margin-top: var(--space-list-block);
837
+ }
838
+ /* 结构模块与普通段落分开:两边都留模块间距,不能由短段距挤在一起。
839
+ 编辑 nodeView 与阅读包装分别列明,单元格最后再按其内部紧凑规则覆盖。 */
840
+ .ywiki-content > :where(ul, ol, blockquote, pre, table, img, .tableWrapper, .doc-table-wrap, .code-block-wrap, .doc-code-wrap, .ywiki-image-frame, .doc-image, .doc-callout, .doc-columns, .doc-file-attachment, .doc-file-video, .doc-video-embed, [data-video-embed], .doc-math-block, .math-block) ,
841
+ .ywiki-content > :where(ul, ol, blockquote, pre, table, img, .tableWrapper, .doc-table-wrap, .code-block-wrap, .doc-code-wrap, .ywiki-image-frame, .doc-image, .doc-callout, .doc-columns, .doc-file-attachment, .doc-file-video, .doc-video-embed, [data-video-embed], .doc-math-block, .math-block) + *,
842
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column) > :where(ul, ol, blockquote, pre, table, img, .tableWrapper, .doc-table-wrap, .code-block-wrap, .doc-code-wrap, .ywiki-image-frame, .doc-image, .doc-callout, .doc-columns, .doc-file-attachment, .doc-file-video, .doc-video-embed, [data-video-embed], .doc-math-block, .math-block),
843
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column) > :where(ul, ol, blockquote, pre, table, img, .tableWrapper, .doc-table-wrap, .code-block-wrap, .doc-code-wrap, .ywiki-image-frame, .doc-image, .doc-callout, .doc-columns, .doc-file-attachment, .doc-file-video, .doc-video-embed, [data-video-embed], .doc-math-block, .math-block) + * {
844
+ margin-top: var(--space-module);
845
+ }
846
+ /* 标题是章节边界;即使前面是表格、代码或媒体,也保留足够章节留白。 */
847
+ .ywiki-content > :where(h1, h2, h3, h4, h5, h6),
848
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column) > :where(h1, h2, h3, h4, h5, h6) {
849
+ margin-top: var(--space-heading-top);
850
+ }
851
+ .ywiki-content > :where(h1, h2, h3, h4, h5, h6) + *,
852
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column) > :where(h1, h2, h3, h4, h5, h6) + * {
853
+ margin-top: var(--space-heading-bottom);
854
+ }
855
+ .ywiki-content > hr,
856
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column, td, th) > hr {
857
+ margin-block: var(--space-divider);
858
+ }
859
+ .ywiki-content > :first-child,
860
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column, td, th, li, li > div, li > span) > :first-child {
861
+ margin-top: 0;
862
+ }
863
+ .ywiki-content > :last-child,
864
+ .ywiki-content :where(.doc-body, blockquote, .doc-callout-content, .doc-column, td, th, li, li > div, li > span) > :last-child {
865
+ margin-bottom: 0;
866
+ }
867
+
868
+ /* 文档表格有自己的紧凑节奏,仍保留作者输入的空段落与显式加粗。 */
869
+ .ywiki-content :where(td, th) > * + * { margin-top: 0.25em; }
870
+ .ywiki-content :where(td, th) > :first-child { margin-top: 0; }
871
+ .ywiki-content :where(td, th) > :where(p, ul, ol) { font-weight: inherit; }
872
+ .ywiki-content :where(td, th) > p:empty { min-height: calc(1em * var(--content-table-line-height)); }
873
+
874
+ /* 阅读端内容宽度交给 token(外观菜单可调) */
875
+ .doc-renderer {
876
+ width: 100%;
877
+ max-width: var(--content-width);
878
+ margin-inline: auto;
879
+ }
880
+
881
+ /* ---------------------------------------------------------------- 图片懒加载占位
882
+ 还没取到字节(接近视口时才取,见 LazyAttachmentImage):
883
+ 给一个最小占位高度,避免图片陆续到达时正文不断被顶下去。 */
884
+ .doc-image {
885
+ cursor: zoom-in;
886
+ }
887
+ .doc-image[data-loading] {
888
+ min-width: 160px;
889
+ min-height: 60px;
890
+ background: var(--color-surface-subtle);
891
+ border-radius: 8px;
892
+ }
893
+ .doc-image-loading,
894
+ .doc-image-missing,
895
+ .doc-unknown {
896
+ color: var(--color-text-muted);
897
+ font-size: 0.9em;
898
+ }
899
+ .doc-unknown {
900
+ border: 1px dashed var(--color-border-strong);
901
+ border-radius: 6px;
902
+ padding: 8px 10px;
903
+ }
904
+
905
+ /* 文件卡片的共同样式在 shared/content-style.css。 */
906
+ .doc-file.is-missing { color: var(--color-text-faint); }
907
+ /* 编辑态图片:src 由 node view 按 attachmentId 解析而来(正文不存存储地址)。
908
+ 给个最小样式,避免加载中/缺失时排版跳动。 */
909
+ .ywiki-prose img.ywiki-image {
910
+ max-width: 100%;
911
+ border-radius: var(--content-media-radius);
912
+ display: block;
913
+ }
914
+ /**
915
+ * 图片容器(node view)的**三层结构**:
916
+ * frame(块级、占满整行)→ 水平对齐(flex justify-content)
917
+ * inner(贴合图片尺寸)→ 选中框 / 四角手柄 / 块选中高亮
918
+ * img
919
+ *
920
+ * 选中框必须画在 **inner** 上(用户反馈"编辑图片大小时外框没有跟随图片
921
+ * 大小变化"):frame 占满整行,蓝框会横跨整行、右边空出一大片,看起来
922
+ * 像框没跟着图片走。
923
+ */
924
+ .ywiki-prose .ywiki-image-frame {
925
+ display: flex;
926
+ justify-content: center;
927
+ /* 图注在图片下方:纵向排列,图片仍按 justify-content 水平对齐 */
928
+ flex-direction: column;
929
+ align-items: center;
930
+ }
931
+ /* 有图注时,图片与图注各自成行;图片的水平对齐交给内层 */
932
+ .ywiki-prose .ywiki-image-frame.has-caption > .ywiki-image-inner { align-self: center; }
933
+ /* 图注:一行灰色小字,超出省略(完整内容见 title) */
934
+ .ywiki-prose .ywiki-image-caption {
935
+ max-width: 100%;
936
+ margin-top: 6px;
937
+ padding: 0 2px;
938
+ color: var(--color-text-muted);
939
+ font-size: 12px;
940
+ line-height: 1.5;
941
+ text-align: center;
942
+ overflow: hidden;
943
+ text-overflow: ellipsis;
944
+ white-space: nowrap;
945
+ user-select: text;
946
+ }
947
+ .ywiki-prose .ywiki-image-gallery {
948
+ display: flex;
949
+ flex-wrap: wrap;
950
+ align-items: flex-start;
951
+ gap: 8px;
952
+ width: 100%;
953
+ }
954
+ /**
955
+ * 图片行**整行选中**:给整行加一圈描边。
956
+ *
957
+ * 只给每张图铺底色是不够的——图片之间的间隙、行首行尾的留白都没有任何
958
+ * 选中信号,整行看起来和未选中几乎一样(用户实测反馈:"一行全选中也要有
959
+ * 选中效果")。
960
+ *
961
+ * 不能用普通块的 `::before` 蓝带:图片行是 flex 容器,绝对定位的伪元素
962
+ * 会参与 flex 布局计算,外扩的 6px 也容易被行高吃掉。改为与其它自带外观
963
+ * 的块一致的实色描边;圆角取 6px,与表格的选中框对齐。
964
+ */
965
+ .ywiki-prose .ywiki-image-gallery.is-block-selected {
966
+ outline: 2px solid var(--color-accent);
967
+ outline-offset: 2px;
968
+ border-radius: 6px;
969
+ }
970
+ /**
971
+ * 单张图片(独立图片块)被**整块选中**:给图片本身加一圈描边。
972
+ *
973
+ * 图片块没有自带外观,走的是"普通块铺蓝带"分支,结果只有一条半透明底色
974
+ * 与图片上的淡色覆盖,**没有边框**——与表格、高亮块、文件卡片的选中观感
975
+ * 不一致(用户实测反馈:"只有一张图的选中没有边框")。
976
+ *
977
+ * 只作用于独立图片(图片行内的子图不带 `is-block-selected`,整行选中时
978
+ * 描边画在行容器上),因此不会与图片行的整行框重叠。
979
+ */
980
+ .ywiki-prose .ywiki-image-frame.is-block-selected .ywiki-image-inner {
981
+ outline: 2px solid var(--color-accent);
982
+ outline-offset: 2px;
983
+ border-radius: 6px;
984
+ }
985
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame.is-in-gallery .ywiki-image-inner {
986
+ /* 图片行里不显示四角缩放手柄(等高排布,单图改宽会破坏对齐)。 */
987
+ cursor: default;
988
+ }
989
+ .ywiki-prose .ywiki-image-gallery {
990
+ position: relative;
991
+ }
992
+ /* 图片行内的框选矩形(挂在 portal 上,视口坐标定位) */
993
+ .ywiki-gallery-marquee {
994
+ position: fixed;
995
+ z-index: 69;
996
+ border: 1px solid color-mix(in srgb, var(--color-accent) 70%, transparent);
997
+ background: color-mix(in srgb, var(--color-accent) 12%, transparent);
998
+ border-radius: 2px;
999
+ pointer-events: none;
1000
+ }
1001
+ /**
1002
+ * 图片上的选中覆盖层:**只有一个 `::after`,强度固定 16%**。
1003
+ *
1004
+ * ## 为什么必须合并到一个选择器(用户实测:"为什么还有蓝色区域")
1005
+ *
1006
+ * 这里曾经有两处独立规则写同一个 `::after`:
1007
+ * - 框选命中(`.is-multi-picked`)16%;
1008
+ * - 整块选中(`.ywiki-image-frame.is-block-selected`)18%。
1009
+ *
1010
+ * 两者可以同时命中(框选后松手会转成块选区),于是同一个伪元素被两条规则
1011
+ * 分别赋值——后者胜出,颜色却与整页带(16%)不一致,图上出现一块更深的矩形。
1012
+ * 更早还叠过一层 frame 的 16% 背景,合计接近 50%。
1013
+ *
1014
+ * 现在统一为一条规则、一个强度:图片区域与非图片区域的选中底色完全相同。
1015
+ *
1016
+ * `outline` 仍按状态区分(框选中是实线、块选中不描边)——那表达的是"这是
1017
+ * 框选出来的"与"这块在选区里"的差别,不影响底色。
1018
+ */
1019
+ .ywiki-prose .ywiki-image-frame.is-multi-picked .ywiki-image-inner,
1020
+ .ywiki-prose .ywiki-image-frame.is-block-selected-image .ywiki-image-inner,
1021
+ .wendang-portal .ywiki-image-frame.is-multi-picked .ywiki-image-inner {
1022
+ /**
1023
+ * 圆角与表格/其他块的选中描边统一为 6px(用户反馈:"图片选中的圆角
1024
+ * 和表格选中的差不多,现在有点不一致")。早先是 3px/4px,混在一起时
1025
+ * 图片的框明显更方。
1026
+ */
1027
+ outline: 2px solid var(--color-accent);
1028
+ outline-offset: 2px;
1029
+ border-radius: 6px;
1030
+ }
1031
+ .ywiki-prose .is-block-selected .ywiki-image-inner::after,
1032
+ .ywiki-prose .ywiki-image-frame.is-multi-picked .ywiki-image-inner::after,
1033
+ .ywiki-prose .ywiki-image-frame.is-block-selected-image .ywiki-image-inner::after,
1034
+ .wendang-portal .ywiki-image-frame.is-multi-picked .ywiki-image-inner::after {
1035
+ content: '';
1036
+ position: absolute;
1037
+ inset: 0;
1038
+ border-radius: var(--content-media-radius, 4px);
1039
+ background: color-mix(in srgb, var(--color-accent) 16%, transparent);
1040
+ pointer-events: none;
1041
+ }
1042
+ /**
1043
+ * 跨图片拖拽:**落点提示**。
1044
+ *
1045
+ * ## 从"虚线框"改为"柔和的整体高亮"(用户反馈:虚线框看起来比较生硬)
1046
+ *
1047
+ * 原先落在目标图上画 2px dashed outline。虚线在照片这类复杂底图上会碎成
1048
+ * 一段段,而且"框住整张图"的观感太抢眼——它表达的是"我要插到这里",不是
1049
+ * "这张图被选中了",用户的原话是"看怎么处理更好看点"。
1050
+ *
1051
+ * 现在改成两层柔和的信号:
1052
+ * 1. 图片本身叠一层淡强调色(和块选中同一套语言,`::after` 已存在,复用);
1053
+ * 2. 外加一圈 2px 实线 + 3px 留白的描边,颜色是强调色但带透明度。
1054
+ *
1055
+ * 不用虚线、不用发光:拖拽是高频操作,提示需要"看得见但不吵"。
1056
+ */
1057
+ .ywiki-prose .ywiki-image-frame.is-image-drop-target .ywiki-image-inner {
1058
+ outline: 2px solid color-mix(in srgb, var(--color-accent) 70%, transparent);
1059
+ outline-offset: 3px;
1060
+ border-radius: var(--content-media-radius, 6px);
1061
+ }
1062
+ /* 落点图上再叠一层淡色,明确"松手就并到这里" */
1063
+ .ywiki-prose .ywiki-image-frame.is-image-drop-target .ywiki-image-inner::after {
1064
+ content: '';
1065
+ position: absolute;
1066
+ inset: 0;
1067
+ border-radius: var(--content-media-radius, 6px);
1068
+ background: color-mix(in srgb, var(--color-accent) 14%, transparent);
1069
+ pointer-events: none;
1070
+ }
1071
+
1072
+ /**
1073
+ * 插入指示线:一条**细长的圆头光带**,插在将要落入的位置。
1074
+ *
1075
+ * 几何与颜色都由脚本内联(挂在 portal / body 上取不到主题变量),这里只给
1076
+ * 形状与层级。圆头 + 柔和外发光让它看起来像"一根发光的针",比纯色方块轻。
1077
+ */
1078
+ .ywiki-image-drop-line,
1079
+ .ywiki-gallery-drop-line {
1080
+ position: fixed;
1081
+ border-radius: 999px;
1082
+ pointer-events: none;
1083
+ /* 必须高于图片行内容,否则会被图片盖住、看起来"拖拽没有反馈" */
1084
+ z-index: 70;
1085
+ }
1086
+ .ywiki-image-drop-line { z-index: 60; }
1087
+ /**
1088
+ * 指示线两端的小圆点:把"针"的两端收圆,视觉上更像刻度而不是一条色块。
1089
+ * 用伪元素而不是额外 DOM,避免拖拽期间频繁创建节点。
1090
+ */
1091
+ .ywiki-image-drop-line::before,
1092
+ .ywiki-image-drop-line::after,
1093
+ .ywiki-gallery-drop-line::before,
1094
+ .ywiki-gallery-drop-line::after {
1095
+ content: '';
1096
+ position: absolute;
1097
+ left: 50%;
1098
+ width: 7px;
1099
+ height: 7px;
1100
+ margin-left: -3.5px;
1101
+ border-radius: 50%;
1102
+ background: inherit;
1103
+ }
1104
+ .ywiki-image-drop-line::before,
1105
+ .ywiki-gallery-drop-line::before { top: -3px; }
1106
+ .ywiki-image-drop-line::after,
1107
+ .ywiki-gallery-drop-line::after { bottom: -3px; }
1108
+ .wendang-portal .ywiki-gallery-drop-line,
1109
+ .wendang-portal .ywiki-image-drop-line { position: fixed; }
1110
+ .ywiki-prose .ywiki-image-frame.is-gallery-dragging {
1111
+ opacity: 0.55;
1112
+ }
1113
+ /**
1114
+ * 图片行(飞书口径):**按比例铺满整行**,高度由比例自然产生。
1115
+ *
1116
+ * 为什么不用固定行高:固定行高在图片少时右侧留一大片空白(实测两图并排只占
1117
+ * 一半宽度)。飞书改成「各列按 比例/比例和 分宽度」——列宽加起来正好铺满,
1118
+ * 高度 = 可用宽 / 比例和,因此同行几乎等高且无空白。
1119
+ *
1120
+ * `--ywiki-image-ratio` 由 node view 按原图宽高比写入,`flex-basis` 用比例
1121
+ * 作为权重,`flex-grow` 让它们把剩余空间按权重分掉。
1122
+ */
1123
+ .ywiki-prose .ywiki-image-gallery {
1124
+ /* 12px 间距与飞书的 column-gap 实测一致 */
1125
+ gap: 12px;
1126
+ align-items: flex-start;
1127
+ }
1128
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame {
1129
+ flex: 1 1 0;
1130
+ /* 基础宽度置零,完全由 flex-grow 按比例分配,避免比例小的图先占位 */
1131
+ min-width: 0;
1132
+ width: auto;
1133
+ height: auto;
1134
+ max-width: none;
1135
+ justify-content: flex-start;
1136
+ }
1137
+ /* 分配权重 = 原始比例 × 用户拖角设定的相对缩放(`--ywiki-image-weight`) */
1138
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame {
1139
+ flex-grow: calc(var(--ywiki-image-ratio, 1) * var(--ywiki-image-weight, 1));
1140
+ }
1141
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame .ywiki-image-inner {
1142
+ width: 100%;
1143
+ max-width: none;
1144
+ }
1145
+ /**
1146
+ * 图库内图片高度由比例与列宽共同决定:
1147
+ * `width:100%` + `aspect-ratio` 让高度自动算出来,不用固定行高。
1148
+ * 没有 aspect-ratio(历史图片)时退回 4:3,等补算比例后再自动校正。
1149
+ */
1150
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame img.ywiki-image {
1151
+ width: 100%;
1152
+ height: auto;
1153
+ max-width: none;
1154
+ aspect-ratio: var(--ywiki-image-ratio, 1.3333);
1155
+ object-fit: contain;
1156
+ border-radius: var(--content-media-radius);
1157
+ }
1158
+ /**
1159
+ * 图片**加载中**:渐变沿边框流动的指示(与阅读端同一口径)。
1160
+ *
1161
+ * 不再用"整块灰底 + 微光"——静态灰块在浅色页面上看不出在加载,更像"图丢了"。
1162
+ * 现在是一条沿圆角绕圈的渐变,像贪吃蛇一样顺着边框跑,图片区域本身保持透明。
1163
+ *
1164
+ * 实现同阅读端:conic-gradient + `mask-composite: exclude` 挖空中间,只留 2px
1165
+ * 边框;旋转靠 `@property` 注册的角度变量插值(定义在 content-style.css,
1166
+ * 该文件也被编辑器引入)。加载完成后 `data-image-loading` 移除,遮罩随之消失。
1167
+ */
1168
+ .ywiki-prose .ywiki-image-frame img.ywiki-image[data-image-loading] {
1169
+ box-sizing: border-box;
1170
+ padding: 3px;
1171
+ border-radius: var(--content-media-radius);
1172
+ background-image: conic-gradient(
1173
+ from var(--ywiki-image-flow-angle),
1174
+ color-mix(in srgb, var(--color-accent) 14%, var(--color-surface-subtle)) 0turn 55%,
1175
+ color-mix(in srgb, var(--color-accent) 55%, transparent) 78%,
1176
+ var(--color-accent) 92%,
1177
+ color-mix(in srgb, var(--color-accent) 14%, var(--color-surface-subtle)) 100%
1178
+ );
1179
+ -webkit-mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0);
1180
+ -webkit-mask-clip: content-box, border-box;
1181
+ -webkit-mask-composite: xor;
1182
+ mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0);
1183
+ mask-clip: content-box, border-box;
1184
+ mask-composite: exclude;
1185
+ animation: ywiki-image-flow 1.4s linear infinite;
1186
+ /* 独立图片没有 aspect-ratio 撑高,需要最小高度才看得见框 */
1187
+ min-height: 120px;
1188
+ }
1189
+ /* 图片行内的高度由 aspect-ratio 与列宽决定,不叠加最小高度(否则整行被撑高) */
1190
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame img.ywiki-image[data-image-loading] {
1191
+ min-height: 0;
1192
+ }
1193
+ /**
1194
+ * 加载失败:淡底 + 细实线边框,**不流动**。
1195
+ *
1196
+ * "在转 = 还在取 / 静止 = 取不到",靠动效区分,不需要图标或文字。
1197
+ * 不用虚线:缩略图尺寸下虚线会碎成一段段,看起来像边框画错了。
1198
+ */
1199
+ .ywiki-prose .ywiki-image-frame img.ywiki-image[data-image-error] {
1200
+ box-sizing: border-box;
1201
+ min-height: 72px;
1202
+ background-color: color-mix(in srgb, var(--color-surface-subtle) 70%, var(--color-border));
1203
+ border-radius: var(--content-media-radius);
1204
+ outline: 1px solid color-mix(in srgb, var(--color-border-strong) 55%, transparent);
1205
+ outline-offset: -1px;
1206
+ }
1207
+ .ywiki-prose .ywiki-image-gallery > .ywiki-image-frame img.ywiki-image[data-image-error] {
1208
+ min-height: 0;
1209
+ }
1210
+ @media (prefers-reduced-motion: reduce) {
1211
+ .ywiki-prose .ywiki-image-frame img.ywiki-image[data-image-loading] {
1212
+ animation: none;
1213
+ }
1214
+ }
1215
+
1216
+ /* 显式缩放过(data-sized)的图默认靠左:缩放锚点在左缘,拖动位置稳定 */
1217
+ .ywiki-prose .ywiki-image-frame[data-sized] {
1218
+ justify-content: flex-start;
1219
+ }
1220
+ /* 显式对齐(图片工具条的左/中/右)优先于上面的默认规则 */
1221
+ .ywiki-prose .ywiki-image-frame[data-align='left'] { justify-content: flex-start; }
1222
+ .ywiki-prose .ywiki-image-frame[data-align='center'] { justify-content: center; }
1223
+ .ywiki-prose .ywiki-image-frame[data-align='right'] { justify-content: flex-end; }
1224
+
1225
+ /* inner 贴合图片:选中框/手柄相对它定位,才随图片尺寸变化 */
1226
+ .ywiki-prose .ywiki-image-inner {
1227
+ position: relative;
1228
+ display: inline-block;
1229
+ max-width: 100%;
1230
+ line-height: 0;
1231
+ }
1232
+ /* 缩放期间禁止选中文本:跟手拖动时若触发文字选区会打断手感 */
1233
+ .ywiki-prose .ywiki-image-frame.is-resizing {
1234
+ user-select: none;
1235
+ }
1236
+
1237
+ /**
1238
+ * 选中态(对齐飞书截图):蓝框 + 四角圆点手柄,拖动等比缩放。
1239
+ * 手柄只在"用户点过这张图"时显示(见 `.img-pick-active` 门控说明),
1240
+ * 未选中时 display:none,既不拦截点击也不产生视觉噪声。
1241
+ */
1242
+ /**
1243
+ * 四角手柄的尺寸与观感对齐飞书(实测飞书是 20×20 的命中区)。
1244
+ *
1245
+ * 早前是 10px 的小圆点:在 380px 宽的缩略图上几乎看不见,用户反馈
1246
+ * "选中了但看不清是不是选中了"(实测飞书明显更醒目)。这里放大到 14px
1247
+ * 的实心圆 + 2px 蓝描边 + 白色打底,并给整块加一圈白色外发光,
1248
+ * 保证在深色/蓝色图片上也能分辨。
1249
+ */
1250
+ .ywiki-prose .ywiki-image-handle {
1251
+ display: none;
1252
+ position: absolute;
1253
+ width: 14px;
1254
+ height: 14px;
1255
+ box-sizing: border-box;
1256
+ border: 2px solid var(--color-accent);
1257
+ border-radius: 50%;
1258
+ background: #fff;
1259
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
1260
+ z-index: 3;
1261
+ }
1262
+ /*
1263
+ * 选中外观需**同时**满足:node view 处于选中态,且用户点过这张图
1264
+ * (`.img-pick-active`)。只看前者会被 PM 的默认选区骗到——文档以图片
1265
+ * 开头时一打开页面就是 NodeSelection,不门控就会出现"没点过却带蓝框"。
1266
+ */
1267
+ .editor-shell.img-pick-active .ywiki-prose .ywiki-image-frame.is-selected .ywiki-image-inner {
1268
+ /**
1269
+ * 双层描边:内层蓝色实线 + 外层白色细线。
1270
+ *
1271
+ * 单用蓝色在蓝底图片上几乎看不出边界(用户反馈"看不清有没有选中");
1272
+ * 白色隔离带让边框在任何底图上都有对比,与飞书的观感一致。
1273
+ *
1274
+ * 圆角与表格/其它块的选中框统一为 6px(用户反馈"图片选中的圆角和表格
1275
+ * 选中的差不多,现在有点不一致"):早先这里是 4px,图片行的框是 3px,
1276
+ * 与表格的 6px 摆在一起时能明显看出差别。
1277
+ */
1278
+ outline: 2px solid var(--color-accent);
1279
+ outline-offset: 3px;
1280
+ border-radius: 6px;
1281
+ box-shadow: 0 0 0 5px #fff, 0 0 0 6px color-mix(in srgb, var(--color-accent) 28%, transparent);
1282
+ }
1283
+ .editor-shell.img-pick-active .ywiki-prose .ywiki-image-frame.is-selected .ywiki-image-handle {
1284
+ display: block;
1285
+ }
1286
+ /*
1287
+ * 图片行内**显示**四角手柄(对齐飞书):拖角调整该图的相对权重,
1288
+ * 整行按新权重重算,因此仍然铺满、仍然等高。
1289
+ * 唯一的例外是「整行处于块选区」时——那时拖动语义是移动整行,
1290
+ * 由行内重排逻辑让位给整块拖拽(见 image-nodeview 的 mousedown 判定)。
1291
+ */
1292
+ .editor-shell.img-pick-active .ywiki-prose .ywiki-image-frame.is-selected.is-in-gallery .ywiki-image-handle {
1293
+ display: block;
1294
+ }
1295
+ /* 图片行内仍画选中蓝框,但只包住被选中的那一张(inner 贴合图片) */
1296
+ .editor-shell.img-pick-active .ywiki-prose .ywiki-image-frame.is-selected.is-in-gallery .ywiki-image-inner {
1297
+ outline: 2px solid var(--color-accent);
1298
+ outline-offset: 3px;
1299
+ /* 与其它块/图片的选中框同一圆角 */
1300
+ border-radius: 6px;
1301
+ }
1302
+ /* 四个角:手柄中心骑在蓝框上(outline-offset 3px + 手柄半宽 7px = -10px) */
1303
+ .ywiki-prose .ywiki-image-handle.handle-nw { left: -10px; top: -10px; cursor: nwse-resize; }
1304
+ .ywiki-prose .ywiki-image-handle.handle-ne { right: -10px; top: -10px; cursor: nesw-resize; }
1305
+ .ywiki-prose .ywiki-image-handle.handle-sw { left: -10px; bottom: -10px; cursor: nesw-resize; }
1306
+ .ywiki-prose .ywiki-image-handle.handle-se { right: -10px; bottom: -10px; cursor: nwse-resize; }
1307
+
1308
+ /**
1309
+ * 已选中的图片:放大镜光标(点击再次 = 打开大图预览)。
1310
+ * 拖拽缩放期间必须让位给缩放光标——否则指针拖离手柄、落在图片上时
1311
+ * 会突然变成放大镜(用户实测反馈)。
1312
+ */
1313
+ .editor-shell.img-pick-active .ywiki-prose .ywiki-image-frame.is-selected:not(.is-resizing) img.ywiki-image {
1314
+ cursor: zoom-in;
1315
+ }
1316
+ .ywiki-prose img.ywiki-image[data-image-missing] {
1317
+ min-width: 120px;
1318
+ min-height: 40px;
1319
+ border: 1px dashed var(--color-border-strong);
1320
+ background: var(--color-surface-subtle);
1321
+ }
1322
+
1323
+ /**
1324
+ * 块级选中:普通块铺蓝底,**自带视觉身份的块只加外圈**。
1325
+ *
1326
+ * ## 两种画法,按块是否有自己的「脸」来分
1327
+ *
1328
+ * 飞书的做法(用户提供了对照截图)是一套区分得很清楚的规则:
1329
+ *
1330
+ * - **普通块**(段落、标题、列表、引用、图片…)——本来没有底色,选中时铺一条
1331
+ * 半透明蓝带,一眼能看出"这一段被选中了";
1332
+ * - **自带视觉身份的块**(高亮块、表格、代码块)——它们本来就有底色或边框,
1333
+ * 再往里铺一层蓝会把内容染色、把表格单元格弄脏。这些块只在**外围加一圈
1334
+ * 描边**,表达"这块在选区里",内容配色完全不动。
1335
+ *
1336
+ * 早先我一度把两类统一成蓝底,结果表格单元格被整片染蓝、高亮块的黄绿底色
1337
+ * 也被改掉——用户明确纠正:"像这类(高亮、表格等等)都可以有个外圈,不用蓝色
1338
+ * 背景"。
1339
+ *
1340
+ * ## 宽度只到正文列,不能铺到整页
1341
+ *
1342
+ * 曾经把带子向两侧溢出到"页面横带"边缘,那是把**可起手区域**和**高亮宽度**
1343
+ * 混为一谈了:起手区可以宽(用户在页面空白处按下就能拖选),但高亮必须只覆盖
1344
+ * 正文,否则左侧目录、右侧大纲栏也被染蓝(用户原话:"我内容区域在红框区域,
1345
+ * 为啥选中后有个这么宽的蓝色背景?不合理啊!")。
1346
+ *
1347
+ * ## 为什么普通块用伪元素而不是直接改 `background`
1348
+ *
1349
+ * 直接改背景会与块自身可能存在的底色冲突;伪元素能叠一层半透明,原底色仍透出。
1350
+ * 不能用 `z-index: -1`:那会让底色跑到祖先背景之后(`.tiptap` 是
1351
+ * `position: relative`),一旦宿主给正文加了底色,高亮就整块消失。
1352
+ */
1353
+ .ywiki-prose .is-block-selected {
1354
+ position: relative;
1355
+ border-radius: 6px;
1356
+ }
1357
+
1358
+ /**
1359
+ * 普通块:铺半透明蓝带。
1360
+ *
1361
+ * 排除自带视觉身份的块(见下方外圈分支)——这是两类画法的唯一分界。
1362
+ * 用 `[data-block-chrome]` 声明式判断,而不是硬枚举类名:新增块时只在自己的
1363
+ * 渲染代码里加属性即可,不必回来改这里(思维导图就曾因为漏改而错误地变成蓝底)。
1364
+ */
1365
+ .ywiki-prose .is-block-selected:not([data-block-chrome]):not(.doc-callout):not(.tableWrapper):not(.code-block-wrap):not(.ywiki-image-gallery)::before {
1366
+ content: '';
1367
+ position: absolute;
1368
+ /**
1369
+ * 四周比块本身**外扩**,让选中色不要紧贴文字(用户反馈"文字选中区域
1370
+ * 往外扩一下")。块盒子就是文字行盒,贴着它画会让文字看起来被框死。
1371
+ *
1372
+ * 纵向外扩量由 `measureBlocksPadding` 按**实测块间距**逐块写入:
1373
+ * - 相邻两个都选中:各溢出间隙的一半 → 两块拼成连续一条,且不重叠
1374
+ * (间隙实测 6.86px 到 21px 不等,写死一个值必然要么留白缝要么叠出深线);
1375
+ * - 开边一侧(首块上方 / 末块下方):用 `SELECT_PAD_Y` 给文字留呼吸空间。
1376
+ *
1377
+ * 横向用 `SELECT_PAD_X`:再宽就会溢出正文列(用户此前明确反对底色超出版心)。
1378
+ * 两侧同时外扩,因此带子比正文列宽 2×6px,仍落在阅读区留白内。
1379
+ */
1380
+ top: calc(-1 * var(--block-select-pad-top, 5px));
1381
+ bottom: calc(-1 * var(--block-select-pad-bottom, 5px));
1382
+ left: calc(-1 * var(--block-select-pad-x, 6px));
1383
+ right: calc(-1 * var(--block-select-pad-x, 6px));
1384
+ background: color-mix(in srgb, var(--color-accent) 16%, transparent);
1385
+ /* 6px 圆角:外扩后的矩形边角更明显,需要圆角才不生硬 */
1386
+ border-radius: 6px;
1387
+ pointer-events: none;
1388
+ }
1389
+
1390
+ /**
1391
+ * 自带视觉身份的块:**只加外圈,不铺蓝底**。
1392
+ *
1393
+ * ## 哪些块算"自带视觉身份"
1394
+ *
1395
+ * 判据是「它本身已经有可见的边框、底色或独立画布」。这类块再往里铺一层蓝,
1396
+ * 会把内容染色或把画布弄脏;只在外围加圈,既表达"在选区里",又不改内容观感:
1397
+ *
1398
+ * - 高亮块(浅色底 + 边框)
1399
+ * - 表格(网格线)
1400
+ * - 代码块(深色底)
1401
+ * - 思维导图(独立画布;用户实测:"为啥思维导图没有框而是蓝色")
1402
+ * - 文件卡片 / 视频嵌入(自带卡片外观)
1403
+ * - 分栏(多列结构,铺底色会把两栏之间的空隙也染上)
1404
+ *
1405
+ * 其余块(段落、标题、列表、引用、图片…)没有自己的外观,走蓝底分支。
1406
+ *
1407
+ * ## 为什么用 `[data-block-chrome]` 而不是继续堆类名选择器
1408
+ *
1409
+ * 之前是 `:is(.doc-callout, .tableWrapper, .code-block-wrap)` 硬枚举。每新增
1410
+ * 一种块都要改两处(`:not()` 与 `:is()`),漏一处就会退化成"这个块又变蓝了"——
1411
+ * 思维导图就是这么漏掉的。改为让节点自己在根元素上声明 `data-block-chrome`,
1412
+ * 新增块时只在自己的渲染代码里加一个属性,不必再来碰这里。
1413
+ *
1414
+ * `outline` 而不是 `border`:border 会参与盒模型,给一个已经撑满正文列宽度的
1415
+ * 表格加上 2px 边框会让它溢出或挤压内容;outline 不占布局,`outline-offset`
1416
+ * 还能让它落在块的外侧,正好是"外圈"的观感。
1417
+ *
1418
+ * 用 55% 而非更浅的透明度:高亮块是浅蓝底、代码块是深底、表格有网格线,
1419
+ * 太淡的圈在这些底色上都看不清边界。
1420
+ */
1421
+ .ywiki-prose :is([data-block-chrome], .doc-callout, .tableWrapper, .code-block-wrap).is-block-selected {
1422
+ /**
1423
+ * 描边圆角跟着**块自己的圆角**走,而不是写死 6px。
1424
+ *
1425
+ * 各块自带外观的圆角并不统一(高亮块 9px、文件卡片 8px、思维导图 12px),
1426
+ * 写死一个值就会出现"框的角比块本身的角更方"的错位观感(用户实测反馈:
1427
+ * "思维导图的选中圆角最好和选中带边框的圆角一致")。用变量按块类型覆盖,
1428
+ * 默认 6px 与表格一致。
1429
+ */
1430
+ --block-select-radius: 6px;
1431
+ /**
1432
+ * 实色而不是 55% 半透明:高亮块自带浅色底与彩色边框,半透明蓝圈叠在
1433
+ * 这些底色上几乎看不出来(用户反馈"高亮没有被选中、没有边框")。与图片
1434
+ * 选中的描边用同一个强度,所有块的"被选中"一眼可辨且观感一致。
1435
+ */
1436
+ outline: 2px solid var(--color-accent);
1437
+ outline-offset: 2px;
1438
+ /* 与铺色分支同一圆角,两种选中画的观感才统一 */
1439
+ border-radius: var(--block-select-radius);
1440
+ }
1441
+ /* 各块按自身外观的圆角覆盖描边圆角(值取自它们各自的 border-radius) */
1442
+ .ywiki-prose .doc-callout.is-block-selected { --block-select-radius: 9px; }
1443
+ .ywiki-prose .doc-file-attachment.is-block-selected { --block-select-radius: 8px; }
1444
+ .ywiki-prose [data-mind-map-node].is-block-selected { --block-select-radius: 12px; }
1445
+
1446
+ /* 块级拖拽期间:屏蔽浏览器原生的字形级选中高亮。
1447
+ 块级选择本质上是一个覆盖整块文字的文本选区(复制/删除需要它),
1448
+ 但浏览器会为它画字形级蓝底,与"整块底色"叠在一起很乱。
1449
+ 这里只影响绘制,不影响选区模型与复制行为。 */
1450
+ .ywiki-prose.is-block-selecting ::selection,
1451
+ .ywiki-prose.is-block-selecting *::selection {
1452
+ background: transparent;
1453
+ color: inherit;
1454
+ }
1455
+
1456
+ /**
1457
+ * 拖拽选择框(飞书式的矩形,跟随鼠标)。
1458
+ *
1459
+ * ## 必须**填充**,不能只描边(用户对比飞书截图后指出)
1460
+ *
1461
+ * 此前这里刻意只画边框、不铺底色,理由是"填充会盖住高亮块/表格的颜色"。
1462
+ * 但飞书的拖拽框本身就是一块**半透明蓝色矩形**,用户一眼就能判断"我现在框住
1463
+ * 了哪些内容、范围有多大";只有边框时,框内的内容看起来和框外没区别,
1464
+ * 拖动过程中几乎无法判断落点,这正是用户反馈的差异。
1465
+ *
1466
+ * 用极低的透明度(12%)解决当初的顾虑:底色仍然透得出来,不会把高亮色
1467
+ * 染成另一种颜色;框的边界由 1px 实线 + 白描边交代清楚。
1468
+ */
1469
+ .block-marquee {
1470
+ position: absolute;
1471
+ z-index: 33;
1472
+ pointer-events: none;
1473
+ /**
1474
+ * 宽高由插件按「按下点 → 当前指针」的拖拽矩形写入,边框必须算在尺寸内——
1475
+ * 否则 1px 边框会让框比鼠标实际划出的范围多出 2px(用户实测:左边贴合、
1476
+ * 右边多出一截)。
1477
+ */
1478
+ box-sizing: border-box;
1479
+ background: color-mix(in srgb, var(--color-accent) 12%, transparent);
1480
+ border: 1px solid color-mix(in srgb, var(--color-accent) 65%, transparent);
1481
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-surface) 60%, transparent);
1482
+ border-radius: 2px;
1483
+ }
1484
+
1485
+ /* ---------------------------------------------------------------- 表格交互样式 */
1486
+ /* 这几条此前完全缺失:resizable 生效但没有任何可视反馈,选中态也没有高亮,
1487
+ 导致"能拖列宽但看不出在哪拖、选中了格子也不知道"。 */
1488
+ /**
1489
+ * 列宽拖拽手柄。
1490
+ *
1491
+ * prosemirror-tables 为**每一行**各插一个 4px 宽的 widget,默认样式是强调色 +
1492
+ * 60% 透明度:鼠标经过列边界时它会在表格上竖着亮起一条分段蓝线,既没有
1493
+ * 拖拽反馈,也不像任何已知控件(用户反馈"表格里这个蓝色是什么?没什么用吧")。
1494
+ *
1495
+ * 改为两级语义:
1496
+ * - 悬停边界:中性色细线,连续贯穿整列(`top/bottom: -1px` 补齐行间缝隙),
1497
+ * 配合 `col-resize` 光标表达"这里可以拖";
1498
+ * - 真正拖拽中(单元格带 `column-resize-dragging`):才使用强调色。
1499
+ */
1500
+ .ywiki-prose .column-resize-handle {
1501
+ position: absolute;
1502
+ right: -2px;
1503
+ top: -4px;
1504
+ bottom: -4px;
1505
+ width: 3px;
1506
+ border-radius: 2px;
1507
+ background-color: var(--color-border-strong, #b9c3d2);
1508
+ pointer-events: none;
1509
+ }
1510
+ .ywiki-prose .column-resize-dragging .column-resize-handle {
1511
+ background-color: var(--color-accent, #2f6feb);
1512
+ box-shadow: 0 0 0 1px var(--color-surface, #fff);
1513
+ }
1514
+ .ywiki-prose.resize-cursor, .ywiki-prose .resize-cursor { cursor: col-resize; }
1515
+ /* 矩形选中的单元格 */
1516
+ .ywiki-prose .selectedCell:after {
1517
+ content: '';
1518
+ position: absolute;
1519
+ inset: 0;
1520
+ background: color-mix(in srgb, var(--color-accent) 8%, transparent);
1521
+ pointer-events: none;
1522
+ z-index: 2;
1523
+ }
1524
+ .ywiki-prose td,
1525
+ .ywiki-prose th {
1526
+ position: relative;
1527
+ }
1528
+ .img-preview-mask {
1529
+ position: fixed;
1530
+ inset: 0;
1531
+ z-index: 1300;
1532
+ display: flex;
1533
+ flex-direction: column;
1534
+ align-items: center;
1535
+ justify-content: center;
1536
+ background: color-mix(in srgb, #0b1220 84%, transparent);
1537
+ overflow: hidden;
1538
+ user-select: none;
1539
+ }
1540
+ .img-preview-stage {
1541
+ display: flex;
1542
+ align-items: center;
1543
+ justify-content: center;
1544
+ width: 100%;
1545
+ flex: 1;
1546
+ min-height: 0;
1547
+ padding: 32px;
1548
+ outline: none;
1549
+ }
1550
+ .img-preview-image {
1551
+ max-width: 100%;
1552
+ max-height: 100%;
1553
+ object-fit: contain;
1554
+ cursor: grab;
1555
+ transition: transform 0.12s ease-out;
1556
+ will-change: transform;
1557
+ }
1558
+ .img-preview-image.is-dragging { cursor: grabbing; transition: none; }
1559
+ .img-preview-toolbar {
1560
+ display: flex;
1561
+ align-items: center;
1562
+ gap: 4px;
1563
+ flex: none;
1564
+ margin-bottom: 24px;
1565
+ padding: 6px 8px;
1566
+ border: 1px solid color-mix(in srgb, #ffffff 18%, transparent);
1567
+ border-radius: 8px;
1568
+ background: color-mix(in srgb, #101828 72%, transparent);
1569
+ color: #f2f5fa;
1570
+ backdrop-filter: blur(8px);
1571
+ }
1572
+ .img-preview-toolbar button {
1573
+ min-width: 32px;
1574
+ height: 30px;
1575
+ padding: 0 8px;
1576
+ border: none;
1577
+ border-radius: 5px;
1578
+ background: transparent;
1579
+ color: inherit;
1580
+ font-family: inherit;
1581
+ font-size: 13px;
1582
+ cursor: pointer;
1583
+ }
1584
+ .img-preview-toolbar button:hover { background: color-mix(in srgb, #ffffff 16%, transparent); }
1585
+ .img-preview-toolbar button:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
1586
+ .img-preview-scale { min-width: 48px; text-align: center; font-size: 12px; opacity: 0.85; }
1587
+ .img-preview-count {
1588
+ min-width: 52px;
1589
+ padding: 0 6px;
1590
+ text-align: center;
1591
+ font-size: 12px;
1592
+ font-variant-numeric: tabular-nums;
1593
+ opacity: 0.85;
1594
+ }
1595
+ .img-preview-divider { width: 1px; height: 16px; margin: 0 4px; background: color-mix(in srgb, #ffffff 26%, transparent); }
1596
+
1597
+ /* 翻页按钮:两侧垂直居中,避开工具条;深色半透明底保证在任何图片上都可见 */
1598
+ .img-preview-nav {
1599
+ position: absolute;
1600
+ inset: 0;
1601
+ pointer-events: none;
1602
+ display: flex;
1603
+ align-items: center;
1604
+ justify-content: space-between;
1605
+ padding: 0 18px;
1606
+ }
1607
+ .img-preview-nav-btn {
1608
+ pointer-events: auto;
1609
+ display: flex;
1610
+ align-items: center;
1611
+ justify-content: center;
1612
+ width: 44px;
1613
+ height: 44px;
1614
+ padding: 0;
1615
+ border: 1px solid color-mix(in srgb, #ffffff 20%, transparent);
1616
+ border-radius: 50%;
1617
+ background: color-mix(in srgb, #101828 66%, transparent);
1618
+ color: #f2f5fa;
1619
+ cursor: pointer;
1620
+ backdrop-filter: blur(8px);
1621
+ transition: background 0.12s, opacity 0.12s;
1622
+ }
1623
+ .img-preview-nav-btn:hover:not(:disabled) { background: color-mix(in srgb, #101828 84%, transparent); }
1624
+ .img-preview-nav-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
1625
+ /* 到头的一侧保留占位(避免另一侧按钮跳动),只降到很低的可见度 */
1626
+ .img-preview-nav-btn:disabled { opacity: 0.22; cursor: default; }
1627
+
1628
+ @media (prefers-reduced-motion: reduce) {
1629
+ .img-preview-image { transition: none; }
1630
+ }
1631
+ .w-select { display: inline-flex; min-width: 0; }
1632
+ .w-select__trigger {
1633
+ display: inline-flex;
1634
+ align-items: center;
1635
+ justify-content: space-between;
1636
+ gap: 6px;
1637
+ width: 100%;
1638
+ min-width: 0;
1639
+ border: 1px solid var(--w-border-strong, var(--color-border-strong, #b9c3d2));
1640
+ border-radius: var(--w-radius-sm, 4px);
1641
+ background: var(--w-surface, var(--color-surface, #fff));
1642
+ color: var(--w-text, var(--color-text, #1f2937));
1643
+ font-family: var(--w-font-sans, inherit);
1644
+ cursor: pointer;
1645
+ transition: border-color var(--w-duration-fast, 0.12s);
1646
+ }
1647
+ .w-select--mini .w-select__trigger { height: var(--w-control-mini, 24px); padding: 0 6px; font-size: var(--w-font-size-mini, 12px); }
1648
+ .w-select--small .w-select__trigger { height: var(--w-control-small, 28px); padding: 0 8px; font-size: var(--w-font-size-small, 13px); }
1649
+ .w-select--medium .w-select__trigger { height: var(--w-control-medium, 32px); padding: 0 10px; font-size: var(--w-font-size-medium, 14px); }
1650
+ .w-select__trigger:hover { border-color: var(--w-accent, var(--color-accent, #2f6feb)); }
1651
+ .w-select__trigger:focus-visible { outline: 2px solid var(--w-accent, var(--color-accent, #2f6feb)); outline-offset: 1px; }
1652
+ .w-select__trigger:disabled { opacity: 0.5; cursor: not-allowed; }
1653
+ .w-select__label { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
1654
+ .w-select__label.is-placeholder { color: var(--w-text-faint, var(--color-text-faint, #7c8798)); }
1655
+ .w-select__caret { flex: none; opacity: 0.65; }
1656
+
1657
+ .w-select-panel { display: flex; flex-direction: column; min-width: 160px; max-width: min(320px, calc(100vw - 24px)); padding: 4px; }
1658
+ .w-select-panel .w-select-search {
1659
+ width: 100%;
1660
+ margin-bottom: 4px;
1661
+ padding: 5px 8px;
1662
+ border: 1px solid var(--w-border, var(--color-border, #dce2eb));
1663
+ border-radius: var(--w-radius-sm, 4px);
1664
+ background: var(--w-surface, var(--color-surface, #fff));
1665
+ color: var(--w-text, var(--color-text, #1f2937));
1666
+ font-size: var(--w-font-size-small, 13px);
1667
+ }
1668
+ .w-select-panel .w-select-search:focus { outline: 2px solid var(--w-accent, #2f6feb); outline-offset: -1px; }
1669
+ .w-select-list {
1670
+ display: flex;
1671
+ flex-direction: column;
1672
+ max-height: min(50vh, 320px);
1673
+ overflow-y: auto;
1674
+ overscroll-behavior: contain;
1675
+ scrollbar-width: thin;
1676
+ }
1677
+ .w-select-option {
1678
+ display: flex;
1679
+ align-items: center;
1680
+ box-sizing: border-box;
1681
+ min-height: 30px;
1682
+ padding: 6px 9px;
1683
+ border: none;
1684
+ border-radius: var(--w-radius-md, 6px);
1685
+ background: transparent;
1686
+ color: var(--w-text, var(--color-text, #1f2937));
1687
+ font-family: inherit;
1688
+ font-size: var(--w-font-size-small, 13px);
1689
+ text-align: left;
1690
+ cursor: pointer;
1691
+ }
1692
+ .w-select-option.is-active { background: var(--w-surface-subtle, var(--color-surface-subtle, #f5f7fa)); }
1693
+ .w-select-option.is-selected { color: var(--w-accent, var(--color-accent, #2f6feb)); background: var(--w-accent-soft, var(--color-accent-soft, #eaf1ff)); }
1694
+ .w-select-option:disabled { opacity: 0.45; cursor: not-allowed; }
1695
+ .w-select-empty { padding: 8px 9px; color: var(--w-text-faint, #7c8798); font-size: var(--w-font-size-small, 13px); }
1696
+ .w-dropdown {
1697
+ min-width: 160px;
1698
+ max-width: min(320px, calc(100vw - 24px));
1699
+ max-height: min(70vh, 520px);
1700
+ overflow-y: auto;
1701
+ overscroll-behavior: contain;
1702
+ padding: 4px;
1703
+ scrollbar-width: thin;
1704
+ scrollbar-color: color-mix(in srgb, var(--w-text-faint, #7c8798) 40%, transparent) transparent;
1705
+ }
1706
+ .w-dropdown::-webkit-scrollbar { width: 8px; }
1707
+ .w-dropdown::-webkit-scrollbar-thumb {
1708
+ border: 2px solid transparent;
1709
+ border-radius: 999px;
1710
+ background-clip: content-box;
1711
+ background-color: color-mix(in srgb, var(--w-text-faint, #7c8798) 36%, transparent);
1712
+ }
1713
+ .w-dropdown-option {
1714
+ display: flex;
1715
+ align-items: center;
1716
+ gap: 6px;
1717
+ box-sizing: border-box;
1718
+ min-height: 30px;
1719
+ padding: 6px 9px;
1720
+ border-radius: var(--w-radius-md, 6px);
1721
+ color: var(--w-text, var(--color-text, #1f2937));
1722
+ font-size: var(--w-font-size-small, 13px);
1723
+ line-height: 1.5;
1724
+ cursor: pointer;
1725
+ user-select: none;
1726
+ }
1727
+ .w-dropdown-option:hover,
1728
+ .w-dropdown-option:focus-visible {
1729
+ background: var(--w-surface-subtle, var(--color-surface-subtle, #f5f7fa));
1730
+ outline: none;
1731
+ }
1732
+ .w-dropdown-option.is-selected {
1733
+ color: var(--w-accent, var(--color-accent, #2f6feb));
1734
+ background: var(--w-accent-soft, var(--color-accent-soft, #eaf1ff));
1735
+ }
1736
+ .w-dropdown-option.is-disabled {
1737
+ opacity: 0.45;
1738
+ cursor: not-allowed;
1739
+ background: transparent;
1740
+ }
1741
+ .w-dropdown-group__title {
1742
+ padding: 6px 9px 3px;
1743
+ color: var(--w-text-faint, var(--color-text-faint, #7c8798));
1744
+ font-size: 11px;
1745
+ line-height: 1.5;
1746
+ }
1747
+ .w-dropdown-group + .w-dropdown-group {
1748
+ margin-top: 2px;
1749
+ padding-top: 3px;
1750
+ border-top: 1px solid var(--w-border, var(--color-border, #dce2eb));
1751
+ }
1752
+ .w-tooltip {
1753
+ padding: 5px 9px;
1754
+ border: 1px solid var(--w-border, var(--color-border, #dce2eb));
1755
+ border-radius: var(--w-radius-sm, 4px);
1756
+ background: var(--w-surface, var(--color-surface, #fff));
1757
+ color: var(--w-text, var(--color-text, #1f2937));
1758
+ font-size: var(--w-font-size-mini, 12px);
1759
+ line-height: 1.55;
1760
+ white-space: nowrap;
1761
+ box-shadow: var(--w-shadow-pop, 0 10px 32px #14284a20);
1762
+ }
1763
+ .wd-dialog-mask {
1764
+ position: fixed;
1765
+ inset: 0;
1766
+ z-index: 1100;
1767
+ display: flex;
1768
+ align-items: flex-start;
1769
+ justify-content: center;
1770
+ padding: 10vh 16px 24px;
1771
+ background: color-mix(in srgb, #101828 42%, transparent);
1772
+ overflow-y: auto;
1773
+ overscroll-behavior: contain;
1774
+ }
1775
+ .wd-dialog-mask.is-fullscreen { padding: 0; overflow: hidden; }
1776
+
1777
+ .wd-dialog {
1778
+ position: relative;
1779
+ display: flex;
1780
+ flex-direction: column;
1781
+ max-width: calc(100vw - 32px);
1782
+ max-height: calc(100dvh - 14vh);
1783
+ border: 1px solid var(--w-border, var(--color-border, #dce2eb));
1784
+ border-radius: var(--w-radius-lg, 8px);
1785
+ background: var(--w-surface, var(--color-surface, #fff));
1786
+ color: var(--w-text, var(--color-text, #1f2937));
1787
+ box-shadow: 0 24px 64px #10182833;
1788
+ outline: none;
1789
+ }
1790
+ .wd-dialog.is-fullscreen {
1791
+ width: 100vw;
1792
+ max-width: none;
1793
+ height: 100dvh;
1794
+ max-height: none;
1795
+ border: 0;
1796
+ border-radius: 0;
1797
+ }
1798
+
1799
+ .wd-dialog__header {
1800
+ display: flex;
1801
+ align-items: center;
1802
+ gap: 12px;
1803
+ flex: none;
1804
+ padding: 14px 18px;
1805
+ border-bottom: 1px solid var(--w-border, var(--color-border, #dce2eb));
1806
+ }
1807
+ .wd-dialog__title {
1808
+ flex: 1;
1809
+ min-width: 0;
1810
+ font-size: 16px;
1811
+ font-weight: 600;
1812
+ line-height: 1.4;
1813
+ }
1814
+ .wd-dialog__close {
1815
+ display: flex;
1816
+ align-items: center;
1817
+ justify-content: center;
1818
+ flex: none;
1819
+ width: 28px;
1820
+ height: 28px;
1821
+ padding: 0;
1822
+ border: none;
1823
+ border-radius: var(--w-radius-sm, 4px);
1824
+ background: transparent;
1825
+ color: var(--w-text-muted, var(--color-text-muted, #667085));
1826
+ cursor: pointer;
1827
+ }
1828
+ .wd-dialog__close:hover { background: var(--w-surface-subtle, #f5f7fa); color: var(--w-text, #1f2937); }
1829
+ .wd-dialog__close:focus-visible { outline: 2px solid var(--w-accent, #2f6feb); outline-offset: -2px; }
1830
+
1831
+ .wd-dialog__body {
1832
+ flex: 1;
1833
+ min-height: 0;
1834
+ overflow-y: auto;
1835
+ padding: 4px 25px 24px;
1836
+ line-height: 1.7;
1837
+ }
1838
+ .wd-dialog.is-fullscreen .wd-dialog__body {
1839
+ display: flex;
1840
+ flex-direction: column;
1841
+ overflow: hidden;
1842
+ padding: 0;
1843
+ }
1844
+
1845
+ .wd-dialog__footer {
1846
+ display: flex;
1847
+ justify-content: flex-end;
1848
+ align-items: center;
1849
+ gap: 8px;
1850
+ flex: none;
1851
+ padding: 0 25px 20px;
1852
+ }
1853
+
1854
+ @media (max-width: 520px) {
1855
+ .wd-dialog__body { padding: 4px 18px 20px; }
1856
+ .wd-dialog__footer { padding: 0 18px 16px; }
1857
+ }
1858
+ .mind-inline { height:100%; min-height:380px; }
1859
+ .mind-inline .mind-map-workspace { height:100%; padding:0; }
1860
+ .mind-canvas-title { display: inline-flex; align-items: center; gap: 14px; max-width: calc(100vw - 110px); }
1861
+ .mind-canvas-title > span { font-size: 13px; font-weight: 400; color: var(--color-text-muted); max-width: 65vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1862
+ /**
1863
+ * 全屏弹层的工作区。
1864
+ *
1865
+ * ## 为什么是 `height:100%` 而不是 `calc(100dvh - 110px)`
1866
+ *
1867
+ * 弹层里 `.wd-dialog__body` 已经是"header 以下的全部高度"(flex 列、无内边距),
1868
+ * 再把 header 高度写死成 110px 去减就是重复扣减:实际 header 只有 57px,
1869
+ * 于是画布底部多出 53px 空白,看起来"没到底"(用户实测:"底部可以进一点")。
1870
+ * 交给父容器决定高度,画布就能填满。
1871
+ *
1872
+ * ## 为什么四周要留内边距
1873
+ *
1874
+ * 全屏时 body 的内边距是 0,工具栏会紧贴 header 的下边线、画布也贴着窗口
1875
+ * 左右边缘(用户实测:"边框距离太近")。这里按工具栏在上、画布在下的顺序
1876
+ * 给一圈呼吸空间;inline(正文内嵌)形态不需要,单独复位为 0。
1877
+ */
1878
+ .mind-map-workspace { display: flex; flex-direction: column; height: 100%; min-height: 300px; box-sizing: border-box; padding: 16px 20px 20px; color: var(--color-text); }
1879
+ .mind-save-hint { margin-bottom: 10px; }
1880
+ .mind-canvas-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 0 10px; flex-wrap: wrap; }
1881
+ .mind-canvas-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
1882
+ .mind-canvas-options { justify-content: flex-end; margin-left: auto; }
1883
+ .mind-canvas-status { font-size: 12px; color: var(--color-text-muted); max-width: 32vw; }
1884
+ .mind-canvas-body { display: flex; flex: 1; min-height: 0; border: 1px solid var(--color-border); border-radius: 12px; overflow: hidden; }
1885
+ .mind-canvas-stage { position: relative; flex: 1; min-width: 0; overflow: hidden; outline: none; background: radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 22px 22px var(--color-surface); }
1886
+ .mind-canvas-stage.mind-grid-hidden { background-image:none; }
1887
+ .mind-canvas-surface { width:100%;height:100%; }
1888
+ .mind-canvas-stage .vue-flow__pane { cursor:default; }
1889
+ .mind-canvas-stage .vue-flow__selection,.mind-marquee { background:color-mix(in srgb,var(--mind-color) 8%,transparent);border:1px solid var(--mind-color);box-sizing:border-box;pointer-events:none; }
1890
+ .mind-marquee {position:absolute;z-index:4;}
1891
+ .mind-canvas-stage.mind-space-pan .vue-flow__pane,
1892
+ .mind-canvas-stage.mind-space-pan .vue-flow__node { cursor:grab; }
1893
+ .mind-canvas-stage .vue-flow__pane.dragging { cursor:grabbing; }
1894
+ .mind-selection-summary {position:absolute;left:16px;top:16px;display:flex;align-items:center;gap:10px;padding:6px 12px;border:1px solid var(--color-border);border-radius:9px;background:var(--color-surface);font-size:12px;}
1895
+ .mind-menu-key {margin-left:22px;float:right;color:var(--color-text-faint);font-size:11px;}
1896
+ .mind-canvas-outline { flex: 0 0 235px; overflow: auto; border-right: 1px solid var(--color-border); padding: 12px 4px; }
1897
+ .mind-canvas-outline button { display: block; border: 0; background: transparent; border-radius: 5px; width: 100%; text-align: left; padding: 7px 10px; color: var(--color-text-muted); white-space: pre-wrap; overflow-wrap: anywhere; }
1898
+ .mind-canvas-outline button.current { color: var(--mind-color); background: var(--color-surface-subtle); }
1899
+ .mind-node-actions { position: absolute; left: 16px; top: 16px; display: flex; flex-wrap: wrap; align-items: center; gap: 5px; border: 1px solid var(--color-border); padding: 6px; background: var(--color-surface); border-radius: 10px; box-shadow: 0 4px 20px #00000008; }
1900
+ .mind-canvas-bottom { position: absolute; bottom: 16px; left: 18px; right: 18px; display: flex; justify-content: space-between; align-items: end; gap: 10px; pointer-events: none; }
1901
+ .mind-canvas-hint { font-size: 11px; color: var(--color-text-faint); padding: 6px 0; }
1902
+ .mind-canvas-viewport { display: flex; align-items: center; gap: 6px; padding: 6px; border: 1px solid var(--color-border); border-radius: 9px; background: var(--color-surface); pointer-events: auto; white-space: nowrap; }
1903
+ .mind-viewport-divider { height:20px;border-left:1px solid var(--color-border);margin:0 2px; }
1904
+ .mind-zoom-percent { min-width:52px;font-variant-numeric:tabular-nums; }
1905
+ .mind-viewport-tip { display:flex;align-items:center;flex-wrap:wrap;gap:7px;max-width:min(480px,calc(100vw - 40px));font-size:12px;line-height:1.6; }
1906
+ .mind-viewport-tip kbd { padding:2px 6px;border-radius:4px;background:#ffffff20;font:inherit;white-space:nowrap; }
1907
+ .mind-canvas-notice { position: absolute; bottom: 70px; left: 50%; transform: translateX(-50%); padding: 8px 14px; margin: 0; border-radius: 7px; background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-text-muted); font-size: 12px; pointer-events: none; max-width: 90%; }
1908
+ .mind-canvas-stage .mind-drop-child { outline: 3px solid var(--mind-color); border-radius: 10px; }
1909
+ .mind-canvas-stage .mind-drop-left { box-shadow:-6px 0 0 0 var(--mind-color);border-radius:9px; }
1910
+ .mind-canvas-stage .mind-drop-right { box-shadow:6px 0 0 0 var(--mind-color);border-radius:9px; }
1911
+ .mind-canvas-stage .mind-drag-branch { opacity:.35; }
1912
+ .mind-canvas-stage .mind-drag-branch-edge { opacity:.12; }
1913
+ .mind-side-preview {position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;}
1914
+ .mind-side-preview path {fill:none;stroke:var(--mind-color);stroke-width:2;stroke-dasharray:6 4;}
1915
+ .mind-side-preview rect {fill:var(--color-surface);stroke:var(--mind-color);stroke-width:2;stroke-dasharray:5 3;}
1916
+ .mind-side-preview text {fill:var(--color-text);font-size:14px;}
1917
+ .mind-canvas-stage .mind-drop-before::before, .mind-canvas-stage .mind-drop-after::after { content: ''; position: absolute; left: -10px; right: -10px; height: 3px; background: var(--mind-color); }
1918
+ .mind-canvas-stage .mind-drop-before::before { top: -7px; }
1919
+ .mind-canvas-stage .mind-drop-after::after { bottom: -7px; }
1920
+ .mind-canvas-stage .vue-flow__edge-path { stroke: var(--mind-color); }
1921
+ @media (max-width: 760px) { .mind-canvas-outline { flex-basis: 170px; } .mind-canvas-hint { display: none; } .mind-canvas-toolbar { gap: 8px; } .mind-canvas-options { justify-content: flex-start; margin-left: 0; } .mind-node-actions { left: 8px; right: 8px; top: 8px; } .mind-canvas-status { max-width: 60vw; } }
1922
+ .mind-inline { height:100%; min-height:380px; }
1923
+ .mind-inline .mind-map-workspace { height:100%; }
1924
+ .mind-search { display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:6px 0 10px;font-size:12px; }
1925
+ .mind-search input {width:180px;font-size:12px;}
1926
+ .mind-outline-row {display:flex;align-items:center;margin:3px 0;}.mind-outline-row input {min-width:0;width:100%;border:0;background:transparent;font:12px/22px inherit;color:var(--color-text);padding:5px;}.mind-outline-row.current {background:var(--color-surface-subtle);}.mind-outline-row>button:last-child {width:24px;flex-shrink:0;padding:2px;}
1927
+ .mind-outline-row textarea{min-width:0;width:100%;border:0;background:transparent;font-size:12px;line-height:22px;color:var(--color-text);padding:5px;resize:none;border-radius:4px;}
1928
+ .mind-inline { height:100%; min-height:380px; }
1929
+ .mind-inline .mind-map-workspace { height:100%; }.mind-settings-menu{width:310px;display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px;font-size:12px;}.mind-settings-menu label{width:100%;display:flex;gap:8px;align-items:center;}.mind-settings-menu input{width:auto;}
1930
+ .mind-canvas-fullscreen {
1931
+ position: fixed !important;
1932
+ top: 0 !important;
1933
+ left: 0 !important;
1934
+ width: 100vw !important;
1935
+ height: 100dvh !important;
1936
+ max-width: none !important;
1937
+ }
1938
+ .mind-topic-shell { position: relative; width: 100%; height: 100%; }
1939
+ .mind-topic { position: relative; border-radius: 9px; background: var(--color-surface); color: var(--color-text); border: 1px solid color-mix(in srgb, var(--mind-color) 38%, var(--color-border)); padding: 10px 16px; font-family: inherit; font-size: 14px; line-height: 22px; display: grid; place-items: center; box-sizing: border-box; }
1940
+ .mind-topic.root { background: var(--mind-color); border-color: var(--mind-color); color: white; font-weight: 600; }
1941
+ .mind-topic.active { box-shadow: 0 0 0 3px color-mix(in srgb, var(--mind-color) 22%, transparent); }
1942
+ .mind-topic-label { width:100%;min-width:0;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-all;text-align:center;line-height:var(--mind-topic-line-height,22px); }
1943
+ .mind-topic-input { box-sizing:border-box;display:block;border:0;border-radius:4px;outline:0;padding:0;margin:0;width:100%;min-width:0;min-height:var(--mind-topic-line-height,22px);max-width:none;resize:none;overflow:hidden;white-space:pre-wrap;word-break:break-all;overflow-wrap:anywhere;background:transparent;color:inherit;font:inherit;line-height:var(--mind-topic-line-height,22px);text-align:center; }
1944
+ .mind-topic-input:focus { box-shadow: none; outline: 0; }
1945
+ .mind-topic-fold {
1946
+ position:absolute;left:calc(100% + 20px);top:calc(50% - 12px);width:24px;min-width:24px;height:24px;padding:0;
1947
+ display:grid;place-items:center;z-index:2;border-radius:50%;border:1px solid var(--mind-color);color:var(--mind-color);background:var(--color-surface);
1948
+ font:11px/1 sans-serif;cursor:pointer;opacity:0;pointer-events:none;transition:opacity .12s ease;
1949
+ }
1950
+ .mind-topic-shell:hover>.mind-topic-fold,.mind-topic-shell.is-selected>.mind-topic-fold,
1951
+ .mind-topic-shell:focus-within>.mind-topic-fold,.mind-topic-shell.is-collapsed>.mind-topic-fold {
1952
+ opacity:1;pointer-events:auto;
1953
+ }
1954
+ .mind-topic-fold:hover {background:color-mix(in srgb,var(--mind-color) 10%,var(--color-surface));}
1955
+ .mind-topic-fold:focus-visible {outline:2px solid var(--mind-color);outline-offset:3px;}
1956
+ .mind-fold-count {font-variant-numeric:tabular-nums;font-weight:600;}
1957
+ /* Keep the node and its connector in one hover region while moving toward the button. */
1958
+ .mind-topic-shell.has-children:not(.root)::before {content:'';position:absolute;left:100%;top:0;width:64px;height:100%;}
1959
+ .mind-topic-handle { opacity: 0; pointer-events: none; }
1960
+ .mind-topic-shell.grows-left .mind-topic-add { left: auto; right: calc(100% - 12px); }
1961
+ .mind-topic-shell .mind-topic-add.root-left {left:auto;right:calc(100% - 12px);}
1962
+ .mind-topic-shell .mind-topic-add.root-right {right:auto;left:calc(100% - 12px);}
1963
+ .mind-topic-shell.grows-left .mind-topic-fold {left:auto;right:calc(100% + 20px);}
1964
+ .mind-topic-shell.grows-left .mind-fold-chevron {transform:rotate(180deg);}
1965
+ .mind-topic-shell.grows-left.has-children:not(.root)::before {left:auto;right:100%;}
1966
+ .mind-topic-shell.grows-down .mind-topic-add { left: calc(50% - 12px); top: calc(100% - 12px); }
1967
+ .mind-topic-shell.grows-down .mind-topic-fold {right:auto;left:calc(50% - 12px);top:calc(100% + 18px);}
1968
+ .mind-topic-shell.grows-down .mind-fold-chevron {transform:rotate(90deg);}
1969
+ .mind-topic-shell.grows-down.has-children:not(.root)::before {left:0;right:auto;top:100%;width:100%;height:60px;}
1970
+ @media(hover:none){.mind-topic-fold{opacity:1;pointer-events:auto;}}
1971
+ .mind-topic-sibling {
1972
+ position: absolute; width: 24px; min-width: 24px; height: 24px; padding: 0;
1973
+ left: calc(50% - 12px); display: grid; place-items: center;
1974
+ border: 0; border-radius: 50%; background: transparent; color: white;
1975
+ cursor: pointer; z-index: 1;
1976
+ }
1977
+ .mind-topic-sibling.before { top: -22px; }
1978
+ .mind-topic-sibling.after { bottom: -22px; }
1979
+ .mind-topic-sibling > span {
1980
+ display: grid; place-items: center; width: 9px; height: 9px; border-radius: 50%;
1981
+ background: color-mix(in srgb, var(--mind-color) 36%, var(--color-surface)); font: 0/1 sans-serif;
1982
+ }
1983
+ .mind-topic-sibling:hover, .mind-topic-sibling:focus-visible { background: transparent; }
1984
+ .mind-topic-sibling:hover > span, .mind-topic-sibling:focus-visible > span {
1985
+ width: 20px; height: 20px; background: var(--mind-color); font-size: 16px;
1986
+ }
1987
+ .mind-topic-sibling:focus-visible { outline: 2px solid var(--mind-color); outline-offset: 1px; }
1988
+ .mind-topic-shell.grows-down .mind-topic-sibling { top: calc(50% - 12px); bottom: auto; }
1989
+ .mind-topic-shell.grows-down .mind-topic-sibling.before { left: -22px; }
1990
+ .mind-topic-shell.grows-down .mind-topic-sibling.after { left: auto; right: -22px; }
1991
+ .mind-topic-description { font-size:12px;line-height:18px;white-space:pre-wrap;color:var(--color-text-muted);width:100%;min-width:0;word-break:break-all;overflow-wrap:anywhere;margin-top:6px; }
1992
+ .root .mind-topic-description { color:#e7f4ff; }.mind-topic-image { width:100%;height:96px;overflow:hidden;margin-top:8px; }
1993
+ .mind-topic-image img {width:100%!important;height:96px!important;object-fit:contain;max-height:96px!important;margin:0!important;}
1994
+ .mind-topic-note { font-size:10px;line-height:14px;margin-top:6px;opacity:.7;cursor:pointer; }
1995
+ /**
1996
+ * 「添加子主题」按钮:骑在节点右缘(或左缘)上的圆形按钮。
1997
+ *
1998
+ * ## 为什么必须显式给全样式(用户实测:"按钮+太怪异了")
1999
+ *
2000
+ * 这里原来只写了尺寸与圆角,**没有背景、边框、字色**。`<button>` 的默认样式
2001
+ * 因此生效:浅灰方块底 + 深灰描边 + 系统字体,压在蓝色根节点上像一块补丁,
2002
+ * 与画布其余部分(圆角卡片、细线连接)完全不是一个语言。
2003
+ *
2004
+ * 现在按参考样式统一为:圆形、白底、细描边、居中「+」,悬停时染色并略微放大。
2005
+ * 用 `display:grid` 而不是 `line-height` 居中——后者在 24px 圆里对不齐。
2006
+ */
2007
+ .mind-topic-add {
2008
+ position: absolute;
2009
+ left: calc(100% - 12px);
2010
+ top: calc(50% - 12px);
2011
+ width: 24px;
2012
+ height: 24px;
2013
+ padding: 0;
2014
+ box-sizing: border-box;
2015
+ display: grid;
2016
+ place-items: center;
2017
+ border-radius: 50%;
2018
+ border: 1px solid color-mix(in srgb, var(--mind-color) 45%, var(--color-border));
2019
+ background: var(--color-surface);
2020
+ color: color-mix(in srgb, var(--mind-color) 82%, var(--color-text));
2021
+ font: 15px/1 system-ui, sans-serif;
2022
+ font-weight: 500;
2023
+ cursor: pointer;
2024
+ z-index: 3;
2025
+ box-shadow: 0 1px 3px rgb(15 23 42 / 12%);
2026
+ transition: background .12s ease, border-color .12s ease, transform .12s ease, box-shadow .12s ease;
2027
+ }
2028
+ /**
2029
+ * 悬停/聚焦:底色换成主题色的淡染,边界加深,轻微放大。
2030
+ *
2031
+ * 只改颜色而不改尺寸(除 transform)是关键:按钮骑在节点边缘,改 width/height
2032
+ * 会让它相对节点跳动;`transform: scale` 不参与布局,视觉放大而位置不动。
2033
+ */
2034
+ .mind-topic-add:hover,
2035
+ .mind-topic-add:focus-visible {
2036
+ background: color-mix(in srgb, var(--mind-color) 14%, var(--color-surface));
2037
+ border-color: var(--mind-color);
2038
+ color: var(--mind-color);
2039
+ transform: scale(1.12);
2040
+ box-shadow: 0 2px 6px rgb(15 23 42 / 18%);
2041
+ }
2042
+ .mind-topic-add:focus-visible { outline: 2px solid var(--mind-color); outline-offset: 2px; }
2043
+ .mind-topic-add:active { transform: scale(0.98); }
2044
+ /* 深色节点(根主题)上按钮是白底压在深蓝上:描边改用白色系,避免与底色混在一起 */
2045
+ .mind-topic-add.root-left,
2046
+ .mind-topic-add.root-right {
2047
+ border-color: color-mix(in srgb, var(--color-surface) 70%, transparent);
2048
+ }
2049
+ .mind-topic-icon { font-size:16px;line-height:20px; }.mind-topic[style*="border: 0"] { background:transparent; }
2050
+ .mind-preview-wrap {display:flex;align-items:center;justify-content:center;overflow:hidden;min-height:240px;}
2051
+ .mind-preview-sized {position:relative;flex-shrink:0;}.mind-preview-scene {position:relative;transform-origin:top left;}.mind-preview-lines {position:absolute;inset:0;}
2052
+ .mind-preview-topic {position:absolute;box-sizing:border-box;border:1px solid color-mix(in srgb,var(--mind-color) 35%,var(--color-border));border-radius:9px;background:var(--color-surface-subtle);color:var(--color-text);padding:10px 16px;display:flex;flex-direction:column;justify-content:center;line-height:22px;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-all;}
2053
+ .mind-preview-title{display:block;width:100%;min-width:0;}.mind-preview-icon{font-size:16px;line-height:20px;}
2054
+ .mind-preview-topic.root {background:var(--mind-color);color:white;font-weight:600;}.mind-preview-topic.text {border:0;background:transparent;}
2055
+ .mind-preview-description {font-size:12px;font-weight:400;line-height:18px;margin-top:6px;opacity:.72;}.mind-preview-note{font-size:10px;line-height:14px;margin-top:6px;opacity:.65;}
2056
+ .mind-preview-image{width:100%;height:96px;margin-top:8px;overflow:hidden;}.mind-preview-image img{width:100%!important;height:96px!important;object-fit:contain;margin:0!important;}
2057
+ .mind-map-block { margin: 20px 0; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); overflow: hidden; }
2058
+ .mind-map-block-header { min-height: 45px; display: flex; gap: 12px; align-items: center; justify-content: space-between; padding: 6px 12px; }
2059
+ .mind-map-block-label { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--color-text-muted); }
2060
+ .mind-map-block-label > span:first-child { color: var(--mind-color); font-size: 18px; }
2061
+ .mind-map-topic-count { font-size: 11px; color: var(--color-text-faint); }
2062
+ .mind-map-block-actions { display: flex; flex-shrink: 0; gap: 4px; }
2063
+ .mind-map-preview { width: 100%; display: block; min-height: 240px; cursor: zoom-in; }
2064
+ .mind-map-preview rect { fill: var(--color-surface-subtle); stroke: var(--mind-color); stroke-opacity: .3; }
2065
+ .mind-map-preview text { fill: var(--color-text); font-family: inherit; }
2066
+ .mind-map-preview .mind-map-root rect { fill: var(--mind-color); stroke: none; }
2067
+ .mind-map-preview .mind-map-root text { fill: white; }
2068
+ .mind-map-preview-outline { overflow: auto; padding: 16px 24px 24px; font-size: 14px; line-height: 2; white-space: pre-wrap; overflow-wrap: anywhere; }
2069
+ .mind-map-invalid { padding: 20px; color: var(--color-text-muted); }
2070
+ @media (max-width: 600px) { .mind-map-topic-count { display: none; } }
2071
+ .mind-details { flex: 0 0 280px; padding: 14px; border-left: 1px solid var(--color-border); overflow: auto; background: var(--color-surface); font-size: 12px; }
2072
+ .mind-details > header { display: flex; justify-content: space-between; align-items: center; }.mind-details-title { color: var(--color-text-muted); overflow-wrap:anywhere; }
2073
+ .mind-details fieldset { border: 0; border-top: 1px solid var(--color-border); padding: 12px 0; margin: 8px 0; display: flex; flex-direction:column; gap:8px; }
2074
+ .mind-details legend { font-weight:600; padding:0 8px 0 0; } .mind-details label { display:grid; grid-template-columns:70px minmax(0,1fr);align-items:center;gap:8px; }
2075
+ .mind-details input,.mind-details textarea { width:100%;font:inherit;box-sizing:border-box; } .mind-details textarea { resize:vertical; }.mind-format-buttons { display:flex;gap:6px; }
2076
+ .mind-relation-item { display:flex;align-items:center;gap:8px; }.mind-relation-item span { flex:1;overflow-wrap:anywhere; }
2077
+ .mind-color-grid {display:grid;grid-template-columns:repeat(8,24px);gap:4px;}.mind-color-grid>*{width:24px;min-width:24px;height:24px;padding:0;}
2078
+ .mind-comments {
2079
+ flex: 0 0 340px;
2080
+ display: flex;
2081
+ flex-direction: column;
2082
+ gap: 12px;
2083
+ min-height: 0;
2084
+ padding: 16px;
2085
+ overflow: auto;
2086
+ border-left: 1px solid var(--color-border);
2087
+ background: var(--color-surface, #fff);
2088
+ font-size: 13px;
2089
+ }
2090
+ .mind-comments__head {
2091
+ display: flex;
2092
+ align-items: flex-start;
2093
+ justify-content: space-between;
2094
+ gap: 8px;
2095
+ }
2096
+ .mind-comments__intro strong { font-size: 14px; }
2097
+ .mind-comments__intro p {
2098
+ margin: 4px 0 0;
2099
+ color: var(--color-text-muted);
2100
+ font-size: 12px;
2101
+ line-height: 1.6;
2102
+ }
2103
+ .mind-comments__head-actions { display: flex; flex: none; gap: 4px; }
2104
+ .mind-comments__error {
2105
+ margin: 0;
2106
+ padding: 8px 10px;
2107
+ border-radius: 6px;
2108
+ background: #fdecec;
2109
+ color: #b42b36;
2110
+ font-size: 12px;
2111
+ }
2112
+ .mind-comments__list { display: grid; gap: 10px; }
2113
+ .mind-comment {
2114
+ display: grid;
2115
+ gap: 8px;
2116
+ padding: 10px 12px;
2117
+ border: 1px solid var(--color-border);
2118
+ border-radius: 8px;
2119
+ }
2120
+ .mind-comment__head {
2121
+ display: flex;
2122
+ align-items: baseline;
2123
+ justify-content: space-between;
2124
+ gap: 8px;
2125
+ }
2126
+ .mind-comment__head span { color: var(--color-text-muted); font-size: 11px; }
2127
+ .mind-comment__body {
2128
+ margin: 0;
2129
+ white-space: pre-wrap;
2130
+ overflow-wrap: anywhere;
2131
+ line-height: 1.7;
2132
+ }
2133
+ .mind-comment__actions { display: flex; flex-wrap: wrap; gap: 4px; }
2134
+ .mind-comment__reply {
2135
+ display: grid;
2136
+ gap: 6px;
2137
+ margin-left: 12px;
2138
+ padding-left: 10px;
2139
+ border-left: 2px solid var(--color-border);
2140
+ }
2141
+ .mind-comment__label {
2142
+ color: var(--color-text-muted);
2143
+ font-size: 11px;
2144
+ font-weight: 600;
2145
+ }
2146
+ .mind-comment__compose { display: grid; gap: 6px; }
2147
+ .mind-comments__compose {
2148
+ display: grid;
2149
+ gap: 6px;
2150
+ padding-top: 12px;
2151
+ border-top: 1px solid var(--color-border);
2152
+ }
2153
+ .mind-comments__empty {
2154
+ margin: 0;
2155
+ color: var(--color-text-muted);
2156
+ font-size: 12px;
2157
+ line-height: 1.7;
2158
+ }
2159
+ .mind-comments textarea {
2160
+ width: 100%;
2161
+ padding: 8px 10px;
2162
+ border: 1px solid var(--color-border);
2163
+ border-radius: 6px;
2164
+ background: var(--color-surface, #fff);
2165
+ color: inherit;
2166
+ font: inherit;
2167
+ line-height: 1.6;
2168
+ box-sizing: border-box;
2169
+ resize: vertical;
2170
+ }
2171
+ .picker-backdrop {
2172
+ position: fixed;
2173
+ inset: 0;
2174
+ z-index: 1100;
2175
+ background: color-mix(in srgb, #000 45%, transparent);
2176
+ display: flex;
2177
+ align-items: flex-start;
2178
+ justify-content: center;
2179
+ padding-top: 12vh;
2180
+ }
2181
+ .picker-backdrop .picker {
2182
+ width: 420px;
2183
+ max-width: calc(100vw - 32px);
2184
+ background: var(--color-surface);
2185
+ border: 1px solid var(--color-border);
2186
+ border-radius: 10px;
2187
+ box-shadow: var(--shadow-pop);
2188
+ padding: 8px;
2189
+ }
2190
+ .picker-backdrop .picker .picker-input {
2191
+ width: 100%;
2192
+ box-sizing: border-box;
2193
+ border: 1px solid var(--color-border);
2194
+ border-radius: 6px;
2195
+ padding: 8px 10px;
2196
+ font-size: 14px;
2197
+ background: var(--color-surface-subtle);
2198
+ color: var(--color-text);
2199
+ }
2200
+ .picker-backdrop .picker-input:focus { outline: none; border-color: var(--color-accent); }
2201
+ .picker-backdrop .picker-list {
2202
+ list-style: none;
2203
+ margin: 6px 0 0;
2204
+ padding: 0;
2205
+ max-height: 320px;
2206
+ overflow-y: auto;
2207
+ }
2208
+ .picker-backdrop .picker-list li {
2209
+ padding: 7px 10px;
2210
+ border-radius: 6px;
2211
+ cursor: pointer;
2212
+ font-size: 14px;
2213
+ color: var(--color-text);
2214
+ }
2215
+ .picker-backdrop .picker-list li.active { background: var(--color-accent-soft); color: var(--color-accent); }
2216
+ .picker-backdrop .picker-title { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2217
+ .picker-backdrop .picker-empty { color: var(--color-text-faint); font-size: 13px; text-align: center; padding: 14px 0; margin: 0; }
2218
+ /*
2219
+ * 垂直节奏:字段内部 8px,字段之间 16px,最后一段之外留出 dialog body 的
2220
+ * 底部内边距。之前的提示文字紧贴输入框、又贴着按钮行,看起来像被截断。
2221
+ */
2222
+ .video-form { display: flex; flex-direction: column; gap: 16px; }
2223
+ .video-field { display: flex; flex-direction: column; gap: 8px; }
2224
+ .video-field label { font-size: 13px; font-weight: 600; color: var(--color-text); }
2225
+ .video-field input { width: 100%; }
2226
+ .video-hint {
2227
+ margin: 0;
2228
+ font-size: 12px;
2229
+ line-height: 1.7;
2230
+ color: var(--color-text-muted);
2231
+ }
2232
+ .video-status {
2233
+ margin: 0;
2234
+ padding: 8px 10px;
2235
+ border-radius: 6px;
2236
+ font-size: 12px;
2237
+ line-height: 1.7;
2238
+ }
2239
+ .video-status--ok {
2240
+ color: var(--color-text);
2241
+ background: var(--color-accent-soft);
2242
+ }
2243
+ .video-status--error {
2244
+ color: var(--color-danger);
2245
+ background: color-mix(in srgb, var(--color-danger) 8%, transparent);
2246
+ }
2247
+ .video-status-meta {
2248
+ margin-left: 4px;
2249
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
2250
+ color: var(--color-text-muted);
2251
+ }
2252
+ .video-source {
2253
+ margin: 0;
2254
+ font-size: 12px;
2255
+ line-height: 1.6;
2256
+ color: var(--color-text-muted);
2257
+ overflow-wrap: anywhere;
2258
+ }
2259
+ /*
2260
+ * `--color-hover` 从来没有被定义过:占位区背景整条声明在计算值阶段失效,
2261
+ * 只剩正文白底,看起来像一块空白矩形。改用确定存在的 `--color-surface-subtle`
2262
+ * 并给出绝对色兜底,非 SDK 宿主也能正常着色。
2263
+ */
2264
+ .doc-video-embed { width: 100%; min-width: 0; border: 1px solid var(--color-border, #dce2eb); border-radius: 8px; overflow: hidden; background: var(--color-surface, #fff); }
2265
+ .doc-video-embed .video-placeholder {
2266
+ min-height: 220px; padding: 28px 24px;
2267
+ display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
2268
+ background: var(--color-surface-subtle, #f5f7fa);
2269
+ }
2270
+ .doc-video-embed .video-play-icon {
2271
+ display: inline-flex; align-items: center; justify-content: center;
2272
+ width: 46px; height: 46px; margin-bottom: 2px; border-radius: 50%;
2273
+ color: var(--color-accent, #2f6feb);
2274
+ background: var(--color-accent-soft, #eaf1ff);
2275
+ font-size: 18px; line-height: 1; text-indent: 2px;
2276
+ }
2277
+ .doc-video-embed .video-placeholder strong { font-size: 14px; font-weight: 600; color: var(--color-text, #1f2937); }
2278
+ .doc-video-embed .video-id { font-size: 12px; color: var(--color-text-muted, #667085); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
2279
+ .doc-video-embed .video-load {
2280
+ margin-top: 4px; padding: 7px 20px;
2281
+ color: var(--color-accent, #2f6feb); background: var(--color-accent-soft, #eaf1ff);
2282
+ border: 0; border-radius: 6px; cursor: pointer; font: inherit; font-size: 13px;
2283
+ }
2284
+ .doc-video-embed .video-load:hover { background: color-mix(in srgb, var(--color-accent, #2f6feb) 16%, transparent); }
2285
+ .doc-video-embed iframe { display: block; width: 100%; aspect-ratio: 16 / 9; min-height: 200px; border: 0; background: #111; }
2286
+ .doc-video-embed .video-footer {
2287
+ display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px;
2288
+ padding: 10px 14px; font-size: 12px;
2289
+ border-top: 1px solid var(--color-border, #dce2eb);
2290
+ background: var(--color-surface, #fff);
2291
+ }
2292
+ .doc-video-embed .video-footer a { color: var(--color-accent, #2f6feb); }
2293
+ .doc-video-embed button:focus-visible, .doc-video-embed a:focus-visible { outline: 2px solid var(--color-accent, #2f6feb); outline-offset: 2px; }
2294
+ .doc-file-video { margin-top: 8px; }
2295
+ .doc-file-video video {
2296
+ width: 100%;
2297
+ max-height: 420px;
2298
+ border-radius: 6px;
2299
+ background: #000;
2300
+ }
2301
+ .doc-file-video-fallback {
2302
+ margin: 0;
2303
+ font-size: 13px;
2304
+ color: var(--color-text-faint);
2305
+ }
2306
+ .wendang-spreadsheet { position: relative; display: flex; flex-direction: column; height: 100%; min-height: 300px; min-width: 0; flex: 1; }
2307
+ .worksheet-grid { position: relative; flex: 1; min-width: 0; min-height: 0; overflow: hidden; }
2308
+ .wendang-spreadsheet > p { position: absolute; top: 8px; left: 12px; z-index: 2; }
2309
+
2310
+ /**
2311
+ * wui 设计令牌与 Vue 版 `wui/styles/tokens.css` 同源:组件自己的变量用 `--w-*`,
2312
+ * 颜色两级 fallback(宿主覆盖 → 主题变量 → 绝对色),因此深色模式无需第二套定义。
2313
+ */
2314
+ .wendang, .wendang-portal {
2315
+ --w-font-sans: var(--font-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif);
2316
+ --w-text: var(--color-text, #1f2937);
2317
+ --w-text-muted: var(--color-text-muted, #667085);
2318
+ --w-text-faint: var(--color-text-faint, #7c8798);
2319
+ --w-surface: var(--color-surface, #fff);
2320
+ --w-surface-subtle: var(--color-surface-subtle, #f5f7fa);
2321
+ --w-border: var(--color-border, #dce2eb);
2322
+ --w-border-strong: var(--color-border-strong, #b9c3d2);
2323
+ --w-accent: var(--color-accent, #2f6feb);
2324
+ --w-accent-soft: var(--color-accent-soft, #eaf1ff);
2325
+ --w-danger: var(--color-danger, #cf3d48);
2326
+ --w-success: var(--color-success, #238353);
2327
+ --w-warning: var(--color-warning, #b76e00);
2328
+ --w-shadow-pop: var(--shadow-pop, 0 10px 32px #14284a20);
2329
+ --w-font-size-mini: 12px; --w-font-size-small: 13px; --w-font-size-medium: 14px;
2330
+ --w-control-mini: 24px; --w-control-small: 28px; --w-control-medium: 32px;
2331
+ --w-radius-sm: 4px; --w-radius-md: 6px; --w-radius-lg: 8px;
2332
+ --w-duration-fast: .12s;
2333
+ }
2334
+ /* ---------------------------------------------------------------- WButton */
2335
+ .w-button {
2336
+ display:inline-flex;align-items:center;justify-content:center;gap:4px;flex:none;box-sizing:border-box;margin:0;
2337
+ border:1px solid transparent;border-radius:var(--w-radius-sm,4px);
2338
+ font-family:var(--w-font-sans,inherit);font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;
2339
+ transition:background-color var(--w-duration-fast,.12s),border-color var(--w-duration-fast,.12s),color var(--w-duration-fast,.12s);
2340
+ }
2341
+ .w-button--mini { height:var(--w-control-mini,24px);padding:0 8px;font-size:var(--w-font-size-mini,12px); }
2342
+ .w-button--small { height:var(--w-control-small,28px);padding:0 10px;font-size:var(--w-font-size-small,13px); }
2343
+ .w-button--medium { height:var(--w-control-medium,32px);padding:0 12px;font-size:var(--w-font-size-medium,14px); }
2344
+ .w-button--narrow { padding-inline:0; }.w-button--block { display:flex;width:100%; }
2345
+ .w-button--default { background:var(--w-surface-subtle,var(--color-surface-subtle,#f5f7fa));border-color:var(--w-border-strong,var(--color-border-strong,#b9c3d2));color:var(--w-text,var(--color-text,#1f2937)); }
2346
+ .w-button--default:not(:disabled):hover { background:color-mix(in srgb,var(--w-accent,#2f6feb) 7%,var(--w-surface-subtle,#f5f7fa));border-color:var(--w-accent,var(--color-accent,#2f6feb));color:var(--w-accent,var(--color-accent,#2f6feb)); }
2347
+ .w-button--text { background:transparent;border-color:transparent;color:var(--w-text,var(--color-text,#1f2937)); }
2348
+ .w-button--text:not(:disabled):hover { background:color-mix(in srgb,currentColor 10%,transparent);color:var(--w-text,var(--color-text,#1f2937)); }
2349
+ .w-button--primary { background:var(--w-accent,var(--color-accent,#2f6feb));border-color:var(--w-accent,var(--color-accent,#2f6feb));color:#fff; }
2350
+ .w-button--primary:not(:disabled):hover { background:color-mix(in srgb,var(--w-accent,#2f6feb) 88%,#000);border-color:color-mix(in srgb,var(--w-accent,#2f6feb) 88%,#000); }
2351
+ .w-button--outline { background:transparent;border-color:var(--w-border,var(--color-border,#dce2eb));color:var(--w-text,var(--color-text,#1f2937)); }
2352
+ .w-button--outline:not(:disabled):hover { border-color:var(--w-accent,var(--color-accent,#2f6feb));color:var(--w-accent,var(--color-accent,#2f6feb)); }
2353
+ .w-button:disabled { opacity:.5;cursor:not-allowed; }.w-button.is-loading { cursor:progress;opacity:.75; }
2354
+ .w-button[aria-pressed=true] { background:var(--w-accent-soft,var(--color-accent-soft,#eaf1ff));border-color:var(--w-accent,var(--color-accent,#2f6feb));color:var(--w-accent,var(--color-accent,#2f6feb)); }
2355
+ .w-button__icon,.w-button__spinner { display:inline-flex;align-items:center;justify-content:center;flex:none; }
2356
+ .w-button__label { display:inline-flex;align-items:center;gap:4px; }.w-button__label > svg,.w-button__label > .wr-icon { flex:none; }
2357
+ .w-button__spinner svg { animation:w-button-spin .8s linear infinite; }
2358
+ @keyframes w-button-spin { to { transform:rotate(360deg); } }
2359
+ .w-button:focus-visible { outline:2px solid var(--w-accent,var(--color-accent,#2f6feb));outline-offset:1px; }
2360
+ /* ---------------------------------------------------------------- WAlert */
2361
+ .w-alert { display:flex;align-items:flex-start;gap:10px;padding:7px 10px;border:1px solid var(--w-border,var(--color-border));border-radius:var(--w-radius-md,6px);background:var(--w-accent-soft,var(--color-accent-soft));color:var(--w-text,var(--color-text));font-size:12px;margin-bottom:10px;flex:none;line-height:1.5; }
2362
+ .w-alert__icon { flex:none;line-height:1.5; }.w-alert__body { flex:1;min-width:0; }
2363
+ .w-alert--warning { background:color-mix(in srgb,var(--w-warning,#b76e00) 12%,var(--w-surface,#fff));border-color:color-mix(in srgb,var(--w-warning,#b76e00) 35%,var(--w-border,#dce2eb)); }
2364
+ .w-alert--danger { background:color-mix(in srgb,var(--w-danger,#cf3d48) 10%,var(--w-surface,#fff));border-color:color-mix(in srgb,var(--w-danger,#cf3d48) 32%,var(--w-border,#dce2eb)); }
2365
+ .w-alert--success { background:color-mix(in srgb,var(--w-success,#238353) 10%,var(--w-surface,#fff));border-color:color-mix(in srgb,var(--w-success,#238353) 32%,var(--w-border,#dce2eb)); }
2366
+ /* ---------------------------------------------------------------- WPopover */
2367
+ .w-popover { position:fixed;z-index:1400;max-width:min(320px,calc(100vw - 24px));max-height:min(70vh,520px);overflow:auto;min-width:160px;padding:4px;display:flex;flex-direction:column;gap:4px;background:var(--w-surface,var(--color-surface,#fff));border:1px solid var(--w-border,var(--color-border));border-radius:var(--w-radius-lg,8px);box-shadow:var(--w-shadow-pop);color:var(--w-text,var(--color-text)); }
2368
+ .w-popover .w-button { justify-content:flex-start;text-align:left;width:100%; }
2369
+ /* 内容自带内边距的面板(高亮块图标/颜色)不再叠加外层 padding。 */
2370
+ .w-popover--flush { padding:0; }
2371
+ .w-popover .wr-settings .w-button { width:auto; }
2372
+ .w-popover-group { padding:6px 8px 2px; font-size:11px; color:var(--color-text-faint); }
2373
+ /* ---------------------------------------------------------------- WDialog */
2374
+ .w-dialog-mask { position:fixed;inset:0;z-index:1100;display:flex;align-items:flex-start;justify-content:center;padding:10vh 16px 24px;background:color-mix(in srgb,#101828 42%,transparent);overflow-y:auto;overscroll-behavior:contain;box-sizing:border-box; }
2375
+ .w-dialog-mask.is-fullscreen { padding:0;overflow:hidden; }
2376
+ .w-dialog { position:relative;display:flex;flex-direction:column;width:520px;max-width:calc(100vw - 32px);max-height:calc(100dvh - 14vh);border:1px solid var(--w-border,var(--color-border,#dce2eb));border-radius:var(--w-radius-lg,8px);background:var(--w-surface,var(--color-surface,#fff));color:var(--w-text,var(--color-text,#1f2937));box-shadow:0 24px 64px #10182833;outline:none;box-sizing:border-box; }
2377
+ .w-dialog.is-fullscreen { width:100vw;max-width:none;height:100dvh;max-height:none;border:0;border-radius:0; }
2378
+ .w-dialog__header { display:flex;align-items:center;gap:12px;flex:none;padding:14px 18px 10px; }
2379
+ .w-dialog__title { flex:1;min-width:0;font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
2380
+ .w-dialog__close { flex:none;display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--w-radius-md,6px);background:transparent;color:var(--w-text-muted,var(--color-text-muted));cursor:pointer; }
2381
+ .w-dialog__close:hover { background:var(--w-surface-subtle,#f5f7fa);color:var(--w-text,#1f2937); }
2382
+ .w-dialog__body { flex:1;min-height:0;padding:4px 18px 18px;overflow:auto;display:flex;flex-direction:column;gap:12px; }
2383
+ .w-dialog.is-fullscreen .w-dialog__body { padding:0;overflow:hidden; }
2384
+ .w-dialog__footer { flex:none;display:flex;justify-content:flex-end;gap:8px;padding:0 18px 16px; }
2385
+ .video-dialog {width:min(520px,calc(100vw - 32px));}
2386
+ .w-dialog label,.wr-mind-panel label { display:flex;flex-direction:column;gap:6px;font-size:13px;margin-bottom:10px; }
2387
+ .w-dialog input,.w-dialog textarea,.wr-mind-panel textarea { width:100%;box-sizing:border-box; }
2388
+ .wr-toolbar { display:flex;align-items:center;gap:8px;flex-wrap:wrap; }
2389
+ .wr-icon { display:block;flex:none; }
2390
+ /**
2391
+ * 编辑端外壳:**不加边框、不留左侧 padding**。
2392
+ *
2393
+ * 块快捷条、「+」和表格入口画在正文左缘之外,需要约 56px 留白;但这段留白
2394
+ * 必须由宿主提供(页面栏宽、文档容器 padding 等)。SDK 自己加 padding 会把
2395
+ * 正文整体右移,而宿主的页头/目录不会跟着动,整篇内容看起来就是歪的。
2396
+ * 宿主没留够时,`blockAffordanceStyle` 会把控件夹进视口作为兜底。
2397
+ */
2398
+ .wr-document { position:relative;min-height:160px; }
2399
+ .wr-document-mount { min-width:0; }
2400
+ .wr-document .editor-canvas { outline:none;width:100%;max-width:var(--content-width);min-height:60vh;margin-inline:auto;padding-bottom:calc(var(--content-font-size,16px) * var(--content-line-height,1.75) + var(--space-block,12px)); }
2401
+ .wr-document-toolbar { margin-bottom:10px; }
2402
+ /* 块左侧入口:与 Vue 版共用一条 8px 间距的竖轨。 */
2403
+ /* 块左侧入口:与 Vue 的 EditorPane / BlockHandleMenu 同一套类名与尺寸。 */
2404
+ .block-plus { position:absolute; z-index:31; width:28px; height:28px; display:flex; align-items:center; justify-content:center; border:1px solid var(--color-border); border-radius:5px; background:var(--color-surface); color:var(--color-text-muted); cursor:pointer; padding:0; transition:background .12s,border-color .12s; }
2405
+ .block-plus:hover { color:var(--color-accent); border-color:var(--color-accent); background:var(--color-accent-soft); }
2406
+ .block-chip { position:absolute; z-index:31; display:flex; align-items:center; width:48px; height:28px; box-sizing:border-box; padding:1px; border:1px solid var(--color-border); border-radius:6px; background:var(--color-surface); transition:border-color .12s; }
2407
+ .block-chip:hover { border-color:var(--color-accent); }
2408
+ .chip-btn { width:22px; height:24px; display:flex; align-items:center; justify-content:center; border:none; background:transparent; color:var(--color-accent); cursor:pointer; padding:0; border-radius:3px; }
2409
+ .chip-btn:hover { color:var(--color-accent); background:var(--color-accent-soft); }
2410
+ .chip-grip { cursor:grab; color:var(--color-text-faint); }
2411
+ .chip-grip:active { cursor:grabbing; }
2412
+ /* 块菜单:主清单 + 右侧子菜单(结构、宽度、间距与 Vue 的 BlockHandleMenu 一致)。 */
2413
+ .block-anchor { position:absolute; z-index:45; overflow-anchor:none; display:flex; align-items:flex-start; gap:4px; pointer-events:auto; }
2414
+ .block-menu { width:208px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); padding:4px; }
2415
+ .bm-item { display:flex; align-items:center; gap:8px; width:100%; padding:6px 8px; border:0; border-radius:6px; background:transparent; cursor:pointer; font-size:13px; font-family:inherit; color:var(--color-text); text-align:left; }
2416
+ .bm-item:hover { background:var(--color-surface-subtle); }
2417
+ .bm-item:focus-visible { outline:2px solid var(--color-accent); outline-offset:-2px; }
2418
+ .bm-item.active { color:var(--color-accent); }
2419
+ .bm-item.disabled { opacity:.45; pointer-events:none; }
2420
+ .bm-item.danger { color:var(--color-danger); }
2421
+ .bm-item span:first-of-type { flex:1; }
2422
+ .bm-chevron { margin-left:auto; opacity:.5; }
2423
+ .bm-sep { height:1px; background:var(--color-border); margin:4px 6px; }
2424
+ .block-submenu { position:relative; width:208px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); padding:4px; max-height:calc(60vh - 10px); overflow:auto; }
2425
+ .block-submenu-color { width:max-content; padding:12px; }
2426
+ /* 文档颜色面板(块菜单与文字工具栏共用同一套版式)。 */
2427
+ .document-color-panel { width:220px; display:flex; flex-direction:column; gap:12px; }
2428
+ .color-section { display:flex; flex-direction:column; gap:6px; }
2429
+ .color-label { color:var(--color-text-muted); font-size:12px; line-height:1.5; }
2430
+ .color-grid { display:grid; grid-template-columns:repeat(8,24px); gap:4px; }
2431
+ .color-choice { width:24px; min-width:24px; height:24px; padding:0; border:1px solid var(--color-border); border-radius:3px; background:var(--color-surface); cursor:pointer; display:flex; align-items:center; justify-content:center; }
2432
+ .color-choice.selected { border-color:var(--color-accent); outline:1px solid var(--color-accent); outline-offset:-1px; }
2433
+ .font-sample { font-size:16px; font-weight:500; line-height:1; }
2434
+ .background-choice { position:relative; }
2435
+ .clear-stroke { display:block; width:27px; height:1px; background:var(--color-border-strong); transform:rotate(-45deg); }
2436
+ /* 图片工具条:与 Vue 的 EditorPane 同尺寸、同布局。 */
2437
+ .img-toolbar { position:absolute; z-index:50; display:flex; align-items:center; gap:2px; padding:3px 4px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); transform:translateX(-50%); }
2438
+ .it-btn { display:flex; align-items:center; justify-content:center; min-width:28px; height:28px; border:0; border-radius:5px; background:transparent; color:var(--color-text); cursor:pointer; padding:0 5px; }
2439
+ .it-btn:hover { background:var(--color-surface-subtle); }
2440
+ .it-btn.on { background:var(--color-accent-soft); color:var(--color-accent); }
2441
+ .it-btn.danger { color:var(--color-danger); }
2442
+ .it-btn.danger:hover { background:color-mix(in srgb,var(--color-danger) 12%,transparent); }
2443
+ .it-sep { width:1px; height:18px; background:var(--color-border); margin:0 3px; }
2444
+ /* 插入菜单:与 Vue 的 SlashMenu.vue / InsertPicker.vue 同一套类名与几何。 */
2445
+ .slash-anchor { position:absolute; z-index:40; display:flex; align-items:flex-start; gap:6px; }
2446
+ .slash-menu { width:268px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); padding:4px; }
2447
+ .slash-content { padding:0 0 4px; max-height:min(560px,calc(100dvh - 26px)); overflow-y:auto; overscroll-behavior:contain; }
2448
+ .slash-group { font-size:11px; color:var(--color-text-faint); padding:7px 8px 3px; }
2449
+ .slash-menu ul { list-style:none; margin:0; padding:0; }
2450
+ .slash-menu li { display:flex; align-items:center; gap:8px; padding:6px 8px; border-radius:6px; cursor:pointer; font-size:14px; color:var(--color-text); }
2451
+ .slash-menu li.active { background:var(--color-accent-soft); }
2452
+ .slash-label { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
2453
+ .slash-hint { color:var(--color-text-faint); font-size:12px; flex:none; }
2454
+ .slash-chevron { color:var(--color-text-faint); flex:none; }
2455
+ .slash-empty { color:var(--color-text-faint); font-size:13px; text-align:center; padding:10px; }
2456
+ .insert-picker { position:absolute; z-index:46; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); padding:10px; }
2457
+ .ip-head { display:flex; align-items:baseline; justify-content:space-between; gap:12px; font-size:12px; color:var(--color-text-muted); margin-bottom:8px; }
2458
+ .ip-dim { color:var(--color-text-faint); flex:none; }
2459
+ .ip-grid { display:grid; grid-template-columns:repeat(8,18px); grid-auto-rows:18px; gap:3px; }
2460
+ .ip-cell { width:18px; height:18px; padding:0; border:1px solid var(--color-border); border-radius:3px; background:var(--color-surface-subtle); cursor:pointer; }
2461
+ .ip-cell.on { background:var(--color-accent-soft); border-color:var(--color-accent); }
2462
+ .ip-counts { display:flex; gap:6px; }
2463
+ .ip-count { display:flex; flex-direction:column; align-items:center; gap:4px; padding:4px 6px; border:1px solid transparent; border-radius:6px; background:transparent; cursor:pointer; }
2464
+ .ip-count:hover { background:var(--color-surface-subtle); }
2465
+ .ip-count.on { border-color:var(--color-accent); background:var(--color-accent-soft); }
2466
+ .ip-count-box { display:flex; gap:2px; width:34px; height:22px; padding:3px; border:1px solid var(--color-border-strong); border-radius:3px; background:var(--color-surface-subtle); box-sizing:border-box; }
2467
+ .ip-count-bar { flex:1 1 0; min-width:0; background:var(--color-border-strong); border-radius:1px; }
2468
+ .ip-count.on .ip-count-bar { background:var(--color-accent); }
2469
+ .ip-count-num { font-size:11px; color:var(--color-text-muted); }
2470
+ .ip-close { position:absolute; right:4px; top:4px; padding:2px; border:0; background:transparent; color:var(--color-text-faint); cursor:pointer; }
2471
+ /* 表格控件:与 Vue 的 TableHandles.vue 同一套类名、尺寸与轨迹。 */
2472
+ .tbl-ui-host { position:absolute; left:0; top:0; width:0; height:0; pointer-events:none; z-index:30; }
2473
+ .tbl-ui-host > * { pointer-events:auto; }
2474
+ .tbl-corner { position:absolute; z-index:34; display:flex; width:44px; height:26px; padding:1px; box-sizing:border-box; border:1px solid var(--color-border); border-radius:6px; background:var(--color-surface); }
2475
+ .tbl-corner button { width:20px; height:22px; padding:0; display:flex; align-items:center; justify-content:center; border:none; border-radius:3px; background:transparent; color:var(--color-accent); cursor:pointer; }
2476
+ .tbl-corner .tbl-grip { color:var(--color-text-faint); cursor:grab; }
2477
+ .tbl-corner .tbl-grip:active { cursor:grabbing; }
2478
+ .tbl-corner button:hover { background:var(--color-accent-soft); }
2479
+ .tbl-axis { position:absolute; z-index:35; padding:0; border:none; border-radius:5px; background:transparent; cursor:pointer; }
2480
+ .tbl-axis::before { content:''; position:absolute; border-radius:3px; background:var(--color-border-strong); box-shadow:0 0 0 2px var(--color-surface); }
2481
+ .tbl-row-axis { width:20px; height:24px; opacity:0; }
2482
+ .tbl-row-axis::before { left:8px; top:4px; width:4px; height:16px; }
2483
+ .tbl-col-axis { width:24px; height:20px; opacity:0; }
2484
+ .tbl-col-axis::before { left:4px; top:8px; width:16px; height:4px; }
2485
+ .tbl-axis.current,.tbl-axis:hover,.tbl-axis:focus-visible,.tbl-axis.on { opacity:1; }
2486
+ .tbl-axis:hover::before,.tbl-axis.on::before { background:var(--color-accent); }
2487
+ .tbl-boundary { position:absolute; z-index:36; display:flex; justify-content:center; align-items:center; width:20px; height:20px; border:none; border-radius:50%; padding:0; background:transparent; color:transparent; cursor:pointer; }
2488
+ .tbl-boundary::before { content:''; position:absolute; width:4px; height:4px; border-radius:50%; background:var(--color-border-strong); }
2489
+ .tbl-boundary:hover,.tbl-boundary:focus-visible { color:#fff; background:var(--color-accent); }
2490
+ .tbl-boundary:hover::before,.tbl-boundary:focus-visible::before { display:none; }
2491
+ .tbl-boundary::after { content:''; position:absolute; pointer-events:none; background:var(--color-accent); display:none; }
2492
+ .tbl-boundary:hover::after,.tbl-boundary:focus-visible::after { display:block; }
2493
+ .tbl-boundary-row::after { left:14px; top:9px; width:var(--insert-length); height:2px; }
2494
+ .tbl-boundary-col::after { top:14px; left:9px; width:2px; height:var(--insert-length); }
2495
+ .tbl-boundary > svg,.tbl-boundary > .wr-icon { position:relative; z-index:1; }
2496
+ .tbl-selection-more { position:absolute; z-index:38; width:32px; height:20px; padding:0; line-height:12px; border:none; border-radius:6px; background:var(--color-accent); color:#fff; cursor:pointer; font-size:20px; }
2497
+ .tbl-ui-host > .tbl-selection { position:absolute; z-index:32; border:2px solid var(--color-accent); border-radius:5px; box-sizing:border-box; pointer-events:none; box-shadow:0 0 0 1px var(--color-surface); }
2498
+ .tbl-cellbar { position:fixed; z-index:55; box-sizing:border-box; width:max-content; max-width:calc(100vw - 24px); background:var(--color-surface); border:1px solid var(--color-border); border-radius:10px; box-shadow:var(--shadow-pop); padding:6px; }
2499
+ .tbl-tools { display:flex; gap:2px; align-items:center; flex-wrap:wrap; }
2500
+ .tool { flex:0 0 auto; display:flex; align-items:center; justify-content:center; gap:2px; min-width:32px; height:32px; padding:0 5px; border:none; border-radius:5px; background:transparent; color:var(--color-text); font-size:15px; cursor:pointer; }
2501
+ .tool:hover { background:var(--color-surface-subtle); }
2502
+ .tool.on { background:var(--color-accent-soft); color:var(--color-accent); }
2503
+ .tool[aria-disabled='true'] { opacity:.3; cursor:not-allowed; }
2504
+ .fill-icon { width:16px; height:16px; border:1px solid currentColor; border-radius:3px; background-color:transparent; }
2505
+ .color-tool { position:relative; padding-bottom:2px; }
2506
+ .color-bar { position:absolute; left:8px; right:8px; bottom:3px; height:2px; border-radius:1px; box-shadow:0 0 0 1px var(--color-surface); }
2507
+ .tool-sep { flex:0 0 1px; height:20px; background:var(--color-border); margin:0 4px; }
2508
+ .tbl-palette { z-index:60; display:flex; flex-direction:column; gap:8px; width:max-content; max-width:calc(100vw - 48px); padding:10px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); }
2509
+ .palette-head { display:flex; flex-direction:column; gap:2px; padding:0 2px; }
2510
+ .palette-title { font-size:13px; font-weight:600; color:var(--color-text); }
2511
+ .palette-hint { font-size:11px; line-height:1.5; color:var(--color-text-muted); max-width:282px; }
2512
+ .palette-grid { display:grid; grid-template-columns:repeat(8,30px); gap:6px; }
2513
+ .tbl-align-menu { z-index:60; width:176px; padding:6px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); }
2514
+ .tbl-align-menu button { display:flex; align-items:center; gap:10px; width:100%; min-height:36px; padding:6px 10px; border:none; border-radius:5px; background:transparent; color:var(--color-text); cursor:pointer; }
2515
+ .tbl-align-menu button span { flex:1; text-align:left; }
2516
+ .tbl-align-menu button:hover,.tbl-align-menu button:focus-visible { background:var(--color-surface-subtle); }
2517
+ .tbl-align-menu button[aria-checked='true'] { color:var(--color-accent); }
2518
+ .swatch { display:flex; align-items:center; justify-content:center; width:30px; height:30px; padding:4px; border:1px solid var(--color-border); border-radius:5px; background:var(--color-surface); cursor:pointer; color:var(--color-text-muted); }
2519
+ .swatch span { width:100%; height:100%; border-radius:2px; }
2520
+ .swatch .glyph { display:flex; align-items:center; justify-content:center; width:100%; height:100%; font-size:15px; font-weight:500; line-height:1; border-radius:0; }
2521
+ .swatch:hover { border-color:var(--color-accent); }
2522
+ .swatch.selected { border-color:var(--color-accent); box-shadow:0 0 0 1px var(--color-accent); }
2523
+ .tbl-ctx { z-index:80; padding:4px; background:var(--color-surface); border:1px solid var(--color-border); border-radius:8px; box-shadow:var(--shadow-pop); }
2524
+ /* 菜单项:与 Vue 的 TableContextMenu.vue 同尺寸与间距。 */
2525
+ .ctx-item { display:flex; align-items:center; gap:8px; width:100%; border:none; background:transparent; min-height:32px; padding:7px 10px; border-radius:6px; color:var(--color-text); cursor:pointer; text-align:left; font:inherit; font-size:13px; }
2526
+ .ctx-item:hover { background:var(--color-surface-subtle); }
2527
+ .ctx-item:focus-visible { outline:2px solid var(--color-accent); outline-offset:-2px; }
2528
+ .ctx-item:disabled { opacity:.5; cursor:wait; }
2529
+ .ctx-chevron { margin-left:auto; }
2530
+ .ctx-styles { margin:2px 4px; padding-left:12px; border-left:1px solid var(--color-border); }
2531
+ .ctx-style-swatch { width:18px; height:14px; border:1px solid var(--color-border); border-radius:3px; }
2532
+ .ctx-item.danger { color:var(--color-danger); }
2533
+ .ctx-sep { height:1px; background:var(--color-border); margin:4px 6px; }
2534
+ .ctx-label { font-size:11px; color:var(--color-text-faint); padding:4px 8px 2px; }
2535
+ .ctx-align { display:flex; gap:4px; padding:2px 6px 6px; }
2536
+ .al-btn { border:1px solid var(--color-border); background:var(--color-surface); border-radius:5px; padding:3px 6px; cursor:pointer; color:var(--color-text-muted); }
2537
+ .al-btn.on { border-color:var(--color-accent); color:var(--color-accent); background:var(--color-accent-soft); }
2538
+ .ctx-width { display:flex; align-items:center; gap:6px; padding:4px 8px; }
2539
+ .ctx-label-inline { color:var(--color-text-muted); }
2540
+ .ctx-num { width:66px; padding:3px 6px; font-size:13px; border:1px solid var(--color-border); border-radius:5px; background:var(--color-surface); color:var(--color-text); }
2541
+ .ctx-mini { border:1px solid var(--color-border); background:var(--color-surface); border-radius:5px; padding:3px 8px; font-size:12px; cursor:pointer; }
2542
+ .ctx-mini.primary { background:var(--color-accent); border-color:var(--color-accent); color:#fff; }
2543
+ .faint { color:var(--color-text-faint); }.small { font-size:11px; }
2544
+ /* 图片预览。 */
2545
+ .wr-link-popover { position:fixed;z-index:1450;padding:8px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-surface);box-shadow:var(--shadow-pop);max-width:calc(100vw - 16px);font-size:13px; }.wr-link-popover input { min-width:250px; }.wr-link-popover a { max-width:350px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
2546
+ /* 高亮块控件:图标常显,工具条在悬停 / 聚焦时出现。 */
2547
+ .callout-controls { display:contents; }
2548
+ .callout-icon-button { justify-self:start;background:transparent;border-color:transparent;margin:0;cursor:default; }
2549
+ .callout-icon-button:not(:disabled) { cursor:pointer; }
2550
+ .callout-toolbar { position:absolute;bottom:calc(100% + 4px);right:0;z-index:25;display:flex;align-items:center;gap:4px;padding:4px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:8px;box-shadow:var(--shadow-pop);opacity:0;visibility:hidden;transition:opacity .1s; }
2551
+ .doc-callout:hover > .callout-controls-host .callout-toolbar,.doc-callout:focus-within > .callout-controls-host .callout-toolbar,.callout-toolbar.is-open { opacity:1;visibility:visible; }
2552
+ .callout-toolbar-button,.callout-preset { min-height:32px;padding:0 8px;border:0;border-radius:5px;background:transparent;color:var(--color-text);font:inherit;font-size:13px;cursor:pointer; }
2553
+ .callout-toolbar-button:hover,.callout-preset:hover { background:var(--color-surface-subtle); }
2554
+ .callout-toolbar-divider { height:16px;border-left:1px solid var(--color-border);margin:0 3px; }
2555
+ .callout-color-panel { width:max-content;display:flex;flex-direction:column;gap:12px;padding:2px; }
2556
+ .callout-color-label { font-size:12px;margin-bottom:6px;color:var(--color-text-muted); }
2557
+ .callout-color-grid { display:grid;grid-template-columns:repeat(8,26px);gap:5px; }
2558
+ .callout-color-choice { position:relative;width:26px;height:26px;padding:0;border:1px solid var(--color-border);border-radius:4px;background:var(--color-surface);cursor:pointer;overflow:hidden;font-size:12px;color:var(--color-text-muted); }
2559
+ .callout-color-choice.is-selected { outline:2px solid var(--color-accent);outline-offset:1px; }
2560
+ .callout-color-choice.is-none::after { content:'';position:absolute;left:-5px;top:12px;width:36px;height:1px;background:var(--color-border-strong);transform:rotate(-45deg); }
2561
+ .callout-font-sample { font-size:16px;line-height:1;color:inherit; }
2562
+ .callout-icon-picker { width:254px;box-sizing:border-box;padding:8px 10px 6px; }
2563
+ .callout-icon-grid { display:grid;grid-template-columns:repeat(6,34px);gap:6px; }
2564
+ .callout-icon-choice { width:34px;height:34px;padding:0;border:0;border-radius:5px;background:transparent;font-size:20px;cursor:pointer; }
2565
+ .callout-icon-choice:hover,.callout-icon-choice[aria-pressed='true'] { background:var(--color-accent-soft); }
2566
+ .callout-icon-footer { display:flex;gap:8px;margin-top:10px;padding-top:8px;border-top:1px solid var(--color-border); }
2567
+ .callout-icon-footer .w-button { flex:1;justify-content:center; }
2568
+ .wr-block-drop-line { position:fixed;z-index:1300;height:3px;pointer-events:none;background:var(--color-accent);border:1px solid #fff;border-radius:999px;box-shadow:0 1px 6px #0003;transform:translateY(-1px); }
2569
+ .wr-block-handle { position:absolute;left:0;z-index:25; }
2570
+ .wr-block-menu,.wr-insert-menu { position:sticky;bottom:10px;z-index:40;background:var(--color-surface);border:1px solid var(--color-border);border-radius:8px;padding:10px;box-shadow:var(--shadow-pop);max-height:360px;overflow:auto; }
2571
+ .wr-insert-menu { display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:5px; }
2572
+ .wr-insert-menu header { display:flex;justify-content:space-between;grid-column:1/-1; }
2573
+ .wr-image { max-width:100%;height:auto;cursor:zoom-in; }.wr-image-preview { max-width:100%;max-height:70vh;object-fit:contain; }
2574
+ .wr-media-placeholder { display:inline-flex;min-height:100px;align-items:center;justify-content:center;background:var(--color-surface-subtle); }
2575
+ .wr-code>header { display:flex;justify-content:space-between;background:var(--color-surface-subtle);padding:6px 10px;font-size:12px; }
2576
+ .wr-video iframe { width:100%;height:350px;border:0; }.doc-file-card video { max-width:100%; }
2577
+ .wr-spreadsheet { height:100%;min-height:360px;position:relative;display:flex;flex-direction:column; }.wr-sheet-engine { flex:1;min-height:300px; }
2578
+ /* 工作表只读预览:与 Vue 的 WorksheetPreview.vue 同一套类名与排版。 */
2579
+ .worksheet-preview { border:1px solid var(--color-border); border-radius:8px; overflow:hidden; background:var(--color-surface); }
2580
+ .worksheet-preview-standalone { display:flex;flex-direction:column;flex:1;min-height:0;border:0;border-radius:0; }
2581
+ .worksheet-preview-standalone .sheet-table { flex:1;min-height:0;max-height:none; }
2582
+ .sheet-tabs { display:flex; gap:8px; align-items:center; flex-wrap:wrap; padding:8px; font-size:12px; }
2583
+ .sheet-note { color:var(--color-text-muted); }
2584
+ .sheet-table { overflow:auto; max-height:600px; outline:none; }
2585
+ .sheet-table table { border-collapse:collapse; table-layout:fixed; width:max-content; font-size:13px; }
2586
+ .sheet-table th,.sheet-table td { border:1px solid var(--color-border); padding:3px 6px; overflow:hidden; white-space:pre-wrap; overflow-wrap:anywhere; vertical-align:top; }
2587
+ .sheet-table th { background:var(--color-surface-subtle); font-weight:500; color:var(--color-text-muted); }
2588
+ .sheet-table thead { position:sticky; top:0; z-index:1; }
2589
+ .sheet-table tr > th:first-child { min-width:40px; text-align:center; }
2590
+ .sheet-paging { display:flex; gap:8px; align-items:center; flex-wrap:wrap; padding:8px; font-size:12px; color:var(--color-text-faint); }
2591
+ .sheet-paging > span { flex:1; }
2592
+ .sheet-view-note { flex:none; margin:0; padding:6px 8px; font-size:12px; color:var(--color-text-muted); background:var(--color-surface-subtle); }
2593
+ /* The Canvas and topic visuals come from the canonical Vue style files. */
2594
+ .wr-mind-editor {height:100%;min-height:380px;min-width:0;}
2595
+ .mind-canvas-layers {position:absolute;left:0;top:0;transform-origin:0 0;}
2596
+ .mind-canvas-edges {position:absolute;left:0;top:0;width:1px;height:1px;overflow:visible;pointer-events:none;}
2597
+ .mind-canvas-stage {touch-action:none;}
2598
+ .mind-canvas-surface {position:absolute;inset:0;}
2599
+ .mind-node-actions,.mind-selection-summary,.mind-canvas-bottom {z-index:5;}
2600
+ .mind-canvas-notice {z-index:6;}
2601
+ .mind-context-menu {position:fixed;z-index:1400;padding:0;min-width:160px;max-height:calc(100vh - 16px);overflow:auto;background:var(--color-surface);border:1px solid var(--color-border);border-radius:8px;box-shadow:var(--shadow-pop);}
2602
+ .mind-side-projection {pointer-events:none;}
2603
+ .mind-canvas-fullscreen .wd-dialog__body {overflow:hidden;}
2604
+ .w-popover .mind-settings-menu .w-button {width:auto;}
2605
+ .mind-space-pan,.mind-space-pan .mind-topic {cursor:grab;}
2606
+ .mind-peer-badge {position:absolute;right:4px;top:4px;padding:1px 5px;border-radius:9px;background:var(--color-accent);color:white;font-size:10px;line-height:14px;pointer-events:none;}
2607
+ .wr-settings { display:flex;flex-direction:column;gap:8px; }
2608
+ @media(max-width:760px) { .wr-mind-hint { display:none; }.wr-mind-panel { flex-basis:210px; } }
2609
+
2610
+ /* Vue WPopover shell around the shared Select / Dropdown content. */
2611
+ .w-popover.w-select-popup,.w-popover.code-settings-popup,.w-popover.code-tooltip-popup,.w-popover.mind-dropdown-popup {
2612
+ box-sizing:border-box;min-width:0;max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);
2613
+ padding:0;display:block;overflow:visible;gap:0;overflow-anchor:none;
2614
+ }