@promptbook/components 0.112.0-48 → 0.112.0-50

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 (45) hide show
  1. package/esm/index.es.js +798 -195
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/src/avatars/avatarAnimationScheduler.d.ts +16 -0
  4. package/esm/src/avatars/avatarPointerTracking.d.ts +16 -0
  5. package/esm/src/avatars/avatarVisibilityTracking.d.ts +17 -0
  6. package/esm/src/avatars/renderAvatarVisual.d.ts +29 -1
  7. package/esm/src/avatars/visuals/octopus3AvatarVisual.d.ts +72 -0
  8. package/esm/src/avatars/visuals/octopus3AvatarVisual.test.d.ts +1 -0
  9. package/esm/src/avatars/visuals/octopusAvatarVisualShared.d.ts +16 -0
  10. package/esm/src/book-components/BookEditor/BookEditor.d.ts +9 -0
  11. package/esm/src/book-components/BookEditor/useBookEditorMonacoLanguage.d.ts +10 -2
  12. package/esm/src/book-components/BookEditor/useBookEditorMonacoStyles.d.ts +2 -1
  13. package/esm/src/book-components/Chat/Chat/ChatMessageRichContent.d.ts +4 -0
  14. package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +12 -3
  15. package/esm/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +1 -0
  16. package/esm/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +2 -1
  17. package/esm/src/book-components/Chat/Chat/renderAdvancedToolCallDetails.d.ts +4 -0
  18. package/esm/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +2 -1
  19. package/esm/src/speech-recognition/OpenAiSpeechRecognition.d.ts +24 -2
  20. package/esm/src/speech-recognition/OpenAiSpeechRecognition.test.d.ts +1 -0
  21. package/esm/src/types/SpeechRecognition.d.ts +4 -0
  22. package/esm/src/version.d.ts +1 -1
  23. package/package.json +1 -1
  24. package/umd/index.umd.js +798 -195
  25. package/umd/index.umd.js.map +1 -1
  26. package/umd/src/avatars/avatarAnimationScheduler.d.ts +16 -0
  27. package/umd/src/avatars/avatarPointerTracking.d.ts +16 -0
  28. package/umd/src/avatars/avatarVisibilityTracking.d.ts +17 -0
  29. package/umd/src/avatars/renderAvatarVisual.d.ts +29 -1
  30. package/umd/src/avatars/visuals/octopus3AvatarVisual.d.ts +72 -0
  31. package/umd/src/avatars/visuals/octopus3AvatarVisual.test.d.ts +1 -0
  32. package/umd/src/avatars/visuals/octopusAvatarVisualShared.d.ts +16 -0
  33. package/umd/src/book-components/BookEditor/BookEditor.d.ts +9 -0
  34. package/umd/src/book-components/BookEditor/useBookEditorMonacoLanguage.d.ts +10 -2
  35. package/umd/src/book-components/BookEditor/useBookEditorMonacoStyles.d.ts +2 -1
  36. package/umd/src/book-components/Chat/Chat/ChatMessageRichContent.d.ts +4 -0
  37. package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +12 -3
  38. package/umd/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +1 -0
  39. package/umd/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +2 -1
  40. package/umd/src/book-components/Chat/Chat/renderAdvancedToolCallDetails.d.ts +4 -0
  41. package/umd/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +2 -1
  42. package/umd/src/speech-recognition/OpenAiSpeechRecognition.d.ts +24 -2
  43. package/umd/src/speech-recognition/OpenAiSpeechRecognition.test.d.ts +1 -0
  44. package/umd/src/types/SpeechRecognition.d.ts +4 -0
  45. package/umd/src/version.d.ts +1 -1
package/esm/index.es.js CHANGED
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
40
40
  * @generated
41
41
  * @see https://github.com/webgptorg/promptbook
42
42
  */
43
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-48';
43
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-50';
44
44
  /**
45
45
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
46
46
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1519,10 +1519,22 @@ function createAvatarRandomFactory(avatarDefinition) {
1519
1519
  */
1520
1520
  function prepareAvatarCanvas(canvas, context, size, devicePixelRatio) {
1521
1521
  const normalizedDevicePixelRatio = Math.max(1, Math.round(devicePixelRatio * 100) / 100);
1522
- canvas.width = Math.round(size * normalizedDevicePixelRatio);
1523
- canvas.height = Math.round(size * normalizedDevicePixelRatio);
1524
- canvas.style.width = `${size}px`;
1525
- canvas.style.height = `${size}px`;
1522
+ const nextCanvasWidth = Math.round(size * normalizedDevicePixelRatio);
1523
+ const nextCanvasHeight = Math.round(size * normalizedDevicePixelRatio);
1524
+ const nextCanvasStyleWidth = `${size}px`;
1525
+ const nextCanvasStyleHeight = `${size}px`;
1526
+ if (canvas.width !== nextCanvasWidth) {
1527
+ canvas.width = nextCanvasWidth;
1528
+ }
1529
+ if (canvas.height !== nextCanvasHeight) {
1530
+ canvas.height = nextCanvasHeight;
1531
+ }
1532
+ if (canvas.style.width !== nextCanvasStyleWidth) {
1533
+ canvas.style.width = nextCanvasStyleWidth;
1534
+ }
1535
+ if (canvas.style.height !== nextCanvasStyleHeight) {
1536
+ canvas.style.height = nextCanvasStyleHeight;
1537
+ }
1526
1538
  context.setTransform(normalizedDevicePixelRatio, 0, 0, normalizedDevicePixelRatio, 0, 0);
1527
1539
  context.clearRect(0, 0, size, size);
1528
1540
  }
