makethisbetter 1.9.2 → 1.11.0

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 (123) hide show
  1. package/README.md +49 -4
  2. package/dist/annotate/toolbar.d.ts +7 -0
  3. package/dist/annotate/toolbar.d.ts.map +1 -1
  4. package/dist/api/client.d.ts +9 -1
  5. package/dist/api/client.d.ts.map +1 -1
  6. package/dist/context/breadcrumbs.d.ts +1 -7
  7. package/dist/context/breadcrumbs.d.ts.map +1 -1
  8. package/dist/context/frustration-state.d.ts +12 -0
  9. package/dist/context/frustration-state.d.ts.map +1 -0
  10. package/dist/context/frustration-state.test.d.ts +2 -0
  11. package/dist/context/frustration-state.test.d.ts.map +1 -0
  12. package/dist/context/frustration.d.ts +5 -5
  13. package/dist/context/frustration.d.ts.map +1 -1
  14. package/dist/context/history-patch.d.ts +4 -0
  15. package/dist/context/history-patch.d.ts.map +1 -0
  16. package/dist/context/history-patch.test.d.ts +2 -0
  17. package/dist/context/history-patch.test.d.ts.map +1 -0
  18. package/dist/i18n/de.d.ts +2 -0
  19. package/dist/i18n/de.d.ts.map +1 -1
  20. package/dist/i18n/en.d.ts +2 -0
  21. package/dist/i18n/en.d.ts.map +1 -1
  22. package/dist/i18n/es.d.ts +2 -0
  23. package/dist/i18n/es.d.ts.map +1 -1
  24. package/dist/i18n/fr.d.ts +2 -0
  25. package/dist/i18n/fr.d.ts.map +1 -1
  26. package/dist/i18n/ja.d.ts +2 -0
  27. package/dist/i18n/ja.d.ts.map +1 -1
  28. package/dist/i18n/ko.d.ts +2 -0
  29. package/dist/i18n/ko.d.ts.map +1 -1
  30. package/dist/i18n/zh-CN.d.ts +2 -0
  31. package/dist/i18n/zh-CN.d.ts.map +1 -1
  32. package/dist/index.d.cts +1 -0
  33. package/dist/index.d.mts +1 -0
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/makethisbetter.cjs +52 -43
  37. package/dist/makethisbetter.cjs.map +1 -1
  38. package/dist/makethisbetter.esm.js +929 -635
  39. package/dist/makethisbetter.esm.js.map +1 -1
  40. package/dist/makethisbetter.js +52 -43
  41. package/dist/makethisbetter.js.map +1 -1
  42. package/dist/popup/clarify.d.ts +12 -1
  43. package/dist/popup/clarify.d.ts.map +1 -1
  44. package/dist/popup/comment.d.ts +1 -0
  45. package/dist/popup/comment.d.ts.map +1 -1
  46. package/dist/record/session.d.ts +6 -1
  47. package/dist/record/session.d.ts.map +1 -1
  48. package/dist/record/session.destroy-during-load.test.d.ts +2 -0
  49. package/dist/record/session.destroy-during-load.test.d.ts.map +1 -0
  50. package/dist/screenshot/capture.d.ts.map +1 -1
  51. package/dist/screenshot/crop.d.ts +19 -0
  52. package/dist/screenshot/crop.d.ts.map +1 -0
  53. package/dist/screenshot/crop.test.d.ts +2 -0
  54. package/dist/screenshot/crop.test.d.ts.map +1 -0
  55. package/dist/styles.d.ts +2 -1
  56. package/dist/styles.d.ts.map +1 -1
  57. package/dist/types.d.ts +6 -1
  58. package/dist/types.d.ts.map +1 -1
  59. package/dist/widget/controller.d.ts +1 -1
  60. package/dist/widget/controller.d.ts.map +1 -1
  61. package/dist/widget/frustration-prompt.d.ts +7 -4
  62. package/dist/widget/frustration-prompt.d.ts.map +1 -1
  63. package/dist/widget/recording-manager.d.ts +2 -1
  64. package/dist/widget/recording-manager.d.ts.map +1 -1
  65. package/dist/widget/tab.d.ts +3 -0
  66. package/dist/widget/tab.d.ts.map +1 -1
  67. package/package.json +5 -3
  68. package/src/annotate/toolbar.ts +48 -0
  69. package/src/api/client.ts +43 -3
  70. package/src/context/breadcrumbs.ts +5 -48
  71. package/src/context/frustration-state.ts +83 -0
  72. package/src/context/frustration.ts +49 -44
  73. package/src/context/history-patch.ts +86 -0
  74. package/src/i18n/de.ts +2 -0
  75. package/src/i18n/en.ts +2 -0
  76. package/src/i18n/es.ts +2 -0
  77. package/src/i18n/fr.ts +2 -0
  78. package/src/i18n/ja.ts +2 -0
  79. package/src/i18n/ko.ts +2 -0
  80. package/src/i18n/zh-CN.ts +2 -0
  81. package/src/index.ts +8 -1
  82. package/src/popup/clarify.ts +170 -52
  83. package/src/popup/comment.ts +15 -11
  84. package/src/record/session.ts +32 -2
  85. package/src/screenshot/capture.ts +73 -12
  86. package/src/screenshot/crop.ts +131 -0
  87. package/src/styles/widget.css +29 -9
  88. package/src/styles.ts +8 -1
  89. package/src/types.ts +20 -1
  90. package/src/widget/controller.ts +38 -7
  91. package/src/widget/frustration-prompt.ts +19 -2
  92. package/src/widget/recording-manager.ts +3 -1
  93. package/src/widget/tab.ts +10 -0
  94. package/src/annotate/draw-note-bar.test.ts +0 -90
  95. package/src/annotate/draw.test.ts +0 -158
  96. package/src/annotate/highlighter.test.ts +0 -70
  97. package/src/annotate/overlay.test.ts +0 -91
  98. package/src/annotate/pin.test.ts +0 -83
  99. package/src/annotate/session.test.ts +0 -344
  100. package/src/annotate/toolbar.test.ts +0 -132
  101. package/src/api/client.test.ts +0 -285
  102. package/src/context/breadcrumbs.test.ts +0 -154
  103. package/src/context/collector.test.ts +0 -14
  104. package/src/context/console.test.ts +0 -44
  105. package/src/context/error-source.test.ts +0 -128
  106. package/src/context/frustration.test.ts +0 -485
  107. package/src/i18n/index.test.ts +0 -36
  108. package/src/popup/clarify.test.ts +0 -725
  109. package/src/popup/comment.test.ts +0 -168
  110. package/src/popup/success.test.ts +0 -190
  111. package/src/record/control-bar.test.ts +0 -110
  112. package/src/record/session.cdn.test.ts +0 -89
  113. package/src/record/session.test.ts +0 -160
  114. package/src/screenshot/capture.test.ts +0 -98
  115. package/src/widget/anon-id.test.ts +0 -42
  116. package/src/widget/controller.test.ts +0 -1054
  117. package/src/widget/dim-overlay.test.ts +0 -27
  118. package/src/widget/frustration-prompt.test.ts +0 -86
  119. package/src/widget/payload.test.ts +0 -222
  120. package/src/widget/pet.test.ts +0 -65
  121. package/src/widget/recording-manager.test.ts +0 -136
  122. package/src/widget/shadow.test.ts +0 -44
  123. package/src/widget/tab.test.ts +0 -107
