@musnows/scriverse 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.js +11 -89
- package/dist/ai.js.map +1 -1
- package/dist/app.js +33 -42
- package/dist/app.js.map +1 -1
- package/dist/public/ai-context-meter.js +45 -4
- package/dist/public/ai-render-scheduler.js +30 -0
- package/dist/public/app.js +284 -194
- package/dist/public/index.html +6 -4
- package/dist/public/markdown.js +22 -10
- package/dist/public/stream-markdown.js +107 -0
- package/dist/public/stream-typewriter.d.ts +1 -0
- package/dist/public/stream-typewriter.js +33 -19
- package/dist/public/styles.css +28 -38
- package/dist/skills/continue-writing/SKILL.md +2 -2
- package/dist/skills/polish-writing/SKILL.md +2 -2
- package/dist/user-auth.js +0 -3
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/public/index.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<script src="/theme-init.js?v=20260827-reader-prefetch-v1"></script>
|
|
10
10
|
<link rel="icon" href="/icon.svg?v=20260712" type="image/svg+xml">
|
|
11
11
|
<link rel="manifest" href="/site.webmanifest">
|
|
12
|
-
<link rel="stylesheet" href="/styles.css?v=20260816-task-scope-volume-collapse-v2&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v3&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=galaxy-compact-controls-v2&feature=galaxy-motion-mode-v2&feature=chapter-search-replace-v3&feature=task-auto-run-ring-center-v3&feature=character-relationship-delete-v1&feature=ai-assistant-workspace-v2&feature=mobile-module-tab-position-v1&feature=volume-detail-icon-v1&feature=editor-actions-flow-v1&feature=reader-controls-subpanel-v1&feature=reader-focus-ring-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v2&feature=ai-composer-square-controls-v2&feature=annotation-line-counts-v1&feature=chapter-comment-filters-v1&feature=line-number-gutter-fill-v1&feature=ai-relationship-roleplay-v1&feature=ai-model-picker-v1&feature=markdown-word-count-five-digit-v2&feature=ai-stream-character-count-stable-v1&feature=ai-stream-character-count-five-digit-v1&feature=annotation-marker-offset-v1&feature=mobile-ai-entry-hidden-v1&feature=phone-client-entry-v1&feature=ai-stream-idle-timeout-v1&feature=ai-user-message-width-v2&feature=ai-chat-image-attachments-v9&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=toast-click-dismiss-v3&feature=character-avatar-v6&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-token-quota-positive-v5&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-stream-connection-seconds-v1&feature=ai-token-usage-estimated-price-v1&feature=record-favorites-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v1&feature=admin-account-identity-v2&feature=task-detail-failure-orange-v1&feature=character-card-header-alignment-v6&feature=character-card-title-fit-v2&feature=book-import-progress-v1&feature=editor-toolbar-compact-v2&feature=reader-first-frame-v1&feature=auth-compact-v2&feature=editor-preview-toggle-v2&feature=setting-title-chrome-v2&feature=entity-pin-icon-center-v1&feature=chapter-center-bottom-space-v1&feature=work-editor-preferences-v1&feature=work-editor-preference-checkbox-v1&feature=ai-roleplay-memory-v2&feature=ai-roleplay-memory-v3&feature=ai-roleplay-memory-v5&feature=character-editor-header-actions-v1&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=roleplay-memory-pin-border-v1&feature=ai-write-tools-v2&feature=ai-write-card-actions-compact-v1&feature=ai-write-plan-actions-footer-v1&feature=ai-question-actions-footer-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-answer-limit-v1&feature=ai-question-batch-v1&feature=semantic-search-v6&feature=chapter-title-renumber-v1&feature=ai-writing-skills-v1&feature=remote-mcp-v1&feature=character-alias-chips-v2&feature=character-title-input-v1&feature=character-detail-value-wrap-v2&feature=ai-settings-textarea-font-v1&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=ai-skill-slash-menu-v1&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v106&feature=im-sidebar-compact-v1&feature=im-narration-contrast-v1&feature=im-member-add-plus-v2&feature=im-button-hierarchy-v1&feature=im-icon-button-size-v1&feature=compact-sidebar-directory-v5&feature=ai-model-config-dialog-v1&feature=system-prompt-override-v3&feature=
|
|
12
|
+
<link rel="stylesheet" href="/styles.css?v=20260816-task-scope-volume-collapse-v2&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v3&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=galaxy-compact-controls-v2&feature=galaxy-motion-mode-v2&feature=chapter-search-replace-v3&feature=task-auto-run-ring-center-v3&feature=character-relationship-delete-v1&feature=ai-assistant-workspace-v2&feature=mobile-module-tab-position-v1&feature=volume-detail-icon-v1&feature=editor-actions-flow-v1&feature=reader-controls-subpanel-v1&feature=reader-focus-ring-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v2&feature=ai-composer-square-controls-v2&feature=ai-composer-compact-controls-v1&feature=ai-context-meter-ring-only-v1&feature=ai-context-cache-hit-v1&feature=annotation-line-counts-v1&feature=chapter-comment-filters-v1&feature=line-number-gutter-fill-v1&feature=ai-relationship-roleplay-v1&feature=ai-model-picker-v1&feature=markdown-word-count-five-digit-v2&feature=ai-stream-character-count-stable-v1&feature=ai-stream-character-count-five-digit-v1&feature=annotation-marker-offset-v1&feature=mobile-ai-entry-hidden-v1&feature=phone-client-entry-v1&feature=ai-stream-idle-timeout-v1&feature=ai-user-message-width-v2&feature=ai-chat-image-attachments-v9&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=toast-click-dismiss-v3&feature=character-avatar-v6&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-token-quota-positive-v5&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-stream-connection-seconds-v1&feature=ai-token-usage-estimated-price-v1&feature=record-favorites-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v1&feature=admin-account-identity-v2&feature=task-detail-failure-orange-v1&feature=character-card-header-alignment-v6&feature=character-card-title-fit-v2&feature=book-import-progress-v1&feature=editor-toolbar-compact-v2&feature=reader-first-frame-v1&feature=auth-compact-v2&feature=editor-preview-toggle-v2&feature=setting-title-chrome-v2&feature=entity-pin-icon-center-v1&feature=chapter-center-bottom-space-v1&feature=work-editor-preferences-v1&feature=work-editor-preference-checkbox-v1&feature=ai-roleplay-memory-v2&feature=ai-roleplay-memory-v3&feature=ai-roleplay-memory-v5&feature=character-editor-header-actions-v1&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=roleplay-memory-pin-border-v1&feature=ai-write-tools-v2&feature=ai-write-card-actions-compact-v1&feature=ai-write-plan-actions-footer-v1&feature=ai-question-actions-footer-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-answer-limit-v1&feature=ai-question-batch-v1&feature=semantic-search-v6&feature=chapter-title-renumber-v1&feature=ai-writing-skills-v1&feature=remote-mcp-v1&feature=character-alias-chips-v2&feature=character-title-input-v1&feature=character-detail-value-wrap-v2&feature=ai-settings-textarea-font-v1&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=ai-skill-slash-menu-v1&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v106&feature=im-sidebar-compact-v1&feature=im-narration-contrast-v1&feature=im-member-add-plus-v2&feature=im-button-hierarchy-v1&feature=im-icon-button-size-v1&feature=compact-sidebar-directory-v5&feature=ai-model-config-dialog-v1&feature=system-prompt-override-v3&feature=entity-editor-back-icon-v1&feature=toast-stack-v1&feature=chapter-header-compact-v4&feature=ai-attachment-disabled-v1&feature=ai-prose-acceptance-removed-v1">
|
|
13
13
|
</head>
|
|
14
14
|
<body class="auth-pending">
|
|
15
15
|
<section id="auth-view" class="auth-view hidden" aria-labelledby="auth-title">
|
|
@@ -433,14 +433,14 @@
|
|
|
433
433
|
<label for="ai-scene-direction">旁白 / 场景<textarea id="ai-scene-direction" rows="3" maxlength="20000" placeholder="写下本轮旁白或场景推进,会随下一条台词一起发送"></textarea></label>
|
|
434
434
|
</section>
|
|
435
435
|
<div class="prompt-composer-leading">
|
|
436
|
-
<button id="ai-attachment-button" class="ai-attachment-button
|
|
436
|
+
<button id="ai-attachment-button" class="ai-attachment-button" type="button" aria-label="添加图片附件" title="选择多模态模型后可添加图片附件" disabled><svg class="ai-image-button-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M16 5h6"></path><path d="M19 2v6"></path><path d="M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5"></path><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path><circle cx="9" cy="9" r="2"></circle></svg></button>
|
|
437
437
|
<button id="ai-scene-button" class="ai-scene-button hidden" type="button" aria-label="旁白与场景" title="旁白与场景" aria-expanded="false" aria-controls="ai-scene-panel"><svg class="ai-scene-button-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="4.5" y="6.5" width="15" height="13" rx="1.5"></rect><path d="M8 10.5h8M8 14h5.5"></path></svg></button>
|
|
438
438
|
</div>
|
|
439
439
|
<input id="ai-attachment-input" class="ai-attachment-input" type="file" accept="image/png,image/jpeg,.jpg,.jpeg" multiple aria-label="选择图片附件">
|
|
440
440
|
<div id="ai-prompt" class="ai-prompt" contenteditable="true" role="textbox" aria-multiline="true" aria-autocomplete="list" aria-controls="ai-mention-menu" aria-haspopup="listbox" aria-expanded="false" aria-keyshortcuts="Enter" title="Enter 发送,Shift+Enter 换行" data-placeholder="告诉 AI 你想讨论或修改什么……"></div>
|
|
441
441
|
<div id="ai-mention-menu" class="ai-mention-menu hidden" role="listbox" aria-label="引用角色、设定、章节或上下文能力"></div>
|
|
442
442
|
<div class="prompt-composer-actions">
|
|
443
|
-
<button id="ai-context-meter" class="ai-context-meter is-empty" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="ai-context-popover" aria-live="polite" aria-label="当前上下文用量"
|
|
443
|
+
<button id="ai-context-meter" class="ai-context-meter is-empty" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="ai-context-popover" aria-live="polite" aria-label="当前上下文用量"></button>
|
|
444
444
|
<section id="ai-context-popover" class="ai-context-popover hidden" role="dialog" aria-labelledby="ai-context-popover-title" aria-describedby="ai-context-popover-description">
|
|
445
445
|
<header class="ai-context-popover-header"><div><strong id="ai-context-popover-title">Token 分布</strong><small id="ai-context-popover-description">按当前模型上下文窗口计算</small></div><button id="ai-context-popover-close" class="ai-context-popover-close" type="button" aria-label="关闭 Token 分布">×</button></header>
|
|
446
446
|
<div id="ai-context-distribution" class="ai-context-distribution" role="list" aria-label="当前 Token 分布"></div>
|
|
@@ -522,6 +522,7 @@
|
|
|
522
522
|
<button type="button" role="menuitemradio" data-chapter-type="设定">设定</button>
|
|
523
523
|
<button type="button" role="menuitemradio" data-chapter-type="作者的话">作者的话</button>
|
|
524
524
|
<button type="button" role="menuitemradio" data-chapter-type="其他">其他</button>
|
|
525
|
+
<div id="chapter-type-ai-reference-separator" class="line-citation-menu-separator hidden" role="separator" aria-orientation="horizontal"></div>
|
|
525
526
|
<button type="button" role="menuitem" data-add-chapter-ai-reference>添加到助手引用</button>
|
|
526
527
|
<button class="danger-button" type="button" role="menuitem" data-delete-chapter>删除章节</button>
|
|
527
528
|
</div>
|
|
@@ -1426,6 +1427,7 @@
|
|
|
1426
1427
|
</dialog>
|
|
1427
1428
|
|
|
1428
1429
|
<div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
|
|
1429
|
-
<script type="module" src="/app.js?v=20260816-extended-thinking-effort-v1&feature=ai-history-rename-v1&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v2&feature=analysis-task-queue-refresh-v1&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=ai-session-id-copy-v2&feature=galaxy-motion-mode-v3&feature=galaxy-edge-label-threshold-v1&feature=calculate-time-tool-v2&feature=analysis-task-expired-toast-v1&feature=global-replace-volume-v1&feature=chapter-search-replace-v1&feature=chapter-save-toast-v1&feature=character-relationship-delete-v1&feature=character-relationship-group-v1&feature=analysis-task-stability-delay-v1&feature=ai-assistant-workspace-v2&feature=volume-detail-icon-v1&feature=volume-story-order-v1&feature=reader-manual-chapter-navigation-v1&feature=ai-message-reference-badges-v1&feature=ai-roleplay-message-reference-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v3&feature=annotation-permissions-v1&feature=annotation-line-counts-v1&feature=ai-relationship-roleplay-v1&feature=ai-roleplay-user-character-visibility-v1&feature=ai-roleplay-story-recall-v1&feature=ai-model-picker-v1&feature=ai-fork-model-unlock-v1&feature=context-percent-format-v1&feature=annotation-precise-locate-v1&feature=markdown-word-count-stable-v1&feature=ai-stream-character-count-stable-v2&feature=ai-process-empty-intermediate-v1&feature=ai-feed-scroll-follow-v2&feature=ai-message-retry-v1&feature=ai-stream-idle-timeout-v2&feature=ai-config-delete-v1&feature=ai-provider-protocol-options-v1&feature=ai-provider-thinking-type-v1&feature=ai-chat-image-attachments-v8&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=ai-image-conversation-model-lock-v1&feature=toast-click-dismiss-v2&feature=system-restart-dialog-delay-v1&feature=character-avatar-v6&feature=character-death-position-v1&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-usage-pricing-label-v1&feature=ai-usage-token-breakdown-v1&feature=ai-usage-pricing-cache-v2&feature=ai-usage-pricing-manual-refresh-v1&feature=ai-monthly-token-quota-v1&feature=ai-provider-token-quota-v1&feature=ai-token-quota-positive-v6&feature=ai-model-thinking-label-v1&feature=ai-model-picker-focus-v1&feature=ai-provider-model-import-v1&feature=ai-assistant-brain-icon-v1&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-token-usage-raw-input-v1&feature=ai-stream-connection-seconds-v1&feature=phone-client-entry-v1&feature=ai-usage-pricing-cache-v1&feature=ai-model-thinking-label-v3&feature=ai-roleplay-speaker-label-v1&feature=toast-modal-host-v1&feature=api-key-copy-existing-v1&feature=character-favorite-v1&feature=record-favorites-v1&feature=ai-token-usage-estimated-price-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=entity-pin-icon-v1&feature=roleplay-favorite-label-v1&feature=ai-roleplay-knowledge-tools-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v2&feature=admin-account-identity-v2&feature=ai-provider-analysis-timeout-v1&feature=task-detail-failure-orange-v1&feature=book-import-progress-v1&feature=presence-multiple-users-v1&feature=ai-context-input-output-v1&feature=editor-blank-lines-preserved-v1&feature=reader-first-frame-v1&feature=vditor-lazy-load-v1&feature=ui-module-preload-v1&feature=reader-initial-prefetch-v1&feature=editor-preview-toggle-v2&feature=vditor-fullscreen-disabled-v1&feature=chapter-auto-indent-v1&feature=chapter-centered-scroll-v1&feature=work-editor-preferences-v1&feature=ai-context-output-usage-v1&feature=ai-roleplay-memory-v4&feature=ai-roleplay-memory-v5&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-header-toolbar-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=annotation-line-anchor-v1&feature=stable-line-ids-v1&feature=live-annotation-anchors-v1&feature=chapter-comment-filters-v1&feature=ai-write-tools-v3&feature=ai-question-option-supplement-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-continuation-ui-v3&feature=ai-background-stream-v1&feature=ai-question-tool-result-v1&feature=ai-question-tool-summary-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-batch-v1&feature=ai-question-answer-limit-v1&feature=semantic-search-v6&feature=chapter-title-renumber-v1&feature=ai-writing-skills-v3&feature=ai-cancel-preserve-process-v2&feature=remote-mcp-v1&feature=character-alias-chips-v2&feature=character-title-input-v1&feature=character-detail-value-wrap-v2&feature=chapter-batch-editor-refresh-v1&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=semantic-search-rag-label-v1&feature=ai-skill-slash-menu-v1&feature=ai-roleplay-scene-bubble-v1&feature=ai-roleplay-scene-collapse-v1&feature=markdown-adjacent-blockquotes-v1&feature=chapter-save-shortcut-v2&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v106&feature=im-sidebar-compact-v1&feature=ai-fork-progress-toast-v1&feature=im-settings-gear-v1&feature=compact-sidebar-directory-v2&feature=chapter-word-count-consistency-v1&feature=
|
|
1430
|
+
<script type="module" src="/app.js?v=20260816-extended-thinking-effort-v1&feature=ai-history-rename-v1&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v2&feature=analysis-task-queue-refresh-v1&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=ai-session-id-copy-v2&feature=galaxy-motion-mode-v3&feature=galaxy-edge-label-threshold-v1&feature=calculate-time-tool-v2&feature=analysis-task-expired-toast-v1&feature=global-replace-volume-v1&feature=chapter-search-replace-v1&feature=chapter-save-toast-v1&feature=character-relationship-delete-v1&feature=character-relationship-group-v1&feature=analysis-task-stability-delay-v1&feature=ai-assistant-workspace-v2&feature=volume-detail-icon-v1&feature=volume-story-order-v1&feature=reader-manual-chapter-navigation-v1&feature=ai-message-reference-badges-v1&feature=ai-roleplay-message-reference-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v3&feature=annotation-permissions-v1&feature=annotation-line-counts-v1&feature=ai-relationship-roleplay-v1&feature=ai-roleplay-user-character-visibility-v1&feature=ai-roleplay-story-recall-v1&feature=ai-model-picker-v1&feature=ai-fork-model-unlock-v1&feature=context-percent-format-v1&feature=annotation-precise-locate-v1&feature=markdown-word-count-stable-v1&feature=ai-stream-character-count-stable-v2&feature=ai-process-empty-intermediate-v1&feature=ai-feed-scroll-follow-v2&feature=ai-message-retry-v1&feature=ai-stream-idle-timeout-v2&feature=ai-config-delete-v1&feature=ai-provider-protocol-options-v1&feature=ai-provider-thinking-type-v1&feature=ai-chat-image-attachments-v8&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=ai-image-conversation-model-lock-v1&feature=toast-click-dismiss-v2&feature=system-restart-dialog-delay-v1&feature=character-avatar-v6&feature=character-death-position-v1&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-usage-pricing-label-v1&feature=ai-usage-token-breakdown-v1&feature=ai-usage-pricing-cache-v2&feature=ai-usage-pricing-manual-refresh-v1&feature=ai-monthly-token-quota-v1&feature=ai-provider-token-quota-v1&feature=ai-token-quota-positive-v6&feature=ai-model-thinking-label-v1&feature=ai-model-picker-focus-v1&feature=ai-provider-model-import-v1&feature=ai-assistant-brain-icon-v1&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-token-usage-raw-input-v1&feature=ai-stream-connection-seconds-v1&feature=phone-client-entry-v1&feature=ai-usage-pricing-cache-v1&feature=ai-model-thinking-label-v3&feature=ai-roleplay-speaker-label-v1&feature=toast-modal-host-v1&feature=api-key-copy-existing-v1&feature=character-favorite-v1&feature=record-favorites-v1&feature=ai-token-usage-estimated-price-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=entity-pin-icon-v1&feature=roleplay-favorite-label-v1&feature=ai-roleplay-knowledge-tools-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v2&feature=admin-account-identity-v2&feature=ai-provider-analysis-timeout-v1&feature=task-detail-failure-orange-v1&feature=book-import-progress-v1&feature=presence-multiple-users-v1&feature=ai-context-input-output-v1&feature=editor-blank-lines-preserved-v1&feature=reader-first-frame-v1&feature=vditor-lazy-load-v1&feature=ui-module-preload-v1&feature=reader-initial-prefetch-v1&feature=editor-preview-toggle-v2&feature=vditor-fullscreen-disabled-v1&feature=chapter-auto-indent-v1&feature=chapter-centered-scroll-v1&feature=work-editor-preferences-v1&feature=ai-context-output-usage-v1&feature=ai-context-meter-ring-only-v1&feature=ai-context-cache-hit-v1&feature=ai-roleplay-memory-v4&feature=ai-roleplay-memory-v5&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-header-toolbar-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=annotation-line-anchor-v1&feature=stable-line-ids-v1&feature=live-annotation-anchors-v1&feature=chapter-comment-filters-v1&feature=ai-write-tools-v3&feature=ai-question-option-supplement-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-continuation-ui-v3&feature=ai-background-stream-v1&feature=ai-question-tool-result-v1&feature=ai-question-tool-summary-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-batch-v1&feature=ai-question-answer-limit-v1&feature=semantic-search-v6&feature=chapter-title-renumber-v1&feature=ai-writing-skills-v3&feature=ai-cancel-preserve-process-v2&feature=remote-mcp-v1&feature=character-alias-chips-v2&feature=character-title-input-v1&feature=character-detail-value-wrap-v2&feature=chapter-batch-editor-refresh-v1&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=semantic-search-rag-label-v1&feature=ai-skill-slash-menu-v1&feature=ai-roleplay-scene-bubble-v1&feature=ai-roleplay-scene-collapse-v1&feature=markdown-adjacent-blockquotes-v1&feature=chapter-save-shortcut-v2&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v106&feature=im-sidebar-compact-v1&feature=ai-fork-progress-toast-v1&feature=im-settings-gear-v1&feature=compact-sidebar-directory-v2&feature=chapter-word-count-consistency-v1&feature=ai-all-message-references-v2&feature=ai-question-render-recovery-v3&feature=setting-category-preservation-v1&feature=toast-stack-v1&feature=toast-stack-label-v2&feature=agent-tool-limits-300-v1&feature=server-dev-logo-v1&feature=chapter-directory-ai-reference-v3&feature=ai-error-origin-v1&feature=ai-stream-render-performance-v2&feature=ai-attachment-disabled-v1&feature=ai-prose-acceptance-removed-v1&feature=ai-inline-message-references-v1"></script>
|
|
1431
|
+
|
|
1430
1432
|
</body>
|
|
1431
1433
|
</html>
|
package/dist/public/markdown.js
CHANGED
|
@@ -142,8 +142,20 @@ function renderMarkdownTable(headers, alignments, rows) {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
export function renderMarkdown(value) {
|
|
145
|
+
return renderMarkdownParts(value).map((part) => part.html).join("");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function renderMarkdownParts(value) {
|
|
145
149
|
const lines = String(value ?? "").replace(/\r\n?/gu, "\n").split("\n");
|
|
146
150
|
const output = [];
|
|
151
|
+
const offsets = [];
|
|
152
|
+
let offset = 0;
|
|
153
|
+
for (const line of lines) {
|
|
154
|
+
offsets.push(offset);
|
|
155
|
+
offset += line.length + 1;
|
|
156
|
+
}
|
|
157
|
+
let lineIndex = 0;
|
|
158
|
+
const emit = (html, endLine = lineIndex) => output.push({ html, end: offsets[endLine] ?? offset - 1 });
|
|
147
159
|
let paragraph = [];
|
|
148
160
|
let list = null;
|
|
149
161
|
let quote = null;
|
|
@@ -151,12 +163,12 @@ export function renderMarkdown(value) {
|
|
|
151
163
|
|
|
152
164
|
const flushParagraph = () => {
|
|
153
165
|
if (!paragraph.length) return;
|
|
154
|
-
|
|
166
|
+
emit(`<p>${paragraph.map(renderInlineMarkdown).join("<br>")}</p>`);
|
|
155
167
|
paragraph = [];
|
|
156
168
|
};
|
|
157
169
|
const flushList = () => {
|
|
158
170
|
if (!list) return;
|
|
159
|
-
|
|
171
|
+
emit(`<${list.tag}>${list.items.map((item) => `<li class="markdown-depth-${item.depth}">${renderInlineMarkdown(item.text)}</li>`).join("")}</${list.tag}>`);
|
|
160
172
|
list = null;
|
|
161
173
|
};
|
|
162
174
|
const flushQuote = () => {
|
|
@@ -166,7 +178,7 @@ export function renderMarkdown(value) {
|
|
|
166
178
|
const html = content.split(/\n\s*\n/gu)
|
|
167
179
|
.map((part) => part.split("\n").map(renderInlineMarkdown).join("<br>"))
|
|
168
180
|
.join("<br><br>");
|
|
169
|
-
|
|
181
|
+
emit(`<blockquote>${html}</blockquote>`);
|
|
170
182
|
}
|
|
171
183
|
quote = null;
|
|
172
184
|
};
|
|
@@ -176,11 +188,11 @@ export function renderMarkdown(value) {
|
|
|
176
188
|
flushQuote();
|
|
177
189
|
};
|
|
178
190
|
|
|
179
|
-
for (
|
|
191
|
+
for (lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
180
192
|
const line = lines[lineIndex];
|
|
181
193
|
if (codeFence) {
|
|
182
194
|
if (/^\s*```/u.test(line)) {
|
|
183
|
-
|
|
195
|
+
emit(`<pre><code${codeFence.language ? ` class="language-${codeFence.language}"` : ""}>${escapeHtml(codeFence.lines.join("\n"))}</code></pre>`, lineIndex + 1);
|
|
184
196
|
codeFence = null;
|
|
185
197
|
} else {
|
|
186
198
|
codeFence.lines.push(line);
|
|
@@ -230,12 +242,12 @@ export function renderMarkdown(value) {
|
|
|
230
242
|
if (heading) {
|
|
231
243
|
flushBlocks();
|
|
232
244
|
const level = heading[1].length;
|
|
233
|
-
|
|
245
|
+
emit(`<h${level}>${renderInlineMarkdown(heading[2])}</h${level}>`, lineIndex + 1);
|
|
234
246
|
continue;
|
|
235
247
|
}
|
|
236
248
|
if (/^\s*(---+|___+|\*\*\*+)\s*$/u.test(line)) {
|
|
237
249
|
flushBlocks();
|
|
238
|
-
|
|
250
|
+
emit("<hr>", lineIndex + 1);
|
|
239
251
|
continue;
|
|
240
252
|
}
|
|
241
253
|
const tableHeaders = splitMarkdownTableRow(line);
|
|
@@ -251,7 +263,7 @@ export function renderMarkdown(value) {
|
|
|
251
263
|
lineIndex += 1;
|
|
252
264
|
}
|
|
253
265
|
lineIndex -= 1;
|
|
254
|
-
|
|
266
|
+
emit(renderMarkdownTable(tableHeaders, alignments, rows), lineIndex + 1);
|
|
255
267
|
continue;
|
|
256
268
|
}
|
|
257
269
|
const listItem = line.match(/^(\s*)([-+*]|\d+\.)\s+(.+)$/u);
|
|
@@ -266,7 +278,7 @@ export function renderMarkdown(value) {
|
|
|
266
278
|
if (list) flushList();
|
|
267
279
|
paragraph.push(line);
|
|
268
280
|
}
|
|
269
|
-
if (codeFence)
|
|
281
|
+
if (codeFence) emit(`<pre><code${codeFence.language ? ` class="language-${codeFence.language}"` : ""}>${escapeHtml(codeFence.lines.join("\n"))}</code></pre>`);
|
|
270
282
|
flushBlocks();
|
|
271
|
-
return output
|
|
283
|
+
return output;
|
|
272
284
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { renderMarkdownParts } from "./markdown.js?v=20260912-stream-render-v2";
|
|
2
|
+
|
|
3
|
+
// 保留末尾两个块,等待列表、引用和表格的后续行确定语义后再冻结前缀。
|
|
4
|
+
export function createMarkdownStreamState() {
|
|
5
|
+
let previous = "";
|
|
6
|
+
let committed = 0;
|
|
7
|
+
return {
|
|
8
|
+
update(value) {
|
|
9
|
+
const source = String(value ?? "").replace(/\r\n?/gu, "\n");
|
|
10
|
+
const reset = !source.startsWith(previous);
|
|
11
|
+
if (reset) committed = 0;
|
|
12
|
+
const parts = renderMarkdownParts(source.slice(committed));
|
|
13
|
+
const stableCount = Math.max(0, parts.length - 2);
|
|
14
|
+
if (stableCount) committed += parts[stableCount - 1].end;
|
|
15
|
+
previous = source;
|
|
16
|
+
return { reset, parts, stableCount };
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 每个节点都是可让出主线程的边界,长列表和表格也不会作为一个大块集中挂载。
|
|
22
|
+
function* patchMarkdownNode(current, next, parent) {
|
|
23
|
+
if (!current || current.nodeType !== next.nodeType || current.nodeName !== next.nodeName) {
|
|
24
|
+
const replacement = next.cloneNode(false);
|
|
25
|
+
if (current) current.replaceWith(replacement);
|
|
26
|
+
else parent.append(replacement);
|
|
27
|
+
current = replacement;
|
|
28
|
+
}
|
|
29
|
+
if (current.nodeType === 3) {
|
|
30
|
+
if (current.data === next.data) return current;
|
|
31
|
+
if (next.data.startsWith(current.data)) current.appendData(next.data.slice(current.data.length));
|
|
32
|
+
else if (current.data !== next.data) current.data = next.data;
|
|
33
|
+
yield;
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
if (current.nodeType !== 1) return current;
|
|
37
|
+
for (const attribute of [...current.attributes]) {
|
|
38
|
+
if (!next.hasAttribute(attribute.name)) current.removeAttribute(attribute.name);
|
|
39
|
+
}
|
|
40
|
+
for (const attribute of next.attributes) {
|
|
41
|
+
if (current.getAttribute(attribute.name) !== attribute.value) current.setAttribute(attribute.name, attribute.value);
|
|
42
|
+
}
|
|
43
|
+
yield;
|
|
44
|
+
const children = [...current.childNodes];
|
|
45
|
+
const nextChildren = [...next.childNodes];
|
|
46
|
+
for (const [index, child] of nextChildren.entries()) yield* patchMarkdownNode(children[index], child, current);
|
|
47
|
+
for (const child of children.slice(nextChildren.length)) { child.remove(); yield; }
|
|
48
|
+
return current;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createStreamingMarkdownRenderer(host, {
|
|
52
|
+
enqueue = (callback) => requestAnimationFrame(callback),
|
|
53
|
+
onRender = () => {},
|
|
54
|
+
now = () => performance.now(),
|
|
55
|
+
budgetMs = 3,
|
|
56
|
+
nodeBudget = 120
|
|
57
|
+
} = {}) {
|
|
58
|
+
const state = createMarkdownStreamState();
|
|
59
|
+
let tail = [];
|
|
60
|
+
let requestedValue = null;
|
|
61
|
+
let appliedValue = null;
|
|
62
|
+
let work = null;
|
|
63
|
+
let queued = false;
|
|
64
|
+
function* apply(value) {
|
|
65
|
+
const update = state.update(value);
|
|
66
|
+
if (update.reset) {
|
|
67
|
+
for (const child of [...host.childNodes]) { child.remove(); yield; }
|
|
68
|
+
tail = [];
|
|
69
|
+
}
|
|
70
|
+
const next = [];
|
|
71
|
+
for (const [index, part] of update.parts.entries()) {
|
|
72
|
+
const previous = tail[index];
|
|
73
|
+
if (previous?.html === part.html) { next.push(previous); continue; }
|
|
74
|
+
const template = host.ownerDocument.createElement("template");
|
|
75
|
+
template.innerHTML = part.html;
|
|
76
|
+
const node = yield* patchMarkdownNode(previous?.node, template.content.firstChild, host);
|
|
77
|
+
next.push({ html: part.html, node });
|
|
78
|
+
}
|
|
79
|
+
for (const item of tail.slice(next.length)) { item.node.remove(); yield; }
|
|
80
|
+
tail = next.slice(update.stableCount);
|
|
81
|
+
appliedValue = value;
|
|
82
|
+
}
|
|
83
|
+
const drain = () => {
|
|
84
|
+
queued = false;
|
|
85
|
+
const started = now();
|
|
86
|
+
if (!work && requestedValue !== appliedValue) work = apply(requestedValue);
|
|
87
|
+
let nodes = 0;
|
|
88
|
+
while (work && nodes < nodeBudget && now() - started < budgetMs) {
|
|
89
|
+
if (work.next().done) { work = null; break; }
|
|
90
|
+
nodes += 1;
|
|
91
|
+
}
|
|
92
|
+
onRender();
|
|
93
|
+
if (work || requestedValue !== appliedValue) schedule();
|
|
94
|
+
};
|
|
95
|
+
const schedule = () => {
|
|
96
|
+
if (queued) return;
|
|
97
|
+
queued = true;
|
|
98
|
+
enqueue(drain);
|
|
99
|
+
};
|
|
100
|
+
return (value) => {
|
|
101
|
+
const normalized = String(value ?? "");
|
|
102
|
+
if (normalized === requestedValue) return false;
|
|
103
|
+
requestedValue = normalized;
|
|
104
|
+
schedule();
|
|
105
|
+
return true;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -27,6 +27,7 @@ export function createStreamTypewriter<FrameHandle = number>(options: {
|
|
|
27
27
|
scheduleFrame?: (callback: () => void) => FrameHandle;
|
|
28
28
|
cancelFrame?: (handle: FrameHandle) => void;
|
|
29
29
|
reducedMotion?: boolean;
|
|
30
|
+
shouldAnimate?: () => boolean;
|
|
30
31
|
speedController?: StreamTypewriterSpeedController | null;
|
|
31
32
|
visibilitySource?: Pick<Document, "visibilityState" | "addEventListener" | "removeEventListener"> | null;
|
|
32
33
|
}): StreamTypewriter;
|
|
@@ -75,23 +75,34 @@ export function createStreamTypewriter({
|
|
|
75
75
|
cancelFrame = (handle) => window.cancelAnimationFrame(handle),
|
|
76
76
|
reducedMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true,
|
|
77
77
|
speedController = null,
|
|
78
|
+
shouldAnimate = () => true,
|
|
78
79
|
visibilitySource = typeof document === "undefined" ? null : document
|
|
79
80
|
}) {
|
|
80
81
|
if (typeof onRender !== "function") throw new TypeError("onRender must be a function");
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
let visibleText = "";
|
|
84
|
+
let visibleCharacterCount = 0;
|
|
85
|
+
let pendingCharacters = [];
|
|
86
|
+
let pendingOffset = 0;
|
|
87
|
+
const pendingCount = () => pendingCharacters.length - pendingOffset;
|
|
88
|
+
const takePending = (count) => {
|
|
89
|
+
const characters = pendingCharacters.slice(pendingOffset, pendingOffset + count);
|
|
90
|
+
visibleText += characters.join("");
|
|
91
|
+
visibleCharacterCount += characters.length;
|
|
92
|
+
pendingOffset += characters.length;
|
|
93
|
+
if (pendingOffset === pendingCharacters.length) { pendingCharacters = []; pendingOffset = 0; }
|
|
94
|
+
};
|
|
84
95
|
const idleResolvers = [];
|
|
85
96
|
let scheduledFrame = null;
|
|
86
97
|
let finishing = false;
|
|
87
98
|
let listeningForVisibility = false;
|
|
88
99
|
|
|
89
|
-
const snapshot = () =>
|
|
100
|
+
const snapshot = () => visibleText;
|
|
90
101
|
const visibilityChanged = () => {
|
|
91
|
-
if (
|
|
102
|
+
if (pendingCount()) typewriter.reveal();
|
|
92
103
|
};
|
|
93
104
|
const resolveIdle = () => {
|
|
94
|
-
if (
|
|
105
|
+
if (pendingCount() || scheduledFrame !== null) return;
|
|
95
106
|
if (listeningForVisibility) {
|
|
96
107
|
visibilitySource.removeEventListener("visibilitychange", visibilityChanged);
|
|
97
108
|
listeningForVisibility = false;
|
|
@@ -101,32 +112,33 @@ export function createStreamTypewriter({
|
|
|
101
112
|
};
|
|
102
113
|
const render = () => {
|
|
103
114
|
onRender(snapshot(), {
|
|
104
|
-
visibleCharacters:
|
|
105
|
-
pendingCharacters:
|
|
115
|
+
visibleCharacters: visibleCharacterCount,
|
|
116
|
+
pendingCharacters: pendingCount()
|
|
106
117
|
});
|
|
107
118
|
};
|
|
108
119
|
const schedule = () => {
|
|
109
|
-
if (visibilitySource?.visibilityState === "hidden") {
|
|
120
|
+
if (visibilitySource?.visibilityState === "hidden" || !shouldAnimate()) {
|
|
110
121
|
typewriter.reveal();
|
|
111
122
|
return;
|
|
112
123
|
}
|
|
113
|
-
if (scheduledFrame !== null ||
|
|
124
|
+
if (scheduledFrame !== null || pendingCount() === 0) return;
|
|
114
125
|
if (visibilitySource && !listeningForVisibility) {
|
|
115
126
|
visibilitySource.addEventListener("visibilitychange", visibilityChanged);
|
|
116
127
|
listeningForVisibility = true;
|
|
117
128
|
}
|
|
118
129
|
scheduledFrame = scheduleFrame(() => {
|
|
119
130
|
scheduledFrame = null;
|
|
120
|
-
const batchSize = reducedMotion
|
|
121
|
-
?
|
|
131
|
+
const batchSize = reducedMotion || !shouldAnimate()
|
|
132
|
+
? pendingCount()
|
|
122
133
|
: streamTypewriterBatchSize(
|
|
123
|
-
|
|
134
|
+
pendingCount(),
|
|
124
135
|
finishing,
|
|
125
136
|
speedController?.charactersPerSecond?.()
|
|
126
137
|
);
|
|
127
|
-
|
|
138
|
+
const catchUp = pendingCount() > 4096 ? Math.min(2048, Math.ceil(pendingCount() / 8)) : batchSize;
|
|
139
|
+
takePending(Math.max(batchSize, catchUp));
|
|
128
140
|
render();
|
|
129
|
-
if (
|
|
141
|
+
if (pendingCount()) schedule();
|
|
130
142
|
else resolveIdle();
|
|
131
143
|
});
|
|
132
144
|
};
|
|
@@ -136,7 +148,7 @@ export function createStreamTypewriter({
|
|
|
136
148
|
const characters = Array.from(String(value ?? ""));
|
|
137
149
|
if (!characters.length) return;
|
|
138
150
|
speedController?.observe?.(characters.length);
|
|
139
|
-
pendingCharacters.push(
|
|
151
|
+
for (const character of characters) pendingCharacters.push(character);
|
|
140
152
|
schedule();
|
|
141
153
|
},
|
|
142
154
|
replace(value) {
|
|
@@ -144,15 +156,17 @@ export function createStreamTypewriter({
|
|
|
144
156
|
cancelFrame(scheduledFrame);
|
|
145
157
|
scheduledFrame = null;
|
|
146
158
|
}
|
|
147
|
-
|
|
148
|
-
|
|
159
|
+
visibleText = String(value ?? "");
|
|
160
|
+
visibleCharacterCount = Array.from(visibleText).length;
|
|
161
|
+
pendingCharacters = [];
|
|
162
|
+
pendingOffset = 0;
|
|
149
163
|
finishing = false;
|
|
150
164
|
render();
|
|
151
165
|
resolveIdle();
|
|
152
166
|
return snapshot();
|
|
153
167
|
},
|
|
154
168
|
finish() {
|
|
155
|
-
if (!
|
|
169
|
+
if (!pendingCount() && scheduledFrame === null) return Promise.resolve(snapshot());
|
|
156
170
|
finishing = true;
|
|
157
171
|
const completed = new Promise((resolve) => idleResolvers.push(resolve));
|
|
158
172
|
schedule();
|
|
@@ -163,7 +177,7 @@ export function createStreamTypewriter({
|
|
|
163
177
|
cancelFrame(scheduledFrame);
|
|
164
178
|
scheduledFrame = null;
|
|
165
179
|
}
|
|
166
|
-
|
|
180
|
+
takePending(pendingCount());
|
|
167
181
|
finishing = false;
|
|
168
182
|
render();
|
|
169
183
|
resolveIdle();
|
package/dist/public/styles.css
CHANGED
|
@@ -1496,11 +1496,11 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1496
1496
|
|
|
1497
1497
|
.hidden { display: none !important; }
|
|
1498
1498
|
.editor-view { container-name: editor-workspace; container-type: inline-size; display: grid; grid-template-rows: auto auto minmax(0, 1fr); height: 100%; }
|
|
1499
|
-
.editor-toolbar { position: relative; display: grid; grid-row: 1; grid-template-areas: "
|
|
1500
|
-
#chapter-path { grid-area: path; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1501
|
-
.chapter-title { grid-area: title; display: block; width: 100%; min-width: 0; border: 0; border-radius: 0; background: transparent; font-size:
|
|
1502
|
-
.chapter-title:focus { box-shadow:
|
|
1503
|
-
.editor-actions { grid-area: actions; display: flex; align-items: center; gap:
|
|
1499
|
+
.editor-toolbar { position: relative; display: grid; grid-row: 1; grid-template-areas: "title actions" "path actions"; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 16px; row-gap: 2px; padding: 6px 18px; border-bottom: 1px solid var(--line); }
|
|
1500
|
+
#chapter-path { grid-area: path; min-width: 0; margin: 0; color: var(--muted); font-size: 10px; line-height: 14px; letter-spacing: .02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1501
|
+
.chapter-title { grid-area: title; display: block; width: 100%; min-width: 0; height: 26px; border: 0; border-radius: 0; background: transparent; font-size: 20px; font-weight: 600; line-height: 26px; padding: 0; text-overflow: ellipsis; }
|
|
1502
|
+
.chapter-title:focus { box-shadow: inset 0 -1px var(--accent); }
|
|
1503
|
+
.editor-actions { grid-area: actions; display: flex; align-items: center; gap: 6px; padding-left: 12px; border-left: 1px solid var(--line); white-space: nowrap; }
|
|
1504
1504
|
.editor-view .editor-actions > button { min-height: 32px; padding: 6px 10px; font-size: 11px; }
|
|
1505
1505
|
.chapter-stats { color: var(--muted); font-size: 11px; }
|
|
1506
1506
|
.chapter-search-panel { position: absolute; z-index: 8; top: calc(100% + 8px); right: 7%; display: grid; width: min(520px, calc(100% - 14%)); gap: 12px; padding: 14px; border: 1px solid var(--line-strong); outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 7px; background: var(--panel); box-shadow: 0 16px 36px rgba(36, 30, 24, .22); }
|
|
@@ -1532,9 +1532,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1532
1532
|
.chapter-foreshadow-reminder-details dt { color: var(--reminder-color); font-size: 9px; font-weight: 700; }
|
|
1533
1533
|
.chapter-foreshadow-reminder-details dd { margin: 0; overflow-wrap: anywhere; color: var(--muted); font-size: 10px; line-height: 1.5; white-space: pre-wrap; }
|
|
1534
1534
|
@container editor-workspace (max-width: 720px) {
|
|
1535
|
-
.editor-toolbar { grid-template-areas: "
|
|
1536
|
-
.
|
|
1537
|
-
.editor-actions { justify-content: flex-end; flex-wrap: wrap; }
|
|
1535
|
+
.editor-toolbar { grid-template-areas: "title" "path" "actions"; grid-template-columns: minmax(0, 1fr); }
|
|
1536
|
+
.editor-actions { justify-content: flex-start; flex-wrap: wrap; margin-top: 4px; padding-left: 0; border-left: 0; }
|
|
1538
1537
|
.chapter-stats { display: none; }
|
|
1539
1538
|
.chapter-foreshadow-reminder { grid-template-areas: "summary" "actions" "details"; grid-template-columns: minmax(0, 1fr); padding-inline: 6%; }
|
|
1540
1539
|
.chapter-foreshadow-reminder-actions { justify-content: flex-start; flex-wrap: wrap; }
|
|
@@ -3088,13 +3087,6 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3088
3087
|
.ai-field-diff-table th:nth-child(2), .ai-field-diff-table th:nth-child(3) { font-size: 8px; }
|
|
3089
3088
|
}
|
|
3090
3089
|
|
|
3091
|
-
.guard-card { margin-top: 10px; padding: 9px 10px; border: 1px solid var(--line); border-left: 3px solid var(--green); border-radius: 4px; background: var(--surface-soft); }
|
|
3092
|
-
.writing-suggestion-ui { display: contents; }
|
|
3093
|
-
.guard-card.warning { border-left-color: #c07b31; }.guard-card.failed { border-left-color: var(--accent); }
|
|
3094
|
-
.guard-card strong { display: block; margin-bottom: 5px; font-size: 10px; }.guard-card p { margin: 4px 0; color: var(--muted); font-size: 9px; line-height: 1.45; }.guard-card p b { color: var(--ink); }
|
|
3095
|
-
.guard-failure-details { margin-top: 6px; }
|
|
3096
|
-
.guard-failure-details summary { width: max-content; max-width: 100%; color: var(--accent-dark); font-size: 9px; line-height: 1.45; cursor: pointer; }
|
|
3097
|
-
.guard-failure-details p { margin-top: 6px; padding: 7px 8px; border: 1px solid var(--line); border-radius: 3px; background: var(--surface); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
3098
3090
|
.message-actions { display: flex; gap: 7px; margin-top: 10px; }
|
|
3099
3091
|
.message-actions button { border: 1px solid rgba(139,61,44,.25); background: var(--surface); color: var(--accent-dark); font-size: 10px; padding: 5px 8px; border-radius: 3px; }
|
|
3100
3092
|
.prompt-box { border-top: 1px solid var(--line); padding-top: 12px; }
|
|
@@ -3172,11 +3164,12 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3172
3164
|
.ai-image-preview-body { display: grid; place-items: center; min-height: 180px; max-height: calc(88vh - 106px); padding: 16px 20px 20px; overflow: auto; background: var(--paper); }
|
|
3173
3165
|
.ai-image-preview-body img { display: block; max-width: 100%; max-height: calc(88vh - 150px); width: auto; height: auto; object-fit: contain; border-radius: 3px; }
|
|
3174
3166
|
.ai-attachment-input { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }
|
|
3175
|
-
.ai-attachment-button, .ai-scene-button { display: grid; place-items: center; width:
|
|
3167
|
+
.ai-attachment-button, .ai-scene-button { display: grid; place-items: center; width: 24px; min-width: 24px; min-height: 24px; height: 24px; padding: 0; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); color: var(--muted); }
|
|
3176
3168
|
.ai-attachment-button:hover, .ai-attachment-button:focus-visible, .ai-scene-button:hover, .ai-scene-button:focus-visible, .ai-scene-button[aria-expanded="true"], .ai-scene-button.is-active { border-color: color-mix(in srgb, var(--accent) 56%, var(--line)); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); color: var(--accent-dark); outline: 0; }
|
|
3177
|
-
.ai-attachment-button:disabled
|
|
3169
|
+
.ai-attachment-button:disabled { border-color: var(--line); background: var(--surface); color: var(--muted); cursor: not-allowed; opacity: .56; }
|
|
3170
|
+
.ai-scene-button:disabled { cursor: wait; opacity: .56; }
|
|
3178
3171
|
.ai-scene-button.hidden { display: none; }
|
|
3179
|
-
.ai-image-button-icon, .ai-scene-button-icon { width:
|
|
3172
|
+
.ai-image-button-icon, .ai-scene-button-icon { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.7; }
|
|
3180
3173
|
|
|
3181
3174
|
.character-roleplay-memory-surface { display: grid; grid-column: 1 / -1; gap: 14px; min-width: 0; }
|
|
3182
3175
|
.roleplay-memory-toolbar { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
|
|
@@ -3230,7 +3223,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3230
3223
|
.ai-skill-option > span { display: grid; gap: 2px; min-width: 0; }
|
|
3231
3224
|
.ai-skill-option em { color: var(--muted); font-size: 9px; font-style: normal; line-height: 1.35; overflow-wrap: anywhere; }
|
|
3232
3225
|
.ai-mention-empty { margin: 0; padding: 10px; color: var(--muted); font-size: 10px; text-align: center; }
|
|
3233
|
-
.ai-prompt { display: block; width: 100%; min-height: 104px; margin: 0; padding: 10px 10px
|
|
3226
|
+
.ai-prompt { display: block; width: 100%; min-height: 104px; margin: 0; padding: 10px 10px 36px; overflow-y: auto; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); color: var(--ink); font-size: 12px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; cursor: text; }
|
|
3234
3227
|
.ai-prompt:empty::before { color: var(--muted); content: attr(data-placeholder); pointer-events: none; }
|
|
3235
3228
|
.ai-prompt:focus { border-color: #a77768; box-shadow: 0 0 0 3px rgba(167,119,104,.12); outline: 0; }
|
|
3236
3229
|
.ai-prompt-reference { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; margin: 0 2px; padding: 2px 4px 2px 7px; border: 1px solid color-mix(in srgb, var(--accent) 48%, var(--line)); border-radius: 999px; background: color-mix(in srgb, var(--accent) 13%, var(--paper)); color: var(--accent-dark); font-size: 10px; line-height: 1.25; vertical-align: baseline; }
|
|
@@ -3238,28 +3231,28 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3238
3231
|
.ai-prompt-reference button { width: 16px; height: 16px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: inherit; font: 14px/1 var(--font-latin), monospace; }
|
|
3239
3232
|
.ai-prompt-reference button:hover, .ai-prompt-reference button:focus-visible { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
|
|
3240
3233
|
.prompt-composer-actions { position: absolute; right: 8px; bottom: 8px; display: flex; gap: 6px; align-items: center; }
|
|
3241
|
-
.ai-context-meter { --context-usage: 0; --context-meter-color: var(--green); position: relative; display: grid; flex: 0 0
|
|
3242
|
-
.ai-context-meter::before { content: ""; position: absolute; inset:
|
|
3234
|
+
.ai-context-meter { --context-usage: 0; --context-meter-color: var(--green); position: relative; display: grid; flex: 0 0 24px; place-items: center; width: 24px; min-height: 24px; height: 24px; overflow: visible; border: 0; border-radius: 50%; background: conic-gradient(var(--context-meter-color) calc(var(--context-usage) * 1%), rgba(143,132,116,.2) 0); color: var(--ink); font-family: var(--font-latin); line-height: 1; cursor: pointer; }
|
|
3235
|
+
.ai-context-meter::before { content: ""; position: absolute; inset: 2px; border-radius: 50%; background: var(--paper); box-shadow: inset 0 0 0 1px rgba(143,132,116,.12); }
|
|
3243
3236
|
.ai-context-meter:hover, .ai-context-meter:focus-visible, .ai-context-meter[aria-expanded="true"] { outline: 0; filter: brightness(.96); }
|
|
3244
3237
|
.ai-context-meter:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
|
|
3245
|
-
.ai-context-meter
|
|
3238
|
+
.ai-context-meter.is-warning { --context-meter-color: #bf6a35; }.ai-context-meter.is-danger { --context-meter-color: #ad463c; }.ai-context-meter.is-empty { opacity: .62; }
|
|
3246
3239
|
.ai-context-popover { position: absolute; right: 0; bottom: calc(100% + 10px); z-index: 40; display: grid; width: min(320px, calc(100vw - 32px)); gap: 12px; padding: 14px; border: 1px solid var(--line); border-radius: 7px; background: var(--paper); color: var(--ink); box-shadow: 0 14px 38px rgba(36, 30, 24, .18); }
|
|
3247
3240
|
.ai-context-popover.hidden { display: none; }
|
|
3248
|
-
.ai-context-popover::after { position: absolute; right:
|
|
3241
|
+
.ai-context-popover::after { position: absolute; right: 67px; bottom: -6px; width: 10px; height: 10px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--paper); content: ""; transform: rotate(45deg); }
|
|
3249
3242
|
.ai-context-popover-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--line); }
|
|
3250
3243
|
.ai-context-popover-header > div { display: grid; gap: 3px; min-width: 0; }
|
|
3251
3244
|
.ai-context-popover-header strong { font-size: 12px; }
|
|
3252
3245
|
.ai-context-popover-header small { color: var(--muted); font: 9px/1.4 var(--font-latin), var(--font-cjk), sans-serif; }
|
|
3253
3246
|
.ai-context-popover-close { flex: 0 0 auto; width: 24px; height: 24px; padding: 0; border: 1px solid var(--line); border-radius: 4px; background: transparent; color: var(--muted); font: 17px/1 var(--font-latin), sans-serif; }
|
|
3254
3247
|
.ai-context-popover-close:hover, .ai-context-popover-close:focus-visible { border-color: var(--accent); color: var(--accent-dark); outline: 0; }
|
|
3255
|
-
.ai-model-picker { display: grid; flex: 0 0
|
|
3248
|
+
.ai-model-picker { display: grid; flex: 0 0 24px; place-items: center; width: 24px; min-width: 24px; min-height: 24px; height: 24px; padding: 0; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); color: var(--muted); }
|
|
3256
3249
|
.ai-model-picker:hover, .ai-model-picker:focus-visible, .ai-model-picker[aria-expanded="true"] { border-color: color-mix(in srgb, var(--accent) 56%, var(--line)); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); color: var(--accent-dark); outline: 0; }
|
|
3257
3250
|
.ai-model-picker:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }
|
|
3258
3251
|
.ai-model-picker:disabled { cursor: wait; opacity: .56; }
|
|
3259
|
-
.ai-model-picker-icon { width:
|
|
3252
|
+
.ai-model-picker-icon { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.7; }
|
|
3260
3253
|
.ai-model-popover { position: absolute; right: 0; bottom: calc(100% + 10px); z-index: 41; display: grid; width: min(280px, calc(100vw - 32px)); gap: 7px; padding: 12px; border: 1px solid var(--line); border-radius: 7px; background: var(--paper); color: var(--ink); box-shadow: 0 14px 38px rgba(36, 30, 24, .18); }
|
|
3261
3254
|
.ai-model-popover.hidden { display: none; }
|
|
3262
|
-
.ai-model-popover::after { position: absolute; right:
|
|
3255
|
+
.ai-model-popover::after { position: absolute; right: 37px; bottom: -6px; width: 10px; height: 10px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--paper); content: ""; transform: rotate(45deg); }
|
|
3263
3256
|
.ai-model-popover > label { color: var(--muted); font-size: 10px; font-weight: 600; }
|
|
3264
3257
|
.ai-model-native-select { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
|
3265
3258
|
.ai-model-options { display: grid; max-height: 240px; gap: 3px; overflow-y: auto; }
|
|
@@ -3287,16 +3280,16 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3287
3280
|
.ai-context-distribution-row[data-key="input"] { --distribution-color: var(--green); }
|
|
3288
3281
|
.ai-context-distribution-row[data-key="output"] { --distribution-color: #718a9f; }
|
|
3289
3282
|
.ai-context-distribution-row[data-key="left"] { --distribution-color: color-mix(in srgb, var(--muted) 55%, transparent); }
|
|
3290
|
-
.ai-send-button { display: grid; flex: 0 0
|
|
3283
|
+
.ai-send-button { display: grid; flex: 0 0 24px; place-items: center; width: 24px; min-width: 24px; min-height: 24px; height: 24px; padding: 0; border: 0; border-radius: 4px; background: var(--accent); color: #fff; box-shadow: 0 3px 8px rgba(139,61,44,.2); }
|
|
3291
3284
|
.ai-send-button:hover, .ai-send-button:focus-visible { background: var(--accent-dark); outline: 0; }
|
|
3292
|
-
.ai-send-button:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 24%, transparent), 0
|
|
3285
|
+
.ai-send-button:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 24%, transparent), 0 3px 8px rgba(139,61,44,.2); }
|
|
3293
3286
|
.ai-send-button:disabled { cursor: wait; opacity: .62; }
|
|
3294
|
-
.ai-send-button-icon { width:
|
|
3287
|
+
.ai-send-button-icon { width: 14px; height: 14px; overflow: visible; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.8; }
|
|
3295
3288
|
.ai-message-images { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
|
|
3296
3289
|
.ai-message-image-preview { display: block; width: 68px; height: 68px; padding: 0; overflow: hidden; border: 1px solid color-mix(in srgb, var(--accent) 34%, var(--line)); border-radius: 5px; background: var(--paper); cursor: zoom-in; }
|
|
3297
3290
|
.ai-message-image-preview:hover, .ai-message-image-preview:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 72%, transparent); outline-offset: 1px; }
|
|
3298
3291
|
.ai-message-image-preview img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
|
3299
|
-
.ai-send-button.is-stop .ai-send-button-icon { width:
|
|
3292
|
+
.ai-send-button.is-stop .ai-send-button-icon { width: 12px; height: 12px; fill: currentColor; stroke: none; }
|
|
3300
3293
|
.ai-citations { display: grid; gap: 6px; max-height: 190px; overflow-y: auto; margin-bottom: 8px; }
|
|
3301
3294
|
.ai-citation-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; border: 1px solid var(--line); border-radius: 5px; background: var(--paper); overflow: hidden; }
|
|
3302
3295
|
.ai-citation-main { min-width: 0; padding: 8px 9px; border: 0; background: transparent; text-align: left; }
|
|
@@ -3328,6 +3321,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3328
3321
|
.user-message .message-body:empty { display: none; }
|
|
3329
3322
|
.user-message-mentions-label { flex: 0 0 auto; opacity: .72; letter-spacing: .08em; }
|
|
3330
3323
|
.user-message-mention { min-width: 0; max-width: 100%; padding: 2px 6px; overflow-wrap: anywhere; border: 1px solid color-mix(in srgb, currentColor 55%, transparent); border-radius: 999px; background: color-mix(in srgb, currentColor 12%, transparent); }
|
|
3324
|
+
.user-message-inline-mention { display: inline-flex; align-items: center; margin: 0 2px; vertical-align: baseline; font-size: .82em; line-height: 1.35; }
|
|
3331
3325
|
|
|
3332
3326
|
/* Toast 使用 Popover Top Layer;必须覆盖 UA 默认居中/系统边框/Canvas 背景 */
|
|
3333
3327
|
.toast-region,
|
|
@@ -4237,8 +4231,6 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
4237
4231
|
@media (max-width: 1100px) {
|
|
4238
4232
|
.left-panel-body { padding-inline: 10px; }
|
|
4239
4233
|
.ai-panel { padding-inline: 14px; }
|
|
4240
|
-
.editor-toolbar { grid-template-areas: "path" "title" "actions"; grid-template-columns: minmax(0, 1fr); gap: 12px; padding-inline: 6%; }
|
|
4241
|
-
.editor-actions { justify-content: flex-end; flex-wrap: wrap; }
|
|
4242
4234
|
.outline-row { grid-template-columns: 1fr 1fr; }.outline-actions { justify-items: start; }
|
|
4243
4235
|
.character-editor-workspace, .character-editor-workspace.history-open { grid-template-columns: 150px minmax(0, 1fr); }
|
|
4244
4236
|
.character-editor-workspace.history-open .character-history-panel { position: absolute; z-index: 3; top: 0; right: 0; bottom: 0; width: min(340px, 44vw); box-shadow: -12px 0 32px rgba(49,42,32,.16); }
|
|
@@ -4497,7 +4489,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
4497
4489
|
.welcome-view h1 { font-size: clamp(30px, 9vw, 44px); }
|
|
4498
4490
|
.welcome-grid { grid-template-columns: 1fr; margin-top: 34px; }
|
|
4499
4491
|
|
|
4500
|
-
.editor-toolbar { padding:
|
|
4492
|
+
.editor-toolbar { padding: 6px var(--mobile-gutter); }
|
|
4501
4493
|
.chapter-search-panel { top: calc(100% + 8px); right: var(--mobile-gutter); left: var(--mobile-gutter); width: auto; max-height: calc(100dvh - 120px); overflow-y: auto; }
|
|
4502
4494
|
.chapter-search-fields { grid-template-columns: minmax(0, 1fr); }
|
|
4503
4495
|
.chapter-foreshadow-reminder { padding: 10px var(--mobile-gutter); }
|
|
@@ -4505,11 +4497,11 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
4505
4497
|
.chapter-foreshadow-reminder-counter { grid-column: 1 / -1; justify-self: start; }
|
|
4506
4498
|
.chapter-foreshadow-reminder-actions button { width: 100%; min-width: 0; min-height: 38px; }
|
|
4507
4499
|
.chapter-foreshadow-reminder[data-multiple="true"] #chapter-foreshadow-reminder-resolve { grid-column: span 2; }
|
|
4508
|
-
.editor-actions { position: static; z-index: auto; right: auto; bottom: auto; left: auto; display:
|
|
4500
|
+
.editor-actions { position: static; z-index: auto; right: auto; bottom: auto; left: auto; display: flex; flex-wrap: wrap; width: 100%; max-width: none; gap: 6px; padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; transform: none; transition: none; }
|
|
4509
4501
|
.app-shell.left-panel-collapsed .editor-actions { transform: none; pointer-events: auto; }
|
|
4510
4502
|
.editor-actions .chapter-stats { grid-column: 1 / -1; }
|
|
4511
4503
|
.editor-view .editor-actions > button { min-width: 0; min-height: 34px; padding-inline: 6px; font-size: 11px; }
|
|
4512
|
-
.chapter-title { font-size:
|
|
4504
|
+
.chapter-title { font-size: 18px; }
|
|
4513
4505
|
.chapter-content { padding: 22px 16px 64px 12px; font-size: max(16px, var(--editor-font-size)); }
|
|
4514
4506
|
.app-shell.editor-typewriter-mode .chapter-content { padding-bottom: max(64px, 45dvh); }
|
|
4515
4507
|
.chapter-line-numbers { width: 32px; font-size: 11px; }
|
|
@@ -4637,7 +4629,6 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
4637
4629
|
button.account-button { width: 32px; height: 32px; }
|
|
4638
4630
|
.top-actions { gap: 3px; }
|
|
4639
4631
|
.left-primary-actions .file-button { font-size: 10px; }
|
|
4640
|
-
.editor-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
4641
4632
|
.editor-actions .chapter-stats { display: none; }
|
|
4642
4633
|
.editor-actions > button { width: auto; }
|
|
4643
4634
|
.book-shelf { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 12px; max-width: none; }
|
|
@@ -4693,7 +4684,7 @@ body { font-size: var(--ui-font-size); }
|
|
|
4693
4684
|
.message-body .markdown-image small { font-size: calc(9px * var(--ai-font-scale)); }
|
|
4694
4685
|
.ai-process-details > summary, .ai-process-step-body, .ai-tool-call-summary { font-size: calc(10px * var(--ai-font-scale)); }
|
|
4695
4686
|
.ai-process-details > summary > small, .ai-process-step > small { font-size: calc(9px * var(--ai-font-scale)); }
|
|
4696
|
-
.
|
|
4687
|
+
.message-actions button { font-size: calc(10px * var(--ai-font-scale)); }
|
|
4697
4688
|
.ai-context-warning strong { font-size: calc(11px * var(--ai-font-scale)); }
|
|
4698
4689
|
.ai-context-warning p, .ai-context-warning button { font-size: calc(9px * var(--ai-font-scale)); }
|
|
4699
4690
|
.prompt-options select, .ai-model-popover > label, .ai-model-option-copy strong, .ai-model-options-empty, .ai-mention-option strong, .ai-mention-empty { font-size: calc(10px * var(--ai-font-scale)); }
|
|
@@ -4705,7 +4696,6 @@ body { font-size: var(--ui-font-size); }
|
|
|
4705
4696
|
.user-message-scene { font-size: calc(10px * var(--ai-font-scale)); }
|
|
4706
4697
|
.user-message-scene-label { font-size: calc(8px * var(--ai-font-scale)); }
|
|
4707
4698
|
.ai-prompt-reference { font-size: calc(10px * var(--ai-font-scale)); }
|
|
4708
|
-
.ai-context-meter b { font-size: calc(9px * var(--ai-font-scale)); }
|
|
4709
4699
|
.ai-context-popover-header strong { font-size: calc(12px * var(--ai-font-scale)); }
|
|
4710
4700
|
.ai-context-popover-header small, .ai-context-distribution-label { font-size: calc(10px * var(--ai-font-scale)); }
|
|
4711
4701
|
.ai-context-distribution-label small, .ai-context-distribution-label strong { font-size: calc(9px * var(--ai-font-scale)); }
|