@@ -18716,8 +18728,8 @@ const DEFAULT_BOOK = padBook(validateBook(spaceTrim$1(`
18716
18728
  // <- [🐱‍🚀] Buttons into genesis book
18717
18729
  // <- TODO: [🐱‍🚀] generateBookBoilerplate and deprecate `DEFAULT_BOOK`
18718
18730
 
18719
- var css_248z$d = ".BookEditor-module_BookEditor__s-0PU{width:100%}.BookEditor-module_bookEditorContainer__wLMwM{box-sizing:border-box;height:100%;padding:10px 25px 0;position:relative;width:100%}.BookEditor-module_bookEditorContainer__wLMwM.BookEditor-module_isVerbose__VQ6iL{background-color:rgba(0,0,0,.05);outline:1px dotted rgba(0,0,0,.5)}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);overflow:hidden;padding-top:10px;transition:box-shadow .2s ease-in-out}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorWrapper__twppD{overflow:visible}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_bookEditorWrapper__twppD.BookEditor-module_isBorderRadiusDisabled__h1I3v{border-radius:0}.BookEditor-module_dropOverlay__xWWoX{align-items:center;background-color:rgba(0,0,0,.5);bottom:0;color:#fff;display:flex;font-size:1.5rem;justify-content:center;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:100}.BookEditor-module_bookEditorActionbar__KW6dc{position:absolute;right:55px;top:10px;z-index:100}.BookEditor-module_fullscreen__rktsl{border:none;border-radius:0;bottom:0;box-shadow:none;height:100%;left:0;padding-top:50px;position:fixed;right:0;top:0;width:100%;z-index:9999}.BookEditor-module_button__hS390{align-items:center;background-color:#fff;border:1px solid #d1d5db;border-radius:.375rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);color:#374151;cursor:pointer;display:inline-flex;gap:.5rem;padding:.5rem 1rem;transition:all .2s ease-in-out}.BookEditor-module_button__hS390:hover{background-color:#f9fafb;border-color:#b7bcce;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.BookEditor-module_savedNotification__OiX9L{align-items:center;animation:BookEditor-module_fadeOut__q8JnR 2s forwards;background-color:rgba(0,0,0,.7);border-radius:.5rem;color:#fff;display:flex;font-size:1.25rem;gap:.5rem;left:50%;padding:1rem 2rem;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:1000}.BookEditor-module_uploadPanel__2JJtD{background:hsla(0,0%,100%,.98);border:1px solid rgba(209,213,219,.9);border-radius:12px;bottom:20px;box-shadow:0 12px 30px rgba(15,23,42,.15);display:flex;flex-direction:column;gap:10px;max-width:calc(100% - 40px);padding:12px;position:absolute;right:20px;width:420px;z-index:220}.BookEditor-module_uploadPanelHeader__pdJd2{align-items:center;display:flex;gap:12px;justify-content:space-between}.BookEditor-module_uploadPanelTitle__TJIVF{color:#111827;font-size:.95rem;font-weight:600}.BookEditor-module_uploadPanelHeaderMeta__Xw0uI{color:#6b7280;font-size:.75rem}.BookEditor-module_uploadPanelSummary__rwSbG{color:#6b7280;display:grid;font-size:.75rem;gap:4px 12px;grid-template-columns:1fr 1fr}.BookEditor-module_uploadPanelProgressBar__a6pjf{background:#e5e7eb;border-radius:999px;height:6px;overflow:hidden}.BookEditor-module_uploadPanelProgressFill__l-TKR{background:linear-gradient(90deg,#2563eb,#10b981);height:100%;transition:width .2s ease}.BookEditor-module_uploadPanelList__VxEd5{display:flex;flex-direction:column;gap:8px;max-height:220px;overflow-y:auto;padding-right:4px}.BookEditor-module_uploadRow__QiSFg{background:#fff;border:1px solid #e5e7eb;border-radius:10px;display:flex;flex-direction:column;gap:6px;padding:8px}.BookEditor-module_uploadRowHeader__po0j5{align-items:center;display:flex;gap:8px;justify-content:space-between}.BookEditor-module_uploadRowName__doQRO{color:#111827;font-size:.8rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.BookEditor-module_uploadRowStatus__jsUb-{color:#6b7280;font-size:.7rem}.BookEditor-module_uploadRowMeta__1lz9h{color:#6b7280;display:flex;font-size:.7rem;justify-content:space-between}.BookEditor-module_uploadRowProgressBar__NoBA7{background:#e5e7eb;border-radius:999px;height:4px;overflow:hidden}.BookEditor-module_uploadRowProgressFill__TrP7e{background:#3b82f6;height:100%;transition:width .2s ease}.BookEditor-module_uploadRowActions__5Y1Mq{display:flex;gap:6px}.BookEditor-module_uploadActionButton__CqJrr{background:#f9fafb;border:1px solid #d1d5db;border-radius:6px;color:#374151;cursor:pointer;font-size:.7rem;padding:2px 8px;transition:all .15s ease-in-out}.BookEditor-module_uploadActionButton__CqJrr:hover{background:#eef2f7;border-color:#cbd5f5}.BookEditor-module_uploadRowError__eEHWw{color:#b91c1c;font-size:.7rem}@keyframes BookEditor-module_fadeOut__q8JnR{0%{opacity:0}10%{opacity:1}70%{opacity:1}to{opacity:0}}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQ0FFSSxVQUNKLENBRUEsOENBS0kscUJBQXNCLENBSHRCLFdBQVksQ0FFWixtQkFBb0IsQ0FEcEIsaUJBQWtCLENBRmxCLFVBS0osQ0FFQSxpRkFFSSxnQ0FBcUMsQ0FDckMsaUNBRUosQ0FFQSxvQ0FDSSwwQkFDSixDQUVBLDRDQUtJLHFCQUF1QixDQUR2QixxQ0FBMEMsQ0FGMUMsa0JBQW1CLENBSW5CLHNDQUEyQyxDQUwzQyxlQUFnQixDQUVoQixnQkFBaUIsQ0FJakIscUNBQ0osQ0FDQSxnRkFFSSxnQkFFSixDQUVBLGtEQUNJLHVFQUNKLENBVUEsNEZBQ0ksZUFDSixDQUVBLHNDQVNJLGtCQUFtQixDQUhuQiwrQkFBb0MsQ0FEcEMsUUFBUyxDQUVULFVBQVksQ0FDWixZQUFhLENBR2IsZ0JBQWlCLENBRGpCLHNCQUF1QixDQVB2QixNQUFPLENBVVAsbUJBQW9CLENBWnBCLGlCQUFrQixDQUdsQixPQUFRLENBRlIsS0FBTSxDQVVOLFdBRUosQ0FRQSw4Q0FDSSxpQkFBa0IsQ0FFbEIsVUFBVyxDQURYLFFBQVMsQ0FFVCxXQUNKLENBRUEscUNBV0ksV0FBWSxDQUZaLGVBQWdCLENBSmhCLFFBQVMsQ0FPVCxlQUFnQixDQUxoQixXQUFZLENBSlosTUFBTyxDQU9QLGdCQUFpQixDQVRqQixjQUFlLENBR2YsT0FBUSxDQUZSLEtBQU0sQ0FJTixVQUFXLENBRVgsWUFLSixDQUVBLGlDQU9JLGtCQUFtQixDQU5uQixxQkFBc0IsQ0FDdEIsd0JBQXlCLENBQ3pCLHFCQUF1QixDQU92QixzQ0FBMkMsQ0FEM0MsYUFBYyxDQUpkLGNBQWUsQ0FDZixtQkFBb0IsQ0FFcEIsU0FBVyxDQUpYLGtCQUFvQixDQU9wQiw4QkFDSixDQUVBLHVDQUNJLHdCQUF5QixDQUN6QixvQkFBcUIsQ0FDckIsaUVBQ0osQ0FFQSw0Q0FhSSxrQkFBbUIsQ0FFbkIsc0RBQThCLENBVjlCLCtCQUFvQyxDQUdwQyxtQkFBcUIsQ0FGckIsVUFBWSxDQU1aLFlBQWEsQ0FIYixpQkFBa0IsQ0FLbEIsU0FBVyxDQVhYLFFBQVMsQ0FJVCxpQkFBa0IsQ0FJbEIsbUJBQW9CLENBVnBCLGlCQUFrQixDQUNsQixPQUFRLENBRVIsOEJBQWdDLENBTWhDLFlBTUosQ0FFQSxzQ0FNSSw4QkFBcUMsQ0FDckMscUNBQTBDLENBQzFDLGtCQUFtQixDQUxuQixXQUFZLENBTVoseUNBQThDLENBRTlDLFlBQWEsQ0FDYixxQkFBc0IsQ0FDdEIsUUFBUyxDQVJULDJCQUE0QixDQUs1QixZQUFhLENBVGIsaUJBQWtCLENBQ2xCLFVBQVcsQ0FFWCxXQUFZLENBVVosV0FDSixDQUVBLDRDQUVJLGtCQUFtQixDQURuQixZQUFhLENBR2IsUUFBUyxDQURULDZCQUVKLENBRUEsMkNBR0ksYUFBYyxDQURkLGdCQUFrQixDQURsQixlQUdKLENBRUEsZ0RBRUksYUFBYyxDQURkLGdCQUVKLENBRUEsNkNBS0ksYUFBYyxDQUpkLFlBQWEsQ0FHYixnQkFBa0IsQ0FEbEIsWUFBYSxDQURiLDZCQUlKLENBRUEsaURBRUksa0JBQW1CLENBQ25CLG1CQUFvQixDQUZwQixVQUFXLENBR1gsZUFDSixDQUVBLGtEQUVJLGlEQUFvRCxDQURwRCxXQUFZLENBRVoseUJBQ0osQ0FFQSwwQ0FDSSxZQUFhLENBQ2IscUJBQXNCLENBQ3RCLE9BQVEsQ0FDUixnQkFBaUIsQ0FDakIsZUFBZ0IsQ0FDaEIsaUJBQ0osQ0FFQSxvQ0FPSSxlQUFnQixDQU5oQix3QkFBeUIsQ0FDekIsa0JBQW1CLENBRW5CLFlBQWEsQ0FDYixxQkFBc0IsQ0FDdEIsT0FBUSxDQUhSLFdBS0osQ0FFQSwwQ0FFSSxrQkFBbUIsQ0FEbkIsWUFBYSxDQUdiLE9BQVEsQ0FEUiw2QkFFSixDQUVBLHdDQUdJLGFBQWMsQ0FGZCxlQUFpQixDQUNqQixlQUFnQixDQUVoQixlQUFnQixDQUNoQixzQkFBdUIsQ0FDdkIsa0JBQ0osQ0FFQSwwQ0FFSSxhQUFjLENBRGQsZUFFSixDQUVBLHdDQUlJLGFBQWMsQ0FIZCxZQUFhLENBRWIsZUFBaUIsQ0FEakIsNkJBR0osQ0FFQSwrQ0FFSSxrQkFBbUIsQ0FDbkIsbUJBQW9CLENBRnBCLFVBQVcsQ0FHWCxlQUNKLENBRUEsZ0RBRUksa0JBQW1CLENBRG5CLFdBQVksQ0FFWix5QkFDSixDQUVBLDJDQUNJLFlBQWEsQ0FDYixPQUNKLENBRUEsNkNBRUksa0JBQW1CLENBRG5CLHdCQUF5QixDQUt6QixpQkFBa0IsQ0FIbEIsYUFBYyxDQUlkLGNBQWUsQ0FIZixlQUFpQixDQUNqQixlQUFnQixDQUdoQiwrQkFDSixDQUVBLG1EQUNJLGtCQUFtQixDQUNuQixvQkFDSixDQUVBLHlDQUVJLGFBQWMsQ0FEZCxlQUVKLENBRUEsNENBQ0ksR0FDSSxTQUNKLENBQ0EsSUFDSSxTQUNKLENBQ0EsSUFDSSxTQUNKLENBQ0EsR0FDSSxTQUNKLENBQ0oiLCJmaWxlIjoiQm9va0VkaXRvci5tb2R1bGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLkJvb2tFZGl0b3Ige1xuICAgIC8qIGhlaWdodDogNDUwcHg7ICovXG4gICAgd2lkdGg6IDEwMCU7XG59XG5cbi5ib29rRWRpdG9yQ29udGFpbmVyIHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDEwcHggMjVweCAwO1xuICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG59XG5cbi5ib29rRWRpdG9yQ29udGFpbmVyLmlzVmVyYm9zZSB7XG4gICAgLyoqL1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC4wNSk7XG4gICAgb3V0bGluZTogMXB4IGRvdHRlZCByZ2JhKDAsIDAsIDAsIDAuNSk7XG4gICAgLyoqL1xufVxuXG4uaXNWZXJib3NlIHtcbiAgICBvdXRsaW5lOiAycHggZG90dGVkIHJnYigyNTUgMTE3IDM4KTtcbn1cblxuLmJvb2tFZGl0b3JXcmFwcGVyIHtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIGJvcmRlci1yYWRpdXM6IDFyZW07XG4gICAgcGFkZGluZy10b3A6IDEwcHg7XG4gICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyMDksIDIxMywgMjE5LCAwLjgpO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHdoaXRlO1xuICAgIGJveC1zaGFkb3c6IDAgMXB4IDJweCAwIHJnYmEoMCwgMCwgMCwgMC4wNSk7XG4gICAgdHJhbnNpdGlvbjogYm94LXNoYWRvdyAwLjJzIGVhc2UtaW4tb3V0O1xufVxuLmlzVmVyYm9zZSAuYm9va0VkaXRvcldyYXBwZXIge1xuICAgIC8qKi9cbiAgICBvdmVyZmxvdzogdmlzaWJsZTtcbiAgICAvKiovXG59XG5cbi5ib29rRWRpdG9yV3JhcHBlcjpob3ZlciB7XG4gICAgYm94LXNoYWRvdzogMCA0cHggNnB4IC0xcHggcmdiYSgwLCAwLCAwLCAwLjEpLCAwIDJweCA0cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMDYpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6Zm9jdXMtd2l0aGluIHtcbiAgICAvKlxuICAgIG91dGxpbmU6IDJweCBzb2xpZCB0cmFuc3BhcmVudDtcbiAgICBvdXRsaW5lLW9mZnNldDogMnB4O1xuICAgIGJveC1zaGFkb3c6IDAgMCAwIDNweCByZ2JhKDk5LCAxMDIsIDI0MSwgMC40KTtcbiAgICAqL1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIuaXNCb3JkZXJSYWRpdXNEaXNhYmxlZCB7XG4gICAgYm9yZGVyLXJhZGl1czogMDtcbn1cblxuLmRyb3BPdmVybGF5IHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwO1xuICAgIGxlZnQ6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogd2hpdGU7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xuICAgIHotaW5kZXg6IDEwMDtcbiAgICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLypcbi5ib29rRWRpdG9yQ29udGFpbmVyIDpnbG9iYWwoLnZpZXctbGluZSkge1xuICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZWVlOyAvKiA8LSBOb3RlOiBgUFJPTVBUQk9PS19TWU5UQVhfQ09MT1JTLkxJTkVgICogL1xufVxuKi9cblxuLmJvb2tFZGl0b3JBY3Rpb25iYXIge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDEwcHg7XG4gICAgcmlnaHQ6IDU1cHg7XG4gICAgei1pbmRleDogMTAwO1xufVxuXG4uZnVsbHNjcmVlbiB7XG4gICAgcG9zaXRpb246IGZpeGVkO1xuICAgIHRvcDogMDtcbiAgICBsZWZ0OiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgei1pbmRleDogOTk5OTtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xuICAgIHBhZGRpbmctdG9wOiA1MHB4O1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBib3gtc2hhZG93OiBub25lO1xufVxuXG4uYnV0dG9uIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkICNkMWQ1ZGI7XG4gICAgYm9yZGVyLXJhZGl1czogMC4zNzVyZW07XG4gICAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiAwLjVyZW07XG4gICAgY29sb3I6ICMzNzQxNTE7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycyBlYXNlLWluLW91dDtcbn1cblxuLmJ1dHRvbjpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2Y5ZmFmYjtcbiAgICBib3JkZXItY29sb3I6ICNiN2JjY2U7XG4gICAgYm94LXNoYWRvdzogMCAxcHggM3B4IDAgcmdiYSgwLCAwLCAwLCAwLjEpLCAwIDFweCAycHggMCByZ2JhKDAsIDAsIDAsIDAuMDYpO1xufVxuXG4uc2F2ZWROb3RpZmljYXRpb24ge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiA1MCU7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjcpO1xuICAgIGNvbG9yOiB3aGl0ZTtcbiAgICBwYWRkaW5nOiAxcmVtIDJyZW07XG4gICAgYm9yZGVyLXJhZGl1czogMC41cmVtO1xuICAgIGZvbnQtc2l6ZTogMS4yNXJlbTtcbiAgICB6LWluZGV4OiAxMDAwO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IDAuNXJlbTtcbiAgICBhbmltYXRpb246IGZhZGVPdXQgMnMgZm9yd2FyZHM7XG59XG5cbi51cGxvYWRQYW5lbCB7XG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgIHJpZ2h0OiAyMHB4O1xuICAgIGJvdHRvbTogMjBweDtcbiAgICB3aWR0aDogNDIwcHg7XG4gICAgbWF4LXdpZHRoOiBjYWxjKDEwMCUgLSA0MHB4KTtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuOTgpO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjA5LCAyMTMsIDIxOSwgMC45KTtcbiAgICBib3JkZXItcmFkaXVzOiAxMnB4O1xuICAgIGJveC1zaGFkb3c6IDAgMTJweCAzMHB4IHJnYmEoMTUsIDIzLCA0MiwgMC4xNSk7XG4gICAgcGFkZGluZzogMTJweDtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZ2FwOiAxMHB4O1xuICAgIHotaW5kZXg6IDIyMDtcbn1cblxuLnVwbG9hZFBhbmVsSGVhZGVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgIGdhcDogMTJweDtcbn1cblxuLnVwbG9hZFBhbmVsVGl0bGUge1xuICAgIGZvbnQtd2VpZ2h0OiA2MDA7XG4gICAgZm9udC1zaXplOiAwLjk1cmVtO1xuICAgIGNvbG9yOiAjMTExODI3O1xufVxuXG4udXBsb2FkUGFuZWxIZWFkZXJNZXRhIHtcbiAgICBmb250LXNpemU6IDAuNzVyZW07XG4gICAgY29sb3I6ICM2YjcyODA7XG59XG5cbi51cGxvYWRQYW5lbFN1bW1hcnkge1xuICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiAxZnIgMWZyO1xuICAgIGdhcDogNHB4IDEycHg7XG4gICAgZm9udC1zaXplOiAwLjc1cmVtO1xuICAgIGNvbG9yOiAjNmI3MjgwO1xufVxuXG4udXBsb2FkUGFuZWxQcm9ncmVzc0JhciB7XG4gICAgaGVpZ2h0OiA2cHg7XG4gICAgYmFja2dyb3VuZDogI2U1ZTdlYjtcbiAgICBib3JkZXItcmFkaXVzOiA5OTlweDtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xufVxuXG4udXBsb2FkUGFuZWxQcm9ncmVzc0ZpbGwge1xuICAgIGhlaWdodDogMTAwJTtcbiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoOTBkZWcsICMyNTYzZWIsICMxMGI5ODEpO1xuICAgIHRyYW5zaXRpb246IHdpZHRoIDAuMnMgZWFzZTtcbn1cblxuLnVwbG9hZFBhbmVsTGlzdCB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIGdhcDogOHB4O1xuICAgIG1heC1oZWlnaHQ6IDIyMHB4O1xuICAgIG92ZXJmbG93LXk6IGF1dG87XG4gICAgcGFkZGluZy1yaWdodDogNHB4O1xufVxuXG4udXBsb2FkUm93IHtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjZTVlN2ViO1xuICAgIGJvcmRlci1yYWRpdXM6IDEwcHg7XG4gICAgcGFkZGluZzogOHB4O1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBnYXA6IDZweDtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmO1xufVxuXG4udXBsb2FkUm93SGVhZGVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgIGdhcDogOHB4O1xufVxuXG4udXBsb2FkUm93TmFtZSB7XG4gICAgZm9udC1zaXplOiAwLjhyZW07XG4gICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICBjb2xvcjogIzExMTgyNztcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG59XG5cbi51cGxvYWRSb3dTdGF0dXMge1xuICAgIGZvbnQtc2l6ZTogMC43cmVtO1xuICAgIGNvbG9yOiAjNmI3MjgwO1xufVxuXG4udXBsb2FkUm93TWV0YSB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgY29sb3I6ICM2YjcyODA7XG59XG5cbi51cGxvYWRSb3dQcm9ncmVzc0JhciB7XG4gICAgaGVpZ2h0OiA0cHg7XG4gICAgYmFja2dyb3VuZDogI2U1ZTdlYjtcbiAgICBib3JkZXItcmFkaXVzOiA5OTlweDtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xufVxuXG4udXBsb2FkUm93UHJvZ3Jlc3NGaWxsIHtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZDogIzNiODJmNjtcbiAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjJzIGVhc2U7XG59XG5cbi51cGxvYWRSb3dBY3Rpb25zIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogNnB4O1xufVxuXG4udXBsb2FkQWN0aW9uQnV0dG9uIHtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjZDFkNWRiO1xuICAgIGJhY2tncm91bmQ6ICNmOWZhZmI7XG4gICAgY29sb3I6ICMzNzQxNTE7XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgcGFkZGluZzogMnB4IDhweDtcbiAgICBib3JkZXItcmFkaXVzOiA2cHg7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIHRyYW5zaXRpb246IGFsbCAwLjE1cyBlYXNlLWluLW91dDtcbn1cblxuLnVwbG9hZEFjdGlvbkJ1dHRvbjpob3ZlciB7XG4gICAgYmFja2dyb3VuZDogI2VlZjJmNztcbiAgICBib3JkZXItY29sb3I6ICNjYmQ1ZjU7XG59XG5cbi51cGxvYWRSb3dFcnJvciB7XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgY29sb3I6ICNiOTFjMWM7XG59XG5cbkBrZXlmcmFtZXMgZmFkZU91dCB7XG4gICAgMCUge1xuICAgICAgICBvcGFjaXR5OiAwO1xuICAgIH1cbiAgICAxMCUge1xuICAgICAgICBvcGFjaXR5OiAxO1xuICAgIH1cbiAgICA3MCUge1xuICAgICAgICBvcGFjaXR5OiAxO1xuICAgIH1cbiAgICAxMDAlIHtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICB9XG59XG4iXX0= */";
18720
- var styles$d = {"BookEditor":"BookEditor-module_BookEditor__s-0PU","bookEditorContainer":"BookEditor-module_bookEditorContainer__wLMwM","isVerbose":"BookEditor-module_isVerbose__VQ6iL","bookEditorWrapper":"BookEditor-module_bookEditorWrapper__twppD","isBorderRadiusDisabled":"BookEditor-module_isBorderRadiusDisabled__h1I3v","dropOverlay":"BookEditor-module_dropOverlay__xWWoX","bookEditorActionbar":"BookEditor-module_bookEditorActionbar__KW6dc","fullscreen":"BookEditor-module_fullscreen__rktsl","button":"BookEditor-module_button__hS390","savedNotification":"BookEditor-module_savedNotification__OiX9L","fadeOut":"BookEditor-module_fadeOut__q8JnR","uploadPanel":"BookEditor-module_uploadPanel__2JJtD","uploadPanelHeader":"BookEditor-module_uploadPanelHeader__pdJd2","uploadPanelTitle":"BookEditor-module_uploadPanelTitle__TJIVF","uploadPanelHeaderMeta":"BookEditor-module_uploadPanelHeaderMeta__Xw0uI","uploadPanelSummary":"BookEditor-module_uploadPanelSummary__rwSbG","uploadPanelProgressBar":"BookEditor-module_uploadPanelProgressBar__a6pjf","uploadPanelProgressFill":"BookEditor-module_uploadPanelProgressFill__l-TKR","uploadPanelList":"BookEditor-module_uploadPanelList__VxEd5","uploadRow":"BookEditor-module_uploadRow__QiSFg","uploadRowHeader":"BookEditor-module_uploadRowHeader__po0j5","uploadRowName":"BookEditor-module_uploadRowName__doQRO","uploadRowStatus":"BookEditor-module_uploadRowStatus__jsUb-","uploadRowMeta":"BookEditor-module_uploadRowMeta__1lz9h","uploadRowProgressBar":"BookEditor-module_uploadRowProgressBar__NoBA7","uploadRowProgressFill":"BookEditor-module_uploadRowProgressFill__TrP7e","uploadRowActions":"BookEditor-module_uploadRowActions__5Y1Mq","uploadActionButton":"BookEditor-module_uploadActionButton__CqJrr","uploadRowError":"BookEditor-module_uploadRowError__eEHWw"};
18731
+ var css_248z$d = ".BookEditor-module_BookEditor__s-0PU{width:100%}.BookEditor-module_bookEditorContainer__wLMwM{box-sizing:border-box;height:100%;padding:10px 25px 0;position:relative;width:100%}.BookEditor-module_bookEditorContainer__wLMwM.BookEditor-module_isVerbose__VQ6iL{background-color:rgba(0,0,0,.05);outline:1px dotted rgba(0,0,0,.5)}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);overflow:hidden;padding-top:10px;transition:box-shadow .2s ease-in-out}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorWrapper__twppD{overflow:visible}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_bookEditorWrapper__twppD{background:linear-gradient(180deg,rgba(15,23,42,.98),rgba(8,15,28,.98));border-color:rgba(51,65,85,.92);box-shadow:0 20px 45px rgba(2,6,23,.4)}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 24px 50px rgba(2,6,23,.48)}.BookEditor-module_bookEditorWrapper__twppD.BookEditor-module_isBorderRadiusDisabled__h1I3v{border-radius:0}.BookEditor-module_dropOverlay__xWWoX{align-items:center;background-color:rgba(0,0,0,.5);bottom:0;color:#fff;display:flex;font-size:1.5rem;justify-content:center;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:100}.BookEditor-module_bookEditorActionbar__KW6dc{position:absolute;right:55px;top:10px;z-index:100}.BookEditor-module_fullscreen__rktsl{border:none;border-radius:0;bottom:0;box-shadow:none;height:100%;left:0;padding-top:50px;position:fixed;right:0;top:0;width:100%;z-index:9999}.BookEditor-module_button__hS390{align-items:center;background-color:#fff;border:1px solid #d1d5db;border-radius:.375rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);color:#374151;cursor:pointer;display:inline-flex;gap:.5rem;padding:.5rem 1rem;transition:all .2s ease-in-out}.BookEditor-module_button__hS390:hover{background-color:#f9fafb;border-color:#b7bcce;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_button__hS390{background-color:rgba(15,23,42,.92);border-color:rgba(71,85,105,.9);box-shadow:0 1px 2px 0 rgba(2,6,23,.35);color:#e2e8f0}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_button__hS390:hover{background-color:rgba(30,41,59,.98);border-color:rgba(125,211,252,.5);box-shadow:0 10px 24px rgba(2,6,23,.35)}.BookEditor-module_savedNotification__OiX9L{align-items:center;animation:BookEditor-module_fadeOut__q8JnR 2s forwards;background-color:rgba(0,0,0,.7);border-radius:.5rem;color:#fff;display:flex;font-size:1.25rem;gap:.5rem;left:50%;padding:1rem 2rem;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:1000}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_savedNotification__OiX9L{background-color:rgba(2,6,23,.86);border:1px solid rgba(51,65,85,.9);color:#e2e8f0}.BookEditor-module_uploadPanel__2JJtD{background:hsla(0,0%,100%,.98);border:1px solid rgba(209,213,219,.9);border-radius:12px;bottom:20px;box-shadow:0 12px 30px rgba(15,23,42,.15);display:flex;flex-direction:column;gap:10px;max-width:calc(100% - 40px);padding:12px;position:absolute;right:20px;width:420px;z-index:220}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanel__2JJtD{background:rgba(8,15,28,.96);border-color:rgba(51,65,85,.9);box-shadow:0 18px 40px rgba(2,6,23,.45)}.BookEditor-module_uploadPanelHeader__pdJd2{align-items:center;display:flex;gap:12px;justify-content:space-between}.BookEditor-module_uploadPanelTitle__TJIVF{color:#111827;font-size:.95rem;font-weight:600}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelTitle__TJIVF{color:#f8fafc}.BookEditor-module_uploadPanelHeaderMeta__Xw0uI{color:#6b7280;font-size:.75rem}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelHeaderMeta__Xw0uI,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelSummary__rwSbG,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowMeta__1lz9h,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowStatus__jsUb-{color:#94a3b8}.BookEditor-module_uploadPanelSummary__rwSbG{color:#6b7280;display:grid;font-size:.75rem;gap:4px 12px;grid-template-columns:1fr 1fr}.BookEditor-module_uploadPanelProgressBar__a6pjf{background:#e5e7eb;border-radius:999px;height:6px;overflow:hidden}.BookEditor-module_uploadPanelProgressFill__l-TKR{background:linear-gradient(90deg,#2563eb,#10b981);height:100%;transition:width .2s ease}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelProgressBar__a6pjf,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowProgressBar__NoBA7{background:#1e293b}.BookEditor-module_uploadPanelList__VxEd5{display:flex;flex-direction:column;gap:8px;max-height:220px;overflow-y:auto;padding-right:4px}.BookEditor-module_uploadRow__QiSFg{background:#fff;border:1px solid #e5e7eb;border-radius:10px;display:flex;flex-direction:column;gap:6px;padding:8px}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRow__QiSFg{background:rgba(15,23,42,.92);border-color:#334155}.BookEditor-module_uploadRowHeader__po0j5{align-items:center;display:flex;gap:8px;justify-content:space-between}.BookEditor-module_uploadRowName__doQRO{color:#111827;font-size:.8rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowName__doQRO{color:#f8fafc}.BookEditor-module_uploadRowStatus__jsUb-{color:#6b7280;font-size:.7rem}.BookEditor-module_uploadRowMeta__1lz9h{color:#6b7280;display:flex;font-size:.7rem;justify-content:space-between}.BookEditor-module_uploadRowProgressBar__NoBA7{background:#e5e7eb;border-radius:999px;height:4px;overflow:hidden}.BookEditor-module_uploadRowProgressFill__TrP7e{background:#3b82f6;height:100%;transition:width .2s ease}.BookEditor-module_uploadRowActions__5Y1Mq{display:flex;gap:6px}.BookEditor-module_uploadActionButton__CqJrr{background:#f9fafb;border:1px solid #d1d5db;border-radius:6px;color:#374151;cursor:pointer;font-size:.7rem;padding:2px 8px;transition:all .15s ease-in-out}.BookEditor-module_uploadActionButton__CqJrr:hover{background:#eef2f7;border-color:#cbd5f5}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadActionButton__CqJrr{background:#0f172a;border-color:#475569;color:#e2e8f0}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadActionButton__CqJrr:hover{background:#1e293b;border-color:#7dd3fc}.BookEditor-module_uploadRowError__eEHWw{color:#b91c1c;font-size:.7rem}@keyframes BookEditor-module_fadeOut__q8JnR{0%{opacity:0}10%{opacity:1}70%{opacity:1}to{opacity:0}}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQ0FFSSxVQUNKLENBRUEsOENBS0kscUJBQXNCLENBSHRCLFdBQVksQ0FFWixtQkFBb0IsQ0FEcEIsaUJBQWtCLENBRmxCLFVBS0osQ0FFQSxpRkFFSSxnQ0FBcUMsQ0FDckMsaUNBRUosQ0FFQSxvQ0FDSSwwQkFDSixDQUVBLDRDQUtJLHFCQUF1QixDQUR2QixxQ0FBMEMsQ0FGMUMsa0JBQW1CLENBSW5CLHNDQUEyQyxDQUwzQyxlQUFnQixDQUVoQixnQkFBaUIsQ0FJakIscUNBQ0osQ0FDQSxnRkFFSSxnQkFFSixDQUVBLGtEQUNJLHVFQUNKLENBRUEsOEdBRUksdUVBQWtGLENBRGxGLCtCQUFvQyxDQUVwQyxzQ0FDSixDQUVBLG9IQUNJLHVDQUNKLENBVUEsNEZBQ0ksZUFDSixDQUVBLHNDQVNJLGtCQUFtQixDQUhuQiwrQkFBb0MsQ0FEcEMsUUFBUyxDQUVULFVBQVksQ0FDWixZQUFhLENBR2IsZ0JBQWlCLENBRGpCLHNCQUF1QixDQVB2QixNQUFPLENBVVAsbUJBQW9CLENBWnBCLGlCQUFrQixDQUdsQixPQUFRLENBRlIsS0FBTSxDQVVOLFdBRUosQ0FRQSw4Q0FDSSxpQkFBa0IsQ0FFbEIsVUFBVyxDQURYLFFBQVMsQ0FFVCxXQUNKLENBRUEscUNBV0ksV0FBWSxDQUZaLGVBQWdCLENBSmhCLFFBQVMsQ0FPVCxlQUFnQixDQUxoQixXQUFZLENBSlosTUFBTyxDQU9QLGdCQUFpQixDQVRqQixjQUFlLENBR2YsT0FBUSxDQUZSLEtBQU0sQ0FJTixVQUFXLENBRVgsWUFLSixDQUVBLGlDQU9JLGtCQUFtQixDQU5uQixxQkFBc0IsQ0FDdEIsd0JBQXlCLENBQ3pCLHFCQUF1QixDQU92QixzQ0FBMkMsQ0FEM0MsYUFBYyxDQUpkLGNBQWUsQ0FDZixtQkFBb0IsQ0FFcEIsU0FBVyxDQUpYLGtCQUFvQixDQU9wQiw4QkFDSixDQUVBLHVDQUNJLHdCQUF5QixDQUN6QixvQkFBcUIsQ0FDckIsaUVBQ0osQ0FFQSxtR0FDSSxtQ0FBd0MsQ0FDeEMsK0JBQW9DLENBRXBDLHVDQUE0QyxDQUQ1QyxhQUVKLENBRUEseUdBQ0ksbUNBQXdDLENBQ3hDLGlDQUFzQyxDQUN0Qyx1Q0FDSixDQUVBLDRDQWFJLGtCQUFtQixDQUVuQixzREFBOEIsQ0FWOUIsK0JBQW9DLENBR3BDLG1CQUFxQixDQUZyQixVQUFZLENBTVosWUFBYSxDQUhiLGlCQUFrQixDQUtsQixTQUFXLENBWFgsUUFBUyxDQUlULGlCQUFrQixDQUlsQixtQkFBb0IsQ0FWcEIsaUJBQWtCLENBQ2xCLE9BQVEsQ0FFUiw4QkFBZ0MsQ0FNaEMsWUFNSixDQUVBLDhHQUNJLGlDQUFzQyxDQUV0QyxrQ0FBdUMsQ0FEdkMsYUFFSixDQUVBLHNDQU1JLDhCQUFxQyxDQUNyQyxxQ0FBMEMsQ0FDMUMsa0JBQW1CLENBTG5CLFdBQVksQ0FNWix5Q0FBOEMsQ0FFOUMsWUFBYSxDQUNiLHFCQUFzQixDQUN0QixRQUFTLENBUlQsMkJBQTRCLENBSzVCLFlBQWEsQ0FUYixpQkFBa0IsQ0FDbEIsVUFBVyxDQUVYLFdBQVksQ0FVWixXQUNKLENBRUEsd0dBQ0ksNEJBQWlDLENBQ2pDLDhCQUFtQyxDQUNuQyx1Q0FDSixDQUVBLDRDQUVJLGtCQUFtQixDQURuQixZQUFhLENBR2IsUUFBUyxDQURULDZCQUVKLENBRUEsMkNBR0ksYUFBYyxDQURkLGdCQUFrQixDQURsQixlQUdKLENBRUEsNkdBQ0ksYUFDSixDQUVBLGdEQUVJLGFBQWMsQ0FEZCxnQkFFSixDQUVBLHViQUlJLGFBQ0osQ0FFQSw2Q0FLSSxhQUFjLENBSmQsWUFBYSxDQUdiLGdCQUFrQixDQURsQixZQUFhLENBRGIsNkJBSUosQ0FFQSxpREFFSSxrQkFBbUIsQ0FDbkIsbUJBQW9CLENBRnBCLFVBQVcsQ0FHWCxlQUNKLENBRUEsa0RBRUksaURBQW9ELENBRHBELFdBQVksQ0FFWix5QkFDSixDQUVBLG9PQUVJLGtCQUNKLENBRUEsMENBQ0ksWUFBYSxDQUNiLHFCQUFzQixDQUN0QixPQUFRLENBQ1IsZ0JBQWlCLENBQ2pCLGVBQWdCLENBQ2hCLGlCQUNKLENBRUEsb0NBT0ksZUFBZ0IsQ0FOaEIsd0JBQXlCLENBQ3pCLGtCQUFtQixDQUVuQixZQUFhLENBQ2IscUJBQXNCLENBQ3RCLE9BQVEsQ0FIUixXQUtKLENBRUEsc0dBRUksNkJBQWtDLENBRGxDLG9CQUVKLENBRUEsMENBRUksa0JBQW1CLENBRG5CLFlBQWEsQ0FHYixPQUFRLENBRFIsNkJBRUosQ0FFQSx3Q0FHSSxhQUFjLENBRmQsZUFBaUIsQ0FDakIsZUFBZ0IsQ0FFaEIsZUFBZ0IsQ0FDaEIsc0JBQXVCLENBQ3ZCLGtCQUNKLENBRUEsMEdBQ0ksYUFDSixDQUVBLDBDQUVJLGFBQWMsQ0FEZCxlQUVKLENBRUEsd0NBSUksYUFBYyxDQUhkLFlBQWEsQ0FFYixlQUFpQixDQURqQiw2QkFHSixDQUVBLCtDQUVJLGtCQUFtQixDQUNuQixtQkFBb0IsQ0FGcEIsVUFBVyxDQUdYLGVBQ0osQ0FFQSxnREFFSSxrQkFBbUIsQ0FEbkIsV0FBWSxDQUVaLHlCQUNKLENBRUEsMkNBQ0ksWUFBYSxDQUNiLE9BQ0osQ0FFQSw2Q0FFSSxrQkFBbUIsQ0FEbkIsd0JBQXlCLENBS3pCLGlCQUFrQixDQUhsQixhQUFjLENBSWQsY0FBZSxDQUhmLGVBQWlCLENBQ2pCLGVBQWdCLENBR2hCLCtCQUNKLENBRUEsbURBQ0ksa0JBQW1CLENBQ25CLG9CQUNKLENBRUEsK0dBRUksa0JBQW1CLENBRG5CLG9CQUFxQixDQUVyQixhQUNKLENBRUEscUhBQ0ksa0JBQW1CLENBQ25CLG9CQUNKLENBRUEseUNBRUksYUFBYyxDQURkLGVBRUosQ0FFQSw0Q0FDSSxHQUNJLFNBQ0osQ0FDQSxJQUNJLFNBQ0osQ0FDQSxJQUNJLFNBQ0osQ0FDQSxHQUNJLFNBQ0osQ0FDSiIsImZpbGUiOiJCb29rRWRpdG9yLm1vZHVsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuQm9va0VkaXRvciB7XG4gICAgLyogaGVpZ2h0OiA0NTBweDsgKi9cbiAgICB3aWR0aDogMTAwJTtcbn1cblxuLmJvb2tFZGl0b3JDb250YWluZXIge1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgcGFkZGluZzogMTBweCAyNXB4IDA7XG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbn1cblxuLmJvb2tFZGl0b3JDb250YWluZXIuaXNWZXJib3NlIHtcbiAgICAvKiovXG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICBvdXRsaW5lOiAxcHggZG90dGVkIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICAvKiovXG59XG5cbi5pc1ZlcmJvc2Uge1xuICAgIG91dGxpbmU6IDJweCBkb3R0ZWQgcmdiKDI1NSAxMTcgMzgpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIge1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgYm9yZGVyLXJhZGl1czogMXJlbTtcbiAgICBwYWRkaW5nLXRvcDogMTBweDtcbiAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDIwOSwgMjEzLCAyMTksIDAuOCk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICB0cmFuc2l0aW9uOiBib3gtc2hhZG93IDAuMnMgZWFzZS1pbi1vdXQ7XG59XG4uaXNWZXJib3NlIC5ib29rRWRpdG9yV3JhcHBlciB7XG4gICAgLyoqL1xuICAgIG92ZXJmbG93OiB2aXNpYmxlO1xuICAgIC8qKi9cbn1cblxuLmJvb2tFZGl0b3JXcmFwcGVyOmhvdmVyIHtcbiAgICBib3gtc2hhZG93OiAwIDRweCA2cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMSksIDAgMnB4IDRweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4wNik7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuYm9va0VkaXRvcldyYXBwZXIge1xuICAgIGJvcmRlci1jb2xvcjogcmdiYSg1MSwgNjUsIDg1LCAwLjkyKTtcbiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTgwZGVnLCByZ2JhKDE1LCAyMywgNDIsIDAuOTgpLCByZ2JhKDgsIDE1LCAyOCwgMC45OCkpO1xuICAgIGJveC1zaGFkb3c6IDAgMjBweCA0NXB4IHJnYmEoMiwgNiwgMjMsIDAuNCk7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuYm9va0VkaXRvcldyYXBwZXI6aG92ZXIge1xuICAgIGJveC1zaGFkb3c6IDAgMjRweCA1MHB4IHJnYmEoMiwgNiwgMjMsIDAuNDgpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6Zm9jdXMtd2l0aGluIHtcbiAgICAvKlxuICAgIG91dGxpbmU6IDJweCBzb2xpZCB0cmFuc3BhcmVudDtcbiAgICBvdXRsaW5lLW9mZnNldDogMnB4O1xuICAgIGJveC1zaGFkb3c6IDAgMCAwIDNweCByZ2JhKDk5LCAxMDIsIDI0MSwgMC40KTtcbiAgICAqL1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIuaXNCb3JkZXJSYWRpdXNEaXNhYmxlZCB7XG4gICAgYm9yZGVyLXJhZGl1czogMDtcbn1cblxuLmRyb3BPdmVybGF5IHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwO1xuICAgIGxlZnQ6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogd2hpdGU7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xuICAgIHotaW5kZXg6IDEwMDtcbiAgICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLypcbi5ib29rRWRpdG9yQ29udGFpbmVyIDpnbG9iYWwoLnZpZXctbGluZSkge1xuICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZWVlOyAvKiA8LSBOb3RlOiBgUFJPTVBUQk9PS19TWU5UQVhfQ09MT1JTLkxJTkVgICogL1xufVxuKi9cblxuLmJvb2tFZGl0b3JBY3Rpb25iYXIge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDEwcHg7XG4gICAgcmlnaHQ6IDU1cHg7XG4gICAgei1pbmRleDogMTAwO1xufVxuXG4uZnVsbHNjcmVlbiB7XG4gICAgcG9zaXRpb246IGZpeGVkO1xuICAgIHRvcDogMDtcbiAgICBsZWZ0OiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgei1pbmRleDogOTk5OTtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xuICAgIHBhZGRpbmctdG9wOiA1MHB4O1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBib3gtc2hhZG93OiBub25lO1xufVxuXG4uYnV0dG9uIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkICNkMWQ1ZGI7XG4gICAgYm9yZGVyLXJhZGl1czogMC4zNzVyZW07XG4gICAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiAwLjVyZW07XG4gICAgY29sb3I6ICMzNzQxNTE7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycyBlYXNlLWluLW91dDtcbn1cblxuLmJ1dHRvbjpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2Y5ZmFmYjtcbiAgICBib3JkZXItY29sb3I6ICNiN2JjY2U7XG4gICAgYm94LXNoYWRvdzogMCAxcHggM3B4IDAgcmdiYSgwLCAwLCAwLCAwLjEpLCAwIDFweCAycHggMCByZ2JhKDAsIDAsIDAsIDAuMDYpO1xufVxuXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLmJ1dHRvbiB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgxNSwgMjMsIDQyLCAwLjkyKTtcbiAgICBib3JkZXItY29sb3I6IHJnYmEoNzEsIDg1LCAxMDUsIDAuOSk7XG4gICAgY29sb3I6ICNlMmU4ZjA7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgyLCA2LCAyMywgMC4zNSk7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuYnV0dG9uOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDMwLCA0MSwgNTksIDAuOTgpO1xuICAgIGJvcmRlci1jb2xvcjogcmdiYSgxMjUsIDIxMSwgMjUyLCAwLjUpO1xuICAgIGJveC1zaGFkb3c6IDAgMTBweCAyNHB4IHJnYmEoMiwgNiwgMjMsIDAuMzUpO1xufVxuXG4uc2F2ZWROb3RpZmljYXRpb24ge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiA1MCU7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjcpO1xuICAgIGNvbG9yOiB3aGl0ZTtcbiAgICBwYWRkaW5nOiAxcmVtIDJyZW07XG4gICAgYm9yZGVyLXJhZGl1czogMC41cmVtO1xuICAgIGZvbnQtc2l6ZTogMS4yNXJlbTtcbiAgICB6LWluZGV4OiAxMDAwO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IDAuNXJlbTtcbiAgICBhbmltYXRpb246IGZhZGVPdXQgMnMgZm9yd2FyZHM7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuc2F2ZWROb3RpZmljYXRpb24ge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMiwgNiwgMjMsIDAuODYpO1xuICAgIGNvbG9yOiAjZTJlOGYwO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoNTEsIDY1LCA4NSwgMC45KTtcbn1cblxuLnVwbG9hZFBhbmVsIHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgcmlnaHQ6IDIwcHg7XG4gICAgYm90dG9tOiAyMHB4O1xuICAgIHdpZHRoOiA0MjBweDtcbiAgICBtYXgtd2lkdGg6IGNhbGMoMTAwJSAtIDQwcHgpO1xuICAgIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC45OCk7XG4gICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyMDksIDIxMywgMjE5LCAwLjkpO1xuICAgIGJvcmRlci1yYWRpdXM6IDEycHg7XG4gICAgYm94LXNoYWRvdzogMCAxMnB4IDMwcHggcmdiYSgxNSwgMjMsIDQyLCAwLjE1KTtcbiAgICBwYWRkaW5nOiAxMnB4O1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBnYXA6IDEwcHg7XG4gICAgei1pbmRleDogMjIwO1xufVxuXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLnVwbG9hZFBhbmVsIHtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDgsIDE1LCAyOCwgMC45Nik7XG4gICAgYm9yZGVyLWNvbG9yOiByZ2JhKDUxLCA2NSwgODUsIDAuOSk7XG4gICAgYm94LXNoYWRvdzogMCAxOHB4IDQwcHggcmdiYSgyLCA2LCAyMywgMC40NSk7XG59XG5cbi51cGxvYWRQYW5lbEhlYWRlciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICBnYXA6IDEycHg7XG59XG5cbi51cGxvYWRQYW5lbFRpdGxlIHtcbiAgICBmb250LXdlaWdodDogNjAwO1xuICAgIGZvbnQtc2l6ZTogMC45NXJlbTtcbiAgICBjb2xvcjogIzExMTgyNztcbn1cblxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRQYW5lbFRpdGxlIHtcbiAgICBjb2xvcjogI2Y4ZmFmYztcbn1cblxuLnVwbG9hZFBhbmVsSGVhZGVyTWV0YSB7XG4gICAgZm9udC1zaXplOiAwLjc1cmVtO1xuICAgIGNvbG9yOiAjNmI3MjgwO1xufVxuXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLnVwbG9hZFBhbmVsSGVhZGVyTWV0YSxcbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUGFuZWxTdW1tYXJ5LFxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRSb3dTdGF0dXMsXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLnVwbG9hZFJvd01ldGEge1xuICAgIGNvbG9yOiAjOTRhM2I4O1xufVxuXG4udXBsb2FkUGFuZWxTdW1tYXJ5IHtcbiAgICBkaXNwbGF5OiBncmlkO1xuICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyIDFmcjtcbiAgICBnYXA6IDRweCAxMnB4O1xuICAgIGZvbnQtc2l6ZTogMC43NXJlbTtcbiAgICBjb2xvcjogIzZiNzI4MDtcbn1cblxuLnVwbG9hZFBhbmVsUHJvZ3Jlc3NCYXIge1xuICAgIGhlaWdodDogNnB4O1xuICAgIGJhY2tncm91bmQ6ICNlNWU3ZWI7XG4gICAgYm9yZGVyLXJhZGl1czogOTk5cHg7XG4gICAgb3ZlcmZsb3c6IGhpZGRlbjtcbn1cblxuLnVwbG9hZFBhbmVsUHJvZ3Jlc3NGaWxsIHtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDkwZGVnLCAjMjU2M2ViLCAjMTBiOTgxKTtcbiAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjJzIGVhc2U7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUGFuZWxQcm9ncmVzc0Jhcixcbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUm93UHJvZ3Jlc3NCYXIge1xuICAgIGJhY2tncm91bmQ6ICMxZTI5M2I7XG59XG5cbi51cGxvYWRQYW5lbExpc3Qge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBnYXA6IDhweDtcbiAgICBtYXgtaGVpZ2h0OiAyMjBweDtcbiAgICBvdmVyZmxvdy15OiBhdXRvO1xuICAgIHBhZGRpbmctcmlnaHQ6IDRweDtcbn1cblxuLnVwbG9hZFJvdyB7XG4gICAgYm9yZGVyOiAxcHggc29saWQgI2U1ZTdlYjtcbiAgICBib3JkZXItcmFkaXVzOiAxMHB4O1xuICAgIHBhZGRpbmc6IDhweDtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZ2FwOiA2cHg7XG4gICAgYmFja2dyb3VuZDogI2ZmZjtcbn1cblxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRSb3cge1xuICAgIGJvcmRlci1jb2xvcjogIzMzNDE1NTtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDE1LCAyMywgNDIsIDAuOTIpO1xufVxuXG4udXBsb2FkUm93SGVhZGVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgIGdhcDogOHB4O1xufVxuXG4udXBsb2FkUm93TmFtZSB7XG4gICAgZm9udC1zaXplOiAwLjhyZW07XG4gICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICBjb2xvcjogIzExMTgyNztcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUm93TmFtZSB7XG4gICAgY29sb3I6ICNmOGZhZmM7XG59XG5cbi51cGxvYWRSb3dTdGF0dXMge1xuICAgIGZvbnQtc2l6ZTogMC43cmVtO1xuICAgIGNvbG9yOiAjNmI3MjgwO1xufVxuXG4udXBsb2FkUm93TWV0YSB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgY29sb3I6ICM2YjcyODA7XG59XG5cbi51cGxvYWRSb3dQcm9ncmVzc0JhciB7XG4gICAgaGVpZ2h0OiA0cHg7XG4gICAgYmFja2dyb3VuZDogI2U1ZTdlYjtcbiAgICBib3JkZXItcmFkaXVzOiA5OTlweDtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xufVxuXG4udXBsb2FkUm93UHJvZ3Jlc3NGaWxsIHtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZDogIzNiODJmNjtcbiAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjJzIGVhc2U7XG59XG5cbi51cGxvYWRSb3dBY3Rpb25zIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogNnB4O1xufVxuXG4udXBsb2FkQWN0aW9uQnV0dG9uIHtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjZDFkNWRiO1xuICAgIGJhY2tncm91bmQ6ICNmOWZhZmI7XG4gICAgY29sb3I6ICMzNzQxNTE7XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgcGFkZGluZzogMnB4IDhweDtcbiAgICBib3JkZXItcmFkaXVzOiA2cHg7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIHRyYW5zaXRpb246IGFsbCAwLjE1cyBlYXNlLWluLW91dDtcbn1cblxuLnVwbG9hZEFjdGlvbkJ1dHRvbjpob3ZlciB7XG4gICAgYmFja2dyb3VuZDogI2VlZjJmNztcbiAgICBib3JkZXItY29sb3I6ICNjYmQ1ZjU7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkQWN0aW9uQnV0dG9uIHtcbiAgICBib3JkZXItY29sb3I6ICM0NzU1Njk7XG4gICAgYmFja2dyb3VuZDogIzBmMTcyYTtcbiAgICBjb2xvcjogI2UyZThmMDtcbn1cblxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRBY3Rpb25CdXR0b246aG92ZXIge1xuICAgIGJhY2tncm91bmQ6ICMxZTI5M2I7XG4gICAgYm9yZGVyLWNvbG9yOiAjN2RkM2ZjO1xufVxuXG4udXBsb2FkUm93RXJyb3Ige1xuICAgIGZvbnQtc2l6ZTogMC43cmVtO1xuICAgIGNvbG9yOiAjYjkxYzFjO1xufVxuXG5Aa2V5ZnJhbWVzIGZhZGVPdXQge1xuICAgIDAlIHtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICB9XG4gICAgMTAlIHtcbiAgICAgICAgb3BhY2l0eTogMTtcbiAgICB9XG4gICAgNzAlIHtcbiAgICAgICAgb3BhY2l0eTogMTtcbiAgICB9XG4gICAgMTAwJSB7XG4gICAgICAgIG9wYWNpdHk6IDA7XG4gICAgfVxufVxuIl19 */";
18732
+ var styles$d = {"BookEditor":"BookEditor-module_BookEditor__s-0PU","bookEditorContainer":"BookEditor-module_bookEditorContainer__wLMwM","isVerbose":"BookEditor-module_isVerbose__VQ6iL","bookEditorWrapper":"BookEditor-module_bookEditorWrapper__twppD","isBorderRadiusDisabled":"BookEditor-module_isBorderRadiusDisabled__h1I3v","dropOverlay":"BookEditor-module_dropOverlay__xWWoX","bookEditorActionbar":"BookEditor-module_bookEditorActionbar__KW6dc","fullscreen":"BookEditor-module_fullscreen__rktsl","button":"BookEditor-module_button__hS390","savedNotification":"BookEditor-module_savedNotification__OiX9L","fadeOut":"BookEditor-module_fadeOut__q8JnR","uploadPanel":"BookEditor-module_uploadPanel__2JJtD","uploadPanelHeader":"BookEditor-module_uploadPanelHeader__pdJd2","uploadPanelTitle":"BookEditor-module_uploadPanelTitle__TJIVF","uploadPanelHeaderMeta":"BookEditor-module_uploadPanelHeaderMeta__Xw0uI","uploadPanelSummary":"BookEditor-module_uploadPanelSummary__rwSbG","uploadRowStatus":"BookEditor-module_uploadRowStatus__jsUb-","uploadRowMeta":"BookEditor-module_uploadRowMeta__1lz9h","uploadPanelProgressBar":"BookEditor-module_uploadPanelProgressBar__a6pjf","uploadPanelProgressFill":"BookEditor-module_uploadPanelProgressFill__l-TKR","uploadRowProgressBar":"BookEditor-module_uploadRowProgressBar__NoBA7","uploadPanelList":"BookEditor-module_uploadPanelList__VxEd5","uploadRow":"BookEditor-module_uploadRow__QiSFg","uploadRowHeader":"BookEditor-module_uploadRowHeader__po0j5","uploadRowName":"BookEditor-module_uploadRowName__doQRO","uploadRowProgressFill":"BookEditor-module_uploadRowProgressFill__TrP7e","uploadRowActions":"BookEditor-module_uploadRowActions__5Y1Mq","uploadActionButton":"BookEditor-module_uploadActionButton__CqJrr","uploadRowError":"BookEditor-module_uploadRowError__eEHWw"};
18721
18733
  styleInject(css_248z$d);
18722
18734
 
18723
18735
  /**
@@ -18928,7 +18940,7 @@ function resolveCodeBlockLanguage(language) {
18928
18940
  return CODE_BLOCK_LANGUAGE_ALIASES[normalizedLanguage] || 'plaintext';
18929
18941
  }
18930
18942
 
18931
- var css_248z$c = ".CodeBlock-module_CodeBlock__6K33Z{border:1px solid #444;border-radius:5px;margin:10px 0;max-width:100%;overflow:hidden;width:100%}.CodeBlock-module_CodeBlockHeader__tfOwl{align-items:center;background-color:#2d2d2d;border-bottom:1px solid #444;color:#ccc;display:flex;font-size:.8em;justify-content:space-between;padding:5px 10px}.CodeBlock-module_CodeBlockButtons__rz1VO{display:flex;gap:8px}.CodeBlock-module_CopyButton__M07tp,.CodeBlock-module_CreateAgentButton__kUEnp,.CodeBlock-module_DownloadButton__ZTrzQ{align-items:center;background:transparent;border:none;color:#aaa;cursor:pointer;display:flex;font-size:inherit;gap:5px;padding:0;transition:color .2s}.CodeBlock-module_CopyButton__M07tp:hover,.CodeBlock-module_CreateAgentButton__kUEnp:hover,.CodeBlock-module_DownloadButton__ZTrzQ:hover{color:#fff}.CodeBlock-module_CodeBlock__6K33Z .monaco-editor,.CodeBlock-module_CodeBlock__6K33Z .monaco-editor .overflow-guard{max-width:100%}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvZGVCbG9jay5tb2R1bGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1DQUlJLHFCQUFzQixDQUZ0QixpQkFBa0IsQ0FEbEIsYUFBYyxDQUtkLGNBQWUsQ0FIZixlQUFnQixDQUVoQixVQUVKLENBRUEseUNBUUksa0JBQW1CLENBUG5CLHdCQUF5QixDQUl6Qiw0QkFBNkIsQ0FIN0IsVUFBVyxDQUlYLFlBQWEsQ0FGYixjQUFnQixDQUdoQiw2QkFBOEIsQ0FKOUIsZ0JBTUosQ0FFQSwwQ0FDSSxZQUFhLENBQ2IsT0FDSixDQUVBLHVIQVVJLGtCQUFtQixDQVBuQixzQkFBdUIsQ0FDdkIsV0FBWSxDQUNaLFVBQVcsQ0FDWCxjQUFlLENBR2YsWUFBYSxDQUZiLGlCQUFrQixDQUlsQixPQUFRLENBSFIsU0FBVSxDQUlWLG9CQUNKLENBRUEseUlBR0ksVUFDSixDQUVBLG9IQUVJLGNBQ0oiLCJmaWxlIjoiQ29kZUJsb2NrLm1vZHVsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuQ29kZUJsb2NrIHtcbiAgICBtYXJnaW46IDEwcHggMDtcbiAgICBib3JkZXItcmFkaXVzOiA1cHg7XG4gICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjNDQ0OyAvKiBEYXJrIG1vZGUgYm9yZGVyICovXG4gICAgd2lkdGg6IDEwMCU7XG4gICAgbWF4LXdpZHRoOiAxMDAlO1xufVxuXG4uQ29kZUJsb2NrSGVhZGVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmQyZDJkO1xuICAgIGNvbG9yOiAjY2NjO1xuICAgIHBhZGRpbmc6IDVweCAxMHB4O1xuICAgIGZvbnQtc2l6ZTogMC44ZW07XG4gICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICM0NDQ7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbn1cblxuLkNvZGVCbG9ja0J1dHRvbnMge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZ2FwOiA4cHg7XG59XG5cbi5Db3B5QnV0dG9uLFxuLkRvd25sb2FkQnV0dG9uLFxuLkNyZWF0ZUFnZW50QnV0dG9uIHtcbiAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgICBib3JkZXI6IG5vbmU7XG4gICAgY29sb3I6ICNhYWE7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIGZvbnQtc2l6ZTogaW5oZXJpdDtcbiAgICBwYWRkaW5nOiAwO1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IDVweDtcbiAgICB0cmFuc2l0aW9uOiBjb2xvciAwLjJzO1xufVxuXG4uQ29weUJ1dHRvbjpob3Zlcixcbi5Eb3dubG9hZEJ1dHRvbjpob3Zlcixcbi5DcmVhdGVBZ2VudEJ1dHRvbjpob3ZlciB7XG4gICAgY29sb3I6ICNmZmY7XG59XG5cbi5Db2RlQmxvY2sgOmdsb2JhbCgubW9uYWNvLWVkaXRvciksXG4uQ29kZUJsb2NrIDpnbG9iYWwoLm1vbmFjby1lZGl0b3IgLm92ZXJmbG93LWd1YXJkKSB7XG4gICAgbWF4LXdpZHRoOiAxMDAlO1xufVxuIl19 */";
18943
+ var css_248z$c = ".CodeBlock-module_CodeBlock__6K33Z{background:#fff;border:1px solid #d0d7e2;border-radius:5px;margin:10px 0;max-width:100%;overflow:hidden;width:100%}.CodeBlock-module_CodeBlockHeader__tfOwl{align-items:center;background-color:#f8fafc;border-bottom:1px solid #d0d7e2;color:#475569;display:flex;font-size:.8em;justify-content:space-between;padding:5px 10px}.CodeBlock-module_CodeBlockButtons__rz1VO{display:flex;gap:8px}.CodeBlock-module_CopyButton__M07tp,.CodeBlock-module_CreateAgentButton__kUEnp,.CodeBlock-module_DownloadButton__ZTrzQ{align-items:center;background:transparent;border:none;color:#64748b;cursor:pointer;display:flex;font-size:inherit;gap:5px;padding:0;transition:color .2s}.CodeBlock-module_CopyButton__M07tp:hover,.CodeBlock-module_CreateAgentButton__kUEnp:hover,.CodeBlock-module_DownloadButton__ZTrzQ:hover{color:#0f172a}.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark]{background:#0f172a;border-color:#334155}.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_CodeBlockHeader__tfOwl{background-color:#111827;border-bottom-color:#334155;color:#cbd5e1}.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_CopyButton__M07tp,.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_CreateAgentButton__kUEnp,.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_DownloadButton__ZTrzQ{color:#94a3b8}.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_CopyButton__M07tp:hover,.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_CreateAgentButton__kUEnp:hover,.CodeBlock-module_CodeBlock__6K33Z[data-code-theme=dark] .CodeBlock-module_DownloadButton__ZTrzQ:hover{color:#f8fafc}.CodeBlock-module_CodeBlock__6K33Z .monaco-editor,.CodeBlock-module_CodeBlock__6K33Z .monaco-editor .overflow-guard{max-width:100%}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvZGVCbG9jay5tb2R1bGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1DQUtJLGVBQW1CLENBRG5CLHdCQUF5QixDQUZ6QixpQkFBa0IsQ0FEbEIsYUFBYyxDQU1kLGNBQWUsQ0FKZixlQUFnQixDQUdoQixVQUVKLENBRUEseUNBUUksa0JBQW1CLENBUG5CLHdCQUF5QixDQUl6QiwrQkFBZ0MsQ0FIaEMsYUFBYyxDQUlkLFlBQWEsQ0FGYixjQUFnQixDQUdoQiw2QkFBOEIsQ0FKOUIsZ0JBTUosQ0FFQSwwQ0FDSSxZQUFhLENBQ2IsT0FDSixDQUVBLHVIQVVJLGtCQUFtQixDQVBuQixzQkFBdUIsQ0FDdkIsV0FBWSxDQUNaLGFBQWMsQ0FDZCxjQUFlLENBR2YsWUFBYSxDQUZiLGlCQUFrQixDQUlsQixPQUFRLENBSFIsU0FBVSxDQUlWLG9CQUNKLENBRUEseUlBR0ksYUFDSixDQUVBLHlEQUVJLGtCQUFtQixDQURuQixvQkFFSixDQUVBLGtHQUNJLHdCQUF5QixDQUV6QiwyQkFBNEIsQ0FENUIsYUFFSixDQUVBLGtTQUdJLGFBQ0osQ0FFQSxvVEFHSSxhQUNKLENBRUEsb0hBRUksY0FDSiIsImZpbGUiOiJDb2RlQmxvY2subW9kdWxlLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi5Db2RlQmxvY2sge1xuICAgIG1hcmdpbjogMTBweCAwO1xuICAgIGJvcmRlci1yYWRpdXM6IDVweDtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkICNkMGQ3ZTI7XG4gICAgYmFja2dyb3VuZDogI2ZmZmZmZjtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBtYXgtd2lkdGg6IDEwMCU7XG59XG5cbi5Db2RlQmxvY2tIZWFkZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNmOGZhZmM7XG4gICAgY29sb3I6ICM0NzU1Njk7XG4gICAgcGFkZGluZzogNXB4IDEwcHg7XG4gICAgZm9udC1zaXplOiAwLjhlbTtcbiAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2QwZDdlMjtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuXG4uQ29kZUJsb2NrQnV0dG9ucyB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBnYXA6IDhweDtcbn1cblxuLkNvcHlCdXR0b24sXG4uRG93bmxvYWRCdXR0b24sXG4uQ3JlYXRlQWdlbnRCdXR0b24ge1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBjb2xvcjogIzY0NzQ4YjtcbiAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgZm9udC1zaXplOiBpbmhlcml0O1xuICAgIHBhZGRpbmc6IDA7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGdhcDogNXB4O1xuICAgIHRyYW5zaXRpb246IGNvbG9yIDAuMnM7XG59XG5cbi5Db3B5QnV0dG9uOmhvdmVyLFxuLkRvd25sb2FkQnV0dG9uOmhvdmVyLFxuLkNyZWF0ZUFnZW50QnV0dG9uOmhvdmVyIHtcbiAgICBjb2xvcjogIzBmMTcyYTtcbn1cblxuLkNvZGVCbG9ja1tkYXRhLWNvZGUtdGhlbWU9J2RhcmsnXSB7XG4gICAgYm9yZGVyLWNvbG9yOiAjMzM0MTU1O1xuICAgIGJhY2tncm91bmQ6ICMwZjE3MmE7XG59XG5cbi5Db2RlQmxvY2tbZGF0YS1jb2RlLXRoZW1lPSdkYXJrJ10gLkNvZGVCbG9ja0hlYWRlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzExMTgyNztcbiAgICBjb2xvcjogI2NiZDVlMTtcbiAgICBib3JkZXItYm90dG9tLWNvbG9yOiAjMzM0MTU1O1xufVxuXG4uQ29kZUJsb2NrW2RhdGEtY29kZS10aGVtZT0nZGFyayddIC5Db3B5QnV0dG9uLFxuLkNvZGVCbG9ja1tkYXRhLWNvZGUtdGhlbWU9J2RhcmsnXSAuRG93bmxvYWRCdXR0b24sXG4uQ29kZUJsb2NrW2RhdGEtY29kZS10aGVtZT0nZGFyayddIC5DcmVhdGVBZ2VudEJ1dHRvbiB7XG4gICAgY29sb3I6ICM5NGEzYjg7XG59XG5cbi5Db2RlQmxvY2tbZGF0YS1jb2RlLXRoZW1lPSdkYXJrJ10gLkNvcHlCdXR0b246aG92ZXIsXG4uQ29kZUJsb2NrW2RhdGEtY29kZS10aGVtZT0nZGFyayddIC5Eb3dubG9hZEJ1dHRvbjpob3Zlcixcbi5Db2RlQmxvY2tbZGF0YS1jb2RlLXRoZW1lPSdkYXJrJ10gLkNyZWF0ZUFnZW50QnV0dG9uOmhvdmVyIHtcbiAgICBjb2xvcjogI2Y4ZmFmYztcbn1cblxuLkNvZGVCbG9jayA6Z2xvYmFsKC5tb25hY28tZWRpdG9yKSxcbi5Db2RlQmxvY2sgOmdsb2JhbCgubW9uYWNvLWVkaXRvciAub3ZlcmZsb3ctZ3VhcmQpIHtcbiAgICBtYXgtd2lkdGg6IDEwMCU7XG59XG4iXX0= */";
18932
18944
  var styles$c = {"CodeBlock":"CodeBlock-module_CodeBlock__6K33Z","CodeBlockHeader":"CodeBlock-module_CodeBlockHeader__tfOwl","CodeBlockButtons":"CodeBlock-module_CodeBlockButtons__rz1VO","CopyButton":"CodeBlock-module_CopyButton__M07tp","DownloadButton":"CodeBlock-module_DownloadButton__ZTrzQ","CreateAgentButton":"CodeBlock-module_CreateAgentButton__kUEnp"};
18933
18945
  styleInject(css_248z$c);
18934
18946
 
@@ -18974,7 +18986,7 @@ function createCodeBlockMonacoModelPath(reactId, language) {
18974
18986
  *
18975
18987
  * @private Internal utility of `<ChatMessage />` component
18976
18988
  */
18977
- function CodeBlock({ code, language, className, onCreateAgent }) {
18989
+ function CodeBlock({ code, language, className, onCreateAgent, theme = 'LIGHT' }) {
18978
18990
  const reactId = useId();
18979
18991
  const normalizedLanguage = resolveCodeBlockLanguage(language);
18980
18992
  const isBookLanguage = normalizedLanguage === 'book';
@@ -19007,9 +19019,9 @@ function CodeBlock({ code, language, className, onCreateAgent }) {
19007
19019
  };
19008
19020
  const header = language ? (jsxs("div", { className: styles$c.CodeBlockHeader, children: [jsx("span", { children: language }), jsxs("div", { className: styles$c.CodeBlockButtons, children: [jsx("button", { onClick: handleCopy, className: styles$c.CopyButton, title: "Copy to clipboard", children: copied ? 'Copied!' : 'Copy' }), jsx("button", { onClick: handleDownload, className: styles$c.DownloadButton, title: "Download code", children: "Download" }), isBookLanguage && onCreateAgent && (jsx("button", { onClick: () => onCreateAgent(code), className: styles$c.CreateAgentButton, title: "Create agent from this book", children: "Create Agent" }))] })] })) : null;
19009
19021
  if (isBookLanguage) {
19010
- return (jsxs("div", { className: classNames(styles$c.CodeBlock, className), children: [header, jsx(BookEditor, { value: code, isReadonly: true, height: lines * 25 /* <- [🧠] A bit more than 19px to accommodate BookEditor lines */ })] }));
19022
+ return (jsxs("div", { className: classNames(styles$c.CodeBlock, className), "data-code-theme": theme.toLowerCase(), children: [header, jsx(BookEditor, { value: code, isReadonly: true, height: lines * 25 /* <- [🧠] A bit more than 19px to accommodate BookEditor lines */, theme: theme })] }));
19011
19023
  }
19012
- return (jsxs("div", { className: classNames(styles$c.CodeBlock, className), children: [header, jsx(MonacoEditorWithShadowDom, { height: `${height}px`, language: normalizedLanguage, path: modelPath, value: code, theme: "vs-dark", options: {
19024
+ return (jsxs("div", { className: classNames(styles$c.CodeBlock, className), "data-code-theme": theme.toLowerCase(), children: [header, jsx(MonacoEditorWithShadowDom, { height: `${height}px`, language: normalizedLanguage, path: modelPath, value: code, theme: theme === 'DARK' ? 'vs-dark' : 'vs-light', options: {
19013
19025
  readOnly: true,
19014
19026
  minimap: { enabled: false },
19015
19027
  automaticLayout: true,
@@ -20506,12 +20518,91 @@ const NOTE_LIKE_COMMITMENT_GROUPS = [
20506
20518
  * @private function of BookEditorMonaco
20507
20519
  */
20508
20520
  const BOOK_EDITOR_LANGUAGE_INITIALIZED_FLAG = 'promptbookBookEditorLanguageInitialized';
20521
+ /**
20522
+ * Internal Monaco flag used to avoid re-defining the Book theme when the requested mode stays unchanged.
20523
+ *
20524
+ * @private function of BookEditorMonaco
20525
+ */
20526
+ const BOOK_EDITOR_THEME_MODE_FLAG = 'promptbookBookEditorThemeMode';
20509
20527
  /**
20510
20528
  * Matches fenced code-block delimiters, including optional leading indentation.
20511
20529
  *
20512
20530
  * @private function of BookEditorMonaco
20513
20531
  */
20514
20532
  const CODE_BLOCK_FENCE_REGEX = /^\s*```.*$/;
20533
+ /**
20534
+ * Shared token rules reused by both light and dark Book Monaco themes.
20535
+ *
20536
+ * @private function of BookEditorMonaco
20537
+ */
20538
+ const BOOK_EDITOR_THEME_RULES = [
20539
+ {
20540
+ token: 'title',
20541
+ foreground: PROMPTBOOK_SYNTAX_COLORS.TITLE.toHex(),
20542
+ fontStyle: 'bold underline',
20543
+ },
20544
+ {
20545
+ token: 'commitment',
20546
+ foreground: PROMPTBOOK_SYNTAX_COLORS.COMMITMENT.toHex(),
20547
+ fontStyle: 'bold',
20548
+ },
20549
+ {
20550
+ token: 'note-commitment',
20551
+ foreground: PROMPTBOOK_SYNTAX_COLORS.NOTE_COMMITMENT.toHex(),
20552
+ },
20553
+ {
20554
+ token: 'todo-commitment',
20555
+ foreground: PROMPTBOOK_SYNTAX_COLORS.TODO_COMMITMENT_TEXT.toHex(),
20556
+ background: PROMPTBOOK_SYNTAX_COLORS.TODO_COMMITMENT_BACKGROUND.toHex(),
20557
+ fontStyle: 'bold',
20558
+ },
20559
+ {
20560
+ token: 'parameter',
20561
+ foreground: PROMPTBOOK_SYNTAX_COLORS.PARAMETER.toHex(),
20562
+ fontStyle: 'italic',
20563
+ },
20564
+ {
20565
+ token: 'agent-reference',
20566
+ foreground: PROMPTBOOK_SYNTAX_COLORS.COMMITMENT.toHex(),
20567
+ fontStyle: 'underline',
20568
+ },
20569
+ {
20570
+ token: 'code-block',
20571
+ foreground: PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex(),
20572
+ },
20573
+ ];
20574
+ /**
20575
+ * Re-defines the shared Book Monaco theme according to the requested light/dark mode.
20576
+ *
20577
+ * @private function of BookEditorMonaco
20578
+ */
20579
+ function applyBookEditorMonacoTheme(monaco, theme) {
20580
+ const colors = theme === 'DARK'
20581
+ ? {
20582
+ 'editor.background': '#09111f',
20583
+ 'editor.foreground': '#e2e8f0',
20584
+ 'editorLineNumber.foreground': '#64748b',
20585
+ 'editorLineNumber.activeForeground': '#cbd5e1',
20586
+ 'editorCursor.foreground': '#7dd3fc',
20587
+ 'editor.selectionBackground': '#1d4ed866',
20588
+ 'editor.inactiveSelectionBackground': '#1e3a8a44',
20589
+ 'editor.scrollbarSlider.background': '#334155',
20590
+ 'editor.scrollbarSlider.hoverBackground': '#475569',
20591
+ 'editor.scrollbarSlider.activeBackground': '#64748b',
20592
+ }
20593
+ : {
20594
+ 'editor.scrollbarSlider.background': '#E0E0E0',
20595
+ 'editor.scrollbarSlider.hoverBackground': '#D0D0D0',
20596
+ 'editor.scrollbarSlider.activeBackground': '#C0C0C0',
20597
+ };
20598
+ monaco.editor.defineTheme(BookEditorMonacoConstants.BOOK_THEME_ID, {
20599
+ base: theme === 'DARK' ? 'vs-dark' : 'vs',
20600
+ inherit: true,
20601
+ rules: [...BOOK_EDITOR_THEME_RULES],
20602
+ colors,
20603
+ });
20604
+ monaco.editor.setTheme(BookEditorMonacoConstants.BOOK_THEME_ID);
20605
+ }
20515
20606
  /**
20516
20607
  * Builds a regex that matches one commitment keyword at line start.
20517
20608
  *
@@ -20589,13 +20680,19 @@ function createNoteLikeBodyRules(token, commitmentTransitionRules) {
20589
20680
  *
20590
20681
  * @private function of BookEditorMonaco
20591
20682
  */
20592
- function ensureBookEditorMonacoLanguage(monaco) {
20683
+ function ensureBookEditorMonacoLanguage(monaco, theme = 'LIGHT') {
20593
20684
  const monacoWithLanguageState = monaco;
20594
20685
  if (monacoWithLanguageState[BOOK_EDITOR_LANGUAGE_INITIALIZED_FLAG]) {
20686
+ if (monacoWithLanguageState[BOOK_EDITOR_THEME_MODE_FLAG] !== theme) {
20687
+ applyBookEditorMonacoTheme(monaco, theme);
20688
+ monacoWithLanguageState[BOOK_EDITOR_THEME_MODE_FLAG] = theme;
20689
+ return;
20690
+ }
20595
20691
  monaco.editor.setTheme(BookEditorMonacoConstants.BOOK_THEME_ID);
20596
20692
  return;
20597
20693
  }
20598
20694
  monacoWithLanguageState[BOOK_EDITOR_LANGUAGE_INITIALIZED_FLAG] = true;
20695
+ monacoWithLanguageState[BOOK_EDITOR_THEME_MODE_FLAG] = theme;
20599
20696
  monaco.languages.register({ id: BookEditorMonacoConstants.BOOK_LANGUAGE_ID });
20600
20697
  const commitmentDefinitions = getAllCommitmentDefinitions();
20601
20698
  const commitmentTypes = [...new Set(commitmentDefinitions.map(({ type }) => type))];
@@ -20690,52 +20787,7 @@ function ensureBookEditorMonacoLanguage(monaco) {
20690
20787
  return { links };
20691
20788
  },
20692
20789
  });
20693
- monaco.editor.defineTheme(BookEditorMonacoConstants.BOOK_THEME_ID, {
20694
- base: 'vs',
20695
- inherit: true,
20696
- rules: [
20697
- {
20698
- token: 'title',
20699
- foreground: PROMPTBOOK_SYNTAX_COLORS.TITLE.toHex(),
20700
- fontStyle: 'bold underline',
20701
- },
20702
- {
20703
- token: 'commitment',
20704
- foreground: PROMPTBOOK_SYNTAX_COLORS.COMMITMENT.toHex(),
20705
- fontStyle: 'bold',
20706
- },
20707
- {
20708
- token: 'note-commitment',
20709
- foreground: PROMPTBOOK_SYNTAX_COLORS.NOTE_COMMITMENT.toHex(),
20710
- },
20711
- {
20712
- token: 'todo-commitment',
20713
- foreground: PROMPTBOOK_SYNTAX_COLORS.TODO_COMMITMENT_TEXT.toHex(),
20714
- background: PROMPTBOOK_SYNTAX_COLORS.TODO_COMMITMENT_BACKGROUND.toHex(),
20715
- fontStyle: 'bold',
20716
- },
20717
- {
20718
- token: 'parameter',
20719
- foreground: PROMPTBOOK_SYNTAX_COLORS.PARAMETER.toHex(),
20720
- fontStyle: 'italic',
20721
- },
20722
- {
20723
- token: 'agent-reference',
20724
- foreground: PROMPTBOOK_SYNTAX_COLORS.COMMITMENT.toHex(),
20725
- fontStyle: 'underline',
20726
- },
20727
- {
20728
- token: 'code-block',
20729
- foreground: PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex(),
20730
- },
20731
- ],
20732
- colors: {
20733
- 'editor.scrollbarSlider.background': '#E0E0E0',
20734
- 'editor.scrollbarSlider.hoverBackground': '#D0D0D0',
20735
- 'editor.scrollbarSlider.activeBackground': '#C0C0C0',
20736
- },
20737
- });
20738
- monaco.editor.setTheme(BookEditorMonacoConstants.BOOK_THEME_ID);
20790
+ applyBookEditorMonacoTheme(monaco, theme);
20739
20791
  }
20740
20792
  /**
20741
20793
  * Ensures the mounted Monaco editor model uses Book language and Book theme.
@@ -20748,8 +20800,8 @@ function ensureBookEditorMonacoLanguage(monaco) {
20748
20800
  * @private function of BookEditorMonaco
20749
20801
  */
20750
20802
  function ensureBookEditorMonacoLanguageForEditor(props) {
20751
- const { monaco, monacoEditor } = props;
20752
- ensureBookEditorMonacoLanguage(monaco);
20803
+ const { monaco, monacoEditor, theme = 'LIGHT' } = props;
20804
+ ensureBookEditorMonacoLanguage(monaco, theme);
20753
20805
  const model = monacoEditor.getModel();
20754
20806
  if (!model) {
20755
20807
  return;
@@ -20764,13 +20816,13 @@ function ensureBookEditorMonacoLanguageForEditor(props) {
20764
20816
  *
20765
20817
  * @private function of BookEditorMonaco
20766
20818
  */
20767
- function useBookEditorMonacoLanguage({ monaco }) {
20819
+ function useBookEditorMonacoLanguage({ monaco, theme }) {
20768
20820
  useEffect(() => {
20769
20821
  if (!monaco) {
20770
20822
  return;
20771
20823
  }
20772
- ensureBookEditorMonacoLanguage(monaco);
20773
- }, [monaco]);
20824
+ ensureBookEditorMonacoLanguage(monaco, theme);
20825
+ }, [monaco, theme]);
20774
20826
  }
20775
20827
 
20776
20828
  /**
@@ -20784,9 +20836,13 @@ const BACKGROUND_POSITION_Y_MULTIPLIER = -0.1;
20784
20836
  *
20785
20837
  * @private function of BookEditorMonaco
20786
20838
  */
20787
- function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledContentPaddingLeft, scaledVerticalLineLeft, zoomLevel, }) {
20839
+ function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledContentPaddingLeft, scaledVerticalLineLeft, zoomLevel, theme, }) {
20788
20840
  useEffect(() => {
20789
20841
  const styleId = `notebook-margin-line-style-${instanceClass}`;
20842
+ const lineColor = theme === 'DARK' ? '#1f2937' : PROMPTBOOK_SYNTAX_COLORS.LINE.toHex();
20843
+ const separatorColor = theme === 'DARK' ? '#334155' : PROMPTBOOK_SYNTAX_COLORS.SEPARATOR.toHex();
20844
+ const codeBlockBackground = theme === 'DARK' ? '#0f172a99' : '#f5f5f566';
20845
+ const codeBlockBorderColor = theme === 'DARK' ? '#38bdf8aa' : PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex();
20790
20846
  let style = document.getElementById(styleId);
20791
20847
  if (!style) {
20792
20848
  style = document.createElement('style');
@@ -20799,7 +20855,7 @@ function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledCont
20799
20855
  /* <- [🚚] */
20800
20856
 
20801
20857
  .${instanceClass} .monaco-editor .view-lines {
20802
- background-image: linear-gradient(to bottom, transparent ${scaledLineHeight - 1}px, ${PROMPTBOOK_SYNTAX_COLORS.LINE.toHex()} ${scaledLineHeight - 1}px);
20858
+ background-image: linear-gradient(to bottom, transparent ${scaledLineHeight - 1}px, ${lineColor} ${scaledLineHeight - 1}px);
20803
20859
  background-size: calc(100% + ${scaledContentPaddingLeft}px) ${scaledLineHeight}px;
20804
20860
  background-position-x: -${scaledContentPaddingLeft}px;
20805
20861
  background-position-y: ${scaledLineHeight * BACKGROUND_POSITION_Y_MULTIPLIER}px;
@@ -20811,7 +20867,7 @@ function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledCont
20811
20867
  top: 0;
20812
20868
  bottom: 0;
20813
20869
  width: 1px;
20814
- background-color: ${PROMPTBOOK_SYNTAX_COLORS.LINE.toHex()};
20870
+ background-color: ${lineColor};
20815
20871
  z-index: 10;
20816
20872
  }
20817
20873
 
@@ -20819,8 +20875,8 @@ function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledCont
20819
20875
  background: linear-gradient(
20820
20876
  to bottom,
20821
20877
  transparent ${scaledLineHeight * 0.9 - 2}px,
20822
- ${PROMPTBOOK_SYNTAX_COLORS.SEPARATOR.toHex()} ${scaledLineHeight * 0.9 - 2}px,
20823
- ${PROMPTBOOK_SYNTAX_COLORS.SEPARATOR.toHex()} ${scaledLineHeight * 0.9 + 1}px,
20878
+ ${separatorColor} ${scaledLineHeight * 0.9 - 2}px,
20879
+ ${separatorColor} ${scaledLineHeight * 0.9 + 1}px,
20824
20880
  transparent ${scaledLineHeight * 0.9 + 1}px
20825
20881
  );
20826
20882
  }
@@ -20830,22 +20886,22 @@ function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledCont
20830
20886
  }
20831
20887
 
20832
20888
  .${instanceClass} .monaco-editor .code-block-box {
20833
- background-color: #f5f5f566;
20834
- border-left: 1px solid ${PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex()};
20835
- border-right: 1px solid ${PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex()};
20889
+ background-color: ${codeBlockBackground};
20890
+ border-left: 1px solid ${codeBlockBorderColor};
20891
+ border-right: 1px solid ${codeBlockBorderColor};
20836
20892
  padding-left: ${Math.round(8 * zoomLevel)}px;
20837
20893
  padding-right: ${Math.round(8 * zoomLevel)}px;
20838
20894
  }
20839
20895
 
20840
20896
  .${instanceClass} .monaco-editor .code-block-top {
20841
- border-top: 1px solid ${PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex()};
20897
+ border-top: 1px solid ${codeBlockBorderColor};
20842
20898
  border-top-left-radius: ${Math.round(10 * zoomLevel)}px;
20843
20899
  border-top-right-radius: ${Math.round(10 * zoomLevel)}px;
20844
20900
  overflow: hidden;
20845
20901
  }
20846
20902
 
20847
20903
  .${instanceClass} .monaco-editor .code-block-bottom {
20848
- border-bottom: 1px solid ${PROMPTBOOK_SYNTAX_COLORS.CODE_BLOCK.toHex()};
20904
+ border-bottom: 1px solid ${codeBlockBorderColor};
20849
20905
  border-bottom-left-radius: ${Math.round(10 * zoomLevel)}px;
20850
20906
  border-bottom-right-radius: ${Math.round(10 * zoomLevel)}px;
20851
20907
  overflow: hidden;
@@ -20856,7 +20912,7 @@ function useBookEditorMonacoStyles({ instanceClass, scaledLineHeight, scaledCont
20856
20912
  style === null || style === void 0 ? void 0 : style.remove();
20857
20913
  }
20858
20914
  };
20859
- }, [instanceClass, scaledLineHeight, scaledContentPaddingLeft, scaledVerticalLineLeft, zoomLevel]);
20915
+ }, [instanceClass, scaledLineHeight, scaledContentPaddingLeft, scaledVerticalLineLeft, theme, zoomLevel]);
20860
20916
  }