@@ -1,9 +1,9 @@
1
- const vt = '*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}:host{all:initial;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;font-size:14px;line-height:1.5;color:#191a1c;-webkit-font-smoothing:antialiased}:host([data-mtb-theme="dark"]) .mtb-popup,:host([data-mtb-theme="dark"]) .mtb-success{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-popup-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="dark"]) .mtb-popup-title,:host([data-mtb-theme="dark"]) .mtb-success-title{color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-quick-option,:host([data-mtb-theme="dark"]) .mtb-textarea{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-popup-close,:host([data-mtb-theme="dark"]) .mtb-success-msg,:host([data-mtb-theme="dark"]) .mtb-close-link{color:#ffffffad}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-popup,:host([data-mtb-theme="auto"]) .mtb-success{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-popup-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="auto"]) .mtb-popup-title,:host([data-mtb-theme="auto"]) .mtb-success-title{color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-quick-option,:host([data-mtb-theme="auto"]) .mtb-textarea{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-popup-close,:host([data-mtb-theme="auto"]) .mtb-success-msg,:host([data-mtb-theme="auto"]) .mtb-close-link{color:#ffffffad}}.mtb-tab{position:fixed;top:50%;right:0;transform:translateY(-50%);z-index:2147483646;display:flex;align-items:center;justify-content:center;width:32px;padding:14px 0;background:#059669;color:#fff;border-radius:8px 0 0 8px;cursor:pointer;box-shadow:-2px 0 14px #05966959;transition:background .15s,box-shadow .15s,width .15s;writing-mode:vertical-lr;text-orientation:mixed;font-size:12px;font-weight:600;letter-spacing:.04em;user-select:none;border:none;outline:none}.mtb-tab.left{right:auto;left:0;border-radius:0 8px 8px 0;box-shadow:2px 0 14px #05966959}.mtb-tab:hover{background:#047857;box-shadow:-3px 0 20px #05966973}.mtb-tab.active{background:#065f46}.mtb-toolbar{position:fixed;top:18px;left:50%;transform:translate(-50%);z-index:2147483647;display:flex;align-items:center;gap:11px;height:46px;padding:0 7px;border-radius:13px;background:linear-gradient(120deg,#10b981,#059669);box-shadow:0 10px 26px #0f172a38;animation:mtbBarIn .2s ease;white-space:nowrap}@keyframes mtbBarIn{0%{transform:translate(-50%,12px);opacity:0}to{transform:translate(-50%);opacity:1}}.mtb-toolbar-modes{display:flex;align-items:center;gap:3px;background:#ffffff29;border-radius:9px;padding:3px}.mtb-toolbar-mode-btn{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:7px;border:none;cursor:pointer;font-family:inherit;font-size:12px;font-weight:550;white-space:nowrap;background:transparent;color:#fffffff2;transition:all .12s}.mtb-toolbar-mode-btn.active{background:#fff;color:#047857}.mtb-toolbar-hint{font-size:12px;color:#fffffff2;white-space:nowrap}.mtb-toolbar-sep{width:1px;height:20px;background:#ffffff38}.mtb-exit-btn{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 12px;border-radius:8px;font-size:11.5px;font-weight:500;color:#fff;cursor:pointer;background:#ffffff29;border:none;font-family:inherit;transition:background .12s}.mtb-exit-btn:hover{background:#ffffff47}@media (max-width: 480px){.mtb-toolbar{max-width:calc(100vw - 16px);gap:6px}.mtb-toolbar-hint,.mtb-toolbar-sep{display:none}.mtb-toolbar-mode-btn,.mtb-exit-btn{padding-right:10px;padding-left:10px}}.mtb-overlay{position:fixed;inset:0;z-index:2147483640;cursor:crosshair}.mtb-dim{position:fixed;inset:0;z-index:2147483639;background:#00000014}.mtb-highlight{position:fixed;z-index:2147483641;pointer-events:none;border:2px solid #10b981;border-radius:6px;background:#10b9810f;transition:all .08s ease}.mtb-highlight.selected{border-color:#3b82f6;background:#3b82f60a}.mtb-highlight-tooltip{position:fixed;z-index:2147483642;pointer-events:none;transform:translate(-50%,-100%);max-width:240px;overflow:hidden;text-overflow:ellipsis;background:#064e3b;color:#fff;padding:4px 10px;border-radius:6px;font-size:11px;font-weight:500;white-space:nowrap;box-shadow:0 4px 12px #0000002e;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.mtb-highlight-tooltip.below{transform:translate(-50%)}.mtb-highlight-tooltip:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:4px solid transparent;border-top-color:#064e3b}.mtb-highlight-tooltip.below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#064e3b}.mtb-draw-svg{position:fixed;inset:0;z-index:2147483643;pointer-events:none;width:100%;height:100%;overflow:visible}.mtb-pin{position:fixed;z-index:2147483644;pointer-events:none;width:22px;height:22px;border-radius:50% 50% 50% 2px;background:#059669;border:2px solid #fff;display:flex;align-items:center;justify-content:center;font-size:10px;color:#fff;font-weight:700;box-shadow:0 2px 8px #05966973;animation:mtbPinPop .25s cubic-bezier(.34,1.56,.64,1);transform:translate(-50%,-50%)}@keyframes mtbPinPop{0%{transform:translate(-50%,-50%) scale(.4)}to{transform:translate(-50%,-50%) scale(1)}}.mtb-popup{position:fixed;z-index:2147483645;display:flex;flex-direction:column;width:min(320px,calc(100vw - 56px));background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;box-shadow:0 24px 64px #0000003d;overflow:hidden;animation:mtbSlideUp .28s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}@keyframes mtbSlideUp{0%{transform:translateY(14px) scale(.97);opacity:0}to{transform:translateY(0) scale(1);opacity:1}}.mtb-popup-header{flex-shrink:0;padding:11px 13px 11px 14px;border-bottom:1px solid rgba(0,0,0,.06);display:flex;align-items:center;gap:8px}.mtb-popup-icon{width:20px;height:20px;border-radius:5px;background:#10b9811a;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mtb-popup-title{flex:1;font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#191a1c}.mtb-popup-close{background:none;border:none;cursor:pointer;padding:3px;color:#00000061;display:flex;align-items:center;border-radius:4px;transition:color .12s}.mtb-popup-close:hover{color:#000000b3}.mtb-popup-body{min-height:0;padding:13px;overflow-y:auto;overscroll-behavior:contain}.mtb-quick-options{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.mtb-quick-option{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:1px solid rgba(0,0,0,.09);border-radius:10px;background:#fafafa;cursor:pointer;font-family:inherit;font-size:13px;color:#191a1c;text-align:left;transition:all .12s}.mtb-quick-option:hover{background:#10b9810f;border-color:#10b9814d}.mtb-quick-option-emoji{font-size:15px;flex-shrink:0;line-height:1}.mtb-textarea-wrap{position:relative}.mtb-textarea{width:100%;height:64px;padding:9px 11px;border:1px solid rgba(0,0,0,.12);border-radius:10px;font-family:inherit;font-size:12.5px;line-height:1.5;color:#191a1c;outline:none;background:#fff;resize:none;transition:border-color .12s,box-shadow .12s}.mtb-textarea:focus{border-color:#10b981;box-shadow:0 0 0 3px #10b98126}.mtb-textarea::placeholder{color:#00000057}.mtb-popup-error{margin-top:8px;color:#dc2626;font-size:11.5px}.mtb-popup-error:empty,.mtb-popup-error[hidden]{display:none}.mtb-popup-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:12px}.mtb-cancel-btn,.mtb-submit-btn{min-width:72px;height:32px;border:none;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0 12px;font-family:inherit;font-size:12.5px;font-weight:600;transition:background .12s}.mtb-cancel-btn{background:#f3f4f6;color:#000000ad}.mtb-cancel-btn:hover{background:#e5e7eb}.mtb-submit-btn{background:#d1d5db;color:#fff}.mtb-submit-btn.ready{background:#059669}.mtb-submit-btn.ready:hover{background:#047857}.mtb-submit-btn.loading{background:#059669;opacity:.7;cursor:wait}.mtb-submit-btn:disabled{cursor:not-allowed}.mtb-success{position:fixed;z-index:2147483645;width:332px;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;box-shadow:0 24px 64px #0000003d;padding:24px 22px;text-align:center;animation:mtbSlideUp .35s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.mtb-success-icon{width:46px;height:46px;border-radius:50%;background:#05966917;display:flex;align-items:center;justify-content:center;margin:0 auto 12px}.mtb-success-title{font-size:16px;font-weight:700;margin-bottom:5px;letter-spacing:-.01em;color:#191a1c}.mtb-success-msg{font-size:13px;color:#0000008c;margin-bottom:16px;line-height:1.6}.mtb-view-feedback-link{display:inline-flex;align-items:center;gap:5px;color:#047857;text-decoration:none;font-size:13px;font-weight:500;font-family:JetBrains Mono,monospace;background:none;border:none;cursor:pointer;transition:text-decoration .12s}.mtb-view-feedback-link:hover{text-decoration:underline}.mtb-close-link{margin-top:13px;background:none;border:none;cursor:pointer;font-size:12px;color:#0006;font-family:inherit;transition:color .12s}.mtb-close-link:hover{color:#000000b3}.mtb-email-capture{margin-bottom:14px;text-align:left}.mtb-email-prompt{font-size:12px;color:#0000008c;line-height:1.5;margin-bottom:8px}.mtb-email-row{display:flex;gap:6px}.mtb-email-input{flex:1;min-width:0;font-size:12.5px;font-family:inherit;padding:7px 10px;border:1px solid rgba(0,0,0,.14);border-radius:8px;outline:none}.mtb-email-input:focus{border-color:#059669}.mtb-email-input.mtb-email-invalid{border-color:#dc2626}.mtb-email-submit{font-size:12px;font-weight:600;font-family:inherit;color:#fff;background:#059669;border:none;border-radius:8px;padding:7px 12px;cursor:pointer;white-space:nowrap}.mtb-email-submit:disabled{opacity:.6;cursor:default}.mtb-email-error{font-size:11.5px;color:#dc2626;margin-top:6px}.mtb-email-saved{font-size:12px;color:#059669;line-height:1.5}.mtb-my-feedback{display:block;margin:8px auto 0;background:none;border:none;cursor:pointer;font-size:11.5px;font-family:inherit;color:#0006;text-decoration:underline;text-underline-offset:2px;transition:color .12s}.mtb-my-feedback:hover{color:#059669}.mtb-pet{position:fixed;bottom:20px;right:20px;z-index:2147483646;cursor:pointer;width:52px;height:52px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:transparent;animation:mtbPetBounce 3s ease-in-out infinite;transition:transform .2s;user-select:none;outline:none;filter:drop-shadow(0 4px 12px rgba(5,150,105,.35))}.mtb-pet:hover{transform:scale(1.12);animation-play-state:paused}.mtb-pet:hover .mtb-pet-bubble{opacity:1;transform:translate(-50%) translateY(0);pointer-events:auto}.mtb-pet.active{animation:none;opacity:.6}.mtb-pet-svg{display:block}@keyframes mtbPetBounce{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.mtb-pet-bubble{position:absolute;bottom:100%;left:50%;transform:translate(-50%) translateY(4px);margin-bottom:8px;background:#064e3b;color:#fff;padding:6px 12px;border-radius:8px;font-size:12px;font-weight:500;white-space:nowrap;box-shadow:0 4px 14px #0000002e;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s}.mtb-pet-bubble.visible{opacity:1;transform:translate(-50%) translateY(0);pointer-events:auto}.mtb-pet-bubble.hidden{opacity:0;pointer-events:none}.mtb-pet-bubble:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:5px solid transparent;border-top-color:#064e3b}.mtb-frustration-prompt{position:fixed;bottom:20px;right:20px;z-index:2147483645;display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:12px;box-shadow:0 8px 30px #0000001f;animation:mtbSlideUp .35s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}:host([data-mtb-theme="dark"]) .mtb-frustration-prompt{background:#151719;border-color:#ffffff1f;color:#f9fafb}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-frustration-prompt{background:#151719;border-color:#ffffff1f;color:#f9fafb}}.mtb-frustration-icon{width:32px;height:32px;border-radius:50%;background:#eab3081a;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;line-height:1}.mtb-frustration-text{font-size:13px;font-weight:500;color:inherit;line-height:1.4}.mtb-frustration-actions{display:flex;gap:6px;flex-shrink:0}.mtb-frustration-tell{height:28px;padding:0 12px;border:none;border-radius:7px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;transition:background .12s}.mtb-frustration-tell:hover{background:#047857}.mtb-frustration-dismiss{height:28px;padding:0 8px;border:none;border-radius:7px;background:transparent;color:#0006;cursor:pointer;font-family:inherit;font-size:12px;transition:color .12s}.mtb-frustration-dismiss:hover{color:#000000b3}:host([data-mtb-theme="dark"]) .mtb-frustration-dismiss{color:#fff6}:host([data-mtb-theme="dark"]) .mtb-frustration-dismiss:hover{color:#ffffffb3}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-frustration-dismiss{color:#fff6}:host([data-mtb-theme="auto"]) .mtb-frustration-dismiss:hover{color:#ffffffb3}}.mtb-record-bar{position:fixed;bottom:48px;left:50%;transform:translate(-50%);z-index:2147483647;display:flex;align-items:center;gap:12px;height:42px;padding:0 8px 0 14px;border-radius:12px;background:#0f172aeb;box-shadow:0 8px 24px #00000040;animation:mtbBarIn .2s ease}.mtb-record-dot{width:8px;height:8px;border-radius:50%;background:#ef4444;animation:mtbRecordPulse 1.2s ease-in-out infinite;flex-shrink:0}@keyframes mtbRecordPulse{0%,to{opacity:1}50%{opacity:.3}}.mtb-record-timer{font-family:JetBrains Mono,SF Mono,Fira Code,Cascadia Code,monospace;font-size:13px;font-weight:500;color:#fff;font-variant-numeric:tabular-nums;letter-spacing:.02em;min-width:38px}.mtb-record-stop{height:28px;padding:0 14px;border:none;border-radius:7px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;transition:background .12s}.mtb-record-stop:hover{background:#047857}.mtb-click-ripple{position:fixed;z-index:2147483644;width:24px;height:24px;border-radius:50%;border:2px solid #10b981;background:#10b98133;pointer-events:none;transform:translate(-50%,-50%) scale(.5);animation:mtbClickRipple .3s ease-out forwards}@keyframes mtbClickRipple{0%{transform:translate(-50%,-50%) scale(.5);opacity:1}to{transform:translate(-50%,-50%) scale(2);opacity:0}}.mtb-dot{display:inline-block;width:4px;height:4px;border-radius:50%;background:#fff;animation:mtbDot 1.2s infinite}.mtb-dot:nth-child(2){animation-delay:.2s}.mtb-dot:nth-child(3){animation-delay:.4s}@keyframes mtbDot{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}.mtb-clarify{position:fixed;z-index:2147483645;width:min(346px,calc(100vw - 56px));background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;box-shadow:0 24px 64px #0000003d;display:flex;flex-direction:column;animation:mtbSlideUp .28s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;overflow:hidden}.mtb-clarify-continuation{width:min(320px,calc(100vw - 56px));animation:none}.mtb-clarify-header{padding:8px 10px;display:flex;align-items:center;gap:7px;border-bottom:1px solid rgba(0,0,0,.06)}.mtb-clarify-icon{width:20px;height:20px;border-radius:6px;background:linear-gradient(140deg,#10b981,#059669);box-shadow:0 1px 3px #05966966;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mtb-clarify-titles{flex:1;min-width:0}.mtb-clarify-title{font-size:12px;font-weight:650;line-height:1.2;color:#191a1c}.mtb-clarify-subtitle{font-size:9.5px;color:#0000006b}.mtb-clarify-close{background:none;border:none;cursor:pointer;padding:3px;color:#00000061;display:flex;transition:color .12s}.mtb-clarify-close:hover{color:#000000b3}.mtb-clarify-messages{flex:1;overflow-y:auto;padding:8px 10px 4px;display:flex;flex-direction:column;gap:6px}.mtb-clarify-bubble{max-width:82%;padding:6px 10px;font-size:12px;line-height:1.4;white-space:pre-wrap;word-break:break-word}.mtb-clarify-ai{align-self:flex-start;background:#fff;color:#191a1c;border:1px solid rgba(0,0,0,.09);border-radius:11px 11px 11px 3px}.mtb-clarify-user{align-self:flex-end;background:#059669;color:#fff;border:1px solid #059669;border-radius:11px 11px 3px}.mtb-clarify-thinking{display:flex;align-items:center;gap:4px;padding:8px 12px}.mtb-clarify-thinking .mtb-dot{width:6px;height:6px;background:#059669b3}.mtb-clarify-footer{padding:3px 10px 10px;display:flex;flex-direction:column}.mtb-clarify-input{width:100%;height:40px;padding:7px 10px;border:1px solid rgba(0,0,0,.12);border-radius:8px;font-family:inherit;font-size:12px;line-height:1.4;color:#191a1c;outline:none;background:#fafafa;resize:none;box-sizing:border-box;transition:border-color .12s,box-shadow .12s,background .12s}.mtb-clarify-input:focus{border-color:#10b981;box-shadow:0 0 0 3px #10b98126;background:#fff}.mtb-clarify-input::placeholder{color:#00000057}.mtb-clarify-actions{display:flex;gap:6px;margin-top:6px}.mtb-clarify-skip{flex:0 0 auto;height:30px;padding:0 12px;border:1px solid rgba(0,0,0,.12);border-radius:8px;background:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:550;color:#0000008c;white-space:nowrap;transition:background .12s}.mtb-clarify-skip:hover{background:#0000000a}.mtb-clarify-send{flex:1;height:30px;display:inline-flex;align-items:center;justify-content:center;gap:5px;border:none;border-radius:8px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;transition:background .12s}.mtb-clarify-send:not(:disabled):hover{background:#047857}.mtb-clarify-send:disabled{background:#00000026;cursor:not-allowed}.mtb-clarify-send-feedback{width:100%;height:34px;display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:9px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:600;transition:background .12s}.mtb-clarify-send-feedback:not(:disabled):hover{background:#047857}.mtb-clarify-send-feedback:disabled{background:#00000026;cursor:not-allowed}.mtb-clarify-error{margin-bottom:8px;color:#dc2626;font-size:11.5px;line-height:1.4;text-align:center}:host([data-mtb-theme="dark"]) .mtb-clarify{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-clarify-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="dark"]) .mtb-clarify-title{color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-clarify-subtitle{color:#ffffff73}:host([data-mtb-theme="dark"]) .mtb-clarify-close{color:#ffffff73}:host([data-mtb-theme="dark"]) .mtb-clarify-close:hover{color:#ffffffbf}:host([data-mtb-theme="dark"]) .mtb-clarify-skip{background:#1f2327;border-color:#ffffff24;color:#ffffffb3}:host([data-mtb-theme="dark"]) .mtb-clarify-skip:hover{background:#ffffff0f}:host([data-mtb-theme="dark"]) .mtb-clarify-ai{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-clarify-input{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-clarify{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-clarify-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="auto"]) .mtb-clarify-title{color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-clarify-subtitle{color:#ffffff73}:host([data-mtb-theme="auto"]) .mtb-clarify-close{color:#ffffff73}:host([data-mtb-theme="auto"]) .mtb-clarify-close:hover{color:#ffffffbf}:host([data-mtb-theme="auto"]) .mtb-clarify-skip{background:#1f2327;border-color:#ffffff24;color:#ffffffb3}:host([data-mtb-theme="auto"]) .mtb-clarify-skip:hover{background:#ffffff0f}:host([data-mtb-theme="auto"]) .mtb-clarify-ai{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-clarify-input{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}}.mtb-dim-clickable{z-index:2147483643;pointer-events:auto;cursor:default;background:#0000001f}.mtb-draw-bar{position:fixed;bottom:48px;left:50%;transform:translate(-50%);z-index:2147483647;display:flex;align-items:center;gap:8px;height:46px;padding:0 8px 0 12px;border-radius:13px;background:#fff;border:1px solid rgba(0,0,0,.08);box-shadow:0 10px 30px #0f172a38;animation:mtbBarIn .2s ease;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.mtb-draw-input{width:220px;height:32px;padding:0 10px;border:1px solid rgba(0,0,0,.12);border-radius:8px;font-family:inherit;font-size:13px;color:#191a1c;outline:none;background:#fafafa;transition:border-color .12s,box-shadow .12s,background .12s}.mtb-draw-input:focus{border-color:#10b981;box-shadow:0 0 0 3px #10b98126;background:#fff}.mtb-draw-input::placeholder{color:#00000057}.mtb-draw-icon-btn{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:8px;background:transparent;color:#374151;cursor:pointer;transition:background .12s,color .12s}.mtb-draw-icon-btn:hover:not(:disabled){background:#0000000f}.mtb-draw-icon-btn:disabled{color:#00000038;cursor:default}.mtb-draw-sep{width:1px;height:22px;background:#0000001a}.mtb-draw-cancel{height:32px;padding:0 12px;border:1px solid rgba(0,0,0,.12);border-radius:8px;background:#fff;color:#0000008c;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:550;transition:background .12s}.mtb-draw-cancel:hover{background:#0000000a}.mtb-draw-submit{height:32px;padding:0 14px;border:none;border-radius:8px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:600;transition:background .12s}.mtb-draw-submit:hover:not(:disabled){background:#047857}.mtb-draw-submit:disabled{opacity:.6;cursor:default}.mtb-draw-error{position:absolute;bottom:100%;left:12px;margin-bottom:6px;color:#dc2626;font-size:11.5px}.mtb-record-preview{margin-bottom:12px}.mtb-record-preview-stage{position:relative;width:100%;height:132px;border-radius:10px;overflow:hidden;background:#0f172a;display:flex;align-items:center;justify-content:center}.mtb-record-preview-stage.playing{align-items:flex-start;justify-content:flex-start}.mtb-record-preview-play{width:44px;height:44px;border-radius:50%;border:none;background:#ffffffeb;color:#059669;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .12s,background .12s}.mtb-record-preview-play:hover:not(:disabled){transform:scale(1.06);background:#fff}.mtb-record-preview-play:disabled{cursor:default;opacity:.6}.mtb-record-preview-badge{position:absolute;right:8px;bottom:8px;padding:2px 7px;border-radius:6px;background:#0009;color:#fff;font-size:11px;font-variant-numeric:tabular-nums;font-family:JetBrains Mono,SF Mono,monospace}.mtb-record-preview-fallback{color:#ffffffd9;font-size:12px}.mtb-record-preview-name{display:block;margin-top:5px;font-size:11px;color:#0000006b}';
2
- class kt {
1
+ const Wt = '*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}:host{all:initial;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;font-size:14px;line-height:1.5;color:#191a1c;-webkit-font-smoothing:antialiased}:host([data-mtb-theme="dark"]) .mtb-popup,:host([data-mtb-theme="dark"]) .mtb-success{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-popup-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="dark"]) .mtb-popup-title,:host([data-mtb-theme="dark"]) .mtb-success-title{color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-quick-option,:host([data-mtb-theme="dark"]) .mtb-textarea{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-popup-close,:host([data-mtb-theme="dark"]) .mtb-success-msg,:host([data-mtb-theme="dark"]) .mtb-close-link{color:#ffffffad}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-popup,:host([data-mtb-theme="auto"]) .mtb-success{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-popup-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="auto"]) .mtb-popup-title,:host([data-mtb-theme="auto"]) .mtb-success-title{color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-quick-option,:host([data-mtb-theme="auto"]) .mtb-textarea{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-popup-close,:host([data-mtb-theme="auto"]) .mtb-success-msg,:host([data-mtb-theme="auto"]) .mtb-close-link{color:#ffffffad}}.mtb-tab{position:fixed;top:50%;right:0;transform:translateY(-50%);z-index:2147483646;display:flex;align-items:center;justify-content:center;width:32px;padding:14px 0;background:#059669;color:#fff;border-radius:8px 0 0 8px;cursor:pointer;box-shadow:-2px 0 14px #05966959;transition:background .15s,box-shadow .15s,width .15s;writing-mode:vertical-lr;text-orientation:mixed;font-size:12px;font-weight:600;letter-spacing:.04em;user-select:none;border:none;outline:none}.mtb-tab.left{right:auto;left:0;border-radius:0 8px 8px 0;box-shadow:2px 0 14px #05966959}.mtb-tab:hover{background:#047857;box-shadow:-3px 0 20px #05966973}.mtb-tab.active{background:#065f46}.mtb-toolbar{position:fixed;top:18px;left:50%;transform:translate(-50%);z-index:2147483647;display:flex;align-items:center;gap:11px;height:46px;padding:0 7px;border-radius:13px;background:linear-gradient(120deg,#10b981,#059669);box-shadow:0 10px 26px #0f172a38;animation:mtbBarIn .2s ease;white-space:nowrap;transition:opacity .15s ease}@keyframes mtbBarIn{0%{transform:translate(-50%,12px);opacity:0}to{transform:translate(-50%);opacity:1}}.mtb-toolbar-faded{opacity:.3;pointer-events:none}.mtb-toolbar-modes{display:flex;align-items:center;gap:3px;background:#ffffff29;border-radius:9px;padding:3px}.mtb-toolbar-mode-btn{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:7px;border:none;cursor:pointer;font-family:inherit;font-size:12px;font-weight:550;white-space:nowrap;background:transparent;color:#fffffff2;transition:all .12s}.mtb-toolbar-mode-btn.active{background:#fff;color:#047857}.mtb-toolbar-hint{font-size:12px;color:#fffffff2;white-space:nowrap}.mtb-toolbar-sep{width:1px;height:20px;background:#ffffff38}.mtb-exit-btn{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 12px;border-radius:8px;font-size:11.5px;font-weight:500;color:#fff;cursor:pointer;background:#ffffff29;border:none;font-family:inherit;transition:background .12s}.mtb-exit-btn:hover{background:#ffffff47}@media (max-width: 480px){.mtb-toolbar{max-width:calc(100vw - 16px);gap:6px}.mtb-toolbar-hint,.mtb-toolbar-sep{display:none}.mtb-toolbar-mode-btn,.mtb-exit-btn{padding-right:10px;padding-left:10px}}.mtb-overlay{position:fixed;inset:0;z-index:2147483640;cursor:crosshair}.mtb-dim{position:fixed;inset:0;z-index:2147483639;background:#00000014}.mtb-highlight{position:fixed;z-index:2147483641;pointer-events:none;border:2px solid #10b981;border-radius:6px;background:#10b9810f;transition:all .08s ease}.mtb-highlight.selected{border-color:#3b82f6;background:#3b82f60a}.mtb-highlight-tooltip{position:fixed;z-index:2147483642;pointer-events:none;transform:translate(-50%,-100%);max-width:240px;overflow:hidden;text-overflow:ellipsis;background:#064e3b;color:#fff;padding:4px 10px;border-radius:6px;font-size:11px;font-weight:500;white-space:nowrap;box-shadow:0 4px 12px #0000002e;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.mtb-highlight-tooltip.below{transform:translate(-50%)}.mtb-highlight-tooltip:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:4px solid transparent;border-top-color:#064e3b}.mtb-highlight-tooltip.below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#064e3b}.mtb-draw-svg{position:fixed;inset:0;z-index:2147483643;pointer-events:none;width:100%;height:100%;overflow:visible}.mtb-pin{position:fixed;z-index:2147483644;pointer-events:none;width:22px;height:22px;border-radius:50% 50% 50% 2px;background:#059669;border:2px solid #fff;display:flex;align-items:center;justify-content:center;font-size:10px;color:#fff;font-weight:700;box-shadow:0 2px 8px #05966973;animation:mtbPinPop .25s cubic-bezier(.34,1.56,.64,1);transform:translate(-50%,-50%)}@keyframes mtbPinPop{0%{transform:translate(-50%,-50%) scale(.4)}to{transform:translate(-50%,-50%) scale(1)}}.mtb-popup{position:fixed;z-index:2147483645;display:flex;flex-direction:column;width:min(320px,calc(100vw - 56px));background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;box-shadow:0 24px 64px #0000003d;overflow:hidden;animation:mtbSlideUp .28s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}@keyframes mtbSlideUp{0%{transform:translateY(14px) scale(.97);opacity:0}to{transform:translateY(0) scale(1);opacity:1}}.mtb-popup-header{flex-shrink:0;padding:11px 13px 11px 14px;border-bottom:1px solid rgba(0,0,0,.06);display:flex;align-items:center;gap:8px}.mtb-popup-icon{width:20px;height:20px;border-radius:5px;background:#10b9811a;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mtb-popup-title{flex:1;font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#191a1c}.mtb-popup-close{background:none;border:none;cursor:pointer;padding:3px;color:#00000061;display:flex;align-items:center;border-radius:4px;transition:color .12s}.mtb-popup-close:hover{color:#000000b3}.mtb-popup-body{min-height:0;padding:13px;overflow-y:auto;overscroll-behavior:contain}.mtb-quick-options{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.mtb-quick-option{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:1px solid rgba(0,0,0,.09);border-radius:10px;background:#fafafa;cursor:pointer;font-family:inherit;font-size:13px;color:#191a1c;text-align:left;transition:all .12s}.mtb-quick-option:hover{background:#10b9810f;border-color:#10b9814d}.mtb-quick-option.selected{background:#10b9811a;border-color:#10b98180}.mtb-quick-option-emoji{font-size:15px;flex-shrink:0;line-height:1}.mtb-textarea-wrap{position:relative}.mtb-textarea{width:100%;height:64px;padding:9px 11px;border:1px solid rgba(0,0,0,.12);border-radius:10px;font-family:inherit;font-size:12.5px;line-height:1.5;color:#191a1c;outline:none;background:#fff;resize:none;transition:border-color .12s,box-shadow .12s}.mtb-textarea:focus{border-color:#10b981;box-shadow:0 0 0 3px #10b98126}.mtb-textarea::placeholder{color:#00000057}.mtb-popup-error{margin-top:8px;color:#dc2626;font-size:11.5px}.mtb-popup-error:empty,.mtb-popup-error[hidden]{display:none}.mtb-popup-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:12px}.mtb-cancel-btn,.mtb-submit-btn{min-width:72px;height:32px;border:none;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0 12px;font-family:inherit;font-size:12.5px;font-weight:600;transition:background .12s}.mtb-cancel-btn{background:#f3f4f6;color:#000000ad}.mtb-cancel-btn:hover{background:#e5e7eb}.mtb-submit-btn{background:#d1d5db;color:#fff}.mtb-submit-btn.ready{background:#059669}.mtb-submit-btn.ready:hover{background:#047857}.mtb-submit-btn.loading{background:#059669;opacity:.7;cursor:wait}.mtb-submit-btn:disabled{cursor:not-allowed}.mtb-success{position:fixed;z-index:2147483645;width:332px;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;box-shadow:0 24px 64px #0000003d;padding:24px 22px;text-align:center;animation:mtbSlideUp .35s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.mtb-success-icon{width:46px;height:46px;border-radius:50%;background:#05966917;display:flex;align-items:center;justify-content:center;margin:0 auto 12px}.mtb-success-title{font-size:16px;font-weight:700;margin-bottom:5px;letter-spacing:-.01em;color:#191a1c}.mtb-success-msg{font-size:13px;color:#0000008c;margin-bottom:16px;line-height:1.6}.mtb-view-feedback-link{display:inline-flex;align-items:center;gap:5px;color:#047857;text-decoration:none;font-size:13px;font-weight:500;font-family:JetBrains Mono,monospace;background:none;border:none;cursor:pointer;transition:text-decoration .12s}.mtb-view-feedback-link:hover{text-decoration:underline}.mtb-close-link{margin-top:13px;background:none;border:none;cursor:pointer;font-size:12px;color:#0006;font-family:inherit;transition:color .12s}.mtb-close-link:hover{color:#000000b3}.mtb-email-capture{margin-bottom:14px;text-align:left}.mtb-email-prompt{font-size:12px;color:#0000008c;line-height:1.5;margin-bottom:8px}.mtb-email-row{display:flex;gap:6px}.mtb-email-input{flex:1;min-width:0;font-size:12.5px;font-family:inherit;padding:7px 10px;border:1px solid rgba(0,0,0,.14);border-radius:8px;outline:none}.mtb-email-input:focus{border-color:#059669}.mtb-email-input.mtb-email-invalid{border-color:#dc2626}.mtb-email-submit{font-size:12px;font-weight:600;font-family:inherit;color:#fff;background:#059669;border:none;border-radius:8px;padding:7px 12px;cursor:pointer;white-space:nowrap}.mtb-email-submit:disabled{opacity:.6;cursor:default}.mtb-email-error{font-size:11.5px;color:#dc2626;margin-top:6px}.mtb-email-saved{font-size:12px;color:#059669;line-height:1.5}.mtb-my-feedback{display:block;margin:8px auto 0;background:none;border:none;cursor:pointer;font-size:11.5px;font-family:inherit;color:#0006;text-decoration:underline;text-underline-offset:2px;transition:color .12s}.mtb-my-feedback:hover{color:#059669}.mtb-pet{position:fixed;bottom:20px;right:20px;z-index:2147483646;cursor:pointer;width:52px;height:52px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:transparent;animation:mtbPetBounce 3s ease-in-out infinite;transition:transform .2s;user-select:none;outline:none;filter:drop-shadow(0 4px 12px rgba(5,150,105,.35))}.mtb-pet:hover{transform:scale(1.12);animation-play-state:paused}.mtb-pet:hover .mtb-pet-bubble{opacity:1;transform:translate(-50%) translateY(0);pointer-events:auto}.mtb-pet.active{animation:none;opacity:.6}.mtb-pet-svg{display:block}@keyframes mtbPetBounce{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.mtb-pet-bubble{position:absolute;bottom:100%;left:50%;transform:translate(-50%) translateY(4px);margin-bottom:8px;background:#064e3b;color:#fff;padding:6px 12px;border-radius:8px;font-size:12px;font-weight:500;white-space:nowrap;box-shadow:0 4px 14px #0000002e;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s}.mtb-pet-bubble.visible{opacity:1;transform:translate(-50%) translateY(0);pointer-events:auto}.mtb-pet-bubble.hidden{opacity:0;pointer-events:none}.mtb-pet-bubble:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:5px solid transparent;border-top-color:#064e3b}.mtb-frustration-prompt{position:fixed;bottom:20px;right:20px;z-index:2147483645;display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:12px;box-shadow:0 8px 30px #0000001f;animation:mtbSlideUp .35s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}:host([data-mtb-theme="dark"]) .mtb-frustration-prompt{background:#151719;border-color:#ffffff1f;color:#f9fafb}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-frustration-prompt{background:#151719;border-color:#ffffff1f;color:#f9fafb}}.mtb-frustration-icon{width:32px;height:32px;border-radius:50%;background:#eab3081a;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;line-height:1}.mtb-frustration-text{font-size:13px;font-weight:500;color:inherit;line-height:1.4}.mtb-frustration-actions{display:flex;gap:6px;flex-shrink:0}.mtb-frustration-tell{height:28px;padding:0 12px;border:none;border-radius:7px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;transition:background .12s}.mtb-frustration-tell:hover{background:#047857}.mtb-frustration-dismiss{height:28px;padding:0 8px;border:none;border-radius:7px;background:transparent;color:#0006;cursor:pointer;font-family:inherit;font-size:12px;transition:color .12s}.mtb-frustration-dismiss:hover{color:#000000b3}:host([data-mtb-theme="dark"]) .mtb-frustration-dismiss{color:#fff6}:host([data-mtb-theme="dark"]) .mtb-frustration-dismiss:hover{color:#ffffffb3}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-frustration-dismiss{color:#fff6}:host([data-mtb-theme="auto"]) .mtb-frustration-dismiss:hover{color:#ffffffb3}}.mtb-record-bar{position:fixed;bottom:48px;left:50%;transform:translate(-50%);z-index:2147483647;display:flex;align-items:center;gap:12px;height:42px;padding:0 8px 0 14px;border-radius:12px;background:#0f172aeb;box-shadow:0 8px 24px #00000040;animation:mtbBarIn .2s ease}.mtb-record-dot{width:8px;height:8px;border-radius:50%;background:#ef4444;animation:mtbRecordPulse 1.2s ease-in-out infinite;flex-shrink:0}@keyframes mtbRecordPulse{0%,to{opacity:1}50%{opacity:.3}}.mtb-record-timer{font-family:JetBrains Mono,SF Mono,Fira Code,Cascadia Code,monospace;font-size:13px;font-weight:500;color:#fff;font-variant-numeric:tabular-nums;letter-spacing:.02em;min-width:38px}.mtb-record-stop{height:28px;padding:0 14px;border:none;border-radius:7px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;transition:background .12s}.mtb-record-stop:hover{background:#047857}.mtb-click-ripple{position:fixed;z-index:2147483644;width:24px;height:24px;border-radius:50%;border:2px solid #10b981;background:#10b98133;pointer-events:none;transform:translate(-50%,-50%) scale(.5);animation:mtbClickRipple .3s ease-out forwards}@keyframes mtbClickRipple{0%{transform:translate(-50%,-50%) scale(.5);opacity:1}to{transform:translate(-50%,-50%) scale(2);opacity:0}}.mtb-dot{display:inline-block;width:4px;height:4px;border-radius:50%;background:#fff;animation:mtbDot 1.2s infinite}.mtb-dot:nth-child(2){animation-delay:.2s}.mtb-dot:nth-child(3){animation-delay:.4s}@keyframes mtbDot{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}.mtb-clarify{position:fixed;z-index:2147483645;width:min(346px,calc(100vw - 56px));background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;box-shadow:0 24px 64px #0000003d;display:flex;flex-direction:column;animation:mtbSlideUp .28s cubic-bezier(.34,1.56,.64,1);font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;overflow:hidden}.mtb-clarify-continuation{width:min(320px,calc(100vw - 56px));animation:none}.mtb-clarify-header{padding:8px 10px;display:flex;align-items:center;gap:7px;border-bottom:1px solid rgba(0,0,0,.06)}.mtb-clarify-icon{width:20px;height:20px;border-radius:6px;background:linear-gradient(140deg,#10b981,#059669);box-shadow:0 1px 3px #05966966;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mtb-clarify-titles{flex:1;min-width:0}.mtb-clarify-title{font-size:12px;font-weight:650;line-height:1.2;color:#191a1c}.mtb-clarify-subtitle{font-size:9.5px;color:#0000006b}.mtb-clarify-close{background:none;border:none;cursor:pointer;padding:3px;color:#00000061;display:flex;transition:color .12s}.mtb-clarify-close:hover{color:#000000b3}.mtb-clarify-messages{flex:1;overflow-y:auto;padding:8px 10px 4px;display:flex;flex-direction:column;gap:6px}.mtb-clarify-bubble{max-width:82%;padding:6px 10px;font-size:12px;line-height:1.4;white-space:pre-wrap;word-break:break-word}.mtb-clarify-ai{align-self:flex-start;background:#fff;color:#191a1c;border:1px solid rgba(0,0,0,.09);border-radius:11px 11px 11px 3px}.mtb-clarify-user{align-self:flex-end;background:#059669;color:#fff;border:1px solid #059669;border-radius:11px 11px 3px}.mtb-clarify-thinking{display:flex;align-items:center;gap:4px;padding:8px 12px}.mtb-clarify-thinking .mtb-dot{width:6px;height:6px;background:#059669b3}.mtb-clarify-footer{padding:3px 10px 10px;display:flex;flex-direction:column}.mtb-clarify-input{width:100%;height:40px;padding:7px 10px;border:1px solid rgba(0,0,0,.12);border-radius:8px;font-family:inherit;font-size:12px;line-height:1.4;color:#191a1c;outline:none;background:#fafafa;resize:none;box-sizing:border-box;transition:border-color .12s,box-shadow .12s,background .12s}.mtb-clarify-input:focus{border-color:#10b981;box-shadow:0 0 0 3px #10b98126;background:#fff}.mtb-clarify-input::placeholder{color:#00000057}.mtb-clarify-actions{display:flex;gap:6px;margin-top:6px}.mtb-clarify-skip,.mtb-clarify-fallback{flex:0 0 auto;height:30px;padding:0 12px;border:1px solid rgba(0,0,0,.12);border-radius:8px;background:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:550;color:#0000008c;white-space:nowrap;transition:background .12s}.mtb-clarify-skip:hover,.mtb-clarify-fallback:hover{background:#0000000a}.mtb-clarify-send,.mtb-clarify-retry{flex:1;height:30px;display:inline-flex;align-items:center;justify-content:center;gap:5px;border:none;border-radius:8px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;transition:background .12s}.mtb-clarify-send:not(:disabled):hover,.mtb-clarify-retry:not(:disabled):hover{background:#047857}.mtb-clarify-send:disabled,.mtb-clarify-retry:disabled{background:#00000026;cursor:not-allowed}.mtb-clarify-send-feedback{width:100%;height:34px;display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:9px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:600;transition:background .12s}.mtb-clarify-send-feedback:not(:disabled):hover{background:#047857}.mtb-clarify-send-feedback:disabled{background:#00000026;cursor:not-allowed}.mtb-clarify-error{margin-bottom:8px;color:#dc2626;font-size:11.5px;line-height:1.4;text-align:center}:host([data-mtb-theme="dark"]) .mtb-clarify{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-clarify-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="dark"]) .mtb-clarify-title{color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-clarify-subtitle{color:#ffffff73}:host([data-mtb-theme="dark"]) .mtb-clarify-close{color:#ffffff73}:host([data-mtb-theme="dark"]) .mtb-clarify-close:hover{color:#ffffffbf}:host([data-mtb-theme="dark"]) .mtb-clarify-skip,:host([data-mtb-theme="dark"]) .mtb-clarify-fallback{background:#1f2327;border-color:#ffffff24;color:#ffffffb3}:host([data-mtb-theme="dark"]) .mtb-clarify-skip:hover,:host([data-mtb-theme="dark"]) .mtb-clarify-fallback:hover{background:#ffffff0f}:host([data-mtb-theme="dark"]) .mtb-clarify-ai{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="dark"]) .mtb-clarify-input{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}@media (prefers-color-scheme: dark){:host([data-mtb-theme="auto"]) .mtb-clarify{background:#151719;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-clarify-header{border-bottom-color:#ffffff1a}:host([data-mtb-theme="auto"]) .mtb-clarify-title{color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-clarify-subtitle{color:#ffffff73}:host([data-mtb-theme="auto"]) .mtb-clarify-close{color:#ffffff73}:host([data-mtb-theme="auto"]) .mtb-clarify-close:hover{color:#ffffffbf}:host([data-mtb-theme="auto"]) .mtb-clarify-skip,:host([data-mtb-theme="auto"]) .mtb-clarify-fallback{background:#1f2327;border-color:#ffffff24;color:#ffffffb3}:host([data-mtb-theme="auto"]) .mtb-clarify-skip:hover,:host([data-mtb-theme="auto"]) .mtb-clarify-fallback:hover{background:#ffffff0f}:host([data-mtb-theme="auto"]) .mtb-clarify-ai{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}:host([data-mtb-theme="auto"]) .mtb-clarify-input{background:#1f2327;border-color:#ffffff1f;color:#f9fafb}}.mtb-dim-clickable{z-index:2147483643;pointer-events:auto;cursor:default;background:#0000001f}.mtb-draw-bar{position:fixed;bottom:48px;left:50%;transform:translate(-50%);z-index:2147483647;display:flex;align-items:center;gap:8px;height:46px;padding:0 8px 0 12px;border-radius:13px;background:#fff;border:1px solid rgba(0,0,0,.08);box-shadow:0 10px 30px #0f172a38;animation:mtbBarIn .2s ease;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.mtb-draw-input{width:220px;height:32px;padding:0 10px;border:1px solid rgba(0,0,0,.12);border-radius:8px;font-family:inherit;font-size:13px;color:#191a1c;outline:none;background:#fafafa;transition:border-color .12s,box-shadow .12s,background .12s}.mtb-draw-input:focus{border-color:#10b981;box-shadow:0 0 0 3px #10b98126;background:#fff}.mtb-draw-input::placeholder{color:#00000057}.mtb-draw-icon-btn{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:8px;background:transparent;color:#374151;cursor:pointer;transition:background .12s,color .12s}.mtb-draw-icon-btn:hover:not(:disabled){background:#0000000f}.mtb-draw-icon-btn:disabled{color:#00000038;cursor:default}.mtb-draw-sep{width:1px;height:22px;background:#0000001a}.mtb-draw-cancel{height:32px;padding:0 12px;border:1px solid rgba(0,0,0,.12);border-radius:8px;background:#fff;color:#0000008c;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:550;transition:background .12s}.mtb-draw-cancel:hover{background:#0000000a}.mtb-draw-submit{height:32px;padding:0 14px;border:none;border-radius:8px;background:#059669;color:#fff;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:600;transition:background .12s}.mtb-draw-submit:hover:not(:disabled){background:#047857}.mtb-draw-submit:disabled{opacity:.6;cursor:default}.mtb-draw-error{position:absolute;bottom:100%;left:12px;margin-bottom:6px;color:#dc2626;font-size:11.5px}.mtb-record-preview{margin-bottom:12px}.mtb-record-preview-stage{position:relative;width:100%;height:132px;border-radius:10px;overflow:hidden;background:#0f172a;display:flex;align-items:center;justify-content:center}.mtb-record-preview-stage.playing{align-items:flex-start;justify-content:flex-start}.mtb-record-preview-play{width:44px;height:44px;border-radius:50%;border:none;background:#ffffffeb;color:#059669;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .12s,background .12s}.mtb-record-preview-play:hover:not(:disabled){transform:scale(1.06);background:#fff}.mtb-record-preview-play:disabled{cursor:default;opacity:.6}.mtb-record-preview-badge{position:absolute;right:8px;bottom:8px;padding:2px 7px;border-radius:6px;background:#0009;color:#fff;font-size:11px;font-variant-numeric:tabular-nums;font-family:JetBrains Mono,SF Mono,monospace}.mtb-record-preview-fallback{color:#ffffffd9;font-size:12px}.mtb-record-preview-name{display:block;margin-top:5px;font-size:11px;color:#0000006b}';
2
+ class Vt {
3
3
  constructor(t = "auto") {
4
4
  this.host = document.createElement("div"), this.host.id = "mtb-widget-host", this.host.style.cssText = "position:fixed;top:0;left:0;width:0;height:0;overflow:visible;z-index:2147483646;", this.host.setAttribute("data-mtb-theme", t), document.body.appendChild(this.host), this.root = this.host.attachShadow({ mode: "open" });
5
5
  const e = document.createElement("style");
6
- e.textContent = vt, this.root.appendChild(e);
6
+ e.textContent = Wt, this.root.appendChild(e);
7
7
  }
8
8
  el(t, e) {
9
9
  const r = document.createElement(t);
@@ -20,37 +20,40 @@ class kt {
20
20
  this.host.remove();
21
21
  }
22
22
  }
23
- class St {
23
+ class Yt {
24
24
  constructor(t, e, r, s, n) {
25
- this.onClick = s, this.el = t.el("button", "mtb-tab"), r === "left" && this.el.classList.add("left"), this.idleLabel = n ?? e.tab, this.activeLabel = e.toolbar.exit, this.setLabel(this.idleLabel), this.el.addEventListener("click", s), t.append(this.el);
25
+ this.active = !1, this.onClick = s, this.customText = n, this.el = t.el("button", "mtb-tab"), r === "left" && this.el.classList.add("left"), this.idleLabel = n ?? e.tab, this.activeLabel = e.toolbar.exit, this.setLabel(this.idleLabel), this.el.addEventListener("click", s), t.append(this.el);
26
26
  }
27
27
  setLabel(t) {
28
28
  this.el.textContent = t, this.el.setAttribute("aria-label", t);
29
29
  }
30
+ setMessages(t) {
31
+ this.idleLabel = this.customText ?? t.tab, this.activeLabel = t.toolbar.exit, this.setLabel(this.active ? this.activeLabel : this.idleLabel);
32
+ }
30
33
  setActive(t) {
31
- this.el.classList.toggle("active", t), this.setLabel(t ? this.activeLabel : this.idleLabel);
34
+ this.active = t, this.el.classList.toggle("active", t), this.setLabel(t ? this.activeLabel : this.idleLabel);
32
35
  }
33
36
  destroy() {
34
37
  this.el.removeEventListener("click", this.onClick), this.el.remove();
35
38
  }
36
39
  }
37
- const Et = 8e3;
38
- class Ct {
40
+ const Xt = 8e3;
41
+ class Kt {
39
42
  constructor(t, e, r) {
40
- this.el = t.el("div", "mtb-frustration-prompt"), this.el.innerHTML = `
43
+ this.autoHideTimer = null, this.el = t.el("div", "mtb-frustration-prompt"), this.el.innerHTML = `
41
44
  <div class="mtb-frustration-icon">&#9888;&#65039;</div>
42
45
  <span class="mtb-frustration-text">${e.frustration.prompt}</span>
43
46
  <div class="mtb-frustration-actions">
44
47
  <button class="mtb-frustration-tell">${e.frustration.action}</button>
45
48
  <button class="mtb-frustration-dismiss">${e.frustration.dismiss}</button>
46
49
  </div>
47
- `, this.el.querySelector(".mtb-frustration-tell").addEventListener("click", r.onTell), this.el.querySelector(".mtb-frustration-dismiss").addEventListener("click", r.onDismiss), t.append(this.el), setTimeout(r.onDismiss, Et);
50
+ `, this.el.querySelector(".mtb-frustration-tell").addEventListener("click", r.onTell), this.el.querySelector(".mtb-frustration-dismiss").addEventListener("click", r.onDismiss), t.append(this.el), this.autoHideTimer = setTimeout(r.onAutoHide, Xt);
48
51
  }
49
52
  destroy() {
50
- this.el.remove();
53
+ this.autoHideTimer && (clearTimeout(this.autoHideTimer), this.autoHideTimer = null), this.el.remove();
51
54
  }
52
55
  }
53
- class _t {
56
+ class Gt {
54
57
  constructor(t, e) {
55
58
  this.onClick = e, this.el = t.el("div", "mtb-dim mtb-dim-clickable"), this.el.addEventListener("click", this.onClick), t.append(this.el);
56
59
  }
@@ -58,13 +61,28 @@ class _t {
58
61
  this.el.removeEventListener("click", this.onClick), this.el.remove();
59
62
  }
60
63
  }
61
- class Tt {
64
+ const Jt = 500;
65
+ class Qt {
62
66
  constructor(t, e, r, s) {
63
- this.currentMode = "markup", this.messages = e, this.el = t.el("div", "mtb-toolbar"), this.el.innerHTML = this.buildHTML(e), t.append(this.el), this.hintEl = this.el.querySelector(".mtb-toolbar-hint"), this.markupBtn = this.el.querySelector(".mtb-toolbar-mode-markup"), this.recordBtn = this.el.querySelector(".mtb-toolbar-mode-record"), this.markupBtn.addEventListener("click", () => {
67
+ this.currentMode = "markup", this.fadeTimer = null, this.faded = !1, this.pointerInside = !1, this.handleDocMouseMove = (n) => {
68
+ const o = this.el.getBoundingClientRect(), a = n.clientX >= o.left && n.clientX <= o.right && n.clientY >= o.top && n.clientY <= o.bottom;
69
+ a && !this.pointerInside ? this.faded ? this.restoreToolbar() : this.startFadeTimer() : !a && this.pointerInside && this.clearFadeTimer(), this.pointerInside = a;
70
+ }, this.messages = e, this.el = t.el("div", "mtb-toolbar"), this.el.innerHTML = this.buildHTML(e), t.append(this.el), this.hintEl = this.el.querySelector(".mtb-toolbar-hint"), this.markupBtn = this.el.querySelector(".mtb-toolbar-mode-markup"), this.recordBtn = this.el.querySelector(".mtb-toolbar-mode-record"), this.markupBtn.addEventListener("click", () => {
64
71
  this.setMode("markup"), s?.("markup");
65
72
  }), this.recordBtn.addEventListener("click", () => {
66
73
  this.setMode("record"), s?.("record");
67
- }), this.el.querySelector(".mtb-exit-btn").addEventListener("click", r);
74
+ }), this.el.querySelector(".mtb-exit-btn").addEventListener("click", r), this.el.addEventListener("click", () => this.clearFadeTimer()), document.addEventListener("mousemove", this.handleDocMouseMove);
75
+ }
76
+ startFadeTimer() {
77
+ this.clearFadeTimer(), this.fadeTimer = setTimeout(() => {
78
+ this.fadeTimer = null, this.faded = !0, this.el.classList.add("mtb-toolbar-faded");
79
+ }, Jt);
80
+ }
81
+ clearFadeTimer() {
82
+ this.fadeTimer !== null && (clearTimeout(this.fadeTimer), this.fadeTimer = null);
83
+ }
84
+ restoreToolbar() {
85
+ this.faded = !1, this.el.classList.remove("mtb-toolbar-faded");
68
86
  }
69
87
  buildHTML(t) {
70
88
  return `
@@ -92,10 +110,10 @@ class Tt {
92
110
  return this.currentMode;
93
111
  }
94
112
  destroy() {
95
- this.el.remove();
113
+ this.clearFadeTimer(), document.removeEventListener("mousemove", this.handleDocMouseMove), this.el.remove();
96
114
  }
97
115
  }
98
- class Lt {
116
+ class Zt {
99
117
  constructor(t, e) {
100
118
  this.onMouseDown = e.onMouseDown, this.onMouseMove = e.onMouseMove, this.onMouseUp = e.onMouseUp, this.onMouseLeave = e.onMouseLeave, this.overlayEl = t.el("div", "mtb-overlay"), this.overlayEl.addEventListener("mousedown", this.onMouseDown), this.overlayEl.addEventListener("mousemove", this.onMouseMove), this.overlayEl.addEventListener("mouseup", this.onMouseUp), this.overlayEl.addEventListener("mouseleave", this.onMouseLeave), t.append(this.overlayEl), this.dimEl = t.el("div", "mtb-dim"), t.append(this.dimEl);
101
119
  }
@@ -103,7 +121,7 @@ class Lt {
103
121
  this.overlayEl.removeEventListener("mousedown", this.onMouseDown), this.overlayEl.removeEventListener("mousemove", this.onMouseMove), this.overlayEl.removeEventListener("mouseup", this.onMouseUp), this.overlayEl.removeEventListener("mouseleave", this.onMouseLeave), this.overlayEl.remove(), this.dimEl.remove();
104
122
  }
105
123
  }
106
- class Mt {
124
+ class te {
107
125
  constructor(t) {
108
126
  this.highlightEl = t.el("div", "mtb-highlight"), this.tooltipEl = t.el("div", "mtb-highlight-tooltip"), this.hide(), t.append(this.highlightEl, this.tooltipEl);
109
127
  }
@@ -112,7 +130,7 @@ class Mt {
112
130
  this.highlightEl.style.top = `${e.top - 2}px`, this.highlightEl.style.left = `${e.left - 2}px`, this.highlightEl.style.width = `${e.width + 4}px`, this.highlightEl.style.height = `${e.height + 4}px`, this.highlightEl.style.display = "block", this.showTooltip(t, e);
113
131
  }
114
132
  showTooltip(t, e) {
115
- this.tooltipEl.textContent = F(t);
133
+ this.tooltipEl.textContent = G(t);
116
134
  const r = e.top < 30;
117
135
  this.tooltipEl.classList.toggle("below", r), this.tooltipEl.style.left = `${e.left + e.width / 2}px`, this.tooltipEl.style.top = r ? `${e.bottom + 8}px` : `${e.top - 8}px`, this.tooltipEl.style.display = "block";
118
136
  }
@@ -126,7 +144,7 @@ class Mt {
126
144
  this.highlightEl.remove(), this.tooltipEl.remove();
127
145
  }
128
146
  }
129
- function F(i) {
147
+ function G(i) {
130
148
  if (i instanceof HTMLElement) {
131
149
  const t = i.getAttribute("aria-label");
132
150
  if (t) return t;
@@ -143,7 +161,7 @@ function F(i) {
143
161
  }
144
162
  return i.tagName.toLowerCase();
145
163
  }
146
- function at(i) {
164
+ function _t(i) {
147
165
  const t = [];
148
166
  let e = i;
149
167
  for (; e && e !== document.body && t.length < 5; ) {
@@ -168,7 +186,7 @@ function at(i) {
168
186
  }
169
187
  return t.join(" > ");
170
188
  }
171
- class Pt {
189
+ class ee {
172
190
  constructor(t) {
173
191
  this.pins = [], this.shadow = t;
174
192
  }
@@ -184,14 +202,18 @@ class Pt {
184
202
  this.clearAll();
185
203
  }
186
204
  }
187
- const D = "#059669", Rt = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', S = {
188
- color: D,
205
+ const O = "#059669", ie = "5,150,105";
206
+ function J(i) {
207
+ return `rgba(${ie},${i})`;
208
+ }
209
+ const re = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', C = {
210
+ color: O,
189
211
  width: "3.5",
190
212
  linecap: "round",
191
213
  linejoin: "round",
192
- filter: "drop-shadow(0 1px 2px rgba(5,150,105,0.35))"
214
+ filter: `drop-shadow(0 1px 2px ${J(0.35)})`
193
215
  };
194
- class Dt {
216
+ class se {
195
217
  constructor(t) {
196
218
  this.currentPath = null, this.currentPoints = [], this.isDrawing = !1, this.committed = [], this.redoStack = [], this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"), this.svg.setAttribute("class", "mtb-draw-svg"), t.append(this.svg);
197
219
  }
@@ -199,12 +221,12 @@ class Dt {
199
221
  this.isDrawing = !0, this.currentPoints = [[t, e]], this.currentPath = this.createPath(), this.svg.appendChild(this.currentPath);
200
222
  }
201
223
  continueDraw(t, e) {
202
- !this.isDrawing || !this.currentPath || (this.currentPoints.push([t, e]), this.currentPath.setAttribute("d", j(this.currentPoints)));
224
+ !this.isDrawing || !this.currentPath || (this.currentPoints.push([t, e]), this.currentPath.setAttribute("d", et(this.currentPoints)));
203
225
  }
204
226
  // Commits the in-progress stroke to the undo stack and clears the redo stack.
205
227
  // Callers decide whether the stroke has enough points before committing.
206
228
  commitStroke() {
207
- return !this.isDrawing || !this.currentPath ? !1 : (this.isDrawing = !1, this.committed.push({ path: this.currentPath, d: j(this.currentPoints), points: this.currentPoints }), this.redoStack = [], this.currentPath = null, this.currentPoints = [], !0);
229
+ return !this.isDrawing || !this.currentPath ? !1 : (this.isDrawing = !1, this.committed.push({ path: this.currentPath, d: et(this.currentPoints), points: this.currentPoints }), this.redoStack = [], this.currentPath = null, this.currentPoints = [], !0);
208
230
  }
209
231
  cancelCurrentDraw() {
210
232
  this.currentPath?.remove(), this.currentPath = null, this.isDrawing = !1, this.currentPoints = [];
@@ -230,7 +252,7 @@ class Dt {
230
252
  }
231
253
  getAnnotation() {
232
254
  if (this.committed.length === 0) return null;
233
- const t = this.committed.flatMap((s) => s.points), [e, r] = At(t);
255
+ const t = this.committed.flatMap((s) => s.points), [e, r] = ne(t);
234
256
  return {
235
257
  type: "draw",
236
258
  x: e,
@@ -253,10 +275,10 @@ class Dt {
253
275
  }
254
276
  createPath() {
255
277
  const t = document.createElementNS("http://www.w3.org/2000/svg", "path");
256
- return t.setAttribute("fill", "none"), t.setAttribute("stroke", S.color), t.setAttribute("stroke-width", S.width), t.setAttribute("stroke-linecap", S.linecap), t.setAttribute("stroke-linejoin", S.linejoin), t.setAttribute("style", `filter:${S.filter}`), t;
278
+ return t.setAttribute("fill", "none"), t.setAttribute("stroke", C.color), t.setAttribute("stroke-width", C.width), t.setAttribute("stroke-linecap", C.linecap), t.setAttribute("stroke-linejoin", C.linejoin), t.setAttribute("style", `filter:${C.filter}`), t;
257
279
  }
258
280
  }
259
- function j(i) {
281
+ function et(i) {
260
282
  if (i.length === 0) return "";
261
283
  const [t, e] = i[0];
262
284
  let r = `M ${t} ${e}`;
@@ -266,14 +288,14 @@ function j(i) {
266
288
  }
267
289
  return r;
268
290
  }
269
- function At(i) {
291
+ function ne(i) {
270
292
  const t = i.map((n) => n[0]), e = i.map((n) => n[1]), r = (Math.min(...t) + Math.max(...t)) / 2, s = (Math.min(...e) + Math.max(...e)) / 2;
271
293
  return [r, s];
272
294
  }
273
- const Ht = 5;
274
- class It {
295
+ const oe = 5;
296
+ class ae {
275
297
  constructor(t, e, r) {
276
- this.messages = e, this.handlers = r, this.interactionActive = !0, this.pendingHighlightFrame = null, this.lastMoveX = 0, this.lastMoveY = 0, this.highlighter = new Mt(t), this.pinMarker = new Pt(t), this.drawLayer = new Dt(t), this.overlay = new Lt(t, {
298
+ this.messages = e, this.handlers = r, this.interactionActive = !0, this.pendingHighlightFrame = null, this.lastMoveX = 0, this.lastMoveY = 0, this.highlighter = new te(t), this.pinMarker = new ee(t), this.drawLayer = new se(t), this.overlay = new Zt(t, {
277
299
  onMouseDown: (s) => this.handleMouseDown(s),
278
300
  onMouseMove: (s) => this.handleMouseMove(s),
279
301
  onMouseUp: (s) => this.handleMouseUp(s),
@@ -296,7 +318,7 @@ class It {
296
318
  }
297
319
  updateHighlight() {
298
320
  if (!this.interactionActive || this.drawLayer.isCurrentlyDrawing() || this.drawSessionActive()) return;
299
- const t = q(this.lastMoveX, this.lastMoveY);
321
+ const t = it(this.lastMoveX, this.lastMoveY);
300
322
  t ? this.highlighter.highlight(t) : this.highlighter.hide();
301
323
  }
302
324
  cancelPendingHighlight() {
@@ -309,16 +331,16 @@ class It {
309
331
  // draw note bar; a tap on an element becomes a pin. Stray taps while a
310
332
  // drawing already exists are ignored so they don't hijack the draw flow.
311
333
  finishStroke(t) {
312
- if (this.drawLayer.getCurrentPointCount() >= Ht) {
334
+ if (this.drawLayer.getCurrentPointCount() >= oe) {
313
335
  this.drawLayer.commitStroke(), this.highlighter.hide(), this.handlers.onDrawStroke();
314
336
  return;
315
337
  }
316
338
  if (this.drawLayer.cancelCurrentDraw(), this.drawLayer.hasStrokes() || !t) return;
317
- const e = q(t.clientX, t.clientY), r = e ? F(e) : this.messages.annotation.element, s = e?.getBoundingClientRect(), n = {
339
+ const e = it(t.clientX, t.clientY), r = e ? G(e) : this.messages.annotation.element, s = e?.getBoundingClientRect(), n = {
318
340
  type: "pin",
319
341
  x: t.clientX,
320
342
  y: t.clientY,
321
- targetSelector: e ? at(e) : void 0,
343
+ targetSelector: e ? _t(e) : void 0,
322
344
  targetText: e?.textContent?.trim().slice(0, 200) ?? "",
323
345
  targetName: r,
324
346
  targetRect: s ? { top: s.top, left: s.left, width: s.width, height: s.height, bottom: s.bottom } : void 0
@@ -359,18 +381,18 @@ class It {
359
381
  this.dismissInteraction(), this.highlighter.destroy(), this.pinMarker.destroy(), this.drawLayer.destroy();
360
382
  }
361
383
  }
362
- function q(i, t) {
384
+ function it(i, t) {
363
385
  return document.elementsFromPoint(i, t).find((e) => e.id !== "mtb-widget-host") ?? null;
364
386
  }
365
- const $t = "mtb-widget-host";
366
- function _(i) {
367
- const t = document.getElementById($t);
387
+ const le = "mtb-widget-host";
388
+ function S(i) {
389
+ const t = document.getElementById(le);
368
390
  return t ? t === i || t.contains(i) : !1;
369
391
  }
370
- function d(i) {
392
+ function h(i) {
371
393
  return i.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
372
394
  }
373
- class Bt {
395
+ class ce {
374
396
  constructor(t, e) {
375
397
  this.loading = !1, this.onSubmit = e.onSubmit, this.submitLabel = e.messages.draw.submit, this.el = t.el("div", "mtb-draw-bar"), this.el.innerHTML = this.buildHTML(e.messages), t.append(this.el), this.input = this.el.querySelector(".mtb-draw-input"), this.undoBtn = this.el.querySelector(".mtb-draw-undo"), this.redoBtn = this.el.querySelector(".mtb-draw-redo"), this.submitBtn = this.el.querySelector(".mtb-draw-submit"), this.errorEl = this.el.querySelector(".mtb-draw-error"), this.undoBtn.addEventListener("click", e.onUndo), this.redoBtn.addEventListener("click", e.onRedo), this.el.querySelector(".mtb-draw-cancel").addEventListener("click", e.onCancel), this.submitBtn.addEventListener("click", () => this.submit()), this.input.addEventListener("keydown", (r) => {
376
398
  r.isComposing || r.keyCode === 229 || r.key === "Enter" && !r.shiftKey && (r.preventDefault(), this.submit());
@@ -378,16 +400,16 @@ class Bt {
378
400
  }
379
401
  buildHTML(t) {
380
402
  return `
381
- <input class="mtb-draw-input" type="text" placeholder="${d(t.draw.note_placeholder)}" />
382
- <button class="mtb-draw-icon-btn mtb-draw-undo" type="button" title="${d(t.draw.undo)}" aria-label="${d(t.draw.undo)}" disabled>
403
+ <input class="mtb-draw-input" type="text" placeholder="${h(t.draw.note_placeholder)}" />
404
+ <button class="mtb-draw-icon-btn mtb-draw-undo" type="button" title="${h(t.draw.undo)}" aria-label="${h(t.draw.undo)}" disabled>
383
405
  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14L4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 0 10h-1"/></svg>
384
406
  </button>
385
- <button class="mtb-draw-icon-btn mtb-draw-redo" type="button" title="${d(t.draw.redo)}" aria-label="${d(t.draw.redo)}" disabled>
407
+ <button class="mtb-draw-icon-btn mtb-draw-redo" type="button" title="${h(t.draw.redo)}" aria-label="${h(t.draw.redo)}" disabled>
386
408
  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14l5-5-5-5"/><path d="M20 9H9a5 5 0 0 0 0 10h1"/></svg>
387
409
  </button>
388
410
  <span class="mtb-draw-sep"></span>
389
- <button class="mtb-draw-cancel" type="button">${d(t.draw.cancel)}</button>
390
- <button class="mtb-draw-submit" type="button">${d(t.draw.submit)}</button>
411
+ <button class="mtb-draw-cancel" type="button">${h(t.draw.cancel)}</button>
412
+ <button class="mtb-draw-submit" type="button">${h(t.draw.submit)}</button>
391
413
  <div class="mtb-draw-error" role="alert" hidden></div>
392
414
  `;
393
415
  }
@@ -407,16 +429,16 @@ class Bt {
407
429
  this.el.remove();
408
430
  }
409
431
  }
410
- class Ft {
432
+ class de {
411
433
  constructor(t, e) {
412
- this.loading = !1, this.onSubmit = e.onSubmit, this.onClose = e.onClose, this.submitLabel = e.messages.popup.submit, this.messages = e.messages, this.el = t.el("div", "mtb-popup"), this.el.innerHTML = this.buildHTML(e), t.append(this.el), this.textarea = this.el.querySelector(".mtb-textarea"), this.submitBtn = this.el.querySelector(".mtb-submit-btn"), this.positionPopup(e.x, e.y, e.targetRect, e.position ?? "right"), this.bindEvents(e.messages), e.onMyFeedback && this.el.querySelector(".mtb-my-feedback").addEventListener("click", e.onMyFeedback), this.textarea.focus();
434
+ this.loading = !1, this.selectedQuickOption = null, this.onSubmit = e.onSubmit, this.onClose = e.onClose, this.submitLabel = e.messages.popup.submit, this.messages = e.messages, this.el = t.el("div", "mtb-popup"), this.el.innerHTML = this.buildHTML(e), t.append(this.el), this.textarea = this.el.querySelector(".mtb-textarea"), this.submitBtn = this.el.querySelector(".mtb-submit-btn"), this.positionPopup(e.x, e.y, e.targetRect, e.position ?? "right"), this.bindEvents(e.messages), e.onMyFeedback && this.el.querySelector(".mtb-my-feedback").addEventListener("click", e.onMyFeedback), this.textarea.focus();
413
435
  }
414
436
  buildHTML(t) {
415
437
  const e = t.messages, r = e.popup.quickOptions.map(
416
438
  (s) => `
417
- <button class="mtb-quick-option" data-quick="${d(s.label)}">
439
+ <button class="mtb-quick-option" data-quick="${h(s.label)}">
418
440
  <span class="mtb-quick-option-emoji">${s.emoji}</span>
419
- <span>${d(s.label)}</span>
441
+ <span>${h(s.label)}</span>
420
442
  </button>`
421
443
  ).join("");
422
444
  return `
@@ -426,7 +448,7 @@ class Ft {
426
448
  <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>
427
449
  </svg>
428
450
  </div>
429
- <span class="mtb-popup-title">${e.popup.about} "${d(t.targetName)}"</span>
451
+ <span class="mtb-popup-title">${e.popup.about} "${h(t.targetName)}"</span>
430
452
  <button class="mtb-popup-close" aria-label="Close">
431
453
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
432
454
  <path d="M18 6L6 18M6 6l12 12"/>
@@ -438,27 +460,33 @@ class Ft {
438
460
  ${r}
439
461
  </div>
440
462
  <div class="mtb-textarea-wrap">
441
- <textarea class="mtb-textarea" placeholder="${d(e.popup.placeholder)}"></textarea>
463
+ <textarea class="mtb-textarea" placeholder="${h(e.popup.placeholder)}"></textarea>
442
464
  </div>
443
465
  <div class="mtb-popup-error" role="alert"></div>
444
466
  <div class="mtb-popup-actions">
445
- <button class="mtb-cancel-btn" type="button">${d(e.popup.cancel)}</button>
446
- <button class="mtb-submit-btn" type="button" disabled>${d(e.popup.submit)}</button>
467
+ <button class="mtb-cancel-btn" type="button">${h(e.popup.cancel)}</button>
468
+ <button class="mtb-submit-btn" type="button" disabled>${h(e.popup.submit)}</button>
447
469
  </div>
448
- ${t.onMyFeedback ? `<button class="mtb-my-feedback" type="button">${d(e.popup.my_feedback)}</button>` : ""}
470
+ ${t.onMyFeedback ? `<button class="mtb-my-feedback" type="button">${h(e.popup.my_feedback)}</button>` : ""}
449
471
  </div>
450
472
  `;
451
473
  }
452
474
  positionPopup(t, e, r, s) {
453
- const n = window.innerWidth, o = window.innerHeight, a = 12, l = 8, c = 32, h = Math.min(320, n - 2 * a - c), u = this.el.offsetHeight || 260, m = a + (s === "left" ? c : 0), g = n - a - (s === "right" ? c : 0);
454
- let y, b;
455
- r ? (y = r.left, b = r.bottom + l, b + u > o - a && (b = r.top - u - l), b < a && (b = Math.min(r.bottom + l, o - u - a))) : (y = t + 12, b = e + 12), y + h > g && (y = g - h), y < m && (y = m), b < a && (b = a), this.el.style.left = `${y}px`, this.el.style.top = `${b}px`, this.el.style.maxHeight = `${o - b - a}px`;
475
+ const n = window.innerWidth, o = window.innerHeight, a = 12, l = 8, c = 32, d = Math.min(320, n - 2 * a - c), u = this.el.offsetHeight || 260, m = a + (s === "left" ? c : 0), p = n - a - (s === "right" ? c : 0);
476
+ let g, y;
477
+ r ? (g = r.left, y = r.bottom + l, y + u > o - a && (y = r.top - u - l), y < a && (y = Math.min(r.bottom + l, o - u - a))) : (g = t + 12, y = e + 12), g + d > p && (g = p - d), g < m && (g = m), y < a && (y = a), this.el.style.left = `${g}px`, this.el.style.top = `${y}px`, this.el.style.maxHeight = `${o - y - a}px`;
456
478
  }
457
479
  bindEvents(t) {
458
480
  this.el.querySelector(".mtb-popup-close").addEventListener("click", () => this.onClose()), this.el.querySelector(".mtb-cancel-btn").addEventListener("click", () => this.onClose()), this.errorEl = this.el.querySelector(".mtb-popup-error"), this.el.querySelectorAll(".mtb-quick-option").forEach((e) => {
459
481
  e.addEventListener("click", () => {
460
482
  const r = e.dataset.quick ?? "";
461
- this.textarea.value = r, this.updateSubmitState(), this.submit();
483
+ if (this.textarea.value.trim().length === 0) {
484
+ this.textarea.value = r, this.updateSubmitState(), this.submit();
485
+ return;
486
+ }
487
+ this.selectedQuickOption = r, this.el.querySelectorAll(".mtb-quick-option").forEach((s) => {
488
+ s.classList.toggle("selected", s === e);
489
+ });
462
490
  });
463
491
  }), this.textarea.addEventListener("input", () => this.updateSubmitState()), this.textarea.addEventListener("keydown", (e) => {
464
492
  e.isComposing || e.keyCode === 229 || e.key === "Enter" && !e.shiftKey && (e.preventDefault(), this.submit());
@@ -470,7 +498,9 @@ class Ft {
470
498
  }
471
499
  submit() {
472
500
  const t = this.textarea.value.trim();
473
- !t || this.loading || this.onSubmit(t);
501
+ if (!t || this.loading) return;
502
+ const e = this.selectedQuickOption ? `[${this.selectedQuickOption}] ${t}` : t;
503
+ this.onSubmit(e);
474
504
  }
475
505
  setLoading(t) {
476
506
  this.loading = t, t ? (this.submitBtn.classList.add("loading"), this.submitBtn.innerHTML = '<span class="mtb-dot"></span><span class="mtb-dot"></span><span class="mtb-dot"></span>', this.textarea.disabled = !0) : (this.submitBtn.classList.remove("loading"), this.submitBtn.textContent = this.submitLabel, this.textarea.disabled = !1), this.updateSubmitState();
@@ -485,24 +515,208 @@ class Ft {
485
515
  this.el.remove();
486
516
  }
487
517
  }
488
- const Ut = 2e3, Ot = 45e3, zt = 346, jt = 270;
489
- class qt {
518
+ class Tt extends Error {
519
+ constructor(t) {
520
+ super(`HTTP ${t}`), this.name = "ApiError", this.status = t;
521
+ }
522
+ }
523
+ function he(i) {
524
+ return i instanceof Tt && i.status === 409;
525
+ }
526
+ const ue = "https://makethisbetter.dev/api/v1";
527
+ class me {
528
+ constructor(t, e, r = 1e3, s, n) {
529
+ this.projectKey = t, this.apiUrl = (e ?? ue).replace(/\/$/, ""), this.retryDelayMs = r, this.userToken = s, this.userTokenFn = n;
530
+ }
531
+ async resolveUserToken() {
532
+ return this.userTokenFn ? this.userTokenFn() : this.userToken;
533
+ }
534
+ async authHeaders(t) {
535
+ const e = { "X-Project-Key": this.projectKey }, r = await this.resolveUserToken();
536
+ return r && (e["X-User-Token"] = r), t && (e["Content-Type"] = t), e;
537
+ }
538
+ async submissionHeaders(t, e) {
539
+ const r = await this.authHeaders(e);
540
+ return r["X-Submission-Token"] = t, r;
541
+ }
542
+ async createSubmissionSession(t, e) {
543
+ const r = pe(), s = new FormData();
544
+ if (s.append("feedback[description]", t.description), s.append("feedback[page_url]", t.page_url), s.append("feedback[user_agent]", t.user_agent), s.append("feedback[browser]", t.browser), s.append("feedback[os]", t.os), s.append("feedback[screen_width]", String(t.screen_width)), s.append("feedback[screen_height]", String(t.screen_height)), s.append("feedback[console_errors]", JSON.stringify(t.console_errors)), s.append("feedback[annotations]", JSON.stringify(t.annotations)), t.target_element && s.append("feedback[target_element]", JSON.stringify(t.target_element)), t.user_id && s.append("feedback[user_id]", t.user_id), t.reporter_external_id && s.append("feedback[reporter_external_id]", t.reporter_external_id), t.reporter_email && s.append("feedback[reporter_email]", t.reporter_email), t.user_email && s.append("feedback[user_email]", t.user_email), t.user_name && s.append("feedback[user_name]", t.user_name), t.breadcrumbs && t.breadcrumbs.length > 0 && s.append("feedback[breadcrumbs]", JSON.stringify(t.breadcrumbs)), t.recording_events && t.recording_events.length > 0) {
545
+ const l = JSON.stringify(t.recording_events), c = new Blob([l], { type: "application/json" });
546
+ s.append("feedback[recording]", c, "interaction-replay.json"), s.append("feedback[recording_duration]", String(t.recording_duration ?? 0));
547
+ }
548
+ if (e) {
549
+ const l = e.type === "image/jpeg" ? "jpg" : "png";
550
+ s.append("feedback[screenshot]", e, `screenshot.${l}`);
551
+ }
552
+ const n = await this.authHeaders();
553
+ return n["X-Submission-Token"] = r, n["X-Idempotency-Key"] = be(), { ...(await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions`, {
554
+ method: "POST",
555
+ headers: n,
556
+ body: s
557
+ })).json()).submission_session, token: r };
558
+ }
559
+ async createIdentityToken(t) {
560
+ const e = await this.authHeaders("application/json");
561
+ try {
562
+ return await (await this.fetchWithRetry(`${this.apiUrl}/widget/identity_tokens`, {
563
+ method: "POST",
564
+ headers: e,
565
+ body: JSON.stringify({ reporter_external_id: t })
566
+ })).json();
567
+ } catch {
568
+ return null;
569
+ }
570
+ }
571
+ async updateReporter(t, e, r) {
572
+ const s = await this.authHeaders("application/json");
573
+ s["X-Identity-Token"] = r;
574
+ try {
575
+ return await this.fetchWithRetry(`${this.apiUrl}/widget/feedbacks/${t}/reporter`, {
576
+ method: "PATCH",
577
+ headers: s,
578
+ body: JSON.stringify({ reporter: { email: e } })
579
+ }), !0;
580
+ } catch {
581
+ return !1;
582
+ }
583
+ }
584
+ async startClarification(t, e, r) {
585
+ const s = {};
586
+ return r && (s.message = r), this.requestClarification(t, e, s);
587
+ }
588
+ async retryClarification(t, e) {
589
+ return this.requestClarification(t, e, { retry: !0 });
590
+ }
591
+ async requestClarification(t, e, r) {
592
+ const s = await this.submissionHeaders(e, "application/json");
593
+ return (await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/clarification`, {
594
+ method: "POST",
595
+ headers: s,
596
+ body: JSON.stringify(r)
597
+ })).json()).clarification;
598
+ }
599
+ async getClarification(t, e) {
600
+ const r = await this.submissionHeaders(e);
601
+ return (await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/clarification`, {
602
+ method: "GET",
603
+ headers: r
604
+ })).json()).clarification;
605
+ }
606
+ // Streams a clarification turn over SSE. Calls onDelta for each token and
607
+ // resolves with the committed result. Throws if the server doesn't stream
608
+ // (e.g. old backend returns JSON) so the caller can fall back to polling.
609
+ async streamClarification(t, e, r, s) {
610
+ const n = await this.submissionHeaders(e, "application/json");
611
+ n.Accept = "text/event-stream";
612
+ const o = await fetch(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/clarification`, {
613
+ method: "POST",
614
+ headers: n,
615
+ body: JSON.stringify({}),
616
+ signal: s
617
+ }), a = o.headers.get("Content-Type") ?? "";
618
+ if (!o.ok || !o.body || !a.includes("text/event-stream"))
619
+ throw new Error("clarify stream unavailable");
620
+ return fe(o.body, r);
621
+ }
622
+ async finalizeSubmissionSession(t, e) {
623
+ const r = await this.submissionHeaders(e);
624
+ return (await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/feedback`, {
625
+ method: "POST",
626
+ headers: r
627
+ })).json()).feedback;
628
+ }
629
+ async abandonSubmissionSession(t, e) {
630
+ const r = await this.submissionHeaders(e);
631
+ await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}`, {
632
+ method: "DELETE",
633
+ headers: r
634
+ });
635
+ }
636
+ async fetchWithRetry(t, e, r = 1) {
637
+ let s;
638
+ try {
639
+ s = await fetch(t, e);
640
+ } catch (n) {
641
+ if (r > 0)
642
+ return await rt(this.retryDelayMs), this.fetchWithRetry(t, e, r - 1);
643
+ throw n;
644
+ }
645
+ if (s.ok) return s;
646
+ if (s.status >= 500 && r > 0)
647
+ return await rt(this.retryDelayMs), this.fetchWithRetry(t, e, r - 1);
648
+ throw new Tt(s.status);
649
+ }
650
+ }
651
+ function rt(i) {
652
+ return i <= 0 ? Promise.resolve() : new Promise((t) => setTimeout(t, i));
653
+ }
654
+ async function fe(i, t) {
655
+ const e = i.getReader(), r = new TextDecoder();
656
+ let s = "", n = null;
657
+ const o = (a) => {
658
+ const l = a.split(`
659
+ `).find((m) => m.startsWith("event:")), c = a.split(`
660
+ `).find((m) => m.startsWith("data:"));
661
+ if (!c) return;
662
+ const d = l?.slice(6).trim(), u = JSON.parse(c.slice(5).trim());
663
+ d === "delta" && typeof u.text == "string" ? t(u.text) : d === "done" && (n = {
664
+ messages: Array.isArray(u.messages) ? u.messages : [],
665
+ done: u.done !== !1,
666
+ failed: u.error === !0
667
+ });
668
+ };
669
+ for (; ; ) {
670
+ const { done: a, value: l } = await e.read();
671
+ if (a) break;
672
+ s += r.decode(l, { stream: !0 });
673
+ let c;
674
+ for (; (c = s.indexOf(`
675
+
676
+ `)) !== -1; ) {
677
+ const d = s.slice(0, c);
678
+ s = s.slice(c + 2);
679
+ try {
680
+ o(d);
681
+ } catch {
682
+ }
683
+ }
684
+ }
685
+ if (s += r.decode(), s.trim())
686
+ try {
687
+ o(s);
688
+ } catch {
689
+ }
690
+ if (!n) throw new Error("clarify stream ended before done");
691
+ return n;
692
+ }
693
+ function be() {
694
+ return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
695
+ }
696
+ function pe() {
697
+ if (typeof crypto > "u" || typeof crypto.getRandomValues != "function")
698
+ throw new Error("Secure random generation is unavailable");
699
+ const i = crypto.getRandomValues(new Uint8Array(32));
700
+ return Array.from(i, (t) => t.toString(16).padStart(2, "0")).join("");
701
+ }
702
+ const ge = 2e3, ye = 45e3, we = 346, ve = 270;
703
+ class xe {
490
704
  constructor(t, e) {
491
- this.pollTimer = null, this.pollDeadline = 0, this.streamingBubble = null, this.lastMessages = [], this.done = !1, this.sending = !1, this.finalizing = !1, this.destroyed = !1, this.submissionSessionId = e.submissionSessionId, this.submissionToken = e.submissionToken, this.apiClient = e.apiClient, this.onFinalize = e.onFinalize, this.i18n = e.messages, this.preloadedResult = e.preloadedResult, this.pendingClarification = e.pendingClarification;
705
+ this.pollTimer = null, this.pollDeadline = 0, this.streamingBubble = null, this.lastMessages = [], this.done = !1, this.sending = !1, this.finalizing = !1, this.destroyed = !1, this.unrecoverable = !1, this.submissionSessionId = e.submissionSessionId, this.submissionToken = e.submissionToken, this.apiClient = e.apiClient, this.onFinalize = e.onFinalize, this.i18n = e.messages, this.preloadedResult = e.preloadedResult, this.pendingClarification = e.pendingClarification;
492
706
  const r = e.element;
493
- this.el = r ?? t.el("div", "mtb-clarify"), this.el.className = r ? "mtb-clarify mtb-clarify-continuation" : "mtb-clarify", this.el.innerHTML = this.buildHTML(e.messages), r || (t.append(this.el), this.positionCard(e.x, e.y, e.position ?? "right")), this.messagesEl = this.el.querySelector(".mtb-clarify-messages"), this.inputEl = this.el.querySelector(".mtb-clarify-input"), this.sendBtn = this.el.querySelector(".mtb-clarify-send"), this.bindEvents(), this.startConversation();
707
+ this.el = r ?? t.el("div", "mtb-clarify"), this.el.className = r ? "mtb-clarify mtb-clarify-continuation" : "mtb-clarify", this.el.innerHTML = this.buildHTML(e.messages), r || (t.append(this.el), this.positionCard(e.x, e.y, e.position ?? "right")), this.messagesEl = this.el.querySelector(".mtb-clarify-messages"), this.bindEvents(), this.startConversation();
494
708
  }
495
709
  // Anchors the card near the annotation point, clamped to the viewport so it
496
710
  // never overflows a screen edge (mirrors CommentPopup.positionPopup).
497
711
  positionCard(t, e, r) {
498
- const s = window.innerWidth, n = window.innerHeight, o = 12, a = 32, l = Math.min(zt, s - 2 * o - a), c = this.el.offsetHeight || jt, h = o + (r === "left" ? a : 0), u = s - o - (r === "right" ? a : 0);
712
+ const s = window.innerWidth, n = window.innerHeight, o = 12, a = 32, l = Math.min(we, s - 2 * o - a), c = this.el.offsetHeight || ve, d = o + (r === "left" ? a : 0), u = s - o - (r === "right" ? a : 0);
499
713
  if (t === void 0 || e === void 0) {
500
- const y = Math.max(h, (s - l) / 2);
501
- this.el.style.left = `${Math.min(y, u - l)}px`, this.el.style.top = `${Math.max(o, (n - c) / 2)}px`, this.el.style.maxHeight = `${n - 2 * o}px`;
714
+ const g = Math.max(d, (s - l) / 2);
715
+ this.el.style.left = `${Math.min(g, u - l)}px`, this.el.style.top = `${Math.max(o, (n - c) / 2)}px`, this.el.style.maxHeight = `${n - 2 * o}px`;
502
716
  return;
503
717
  }
504
- let m = t + 12, g = e + 12;
505
- m + l > u && (m = t - l - 12), m + l > u && (m = u - l), m < h && (m = h), g + c > n - o && (g = n - c - o), g < o && (g = o), this.el.style.left = `${m}px`, this.el.style.top = `${g}px`, this.el.style.maxHeight = `${n - g - o}px`;
718
+ let m = t + 12, p = e + 12;
719
+ m + l > u && (m = t - l - 12), m + l > u && (m = u - l), m < d && (m = d), p + c > n - o && (p = n - c - o), p < o && (p = o), this.el.style.left = `${m}px`, this.el.style.top = `${p}px`, this.el.style.maxHeight = `${n - p - o}px`;
506
720
  }
507
721
  buildHTML(t) {
508
722
  return `
@@ -513,44 +727,50 @@ class qt {
513
727
  </svg>
514
728
  </span>
515
729
  <div class="mtb-clarify-titles">
516
- <div class="mtb-clarify-title">${d(t.clarify.title)}</div>
517
- <div class="mtb-clarify-subtitle">${d(t.clarify.subtitle)}</div>
730
+ <div class="mtb-clarify-title">${h(t.clarify.title)}</div>
731
+ <div class="mtb-clarify-subtitle">${h(t.clarify.subtitle)}</div>
518
732
  </div>
519
- <button class="mtb-clarify-close" type="button" title="${d(t.clarify.skip)}" aria-label="${d(t.clarify.skip)}">
733
+ <button class="mtb-clarify-close" type="button" title="${h(t.clarify.skip)}" aria-label="${h(t.clarify.skip)}">
520
734
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
521
735
  <path d="M18 6L6 18M6 6l12 12"/>
522
736
  </svg>
523
737
  </button>
524
738
  </div>
525
739
  <div class="mtb-clarify-messages"></div>
526
- <div class="mtb-clarify-footer">
527
- <textarea class="mtb-clarify-input" rows="1" placeholder="${d(t.clarify.placeholder)}"></textarea>
528
- <div class="mtb-clarify-actions">
529
- <button class="mtb-clarify-skip" type="button">${d(t.clarify.skip)}</button>
530
- <button class="mtb-clarify-send" type="button" disabled>
531
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
532
- <line x1="22" y1="2" x2="11" y2="13"/>
533
- <polygon points="22 2 15 22 11 13 2 9 22 2"/>
534
- </svg>
535
- <span>${d(t.clarify.send)}</span>
536
- </button>
537
- </div>
740
+ <div class="mtb-clarify-footer">${this.buildConversationControls(t)}</div>
741
+ `;
742
+ }
743
+ buildConversationControls(t) {
744
+ return `
745
+ <textarea class="mtb-clarify-input" rows="1" placeholder="${h(t.clarify.placeholder)}"></textarea>
746
+ <div class="mtb-clarify-actions">
747
+ <button class="mtb-clarify-skip" type="button">${h(t.clarify.skip)}</button>
748
+ <button class="mtb-clarify-send" type="button" disabled>
749
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
750
+ <line x1="22" y1="2" x2="11" y2="13"/>
751
+ <polygon points="22 2 15 22 11 13 2 9 22 2"/>
752
+ </svg>
753
+ <span>${h(t.clarify.send)}</span>
754
+ </button>
538
755
  </div>
539
756
  `;
540
757
  }
541
758
  bindEvents() {
542
- const t = () => {
543
- this.stopPolling(), this.finalize();
544
- };
545
- this.el.querySelector(".mtb-clarify-skip").addEventListener("click", t), this.el.querySelector(".mtb-clarify-close").addEventListener("click", t), this.inputEl.addEventListener("input", () => {
759
+ this.el.querySelector(".mtb-clarify-close").addEventListener("click", () => this.skipAndFinalize()), this.bindConversationControls();
760
+ }
761
+ bindConversationControls() {
762
+ this.inputEl = this.el.querySelector(".mtb-clarify-input"), this.sendBtn = this.el.querySelector(".mtb-clarify-send"), this.el.querySelector(".mtb-clarify-skip").addEventListener("click", () => this.skipAndFinalize()), this.inputEl.addEventListener("input", () => {
546
763
  this.sendBtn.disabled = !this.inputEl.value.trim();
547
- }), this.inputEl.addEventListener("keydown", (e) => {
548
- e.isComposing || e.keyCode === 229 || e.key === "Enter" && !e.shiftKey && (e.preventDefault(), this.sendMessage());
764
+ }), this.inputEl.addEventListener("keydown", (t) => {
765
+ t.isComposing || t.keyCode === 229 || t.key === "Enter" && !t.shiftKey && (t.preventDefault(), this.sendMessage());
549
766
  }), this.sendBtn.addEventListener("click", () => this.sendMessage());
550
767
  }
768
+ skipAndFinalize() {
769
+ this.stopPolling(), this.finalize();
770
+ }
551
771
  async startConversation() {
552
772
  if (this.preloadedResult) {
553
- this.renderConversation(this.preloadedResult.messages, this.preloadedResult.done), this.preloadedResult.done && this.handleDone();
773
+ this.applyResult(this.preloadedResult);
554
774
  return;
555
775
  }
556
776
  if (this.pendingClarification) {
@@ -558,7 +778,7 @@ class qt {
558
778
  try {
559
779
  const t = await this.pendingClarification;
560
780
  if (this.destroyed) return;
561
- t ? (this.renderConversation(t.messages, t.done), t.done ? this.handleDone() : this.startPolling()) : await this.runInitialTurnViaPolling();
781
+ t ? this.applyResult(t) || this.startPolling() : await this.runInitialTurnViaPolling();
562
782
  } catch {
563
783
  if (this.destroyed) return;
564
784
  await this.runInitialTurnViaPolling();
@@ -591,7 +811,7 @@ class qt {
591
811
  (e) => this.appendStreamDelta(e)
592
812
  );
593
813
  if (this.destroyed) return;
594
- this.endStreamingBubble(), this.renderConversation(t.messages, t.done), t.done ? this.handleDone() : this.startPolling();
814
+ this.endStreamingBubble(), this.applyResult(t) || this.startPolling();
595
815
  } catch {
596
816
  if (this.destroyed) return;
597
817
  this.endStreamingBubble(), await this.runInitialTurnViaPolling();
@@ -604,10 +824,10 @@ class qt {
604
824
  this.submissionToken
605
825
  );
606
826
  if (this.destroyed) return;
607
- this.renderConversation(t.messages, t.done), t.done ? this.handleDone() : this.startPolling();
827
+ this.applyResult(t) || this.startPolling();
608
828
  } catch {
609
829
  if (this.destroyed) return;
610
- this.handleDone();
830
+ this.handleFailure();
611
831
  }
612
832
  }
613
833
  async runAnswerTurn(t) {
@@ -616,7 +836,7 @@ class qt {
616
836
  this.submissionToken,
617
837
  t
618
838
  );
619
- this.destroyed || (this.renderConversation(e.messages, e.done), e.done ? this.handleDone() : this.startPolling());
839
+ this.destroyed || this.applyResult(e) || this.startPolling();
620
840
  }
621
841
  showError() {
622
842
  const t = this.el.querySelector(".mtb-clarify-footer"), e = document.createElement("div");
@@ -632,14 +852,14 @@ class qt {
632
852
  this.streamingBubble = null;
633
853
  }
634
854
  startPolling() {
635
- this.stopPolling(), this.pollDeadline = Date.now() + Ot, this.pollTimer = setInterval(() => this.poll(), Ut);
855
+ this.stopPolling(), this.pollDeadline = Date.now() + ye, this.pollTimer = setInterval(() => this.poll(), ge);
636
856
  }
637
857
  stopPolling() {
638
858
  this.pollTimer !== null && (clearInterval(this.pollTimer), this.pollTimer = null);
639
859
  }
640
860
  async poll() {
641
861
  if (Date.now() > this.pollDeadline) {
642
- this.stopPolling(), this.handleDone();
862
+ this.stopPolling(), this.handleFailure();
643
863
  return;
644
864
  }
645
865
  try {
@@ -648,15 +868,61 @@ class qt {
648
868
  this.submissionToken
649
869
  );
650
870
  if (this.destroyed) return;
651
- this.renderConversation(t.messages, t.done), t.done && (this.stopPolling(), this.handleDone());
871
+ this.applyResult(t) && this.stopPolling();
652
872
  } catch {
653
873
  if (this.destroyed) return;
654
- this.stopPolling(), this.handleDone();
874
+ this.stopPolling(), this.handleFailure();
655
875
  }
656
876
  }
657
877
  handleDone() {
658
878
  this.done || (this.done = !0, this.stopPolling(), this.removeThinking(), this.showFinalizeButton());
659
879
  }
880
+ handleFailure() {
881
+ this.done || (this.done = !0, this.stopPolling(), this.removeThinking(), this.showClarificationFailureActions());
882
+ }
883
+ showClarificationFailureActions() {
884
+ const t = this.el.querySelector(".mtb-clarify-footer");
885
+ t.innerHTML = `
886
+ <div class="mtb-clarify-error">${h(this.i18n.clarify.error)}</div>
887
+ <div class="mtb-clarify-actions">
888
+ <button class="mtb-clarify-fallback" type="button">${h(this.i18n.clarify.send_feedback)}</button>
889
+ <button class="mtb-clarify-retry" type="button">${h(this.i18n.clarify.retry)}</button>
890
+ </div>
891
+ `, t.querySelector(".mtb-clarify-fallback").addEventListener("click", () => this.skipAndFinalize()), t.querySelector(".mtb-clarify-retry").addEventListener("click", () => {
892
+ this.destroyed || this.retryClarification();
893
+ });
894
+ }
895
+ async retryClarification() {
896
+ if (!(this.sending || this.destroyed)) {
897
+ this.sending = !0, this.done = !1, this.showConversationControls(), this.inputEl.disabled = !0, this.sendBtn.disabled = !0, this.renderConversation(this.lastMessages, !1);
898
+ try {
899
+ const t = await this.apiClient.getClarification(this.submissionSessionId, this.submissionToken);
900
+ if (this.destroyed) return;
901
+ let e = t;
902
+ if (t.status === "failed" ? e = await this.apiClient.retryClarification(this.submissionSessionId, this.submissionToken) : t.status === "idle" && (e = await this.apiClient.startClarification(this.submissionSessionId, this.submissionToken)), this.destroyed) return;
903
+ this.applyResult(e) || (this.showConversationControls(), this.startPolling());
904
+ } catch {
905
+ if (this.destroyed) return;
906
+ this.handleFailure();
907
+ } finally {
908
+ this.sending = !1;
909
+ }
910
+ }
911
+ }
912
+ showConversationControls() {
913
+ const t = this.el.querySelector(".mtb-clarify-footer");
914
+ t.innerHTML = this.buildConversationControls(this.i18n), this.bindConversationControls();
915
+ }
916
+ // Returns true when the exchange has settled — the caller uses that to decide
917
+ // whether it still needs to poll.
918
+ applyResult(t) {
919
+ this.renderConversation(t.messages, t.done);
920
+ const e = "status" in t ? t.status : void 0;
921
+ return ("status" in t ? t.status === "failed" : t.failed === !0) ? (this.handleFailure(), !0) : t.done ? (this.handleDone(), !0) : e === "awaiting_response" ? (this.stopPolling(), this.removeThinking(), this.enableInput(), !0) : !1;
922
+ }
923
+ enableInput() {
924
+ this.el.contains(this.inputEl) || this.showConversationControls(), this.inputEl.disabled = !1, this.sendBtn.disabled = !this.inputEl.value.trim();
925
+ }
660
926
  showFinalizeButton() {
661
927
  const t = this.el.querySelector(".mtb-clarify-footer");
662
928
  t.innerHTML = `
@@ -665,28 +931,43 @@ class qt {
665
931
  <line x1="22" y1="2" x2="11" y2="13"/>
666
932
  <polygon points="22 2 15 22 11 13 2 9 22 2"/>
667
933
  </svg>
668
- <span>${d(this.i18n.clarify.send_feedback)}</span>
934
+ <span>${h(this.i18n.clarify.send_feedback)}</span>
669
935
  </button>
670
936
  `, t.querySelector(".mtb-clarify-send-feedback").addEventListener("click", () => {
671
937
  this.destroyed || this.finalize();
672
938
  });
673
939
  }
674
940
  async finalize() {
675
- if (!(this.finalizing || this.destroyed)) {
941
+ if (!(this.finalizing || this.destroyed || this.unrecoverable)) {
676
942
  this.finalizing = !0, this.el.querySelectorAll("button").forEach((t) => {
677
943
  t.disabled = !0;
678
944
  });
679
945
  try {
680
946
  await this.onFinalize();
681
- } catch {
947
+ } catch (t) {
682
948
  if (this.destroyed) return;
683
- this.finalizing = !1, this.clearError(), this.showError(), this.showRetryButton();
949
+ if (this.finalizing = !1, this.clearError(), he(t)) {
950
+ this.showUnrecoverable();
951
+ return;
952
+ }
953
+ this.showFinalizeRetry();
684
954
  }
685
955
  }
686
956
  }
687
- showRetryButton() {
957
+ showUnrecoverable() {
958
+ this.unrecoverable = !0, this.stopPolling();
959
+ const t = this.el.querySelector(".mtb-clarify-footer");
960
+ t.innerHTML = `<div class="mtb-clarify-error">${h(this.i18n.clarify.expired)}</div>`;
961
+ }
962
+ // Renders the reason and the retry together: replacing the footer wholesale is
963
+ // what used to discard the error message showError() had just prepended, so the
964
+ // reporter saw a bare Retry button with no explanation.
965
+ showFinalizeRetry() {
688
966
  const t = this.el.querySelector(".mtb-clarify-footer");
689
- t.innerHTML = `<button class="mtb-clarify-retry" type="button">${d(this.i18n.clarify.retry)}</button>`, t.querySelector(".mtb-clarify-retry").addEventListener("click", () => {
967
+ t.innerHTML = `
968
+ <div class="mtb-clarify-error">${h(this.i18n.error.submit)}</div>
969
+ <button class="mtb-clarify-send-feedback mtb-clarify-retry" type="button">${h(this.i18n.clarify.retry)}</button>
970
+ `, t.querySelector(".mtb-clarify-retry").addEventListener("click", () => {
690
971
  this.destroyed || this.finalize();
691
972
  });
692
973
  }
@@ -717,8 +998,8 @@ class qt {
717
998
  this.destroyed = !0, this.stopPolling(), this.el.remove();
718
999
  }
719
1000
  }
720
- const Nt = 5e3, Wt = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
721
- class Vt {
1001
+ const ke = 5e3, Se = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1002
+ class Ee {
722
1003
  constructor(t, e, r, s, n) {
723
1004
  this.messages = e, this.el = t.el("div", "mtb-success"), this.el.style.right = "20px", this.el.style.bottom = "20px";
724
1005
  const o = n?.skipFollowup ? e.success.title_no_ai : e.success.title, a = n?.skipFollowup ? e.success.message_no_ai : e.success.message, l = s ? `<button class="mtb-view-feedback-link">${e.success.view_feedback} <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg></button>` : "", c = n?.emailCapture ? `
@@ -732,7 +1013,7 @@ class Vt {
732
1013
  </div>` : "";
733
1014
  this.el.innerHTML = `
734
1015
  <div class="mtb-success-icon">
735
- <svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="${D}" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
1016
+ <svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="${O}" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
736
1017
  <polyline points="20 6 9 17 4 12"/>
737
1018
  </svg>
738
1019
  </div>
@@ -741,12 +1022,12 @@ class Vt {
741
1022
  ${c}
742
1023
  ${l}
743
1024
  <button class="mtb-close-link">${e.success.close}</button>
744
- `, t.append(this.el), this.el.querySelector(".mtb-close-link").addEventListener("click", r), s && this.el.querySelector(".mtb-view-feedback-link").addEventListener("click", s), n?.emailCapture ? this.bindEmailCapture(n.emailCapture.onSubmit) : setTimeout(() => r(), Nt);
1025
+ `, t.append(this.el), this.el.querySelector(".mtb-close-link").addEventListener("click", r), s && this.el.querySelector(".mtb-view-feedback-link").addEventListener("click", s), n?.emailCapture ? this.bindEmailCapture(n.emailCapture.onSubmit) : setTimeout(() => r(), ke);
745
1026
  }
746
1027
  bindEmailCapture(t) {
747
1028
  const e = this.el.querySelector(".mtb-email-input"), r = this.el.querySelector(".mtb-email-submit"), s = this.el.querySelector(".mtb-email-error"), n = async () => {
748
1029
  const o = e.value.trim();
749
- if (!Wt.test(o)) {
1030
+ if (!Se.test(o)) {
750
1031
  e.classList.add("mtb-email-invalid");
751
1032
  return;
752
1033
  }
@@ -760,7 +1041,7 @@ class Vt {
760
1041
  this.el.remove();
761
1042
  }
762
1043
  }
763
- function Yt(i, t) {
1044
+ function Ce(i, t) {
764
1045
  if (i.match(/^[a-z]+:\/\//i))
765
1046
  return i;
766
1047
  if (i.match(/^\/\//))
@@ -770,7 +1051,7 @@ function Yt(i, t) {
770
1051
  const e = document.implementation.createHTMLDocument(), r = e.createElement("base"), s = e.createElement("a");
771
1052
  return e.head.appendChild(r), e.body.appendChild(s), t && (r.href = t), s.href = i, s.href;
772
1053
  }
773
- const Kt = /* @__PURE__ */ (() => {
1054
+ const _e = /* @__PURE__ */ (() => {
774
1055
  let i = 0;
775
1056
  const t = () => (
776
1057
  // eslint-disable-next-line no-bitwise
@@ -778,33 +1059,33 @@ const Kt = /* @__PURE__ */ (() => {
778
1059
  );
779
1060
  return () => (i += 1, `u${t()}${i}`);
780
1061
  })();
781
- function x(i) {
1062
+ function v(i) {
782
1063
  const t = [];
783
1064
  for (let e = 0, r = i.length; e < r; e++)
784
1065
  t.push(i[e]);
785
1066
  return t;
786
1067
  }
787
- let v = null;
788
- function lt(i = {}) {
789
- return v || (i.includeStyleProperties ? (v = i.includeStyleProperties, v) : (v = x(window.getComputedStyle(document.documentElement)), v));
1068
+ let x = null;
1069
+ function Mt(i = {}) {
1070
+ return x || (i.includeStyleProperties ? (x = i.includeStyleProperties, x) : (x = v(window.getComputedStyle(document.documentElement)), x));
790
1071
  }
791
- function M(i, t) {
1072
+ function $(i, t) {
792
1073
  const r = (i.ownerDocument.defaultView || window).getComputedStyle(i).getPropertyValue(t);
793
1074
  return r ? parseFloat(r.replace("px", "")) : 0;
794
1075
  }
795
- function Xt(i) {
796
- const t = M(i, "border-left-width"), e = M(i, "border-right-width");
1076
+ function Te(i) {
1077
+ const t = $(i, "border-left-width"), e = $(i, "border-right-width");
797
1078
  return i.clientWidth + t + e;
798
1079
  }
799
- function Gt(i) {
800
- const t = M(i, "border-top-width"), e = M(i, "border-bottom-width");
1080
+ function Me(i) {
1081
+ const t = $(i, "border-top-width"), e = $(i, "border-bottom-width");
801
1082
  return i.clientHeight + t + e;
802
1083
  }
803
- function ct(i, t = {}) {
804
- const e = t.width || Xt(i), r = t.height || Gt(i);
1084
+ function Lt(i, t = {}) {
1085
+ const e = t.width || Te(i), r = t.height || Me(i);
805
1086
  return { width: e, height: r };
806
1087
  }
807
- function Jt() {
1088
+ function Le() {
808
1089
  let i, t;
809
1090
  try {
810
1091
  t = process;
@@ -813,11 +1094,11 @@ function Jt() {
813
1094
  const e = t && t.env ? t.env.devicePixelRatio : null;
814
1095
  return e && (i = parseInt(e, 10), Number.isNaN(i) && (i = 1)), i || window.devicePixelRatio || 1;
815
1096
  }
816
- const p = 16384;
817
- function Qt(i) {
818
- (i.width > p || i.height > p) && (i.width > p && i.height > p ? i.width > i.height ? (i.height *= p / i.width, i.width = p) : (i.width *= p / i.height, i.height = p) : i.width > p ? (i.height *= p / i.width, i.width = p) : (i.width *= p / i.height, i.height = p));
1097
+ const b = 16384;
1098
+ function Ae(i) {
1099
+ (i.width > b || i.height > b) && (i.width > b && i.height > b ? i.width > i.height ? (i.height *= b / i.width, i.width = b) : (i.width *= b / i.height, i.height = b) : i.width > b ? (i.height *= b / i.width, i.width = b) : (i.width *= b / i.height, i.height = b));
819
1100
  }
820
- function P(i) {
1101
+ function F(i) {
821
1102
  return new Promise((t, e) => {
822
1103
  const r = new Image();
823
1104
  r.onload = () => {
@@ -827,12 +1108,12 @@ function P(i) {
827
1108
  }, r.onerror = e, r.crossOrigin = "anonymous", r.decoding = "async", r.src = i;
828
1109
  });
829
1110
  }
830
- async function Zt(i) {
1111
+ async function Pe(i) {
831
1112
  return Promise.resolve().then(() => new XMLSerializer().serializeToString(i)).then(encodeURIComponent).then((t) => `data:image/svg+xml;charset=utf-8,${t}`);
832
1113
  }
833
- async function te(i, t, e) {
1114
+ async function Re(i, t, e) {
834
1115
  const r = "http://www.w3.org/2000/svg", s = document.createElementNS(r, "svg"), n = document.createElementNS(r, "foreignObject");
835
- return s.setAttribute("width", `${t}`), s.setAttribute("height", `${e}`), s.setAttribute("viewBox", `0 0 ${t} ${e}`), n.setAttribute("width", "100%"), n.setAttribute("height", "100%"), n.setAttribute("x", "0"), n.setAttribute("y", "0"), n.setAttribute("externalResourcesRequired", "true"), s.appendChild(n), n.appendChild(i), Zt(s);
1116
+ return s.setAttribute("width", `${t}`), s.setAttribute("height", `${e}`), s.setAttribute("viewBox", `0 0 ${t} ${e}`), n.setAttribute("width", "100%"), n.setAttribute("height", "100%"), n.setAttribute("x", "0"), n.setAttribute("y", "0"), n.setAttribute("externalResourcesRequired", "true"), s.appendChild(n), n.appendChild(i), Pe(s);
836
1117
  }
837
1118
  const f = (i, t) => {
838
1119
  if (i instanceof t)
@@ -840,67 +1121,67 @@ const f = (i, t) => {
840
1121
  const e = Object.getPrototypeOf(i);
841
1122
  return e === null ? !1 : e.constructor.name === t.name || f(e, t);
842
1123
  };
843
- function ee(i) {
1124
+ function De(i) {
844
1125
  const t = i.getPropertyValue("content");
845
1126
  return `${i.cssText} content: '${t.replace(/'|"/g, "")}';`;
846
1127
  }
847
- function ie(i, t) {
848
- return lt(t).map((e) => {
1128
+ function Ie(i, t) {
1129
+ return Mt(t).map((e) => {
849
1130
  const r = i.getPropertyValue(e), s = i.getPropertyPriority(e);
850
1131
  return `${e}: ${r}${s ? " !important" : ""};`;
851
1132
  }).join(" ");
852
1133
  }
853
- function re(i, t, e, r) {
854
- const s = `.${i}:${t}`, n = e.cssText ? ee(e) : ie(e, r);
1134
+ function He(i, t, e, r) {
1135
+ const s = `.${i}:${t}`, n = e.cssText ? De(e) : Ie(e, r);
855
1136
  return document.createTextNode(`${s}{${n}}`);
856
1137
  }
857
- function N(i, t, e, r) {
1138
+ function st(i, t, e, r) {
858
1139
  const s = window.getComputedStyle(i, e), n = s.getPropertyValue("content");
859
1140
  if (n === "" || n === "none")
860
1141
  return;
861
- const o = Kt();
1142
+ const o = _e();
862
1143
  try {
863
1144
  t.className = `${t.className} ${o}`;
864
1145
  } catch {
865
1146
  return;
866
1147
  }
867
1148
  const a = document.createElement("style");
868
- a.appendChild(re(o, e, s, r)), t.appendChild(a);
1149
+ a.appendChild(He(o, e, s, r)), t.appendChild(a);
869
1150
  }
870
- function se(i, t, e) {
871
- N(i, t, ":before", e), N(i, t, ":after", e);
1151
+ function $e(i, t, e) {
1152
+ st(i, t, ":before", e), st(i, t, ":after", e);
872
1153
  }
873
- const W = "application/font-woff", V = "image/jpeg", ne = {
874
- woff: W,
875
- woff2: W,
1154
+ const nt = "application/font-woff", ot = "image/jpeg", Fe = {
1155
+ woff: nt,
1156
+ woff2: nt,
876
1157
  ttf: "application/font-truetype",
877
1158
  eot: "application/vnd.ms-fontobject",
878
1159
  png: "image/png",
879
- jpg: V,
880
- jpeg: V,
1160
+ jpg: ot,
1161
+ jpeg: ot,
881
1162
  gif: "image/gif",
882
1163
  tiff: "image/tiff",
883
1164
  svg: "image/svg+xml",
884
1165
  webp: "image/webp"
885
1166
  };
886
- function oe(i) {
1167
+ function Be(i) {
887
1168
  const t = /\.([^./]*?)$/g.exec(i);
888
1169
  return t ? t[1] : "";
889
1170
  }
890
- function U(i) {
891
- const t = oe(i).toLowerCase();
892
- return ne[t] || "";
1171
+ function Q(i) {
1172
+ const t = Be(i).toLowerCase();
1173
+ return Fe[t] || "";
893
1174
  }
894
- function ae(i) {
1175
+ function Ue(i) {
895
1176
  return i.split(/,/)[1];
896
1177
  }
897
- function I(i) {
1178
+ function V(i) {
898
1179
  return i.search(/^(data:)/) !== -1;
899
1180
  }
900
- function le(i, t) {
1181
+ function Oe(i, t) {
901
1182
  return `data:${t};base64,${i}`;
902
1183
  }
903
- async function dt(i, t, e) {
1184
+ async function At(i, t, e) {
904
1185
  const r = await fetch(i, t);
905
1186
  if (r.status === 404)
906
1187
  throw new Error(`Resource "${r.url}" not found`);
@@ -916,86 +1197,86 @@ async function dt(i, t, e) {
916
1197
  }, a.readAsDataURL(s);
917
1198
  });
918
1199
  }
919
- const H = {};
920
- function ce(i, t, e) {
1200
+ const j = {};
1201
+ function ze(i, t, e) {
921
1202
  let r = i.replace(/\?.*/, "");
922
1203
  return e && (r = i), /ttf|otf|eot|woff2?/i.test(r) && (r = r.replace(/.*\//, "")), t ? `[${t}]${r}` : r;
923
1204
  }
924
- async function O(i, t, e) {
925
- const r = ce(i, t, e.includeQueryParams);
926
- if (H[r] != null)
927
- return H[r];
1205
+ async function Z(i, t, e) {
1206
+ const r = ze(i, t, e.includeQueryParams);
1207
+ if (j[r] != null)
1208
+ return j[r];
928
1209
  e.cacheBust && (i += (/\?/.test(i) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime());
929
1210
  let s;
930
1211
  try {
931
- const n = await dt(i, e.fetchRequestInit, ({ res: o, result: a }) => (t || (t = o.headers.get("Content-Type") || ""), ae(a)));
932
- s = le(n, t);
1212
+ const n = await At(i, e.fetchRequestInit, ({ res: o, result: a }) => (t || (t = o.headers.get("Content-Type") || ""), Ue(a)));
1213
+ s = Oe(n, t);
933
1214
  } catch (n) {
934
1215
  s = e.imagePlaceholder || "";
935
1216
  let o = `Failed to fetch resource: ${i}`;
936
1217
  n && (o = typeof n == "string" ? n : n.message), o && console.warn(o);
937
1218
  }
938
- return H[r] = s, s;
1219
+ return j[r] = s, s;
939
1220
  }
940
- async function de(i) {
1221
+ async function je(i) {
941
1222
  const t = i.toDataURL();
942
- return t === "data:," ? i.cloneNode(!1) : P(t);
1223
+ return t === "data:," ? i.cloneNode(!1) : F(t);
943
1224
  }
944
- async function he(i, t) {
1225
+ async function qe(i, t) {
945
1226
  if (i.currentSrc) {
946
1227
  const n = document.createElement("canvas"), o = n.getContext("2d");
947
1228
  n.width = i.clientWidth, n.height = i.clientHeight, o?.drawImage(i, 0, 0, n.width, n.height);
948
1229
  const a = n.toDataURL();
949
- return P(a);
1230
+ return F(a);
950
1231
  }
951
- const e = i.poster, r = U(e), s = await O(e, r, t);
952
- return P(s);
1232
+ const e = i.poster, r = Q(e), s = await Z(e, r, t);
1233
+ return F(s);
953
1234
  }
954
- async function ue(i, t) {
1235
+ async function Ne(i, t) {
955
1236
  var e;
956
1237
  try {
957
1238
  if (!((e = i?.contentDocument) === null || e === void 0) && e.body)
958
- return await A(i.contentDocument.body, t, !0);
1239
+ return await z(i.contentDocument.body, t, !0);
959
1240
  } catch {
960
1241
  }
961
1242
  return i.cloneNode(!1);
962
1243
  }
963
- async function me(i, t) {
964
- return f(i, HTMLCanvasElement) ? de(i) : f(i, HTMLVideoElement) ? he(i, t) : f(i, HTMLIFrameElement) ? ue(i, t) : i.cloneNode(ht(i));
1244
+ async function We(i, t) {
1245
+ return f(i, HTMLCanvasElement) ? je(i) : f(i, HTMLVideoElement) ? qe(i, t) : f(i, HTMLIFrameElement) ? Ne(i, t) : i.cloneNode(Pt(i));
965
1246
  }
966
- const fe = (i) => i.tagName != null && i.tagName.toUpperCase() === "SLOT", ht = (i) => i.tagName != null && i.tagName.toUpperCase() === "SVG";
967
- async function pe(i, t, e) {
1247
+ const Ve = (i) => i.tagName != null && i.tagName.toUpperCase() === "SLOT", Pt = (i) => i.tagName != null && i.tagName.toUpperCase() === "SVG";
1248
+ async function Ye(i, t, e) {
968
1249
  var r, s;
969
- if (ht(t))
1250
+ if (Pt(t))
970
1251
  return t;
971
1252
  let n = [];
972
- return fe(i) && i.assignedNodes ? n = x(i.assignedNodes()) : f(i, HTMLIFrameElement) && (!((r = i.contentDocument) === null || r === void 0) && r.body) ? n = x(i.contentDocument.body.childNodes) : n = x(((s = i.shadowRoot) !== null && s !== void 0 ? s : i).childNodes), n.length === 0 || f(i, HTMLVideoElement) || await n.reduce((o, a) => o.then(() => A(a, e)).then((l) => {
1253
+ return Ve(i) && i.assignedNodes ? n = v(i.assignedNodes()) : f(i, HTMLIFrameElement) && (!((r = i.contentDocument) === null || r === void 0) && r.body) ? n = v(i.contentDocument.body.childNodes) : n = v(((s = i.shadowRoot) !== null && s !== void 0 ? s : i).childNodes), n.length === 0 || f(i, HTMLVideoElement) || await n.reduce((o, a) => o.then(() => z(a, e)).then((l) => {
973
1254
  l && t.appendChild(l);
974
1255
  }), Promise.resolve()), t;
975
1256
  }
976
- function be(i, t, e) {
1257
+ function Xe(i, t, e) {
977
1258
  const r = t.style;
978
1259
  if (!r)
979
1260
  return;
980
1261
  const s = window.getComputedStyle(i);
981
- s.cssText ? (r.cssText = s.cssText, r.transformOrigin = s.transformOrigin) : lt(e).forEach((n) => {
1262
+ s.cssText ? (r.cssText = s.cssText, r.transformOrigin = s.transformOrigin) : Mt(e).forEach((n) => {
982
1263
  let o = s.getPropertyValue(n);
983
1264
  n === "font-size" && o.endsWith("px") && (o = `${Math.floor(parseFloat(o.substring(0, o.length - 2))) - 0.1}px`), f(i, HTMLIFrameElement) && n === "display" && o === "inline" && (o = "block"), n === "d" && t.getAttribute("d") && (o = `path(${t.getAttribute("d")})`), r.setProperty(n, o, s.getPropertyPriority(n));
984
1265
  });
985
1266
  }
986
- function ge(i, t) {
1267
+ function Ke(i, t) {
987
1268
  f(i, HTMLTextAreaElement) && (t.innerHTML = i.value), f(i, HTMLInputElement) && t.setAttribute("value", i.value);
988
1269
  }
989
- function ye(i, t) {
1270
+ function Ge(i, t) {
990
1271
  if (f(i, HTMLSelectElement)) {
991
1272
  const e = t, r = Array.from(e.children).find((s) => i.value === s.getAttribute("value"));
992
1273
  r && r.setAttribute("selected", "");
993
1274
  }
994
1275
  }
995
- function we(i, t, e) {
996
- return f(t, Element) && (be(i, t, e), se(i, t, e), ge(i, t), ye(i, t)), t;
1276
+ function Je(i, t, e) {
1277
+ return f(t, Element) && (Xe(i, t, e), $e(i, t, e), Ke(i, t), Ge(i, t)), t;
997
1278
  }
998
- async function xe(i, t) {
1279
+ async function Qe(i, t) {
999
1280
  const e = i.querySelectorAll ? i.querySelectorAll("use") : [];
1000
1281
  if (e.length === 0)
1001
1282
  return i;
@@ -1004,7 +1285,7 @@ async function xe(i, t) {
1004
1285
  const a = e[n].getAttribute("xlink:href");
1005
1286
  if (a) {
1006
1287
  const l = i.querySelector(a), c = document.querySelector(a);
1007
- !l && c && !r[a] && (r[a] = await A(c, t, !0));
1288
+ !l && c && !r[a] && (r[a] = await z(c, t, !0));
1008
1289
  }
1009
1290
  }
1010
1291
  const s = Object.values(r);
@@ -1019,31 +1300,31 @@ async function xe(i, t) {
1019
1300
  }
1020
1301
  return i;
1021
1302
  }
1022
- async function A(i, t, e) {
1023
- return !e && t.filter && !t.filter(i) ? null : Promise.resolve(i).then((r) => me(r, t)).then((r) => pe(i, r, t)).then((r) => we(i, r, t)).then((r) => xe(r, t));
1303
+ async function z(i, t, e) {
1304
+ return !e && t.filter && !t.filter(i) ? null : Promise.resolve(i).then((r) => We(r, t)).then((r) => Ye(i, r, t)).then((r) => Je(i, r, t)).then((r) => Qe(r, t));
1024
1305
  }
1025
- const ut = /url\((['"]?)([^'"]+?)\1\)/g, ve = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g, ke = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
1026
- function Se(i) {
1306
+ const Rt = /url\((['"]?)([^'"]+?)\1\)/g, Ze = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g, ti = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
1307
+ function ei(i) {
1027
1308
  const t = i.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
1028
1309
  return new RegExp(`(url\\(['"]?)(${t})(['"]?\\))`, "g");
1029
1310
  }
1030
- function Ee(i) {
1311
+ function ii(i) {
1031
1312
  const t = [];
1032
- return i.replace(ut, (e, r, s) => (t.push(s), e)), t.filter((e) => !I(e));
1313
+ return i.replace(Rt, (e, r, s) => (t.push(s), e)), t.filter((e) => !V(e));
1033
1314
  }
1034
- async function Ce(i, t, e, r, s) {
1315
+ async function ri(i, t, e, r, s) {
1035
1316
  try {
1036
- const n = e ? Yt(t, e) : t, o = U(t);
1317
+ const n = e ? Ce(t, e) : t, o = Q(t);
1037
1318
  let a;
1038
- return s || (a = await O(n, o, r)), i.replace(Se(t), `$1${a}$3`);
1319
+ return s || (a = await Z(n, o, r)), i.replace(ei(t), `$1${a}$3`);
1039
1320
  } catch {
1040
1321
  }
1041
1322
  return i;
1042
1323
  }
1043
- function _e(i, { preferredFontFormat: t }) {
1044
- return t ? i.replace(ke, (e) => {
1324
+ function si(i, { preferredFontFormat: t }) {
1325
+ return t ? i.replace(ti, (e) => {
1045
1326
  for (; ; ) {
1046
- const [r, , s] = ve.exec(e) || [];
1327
+ const [r, , s] = Ze.exec(e) || [];
1047
1328
  if (!s)
1048
1329
  return "";
1049
1330
  if (s === t)
@@ -1051,32 +1332,32 @@ function _e(i, { preferredFontFormat: t }) {
1051
1332
  }
1052
1333
  }) : i;
1053
1334
  }
1054
- function mt(i) {
1055
- return i.search(ut) !== -1;
1335
+ function Dt(i) {
1336
+ return i.search(Rt) !== -1;
1056
1337
  }
1057
- async function ft(i, t, e) {
1058
- if (!mt(i))
1338
+ async function It(i, t, e) {
1339
+ if (!Dt(i))
1059
1340
  return i;
1060
- const r = _e(i, e);
1061
- return Ee(r).reduce((n, o) => n.then((a) => Ce(a, o, t, e)), Promise.resolve(r));
1341
+ const r = si(i, e);
1342
+ return ii(r).reduce((n, o) => n.then((a) => ri(a, o, t, e)), Promise.resolve(r));
1062
1343
  }
1063
1344
  async function k(i, t, e) {
1064
1345
  var r;
1065
1346
  const s = (r = t.style) === null || r === void 0 ? void 0 : r.getPropertyValue(i);
1066
1347
  if (s) {
1067
- const n = await ft(s, null, e);
1348
+ const n = await It(s, null, e);
1068
1349
  return t.style.setProperty(i, n, t.style.getPropertyPriority(i)), !0;
1069
1350
  }
1070
1351
  return !1;
1071
1352
  }
1072
- async function Te(i, t) {
1353
+ async function ni(i, t) {
1073
1354
  await k("background", i, t) || await k("background-image", i, t), await k("mask", i, t) || await k("-webkit-mask", i, t) || await k("mask-image", i, t) || await k("-webkit-mask-image", i, t);
1074
1355
  }
1075
- async function Le(i, t) {
1356
+ async function oi(i, t) {
1076
1357
  const e = f(i, HTMLImageElement);
1077
- if (!(e && !I(i.src)) && !(f(i, SVGImageElement) && !I(i.href.baseVal)))
1358
+ if (!(e && !V(i.src)) && !(f(i, SVGImageElement) && !V(i.href.baseVal)))
1078
1359
  return;
1079
- const r = e ? i.src : i.href.baseVal, s = await O(r, U(r), t);
1360
+ const r = e ? i.src : i.href.baseVal, s = await Z(r, Q(r), t);
1080
1361
  await new Promise((n, o) => {
1081
1362
  i.onload = n, i.onerror = t.onImageErrorHandler ? (...l) => {
1082
1363
  try {
@@ -1089,14 +1370,14 @@ async function Le(i, t) {
1089
1370
  a.decode && (a.decode = n), a.loading === "lazy" && (a.loading = "eager"), e ? (i.srcset = "", i.src = s) : i.href.baseVal = s;
1090
1371
  });
1091
1372
  }
1092
- async function Me(i, t) {
1093
- const r = x(i.childNodes).map((s) => pt(s, t));
1373
+ async function ai(i, t) {
1374
+ const r = v(i.childNodes).map((s) => Ht(s, t));
1094
1375
  await Promise.all(r).then(() => i);
1095
1376
  }
1096
- async function pt(i, t) {
1097
- f(i, Element) && (await Te(i, t), await Le(i, t), await Me(i, t));
1377
+ async function Ht(i, t) {
1378
+ f(i, Element) && (await ni(i, t), await oi(i, t), await ai(i, t));
1098
1379
  }
1099
- function Pe(i, t) {
1380
+ function li(i, t) {
1100
1381
  const { style: e } = i;
1101
1382
  t.backgroundColor && (e.backgroundColor = t.backgroundColor), t.width && (e.width = `${t.width}px`), t.height && (e.height = `${t.height}px`);
1102
1383
  const r = t.style;
@@ -1104,23 +1385,23 @@ function Pe(i, t) {
1104
1385
  e[s] = r[s];
1105
1386
  }), i;
1106
1387
  }
1107
- const Y = {};
1108
- async function K(i) {
1109
- let t = Y[i];
1388
+ const at = {};
1389
+ async function lt(i) {
1390
+ let t = at[i];
1110
1391
  if (t != null)
1111
1392
  return t;
1112
1393
  const r = await (await fetch(i)).text();
1113
- return t = { url: i, cssText: r }, Y[i] = t, t;
1394
+ return t = { url: i, cssText: r }, at[i] = t, t;
1114
1395
  }
1115
- async function X(i, t) {
1396
+ async function ct(i, t) {
1116
1397
  let e = i.cssText;
1117
1398
  const r = /url\(["']?([^"')]+)["']?\)/g, n = (e.match(/url\([^)]+\)/g) || []).map(async (o) => {
1118
1399
  let a = o.replace(r, "$1");
1119
- return a.startsWith("https://") || (a = new URL(a, i.url).href), dt(a, t.fetchRequestInit, ({ result: l }) => (e = e.replace(o, `url(${l})`), [o, l]));
1400
+ return a.startsWith("https://") || (a = new URL(a, i.url).href), At(a, t.fetchRequestInit, ({ result: l }) => (e = e.replace(o, `url(${l})`), [o, l]));
1120
1401
  });
1121
1402
  return Promise.all(n).then(() => e);
1122
1403
  }
1123
- function G(i) {
1404
+ function dt(i) {
1124
1405
  if (i == null)
1125
1406
  return [];
1126
1407
  const t = [], e = /(\/\*[\s\S]*?\*\/)/gi;
@@ -1146,15 +1427,15 @@ function G(i) {
1146
1427
  }
1147
1428
  return t;
1148
1429
  }
1149
- async function Re(i, t) {
1430
+ async function ci(i, t) {
1150
1431
  const e = [], r = [];
1151
1432
  return i.forEach((s) => {
1152
1433
  if ("cssRules" in s)
1153
1434
  try {
1154
- x(s.cssRules || []).forEach((n, o) => {
1435
+ v(s.cssRules || []).forEach((n, o) => {
1155
1436
  if (n.type === CSSRule.IMPORT_RULE) {
1156
1437
  let a = o + 1;
1157
- const l = n.href, c = K(l).then((h) => X(h, t)).then((h) => G(h).forEach((u) => {
1438
+ const l = n.href, c = lt(l).then((d) => ct(d, t)).then((d) => dt(d).forEach((u) => {
1158
1439
  try {
1159
1440
  s.insertRule(u, u.startsWith("@import") ? a += 1 : s.cssRules.length);
1160
1441
  } catch (m) {
@@ -1163,15 +1444,15 @@ async function Re(i, t) {
1163
1444
  error: m
1164
1445
  });
1165
1446
  }
1166
- })).catch((h) => {
1167
- console.error("Error loading remote css", h.toString());
1447
+ })).catch((d) => {
1448
+ console.error("Error loading remote css", d.toString());
1168
1449
  });
1169
1450
  r.push(c);
1170
1451
  }
1171
1452
  });
1172
1453
  } catch (n) {
1173
1454
  const o = i.find((a) => a.href == null) || document.styleSheets[0];
1174
- s.href != null && r.push(K(s.href).then((a) => X(a, t)).then((a) => G(a).forEach((l) => {
1455
+ s.href != null && r.push(lt(s.href).then((a) => ct(a, t)).then((a) => dt(a).forEach((l) => {
1175
1456
  o.insertRule(l, o.cssRules.length);
1176
1457
  })).catch((a) => {
1177
1458
  console.error("Error loading remote stylesheet", a);
@@ -1180,7 +1461,7 @@ async function Re(i, t) {
1180
1461
  }), Promise.all(r).then(() => (i.forEach((s) => {
1181
1462
  if ("cssRules" in s)
1182
1463
  try {
1183
- x(s.cssRules || []).forEach((n) => {
1464
+ v(s.cssRules || []).forEach((n) => {
1184
1465
  e.push(n);
1185
1466
  });
1186
1467
  } catch (n) {
@@ -1188,100 +1469,164 @@ async function Re(i, t) {
1188
1469
  }
1189
1470
  }), e));
1190
1471
  }
1191
- function De(i) {
1192
- return i.filter((t) => t.type === CSSRule.FONT_FACE_RULE).filter((t) => mt(t.style.getPropertyValue("src")));
1472
+ function di(i) {
1473
+ return i.filter((t) => t.type === CSSRule.FONT_FACE_RULE).filter((t) => Dt(t.style.getPropertyValue("src")));
1193
1474
  }
1194
- async function Ae(i, t) {
1475
+ async function hi(i, t) {
1195
1476
  if (i.ownerDocument == null)
1196
1477
  throw new Error("Provided element is not within a Document");
1197
- const e = x(i.ownerDocument.styleSheets), r = await Re(e, t);
1198
- return De(r);
1478
+ const e = v(i.ownerDocument.styleSheets), r = await ci(e, t);
1479
+ return di(r);
1199
1480
  }
1200
- function bt(i) {
1481
+ function $t(i) {
1201
1482
  return i.trim().replace(/["']/g, "");
1202
1483
  }
1203
- function He(i) {
1484
+ function ui(i) {
1204
1485
  const t = /* @__PURE__ */ new Set();
1205
1486
  function e(r) {
1206
1487
  (r.style.fontFamily || getComputedStyle(r).fontFamily).split(",").forEach((n) => {
1207
- t.add(bt(n));
1488
+ t.add($t(n));
1208
1489
  }), Array.from(r.children).forEach((n) => {
1209
1490
  n instanceof HTMLElement && e(n);
1210
1491
  });
1211
1492
  }
1212
1493
  return e(i), t;
1213
1494
  }
1214
- async function Ie(i, t) {
1215
- const e = await Ae(i, t), r = He(i);
1216
- return (await Promise.all(e.filter((n) => r.has(bt(n.style.fontFamily))).map((n) => {
1495
+ async function mi(i, t) {
1496
+ const e = await hi(i, t), r = ui(i);
1497
+ return (await Promise.all(e.filter((n) => r.has($t(n.style.fontFamily))).map((n) => {
1217
1498
  const o = n.parentStyleSheet ? n.parentStyleSheet.href : null;
1218
- return ft(n.cssText, o, t);
1499
+ return It(n.cssText, o, t);
1219
1500
  }))).join(`
1220
1501
  `);
1221
1502
  }
1222
- async function $e(i, t) {
1223
- const e = t.fontEmbedCSS != null ? t.fontEmbedCSS : t.skipFonts ? null : await Ie(i, t);
1503
+ async function fi(i, t) {
1504
+ const e = t.fontEmbedCSS != null ? t.fontEmbedCSS : t.skipFonts ? null : await mi(i, t);
1224
1505
  if (e) {
1225
1506
  const r = document.createElement("style"), s = document.createTextNode(e);
1226
1507
  r.appendChild(s), i.firstChild ? i.insertBefore(r, i.firstChild) : i.appendChild(r);
1227
1508
  }
1228
1509
  }
1229
- async function Be(i, t = {}) {
1230
- const { width: e, height: r } = ct(i, t), s = await A(i, t, !0);
1231
- return await $e(s, t), await pt(s, t), Pe(s, t), await te(s, e, r);
1510
+ async function bi(i, t = {}) {
1511
+ const { width: e, height: r } = Lt(i, t), s = await z(i, t, !0);
1512
+ return await fi(s, t), await Ht(s, t), li(s, t), await Re(s, e, r);
1232
1513
  }
1233
- async function Fe(i, t = {}) {
1234
- const { width: e, height: r } = ct(i, t), s = await Be(i, t), n = await P(s), o = document.createElement("canvas"), a = o.getContext("2d"), l = t.pixelRatio || Jt(), c = t.canvasWidth || e, h = t.canvasHeight || r;
1235
- return o.width = c * l, o.height = h * l, t.skipAutoScale || Qt(o), o.style.width = `${c}`, o.style.height = `${h}`, t.backgroundColor && (a.fillStyle = t.backgroundColor, a.fillRect(0, 0, o.width, o.height)), a.drawImage(n, 0, 0, o.width, o.height), o;
1514
+ async function pi(i, t = {}) {
1515
+ const { width: e, height: r } = Lt(i, t), s = await bi(i, t), n = await F(s), o = document.createElement("canvas"), a = o.getContext("2d"), l = t.pixelRatio || Le(), c = t.canvasWidth || e, d = t.canvasHeight || r;
1516
+ return o.width = c * l, o.height = d * l, t.skipAutoScale || Ae(o), o.style.width = `${c}`, o.style.height = `${d}`, t.backgroundColor && (a.fillStyle = t.backgroundColor, a.fillRect(0, 0, o.width, o.height)), a.drawImage(n, 0, 0, o.width, o.height), o;
1236
1517
  }
1237
- async function Ue(i, t = {}) {
1238
- return (await Fe(i, t)).toDataURL("image/jpeg", t.quality || 1);
1518
+ async function gi(i, t = {}) {
1519
+ return (await pi(i, t)).toDataURL("image/jpeg", t.quality || 1);
1239
1520
  }
1240
- async function Oe(i = []) {
1521
+ const q = 400, N = 300, ht = 150, ut = 0.3, mt = 0.85;
1522
+ function yi(i) {
1523
+ let t = 1 / 0, e = 1 / 0, r = -1 / 0, s = -1 / 0;
1524
+ for (const n of i)
1525
+ if (n.type === "pin") {
1526
+ if (t = Math.min(t, n.x), e = Math.min(e, n.y), r = Math.max(r, n.x), s = Math.max(s, n.y), n.targetRect) {
1527
+ const o = n.targetRect;
1528
+ t = Math.min(t, o.left), e = Math.min(e, o.top), r = Math.max(r, o.left + o.width), s = Math.max(s, o.bottom);
1529
+ }
1530
+ } else if (n.type === "draw" && n.drawPath)
1531
+ for (const o of Ft(n.drawPath))
1532
+ for (const [a, l] of o)
1533
+ t = Math.min(t, a), e = Math.min(e, l), r = Math.max(r, a), s = Math.max(s, l);
1534
+ return !isFinite(t) || !isFinite(e) ? null : { minX: t, minY: e, maxX: r, maxY: s };
1535
+ }
1536
+ function wi(i, t, e) {
1537
+ const r = yi(i);
1538
+ if (!r) return null;
1539
+ const s = Math.max(ht, t * ut), n = Math.max(ht, e * ut);
1540
+ let o = r.minX - s, a = r.minY - n, l = r.maxX - r.minX + s * 2, c = r.maxY - r.minY + n * 2;
1541
+ return l < q && (o -= (q - l) / 2, l = q), c < N && (a -= (N - c) / 2, c = N), o = Math.max(0, o), a = Math.max(0, a), l = Math.min(l, t - o), c = Math.min(c, e - a), l >= t * mt && c >= e * mt ? null : {
1542
+ x: Math.round(o),
1543
+ y: Math.round(a),
1544
+ width: Math.round(l),
1545
+ height: Math.round(c)
1546
+ };
1547
+ }
1548
+ function vi(i, t) {
1549
+ const e = document.createElement("canvas");
1550
+ e.width = t.width, e.height = t.height;
1551
+ const r = e.getContext("2d");
1552
+ return r && r.drawImage(i, t.x, t.y, t.width, t.height, 0, 0, t.width, t.height), e;
1553
+ }
1554
+ async function xi(i = []) {
1241
1555
  try {
1242
- const t = await Ue(document.body, {
1556
+ const t = Ei(document.body), e = await gi(document.body, {
1243
1557
  quality: 0.85,
1244
1558
  pixelRatio: 1,
1245
1559
  backgroundColor: "#ffffff",
1246
1560
  skipFonts: !0,
1247
1561
  skipAutoScale: !1,
1248
- filter: (e) => !(e instanceof HTMLElement && e.id === "mtb-widget-host")
1562
+ filter: (r) => !(r instanceof HTMLElement && r.id === "mtb-widget-host")
1249
1563
  });
1250
1564
  if (i.length > 0) {
1251
- const e = await ze(t, i);
1252
- if (e) return e;
1565
+ const r = await ki(e, i, t);
1566
+ if (r) return r;
1253
1567
  }
1254
- return Ye(t);
1568
+ return Ti(e);
1255
1569
  } catch {
1256
1570
  return null;
1257
1571
  }
1258
1572
  }
1259
- async function ze(i, t) {
1260
- const e = document.createElement("canvas"), r = e.getContext("2d");
1261
- if (!r) return null;
1262
- const s = await We(i);
1573
+ async function ki(i, t, e) {
1574
+ const r = document.createElement("canvas"), s = r.getContext("2d");
1263
1575
  if (!s) return null;
1264
- e.width = s.naturalWidth || window.innerWidth, e.height = s.naturalHeight || window.innerHeight, r.drawImage(s, 0, 0);
1265
- const n = e.width / window.innerWidth, o = e.height / window.innerHeight;
1266
- let a = 0;
1267
- for (const l of t)
1268
- l.type === "draw" && l.drawPath ? je(r, l.drawPath, n, o) : l.type === "pin" && qe(r, l.x * n, l.y * o, ++a);
1269
- return Ve(e);
1270
- }
1271
- function je(i, t, e, r) {
1272
- i.save(), i.strokeStyle = D, i.lineWidth = 3.5, i.lineCap = "round", i.lineJoin = "round", i.shadowColor = "rgba(5,150,105,0.35)", i.shadowOffsetY = 1, i.shadowBlur = 2;
1273
- for (const s of Ne(t))
1274
- if (s.length !== 0) {
1275
- i.beginPath(), i.moveTo(s[0][0] * e, s[0][1] * r);
1276
- for (let n = 1; n < s.length; n++) i.lineTo(s[n][0] * e, s[n][1] * r);
1576
+ const n = await _i(i);
1577
+ if (!n) return null;
1578
+ r.width = n.naturalWidth || window.innerWidth, r.height = n.naturalHeight || window.innerHeight, s.drawImage(n, 0, 0);
1579
+ const o = r.width / e.width, a = r.height / e.height;
1580
+ let l = 0;
1581
+ for (const d of t)
1582
+ d.type === "draw" && d.drawPath ? Si(s, d.drawPath, e, o, a) : d.type === "pin" && Ci(
1583
+ s,
1584
+ (d.x - e.left) * o,
1585
+ (d.y - e.top) * a,
1586
+ ++l
1587
+ );
1588
+ const c = wi(t, window.innerWidth, window.innerHeight);
1589
+ if (c) {
1590
+ const d = Math.max(0, Math.round((c.x - e.left) * o)), u = Math.max(0, Math.round((c.y - e.top) * a)), m = Math.min(r.width, Math.round((c.x + c.width - e.left) * o)), p = Math.min(r.height, Math.round((c.y + c.height - e.top) * a)), g = {
1591
+ x: d,
1592
+ y: u,
1593
+ width: m - d,
1594
+ height: p - u
1595
+ };
1596
+ return ft(vi(r, g));
1597
+ }
1598
+ return ft(r);
1599
+ }
1600
+ function Si(i, t, e, r, s) {
1601
+ i.save(), i.strokeStyle = O, i.lineWidth = 3.5, i.lineCap = "round", i.lineJoin = "round", i.shadowColor = J(0.35), i.shadowOffsetY = 1, i.shadowBlur = 2;
1602
+ for (const n of Ft(t))
1603
+ if (n.length !== 0) {
1604
+ i.beginPath(), i.moveTo(
1605
+ (n[0][0] - e.left) * r,
1606
+ (n[0][1] - e.top) * s
1607
+ );
1608
+ for (let o = 1; o < n.length; o++)
1609
+ i.lineTo(
1610
+ (n[o][0] - e.left) * r,
1611
+ (n[o][1] - e.top) * s
1612
+ );
1277
1613
  i.stroke();
1278
1614
  }
1279
1615
  i.restore();
1280
1616
  }
1281
- function qe(i, t, e, r) {
1282
- i.save(), i.shadowColor = "rgba(5,150,105,0.45)", i.shadowOffsetY = 2, i.shadowBlur = 8, i.fillStyle = D, i.beginPath(), i.arc(t, e, 11, 0, Math.PI * 2), i.fill(), i.shadowColor = "transparent", i.lineWidth = 2, i.strokeStyle = "#ffffff", i.stroke(), i.fillStyle = "#ffffff", i.font = `700 10px ${Rt}`, i.textAlign = "center", i.textBaseline = "middle", i.fillText(String(r), t, e), i.restore();
1617
+ function Ei(i) {
1618
+ const t = i.getBoundingClientRect(), e = window.getComputedStyle(i), r = parseFloat(e.borderLeftWidth) + parseFloat(e.borderRightWidth), s = parseFloat(e.borderTopWidth) + parseFloat(e.borderBottomWidth);
1619
+ return {
1620
+ left: t.left,
1621
+ top: t.top,
1622
+ width: i.clientWidth + (Number.isFinite(r) ? r : 0) || window.innerWidth,
1623
+ height: i.clientHeight + (Number.isFinite(s) ? s : 0) || window.innerHeight
1624
+ };
1625
+ }
1626
+ function Ci(i, t, e, r) {
1627
+ i.save(), i.shadowColor = J(0.45), i.shadowOffsetY = 2, i.shadowBlur = 8, i.fillStyle = O, i.beginPath(), i.arc(t, e, 11, 0, Math.PI * 2), i.fill(), i.shadowColor = "transparent", i.lineWidth = 2, i.strokeStyle = "#ffffff", i.stroke(), i.fillStyle = "#ffffff", i.font = `700 10px ${re}`, i.textAlign = "center", i.textBaseline = "middle", i.fillText(String(r), t, e), i.restore();
1283
1628
  }
1284
- function Ne(i) {
1629
+ function Ft(i) {
1285
1630
  const t = [];
1286
1631
  let e = null;
1287
1632
  const r = i.match(/[ML]\s*[-\d.]+\s+[-\d.]+/g) ?? [];
@@ -1291,13 +1636,13 @@ function Ne(i) {
1291
1636
  }
1292
1637
  return t;
1293
1638
  }
1294
- function We(i) {
1639
+ function _i(i) {
1295
1640
  return new Promise((t) => {
1296
1641
  const e = new Image();
1297
1642
  e.onload = () => t(e), e.onerror = () => t(null), e.src = i;
1298
1643
  });
1299
1644
  }
1300
- function Ve(i) {
1645
+ function ft(i) {
1301
1646
  return new Promise((t) => {
1302
1647
  try {
1303
1648
  i.toBlob((e) => t(e), "image/jpeg", 0.85);
@@ -1306,13 +1651,13 @@ function Ve(i) {
1306
1651
  }
1307
1652
  });
1308
1653
  }
1309
- function Ye(i) {
1654
+ function Ti(i) {
1310
1655
  const [t, e] = i.split(","), r = t.match(/:(.*?);/)?.[1] ?? "image/png", s = atob(e), n = new Uint8Array(s.length);
1311
1656
  for (let o = 0; o < s.length; o++)
1312
1657
  n[o] = s.charCodeAt(o);
1313
1658
  return new Blob([n], { type: r });
1314
1659
  }
1315
- class Ke {
1660
+ class Mi {
1316
1661
  constructor() {
1317
1662
  this.listeners = /* @__PURE__ */ new Set(), this.originalOnError = null, this.installedOnError = null, this.rejectionHandler = null, this.hooked = !1;
1318
1663
  }
@@ -1334,20 +1679,20 @@ class Ke {
1334
1679
  for (const e of this.listeners) e(t);
1335
1680
  }
1336
1681
  }
1337
- const z = new Ke(), Xe = 20;
1338
- class Ge {
1682
+ const tt = new Mi(), Li = 20;
1683
+ class Ai {
1339
1684
  constructor() {
1340
1685
  this.errors = [], this.unsubscribe = null;
1341
1686
  }
1342
1687
  start() {
1343
- this.unsubscribe || (this.unsubscribe = z.subscribe((t) => this.record(t)));
1688
+ this.unsubscribe || (this.unsubscribe = tt.subscribe((t) => this.record(t)));
1344
1689
  }
1345
1690
  record(t) {
1346
1691
  const e = t.line != null ? ` (${t.line}:${t.col ?? 0})` : "";
1347
1692
  this.addError(`${t.message}${e}`);
1348
1693
  }
1349
1694
  addError(t) {
1350
- this.errors.length >= Xe || this.errors.includes(t) || this.errors.push(t);
1695
+ this.errors.length >= Li || this.errors.includes(t) || this.errors.push(t);
1351
1696
  }
1352
1697
  getErrors() {
1353
1698
  return [...this.errors];
@@ -1356,40 +1701,69 @@ class Ge {
1356
1701
  this.unsubscribe?.(), this.unsubscribe = null;
1357
1702
  }
1358
1703
  }
1359
- const Je = 20;
1360
- class Qe {
1704
+ const I = /* @__PURE__ */ new Set();
1705
+ let M = null, L = null, A = null, B = null, P = null;
1706
+ function Bt(i) {
1707
+ I.add(i), Pi();
1708
+ let t = !1;
1709
+ return () => {
1710
+ t || (t = !0, I.delete(i), I.size === 0 && Ri());
1711
+ };
1712
+ }
1713
+ function W() {
1714
+ for (const i of [...I])
1715
+ try {
1716
+ i();
1717
+ } catch {
1718
+ }
1719
+ }
1720
+ function Pi() {
1721
+ if (A) return;
1722
+ P = () => W(), window.addEventListener("popstate", P), M = history.pushState, L = history.replaceState;
1723
+ const i = M, t = L;
1724
+ A = function(e, r, s) {
1725
+ i.call(history, e, r, s), W();
1726
+ }, B = function(e, r, s) {
1727
+ t.call(history, e, r, s), W();
1728
+ }, history.pushState = A, history.replaceState = B;
1729
+ }
1730
+ function Ri() {
1731
+ P && (window.removeEventListener("popstate", P), P = null), M && history.pushState === A && (history.pushState = M), L && history.replaceState === B && (history.replaceState = L), M = null, L = null, A = null, B = null;
1732
+ }
1733
+ const Di = 20;
1734
+ class Ii {
1361
1735
  constructor() {
1362
- this.breadcrumbs = [], this.active = !1, this.unsubscribeErrors = null, this.boundPopstateHandler = null, this.originalPushState = null, this.originalReplaceState = null, this.installedPushState = null, this.installedReplaceState = null, this.lastUrl = "", this.boundClickHandler = (t) => this.handleClick(t), this.boundChangeHandler = (t) => this.handleChange(t);
1736
+ this.breadcrumbs = [], this.active = !1, this.unsubscribeErrors = null, this.unsubscribeNavigation = null, this.lastUrl = "", this.boundClickHandler = (t) => this.handleClick(t), this.boundChangeHandler = (t) => this.handleChange(t);
1363
1737
  }
1364
1738
  start() {
1365
- this.active || (this.active = !0, this.lastUrl = location.href, document.addEventListener("click", this.boundClickHandler, { capture: !0, passive: !0 }), document.addEventListener("change", this.boundChangeHandler, { capture: !0, passive: !0 }), this.unsubscribeErrors = z.subscribe((t) => this.recordError(t)), this.startNavigationTracking());
1739
+ this.active || (this.active = !0, this.lastUrl = location.href, document.addEventListener("click", this.boundClickHandler, { capture: !0, passive: !0 }), document.addEventListener("change", this.boundChangeHandler, { capture: !0, passive: !0 }), this.unsubscribeErrors = tt.subscribe((t) => this.recordError(t)), this.unsubscribeNavigation = Bt(() => this.handleNavigation()));
1366
1740
  }
1367
1741
  stop() {
1368
- this.active && (this.active = !1, document.removeEventListener("click", this.boundClickHandler, !0), document.removeEventListener("change", this.boundChangeHandler, !0), this.unsubscribeErrors?.(), this.unsubscribeErrors = null, this.stopNavigationTracking());
1742
+ this.active && (this.active = !1, document.removeEventListener("click", this.boundClickHandler, !0), document.removeEventListener("change", this.boundChangeHandler, !0), this.unsubscribeErrors?.(), this.unsubscribeErrors = null, this.unsubscribeNavigation?.(), this.unsubscribeNavigation = null);
1369
1743
  }
1370
1744
  getBreadcrumbs() {
1371
1745
  return [...this.breadcrumbs];
1372
1746
  }
1373
1747
  add(t) {
1374
- this.breadcrumbs.push(t), this.breadcrumbs.length > Je && this.breadcrumbs.shift();
1748
+ this.breadcrumbs.push(t), this.breadcrumbs.length > Di && this.breadcrumbs.shift();
1375
1749
  }
1376
1750
  handleClick(t) {
1377
1751
  const e = t.target;
1378
- if (e && !_(e))
1752
+ if (e && !S(e))
1379
1753
  try {
1380
1754
  this.add({
1381
1755
  type: "ui",
1382
1756
  category: "ui.click",
1383
1757
  timestamp: Date.now(),
1384
- message: F(e),
1385
- data: { selector: at(e) }
1758
+ message: G(e),
1759
+ data: { selector: _t(e) }
1386
1760
  });
1387
1761
  } catch {
1388
1762
  }
1389
1763
  }
1390
1764
  handleChange(t) {
1391
1765
  const e = t.target;
1392
- if (e && !_(e))
1766
+ if (e && !S(e))
1393
1767
  try {
1394
1768
  const r = e, s = r.name || r.placeholder || e.getAttribute("aria-label") || e.tagName;
1395
1769
  this.add({
@@ -1411,18 +1785,6 @@ class Qe {
1411
1785
  data: { message: t.message }
1412
1786
  });
1413
1787
  }
1414
- startNavigationTracking() {
1415
- this.boundPopstateHandler = () => this.handleNavigation(), window.addEventListener("popstate", this.boundPopstateHandler), this.originalPushState = history.pushState.bind(history), this.originalReplaceState = history.replaceState.bind(history);
1416
- const t = this.originalPushState, e = this.originalReplaceState, r = () => this.handleNavigation();
1417
- this.installedPushState = function(s, n, o) {
1418
- t(s, n, o), r();
1419
- }, this.installedReplaceState = function(s, n, o) {
1420
- e(s, n, o), r();
1421
- }, history.pushState = this.installedPushState, history.replaceState = this.installedReplaceState;
1422
- }
1423
- stopNavigationTracking() {
1424
- this.boundPopstateHandler && (window.removeEventListener("popstate", this.boundPopstateHandler), this.boundPopstateHandler = null), this.originalPushState && history.pushState === this.installedPushState && (history.pushState = this.originalPushState), this.originalReplaceState && history.replaceState === this.installedReplaceState && (history.replaceState = this.originalReplaceState), this.originalPushState = null, this.originalReplaceState = null, this.installedPushState = null, this.installedReplaceState = null;
1425
- }
1426
1788
  handleNavigation() {
1427
1789
  if (!this.active) return;
1428
1790
  const t = this.lastUrl, e = location.href;
@@ -1435,7 +1797,40 @@ class Qe {
1435
1797
  }));
1436
1798
  }
1437
1799
  }
1438
- const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @__PURE__ */ new Set([
1800
+ const Ut = "mtb_frustration_state";
1801
+ let Y = null;
1802
+ function U() {
1803
+ try {
1804
+ const i = window.sessionStorage.getItem(Ut);
1805
+ return H(i ? JSON.parse(i) : Y);
1806
+ } catch {
1807
+ return H(Y);
1808
+ }
1809
+ }
1810
+ function Ot(i) {
1811
+ const t = H(i);
1812
+ Y = t;
1813
+ try {
1814
+ window.sessionStorage.setItem(Ut, JSON.stringify(t));
1815
+ } catch {
1816
+ }
1817
+ }
1818
+ function Hi() {
1819
+ return U().dismissedByUser;
1820
+ }
1821
+ function $i() {
1822
+ Ot({ ...U(), dismissedByUser: !0 });
1823
+ }
1824
+ function H(i) {
1825
+ const t = i ?? {};
1826
+ return {
1827
+ navTimestamps: Array.isArray(t.navTimestamps) ? t.navTimestamps.filter((e) => typeof e == "number") : [],
1828
+ cooldownUntil: typeof t.cooldownUntil == "number" ? t.cooldownUntil : 0,
1829
+ errorPageUrls: Array.isArray(t.errorPageUrls) ? t.errorPageUrls.filter((e) => typeof e == "string").slice(-20) : [],
1830
+ dismissedByUser: t.dismissedByUser === !0
1831
+ };
1832
+ }
1833
+ const Fi = 3, Bi = 1e3, Ui = 3, Oi = 5e3, bt = 500, zi = 500, ji = 300, qi = /* @__PURE__ */ new Set([
1439
1834
  "A",
1440
1835
  "BUTTON",
1441
1836
  "INPUT",
@@ -1444,7 +1839,7 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1444
1839
  "LABEL",
1445
1840
  "SUMMARY",
1446
1841
  "DETAILS"
1447
- ]), oi = /* @__PURE__ */ new Set([
1842
+ ]), Ni = /* @__PURE__ */ new Set([
1448
1843
  "button",
1449
1844
  "link",
1450
1845
  "checkbox",
@@ -1458,19 +1853,19 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1458
1853
  "listbox",
1459
1854
  "slider",
1460
1855
  "spinbutton"
1461
- ]), Q = [
1856
+ ]), pt = [
1462
1857
  "404",
1463
1858
  "500",
1464
1859
  "not found",
1465
1860
  "page not found",
1466
1861
  "server error",
1467
1862
  "internal server error"
1468
- ], T = class T {
1863
+ ], R = class R {
1469
1864
  constructor(t) {
1470
- this.clickHistory = [], this.unsubscribeErrors = null, this.active = !1, this.errorCount = 0, this.deadClickCount = 0, this.cooldownUntil = 0, this.navTimestamps = [], this.boundPopstateHandler = null, this.originalPushState = null, this.originalReplaceState = null, this.installedPushState = null, this.installedReplaceState = null, this.boundSubmitHandler = null, this.boundInvalidHandler = null, this.recentSubmitForms = /* @__PURE__ */ new WeakSet(), this.errorPageUrls = /* @__PURE__ */ new Set(), this.domObserver = null, this.pendingDomChecks = 0, this.lastMutationAt = -1, this.onFrustration = t, this.boundClickHandler = (e) => this.handleClick(e);
1865
+ this.clickHistory = [], this.unsubscribeErrors = null, this.active = !1, this.errorCount = 0, this.deadClickCount = 0, this.cooldownUntil = 0, this.navTimestamps = [], this.unsubscribeNavigation = null, this.boundSubmitHandler = null, this.boundInvalidHandler = null, this.recentSubmitForms = /* @__PURE__ */ new WeakSet(), this.errorPageUrls = /* @__PURE__ */ new Set(), this.domObserver = null, this.pendingDomChecks = 0, this.lastMutationAt = -1, this.onFrustration = t, this.boundClickHandler = (e) => this.handleClick(e);
1471
1866
  }
1472
1867
  start() {
1473
- this.active || (this.active = !0, document.addEventListener("click", this.boundClickHandler, !0), this.unsubscribeErrors = z.subscribe((t) => {
1868
+ this.active || (this.active = !0, this.restoreState(), document.addEventListener("click", this.boundClickHandler, !0), this.unsubscribeErrors = tt.subscribe((t) => {
1474
1869
  this.errorCount++;
1475
1870
  }), this.startNavigationTracking(), this.startFormTracking(), this.checkErrorPage());
1476
1871
  }
@@ -1478,16 +1873,27 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1478
1873
  this.active && (this.active = !1, document.removeEventListener("click", this.boundClickHandler, !0), this.unsubscribeErrors?.(), this.unsubscribeErrors = null, this.clickHistory = [], this.stopNavigationTracking(), this.stopFormTracking(), this.errorPageUrls.clear(), this.disconnectDomObserver());
1479
1874
  }
1480
1875
  startNavigationTracking() {
1481
- this.boundPopstateHandler = () => this.handleNavigation(), window.addEventListener("popstate", this.boundPopstateHandler), this.originalPushState = history.pushState.bind(history), this.originalReplaceState = history.replaceState.bind(history);
1482
- const t = this.originalPushState, e = this.originalReplaceState, r = () => this.handleNavigation();
1483
- this.installedPushState = function(s, n, o) {
1484
- t(s, n, o), r();
1485
- }, this.installedReplaceState = function(s, n, o) {
1486
- e(s, n, o), r();
1487
- }, history.pushState = this.installedPushState, history.replaceState = this.installedReplaceState;
1876
+ this.unsubscribeNavigation = Bt(() => this.handleNavigation());
1488
1877
  }
1489
1878
  stopNavigationTracking() {
1490
- this.boundPopstateHandler && (window.removeEventListener("popstate", this.boundPopstateHandler), this.boundPopstateHandler = null), this.originalPushState && history.pushState === this.installedPushState && (history.pushState = this.originalPushState), this.originalReplaceState && history.replaceState === this.installedReplaceState && (history.replaceState = this.originalReplaceState), this.originalPushState = null, this.originalReplaceState = null, this.installedPushState = null, this.installedReplaceState = null, this.navTimestamps = [];
1879
+ this.unsubscribeNavigation?.(), this.unsubscribeNavigation = null, this.navTimestamps = [];
1880
+ }
1881
+ // Rehydrates the state a Turbo Drive visit would otherwise reset. Without this,
1882
+ // a fresh detector on every page starts with an empty nav history (so
1883
+ // `rapid_navigation` can never reach its 3-in-5s threshold), no cooldown, and no
1884
+ // memory of which error pages it already reported.
1885
+ restoreState() {
1886
+ const t = U();
1887
+ this.navTimestamps = t.navTimestamps, this.cooldownUntil = t.cooldownUntil, this.errorPageUrls = new Set(t.errorPageUrls);
1888
+ }
1889
+ persistState() {
1890
+ const t = U();
1891
+ Ot({
1892
+ ...t,
1893
+ navTimestamps: this.navTimestamps,
1894
+ cooldownUntil: this.cooldownUntil,
1895
+ errorPageUrls: [...this.errorPageUrls]
1896
+ });
1491
1897
  }
1492
1898
  startFormTracking() {
1493
1899
  this.boundSubmitHandler = (t) => this.handleFormSubmit(t), this.boundInvalidHandler = (t) => this.handleFormInvalid(t), document.addEventListener("submit", this.boundSubmitHandler, !0), document.addEventListener("invalid", this.boundInvalidHandler, !0);
@@ -1497,54 +1903,62 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1497
1903
  }
1498
1904
  handleClick(t) {
1499
1905
  const e = t.target;
1500
- if (!e || _(e)) return;
1906
+ if (!e || S(e)) return;
1907
+ this.trackFormSubmitIntent(e);
1501
1908
  const r = Date.now();
1502
1909
  this.clickHistory.push({ target: e, time: r });
1503
- const s = r - ti;
1504
- if (this.clickHistory = this.clickHistory.filter((o) => o.time > s), this.clickHistory.filter((o) => o.target === e).length >= Ze) {
1910
+ const s = r - Bi;
1911
+ if (this.clickHistory = this.clickHistory.filter((o) => o.time > s), this.clickHistory.filter((o) => o.target === e).length >= Fi) {
1505
1912
  this.clickHistory = [], this.emitHighPriority({
1506
1913
  signal: "rage_click",
1507
- target: E(e),
1914
+ target: _(e),
1508
1915
  timestamp: r
1509
1916
  });
1510
1917
  return;
1511
1918
  }
1512
1919
  this.isInteractive(e) || (this.deadClickCount++, this.deadClickCount >= 3 && this.errorCount > 0 && (this.deadClickCount = 0, this.errorCount = 0, this.emitIfReady({
1513
1920
  signal: "dead_click",
1514
- target: E(e),
1921
+ target: _(e),
1515
1922
  timestamp: r
1516
1923
  }))), this.checkDeadClickDom(e, r);
1517
1924
  }
1518
1925
  handleNavigation() {
1519
1926
  const t = Date.now();
1520
1927
  this.navTimestamps.push(t);
1521
- const e = t - ii;
1522
- this.navTimestamps = this.navTimestamps.filter((r) => r > e), this.navTimestamps.length >= ei && (this.navTimestamps = [], this.emitIfReady({
1928
+ const e = t - Oi;
1929
+ this.navTimestamps = this.navTimestamps.filter((r) => r > e), this.navTimestamps.length >= Ui && (this.navTimestamps = [], this.emitIfReady({
1523
1930
  signal: "rapid_navigation",
1524
1931
  timestamp: t
1525
- })), setTimeout(() => {
1932
+ })), this.persistState(), setTimeout(() => {
1526
1933
  this.active && this.checkErrorPage();
1527
- }, si);
1934
+ }, ji);
1528
1935
  }
1529
1936
  handleFormSubmit(t) {
1530
1937
  const e = t.target;
1531
- e instanceof HTMLFormElement && (_(e) || (this.recentSubmitForms.add(e), setTimeout(() => {
1532
- this.recentSubmitForms.delete(e);
1533
- }, J), setTimeout(() => {
1938
+ e instanceof HTMLFormElement && (S(e) || (this.rememberSubmitAttempt(e), setTimeout(() => {
1534
1939
  this.active && e.querySelector('[aria-invalid="true"], .is-invalid') && this.emitIfReady({
1535
1940
  signal: "form_failure",
1536
- target: E(e),
1941
+ target: _(e),
1537
1942
  timestamp: Date.now()
1538
1943
  });
1539
- }, J)));
1944
+ }, bt)));
1945
+ }
1946
+ trackFormSubmitIntent(t) {
1947
+ const e = t.closest("button, input");
1948
+ (e instanceof HTMLButtonElement || e instanceof HTMLInputElement) && (e.type !== "submit" && e.type !== "image" || !e.form || S(e.form) || this.rememberSubmitAttempt(e.form));
1949
+ }
1950
+ rememberSubmitAttempt(t) {
1951
+ this.recentSubmitForms.add(t), setTimeout(() => {
1952
+ this.recentSubmitForms.delete(t);
1953
+ }, bt);
1540
1954
  }
1541
1955
  handleFormInvalid(t) {
1542
1956
  const e = t.target;
1543
- if (!e || _(e)) return;
1957
+ if (!e || S(e)) return;
1544
1958
  const r = e.closest("form");
1545
1959
  !r || !this.recentSubmitForms.has(r) || this.emitIfReady({
1546
1960
  signal: "form_failure",
1547
- target: E(r),
1961
+ target: _(r),
1548
1962
  timestamp: Date.now()
1549
1963
  });
1550
1964
  }
@@ -1552,7 +1966,7 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1552
1966
  const t = location.href;
1553
1967
  if (this.errorPageUrls.has(t)) return;
1554
1968
  const e = document.title.toLowerCase();
1555
- if (Q.some((s) => e.includes(s))) {
1969
+ if (pt.some((s) => e.includes(s))) {
1556
1970
  this.errorPageUrls.add(t), this.emitHighPriority({
1557
1971
  signal: "error_page",
1558
1972
  detail: document.title,
@@ -1565,7 +1979,7 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1565
1979
  );
1566
1980
  for (const s of r) {
1567
1981
  const n = s.textContent ?? "";
1568
- if (n.length < 200 && Q.some((o) => n.toLowerCase().includes(o))) {
1982
+ if (n.length < 200 && pt.some((o) => n.toLowerCase().includes(o))) {
1569
1983
  this.errorPageUrls.add(t), this.emitHighPriority({
1570
1984
  signal: "error_page",
1571
1985
  detail: n.trim().slice(0, 60),
@@ -1584,10 +1998,10 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1584
1998
  const r = this.lastMutationAt >= e;
1585
1999
  this.pendingDomChecks === 0 && this.disconnectDomObserver(), !r && this.active && this.emitIfReady({
1586
2000
  signal: "dead_click_dom",
1587
- target: E(t),
2001
+ target: _(t),
1588
2002
  timestamp: e
1589
2003
  });
1590
- }, ri));
2004
+ }, zi));
1591
2005
  }
1592
2006
  ensureDomObserver() {
1593
2007
  this.domObserver || (this.domObserver = new MutationObserver(() => {
@@ -1612,206 +2026,43 @@ const Ze = 3, ti = 1e3, ei = 3, ii = 5e3, J = 500, ri = 500, si = 300, ni = /* @
1612
2026
  return !1;
1613
2027
  }
1614
2028
  isInteractive(t) {
1615
- if (ni.has(t.tagName)) return !0;
2029
+ if (qi.has(t.tagName)) return !0;
1616
2030
  const e = t.getAttribute("role");
1617
- return !!(e && oi.has(e) || t.hasAttribute("onclick") || t.hasAttribute("tabindex") || t.contentEditable === "true" || window.getComputedStyle(t).cursor === "pointer" || t.closest('a, button, [role="button"], [role="link"], label'));
2031
+ return !!(e && Ni.has(e) || t.hasAttribute("onclick") || t.hasAttribute("tabindex") || t.contentEditable === "true" || window.getComputedStyle(t).cursor === "pointer" || t.closest('a, button, [role="button"], [role="link"], label'));
1618
2032
  }
1619
2033
  emitIfReady(t) {
1620
2034
  const e = Date.now();
1621
- e < this.cooldownUntil || (this.cooldownUntil = e + T.COOLDOWN_MS, this.onFrustration(t));
2035
+ e < this.cooldownUntil || (this.cooldownUntil = e + R.COOLDOWN_MS, this.persistState(), this.onFrustration(t));
1622
2036
  }
1623
2037
  emitHighPriority(t) {
1624
- this.cooldownUntil = Date.now() + T.COOLDOWN_MS, this.onFrustration(t);
2038
+ this.cooldownUntil = Date.now() + R.COOLDOWN_MS, this.persistState(), this.onFrustration(t);
1625
2039
  }
1626
2040
  };
1627
- T.COOLDOWN_MS = 6e4;
1628
- let $ = T;
1629
- function E(i) {
2041
+ R.COOLDOWN_MS = 6e4;
2042
+ let X = R;
2043
+ function _(i) {
1630
2044
  const t = i.tagName.toLowerCase(), e = i.id ? `#${i.id}` : "", r = i.className && typeof i.className == "string" ? "." + i.className.trim().split(/\s+/).slice(0, 2).join(".") : "", s = i.textContent?.trim().slice(0, 30) ?? "";
1631
2045
  return `<${t}${e}${r}>${s ? ` "${s}"` : ""}`;
1632
2046
  }
1633
- function ai() {
2047
+ function Wi() {
1634
2048
  return {
1635
2049
  page_url: window.location.href,
1636
2050
  user_agent: navigator.userAgent,
1637
- browser: li(),
1638
- os: ci(),
2051
+ browser: Vi(),
2052
+ os: Yi(),
1639
2053
  screen_width: window.screen.width,
1640
2054
  screen_height: window.screen.height
1641
2055
  };
1642
2056
  }
1643
- function li() {
2057
+ function Vi() {
1644
2058
  const i = navigator.userAgent;
1645
2059
  return /Edg\//.test(i) ? `Edge ${i.match(/Edg\/(\S+)/)?.[1] ?? ""}` : /OPR\//.test(i) ? `Opera ${i.match(/OPR\/(\S+)/)?.[1] ?? ""}` : /Chrome\//.test(i) ? `Chrome ${i.match(/Chrome\/(\S+)/)?.[1] ?? ""}` : /Safari\//.test(i) && /Version\//.test(i) ? `Safari ${i.match(/Version\/(\S+)/)?.[1] ?? ""}` : /Firefox\//.test(i) ? `Firefox ${i.match(/Firefox\/(\S+)/)?.[1] ?? ""}` : "Unknown";
1646
2060
  }
1647
- function ci() {
2061
+ function Yi() {
1648
2062
  const i = navigator.userAgent;
1649
2063
  return /Windows NT 10/.test(i) ? "Windows 10/11" : /Windows NT/.test(i) ? "Windows" : /Mac OS X 10_15|macOS 1[56789]/.test(i) || /Mac OS X/.test(i) ? "macOS" : /Android/.test(i) ? `Android ${i.match(/Android (\d+)/)?.[1] ?? ""}` : /iPhone|iPad|iPod/.test(i) ? "iOS" : /Linux/.test(i) ? "Linux" : "Unknown";
1650
2064
  }
1651
- const di = "https://makethisbetter.dev/api/v1";
1652
- class hi {
1653
- constructor(t, e, r = 1e3, s, n) {
1654
- this.projectKey = t, this.apiUrl = (e ?? di).replace(/\/$/, ""), this.retryDelayMs = r, this.userToken = s, this.userTokenFn = n;
1655
- }
1656
- async resolveUserToken() {
1657
- return this.userTokenFn ? this.userTokenFn() : this.userToken;
1658
- }
1659
- async authHeaders(t) {
1660
- const e = { "X-Project-Key": this.projectKey }, r = await this.resolveUserToken();
1661
- return r && (e["X-User-Token"] = r), t && (e["Content-Type"] = t), e;
1662
- }
1663
- async submissionHeaders(t, e) {
1664
- const r = await this.authHeaders(e);
1665
- return r["X-Submission-Token"] = t, r;
1666
- }
1667
- async createSubmissionSession(t, e) {
1668
- const r = fi(), s = new FormData();
1669
- if (s.append("feedback[description]", t.description), s.append("feedback[page_url]", t.page_url), s.append("feedback[user_agent]", t.user_agent), s.append("feedback[browser]", t.browser), s.append("feedback[os]", t.os), s.append("feedback[screen_width]", String(t.screen_width)), s.append("feedback[screen_height]", String(t.screen_height)), s.append("feedback[console_errors]", JSON.stringify(t.console_errors)), s.append("feedback[annotations]", JSON.stringify(t.annotations)), t.target_element && s.append("feedback[target_element]", JSON.stringify(t.target_element)), t.user_id && s.append("feedback[user_id]", t.user_id), t.reporter_external_id && s.append("feedback[reporter_external_id]", t.reporter_external_id), t.reporter_email && s.append("feedback[reporter_email]", t.reporter_email), t.user_email && s.append("feedback[user_email]", t.user_email), t.user_name && s.append("feedback[user_name]", t.user_name), t.breadcrumbs && t.breadcrumbs.length > 0 && s.append("feedback[breadcrumbs]", JSON.stringify(t.breadcrumbs)), t.recording_events && t.recording_events.length > 0) {
1670
- const l = JSON.stringify(t.recording_events), c = new Blob([l], { type: "application/json" });
1671
- s.append("feedback[recording]", c, "interaction-replay.json"), s.append("feedback[recording_duration]", String(t.recording_duration ?? 0));
1672
- }
1673
- if (e) {
1674
- const l = e.type === "image/jpeg" ? "jpg" : "png";
1675
- s.append("feedback[screenshot]", e, `screenshot.${l}`);
1676
- }
1677
- const n = await this.authHeaders();
1678
- return n["X-Submission-Token"] = r, n["X-Idempotency-Key"] = mi(), { ...(await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions`, {
1679
- method: "POST",
1680
- headers: n,
1681
- body: s
1682
- })).json()).submission_session, token: r };
1683
- }
1684
- async createIdentityToken(t) {
1685
- const e = await this.authHeaders("application/json");
1686
- try {
1687
- return await (await this.fetchWithRetry(`${this.apiUrl}/widget/identity_tokens`, {
1688
- method: "POST",
1689
- headers: e,
1690
- body: JSON.stringify({ reporter_external_id: t })
1691
- })).json();
1692
- } catch {
1693
- return null;
1694
- }
1695
- }
1696
- async updateReporter(t, e, r) {
1697
- const s = await this.authHeaders("application/json");
1698
- s["X-Identity-Token"] = r;
1699
- try {
1700
- return await this.fetchWithRetry(`${this.apiUrl}/widget/feedbacks/${t}/reporter`, {
1701
- method: "PATCH",
1702
- headers: s,
1703
- body: JSON.stringify({ reporter: { email: e } })
1704
- }), !0;
1705
- } catch {
1706
- return !1;
1707
- }
1708
- }
1709
- async startClarification(t, e, r) {
1710
- const s = {};
1711
- r && (s.message = r);
1712
- const n = await this.submissionHeaders(e, "application/json");
1713
- return (await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/clarification`, {
1714
- method: "POST",
1715
- headers: n,
1716
- body: JSON.stringify(s)
1717
- })).json()).clarification;
1718
- }
1719
- async getClarification(t, e) {
1720
- const r = await this.submissionHeaders(e);
1721
- return (await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/clarification`, {
1722
- method: "GET",
1723
- headers: r
1724
- })).json()).clarification;
1725
- }
1726
- // Streams a clarification turn over SSE. Calls onDelta for each token and
1727
- // resolves with the committed result. Throws if the server doesn't stream
1728
- // (e.g. old backend returns JSON) so the caller can fall back to polling.
1729
- async streamClarification(t, e, r) {
1730
- const s = await this.submissionHeaders(e, "application/json");
1731
- s.Accept = "text/event-stream";
1732
- const n = await fetch(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/clarification`, {
1733
- method: "POST",
1734
- headers: s,
1735
- body: JSON.stringify({})
1736
- }), o = n.headers.get("Content-Type") ?? "";
1737
- if (!n.ok || !n.body || !o.includes("text/event-stream"))
1738
- throw new Error("clarify stream unavailable");
1739
- return ui(n.body, r);
1740
- }
1741
- async finalizeSubmissionSession(t, e) {
1742
- const r = await this.submissionHeaders(e);
1743
- return (await (await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}/feedback`, {
1744
- method: "POST",
1745
- headers: r
1746
- })).json()).feedback;
1747
- }
1748
- async abandonSubmissionSession(t, e) {
1749
- const r = await this.submissionHeaders(e);
1750
- await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${t}`, {
1751
- method: "DELETE",
1752
- headers: r
1753
- });
1754
- }
1755
- async fetchWithRetry(t, e, r = 1) {
1756
- let s;
1757
- try {
1758
- s = await fetch(t, e);
1759
- } catch (n) {
1760
- if (r > 0)
1761
- return await Z(this.retryDelayMs), this.fetchWithRetry(t, e, r - 1);
1762
- throw n;
1763
- }
1764
- if (s.ok) return s;
1765
- if (s.status >= 500 && r > 0)
1766
- return await Z(this.retryDelayMs), this.fetchWithRetry(t, e, r - 1);
1767
- throw new Error(`HTTP ${s.status}`);
1768
- }
1769
- }
1770
- function Z(i) {
1771
- return i <= 0 ? Promise.resolve() : new Promise((t) => setTimeout(t, i));
1772
- }
1773
- async function ui(i, t) {
1774
- const e = i.getReader(), r = new TextDecoder();
1775
- let s = "", n = { messages: [], done: !0 };
1776
- const o = (a) => {
1777
- const l = a.split(`
1778
- `).find((m) => m.startsWith("event:")), c = a.split(`
1779
- `).find((m) => m.startsWith("data:"));
1780
- if (!c) return;
1781
- const h = l?.slice(6).trim(), u = JSON.parse(c.slice(5).trim());
1782
- h === "delta" && typeof u.text == "string" ? t(u.text) : h === "done" && (n = {
1783
- messages: Array.isArray(u.messages) ? u.messages : [],
1784
- done: u.done !== !1
1785
- });
1786
- };
1787
- for (; ; ) {
1788
- const { done: a, value: l } = await e.read();
1789
- if (a) break;
1790
- s += r.decode(l, { stream: !0 });
1791
- let c;
1792
- for (; (c = s.indexOf(`
1793
-
1794
- `)) !== -1; ) {
1795
- const h = s.slice(0, c);
1796
- s = s.slice(c + 2);
1797
- try {
1798
- o(h);
1799
- } catch {
1800
- }
1801
- }
1802
- }
1803
- return n;
1804
- }
1805
- function mi() {
1806
- return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
1807
- }
1808
- function fi() {
1809
- if (typeof crypto > "u" || typeof crypto.getRandomValues != "function")
1810
- throw new Error("Secure random generation is unavailable");
1811
- const i = crypto.getRandomValues(new Uint8Array(32));
1812
- return Array.from(i, (t) => t.toString(16).padStart(2, "0")).join("");
1813
- }
1814
- function pi(i, t, e, r, s, n, o, a, l) {
2065
+ function Xi(i, t, e, r, s, n, o, a, l) {
1815
2066
  return {
1816
2067
  description: i,
1817
2068
  ...t,
@@ -1832,50 +2083,50 @@ function pi(i, t, e, r, s, n, o, a, l) {
1832
2083
  breadcrumbs: l
1833
2084
  };
1834
2085
  }
1835
- const tt = "mtb_anon_id", gt = "mtb_reporter_email", yt = "mtb_board_url";
1836
- let et = null, wt = null, xt = null;
1837
- function it() {
2086
+ const gt = "mtb_anon_id", zt = "mtb_reporter_email", jt = "mtb_board_url";
2087
+ let yt = null, qt = null, Nt = null;
2088
+ function wt() {
1838
2089
  try {
1839
- const i = window.localStorage.getItem(tt);
2090
+ const i = window.localStorage.getItem(gt);
1840
2091
  if (i?.startsWith("anon_")) return i;
1841
- const t = nt();
1842
- return window.localStorage.setItem(tt, t), t;
2092
+ const t = kt();
2093
+ return window.localStorage.setItem(gt, t), t;
1843
2094
  } catch {
1844
- return et ?? (et = nt()), et;
2095
+ return yt ?? (yt = kt()), yt;
1845
2096
  }
1846
2097
  }
1847
- function rt() {
2098
+ function vt() {
1848
2099
  try {
1849
- return window.localStorage.getItem(gt) ?? void 0;
2100
+ return window.localStorage.getItem(zt) ?? void 0;
1850
2101
  } catch {
1851
- return wt ?? void 0;
2102
+ return qt ?? void 0;
1852
2103
  }
1853
2104
  }
1854
- function bi(i) {
1855
- wt = i;
2105
+ function Ki(i) {
2106
+ qt = i;
1856
2107
  try {
1857
- window.localStorage.setItem(gt, i);
2108
+ window.localStorage.setItem(zt, i);
1858
2109
  } catch {
1859
2110
  }
1860
2111
  }
1861
- function gi() {
2112
+ function Gi() {
1862
2113
  try {
1863
- return window.localStorage.getItem(yt) ?? void 0;
2114
+ return window.localStorage.getItem(jt) ?? void 0;
1864
2115
  } catch {
1865
- return xt ?? void 0;
2116
+ return Nt ?? void 0;
1866
2117
  }
1867
2118
  }
1868
- function st(i) {
1869
- xt = i;
2119
+ function xt(i) {
2120
+ Nt = i;
1870
2121
  try {
1871
- window.localStorage.setItem(yt, i);
2122
+ window.localStorage.setItem(jt, i);
1872
2123
  } catch {
1873
2124
  }
1874
2125
  }
1875
- function nt() {
2126
+ function kt() {
1876
2127
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? `anon_${crypto.randomUUID()}` : `anon_${`${Date.now().toString(16)}-${Math.random().toString(16).slice(2, 10)}`}`;
1877
2128
  }
1878
- const yi = {
2129
+ const Ji = {
1879
2130
  tab: "Feedback",
1880
2131
  toolbar: {
1881
2132
  markup: "Mark up",
@@ -1948,9 +2199,11 @@ const yi = {
1948
2199
  send: "Send",
1949
2200
  send_feedback: "Send feedback",
1950
2201
  skip: "Skip & send",
1951
- retry: "Retry"
2202
+ retry: "Retry",
2203
+ error: "AI clarification failed. Please try again.",
2204
+ expired: "This feedback session expired before it could be sent. Please close the widget and submit again."
1952
2205
  }
1953
- }, wi = {
2206
+ }, Qi = {
1954
2207
  tab: "反馈",
1955
2208
  toolbar: {
1956
2209
  markup: "标注",
@@ -2023,9 +2276,11 @@ const yi = {
2023
2276
  send: "发送",
2024
2277
  send_feedback: "发送反馈",
2025
2278
  skip: "跳过并发送",
2026
- retry: "重试"
2279
+ retry: "重试",
2280
+ error: "AI 澄清失败,请重试。",
2281
+ expired: "这条反馈在发送前已过期。请关闭组件后重新提交。"
2027
2282
  }
2028
- }, xi = {
2283
+ }, Zi = {
2029
2284
  tab: "フィードバック",
2030
2285
  toolbar: {
2031
2286
  markup: "マークアップ",
@@ -2098,9 +2353,11 @@ const yi = {
2098
2353
  send: "送信",
2099
2354
  send_feedback: "フィードバックを送信",
2100
2355
  skip: "スキップして送信",
2101
- retry: "再試行"
2356
+ retry: "再試行",
2357
+ error: "AIによる確認に失敗しました。もう一度お試しください。",
2358
+ expired: "このフィードバックは送信される前に有効期限が切れました。ウィジェットを閉じて、もう一度送信してください。"
2102
2359
  }
2103
- }, vi = {
2360
+ }, tr = {
2104
2361
  tab: "피드백",
2105
2362
  toolbar: {
2106
2363
  markup: "마크업",
@@ -2173,9 +2430,11 @@ const yi = {
2173
2430
  send: "보내기",
2174
2431
  send_feedback: "피드백 보내기",
2175
2432
  skip: "건너뛰고 보내기",
2176
- retry: "재시도"
2433
+ retry: "재시도",
2434
+ error: "AI 확인에 실패했습니다. 다시 시도해 주세요.",
2435
+ expired: "이 피드백 세션은 전송되기 전에 만료되었습니다. 위젯을 닫고 다시 보내 주세요."
2177
2436
  }
2178
- }, ki = {
2437
+ }, er = {
2179
2438
  tab: "Comentarios",
2180
2439
  toolbar: {
2181
2440
  markup: "Anotar",
@@ -2248,9 +2507,11 @@ const yi = {
2248
2507
  send: "Enviar",
2249
2508
  send_feedback: "Enviar comentario",
2250
2509
  skip: "Omitir y enviar",
2251
- retry: "Reintentar"
2510
+ retry: "Reintentar",
2511
+ error: "No se pudo completar la aclaración con IA. Inténtalo de nuevo.",
2512
+ expired: "Esta sesión de comentarios caducó antes de poder enviarse. Cierra el widget y envíalo de nuevo."
2252
2513
  }
2253
- }, Si = {
2514
+ }, ir = {
2254
2515
  tab: "Avis",
2255
2516
  toolbar: {
2256
2517
  markup: "Annoter",
@@ -2323,9 +2584,11 @@ const yi = {
2323
2584
  send: "Envoyer",
2324
2585
  send_feedback: "Envoyer le retour",
2325
2586
  skip: "Ignorer et envoyer",
2326
- retry: "Réessayer"
2587
+ retry: "Réessayer",
2588
+ error: "La clarification par IA a échoué. Réessayez.",
2589
+ expired: "Cette session de retour a expiré avant d'avoir pu être envoyée. Fermez le widget et renvoyez-la."
2327
2590
  }
2328
- }, Ei = {
2591
+ }, rr = {
2329
2592
  tab: "Feedback",
2330
2593
  toolbar: {
2331
2594
  markup: "Markieren",
@@ -2398,58 +2661,67 @@ const yi = {
2398
2661
  send: "Senden",
2399
2662
  send_feedback: "Feedback senden",
2400
2663
  skip: "Überspringen & senden",
2401
- retry: "Erneut versuchen"
2402
- }
2403
- }, C = {
2404
- en: yi,
2405
- "zh-CN": wi,
2406
- ja: xi,
2407
- ko: vi,
2408
- es: ki,
2409
- fr: Si,
2410
- de: Ei
2664
+ retry: "Erneut versuchen",
2665
+ error: "Die KI-Klärung ist fehlgeschlagen. Bitte erneut versuchen.",
2666
+ expired: "Diese Feedback-Sitzung ist abgelaufen, bevor sie gesendet werden konnte. Bitte schließe das Widget und sende erneut."
2667
+ }
2668
+ }, T = {
2669
+ en: Ji,
2670
+ "zh-CN": Qi,
2671
+ ja: Zi,
2672
+ ko: tr,
2673
+ es: er,
2674
+ fr: ir,
2675
+ de: rr
2411
2676
  };
2412
- function Ci(i) {
2413
- if (C[i]) return C[i];
2677
+ function St(i) {
2678
+ if (T[i]) return T[i];
2414
2679
  const t = i.split("-")[0];
2415
- return C[t] ? C[t] : C.en;
2680
+ return T[t] ? T[t] : T.en;
2416
2681
  }
2417
- const _i = 60, Ti = "https://cdn.jsdelivr.net/npm/@rrweb/record@2.1.0/umd/record.min.js", Li = "sha384-MrD66HBNSykaP2N95+6hQCFlF5oH2tvL3TD/zyvHNkP/sAFWZx98DX9MEDy8MdVT";
2418
- let L = null;
2419
- function Mi() {
2420
- return L || (L = Pi().catch(() => Ri()), L);
2682
+ const sr = 60, nr = "rr-block", or = "rr-mask", ar = "https://cdn.jsdelivr.net/npm/@rrweb/record@2.1.0/umd/record.min.js", lr = "sha384-MrD66HBNSykaP2N95+6hQCFlF5oH2tvL3TD/zyvHNkP/sAFWZx98DX9MEDy8MdVT";
2683
+ let D = null;
2684
+ function cr() {
2685
+ return D || (D = dr().catch(() => hr()), D);
2421
2686
  }
2422
- async function Pi() {
2687
+ async function dr() {
2423
2688
  return (await import("@rrweb/record")).record;
2424
2689
  }
2425
- function ot() {
2690
+ function Et() {
2426
2691
  const i = globalThis;
2427
2692
  return i.rrwebRecord?.record ?? i.rrweb?.record;
2428
2693
  }
2429
- function Ri() {
2694
+ function hr() {
2430
2695
  return new Promise((i, t) => {
2431
- const e = ot();
2696
+ const e = Et();
2432
2697
  if (e) {
2433
2698
  i(e);
2434
2699
  return;
2435
2700
  }
2436
2701
  const r = document.createElement("script");
2437
- r.src = Ti, r.integrity = Li, r.crossOrigin = "anonymous", r.onload = () => {
2438
- const s = ot();
2702
+ r.src = ar, r.integrity = lr, r.crossOrigin = "anonymous", r.onload = () => {
2703
+ const s = Et();
2439
2704
  s ? i(s) : t(new Error("rrweb record global not found after script load"));
2440
2705
  }, r.onerror = () => t(new Error("Failed to load rrweb from CDN")), document.head.appendChild(r);
2441
2706
  });
2442
2707
  }
2443
- class Di {
2444
- constructor(t, e) {
2445
- this.events = [], this.stopFn = null, this.startedAt = 0, this.timer = null, this.clickHandler = null, this.stopped = !1, this.shadow = t, this.onMaxReached = e;
2708
+ class ur {
2709
+ constructor(t, e, r = {}) {
2710
+ this.events = [], this.stopFn = null, this.startedAt = 0, this.timer = null, this.clickHandler = null, this.stopped = !1, this.destroyed = !1, this.shadow = t, this.onMaxReached = e, this.options = r;
2446
2711
  }
2447
2712
  async start() {
2448
- const t = await Mi();
2449
- this.startedAt = Date.now(), this.stopped = !1, this.stopFn = t({
2713
+ const t = await cr();
2714
+ this.destroyed || (this.startedAt = Date.now(), this.stopped = !1, this.stopFn = t({
2450
2715
  emit: (e) => {
2451
2716
  this.stopped || this.events.push(e);
2452
- }
2717
+ },
2718
+ // Default to masking every input value, not just password fields (rrweb's
2719
+ // own default). A replay is captured from whatever page the reporter happens
2720
+ // to be on, which may be a checkout or a 2FA prompt, and nothing downstream
2721
+ // scrubs it. Customers who need real values in replays must opt in.
2722
+ maskAllInputs: this.options.maskAllInputs ?? !0,
2723
+ blockClass: nr,
2724
+ maskTextClass: or
2453
2725
  }), this.clickHandler = (e) => {
2454
2726
  this.showClickRipple(e.clientX, e.clientY), t.addCustomEvent?.("mtb-click", {
2455
2727
  x: e.clientX,
@@ -2458,7 +2730,7 @@ class Di {
2458
2730
  });
2459
2731
  }, document.addEventListener("click", this.clickHandler, !0), this.timer = setTimeout(() => {
2460
2732
  this.onMaxReached?.();
2461
- }, _i * 1e3);
2733
+ }, sr * 1e3));
2462
2734
  }
2463
2735
  stop() {
2464
2736
  return this.stopped = !0, this.stopFn?.(), this.stopFn = null, this.cleanupTimer(), this.cleanupClickHandler(), {
@@ -2470,7 +2742,7 @@ class Di {
2470
2742
  return this.startedAt === 0 ? 0 : Math.max(1, Math.round((Date.now() - this.startedAt) / 1e3));
2471
2743
  }
2472
2744
  destroy() {
2473
- this.stopped = !0, this.stopFn?.(), this.stopFn = null, this.cleanupTimer(), this.cleanupClickHandler(), this.events = [], this.startedAt = 0;
2745
+ this.destroyed = !0, this.stopped = !0, this.stopFn?.(), this.stopFn = null, this.cleanupTimer(), this.cleanupClickHandler(), this.events = [], this.startedAt = 0;
2474
2746
  }
2475
2747
  cleanupTimer() {
2476
2748
  this.timer && (clearTimeout(this.timer), this.timer = null);
@@ -2483,7 +2755,7 @@ class Di {
2483
2755
  r.style.left = `${t}px`, r.style.top = `${e}px`, this.shadow.append(r), r.addEventListener("animationend", () => r.remove());
2484
2756
  }
2485
2757
  }
2486
- class Ai {
2758
+ class mr {
2487
2759
  constructor(t, e, r, s) {
2488
2760
  this.intervalId = null, this.getDuration = r, this.el = t.el("div", "mtb-record-bar"), this.el.innerHTML = `
2489
2761
  <span class="mtb-record-dot"></span>
@@ -2499,12 +2771,12 @@ class Ai {
2499
2771
  this.intervalId && (clearInterval(this.intervalId), this.intervalId = null), this.el.remove();
2500
2772
  }
2501
2773
  }
2502
- class Hi {
2774
+ class fr {
2503
2775
  constructor() {
2504
2776
  this.session = null, this.bar = null, this.result = null;
2505
2777
  }
2506
- async start(t, e, r) {
2507
- this.session = new Di(t, r), this.bar = new Ai(
2778
+ async start(t, e, r, s = {}) {
2779
+ this.session = new ur(t, r, s), this.bar = new mr(
2508
2780
  t,
2509
2781
  e,
2510
2782
  () => this.session?.getDuration() ?? 0,
@@ -2524,10 +2796,10 @@ class Hi {
2524
2796
  this.session?.destroy(), this.session = null, this.bar?.destroy(), this.bar = null;
2525
2797
  }
2526
2798
  }
2527
- const Ii = 3e3;
2528
- class B {
2799
+ const br = 3e3, Ct = 12e3;
2800
+ class K {
2529
2801
  constructor(t) {
2530
- this.tab = null, this.toolbar = null, this.session = null, this.drawBar = null, this.dim = null, this.popup = null, this.clarify = null, this.success = null, this.frustrationPrompt = null, this.frustrationDetector = null, this.mode = "idle", this.via = "pin", this.currentAnnotation = null, this.submittingUi = null, this.lastPopupPos = null, this.recordingManager = null, this.activeSubmission = null, this.submissionAttempt = 0, this.lastHandoff = {}, this.frustrationDismissedByUser = !1, this.handleKeydown = (e) => {
2802
+ this.tab = null, this.toolbar = null, this.session = null, this.drawBar = null, this.dim = null, this.popup = null, this.clarify = null, this.success = null, this.frustrationPrompt = null, this.frustrationDetector = null, this.mode = "idle", this.via = "pin", this.currentAnnotation = null, this.submittingUi = null, this.lastPopupPos = null, this.recordingManager = null, this.activeSubmission = null, this.submissionAttempt = 0, this.lastHandoff = {}, this.handleKeydown = (e) => {
2531
2803
  if (e.key === "Escape")
2532
2804
  switch (this.mode) {
2533
2805
  case "annotating":
@@ -2543,10 +2815,10 @@ class B {
2543
2815
  }
2544
2816
  }, this.handleRecordStop = () => {
2545
2817
  this.recordingManager && (this.recordingManager.stop(), this.via = "record", this.showPopup(window.innerWidth / 2, window.innerHeight / 2, this.messages.record.timer_label));
2546
- }, this.config = t, this.messages = Ci(t.locale ?? "en"), this.apiClient = new hi(t.projectKey, t.apiUrl, void 0, t.userToken, t.userTokenFn), this.consoleCollector = new Ge(), this.consoleCollector.start(), this.breadcrumbCollector = new Qe(), this.breadcrumbCollector.start(), this.buildUI(), t.frustrationDetection !== !1 && (this.frustrationDetector = new $(() => this.handleFrustration()), this.frustrationDetector.start()), document.addEventListener("keydown", this.handleKeydown, !0);
2818
+ }, this.config = t, this.messages = St(t.locale ?? document.documentElement.lang ?? "en"), this.apiClient = new me(t.projectKey, t.apiUrl, void 0, t.userToken, t.userTokenFn), this.consoleCollector = new Ai(), this.consoleCollector.start(), this.breadcrumbCollector = new Ii(), this.breadcrumbCollector.start(), this.buildUI(), t.frustrationDetection !== !1 && (this.frustrationDetector = new X(() => this.handleFrustration()), this.frustrationDetector.start()), document.addEventListener("keydown", this.handleKeydown, !0);
2547
2819
  }
2548
2820
  buildUI() {
2549
- this.shadow = new kt(this.config.theme ?? "auto"), this.tab = new St(
2821
+ this.shadow = new Vt(this.config.theme ?? "auto"), this.tab = new Yt(
2550
2822
  this.shadow,
2551
2823
  this.messages,
2552
2824
  this.config.position ?? "right",
@@ -2554,24 +2826,33 @@ class B {
2554
2826
  this.config.tabText
2555
2827
  );
2556
2828
  }
2829
+ // Takes effect for anything opened afterwards. Components already on screen keep
2830
+ // the language they were opened in rather than being re-rendered underneath a
2831
+ // reporter who may be mid-sentence.
2832
+ setLocale(t) {
2833
+ this.config.locale = t, this.messages = St(t), this.tab?.setMessages(this.messages);
2834
+ }
2557
2835
  handleTabClick() {
2558
2836
  this.mode === "idle" ? (this.dismissFrustrationPrompt(), this.enterAnnotationMode()) : this.exitAll();
2559
2837
  }
2560
2838
  handleFrustration() {
2561
- this.mode !== "idle" || this.frustrationPrompt || this.frustrationDismissedByUser || (this.frustrationPrompt = new Ct(this.shadow, this.messages, {
2839
+ this.mode !== "idle" || this.frustrationPrompt || Hi() || (this.frustrationPrompt = new Kt(this.shadow, this.messages, {
2562
2840
  onTell: () => {
2563
2841
  this.dismissFrustrationPrompt(), this.enterAnnotationMode();
2564
2842
  },
2565
2843
  onDismiss: () => {
2566
- this.frustrationDismissedByUser = !0, this.dismissFrustrationPrompt();
2567
- }
2844
+ $i(), this.dismissFrustrationPrompt();
2845
+ },
2846
+ // An unnoticed card is not a refusal, so it must not suppress later
2847
+ // prompts. The detector's own 60s cooldown does the rate limiting.
2848
+ onAutoHide: () => this.dismissFrustrationPrompt()
2568
2849
  }));
2569
2850
  }
2570
2851
  dismissFrustrationPrompt() {
2571
2852
  this.frustrationPrompt?.destroy(), this.frustrationPrompt = null;
2572
2853
  }
2573
2854
  enterAnnotationMode() {
2574
- this.mode = "annotating", this.tab?.setActive(!0), this.toolbar = new Tt(
2855
+ this.mode = "annotating", this.tab?.setActive(!0), this.toolbar = new Qt(
2575
2856
  this.shadow,
2576
2857
  this.messages,
2577
2858
  () => this.exitAll(),
@@ -2579,7 +2860,7 @@ class B {
2579
2860
  ), this.session = this.createSession();
2580
2861
  }
2581
2862
  createSession() {
2582
- return new It(this.shadow, this.messages, {
2863
+ return new ae(this.shadow, this.messages, {
2583
2864
  onPin: (t, e) => {
2584
2865
  this.currentAnnotation = t, this.via = "pin", this.showPopup(t.x, t.y, e, t.targetRect);
2585
2866
  },
@@ -2593,14 +2874,19 @@ class B {
2593
2874
  }
2594
2875
  if (t === "record") {
2595
2876
  if (this.mode === "recording") return;
2596
- this.mode = "recording", this.currentAnnotation = null, this.teardownDraw(), this.session?.destroy(), this.session = null, this.recordingManager = new Hi(), this.recordingManager.start(this.shadow, this.messages, this.handleRecordStop).catch((e) => {
2877
+ this.mode = "recording", this.currentAnnotation = null, this.teardownDraw(), this.session?.destroy(), this.session = null, this.recordingManager = new fr(), this.recordingManager.start(
2878
+ this.shadow,
2879
+ this.messages,
2880
+ this.handleRecordStop,
2881
+ this.config.recording ?? {}
2882
+ ).catch((e) => {
2597
2883
  console.warn("[MakeThisBetter] Interaction replay unavailable, falling back to markup:", e), this.mode === "recording" && (this.toolbar?.setMode("markup"), this.handleToolbarModeChange("markup"));
2598
2884
  });
2599
2885
  } else
2600
2886
  this.recordingManager?.destroy(), this.recordingManager = null, this.teardownDraw(), this.session || (this.session = this.createSession()), this.mode = "annotating";
2601
2887
  }
2602
2888
  handleDrawStroke() {
2603
- this.mode !== "drawing" && (this.mode = "drawing", this.drawBar = new Bt(this.shadow, {
2889
+ this.mode !== "drawing" && (this.mode = "drawing", this.drawBar = new ce(this.shadow, {
2604
2890
  messages: this.messages,
2605
2891
  onUndo: () => this.handleDrawUndoRedo("undo"),
2606
2892
  onRedo: () => this.handleDrawUndoRedo("redo"),
@@ -2629,7 +2915,7 @@ class B {
2629
2915
  this.currentAnnotation = e, this.via = "draw", this.session?.dismissInteraction(), this.submittingUi = this.drawBar, this.handleSubmit(t || this.messages.annotation.drawing);
2630
2916
  }
2631
2917
  showPopup(t, e, r, s) {
2632
- this.mode = "popup", this.lastPopupPos = { x: t, y: e }, this.teardownDraw(), this.session?.dismissInteraction(), this.popup?.destroy(), this.popup = null, this.dim?.destroy(), this.dim = null, this.dim = new _t(this.shadow, () => this.exitAll()), this.popup = new Ft(this.shadow, {
2918
+ this.mode = "popup", this.lastPopupPos = { x: t, y: e }, this.teardownDraw(), this.session?.dismissInteraction(), this.popup?.destroy(), this.popup = null, this.dim?.destroy(), this.dim = null, this.dim = new Gt(this.shadow, () => this.exitAll()), this.popup = new de(this.shadow, {
2633
2919
  targetName: r,
2634
2920
  x: t,
2635
2921
  y: e,
@@ -2642,29 +2928,29 @@ class B {
2642
2928
  }), this.submittingUi = this.popup;
2643
2929
  }
2644
2930
  buildMyFeedbackHandler() {
2645
- if (!this.config.user && gi())
2931
+ if (!this.config.user && Gi())
2646
2932
  return async () => {
2647
- const t = await this.apiClient.createIdentityToken(it());
2648
- !t?.identity_token || !t.board_url || (st(t.board_url), window.open(`${t.board_url}?identity=${encodeURIComponent(t.identity_token)}`, "_blank"));
2933
+ const t = await this.apiClient.createIdentityToken(wt());
2934
+ !t?.identity_token || !t.board_url || (xt(t.board_url), window.open(`${t.board_url}?identity=${encodeURIComponent(t.identity_token)}`, "_blank"));
2649
2935
  };
2650
2936
  }
2651
2937
  async handleSubmit(t) {
2652
2938
  const e = this.submittingUi;
2653
2939
  if (!e) return;
2654
2940
  const r = ++this.submissionAttempt;
2655
- e.setLoading(!0), await $i();
2941
+ e.setLoading(!0), await pr();
2656
2942
  const s = this.currentAnnotation, n = this.recordingManager?.getRecording() ?? void 0, [o, a] = await Promise.all([
2657
- Oe(s ? [s] : []),
2658
- Promise.resolve(ai())
2659
- ]), l = pi(
2943
+ xi(s ? [s] : []),
2944
+ Promise.resolve(Wi())
2945
+ ]), l = Xi(
2660
2946
  t,
2661
2947
  a,
2662
2948
  this.consoleCollector.getErrors(),
2663
2949
  s,
2664
2950
  this.config.user,
2665
2951
  n,
2666
- this.config.user ? void 0 : it(),
2667
- this.config.user ? void 0 : rt(),
2952
+ this.config.user ? void 0 : wt(),
2953
+ this.config.user ? void 0 : vt(),
2668
2954
  this.breadcrumbCollector.getBreadcrumbs()
2669
2955
  );
2670
2956
  try {
@@ -2682,31 +2968,35 @@ class B {
2682
2968
  }
2683
2969
  async speculativeClarify(t, e, r) {
2684
2970
  if (!t.ai_clarify_available) {
2685
- const l = this.teardownSubmittingUi(!0);
2971
+ const u = this.teardownSubmittingUi(!0);
2686
2972
  this.showClarify(t, e, {
2687
- element: l,
2973
+ element: u,
2688
2974
  preloadedResult: { messages: [], done: !0 }
2689
2975
  });
2690
2976
  return;
2691
2977
  }
2692
- const s = this.apiClient.streamClarification(
2978
+ const s = new AbortController();
2979
+ let n = setTimeout(() => s.abort(), Ct);
2980
+ const o = () => {
2981
+ clearTimeout(n), n = setTimeout(() => s.abort(), Ct);
2982
+ }, a = this.apiClient.streamClarification(
2693
2983
  t.id,
2694
2984
  t.token,
2695
- () => {
2696
- }
2697
- ).catch(() => null), n = new Promise(
2698
- (l) => setTimeout(() => l(null), Ii)
2699
- ), o = await Promise.race([s, n]);
2985
+ o,
2986
+ s.signal
2987
+ ).catch(() => null).finally(() => clearTimeout(n)), l = new Promise(
2988
+ (u) => setTimeout(() => u(null), br)
2989
+ ), c = await Promise.race([a, l]);
2700
2990
  if (r !== this.submissionAttempt) return;
2701
- const a = this.teardownSubmittingUi(!0);
2702
- o ? this.showClarify(t, e, { element: a, preloadedResult: o }) : this.showClarify(t, e, { element: a, pendingClarification: s });
2991
+ const d = this.teardownSubmittingUi(!0);
2992
+ c ? this.showClarify(t, e, { element: d, preloadedResult: c }) : this.showClarify(t, e, { element: d, pendingClarification: a });
2703
2993
  }
2704
2994
  teardownSubmittingUi(t = !1) {
2705
2995
  const e = t ? this.popup?.releaseElement() : void 0;
2706
2996
  return this.teardownDraw(), e || this.popup?.destroy(), this.popup = null, this.dim?.destroy(), this.dim = null, this.session?.hideHighlight(), this.session?.destroy(), this.session = null, this.recordingManager?.destroy(), this.recordingManager = null, this.submittingUi = null, e;
2707
2997
  }
2708
2998
  showClarify(t, e, r) {
2709
- this.mode = "clarifying", this.tab?.setActive(!0), this.clarify = new qt(this.shadow, {
2999
+ this.mode = "clarifying", this.tab?.setActive(!0), this.clarify = new xe(this.shadow, {
2710
3000
  submissionSessionId: t.id,
2711
3001
  submissionToken: t.token,
2712
3002
  apiClient: this.apiClient,
@@ -2728,21 +3018,21 @@ class B {
2728
3018
  feedbackId: r.id,
2729
3019
  boardUrl: r.board_url,
2730
3020
  identityToken: r.identity_token
2731
- }, r.board_url && st(r.board_url), this.clarify?.destroy(), this.clarify = null, this.toolbar?.destroy(), this.toolbar = null, this.showSuccess({ skipFollowup: t.ai_clarify_available === !1 }));
3021
+ }, r.board_url && xt(r.board_url), this.clarify?.destroy(), this.clarify = null, this.toolbar?.destroy(), this.toolbar = null, this.showSuccess({ skipFollowup: t.ai_clarify_available === !1 }));
2732
3022
  }
2733
3023
  showSuccess(t) {
2734
- this.mode = "idle", this.tab?.setActive(!1), this.success = new Vt(this.shadow, this.messages, () => {
3024
+ this.mode = "idle", this.tab?.setActive(!1), this.success = new Ee(this.shadow, this.messages, () => {
2735
3025
  this.success?.destroy(), this.success = null;
2736
3026
  }, this.buildViewFeedbackHandler(), { ...t, emailCapture: this.buildEmailCapture() });
2737
3027
  }
2738
3028
  buildEmailCapture() {
2739
3029
  if (this.config.user) return;
2740
3030
  const { feedbackId: t, identityToken: e } = this.lastHandoff;
2741
- if (!(!t || !e) && !rt())
3031
+ if (!(!t || !e) && !vt())
2742
3032
  return {
2743
3033
  onSubmit: async (r) => {
2744
3034
  const s = await this.apiClient.updateReporter(t, r, e);
2745
- return s && bi(r), s;
3035
+ return s && Ki(r), s;
2746
3036
  }
2747
3037
  };
2748
3038
  }
@@ -2770,24 +3060,28 @@ class B {
2770
3060
  document.removeEventListener("keydown", this.handleKeydown, !0), this.exitAll(), this.consoleCollector.stop(), this.breadcrumbCollector.stop(), this.frustrationDetector?.stop(), this.dismissFrustrationPrompt(), this.clarify?.destroy(), this.success?.destroy(), this.tab?.destroy(), this.recordingManager?.destroy(), this.shadow.destroy();
2771
3061
  }
2772
3062
  }
2773
- function $i() {
3063
+ function pr() {
2774
3064
  return new Promise((i) => requestAnimationFrame(() => setTimeout(i, 0)));
2775
3065
  }
2776
- let w = null, R = null;
2777
- const Bi = {
3066
+ let w = null, E = null;
3067
+ const gr = {
2778
3068
  init(i) {
2779
- w && (w.destroy(), w = null), R = i, document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => {
2780
- w = new B(i);
2781
- }) : w = new B(i);
3069
+ w && (w.destroy(), w = null), E = i, document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => {
3070
+ w = new K(i);
3071
+ }) : w = new K(i);
2782
3072
  },
2783
3073
  destroy() {
2784
- w?.destroy(), w = null, R = null;
3074
+ w?.destroy(), w = null, E = null;
3075
+ },
3076
+ setLocale(i) {
3077
+ E && (E.locale = i), w?.setLocale(i);
2785
3078
  }
2786
3079
  };
2787
- typeof window < "u" && (window.MakeThisBetter = Bi, document.addEventListener("turbo:load", () => {
2788
- R && !document.getElementById("mtb-widget-host") && (w?.destroy(), w = new B(R));
3080
+ typeof window < "u" && (window.MakeThisBetter = gr, document.addEventListener("turbo:load", () => {
3081
+ const i = document.getElementById("mtb-widget-host");
3082
+ E && (!i || !i.shadowRoot) && (w?.destroy(), i?.remove(), w = new K(E));
2789
3083
  }));
2790
3084
  export {
2791
- Bi as MakeThisBetter
3085
+ gr as MakeThisBetter
2792
3086
  };
2793
3087
  //# sourceMappingURL=makethisbetter.esm.js.map