20861
20917
 
20862
20918
  /**
@@ -21769,7 +21825,7 @@ async function resolveClipboardUploadFiles(dataTransfer) {
21769
21825
  * @private Internal component used by `BookEditor`
21770
21826
  */
21771
21827
  function BookEditorMonaco(props) {
21772
- const { value, onChange, diagnostics, isReadonly, translations, onFileUpload, isUploadButtonShown, isCameraButtonShown, isDownloadButtonShown, isAboutButtonShown = true, isFullscreenButtonShown = true, onFullscreenClick, isFullscreen, zoom = 1, monacoModelPath, hoistedMenuItems, } = props;
21828
+ const { value, onChange, diagnostics, isReadonly, theme = 'LIGHT', translations, onFileUpload, isUploadButtonShown, isCameraButtonShown, isDownloadButtonShown, isAboutButtonShown = true, isFullscreenButtonShown = true, onFullscreenClick, isFullscreen, zoom = 1, monacoModelPath, hoistedMenuItems, } = props;
21773
21829
  const zoomLevel = zoom;
21774
21830
  const scaledLineHeight = Math.round(BookEditorMonacoConstants.LINE_HEIGHT * zoomLevel);
21775
21831
  const scaledContentPaddingLeft = Math.max(8, Math.round(BookEditorMonacoConstants.CONTENT_PADDING_LEFT * zoomLevel));
@@ -21794,7 +21850,7 @@ function BookEditorMonaco(props) {
21794
21850
  onFileUpload,
21795
21851
  });
21796
21852
  const combinedDiagnostics = [...(diagnostics || []), ...createDeprecatedCommitmentDiagnostics(value)];
21797
- useBookEditorMonacoLanguage({ monaco });
21853
+ useBookEditorMonacoLanguage({ monaco, theme });
21798
21854
  useBookEditorMonacoDiagnostics({ monaco, editor, diagnostics: combinedDiagnostics });
21799
21855
  useBookEditorMonacoDecorations({ editor, monaco });
21800
21856
  useBookEditorMonacoStyles({
@@ -21803,6 +21859,7 @@ function BookEditorMonaco(props) {
21803
21859
  scaledLineHeight,
21804
21860
  scaledVerticalLineLeft,
21805
21861
  zoomLevel,
21862
+ theme,
21806
21863
  });
21807
21864
  /**
21808
21865
  * Re-applies Book language + theme to the currently mounted Monaco model.
@@ -21811,9 +21868,9 @@ function BookEditorMonaco(props) {
21811
21868
  if (!editor || !monaco) {
21812
21869
  return;
21813
21870
  }
21814
- ensureBookEditorMonacoLanguageForEditor({ monaco, monacoEditor: editor });
21871
+ ensureBookEditorMonacoLanguageForEditor({ monaco, monacoEditor: editor, theme });
21815
21872
  logBookEditorMonacoDebug(`Re-applied Book Monaco language/theme (${reason}).`);
21816
- }, [editor, monaco]);
21873
+ }, [editor, monaco, theme]);
21817
21874
  useEffect(() => {
21818
21875
  setIsTouchDevice(typeof window !== 'undefined' && window.matchMedia('(pointer: coarse)').matches);
21819
21876
  }, []);
@@ -21920,16 +21977,16 @@ function BookEditorMonaco(props) {
21920
21977
  * Ensures Book language/tokenizer is ready before Monaco creates the editor model.
21921
21978
  */
21922
21979
  const handleBeforeMonacoMount = useCallback((beforeMountMonaco) => {
21923
- ensureBookEditorMonacoLanguage(beforeMountMonaco);
21924
- }, []);
21980
+ ensureBookEditorMonacoLanguage(beforeMountMonaco, theme);
21981
+ }, [theme]);
21925
21982
  /**
21926
21983
  * Re-applies Book language/theme once Monaco editor is mounted.
21927
21984
  */
21928
21985
  const handleMonacoMount = useCallback((mountedEditor, mountedMonaco) => {
21929
21986
  setEditor(mountedEditor);
21930
- ensureBookEditorMonacoLanguageForEditor({ monaco: mountedMonaco, monacoEditor: mountedEditor });
21987
+ ensureBookEditorMonacoLanguageForEditor({ monaco: mountedMonaco, monacoEditor: mountedEditor, theme });
21931
21988
  logBookEditorMonacoDebug('Mounted Monaco editor and re-applied Book language/theme.');
21932
- }, []);
21989
+ }, [theme]);
21933
21990
  const handleDragOver = useCallback((event) => {
21934
21991
  event.preventDefault();
21935
21992
  setIsDragOver(true);
@@ -22035,7 +22092,7 @@ const DEFAULT_BOOK_EDITOR_HEIGHT = countLines(DEFAULT_BOOK) * 30 + 20;
22035
22092
  * @public exported from `@promptbook/components`
22036
22093
  */
22037
22094
  function BookEditor(props) {
22038
- const { agentSource, className, style, zoom = 1, value, onChange, diagnostics, onFileUpload, isVerbose = DEFAULT_IS_VERBOSE, isBorderRadiusDisabled = false, isReadonly = false, translations, isUploadButtonShown = true, isCameraButtonShown, isDownloadButtonShown = true, isAboutButtonShown = true, isFullscreenButtonShown = true, sync, monacoModelPath, hoistedMenuItems, } = props;
22095
+ const { agentSource, className, style, theme = 'LIGHT', zoom = 1, value, onChange, diagnostics, onFileUpload, isVerbose = DEFAULT_IS_VERBOSE, isBorderRadiusDisabled = false, isReadonly = false, translations, isUploadButtonShown = true, isCameraButtonShown, isDownloadButtonShown = true, isAboutButtonShown = true, isFullscreenButtonShown = true, sync, monacoModelPath, hoistedMenuItems, } = props;
22039
22096
  const [isFullscreen, setIsFullscreen] = useState(false);
22040
22097
  /**
22041
22098
  * Toggles fullscreen mode for the editor.
@@ -22043,7 +22100,7 @@ function BookEditor(props) {
22043
22100
  const handleFullscreenToggle = () => {
22044
22101
  setIsFullscreen(!isFullscreen);
22045
22102
  };
22046
- const editorContent = (jsx("div", { "data-book-component": "BookEditor", className: classNames(styles$d.BookEditor, isVerbose && styles$d.isVerbose, styles$d.bookEditorWrapper, isBorderRadiusDisabled && styles$d.isBorderRadiusDisabled, isFullscreen && styles$d.fullscreen, className), style: isFullscreen
22103
+ const editorContent = (jsx("div", { "data-book-component": "BookEditor", "data-book-editor-theme": theme.toLowerCase(), className: classNames(styles$d.BookEditor, isVerbose && styles$d.isVerbose, styles$d.bookEditorWrapper, isBorderRadiusDisabled && styles$d.isBorderRadiusDisabled, isFullscreen && styles$d.fullscreen, className), style: isFullscreen
22047
22104
  ? style
22048
22105
  : {
22049
22106
  ...(style || {}),
@@ -22054,7 +22111,7 @@ function BookEditor(props) {
22054
22111
  ? `${props.height}px`
22055
22112
  : props.height || `${DEFAULT_BOOK_EDITOR_HEIGHT}px`,
22056
22113
  }),
22057
- }, children: jsx(BookEditorMonaco, { value: agentSource || value, onChange: onChange, diagnostics: diagnostics, onFileUpload: onFileUpload, isVerbose: isVerbose, isBorderRadiusDisabled: isBorderRadiusDisabled, isReadonly: isReadonly, translations: translations, isUploadButtonShown: isUploadButtonShown, isCameraButtonShown: isCameraButtonShown, isDownloadButtonShown: isDownloadButtonShown, isAboutButtonShown: isAboutButtonShown, isFullscreenButtonShown: isFullscreenButtonShown, onFullscreenClick: handleFullscreenToggle, isFullscreen: isFullscreen, sync: sync, zoom: zoom, monacoModelPath: monacoModelPath, hoistedMenuItems: hoistedMenuItems }) }));
22114
+ }, children: jsx(BookEditorMonaco, { value: agentSource || value, onChange: onChange, diagnostics: diagnostics, onFileUpload: onFileUpload, isVerbose: isVerbose, isBorderRadiusDisabled: isBorderRadiusDisabled, isReadonly: isReadonly, translations: translations, isUploadButtonShown: isUploadButtonShown, isCameraButtonShown: isCameraButtonShown, isDownloadButtonShown: isDownloadButtonShown, isAboutButtonShown: isAboutButtonShown, isFullscreenButtonShown: isFullscreenButtonShown, onFullscreenClick: handleFullscreenToggle, isFullscreen: isFullscreen, sync: sync, zoom: zoom, monacoModelPath: monacoModelPath, hoistedMenuItems: hoistedMenuItems, theme: theme }) }));
22058
22115
  return isFullscreen && typeof document !== 'undefined' ? createPortal(editorContent, document.body) : editorContent;
22059
22116
  }
22060
22117
 
@@ -26079,6 +26136,138 @@ function interpolateExponentially(currentValue, targetValue, deltaMs, smoothingW
26079
26136
  return currentValue + (targetValue - currentValue) * blend;
26080
26137
  }
26081
26138
 
26139
+ // Note: [💞] Ignore a discrepancy between file name and entity name
26140
+ /**
26141
+ * Next registration id used by the shared avatar animation scheduler.
26142
+ *
26143
+ * @private utility of the avatar rendering system
26144
+ */
26145
+ let nextAvatarAnimationListenerId = 1;
26146
+ /**
26147
+ * Active avatar animation callbacks keyed by their registration id.
26148
+ *
26149
+ * @private utility of the avatar rendering system
26150
+ */
26151
+ const avatarAnimationListeners = new Map();
26152
+ /**
26153
+ * Active shared animation-frame handle.
26154
+ *
26155
+ * @private utility of the avatar rendering system
26156
+ */
26157
+ let avatarAnimationFrameId = null;
26158
+ /**
26159
+ * Registers one avatar animation callback in the shared animation loop.
26160
+ *
26161
+ * @param avatarAnimationListener Frame callback invoked on every animation frame.
26162
+ * @returns Cleanup function that unregisters the callback.
26163
+ *
26164
+ * @private utility of the avatar rendering system
26165
+ */
26166
+ function retainAvatarAnimationListener(avatarAnimationListener) {
26167
+ if (typeof window === 'undefined') {
26168
+ return () => undefined;
26169
+ }
26170
+ const listenerId = nextAvatarAnimationListenerId++;
26171
+ avatarAnimationListeners.set(listenerId, avatarAnimationListener);
26172
+ ensureAvatarAnimationLoop();
26173
+ return () => {
26174
+ avatarAnimationListeners.delete(listenerId);
26175
+ if (avatarAnimationListeners.size === 0 && avatarAnimationFrameId !== null) {
26176
+ window.cancelAnimationFrame(avatarAnimationFrameId);
26177
+ avatarAnimationFrameId = null;
26178
+ }
26179
+ };
26180
+ }
26181
+ /**
26182
+ * Ensures the shared animation loop is running while at least one avatar listener is active.
26183
+ *
26184
+ * @private utility of the avatar rendering system
26185
+ */
26186
+ function ensureAvatarAnimationLoop() {
26187
+ if (avatarAnimationFrameId !== null || avatarAnimationListeners.size === 0 || typeof window === 'undefined') {
26188
+ return;
26189
+ }
26190
+ const runFrame = (now) => {
26191
+ avatarAnimationFrameId = null;
26192
+ for (const avatarAnimationListener of [...avatarAnimationListeners.values()]) {
26193
+ avatarAnimationListener(now);
26194
+ }
26195
+ ensureAvatarAnimationLoop();
26196
+ };
26197
+ avatarAnimationFrameId = window.requestAnimationFrame(runFrame);
26198
+ }
26199
+
26200
+ // Note: [💞] Ignore a discrepancy between file name and entity name
26201
+ /**
26202
+ * Shared `IntersectionObserver` callbacks grouped by observed element.
26203
+ *
26204
+ * @private utility of the avatar rendering system
26205
+ */
26206
+ const avatarVisibilityListeners = new Map();
26207
+ /**
26208
+ * Lazily created shared `IntersectionObserver` used by avatar canvases.
26209
+ *
26210
+ * @private utility of the avatar rendering system
26211
+ */
26212
+ let avatarVisibilityObserver = null;
26213
+ /**
26214
+ * Observes one avatar element and notifies the caller when it enters or leaves the viewport.
26215
+ *
26216
+ * @param element Observed avatar element.
26217
+ * @param avatarVisibilityListener Listener notified with the current visibility state.
26218
+ * @returns Cleanup function that stops observing the element.
26219
+ *
26220
+ * @private utility of the avatar rendering system
26221
+ */
26222
+ function observeAvatarVisibility(element, avatarVisibilityListener) {
26223
+ if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') {
26224
+ avatarVisibilityListener(true);
26225
+ return () => undefined;
26226
+ }
26227
+ const observer = getAvatarVisibilityObserver();
26228
+ const elementListeners = avatarVisibilityListeners.get(element) || new Set();
26229
+ elementListeners.add(avatarVisibilityListener);
26230
+ avatarVisibilityListeners.set(element, elementListeners);
26231
+ observer.observe(element);
26232
+ return () => {
26233
+ const currentElementListeners = avatarVisibilityListeners.get(element);
26234
+ if (!currentElementListeners) {
26235
+ return;
26236
+ }
26237
+ currentElementListeners.delete(avatarVisibilityListener);
26238
+ if (currentElementListeners.size > 0) {
26239
+ return;
26240
+ }
26241
+ avatarVisibilityListeners.delete(element);
26242
+ observer.unobserve(element);
26243
+ };
26244
+ }
26245
+ /**
26246
+ * Creates the shared `IntersectionObserver` used by all avatar canvases.
26247
+ *
26248
+ * @returns Shared observer instance.
26249
+ *
26250
+ * @private utility of the avatar rendering system
26251
+ */
26252
+ function getAvatarVisibilityObserver() {
26253
+ if (avatarVisibilityObserver) {
26254
+ return avatarVisibilityObserver;
26255
+ }
26256
+ avatarVisibilityObserver = new IntersectionObserver((entries) => {
26257
+ for (const entry of entries) {
26258
+ const elementListeners = avatarVisibilityListeners.get(entry.target);
26259
+ if (!elementListeners) {
26260
+ continue;
26261
+ }
26262
+ const isVisible = entry.isIntersecting && entry.intersectionRatio > 0;
26263
+ for (const avatarVisibilityListener of elementListeners) {
26264
+ avatarVisibilityListener(isVisible);
26265
+ }
26266
+ }
26267
+ });
26268
+ return avatarVisibilityObserver;
26269
+ }
26270
+
26082
26271
  // Note: [💞] Ignore a discrepancy between file name and entity name
26083
26272
  /**
26084
26273
  * Active avatar instances currently consuming the shared pointer tracker.
@@ -26092,6 +26281,18 @@ let avatarPointerTrackingConsumerCount = 0;
26092
26281
  * @private utility of the avatar rendering system
26093
26282
  */
26094
26283
  let currentAvatarPointerSnapshot = null;
26284
+ /**
26285
+ * Monotonic version incremented whenever the shared pointer snapshot changes.
26286
+ *
26287
+ * @private utility of the avatar rendering system
26288
+ */
26289
+ let currentAvatarPointerSnapshotVersion = 0;
26290
+ /**
26291
+ * Monotonic version incremented whenever scrolling or resizing may invalidate cached avatar bounds.
26292
+ *
26293
+ * @private utility of the avatar rendering system
26294
+ */
26295
+ let currentAvatarViewportLayoutVersion = 0;
26095
26296
  /**
26096
26297
  * Cleanup function for the lazily attached global listeners.
26097
26298
  *
@@ -26129,6 +26330,26 @@ function retainAvatarPointerTracking() {
26129
26330
  function getAvatarPointerSnapshot() {
26130
26331
  return currentAvatarPointerSnapshot;
26131
26332
  }
26333
+ /**
26334
+ * Returns the current pointer snapshot version.
26335
+ *
26336
+ * @returns Monotonic pointer snapshot version.
26337
+ *
26338
+ * @private utility of the avatar rendering system
26339
+ */
26340
+ function getAvatarPointerSnapshotVersion() {
26341
+ return currentAvatarPointerSnapshotVersion;
26342
+ }
26343
+ /**
26344
+ * Returns the current viewport-layout version used to invalidate cached avatar bounds.
26345
+ *
26346
+ * @returns Monotonic viewport-layout version.
26347
+ *
26348
+ * @private utility of the avatar rendering system
26349
+ */
26350
+ function getAvatarViewportLayoutVersion() {
26351
+ return currentAvatarViewportLayoutVersion;
26352
+ }
26132
26353
  /**
26133
26354
  * Attaches the global pointer/touch listeners used by all live avatar canvases.
26134
26355
  *
@@ -26141,7 +26362,11 @@ function attachAvatarPointerTrackingListeners() {
26141
26362
  return () => undefined;
26142
26363
  }
26143
26364
  const clearPointerSnapshot = () => {
26365
+ if (currentAvatarPointerSnapshot === null) {
26366
+ return;
26367
+ }
26144
26368
  currentAvatarPointerSnapshot = null;
26369
+ currentAvatarPointerSnapshotVersion++;
26145
26370
  };
26146
26371
  const updatePointerSnapshot = (clientX, clientY, pointerType) => {
26147
26372
  currentAvatarPointerSnapshot = {
@@ -26150,6 +26375,10 @@ function attachAvatarPointerTrackingListeners() {
26150
26375
  isPointerActive: true,
26151
26376
  pointerType,
26152
26377
  };
26378
+ currentAvatarPointerSnapshotVersion++;
26379
+ };
26380
+ const invalidateViewportLayout = () => {
26381
+ currentAvatarViewportLayoutVersion++;
26153
26382
  };
26154
26383
  const handlePointerMove = (event) => {
26155
26384
  updatePointerSnapshot(event.clientX, event.clientY, normalizeAvatarPointerType(event.pointerType));
@@ -26185,6 +26414,8 @@ function attachAvatarPointerTrackingListeners() {
26185
26414
  window.addEventListener('touchmove', handleTouchEvent, { passive: true });
26186
26415
  window.addEventListener('touchend', clearPointerSnapshot, { passive: true });
26187
26416
  window.addEventListener('touchcancel', clearPointerSnapshot, { passive: true });
26417
+ window.addEventListener('scroll', invalidateViewportLayout, { passive: true, capture: true });
26418
+ window.addEventListener('resize', invalidateViewportLayout, { passive: true });
26188
26419
  return () => {
26189
26420
  window.removeEventListener('pointermove', handlePointerMove);
26190
26421
  window.removeEventListener('pointerdown', handlePointerDown);
@@ -26196,6 +26427,8 @@ function attachAvatarPointerTrackingListeners() {
26196
26427
  window.removeEventListener('touchmove', handleTouchEvent);
26197
26428
  window.removeEventListener('touchend', clearPointerSnapshot);
26198
26429
  window.removeEventListener('touchcancel', clearPointerSnapshot);
26430
+ window.removeEventListener('scroll', invalidateViewportLayout, true);
26431
+ window.removeEventListener('resize', invalidateViewportLayout);
26199
26432
  };
26200
26433
  }
26201
26434
  /**
@@ -26289,37 +26522,49 @@ function traceSmoothClosedPath(context, points) {
26289
26522
  * @private shared geometry helper of `octopus3AvatarVisual` and `asciiOctopusAvatarVisual`
26290
26523
  */
26291
26524
  function createOrganicOctopusTentacleShapes(options) {
26292
- const { size, centerX, centerY, bodyRadius, horizontalStretch, tentacleCount, shapePhase, createRandom, timeMs, saltPrefix, bodyPoints } = options;
26525
+ var _a, _b, _c, _d, _e, _f, _g, _h;
26526
+ const { size, centerX, centerY, bodyRadius, horizontalStretch, tentacleCount, shapePhase, createRandom, timeMs, saltPrefix, bodyPoints, variation, } = options;
26293
26527
  const baseY = centerY + bodyRadius * 0.74;
26294
26528
  const lowerBodyAnchorPoints = bodyPoints ? resolveTentacleBodyAnchorPoints(bodyPoints, centerY + bodyRadius * 0.04) : null;
26529
+ const flowLengthScale = (_a = variation === null || variation === void 0 ? void 0 : variation.flowLengthScale) !== null && _a !== void 0 ? _a : 1;
26530
+ const lateralReachScale = (_b = variation === null || variation === void 0 ? void 0 : variation.lateralReachScale) !== null && _b !== void 0 ? _b : 1;
26531
+ const tipReachScale = (_c = variation === null || variation === void 0 ? void 0 : variation.tipReachScale) !== null && _c !== void 0 ? _c : 1;
26532
+ const baseWidthScale = (_d = variation === null || variation === void 0 ? void 0 : variation.baseWidthScale) !== null && _d !== void 0 ? _d : 1;
26533
+ const tipWidthScale = (_e = variation === null || variation === void 0 ? void 0 : variation.tipWidthScale) !== null && _e !== void 0 ? _e : 1;
26534
+ const rootSpreadScale = (_f = variation === null || variation === void 0 ? void 0 : variation.rootSpreadScale) !== null && _f !== void 0 ? _f : 1;
26535
+ const startYOffsetScale = (_g = variation === null || variation === void 0 ? void 0 : variation.startYOffsetScale) !== null && _g !== void 0 ? _g : 1;
26536
+ const swayScale = (_h = variation === null || variation === void 0 ? void 0 : variation.swayScale) !== null && _h !== void 0 ? _h : 1;
26295
26537
  return Array.from({ length: tentacleCount }, (_, tentacleIndex) => {
26296
26538
  const tentacleRandom = createRandom(`${saltPrefix}-tentacle-${tentacleIndex}`);
26297
26539
  const spreadProgress = tentacleCount === 1 ? 0.5 : tentacleIndex / (tentacleCount - 1);
26298
26540
  const centeredProgress = spreadProgress - 0.5;
26541
+ const spreadCenteredProgress = centeredProgress * rootSpreadScale;
26542
+ const spreadAnchorProgress = Math.min(1, Math.max(0, 0.5 + spreadCenteredProgress));
26299
26543
  const temporalSway = Math.sin(timeMs / (720 + tentacleIndex * 34) + shapePhase + tentacleRandom() * Math.PI * 2) *
26300
26544
  size *
26301
- (0.014 + tentacleRandom() * 0.015);
26302
- const flowLength = size * (0.24 + tentacleRandom() * 0.18);
26303
- const curlDirection = centeredProgress === 0 ? (tentacleRandom() < 0.5 ? -1 : 1) : Math.sign(centeredProgress);
26304
- const lateralReach = centeredProgress * size * (0.1 + tentacleRandom() * 0.1) + temporalSway;
26305
- const tipReach = curlDirection * size * (0.025 + tentacleRandom() * 0.07);
26306
- const startYOffset = Math.abs(centeredProgress) * size * 0.012 + tentacleRandom() * size * 0.01;
26545
+ (0.014 + tentacleRandom() * 0.015) *
26546
+ swayScale;
26547
+ const flowLength = size * (0.24 + tentacleRandom() * 0.18) * flowLengthScale;
26548
+ const curlDirection = spreadCenteredProgress === 0 ? (tentacleRandom() < 0.5 ? -1 : 1) : Math.sign(spreadCenteredProgress);
26549
+ const lateralReach = spreadCenteredProgress * size * (0.1 + tentacleRandom() * 0.1) * lateralReachScale + temporalSway;
26550
+ const tipReach = curlDirection * size * (0.025 + tentacleRandom() * 0.07) * tipReachScale;
26551
+ const startYOffset = (Math.abs(spreadCenteredProgress) * size * 0.012 + tentacleRandom() * size * 0.01) * startYOffsetScale;
26307
26552
  const startPoint = lowerBodyAnchorPoints && lowerBodyAnchorPoints.length >= 2
26308
26553
  ? createInsetTentacleStartPoint({
26309
26554
  bodyPoints: lowerBodyAnchorPoints,
26310
- anchorProgress: spreadProgress,
26555
+ anchorProgress: spreadAnchorProgress,
26311
26556
  centerX,
26312
26557
  centerY,
26313
26558
  bodyRadius,
26314
- centeredProgress,
26559
+ centeredProgress: spreadCenteredProgress,
26315
26560
  startYOffset,
26316
26561
  })
26317
26562
  : {
26318
- x: centerX + centeredProgress * bodyRadius * horizontalStretch * 1.52,
26563
+ x: centerX + spreadCenteredProgress * bodyRadius * horizontalStretch * 1.52,
26319
26564
  y: baseY + startYOffset,
26320
26565
  };
26321
26566
  const controlPointOne = {
26322
- x: startPoint.x + centeredProgress * size * 0.045 + temporalSway * 0.4,
26567
+ x: startPoint.x + spreadCenteredProgress * size * 0.045 * lateralReachScale + temporalSway * 0.4,
26323
26568
  y: startPoint.y + flowLength * (0.21 + tentacleRandom() * 0.08),
26324
26569
  };
26325
26570
  const controlPointTwo = {
@@ -26332,8 +26577,8 @@ function createOrganicOctopusTentacleShapes(options) {
26332
26577
  flowLength * (0.9 + tentacleRandom() * 0.12) +
26333
26578
  Math.cos(timeMs / (840 + tentacleIndex * 41) + shapePhase) * size * (0.008 + tentacleRandom() * 0.01),
26334
26579
  };
26335
- const baseWidth = size * (0.038 + tentacleRandom() * 0.02) * (1 - Math.abs(centeredProgress) * 0.18);
26336
- const tipWidth = baseWidth * (0.18 + tentacleRandom() * 0.2);
26580
+ const baseWidth = size * (0.038 + tentacleRandom() * 0.02) * (1 - Math.abs(spreadCenteredProgress) * 0.18) * baseWidthScale;
26581
+ const tipWidth = baseWidth * Math.min(0.52, (0.18 + tentacleRandom() * 0.2) * tipWidthScale);
26337
26582
  return {
26338
26583
  startPoint,
26339
26584
  controlPointOne,
@@ -27989,6 +28234,244 @@ function drawAlienEye(context, centerX, centerY, radiusX, radiusY, palette, time
27989
28234
  }
27990
28235
 
27991
28236
  /* eslint-disable no-magic-numbers */
28237
+ /**
28238
+ * Builds one deterministic morphology profile for `Octopus3`.
28239
+ *
28240
+ * @param createRandom Seeded random factory scoped to the current avatar.
28241
+ * @returns Stable morphology profile.
28242
+ *
28243
+ * @private helper of `octopus3AvatarVisual`
28244
+ */
28245
+ function createOctopus3MorphologyProfile(createRandom) {
28246
+ const bodyRandom = createRandom('octopus3-body-profile');
28247
+ const faceRandom = createRandom('octopus3-face-profile');
28248
+ const detailRandom = createRandom('octopus3-detail-profile');
28249
+ const bodyFamilyRoll = bodyRandom();
28250
+ let bodyFamily;
28251
+ let body;
28252
+ let tentacles;
28253
+ if (bodyFamilyRoll < 0.34) {
28254
+ bodyFamily = 'lantern';
28255
+ body = {
28256
+ centerXJitterRatio: resolveSeededRange(bodyRandom, -0.018, 0.018),
28257
+ centerYRatio: resolveSeededRange(bodyRandom, 0.39, 0.435),
28258
+ bodyRadiusRatio: resolveSeededRange(bodyRandom, 0.19, 0.23),
28259
+ horizontalStretch: resolveSeededRange(bodyRandom, 0.94, 1.08),
28260
+ verticalStretch: resolveSeededRange(bodyRandom, 1.02, 1.18),
28261
+ mantleLiftRatio: resolveSeededRange(bodyRandom, 0.115, 0.148),
28262
+ lowerDropRatio: resolveSeededRange(bodyRandom, 0.042, 0.066),
28263
+ tentacleDepthRatio: resolveSeededRange(bodyRandom, 0.018, 0.03),
28264
+ wobbleAmplitudeRatio: resolveSeededRange(bodyRandom, 0.009, 0.017),
28265
+ lobeCount: resolveSeededIntegerRange(bodyRandom, 4, 6),
28266
+ pointCount: resolveSeededIntegerRange(bodyRandom, 38, 42),
28267
+ shadowWidthRatio: resolveSeededRange(bodyRandom, 0.18, 0.23),
28268
+ shadowHeightRatio: resolveSeededRange(bodyRandom, 0.055, 0.075),
28269
+ crownHighlightWidthRatio: resolveSeededRange(bodyRandom, 0.14, 0.18),
28270
+ crownHighlightHeightRatio: resolveSeededRange(bodyRandom, 0.045, 0.062),
28271
+ crownHighlightYOffsetRatio: resolveSeededRange(bodyRandom, -0.165, -0.135),
28272
+ };
28273
+ tentacles = {
28274
+ count: resolveSeededIntegerRange(bodyRandom, 7, 10),
28275
+ flowLengthScale: resolveSeededRange(bodyRandom, 1.08, 1.34),
28276
+ lateralReachScale: resolveSeededRange(bodyRandom, 0.72, 0.94),
28277
+ tipReachScale: resolveSeededRange(bodyRandom, 0.82, 1.06),
28278
+ baseWidthScale: resolveSeededRange(bodyRandom, 0.82, 0.98),
28279
+ tipWidthScale: resolveSeededRange(bodyRandom, 0.9, 1.08),
28280
+ rootSpreadScale: resolveSeededRange(bodyRandom, 0.76, 0.94),
28281
+ startYOffsetScale: resolveSeededRange(bodyRandom, 0.82, 1),
28282
+ swayScale: resolveSeededRange(bodyRandom, 0.82, 1.02),
28283
+ };
28284
+ }
28285
+ else if (bodyFamilyRoll < 0.68) {
28286
+ bodyFamily = 'drifter';
28287
+ body = {
28288
+ centerXJitterRatio: resolveSeededRange(bodyRandom, -0.025, 0.025),
28289
+ centerYRatio: resolveSeededRange(bodyRandom, 0.425, 0.46),
28290
+ bodyRadiusRatio: resolveSeededRange(bodyRandom, 0.175, 0.215),
28291
+ horizontalStretch: resolveSeededRange(bodyRandom, 1.22, 1.42),
28292
+ verticalStretch: resolveSeededRange(bodyRandom, 0.82, 0.92),
28293
+ mantleLiftRatio: resolveSeededRange(bodyRandom, 0.092, 0.115),
28294
+ lowerDropRatio: resolveSeededRange(bodyRandom, 0.02, 0.036),
28295
+ tentacleDepthRatio: resolveSeededRange(bodyRandom, 0.032, 0.052),
28296
+ wobbleAmplitudeRatio: resolveSeededRange(bodyRandom, 0.013, 0.022),
28297
+ lobeCount: resolveSeededIntegerRange(bodyRandom, 7, 9),
28298
+ pointCount: resolveSeededIntegerRange(bodyRandom, 40, 46),
28299
+ shadowWidthRatio: resolveSeededRange(bodyRandom, 0.24, 0.28),
28300
+ shadowHeightRatio: resolveSeededRange(bodyRandom, 0.06, 0.082),
28301
+ crownHighlightWidthRatio: resolveSeededRange(bodyRandom, 0.17, 0.22),
28302
+ crownHighlightHeightRatio: resolveSeededRange(bodyRandom, 0.038, 0.055),
28303
+ crownHighlightYOffsetRatio: resolveSeededRange(bodyRandom, -0.14, -0.11),
28304
+ };
28305
+ tentacles = {
28306
+ count: resolveSeededIntegerRange(bodyRandom, 10, 13),
28307
+ flowLengthScale: resolveSeededRange(bodyRandom, 0.88, 1.08),
28308
+ lateralReachScale: resolveSeededRange(bodyRandom, 1.18, 1.42),
28309
+ tipReachScale: resolveSeededRange(bodyRandom, 1.12, 1.42),
28310
+ baseWidthScale: resolveSeededRange(bodyRandom, 0.9, 1.06),
28311
+ tipWidthScale: resolveSeededRange(bodyRandom, 0.88, 1.08),
28312
+ rootSpreadScale: resolveSeededRange(bodyRandom, 1.12, 1.32),
28313
+ startYOffsetScale: resolveSeededRange(bodyRandom, 0.92, 1.14),
28314
+ swayScale: resolveSeededRange(bodyRandom, 1.04, 1.22),
28315
+ };
28316
+ }
28317
+ else {
28318
+ bodyFamily = 'rounded';
28319
+ body = {
28320
+ centerXJitterRatio: resolveSeededRange(bodyRandom, -0.02, 0.02),
28321
+ centerYRatio: resolveSeededRange(bodyRandom, 0.398, 0.442),
28322
+ bodyRadiusRatio: resolveSeededRange(bodyRandom, 0.208, 0.248),
28323
+ horizontalStretch: resolveSeededRange(bodyRandom, 1.06, 1.22),
28324
+ verticalStretch: resolveSeededRange(bodyRandom, 0.9, 1.01),
28325
+ mantleLiftRatio: resolveSeededRange(bodyRandom, 0.1, 0.128),
28326
+ lowerDropRatio: resolveSeededRange(bodyRandom, 0.032, 0.052),
28327
+ tentacleDepthRatio: resolveSeededRange(bodyRandom, 0.038, 0.06),
28328
+ wobbleAmplitudeRatio: resolveSeededRange(bodyRandom, 0.014, 0.024),
28329
+ lobeCount: resolveSeededIntegerRange(bodyRandom, 5, 8),
28330
+ pointCount: resolveSeededIntegerRange(bodyRandom, 39, 44),
28331
+ shadowWidthRatio: resolveSeededRange(bodyRandom, 0.2, 0.25),
28332
+ shadowHeightRatio: resolveSeededRange(bodyRandom, 0.055, 0.08),
28333
+ crownHighlightWidthRatio: resolveSeededRange(bodyRandom, 0.16, 0.2),
28334
+ crownHighlightHeightRatio: resolveSeededRange(bodyRandom, 0.05, 0.07),
28335
+ crownHighlightYOffsetRatio: resolveSeededRange(bodyRandom, -0.155, -0.122),
28336
+ };
28337
+ tentacles = {
28338
+ count: resolveSeededIntegerRange(bodyRandom, 8, 12),
28339
+ flowLengthScale: resolveSeededRange(bodyRandom, 0.94, 1.16),
28340
+ lateralReachScale: resolveSeededRange(bodyRandom, 0.9, 1.14),
28341
+ tipReachScale: resolveSeededRange(bodyRandom, 0.96, 1.22),
28342
+ baseWidthScale: resolveSeededRange(bodyRandom, 1.02, 1.2),
28343
+ tipWidthScale: resolveSeededRange(bodyRandom, 1.02, 1.22),
28344
+ rootSpreadScale: resolveSeededRange(bodyRandom, 0.94, 1.08),
28345
+ startYOffsetScale: resolveSeededRange(bodyRandom, 0.9, 1.08),
28346
+ swayScale: resolveSeededRange(bodyRandom, 0.9, 1.1),
28347
+ };
28348
+ }
28349
+ const faceFamilyRoll = faceRandom();
28350
+ let faceFamily;
28351
+ let face;
28352
+ if (faceFamilyRoll < 0.34) {
28353
+ faceFamily = 'watchful';
28354
+ face = {
28355
+ eyeSpacingRatio: resolveSeededRange(faceRandom, 0.118, 0.152),
28356
+ eyeCenterYOffsetRatio: resolveSeededRange(faceRandom, -0.026, -0.002),
28357
+ eyeRadiusXRatio: resolveSeededRange(faceRandom, 0.05, 0.062),
28358
+ eyeHeightRatio: resolveSeededRange(faceRandom, 1.18, 1.38),
28359
+ eyeRotationRange: resolveSeededRange(faceRandom, 0.16, 0.28),
28360
+ eyeTiltBias: resolveSeededRange(faceRandom, 0.02, 0.06),
28361
+ mouthWidthRatio: resolveSeededRange(faceRandom, 0.058, 0.074),
28362
+ mouthYOffsetRatio: resolveSeededRange(faceRandom, 0.086, 0.104),
28363
+ mouthCurveDepthRatio: resolveSeededRange(faceRandom, 0.126, 0.15),
28364
+ mouthCenterOffsetRatio: resolveSeededRange(faceRandom, -0.006, 0.006),
28365
+ mouthCornerTiltRatio: resolveSeededRange(faceRandom, -0.002, 0.002),
28366
+ eyeStyle: {
28367
+ irisScale: resolveSeededRange(faceRandom, 1, 1.1),
28368
+ pupilWidthScale: resolveSeededRange(faceRandom, 0.86, 1.02),
28369
+ pupilHeightScale: resolveSeededRange(faceRandom, 0.94, 1.08),
28370
+ upperLidArchRatio: resolveSeededRange(faceRandom, 0.96, 1.12),
28371
+ upperLidInsetRatio: resolveSeededRange(faceRandom, 0.08, 0.14),
28372
+ lowerLidOpacity: resolveSeededRange(faceRandom, 0.12, 0.22),
28373
+ },
28374
+ };
28375
+ }
28376
+ else if (faceFamilyRoll < 0.68) {
28377
+ faceFamily = 'sleepy';
28378
+ face = {
28379
+ eyeSpacingRatio: resolveSeededRange(faceRandom, 0.092, 0.124),
28380
+ eyeCenterYOffsetRatio: resolveSeededRange(faceRandom, -0.002, 0.024),
28381
+ eyeRadiusXRatio: resolveSeededRange(faceRandom, 0.058, 0.074),
28382
+ eyeHeightRatio: resolveSeededRange(faceRandom, 0.96, 1.14),
28383
+ eyeRotationRange: resolveSeededRange(faceRandom, 0.1, 0.22),
28384
+ eyeTiltBias: resolveSeededRange(faceRandom, 0.01, 0.05),
28385
+ mouthWidthRatio: resolveSeededRange(faceRandom, 0.066, 0.086),
28386
+ mouthYOffsetRatio: resolveSeededRange(faceRandom, 0.094, 0.118),
28387
+ mouthCurveDepthRatio: resolveSeededRange(faceRandom, 0.118, 0.145),
28388
+ mouthCenterOffsetRatio: resolveSeededRange(faceRandom, -0.004, 0.004),
28389
+ mouthCornerTiltRatio: resolveSeededRange(faceRandom, -0.004, 0.004),
28390
+ eyeStyle: {
28391
+ irisScale: resolveSeededRange(faceRandom, 0.9, 1),
28392
+ pupilWidthScale: resolveSeededRange(faceRandom, 1, 1.18),
28393
+ pupilHeightScale: resolveSeededRange(faceRandom, 0.78, 0.92),
28394
+ upperLidArchRatio: resolveSeededRange(faceRandom, 0.7, 0.88),
28395
+ upperLidInsetRatio: resolveSeededRange(faceRandom, -0.02, 0.06),
28396
+ lowerLidOpacity: resolveSeededRange(faceRandom, 0.22, 0.34),
28397
+ },
28398
+ };
28399
+ }
28400
+ else {
28401
+ faceFamily = 'mischief';
28402
+ face = {
28403
+ eyeSpacingRatio: resolveSeededRange(faceRandom, 0.086, 0.114),
28404
+ eyeCenterYOffsetRatio: resolveSeededRange(faceRandom, -0.018, 0.01),
28405
+ eyeRadiusXRatio: resolveSeededRange(faceRandom, 0.046, 0.06),
28406
+ eyeHeightRatio: resolveSeededRange(faceRandom, 1.08, 1.28),
28407
+ eyeRotationRange: resolveSeededRange(faceRandom, 0.28, 0.44),
28408
+ eyeTiltBias: resolveSeededRange(faceRandom, 0.12, 0.22),
28409
+ mouthWidthRatio: resolveSeededRange(faceRandom, 0.052, 0.074),
28410
+ mouthYOffsetRatio: resolveSeededRange(faceRandom, 0.082, 0.1),
28411
+ mouthCurveDepthRatio: resolveSeededRange(faceRandom, 0.116, 0.15),
28412
+ mouthCenterOffsetRatio: resolveSeededRange(faceRandom, -0.018, 0.018),
28413
+ mouthCornerTiltRatio: resolveSeededRange(faceRandom, -0.01, 0.01),
28414
+ eyeStyle: {
28415
+ irisScale: resolveSeededRange(faceRandom, 1.04, 1.12),
28416
+ pupilWidthScale: resolveSeededRange(faceRandom, 0.72, 0.9),
28417
+ pupilHeightScale: resolveSeededRange(faceRandom, 0.96, 1.14),
28418
+ upperLidArchRatio: resolveSeededRange(faceRandom, 0.88, 1.02),
28419
+ upperLidInsetRatio: resolveSeededRange(faceRandom, 0.04, 0.12),
28420
+ lowerLidOpacity: resolveSeededRange(faceRandom, 0.08, 0.18),
28421
+ },
28422
+ };
28423
+ }
28424
+ return {
28425
+ bodyFamily,
28426
+ faceFamily,
28427
+ body,
28428
+ tentacles,
28429
+ face,
28430
+ details: {
28431
+ mantleCurrentCount: resolveSeededIntegerRange(detailRandom, 4, 8),
28432
+ mantleNodeCount: resolveSeededIntegerRange(detailRandom, 3, 7),
28433
+ },
28434
+ };
28435
+ }
28436
+ /**
28437
+ * Resolves one seeded floating-point number inside the provided range.
28438
+ *
28439
+ * @param random Seeded random generator.
28440
+ * @param minimumValue Inclusive lower bound.
28441
+ * @param maximumValue Inclusive upper bound.
28442
+ * @returns Seeded number within the range.
28443
+ *
28444
+ * @private helper of `octopus3AvatarVisual`
28445
+ */
28446
+ function resolveSeededRange(random, minimumValue, maximumValue) {
28447
+ return minimumValue + random() * (maximumValue - minimumValue);
28448
+ }
28449
+ /**
28450
+ * Resolves one seeded integer inside the provided inclusive range.
28451
+ *
28452
+ * @param random Seeded random generator.
28453
+ * @param minimumValue Inclusive lower bound.
28454
+ * @param maximumValue Inclusive upper bound.
28455
+ * @returns Seeded integer within the range.
28456
+ *
28457
+ * @private helper of `octopus3AvatarVisual`
28458
+ */
28459
+ function resolveSeededIntegerRange(random, minimumValue, maximumValue) {
28460
+ return minimumValue + Math.floor(random() * (maximumValue - minimumValue + 1));
28461
+ }
28462
+ /**
28463
+ * Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
28464
+ *
28465
+ * @param opacity Opacity ratio in the range `[0, 1]`.
28466
+ * @returns Two-digit hexadecimal alpha string.
28467
+ *
28468
+ * @private helper of `octopus3AvatarVisual`
28469
+ */
28470
+ function formatAlphaHex(opacity) {
28471
+ return Math.round(Math.min(1, Math.max(0, opacity)) * 255)
28472
+ .toString(16)
28473
+ .padStart(2, '0');
28474
+ }
27992
28475
  /**
27993
28476
  * Octopus3 avatar visual.
27994
28477
  *
@@ -28001,22 +28484,24 @@ const octopus3AvatarVisual = {
28001
28484
  isAnimated: true,
28002
28485
  supportsPointerTracking: true,
28003
28486
  render({ context, size, palette, createRandom, timeMs, interaction }) {
28004
- const staticRandom = createRandom('octopus3-static');
28005
- const centerX = size * (0.5 + (staticRandom() - 0.5) * 0.02) + interaction.bodyOffsetX * size * 0.05;
28006
- const centerY = size * (0.41 + staticRandom() * 0.05) + interaction.bodyOffsetY * size * 0.035;
28007
- const bodyRadius = size * (0.2 + staticRandom() * 0.045);
28008
- const horizontalStretch = 1.08 + staticRandom() * 0.22;
28009
- const verticalStretch = 0.9 + staticRandom() * 0.12;
28010
- const mantleLift = size * (0.105 + staticRandom() * 0.03);
28011
- const lowerDrop = size * (0.028 + staticRandom() * 0.022);
28012
- const tentacleDepth = size * (0.022 + staticRandom() * 0.018);
28013
- const wobbleAmplitude = size * (0.01 + staticRandom() * 0.01);
28014
- const lobeCount = 5 + Math.floor(staticRandom() * 3);
28015
- const shapePhase = staticRandom() * Math.PI * 2;
28016
- const tentacleCount = 8 + Math.floor(staticRandom() * 5);
28017
- const eyeSpacing = size * (0.11 + staticRandom() * 0.04);
28018
- const eyeRadiusX = size * (0.056 + staticRandom() * 0.014);
28019
- const eyeRadiusY = eyeRadiusX * (1.18 + staticRandom() * 0.18);
28487
+ const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
28488
+ const animationRandom = createRandom('octopus3-animation-profile');
28489
+ const eyeRandom = createRandom('octopus3-eye-profile');
28490
+ const centerX = size * (0.5 + morphologyProfile.body.centerXJitterRatio) + interaction.bodyOffsetX * size * 0.05;
28491
+ const centerY = size * morphologyProfile.body.centerYRatio + interaction.bodyOffsetY * size * 0.035;
28492
+ const bodyRadius = size * morphologyProfile.body.bodyRadiusRatio;
28493
+ const horizontalStretch = morphologyProfile.body.horizontalStretch;
28494
+ const verticalStretch = morphologyProfile.body.verticalStretch;
28495
+ const mantleLift = size * morphologyProfile.body.mantleLiftRatio;
28496
+ const lowerDrop = size * morphologyProfile.body.lowerDropRatio;
28497
+ const tentacleDepth = size * morphologyProfile.body.tentacleDepthRatio;
28498
+ const wobbleAmplitude = size * morphologyProfile.body.wobbleAmplitudeRatio;
28499
+ const lobeCount = morphologyProfile.body.lobeCount;
28500
+ const shapePhase = animationRandom() * Math.PI * 2;
28501
+ const eyeSpacing = size * morphologyProfile.face.eyeSpacingRatio;
28502
+ const eyeCenterY = centerY + size * morphologyProfile.face.eyeCenterYOffsetRatio;
28503
+ const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio;
28504
+ const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio;
28020
28505
  const bodyPoints = createOrganicOctopusBodyPoints({
28021
28506
  centerX,
28022
28507
  centerY,
@@ -28030,7 +28515,7 @@ const octopus3AvatarVisual = {
28030
28515
  lobeCount,
28031
28516
  shapePhase,
28032
28517
  timeMs,
28033
- pointCount: 40,
28518
+ pointCount: morphologyProfile.body.pointCount,
28034
28519
  });
28035
28520
  const tentacleShapes = createOrganicOctopusTentacleShapes({
28036
28521
  size,
@@ -28038,17 +28523,27 @@ const octopus3AvatarVisual = {
28038
28523
  centerY,
28039
28524
  bodyRadius,
28040
28525
  horizontalStretch,
28041
- tentacleCount,
28526
+ tentacleCount: morphologyProfile.tentacles.count,
28042
28527
  shapePhase,
28043
28528
  createRandom,
28044
28529
  timeMs,
28045
28530
  saltPrefix: 'octopus3',
28046
28531
  bodyPoints,
28532
+ variation: {
28533
+ flowLengthScale: morphologyProfile.tentacles.flowLengthScale,
28534
+ lateralReachScale: morphologyProfile.tentacles.lateralReachScale,
28535
+ tipReachScale: morphologyProfile.tentacles.tipReachScale,
28536
+ baseWidthScale: morphologyProfile.tentacles.baseWidthScale,
28537
+ tipWidthScale: morphologyProfile.tentacles.tipWidthScale,
28538
+ rootSpreadScale: morphologyProfile.tentacles.rootSpreadScale,
28539
+ startYOffsetScale: morphologyProfile.tentacles.startYOffsetScale,
28540
+ swayScale: morphologyProfile.tentacles.swayScale,
28541
+ },
28047
28542
  });
28048
28543
  drawAvatarFrame(context, size, palette);
28049
- drawOctopus3Atmosphere(context, size, palette, centerX, centerY, timeMs, shapePhase);
28544
+ drawOctopus3Atmosphere(context, size, palette, centerX, centerY, timeMs, shapePhase, morphologyProfile);
28050
28545
  context.beginPath();
28051
- context.ellipse(centerX, centerY + size * 0.25, size * 0.24, size * 0.08, 0, 0, Math.PI * 2);
28546
+ context.ellipse(centerX, centerY + size * 0.25, size * morphologyProfile.body.shadowWidthRatio, size * morphologyProfile.body.shadowHeightRatio, 0, 0, Math.PI * 2);
28052
28547
  context.fillStyle = `${palette.shadow}33`;
28053
28548
  context.fill();
28054
28549
  for (const tentacleShape of tentacleShapes) {
@@ -28076,8 +28571,8 @@ const octopus3AvatarVisual = {
28076
28571
  innerGlowGradient.addColorStop(1, `${palette.shadow}00`);
28077
28572
  context.fillStyle = innerGlowGradient;
28078
28573
  context.fillRect(centerX - size * 0.36, centerY - size * 0.34, size * 0.72, size * 0.72);
28079
- drawMantleCurrents(context, centerX, centerY, size, palette, timeMs, shapePhase);
28080
- drawMantleNodes(context, centerX, centerY, size, palette, createRandom);
28574
+ drawMantleCurrents(context, centerX, centerY, size, palette, timeMs, shapePhase, morphologyProfile);
28575
+ drawMantleNodes(context, centerX, centerY, size, palette, createRandom, morphologyProfile);
28081
28576
  context.restore();
28082
28577
  context.save();
28083
28578
  traceSmoothClosedPath(context, bodyPoints);
@@ -28086,14 +28581,19 @@ const octopus3AvatarVisual = {
28086
28581
  context.stroke();
28087
28582
  context.restore();
28088
28583
  context.beginPath();
28089
- context.ellipse(centerX, centerY - size * 0.14, size * 0.18, size * 0.062, 0, Math.PI, Math.PI * 2);
28584
+ context.ellipse(centerX, centerY + size * morphologyProfile.body.crownHighlightYOffsetRatio, size * morphologyProfile.body.crownHighlightWidthRatio, size * morphologyProfile.body.crownHighlightHeightRatio, 0, Math.PI, Math.PI * 2);
28090
28585
  context.fillStyle = `${palette.highlight}3d`;
28091
28586
  context.fill();
28092
- drawSeededEye(context, centerX - eyeSpacing, centerY - size * 0.01, eyeRadiusX, eyeRadiusY, (staticRandom() - 0.5) * 0.28, palette, timeMs, shapePhase, interaction);
28093
- drawSeededEye(context, centerX + eyeSpacing, centerY - size * 0.01, eyeRadiusX, eyeRadiusY, (staticRandom() - 0.5) * 0.28, palette, timeMs, shapePhase + Math.PI / 4, interaction);
28587
+ drawSeededEye(context, centerX - eyeSpacing, eyeCenterY, eyeRadiusX, eyeRadiusY, -morphologyProfile.face.eyeTiltBias + (eyeRandom() - 0.5) * morphologyProfile.face.eyeRotationRange, palette, timeMs, shapePhase, interaction, morphologyProfile.face.eyeStyle);
28588
+ drawSeededEye(context, centerX + eyeSpacing, eyeCenterY, eyeRadiusX, eyeRadiusY, morphologyProfile.face.eyeTiltBias + (eyeRandom() - 0.5) * morphologyProfile.face.eyeRotationRange, palette, timeMs, shapePhase + Math.PI / 4, interaction, morphologyProfile.face.eyeStyle);
28589
+ const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio;
28590
+ const mouthY = centerY + size * morphologyProfile.face.mouthYOffsetRatio;
28591
+ const mouthCornerTilt = size * morphologyProfile.face.mouthCornerTiltRatio;
28094
28592
  context.beginPath();
28095
- context.moveTo(centerX - size * 0.07, centerY + size * 0.09);
28096
- context.quadraticCurveTo(centerX, centerY + size * (0.14 + Math.sin(timeMs / 620 + shapePhase) * 0.016) + interaction.gazeY * size * 0.012, centerX + size * 0.07, centerY + size * 0.09);
28593
+ context.moveTo(centerX - mouthHalfWidth, mouthY - mouthCornerTilt);
28594
+ context.quadraticCurveTo(centerX + size * morphologyProfile.face.mouthCenterOffsetRatio, centerY +
28595
+ size * (morphologyProfile.face.mouthCurveDepthRatio + Math.sin(timeMs / 620 + shapePhase) * 0.016) +
28596
+ interaction.gazeY * size * 0.012, centerX + mouthHalfWidth, mouthY + mouthCornerTilt);
28097
28597
  context.strokeStyle = `${palette.ink}b3`;
28098
28598
  context.lineWidth = size * 0.012;
28099
28599
  context.lineCap = 'round';
@@ -28110,17 +28610,18 @@ const octopus3AvatarVisual = {
28110
28610
  * @param centerY Body center Y coordinate.
28111
28611
  * @param timeMs Current animation time in milliseconds.
28112
28612
  * @param shapePhase Seed-based phase offset.
28613
+ * @param morphologyProfile Seeded morphology profile.
28113
28614
  *
28114
28615
  * @private helper of `octopus3AvatarVisual`
28115
28616
  */
28116
- function drawOctopus3Atmosphere(context, size, palette, centerX, centerY, timeMs, shapePhase) {
28117
- const haloGradient = context.createRadialGradient(centerX, centerY - size * 0.08, size * 0.06, centerX, centerY, size * 0.62);
28617
+ function drawOctopus3Atmosphere(context, size, palette, centerX, centerY, timeMs, shapePhase, morphologyProfile) {
28618
+ const haloGradient = context.createRadialGradient(centerX, centerY - size * (0.07 + (morphologyProfile.body.verticalStretch - 0.9) * 0.05), size * 0.06, centerX, centerY, size * (0.56 + morphologyProfile.body.bodyRadiusRatio * 0.45));
28118
28619
  haloGradient.addColorStop(0, `${palette.highlight}5c`);
28119
28620
  haloGradient.addColorStop(0.35, `${palette.accent}26`);
28120
28621
  haloGradient.addColorStop(1, `${palette.highlight}00`);
28121
28622
  context.fillStyle = haloGradient;
28122
28623
  context.fillRect(0, 0, size, size);
28123
- const lowerGlowGradient = context.createRadialGradient(centerX + Math.sin(timeMs / 1600 + shapePhase) * size * 0.04, centerY + size * 0.2, size * 0.04, centerX, centerY + size * 0.2, size * 0.48);
28624
+ const lowerGlowGradient = context.createRadialGradient(centerX + Math.sin(timeMs / 1600 + shapePhase) * size * 0.04, centerY + size * (0.18 + morphologyProfile.tentacles.flowLengthScale * 0.025), size * 0.04, centerX, centerY + size * (0.18 + morphologyProfile.tentacles.flowLengthScale * 0.025), size * (0.42 + morphologyProfile.tentacles.lateralReachScale * 0.06));
28124
28625
  lowerGlowGradient.addColorStop(0, `${palette.secondary}1f`);
28125
28626
  lowerGlowGradient.addColorStop(1, `${palette.secondary}00`);
28126
28627
  context.fillStyle = lowerGlowGradient;
@@ -28229,18 +28730,22 @@ function drawTentacleSuckers(context, tentacleShape, palette) {
28229
28730
  * @param palette Derived avatar palette.
28230
28731
  * @param timeMs Current animation time in milliseconds.
28231
28732
  * @param shapePhase Seed-based phase offset.
28733
+ * @param morphologyProfile Seeded morphology profile.
28232
28734
  *
28233
28735
  * @private helper of `octopus3AvatarVisual`
28234
28736
  */
28235
- function drawMantleCurrents(context, centerX, centerY, size, palette, timeMs, shapePhase) {
28236
- for (let currentIndex = 0; currentIndex < 6; currentIndex++) {
28237
- const horizontalOffset = (currentIndex - 2.5) * size * 0.06;
28737
+ function drawMantleCurrents(context, centerX, centerY, size, palette, timeMs, shapePhase, morphologyProfile) {
28738
+ const centeredCurrentIndex = (morphologyProfile.details.mantleCurrentCount - 1) / 2;
28739
+ for (let currentIndex = 0; currentIndex < morphologyProfile.details.mantleCurrentCount; currentIndex++) {
28740
+ const horizontalOffset = (currentIndex - centeredCurrentIndex) *
28741
+ size *
28742
+ (0.05 + (morphologyProfile.body.horizontalStretch - 0.9) * 0.025);
28238
28743
  const sway = Math.sin(timeMs / 680 + currentIndex * 0.78 + shapePhase) * size * 0.024;
28239
28744
  context.beginPath();
28240
- context.moveTo(centerX + horizontalOffset * 0.3, centerY - size * 0.13);
28241
- context.bezierCurveTo(centerX + horizontalOffset - sway * 0.25, centerY - size * 0.04, centerX + horizontalOffset + sway, centerY + size * 0.06, centerX + horizontalOffset * 0.7 + sway * 0.46, centerY + size * 0.2);
28745
+ context.moveTo(centerX + horizontalOffset * 0.3, centerY - size * (0.11 + morphologyProfile.body.verticalStretch * 0.02));
28746
+ context.bezierCurveTo(centerX + horizontalOffset - sway * 0.25, centerY - size * 0.04, centerX + horizontalOffset + sway, centerY + size * 0.06, centerX + horizontalOffset * 0.7 + sway * 0.46, centerY + size * (0.16 + morphologyProfile.body.verticalStretch * 0.035));
28242
28747
  context.strokeStyle = currentIndex % 2 === 0 ? `${palette.highlight}30` : `${palette.accent}26`;
28243
- context.lineWidth = size * (0.008 + currentIndex * 0.0007);
28748
+ context.lineWidth = size * (0.0075 + currentIndex * 0.00065 + morphologyProfile.tentacles.baseWidthScale * 0.0005);
28244
28749
  context.lineCap = 'round';
28245
28750
  context.stroke();
28246
28751
  }
@@ -28254,14 +28759,17 @@ function drawMantleCurrents(context, centerX, centerY, size, palette, timeMs, sh
28254
28759
  * @param size Canvas size in CSS pixels.
28255
28760
  * @param palette Derived avatar palette.
28256
28761
  * @param createRandom Seeded random factory scoped to the avatar.
28762
+ * @param morphologyProfile Seeded morphology profile.
28257
28763
  *
28258
28764
  * @private helper of `octopus3AvatarVisual`
28259
28765
  */
28260
- function drawMantleNodes(context, centerX, centerY, size, palette, createRandom) {
28261
- for (let nodeIndex = 0; nodeIndex < 5; nodeIndex++) {
28766
+ function drawMantleNodes(context, centerX, centerY, size, palette, createRandom, morphologyProfile) {
28767
+ for (let nodeIndex = 0; nodeIndex < morphologyProfile.details.mantleNodeCount; nodeIndex++) {
28262
28768
  const nodeRandom = createRandom(`octopus3-node-${nodeIndex}`);
28263
- const nodeX = centerX + (nodeRandom() - 0.5) * size * 0.28;
28264
- const nodeY = centerY - size * 0.03 + (nodeRandom() - 0.5) * size * 0.2;
28769
+ const nodeX = centerX + (nodeRandom() - 0.5) * size * (0.2 + (morphologyProfile.body.horizontalStretch - 0.9) * 0.16);
28770
+ const nodeY = centerY -
28771
+ size * 0.03 +
28772
+ (nodeRandom() - 0.5) * size * (0.16 + (morphologyProfile.body.verticalStretch - 0.82) * 0.1);
28265
28773
  const nodeRadius = size * (0.016 + nodeRandom() * 0.016);
28266
28774
  context.beginPath();
28267
28775
  context.arc(nodeX, nodeY, nodeRadius, 0, Math.PI * 2);
@@ -28282,10 +28790,11 @@ function drawMantleNodes(context, centerX, centerY, size, palette, createRandom)
28282
28790
  * @param timeMs Current animation time in milliseconds.
28283
28791
  * @param phase Seed-based animation phase.
28284
28792
  * @param interaction Smoothed avatar interaction state.
28793
+ * @param eyeStyle Seeded eye-style traits.
28285
28794
  *
28286
28795
  * @private helper of `octopus3AvatarVisual`
28287
28796
  */
28288
- function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, palette, timeMs, phase, interaction) {
28797
+ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, palette, timeMs, phase, interaction, eyeStyle) {
28289
28798
  const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
28290
28799
  radiusX,
28291
28800
  radiusY,
@@ -28306,11 +28815,11 @@ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, pa
28306
28815
  irisGradient.addColorStop(0.58, palette.secondary);
28307
28816
  irisGradient.addColorStop(1, palette.shadow);
28308
28817
  context.beginPath();
28309
- context.ellipse(pupilOffsetX, pupilOffsetY, radiusX * 0.66, radiusY * 0.74, 0, 0, Math.PI * 2);
28818
+ context.ellipse(pupilOffsetX, pupilOffsetY, radiusX * 0.66 * eyeStyle.irisScale, radiusY * 0.74 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
28310
28819
  context.fillStyle = irisGradient;
28311
28820
  context.fill();
28312
28821
  context.beginPath();
28313
- context.ellipse(pupilOffsetX, pupilOffsetY, radiusX * 0.14, radiusY * 0.5, 0, 0, Math.PI * 2);
28822
+ context.ellipse(pupilOffsetX, pupilOffsetY, radiusX * 0.14 * eyeStyle.pupilWidthScale, radiusY * 0.5 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
28314
28823
  context.fillStyle = palette.ink;
28315
28824
  context.fill();
28316
28825
  context.beginPath();
@@ -28327,12 +28836,21 @@ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, pa
28327
28836
  context.lineWidth = radiusX * 0.18;
28328
28837
  context.stroke();
28329
28838
  context.beginPath();
28330
- context.moveTo(-radiusX * 0.88, -radiusY * 0.08);
28331
- context.quadraticCurveTo(0, -radiusY * (0.9 - interaction.gazeY * 0.16 + interaction.intensity * 0.08), radiusX * 0.88, -radiusY * 0.08);
28839
+ context.moveTo(-radiusX * 0.88, -radiusY * eyeStyle.upperLidInsetRatio);
28840
+ context.quadraticCurveTo(0, -radiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), radiusX * 0.88, -radiusY * eyeStyle.upperLidInsetRatio);
28332
28841
  context.strokeStyle = `${palette.shadow}73`;
28333
28842
  context.lineWidth = radiusX * 0.16;
28334
28843
  context.lineCap = 'round';
28335
28844
  context.stroke();
28845
+ if (eyeStyle.lowerLidOpacity > 0) {
28846
+ context.beginPath();
28847
+ context.moveTo(-radiusX * 0.74, radiusY * 0.2);
28848
+ context.quadraticCurveTo(0, radiusY * 0.38, radiusX * 0.74, radiusY * 0.2);
28849
+ context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
28850
+ context.lineWidth = radiusX * 0.08;
28851
+ context.lineCap = 'round';
28852
+ context.stroke();
28853
+ }
28336
28854
  context.restore();
28337
28855
  }
28338
28856
 
@@ -28466,32 +28984,55 @@ function getAvatarVisualById(visualId) {
28466
28984
  return avatarVisual;
28467
28985
  }
28468
28986
 
28987
+ /**
28988
+ * Resolves the stable avatar render inputs reused across multiple frames.
28989
+ *
28990
+ * @param options Avatar identity and visual selection.
28991
+ * @returns Stable render data ready to be used by `renderAvatarVisual`.
28992
+ *
28993
+ * @private shared helper for canvas avatar rendering
28994
+ */
28995
+ function resolveAvatarRenderDefinition(options) {
28996
+ const avatarDefinition = normalizeAvatarDefinition(options.avatarDefinition);
28997
+ const surface = options.surface || 'framed';
28998
+ return {
28999
+ avatarDefinition,
29000
+ avatarVisual: getAvatarVisualById(options.visualId),
29001
+ surface,
29002
+ palette: createAvatarPalette(avatarDefinition, surface),
29003
+ createRandom: createAvatarRandomFactory(avatarDefinition),
29004
+ };
29005
+ }
28469
29006
  /**
28470
29007
  * Renders one deterministic avatar frame into the provided canvas.
28471
29008
  *
28472
29009
  * @param options Rendering options.
29010
+ * @param resolvedAvatarRenderDefinition Optional stable render data reused between frames.
28473
29011
  *
28474
29012
  * @private shared helper for canvas avatar rendering
28475
29013
  */
28476
- function renderAvatarVisual(options) {
28477
- const normalizedAvatarDefinition = normalizeAvatarDefinition(options.avatarDefinition);
28478
- const avatarVisual = getAvatarVisualById(options.visualId);
28479
- const surface = options.surface || 'framed';
29014
+ function renderAvatarVisual(options, resolvedAvatarRenderDefinition) {
29015
+ const resolvedRenderDefinition = resolvedAvatarRenderDefinition ||
29016
+ resolveAvatarRenderDefinition({
29017
+ avatarDefinition: options.avatarDefinition,
29018
+ visualId: options.visualId,
29019
+ surface: options.surface,
29020
+ });
28480
29021
  const context = options.canvas.getContext('2d');
28481
29022
  if (!context) {
28482
29023
  throw new Error('2D canvas rendering context is unavailable.');
28483
29024
  }
28484
29025
  prepareAvatarCanvas(options.canvas, context, options.size, options.devicePixelRatio || 1);
28485
- avatarVisual.render({
29026
+ resolvedRenderDefinition.avatarVisual.render({
28486
29027
  canvas: options.canvas,
28487
29028
  context,
28488
29029
  size: options.size,
28489
29030
  devicePixelRatio: options.devicePixelRatio || 1,
28490
29031
  timeMs: options.timeMs,
28491
- avatarDefinition: normalizedAvatarDefinition,
28492
- palette: createAvatarPalette(normalizedAvatarDefinition, surface),
28493
- createRandom: createAvatarRandomFactory(normalizedAvatarDefinition),
28494
- surface,
29032
+ avatarDefinition: resolvedRenderDefinition.avatarDefinition,
29033
+ palette: resolvedRenderDefinition.palette,
29034
+ createRandom: resolvedRenderDefinition.createRandom,
29035
+ surface: resolvedRenderDefinition.surface,
28495
29036
  interaction: options.interaction || createIdleAvatarInteractionState(),
28496
29037
  });
28497
29038
  }
@@ -28502,6 +29043,14 @@ function renderAvatarVisual(options) {
28502
29043
  * @private helper of `<Avatar/>`
28503
29044
  */
28504
29045
  const AVATAR_CANVAS_RADIUS_RATIO = 0.18;
29046
+ /**
29047
+ * Maximum time between layout-bound refreshes while pointer tracking is active.
29048
+ *
29049
+ * This keeps pointer-aware visuals aligned with chat/layout shifts without forcing a layout read every frame.
29050
+ *
29051
+ * @private helper of `<Avatar/>`
29052
+ */
29053
+ const ACTIVE_POINTER_BOUNDS_REFRESH_MS = 120;
28505
29054
  /**
28506
29055
  * Canvas-based deterministic avatar component.
28507
29056
  *
@@ -28512,21 +29061,58 @@ function Avatar(props) {
28512
29061
  const canvasRef = useRef(null);
28513
29062
  const animationStartRef = useRef(null);
28514
29063
  const interactionRuntimeStateRef = useRef(createAvatarInteractionRuntimeState());
29064
+ const avatarBoundsRef = useRef(null);
29065
+ const lastResolvedPointerVersionRef = useRef(-1);
29066
+ const lastResolvedViewportLayoutVersionRef = useRef(-1);
29067
+ const lastAvatarBoundsRefreshAtRef = useRef(0);
28515
29068
  const avatarColorsKey = avatarDefinition.colors.join('|');
28516
- const normalizedAvatarDefinition = useMemo(() => normalizeAvatarDefinition(avatarDefinition), [avatarDefinition.agentHash, avatarDefinition.agentName, avatarColorsKey]);
28517
- const avatarDefinitionKey = useMemo(() => createAvatarDefinitionKey(normalizedAvatarDefinition), [normalizedAvatarDefinition.agentHash, normalizedAvatarDefinition.agentName, normalizedAvatarDefinition.colors.join('|')]);
28518
- const avatarVisual = useMemo(() => getAvatarVisualById(visualId), [visualId]);
29069
+ const resolvedAvatarRenderDefinition = useMemo(() => resolveAvatarRenderDefinition({
29070
+ avatarDefinition,
29071
+ visualId,
29072
+ surface,
29073
+ }), [avatarDefinition.agentHash, avatarDefinition.agentName, avatarColorsKey, surface, visualId]);
29074
+ const avatarDefinitionKey = useMemo(() => createAvatarDefinitionKey(resolvedAvatarRenderDefinition.avatarDefinition), [
29075
+ resolvedAvatarRenderDefinition.avatarDefinition.agentHash,
29076
+ resolvedAvatarRenderDefinition.avatarDefinition.agentName,
29077
+ resolvedAvatarRenderDefinition.avatarDefinition.colors.join('|'),
29078
+ ]);
29079
+ const [isVisible, setIsVisible] = useState(true);
29080
+ useEffect(() => {
29081
+ const canvas = canvasRef.current;
29082
+ if (!canvas) {
29083
+ throw new Error('Avatar canvas is not mounted.');
29084
+ }
29085
+ return observeAvatarVisibility(canvas, setIsVisible);
29086
+ }, []);
28519
29087
  useEffect(() => {
28520
29088
  interactionRuntimeStateRef.current = createAvatarInteractionRuntimeState();
28521
- }, [avatarDefinitionKey, visualId]);
29089
+ avatarBoundsRef.current = null;
29090
+ lastResolvedPointerVersionRef.current = -1;
29091
+ lastResolvedViewportLayoutVersionRef.current = -1;
29092
+ lastAvatarBoundsRefreshAtRef.current = 0;
29093
+ }, [avatarDefinitionKey, isVisible, visualId]);
29094
+ useEffect(() => {
29095
+ const canvas = canvasRef.current;
29096
+ if (!canvas || typeof ResizeObserver === 'undefined') {
29097
+ return;
29098
+ }
29099
+ const resizeObserver = new ResizeObserver(() => {
29100
+ avatarBoundsRef.current = null;
29101
+ });
29102
+ resizeObserver.observe(canvas);
29103
+ return () => {
29104
+ resizeObserver.disconnect();
29105
+ };
29106
+ }, []);
28522
29107
  useEffect(() => {
28523
29108
  const canvas = canvasRef.current;
28524
29109
  if (!canvas) {
28525
29110
  throw new Error('Avatar canvas is not mounted.');
28526
29111
  }
29112
+ const avatarVisual = resolvedAvatarRenderDefinition.avatarVisual;
28527
29113
  const isDynamicAvatar = avatarVisual.isAnimated || avatarVisual.supportsPointerTracking === true;
28528
- const releasePointerTracking = avatarVisual.supportsPointerTracking ? retainAvatarPointerTracking() : null;
28529
- let animationFrameId = null;
29114
+ const shouldTrackPointer = avatarVisual.supportsPointerTracking === true && isVisible;
29115
+ const releasePointerTracking = shouldTrackPointer ? retainAvatarPointerTracking() : null;
28530
29116
  if (animationStartRef.current === null) {
28531
29117
  animationStartRef.current = performance.now();
28532
29118
  }
@@ -28534,7 +29120,18 @@ function Avatar(props) {
28534
29120
  const pointerSnapshot = avatarVisual.supportsPointerTracking ? getAvatarPointerSnapshot() : null;
28535
29121
  let interactionState = createIdleAvatarInteractionState();
28536
29122
  if (avatarVisual.supportsPointerTracking && pointerSnapshot) {
28537
- interactionRuntimeStateRef.current = stepAvatarInteractionRuntimeState(interactionRuntimeStateRef.current, resolveAvatarPointerTarget(canvas.getBoundingClientRect(), pointerSnapshot), now);
29123
+ const pointerSnapshotVersion = getAvatarPointerSnapshotVersion();
29124
+ const viewportLayoutVersion = getAvatarViewportLayoutVersion();
29125
+ if (avatarBoundsRef.current === null ||
29126
+ lastResolvedPointerVersionRef.current !== pointerSnapshotVersion ||
29127
+ lastResolvedViewportLayoutVersionRef.current !== viewportLayoutVersion ||
29128
+ now - lastAvatarBoundsRefreshAtRef.current >= ACTIVE_POINTER_BOUNDS_REFRESH_MS) {
29129
+ avatarBoundsRef.current = canvas.getBoundingClientRect();
29130
+ lastResolvedPointerVersionRef.current = pointerSnapshotVersion;
29131
+ lastResolvedViewportLayoutVersionRef.current = viewportLayoutVersion;
29132
+ lastAvatarBoundsRefreshAtRef.current = now;
29133
+ }
29134
+ interactionRuntimeStateRef.current = stepAvatarInteractionRuntimeState(interactionRuntimeStateRef.current, resolveAvatarPointerTarget(avatarBoundsRef.current, pointerSnapshot), now);
28538
29135
  interactionState = interactionRuntimeStateRef.current;
28539
29136
  }
28540
29137
  else if (avatarVisual.supportsPointerTracking) {
@@ -28543,35 +29140,35 @@ function Avatar(props) {
28543
29140
  }
28544
29141
  renderAvatarVisual({
28545
29142
  canvas,
28546
- avatarDefinition: normalizedAvatarDefinition,
29143
+ avatarDefinition: resolvedAvatarRenderDefinition.avatarDefinition,
28547
29144
  visualId,
28548
29145
  surface,
28549
29146
  size,
28550
29147
  timeMs: now - animationStartRef.current,
28551
29148
  devicePixelRatio: window.devicePixelRatio || 1,
28552
29149
  interaction: interactionState,
28553
- });
28554
- if (isDynamicAvatar) {
28555
- animationFrameId = window.requestAnimationFrame(renderFrame);
28556
- }
29150
+ }, resolvedAvatarRenderDefinition);
28557
29151
  };
28558
29152
  renderFrame(performance.now());
29153
+ if (!isDynamicAvatar || !isVisible) {
29154
+ return () => {
29155
+ releasePointerTracking === null || releasePointerTracking === void 0 ? void 0 : releasePointerTracking();
29156
+ };
29157
+ }
29158
+ const releaseAnimationListener = retainAvatarAnimationListener(renderFrame);
28559
29159
  return () => {
28560
- if (animationFrameId !== null) {
28561
- window.cancelAnimationFrame(animationFrameId);
28562
- }
29160
+ releaseAnimationListener();
28563
29161
  releasePointerTracking === null || releasePointerTracking === void 0 ? void 0 : releasePointerTracking();
28564
29162
  };
28565
29163
  }, [
28566
29164
  avatarDefinitionKey,
28567
- avatarVisual.isAnimated,
28568
- avatarVisual.supportsPointerTracking,
28569
- normalizedAvatarDefinition,
29165
+ isVisible,
29166
+ resolvedAvatarRenderDefinition,
28570
29167
  size,
28571
29168
  surface,
28572
29169
  visualId,
28573
29170
  ]);
28574
- return (jsx("canvas", { ref: canvasRef, title: title || `${normalizedAvatarDefinition.agentName} avatar`, className: className, style: {
29171
+ return (jsx("canvas", { ref: canvasRef, title: title || `${resolvedAvatarRenderDefinition.avatarDefinition.agentName} avatar`, className: className, style: {
28575
29172
  width: size,
28576
29173
  height: size,
28577
29174
  display: 'block',
@@ -29980,7 +30577,7 @@ function StreamingFeaturePlaceholder({ kind }) {
29980
30577
  * @private internal component of `<ChatMessageItem/>`
29981
30578
  */
29982
30579
  function ChatMessageRichContent(props) {
29983
- const { content, contentSegments, streamingFeaturePlaceholderKind, onCreateAgent } = props;
30580
+ const { content, contentSegments, streamingFeaturePlaceholderKind, onCreateAgent, mode } = props;
29984
30581
  if (content === LOADING_INTERACTIVE_IMAGE) {
29985
30582
  return null;
29986
30583
  }
@@ -29989,7 +30586,7 @@ function ChatMessageRichContent(props) {
29989
30586
  return (jsx(MarkdownContent, { content: segment.content, onCreateAgent: onCreateAgent }, `text-${segmentIndex}`));
29990
30587
  }
29991
30588
  if (segment.type === 'code') {
29992
- return (jsx(CodeBlock, { code: segment.code, language: segment.language, onCreateAgent: onCreateAgent }, `code-${segmentIndex}`));
30589
+ return (jsx(CodeBlock, { code: segment.code, language: segment.language, onCreateAgent: onCreateAgent, theme: mode }, `code-${segmentIndex}`));
29993
30590
  }
29994
30591
  if (segment.type === 'image') {
29995
30592
  return (jsx(ImagePromptRenderer, { alt: segment.alt, prompt: segment.prompt }, `image-${segmentIndex}`));
@@ -46822,6 +47419,8 @@ const ChatMessageItem = memo(
46822
47419
  const swipeDirectionMultiplier = isMe ? -1 : 1;
46823
47420
  const swipeTranslation = `${isMe ? -replySwipeDistance : replySwipeDistance}px`;
46824
47421
  const isReplySwipeArmed = replySwipeDistance >= REPLY_SWIPE_TRIGGER_PX * 0.5;
47422
+ const articleModeBackgroundColor = mode === 'DARK' ? 'rgba(15, 23, 42, 0.78)' : '#ffffff';
47423
+ const articleModeTextColor = mode === 'DARK' ? '#e2e8f0' : '#0f172a';
46825
47424
  /**
46826
47425
  * Renders the optional message utility buttons used for copy/read actions.
46827
47426
  *
@@ -47023,10 +47622,12 @@ const ChatMessageItem = memo(
47023
47622
  aspectRatio: '1 / 1',
47024
47623
  borderRadius: '50%',
47025
47624
  } })), isAvatarTooltipVisible && (participant === null || participant === void 0 ? void 0 : participant.agentSource) && avatarTooltipPosition && (jsx(AvatarProfileTooltip, { ref: tooltipRef, agentSource: participant.agentSource, position: avatarTooltipPosition }))] })), jsxs("div", { className: classNames(styles$5.messageStack, chatCssClassNames.messageStack), children: [shouldShowParticipantLabel && participantLabel && (jsx("div", { className: styles$5.participantLabel, children: participantLabel })), jsxs("div", { className: classNames(styles$5.messageText, isReplyActionEnabled && styles$5.replyEnabledMessageText, isReplySwipeArmed && styles$5.replySwipeActive, isAgentArticleMode && styles$5.articleModeAgentMessageText, chatCssClassNames.messageContent), style: {
47026
- '--message-bg-color': isAgentArticleMode ? '#ffffff' : color.toHex(),
47027
- '--message-text-color': isAgentArticleMode ? '#0f172a' : colorOfText.toHex(),
47625
+ '--message-bg-color': isAgentArticleMode ? articleModeBackgroundColor : color.toHex(),
47626
+ '--message-text-color': isAgentArticleMode
47627
+ ? articleModeTextColor
47628
+ : colorOfText.toHex(),
47028
47629
  '--chat-message-swipe-offset': swipeTranslation,
47029
- }, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsx("div", { className: classNames(styles$5.replySwipeIndicator, isMe && styles$5.replySwipeIndicatorRight, isReplySwipeArmed && styles$5.replySwipeIndicatorActive), "aria-hidden": "true", children: jsx(Reply, { className: styles$5.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsx("div", { className: styles$5.voiceCallIndicator, children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }) })), replyingToMessage && replyPreviewText && replySenderLabel && (jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$5.replyBubblePreview })), jsx("div", { ref: contentWithoutButtonsRef, children: jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent }) }), message.attachments && message.attachments.length > 0 && (jsx("div", { className: styles$5.attachments, children: message.attachments.map((attachment, index) => (jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$5.attachment, title: attachment.name, children: [jsx("span", { className: styles$5.attachmentIcon, children: "\uD83D\uDCCE" }), jsx("span", { className: styles$5.attachmentName, children: attachment.name })] }, index))) })), jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsx("div", { className: styles$5.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxs("div", { className: styles$5.citationFootnoteItem, children: [jsx("span", { className: styles$5.citationFootnoteNumber, children: footnote.number }), jsx(SourceChip, { citation: footnote.citation, onClick: onCitationClick, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsx("div", { className: styles$5.sourceCitations, children: transitiveCitations.map((citation, index) => (jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, onClick: onCitationClick }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsx("div", { className: styles$5.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsx("button", { type: "button", className: classNames(styles$5.messageButton, button.type === 'action' && styles$5.actionMessageButton), onClick: (event) => {
47630
+ }, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsx("div", { className: classNames(styles$5.replySwipeIndicator, isMe && styles$5.replySwipeIndicatorRight, isReplySwipeArmed && styles$5.replySwipeIndicatorActive), "aria-hidden": "true", children: jsx(Reply, { className: styles$5.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsx("div", { className: styles$5.voiceCallIndicator, children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }) })), replyingToMessage && replyPreviewText && replySenderLabel && (jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$5.replyBubblePreview })), jsx("div", { ref: contentWithoutButtonsRef, children: jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsx("div", { className: styles$5.attachments, children: message.attachments.map((attachment, index) => (jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$5.attachment, title: attachment.name, children: [jsx("span", { className: styles$5.attachmentIcon, children: "\uD83D\uDCCE" }), jsx("span", { className: styles$5.attachmentName, children: attachment.name })] }, index))) })), jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsx("div", { className: styles$5.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxs("div", { className: styles$5.citationFootnoteItem, children: [jsx("span", { className: styles$5.citationFootnoteNumber, children: footnote.number }), jsx(SourceChip, { citation: footnote.citation, onClick: onCitationClick, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsx("div", { className: styles$5.sourceCitations, children: transitiveCitations.map((citation, index) => (jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, onClick: onCitationClick }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsx("div", { className: styles$5.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsx("button", { type: "button", className: classNames(styles$5.messageButton, button.type === 'action' && styles$5.actionMessageButton), onClick: (event) => {
47030
47631
  event.stopPropagation();
47031
47632
  if (button.type === 'message') {
47032
47633
  const quickMessageHandler = onQuickMessageButton || onMessage;
@@ -47220,7 +47821,7 @@ function ChatRatingModal(props) {
47220
47821
  }
47221
47822
  return '';
47222
47823
  })();
47223
- return (jsx("div", { className: styles$5.ratingModal, onClick: (event) => {
47824
+ return (jsx("div", { className: styles$5.ratingModal, "data-chat-modal": "rating", "data-chat-theme": mode.toLowerCase(), onClick: (event) => {
47224
47825
  if (event.target === event.currentTarget && isMobile) {
47225
47826
  onClose();
47226
47827
  }
@@ -47324,12 +47925,14 @@ const TOOL_CALL_REPORT_FILENAME_UNSAFE_CHARACTER_PATTERN = /[^a-zA-Z0-9_-]/g;
47324
47925
  */
47325
47926
  function renderAdvancedToolCallDetails(options) {
47326
47927
  const { toolCall } = options;
47928
+ const mode = options.mode || 'LIGHT';
47327
47929
  const header = resolveAdvancedToolCallHeader(options);
47328
47930
  const payloadSections = createAdvancedToolCallPayloadSections(toolCall, options.availableTools);
47329
47931
  return (jsxs(Fragment, { children: [jsxs("header", { className: styles$5.toolCallHeader, children: [jsx("span", { className: styles$5.toolCallIcon, "aria-hidden": "true", children: header.emoji }), jsxs("div", { className: styles$5.toolCallHeaderMeta, children: [jsx("p", { className: styles$5.toolCallModalLabel, children: "Advanced" }), jsx("h3", { className: styles$5.toolCallTitle, children: header.title }), jsxs("p", { className: styles$5.toolCallSubtitle, children: [header.subtitle, " \u00B7 ", resolveToolCallState(toolCall).toLowerCase()] })] })] }), jsx("div", { className: styles$5.toolCallGrid, children: payloadSections.map((payloadSection) => (jsxs("section", { className: styles$5.toolCallPanel, children: [jsx("p", { className: styles$5.toolCallPanelTitle, children: payloadSection.title }), renderAdvancedToolCallPayload({
47330
47932
  toolCall,
47331
47933
  sectionId: payloadSection.id,
47332
47934
  payload: payloadSection.payload,
47935
+ mode,
47333
47936
  })] }, payloadSection.id))) })] }));
47334
47937
  }
47335
47938
  /**
@@ -47463,7 +48066,7 @@ function createAdvancedToolCallPayloadSections(toolCall, availableTools) {
47463
48066
  * @private function of ChatToolCallModal
47464
48067
  */
47465
48068
  function renderAdvancedToolCallPayload(options) {
47466
- const { toolCall, sectionId, payload } = options;
48069
+ const { toolCall, sectionId, payload, mode } = options;
47467
48070
  const formattedPayload = formatToolCallPayload(payload);
47468
48071
  const modelPath = createToolCallPayloadMonacoPath({
47469
48072
  toolCall,
@@ -47471,7 +48074,7 @@ function renderAdvancedToolCallPayload(options) {
47471
48074
  language: formattedPayload.language,
47472
48075
  });
47473
48076
  const editorHeight = resolveToolCallPayloadEditorHeight(formattedPayload.content);
47474
- return (jsx("div", { className: styles$5.toolCallPayloadContainer, children: jsx("div", { className: styles$5.toolCallPayloadEditor, children: jsx(MonacoEditorWithShadowDom, { height: `${editorHeight}px`, language: formattedPayload.language, path: modelPath, value: formattedPayload.content, theme: "vs-light", options: TOOL_CALL_PAYLOAD_EDITOR_OPTIONS }) }) }));
48077
+ return (jsx("div", { className: styles$5.toolCallPayloadContainer, children: jsx("div", { className: styles$5.toolCallPayloadEditor, children: jsx(MonacoEditorWithShadowDom, { height: `${editorHeight}px`, language: formattedPayload.language, path: modelPath, value: formattedPayload.content, theme: mode === 'DARK' ? 'vs-dark' : 'vs-light', options: TOOL_CALL_PAYLOAD_EDITOR_OPTIONS }) }) }));
47475
48078
  }
47476
48079
  /**
47477
48080
  * Resolves Monaco editor height from payload line count with bounded limits.
@@ -49543,12 +50146,6 @@ function TeamToolCallModalContent(options) {
49543
50146
  });
49544
50147
  }
49545
50148
  }
49546
- const staticConversationDelayConfig = {
49547
- ...FAST_FLOW,
49548
- beforeFirstMessage: 0,
49549
- // Show the full internal exchange immediately so the modal never opens as a blank panel.
49550
- showIntermediateMessages: messages.length,
49551
- };
49552
50149
  const agentName = ((_c = (_b = teamResult.conversation) === null || _b === void 0 ? void 0 : _b.find((entry) => entry.sender === 'AGENT' || entry.role === 'AGENT')) === null || _c === void 0 ? void 0 : _c.name) || 'Agent';
49553
50150
  const teammateConversationName = ((_e = (_d = teamResult.conversation) === null || _d === void 0 ? void 0 : _d.find((entry) => entry.sender === 'TEAMMATE' || entry.role === 'TEAMMATE')) === null || _e === void 0 ? void 0 : _e.name) || '';
49554
50151
  const teammateProfile = teammateUrl ? teamProfiles[teammateUrl] : undefined;
@@ -49585,7 +50182,12 @@ function TeamToolCallModalContent(options) {
49585
50182
  avatarSrc: resolvedTeammateAvatar || undefined,
49586
50183
  },
49587
50184
  ];
49588
- return (jsxs(Fragment, { children: [jsx("div", { className: classNames(styles$5.searchModalHeader, styles$5.teamModalHeader), children: jsxs("div", { className: styles$5.teamHeaderParticipants, children: [jsx(TeamHeaderProfile, { label: resolvedAgentLabel, avatarSrc: resolvedAgentAvatar, avatarDefinition: resolvedAgentAvatarDefinition, avatarVisualId: resolvedAgentAvatarVisualId, fallbackColor: resolvedAgentHeaderColor }), jsx("span", { className: styles$5.teamHeaderDivider, children: "talking with" }), jsx(TeamHeaderProfile, { label: resolvedTeammateLabel, avatarSrc: resolvedTeammateAvatar, fallbackColor: "#0ea5e9", href: teammateLink })] }) }), jsxs("div", { className: styles$5.searchModalContent, children: [messages.length > 0 ? (jsx("div", { className: styles$5.teamChatContainer, children: jsx(MockedChat, { title: `Chat between ${resolvedAgentLabel} and ${resolvedTeammateLabel}`, messages: messages, participants: participants, isResettable: false, isPausable: false, isSaveButtonEnabled: false, isCopyButtonEnabled: false, visual: "STANDALONE", delayConfig: staticConversationDelayConfig }) })) : (jsx("div", { className: styles$5.noResults, children: "No teammate conversation available." })), (hasTeamToolCalls || hasTeamCitations) && (jsxs("div", { className: styles$5.teamToolCallSection, children: [hasTeamToolCalls && (jsxs("div", { className: styles$5.teamToolCallGroup, children: [jsx("div", { className: styles$5.teamToolCallHeading, children: "Actions" }), jsx("div", { className: styles$5.teamToolCallChips, children: teamToolCalls.map((toolCallEntry, index) => {
50185
+ return (jsxs(Fragment, { children: [jsx("div", { className: classNames(styles$5.searchModalHeader, styles$5.teamModalHeader), children: jsxs("div", { className: styles$5.teamHeaderParticipants, children: [jsx(TeamHeaderProfile, { label: resolvedAgentLabel, avatarSrc: resolvedAgentAvatar, avatarDefinition: resolvedAgentAvatarDefinition, avatarVisualId: resolvedAgentAvatarVisualId, fallbackColor: resolvedAgentHeaderColor }), jsx("span", { className: styles$5.teamHeaderDivider, children: "talking with" }), jsx(TeamHeaderProfile, { label: resolvedTeammateLabel, avatarSrc: resolvedTeammateAvatar, fallbackColor: "#0ea5e9", href: teammateLink })] }) }), jsxs("div", { className: styles$5.searchModalContent, children: [messages.length > 0 ? (jsx("div", { className: styles$5.teamChatContainer, children: jsx(MockedChat, { title: `Chat between ${resolvedAgentLabel} and ${resolvedTeammateLabel}`, messages: messages, participants: participants, isResettable: false, isPausable: false, isSaveButtonEnabled: false, isCopyButtonEnabled: false, layout: "STANDALONE", delayConfig: {
50186
+ // Note+TODO: For some strange reason, <MockedChat/> is not running and stays static on the initial frame, so doing this hack to force it to show the entire chat at once. Need to investigate why the animation is not running as expected and then just use `delayConfig={FAST_FLOW}`
50187
+ ...FAST_FLOW,
50188
+ beforeFirstMessage: 0,
50189
+ showIntermediateMessages: messages.length,
50190
+ }, visualMode: "BUBBLE_MODE" }) })) : (jsx("div", { className: styles$5.noResults, children: "No teammate conversation available." })), (hasTeamToolCalls || hasTeamCitations) && (jsxs("div", { className: styles$5.teamToolCallSection, children: [hasTeamToolCalls && (jsxs("div", { className: styles$5.teamToolCallGroup, children: [jsx("div", { className: styles$5.teamToolCallHeading, children: "Actions" }), jsx("div", { className: styles$5.teamToolCallChips, children: teamToolCalls.map((toolCallEntry, index) => {
49589
50191
  const chipletInfo = getToolCallChipletInfo(toolCallEntry.toolCall, undefined, toolTitles);
49590
50192
  const chipletText = buildToolCallChipText(chipletInfo);
49591
50193
  return (jsxs("button", { className: styles$5.completedToolCall, onClick: () => {
@@ -49604,12 +50206,13 @@ function TeamToolCallModalContent(options) {
49604
50206
  *
49605
50207
  * @private component of `ChatToolCallModal`
49606
50208
  */
49607
- function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColor, chatUiTranslations, focusedToolCall, isAdvancedView, locale, onClearSelectedTeamToolCall, onRequestAdvancedView, onSelectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toolCall, toolCallDate, toolTitles, }) {
50209
+ function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColor, chatUiTranslations, focusedToolCall, isAdvancedView, locale, mode, onClearSelectedTeamToolCall, onRequestAdvancedView, onSelectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toolCall, toolCallDate, toolTitles, }) {
49608
50210
  if (isAdvancedView) {
49609
50211
  return renderAdvancedToolCallDetails({
49610
50212
  toolCall: focusedToolCall,
49611
50213
  toolTitles,
49612
50214
  availableTools,
50215
+ mode,
49613
50216
  });
49614
50217
  }
49615
50218
  if (teamResult === null || teamResult === void 0 ? void 0 : teamResult.teammate) {
@@ -49876,7 +50479,7 @@ function handleModalBackdropClick(event, onClose) {
49876
50479
  * @private component of `<Chat/>`
49877
50480
  */
49878
50481
  function ChatToolCallModal(props) {
49879
- const { isOpen, toolCall, toolCallIdentity, onClose, toolTitles, agentParticipant, buttonColor, teamAgentProfiles, chatUiTranslations, locale, availableTools, } = props;
50482
+ const { isOpen, toolCall, mode = 'LIGHT', toolCallIdentity, onClose, toolTitles, agentParticipant, buttonColor, teamAgentProfiles, chatUiTranslations, locale, availableTools, } = props;
49880
50483
  const { clearSelectedTeamToolCall, exportAdvancedToolCallReport, focusedToolCall, isAdvancedView, modalDialogRef, openAdvancedView, selectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toggleViewMode, toolCallDate, } = useChatToolCallModalState({
49881
50484
  isOpen,
49882
50485
  toolCall,
@@ -49896,9 +50499,9 @@ function ChatToolCallModal(props) {
49896
50499
  const modeToggleLabel = isAdvancedView
49897
50500
  ? (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.toolCallModalSimpleLabel) || 'Simple'
49898
50501
  : (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.toolCallModalAdvancedLabel) || 'Advanced';
49899
- return (jsx("div", { className: styles$5.ratingModal, onClick: (event) => {
50502
+ return (jsx("div", { className: styles$5.ratingModal, "data-chat-modal": "tool-call", "data-chat-theme": mode.toLowerCase(), onClick: (event) => {
49900
50503
  handleModalBackdropClick(event, onClose);
49901
- }, children: jsxs("div", { ref: modalDialogRef, className: classNames(styles$5.ratingModalContent, styles$5.toolCallModal), role: "dialog", "aria-modal": "true", "aria-label": modalTitle, tabIndex: -1, children: [jsx("button", { type: "button", className: styles$5.modalCloseButton, onClick: onClose, "aria-label": closeButtonLabel, children: jsx(CloseIcon, {}) }), jsx(ChatToolCallModalContent, { toolCall: toolCall, focusedToolCall: resolvedFocusedToolCall, isAdvancedView: isAdvancedView, teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: selectTeamToolCall, onClearSelectedTeamToolCall: clearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, locale: locale, chatUiTranslations: chatUiTranslations, availableTools: availableTools, onRequestAdvancedView: openAdvancedView }), jsxs("div", { className: styles$5.toolCallModeFooter, children: [isAdvancedView && (jsxs(Fragment, { children: [jsx("button", { type: "button", className: styles$5.toolCallModeButton, onClick: () => {
50504
+ }, children: jsxs("div", { ref: modalDialogRef, className: classNames(styles$5.ratingModalContent, styles$5.toolCallModal), role: "dialog", "aria-modal": "true", "aria-label": modalTitle, tabIndex: -1, children: [jsx("button", { type: "button", className: styles$5.modalCloseButton, onClick: onClose, "aria-label": closeButtonLabel, children: jsx(CloseIcon, {}) }), jsx(ChatToolCallModalContent, { toolCall: toolCall, focusedToolCall: resolvedFocusedToolCall, isAdvancedView: isAdvancedView, teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: selectTeamToolCall, onClearSelectedTeamToolCall: clearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, locale: locale, chatUiTranslations: chatUiTranslations, availableTools: availableTools, onRequestAdvancedView: openAdvancedView, mode: mode }), jsxs("div", { className: styles$5.toolCallModeFooter, children: [isAdvancedView && (jsxs(Fragment, { children: [jsx("button", { type: "button", className: styles$5.toolCallModeButton, onClick: () => {
49902
50505
  void exportAdvancedToolCallReport('clipboard');
49903
50506
  }, children: copyButtonLabel }), jsx("button", { type: "button", className: styles$5.toolCallModeButton, onClick: () => {
49904
50507
  void exportAdvancedToolCallReport('file');
@@ -50524,7 +51127,7 @@ function hasChatActions(postprocessedMessages, { onReset, newChatButtonHref, onU
50524
51127
  * @public exported from `@promptbook/components`
50525
51128
  */
50526
51129
  function Chat(props) {
50527
- const { title = 'Chat', messages, onChange, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, onCancelReply, onReset, resetRequiresConfirmation = true, newChatButtonHref, onFeedback, feedbackMode = 'stars', feedbackTranslations, timingTranslations, onFileUpload, chatLocale, speechRecognition, placeholderMessageContent, defaultMessage, enterBehavior, resolveEnterBehavior, children, className, style, isAiTextHumanizedAndPromptbookified = true, isVoiceCalling = false, isFocusedOnLoad, participants = [], canReplyToMessage, replyingToMessage, extraActions, actionsContainer, saveFormats, isSaveButtonEnabled = true, isCopyButtonEnabled = true, buttonColor: buttonColorRaw, onUseTemplate, onCreateAgent, toolTitles, teammates, teamAgentProfiles, visual, visualMode = 'ARTICLE_MODE', effectConfigs, soundSystem, speechRecognitionLanguage, isSpeechPlaybackEnabled = true, elevenLabsVoiceId, chatUiTranslations, } = props;
51130
+ const { title = 'Chat', messages, onChange, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, onCancelReply, onReset, resetRequiresConfirmation = true, newChatButtonHref, onFeedback, feedbackMode = 'stars', feedbackTranslations, timingTranslations, onFileUpload, chatLocale, speechRecognition, placeholderMessageContent, defaultMessage, enterBehavior, resolveEnterBehavior, children, className, style, isAiTextHumanizedAndPromptbookified = true, isVoiceCalling = false, isFocusedOnLoad, participants = [], canReplyToMessage, replyingToMessage, extraActions, actionsContainer, saveFormats, isSaveButtonEnabled = true, isCopyButtonEnabled = true, buttonColor: buttonColorRaw, onUseTemplate, onCreateAgent, toolTitles, teammates, teamAgentProfiles, layout, visualMode = 'ARTICLE_MODE', theme = 'LIGHT', effectConfigs, soundSystem, speechRecognitionLanguage, isSpeechPlaybackEnabled = true, elevenLabsVoiceId, chatUiTranslations, } = props;
50528
51131
  const buttonColor = useMemo(() => Color.from(buttonColorRaw || '#0066cc'), [buttonColorRaw]);
50529
51132
  const agentParticipant = useMemo(() => participants.find((participant) => participant.name === 'AGENT'), [participants]);
50530
51133
  const postprocessedMessages = useChatPostprocessedMessages({
@@ -50544,7 +51147,7 @@ function Chat(props) {
50544
51147
  const { citationModalOpen, closeCitationModal, closeToolCallModal, openCitation, openToolCall, selectedCitation, selectedMessageAvailableTools, selectedToolCall, selectedToolCallIdentity, toolCallModalOpen, } = useChatToolCallState({
50545
51148
  messages: postprocessedMessages,
50546
51149
  });
50547
- const mode = 'LIGHT';
51150
+ const mode = theme;
50548
51151
  const scrollToBottomCssClassName = getChatCssClassName('scrollToBottom');
50549
51152
  const handleButtonClick = useCallback((originalHandler) => {
50550
51153
  return (event) => {
@@ -50565,11 +51168,11 @@ function Chat(props) {
50565
51168
  extraActions,
50566
51169
  isSaveButtonEnabled,
50567
51170
  });
50568
- const isConstrainedArticleMode = visualMode === 'ARTICLE_MODE' && visual === 'FULL_PAGE';
51171
+ const isConstrainedArticleMode = visualMode === 'ARTICLE_MODE' && layout === 'FULL_PAGE';
50569
51172
  useChatCompleteNotification(messages, soundSystem);
50570
51173
  return (jsxs(Fragment, { children: [feedbackStatus && (jsx("div", { className: classNames(styles$5.feedbackStatus, feedbackStatus.variant === 'success'
50571
51174
  ? styles$5.feedbackStatusSuccess
50572
- : styles$5.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsx("div", { className: classNames(className, styles$5.Chat, visual === 'STANDALONE' && styles$5.standaloneVisual, visual === 'FULL_PAGE' && styles$5.fullPageVisual, isConstrainedArticleMode && styles$5.constrainedArticleVisual, getChatCssClassName('Chat'), chatCssClassNames.chat), style, children: jsxs("div", { className: classNames(className, styles$5.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsx("div", { className: classNames(styles$5.chatChildren), children: children }), shouldShowScrollToBottom && (jsx("div", { className: styles$5.scrollToBottomContainer, children: jsxs("div", { className: styles$5.scrollToBottomWrapper, children: [jsx(SolidArrowButton, { "data-button-type": "custom", direction: "down", iconSize: 33, className: classNames(styles$5.scrollToBottom, scrollToBottomCssClassName), onClick: handleButtonClick(() => scrollToBottom()), "aria-label": ariaLabel, title: ariaLabel }), badgeLabel && (jsx("span", { className: styles$5.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsx("div", { className: styles$5.voiceCallIndicatorBar, children: jsxs("div", { className: styles$5.voiceCallIndicator, children: [jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), jsx("span", { children: "Voice call active" }), jsx("div", { className: styles$5.voiceCallPulse })] }) })), jsx(ChatActionsBar, { actionsRef: actionsRef, actionsContainer: actionsContainer, messages: postprocessedMessages, participants: participants, title: title, onReset: onReset, resetRequiresConfirmation: resetRequiresConfirmation, newChatButtonHref: newChatButtonHref, onUseTemplate: onUseTemplate, extraActions: extraActions, saveFormats: saveFormats, isSaveButtonEnabled: isSaveButtonEnabled, shouldFadeActions: shouldFadeActions, shouldDisableActions: shouldDisableActions, chatUiTranslations: chatUiTranslations, onButtonClick: handleButtonClick }), jsx(ChatMessageList, { messages: postprocessedMessages, participants: participants, expandedMessageId: expandedMessageId, messageRatings: messageRatings, setExpandedMessageId: setExpandedMessageId, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, chatLocale: chatLocale, onCopy: handleCopy, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, soundSystem: soundSystem, onToolCallClick: openToolCall, onCitationClick: openCitation, setChatMessagesElement: setChatMessagesElement, onScroll: handleChatScroll, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations, chatMessagesClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatMessages, getChatCssClassName('chatMessages'), chatCssClassNames.chatMessages), hasActions: hasActions }), onMessage && (jsx(ChatInputArea, { onMessage: onMessage, onChange: onChange, onFileUpload: onFileUpload, speechRecognition: speechRecognition, speechRecognitionLanguage: speechRecognitionLanguage, replyingToMessage: replyingToMessage, onCancelReply: onCancelReply, defaultMessage: defaultMessage, enterBehavior: enterBehavior, resolveEnterBehavior: resolveEnterBehavior, placeholderMessageContent: placeholderMessageContent || (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.inputPlaceholder), isFocusedOnLoad: isFocusedOnLoad, isMobile: isMobile, isVoiceCalling: isVoiceCalling, participants: participants, buttonColor: buttonColor, soundSystem: soundSystem, onButtonClick: handleButtonClick, chatUiTranslations: chatUiTranslations, chatInputClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatInput, getChatCssClassName('chatInput'), chatCssClassNames.chatInput) }))] }) }), jsx(ChatToolCallModal, { isOpen: toolCallModalOpen, toolCall: selectedToolCall, toolCallIdentity: selectedToolCallIdentity, onClose: closeToolCallModal, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, teamAgentProfiles: teamAgentProfiles, chatUiTranslations: chatUiTranslations, locale: chatLocale, availableTools: selectedMessageAvailableTools }), jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, soundSystem: soundSystem, onClose: closeCitationModal }), jsx(ChatRatingModal, { isOpen: ratingModalOpen, selectedMessage: selectedMessage, postprocessedMessages: postprocessedMessages, messages: messages, hoveredRating: hoveredRating, messageRatings: messageRatings, textRating: textRating, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, mode: mode, isMobile: isMobile, onClose: () => setRatingModalOpen(false), setHoveredRating: setHoveredRating, setMessageRatings: setMessageRatings, setSelectedMessage: setSelectedMessage, setTextRating: setTextRating, submitRating: submitRating })] }));
51175
+ : styles$5.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsx("div", { className: classNames(className, styles$5.Chat, layout === 'STANDALONE' && styles$5.standaloneVisual, layout === 'FULL_PAGE' && styles$5.fullPageVisual, isConstrainedArticleMode && styles$5.constrainedArticleVisual, getChatCssClassName('Chat'), chatCssClassNames.chat), "data-chat-theme": mode.toLowerCase(), style, children: jsxs("div", { className: classNames(className, styles$5.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsx("div", { className: classNames(styles$5.chatChildren), children: children }), shouldShowScrollToBottom && (jsx("div", { className: styles$5.scrollToBottomContainer, children: jsxs("div", { className: styles$5.scrollToBottomWrapper, children: [jsx(SolidArrowButton, { "data-button-type": "custom", direction: "down", iconSize: 33, className: classNames(styles$5.scrollToBottom, scrollToBottomCssClassName), onClick: handleButtonClick(() => scrollToBottom()), "aria-label": ariaLabel, title: ariaLabel }), badgeLabel && (jsx("span", { className: styles$5.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsx("div", { className: styles$5.voiceCallIndicatorBar, children: jsxs("div", { className: styles$5.voiceCallIndicator, children: [jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), jsx("span", { children: "Voice call active" }), jsx("div", { className: styles$5.voiceCallPulse })] }) })), jsx(ChatActionsBar, { actionsRef: actionsRef, actionsContainer: actionsContainer, messages: postprocessedMessages, participants: participants, title: title, onReset: onReset, resetRequiresConfirmation: resetRequiresConfirmation, newChatButtonHref: newChatButtonHref, onUseTemplate: onUseTemplate, extraActions: extraActions, saveFormats: saveFormats, isSaveButtonEnabled: isSaveButtonEnabled, shouldFadeActions: shouldFadeActions, shouldDisableActions: shouldDisableActions, chatUiTranslations: chatUiTranslations, onButtonClick: handleButtonClick }), jsx(ChatMessageList, { messages: postprocessedMessages, participants: participants, expandedMessageId: expandedMessageId, messageRatings: messageRatings, setExpandedMessageId: setExpandedMessageId, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, chatLocale: chatLocale, onCopy: handleCopy, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, soundSystem: soundSystem, onToolCallClick: openToolCall, onCitationClick: openCitation, setChatMessagesElement: setChatMessagesElement, onScroll: handleChatScroll, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations, chatMessagesClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatMessages, getChatCssClassName('chatMessages'), chatCssClassNames.chatMessages), hasActions: hasActions }), onMessage && (jsx(ChatInputArea, { onMessage: onMessage, onChange: onChange, onFileUpload: onFileUpload, speechRecognition: speechRecognition, speechRecognitionLanguage: speechRecognitionLanguage, replyingToMessage: replyingToMessage, onCancelReply: onCancelReply, defaultMessage: defaultMessage, enterBehavior: enterBehavior, resolveEnterBehavior: resolveEnterBehavior, placeholderMessageContent: placeholderMessageContent || (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.inputPlaceholder), isFocusedOnLoad: isFocusedOnLoad, isMobile: isMobile, isVoiceCalling: isVoiceCalling, participants: participants, buttonColor: buttonColor, soundSystem: soundSystem, onButtonClick: handleButtonClick, chatUiTranslations: chatUiTranslations, chatInputClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatInput, getChatCssClassName('chatInput'), chatCssClassNames.chatInput) }))] }) }), jsx(ChatToolCallModal, { isOpen: toolCallModalOpen, toolCall: selectedToolCall, toolCallIdentity: selectedToolCallIdentity, onClose: closeToolCallModal, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, teamAgentProfiles: teamAgentProfiles, chatUiTranslations: chatUiTranslations, locale: chatLocale, availableTools: selectedMessageAvailableTools, mode: mode }), jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, soundSystem: soundSystem, onClose: closeCitationModal }), jsx(ChatRatingModal, { isOpen: ratingModalOpen, selectedMessage: selectedMessage, postprocessedMessages: postprocessedMessages, messages: messages, hoveredRating: hoveredRating, messageRatings: messageRatings, textRating: textRating, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, mode: mode, isMobile: isMobile, onClose: () => setRatingModalOpen(false), setHoveredRating: setHoveredRating, setMessageRatings: setMessageRatings, setSelectedMessage: setSelectedMessage, setTextRating: setTextRating, submitRating: submitRating })] }));
50573
51176
  }
50574
51177
 
50575
51178
  /**
@@ -51875,7 +52478,7 @@ function PromptbookAgentSeamlessIntegration(props) {
51875
52478
  : styles.PromptbookAgentSeamlessIntegrationStatusPending) }), jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationText, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLabel, children: "Chat" }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationHint, children: displayName })] }), jsx("span", { className: styles.PromptbookAgentSeamlessIntegrationScreenReaderOnly, children: connectionStatusText })] }), isOpen && (jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationWindow, id: windowId, children: [jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationHeader, style: { backgroundColor: color }, ref: setHeaderElement, children: [jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationTitleWrap, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationTitle, children: displayName }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationSubtitle, children: connectionStatusText })] }), isIframeUsed && (jsx("button", { className: styles.PromptbookAgentSeamlessIntegrationClose, onClick: () => setOpen(false), title: "Close", "aria-label": "Close chat", children: jsx(CloseIcon, {}) }))] }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationContent, children: isIframeUsed ? (jsxs(Fragment, { children: [!isIframeLoaded && (jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationLoading, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingShimmer }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingSpinner }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingTitle, children: "Preparing your chat" }), jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingText, children: ["Connecting to ", displayName, "..."] })] })), jsx("iframe", { src: agentUrl + '/chat?headless', className: styles.PromptbookAgentSeamlessIntegrationIframe, style: { opacity: isIframeLoaded ? 1 : 0 }, tabIndex: -1, onLoad: () => {
51876
52479
  setIsIframeLoaded(true);
51877
52480
  setIsChatConnected(true);
51878
- } })] })) : agent ? (jsx(AgentChat, { agent: agent, actionsContainer: headerElement, isFocusedOnLoad: isFocusedOnLoad, extraActions: jsx("button", { className: styles.PromptbookAgentSeamlessIntegrationClose, onClick: () => setOpen(false), title: "Close", "aria-label": "Close chat", children: jsx(CloseIcon, {}) }), visual: "STANDALONE" })) : error ? (jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationError, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationErrorTitle, children: "Failed to connect to the agent" }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationErrorMessage, children: error.message })] })) : (jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationLoading, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingShimmer }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingSpinner }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingTitle, children: "Preparing your chat" }), jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingText, children: ["Connecting to ", displayName, "..."] })] })) })] }))] }));
52481
+ } })] })) : agent ? (jsx(AgentChat, { agent: agent, actionsContainer: headerElement, isFocusedOnLoad: isFocusedOnLoad, extraActions: jsx("button", { className: styles.PromptbookAgentSeamlessIntegrationClose, onClick: () => setOpen(false), title: "Close", "aria-label": "Close chat", children: jsx(CloseIcon, {}) }), layout: "STANDALONE" })) : error ? (jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationError, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationErrorTitle, children: "Failed to connect to the agent" }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationErrorMessage, children: error.message })] })) : (jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationLoading, children: [jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingShimmer }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingSpinner }), jsx("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingTitle, children: "Preparing your chat" }), jsxs("div", { className: styles.PromptbookAgentSeamlessIntegrationLoadingText, children: ["Connecting to ", displayName, "..."] })] })) })] }))] }));
51879
52482
  }
51880
52483
 
51881
52484
  /**