@gemboss/ui 0.36.1 → 0.40.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 (47) hide show
  1. package/CHANGELOG.md +441 -0
  2. package/README.md +617 -14
  3. package/catalog/editor.html +45 -25
  4. package/catalog/index.html +5522 -1448
  5. package/gemboss-ui.css +3 -3
  6. package/package.json +11 -2
  7. package/parts/components.css +2 -2
  8. package/parts/core.css +1 -1
  9. package/parts/shell.css +2 -2
  10. package/src/assistant/chat-markdown.ts +7 -4
  11. package/src/assistant.css +1 -1
  12. package/src/auth-field.css +1 -0
  13. package/src/auth-field.tsx +74 -0
  14. package/src/auth-sso-plain.js +1 -0
  15. package/src/auth.css +1 -1
  16. package/src/auth.tsx +64 -1
  17. package/src/brand-gem.tsx +19 -0
  18. package/src/brand.tsx +4 -7
  19. package/src/chat-plain.js +2 -2
  20. package/src/editor/controls.tsx +148 -11
  21. package/src/editor/frame.tsx +8 -4
  22. package/src/editor/index.ts +8 -4
  23. package/src/editor/panel.tsx +44 -14
  24. package/src/editor/repeater.tsx +322 -0
  25. package/src/editor/sortable.tsx +50 -24
  26. package/src/editor/swatch.ts +20 -0
  27. package/src/editor/tiles.tsx +51 -0
  28. package/src/editor-plain.js +1 -1
  29. package/src/editor-repeater.css +1 -0
  30. package/src/editor-tiles.css +1 -0
  31. package/src/editor.css +1 -1
  32. package/src/gemboss-field.css +1 -1
  33. package/src/icons.tsx +11 -0
  34. package/src/index.ts +14 -2
  35. package/src/kit-plain.js +1 -1
  36. package/src/service-switcher-plain.js +1 -1
  37. package/src/service-switcher.css +1 -1
  38. package/src/service-switcher.tsx +119 -35
  39. package/src/services.ts +4 -2
  40. package/src/shell.css +1 -1
  41. package/src/site.css +1 -0
  42. package/src/site.tsx +50 -0
  43. package/src/team-chat-data.ts +79 -0
  44. package/src/team-chat.css +1 -0
  45. package/src/team-chat.tsx +825 -0
  46. package/src/toggle-bar.tsx +60 -0
  47. package/src/ui.css +1 -1
@@ -0,0 +1 @@
1
+ (function(i){"use strict";var g=i.gembossUI||(i.gembossUI={}),d="https://admin.gemboss.ai",l={not_member:"Your GemBoss account does not have access here. Use the password.",invalid:"That sign-in did not go through. Try again, or use the password.",off:"Signing in with GemBoss is not available here yet. Use the password."},f='<svg viewBox="0 0 32 32" width="18" height="18" aria-hidden="true" focusable="false"><rect width="32" height="32" rx="7"/><g transform="translate(16,16) scale(0.24) translate(-50,-62)"><polygon points="26,14 74,14 66,50 34,50" fill="#8a93ff"/><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="#f4f4f2" stroke-width="5" stroke-linejoin="round"/><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="#f4f4f2" stroke-opacity="0.72" stroke-width="3" stroke-linejoin="round"/></g></svg>';function b(){var s=document.querySelectorAll("a[data-gb-sso]");if(!s.length)return!1;var t=new URLSearchParams(location.search),h=t.get("sso"),c=!t.has("sso")&&t.get("password")!=="1"&&/(?:^|;\s*)gb_sso=1(?:;|$)/.test(document.cookie),o=null;return s.forEach(function(e){var m=(e.getAttribute("data-issuer")||d)+"/api/auth/sso/authorize?service="+encodeURIComponent(e.getAttribute("data-gb-sso"))+"&next="+encodeURIComponent(e.getAttribute("data-next")||"/");e.href=m,o=o||e,e.querySelector("svg")||(e.innerHTML=f+'<span class="gb-auth-sso-label">Continue with GemBoss</span>',e.querySelector("rect").style.fill="var(--gb-mark-bg, #0b0b0c)");var r=e.closest(".gb-auth-sso")||e.parentNode;if(h&&!r.querySelector(".gb-auth-sso-why")){var n=document.createElement("p");n.className="gb-auth-sso-why",n.setAttribute("role","status"),n.textContent=l[h]||l.invalid,e.after(n)}if(!r.querySelector(".gb-auth-or")){var a=document.createElement("p");a.className="gb-auth-or",a.textContent="or use the password",r.append(a)}e.addEventListener("click",function(){u(e)})}),c&&(u(o),location.replace(o.href)),c}function u(s){var t=s.querySelector(".gb-auth-sso-label");t&&(t.textContent="Continuing with GemBoss\u2026")}g.initContinueWithGemBoss=b})(typeof globalThis<"u"?globalThis:this);
package/src/auth.css CHANGED
@@ -1 +1 @@
1
- .gb-auth{--gb-surface: #ffffff;--gb-ink: var(--gemboss-text-strong, #1b1c1e);--gb-muted: #6d7175;--gb-line: #e1e3e5;--gb-field-line: #c9cccf;--gb-field-bg: #ffffff;--gb-field-hover: #fafafa;--gb-placeholder: #868b94;--gb-accent: #5661f5;--gb-btn: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-btn-ink: #ffffff;--gb-wordmark: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-hover: #f7f7f5;--gb-hover-line: #b9bbc0;--gb-err-bg: #fee2e2;--gb-err-ink: #b91c1c;--gb-err-line: transparent;--gb-card-shadow: 0 24px 64px rgba(15, 23, 42, .08);--gb-mark-bg: #0b0b0c;--gb-facet: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 120'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='0.45' stroke-linejoin='round'%3E%3Cpath d='M26,14 74,14 96,50 50,110 4,50Z'/%3E%3Cpath d='M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110'/%3E%3C/g%3E%3C/svg%3E");--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(27, 28, 30, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(86, 97, 245, .06), transparent 60%), #fafafb;--gb-page-flat: #ffffff;--gb-panel-bg: radial-gradient(900px 520px at 78% 12%, rgba(86, 97, 245, .26), transparent 62%), radial-gradient(700px 480px at 12% 96%, rgba(86, 97, 245, .12), transparent 60%), #0b0b0c;--gb-panel-ink: #f4f4f2;--gb-panel-muted: rgba(244, 244, 242, .72);--gb-panel-eyebrow: #8a93ff;--gb-panel-facet-o: .05;--gb-panel-grid-bg: linear-gradient(160deg, #1b1c22 0%, #0b0b0c 72%);--gb-panel-grid-line: rgba(138, 147, 255, .1);--gb-panel-grid-size: 34px;--gb-panel-grid-fade: radial-gradient(90% 80% at 30% 20%, #000, transparent 75%);color-scheme:light dark;position:fixed;top:var(--vvt, 0px);left:0;right:0;height:100vh;height:var(--vvh, 100dvh);container:gb-auth / size;overflow-y:auto;background:var(--gb-page);color:var(--gb-ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif}.gb-auth-split{display:grid;grid-template-columns:1fr;min-height:100%}.gb-auth-stage{box-sizing:border-box;display:flex;min-height:100%;padding:clamp(12px,3cqh,24px) clamp(16px,4vw,24px)}.gb-auth-panel-in{position:relative;box-sizing:border-box;width:100%;max-width:520px;padding:48px clamp(32px,5vw,64px)}.gb-auth-eyebrow{margin:0 0 20px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:12px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;color:var(--gb-panel-eyebrow)}.gb-auth-panel-h{margin:0 0 16px;font-size:clamp(28px,3.2vw,40px);line-height:1.15;letter-spacing:-.02em;font-weight:700;color:var(--gb-panel-ink)}.gb-auth-panel-p{margin:0;font-size:15px;line-height:1.6;color:var(--gb-panel-muted)}.gb-auth-panel{display:none}@container gb-auth (min-width: 900px) and (min-height: 520px){.gb-auth-split{grid-template-columns:minmax(420px,1fr) minmax(0,1.05fr)}.gb-auth-split .gb-auth-stage{background:var(--gb-surface)}.gb-auth-split .gb-auth-card{border:none;box-shadow:none;max-width:400px}.gb-auth-panel{display:flex;align-items:center;position:relative;overflow:hidden;background:var(--gb-panel-bg);color:var(--gb-panel-ink)}.gb-auth-panel:before{content:"";position:absolute;inset:-45% -38% auto auto;width:132%;aspect-ratio:1;background-image:var(--gb-facet);background-size:contain;background-repeat:no-repeat;opacity:var(--gb-panel-facet-o);pointer-events:none}.gb-auth-split .gb-auth-panel--grid{background:var(--gb-panel-grid-bg)}.gb-auth-panel.gb-auth-panel--grid:before{inset:0;width:auto;aspect-ratio:auto;background-image:linear-gradient(var(--gb-panel-grid-line) 1px,transparent 1px),linear-gradient(90deg,var(--gb-panel-grid-line) 1px,transparent 1px);background-size:var(--gb-panel-grid-size) var(--gb-panel-grid-size);background-repeat:repeat;opacity:1;-webkit-mask-image:var(--gb-panel-grid-fade);mask-image:var(--gb-panel-grid-fade)}.gb-auth-panel.gb-auth-panel--none:before{content:none}}.gb-auth-card{width:100%;max-width:380px;margin:auto;background:var(--gb-surface);border:1px solid var(--gb-line);border-radius:14px;padding:clamp(18px,3.5cqh,28px) 28px;box-shadow:var(--gb-card-shadow)}.gb-auth-header{text-align:center;margin-bottom:clamp(12px,3cqh,24px)}.gb-auth-mark{display:inline-flex;margin-bottom:clamp(6px,calc(6px + (100cqh - 480px)*.075),12px)}.gb-auth-mark svg,.gb-auth-mark img{width:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px);height:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px)}@container gb-auth (max-height: 479.98px){.gb-auth-mark{display:none}}.gb-auth-header h1{font-size:clamp(19px,2.75cqh,22px);font-weight:700;margin:0 0 clamp(0px,calc((100cqh - 560px)*.1),4px);background:var(--gb-wordmark);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.gb-auth-header p{margin:0;font-size:13px;color:var(--gb-muted)}@container gb-auth (max-height: 599.98px){.gb-auth-header p{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}.gb-auth-form{display:flex;flex-direction:column;gap:clamp(8px,1.5cqh,12px)}.gb-auth-form label{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-input{box-sizing:border-box;height:32px;min-height:44px;min-width:0;padding:0 12px;font:inherit;font-size:13px;line-height:20px;border:1px solid;border-radius:8px}@media (max-width: 47.9975em){.gb-auth-input{font-size:16px}}@media (pointer: coarse){.gb-auth-input{height:auto}}.gb-auth-form input{width:100%;box-sizing:border-box;background-color:var(--gb-field-bg);border-color:var(--gb-field-line);color:var(--gb-ink)}.gb-auth-form input::placeholder{color:var(--gb-placeholder)}.gb-auth-form input:hover:not(:disabled){background-color:var(--gb-field-hover);border-color:var(--gb-hover-line)}.gb-auth-form input:focus-visible{outline:2px solid var(--gb-ink);outline-offset:1px;border-color:var(--gb-ink)}.gb-auth-field{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-pw{position:relative;display:flex}.gb-auth-pw input{width:100%;padding-right:48px}.gb-auth-pw-toggle{min-height:44px;min-width:44px;position:absolute;right:0;top:0;bottom:0;display:inline-flex;align-items:center;justify-content:center;padding:0;margin:0;background:none;border:none;border-radius:8px;cursor:pointer;color:var(--gb-muted);transition:none}.gb-auth-pw-toggle:hover{color:var(--gb-ink)}.gb-auth-pw-toggle:focus-visible{outline:2px solid var(--gemboss-primary, #1b1c1e);outline-offset:-2px}.gb-auth-error{background:var(--gb-err-bg);border:1px solid var(--gb-err-line);color:var(--gb-err-ink);padding:8px 10px;font-size:13px;border-radius:6px}.gb-auth-form>.gb-auth-submit{margin-top:clamp(2px,.75cqh,6px);min-height:44px;font-size:14px;font-weight:600;border:none;border-radius:8px;background:var(--gb-btn);color:var(--gb-btn-ink);cursor:pointer;font-family:inherit;transition:opacity .15s ease,transform .15s ease}.gb-auth-form>.gb-auth-submit:hover:not(:disabled){transform:translateY(-1px)}.gb-auth-form>.gb-auth-submit:disabled{opacity:.6;cursor:not-allowed}.gb-auth-foot{margin:clamp(10px,2cqh,16px) 0 0;font-size:13px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-foot a{display:inline-block;min-height:24px;line-height:24px;padding:0 2px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-foot a:hover,.gb-auth-foot a:focus-visible{text-decoration:underline}.gb-auth-card .gb-auth-help{margin:clamp(8px,1.75cqh,14px) 0 0;font-size:12px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-card .gb-auth-help a{display:inline-block;min-height:24px;line-height:24px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-card .gb-auth-help a:hover,.gb-auth-card .gb-auth-help a:focus-visible{text-decoration:underline}@media (max-width: 480px){.gb-auth{background:var(--gb-page-flat)}.gb-auth-stage{padding:max(clamp(10px,3cqh,20px),env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(clamp(10px,3cqh,20px),env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left))}.gb-auth-card{border:none;border-radius:0;box-shadow:none;padding:0}}@container gb-auth (max-height: 399.98px){.gb-auth-header{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}@container gb-auth (max-height: 359.98px){.gb-auth-card .gb-auth-help,.gb-auth-foot{display:none}.gb-auth-stage{padding-top:max(8px,env(safe-area-inset-top));padding-bottom:max(8px,env(safe-area-inset-bottom))}}@container gb-auth (max-height: 359.98px) and (min-width: 481px){.gb-auth-card{padding-top:14px;padding-bottom:14px}}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}}:root[data-theme=dark] .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}
1
+ .gb-auth{--gb-surface: #ffffff;--gb-ink: var(--gemboss-text-strong, #1b1c1e);--gb-muted: #6d7175;--gb-line: #e1e3e5;--gb-field-line: #c9cccf;--gb-field-bg: #ffffff;--gb-field-hover: #fafafa;--gb-placeholder: #868b94;--gb-accent: #5661f5;--gb-btn: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-btn-ink: #ffffff;--gb-wordmark: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-hover: #f7f7f5;--gb-hover-line: #b9bbc0;--gb-err-bg: #fee2e2;--gb-err-ink: #b91c1c;--gb-err-line: transparent;--gb-card-shadow: 0 24px 64px rgba(15, 23, 42, .08);--gb-mark-bg: #0b0b0c;--gb-facet: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 120'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='0.45' stroke-linejoin='round'%3E%3Cpath d='M26,14 74,14 96,50 50,110 4,50Z'/%3E%3Cpath d='M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110'/%3E%3C/g%3E%3C/svg%3E");--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(27, 28, 30, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(86, 97, 245, .06), transparent 60%), #fafafb;--gb-page-flat: #ffffff;--gb-panel-bg: radial-gradient(900px 520px at 78% 12%, rgba(86, 97, 245, .26), transparent 62%), radial-gradient(700px 480px at 12% 96%, rgba(86, 97, 245, .12), transparent 60%), #0b0b0c;--gb-panel-ink: #f4f4f2;--gb-panel-muted: rgba(244, 244, 242, .72);--gb-panel-eyebrow: #8a93ff;--gb-panel-facet-o: .05;--gb-panel-grid-bg: linear-gradient(160deg, #1b1c22 0%, #0b0b0c 72%);--gb-panel-grid-line: rgba(138, 147, 255, .1);--gb-panel-grid-size: 34px;--gb-panel-grid-fade: radial-gradient(90% 80% at 30% 20%, #000, transparent 75%);color-scheme:light dark;position:fixed;top:var(--vvt, 0px);left:0;right:0;height:100vh;height:var(--vvh, 100dvh);container:gb-auth / size;overflow-y:auto;background:var(--gb-page);color:var(--gb-ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif}.gb-auth-split{display:grid;grid-template-columns:1fr;min-height:100%}.gb-auth-stage{box-sizing:border-box;display:flex;min-height:100%;padding:clamp(12px,3cqh,24px) clamp(16px,4vw,24px)}.gb-auth-panel-in{position:relative;box-sizing:border-box;width:100%;max-width:520px;padding:48px clamp(32px,5vw,64px)}.gb-auth-eyebrow{margin:0 0 20px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:12px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;color:var(--gb-panel-eyebrow)}.gb-auth-panel-h{margin:0 0 16px;font-size:clamp(28px,3.2vw,40px);line-height:1.15;letter-spacing:-.02em;font-weight:700;color:var(--gb-panel-ink)}.gb-auth-panel-p{margin:0;font-size:15px;line-height:1.6;color:var(--gb-panel-muted)}.gb-auth-panel{display:none}@container gb-auth (min-width: 900px) and (min-height: 520px){.gb-auth-split{grid-template-columns:minmax(420px,1fr) minmax(0,1.05fr)}.gb-auth-split .gb-auth-stage{background:var(--gb-surface)}.gb-auth-split .gb-auth-card{border:none;box-shadow:none;max-width:400px}.gb-auth-panel{display:flex;align-items:center;position:relative;overflow:hidden;background:var(--gb-panel-bg);color:var(--gb-panel-ink)}.gb-auth-panel:before{content:"";position:absolute;inset:-45% -38% auto auto;width:132%;aspect-ratio:1;background-image:var(--gb-facet);background-size:contain;background-repeat:no-repeat;opacity:var(--gb-panel-facet-o);pointer-events:none}.gb-auth-split .gb-auth-panel--grid{background:var(--gb-panel-grid-bg)}.gb-auth-panel.gb-auth-panel--grid:before{inset:0;width:auto;aspect-ratio:auto;background-image:linear-gradient(var(--gb-panel-grid-line) 1px,transparent 1px),linear-gradient(90deg,var(--gb-panel-grid-line) 1px,transparent 1px);background-size:var(--gb-panel-grid-size) var(--gb-panel-grid-size);background-repeat:repeat;opacity:1;-webkit-mask-image:var(--gb-panel-grid-fade);mask-image:var(--gb-panel-grid-fade)}.gb-auth-panel.gb-auth-panel--none:before{content:none}}.gb-auth-card{width:100%;max-width:380px;margin:auto;background:var(--gb-surface);border:1px solid var(--gb-line);border-radius:14px;padding:clamp(18px,3.5cqh,28px) 28px;box-shadow:var(--gb-card-shadow)}.gb-auth-header{text-align:center;margin-bottom:clamp(12px,3cqh,24px)}.gb-auth-mark{display:inline-flex;margin-bottom:clamp(6px,calc(6px + (100cqh - 480px)*.075),12px)}.gb-auth-mark svg,.gb-auth-mark img{width:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px);height:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px)}@container gb-auth (max-height: 479.98px){.gb-auth-mark{display:none}}.gb-auth-header h1{font-size:clamp(19px,2.75cqh,22px);font-weight:700;margin:0 0 clamp(0px,calc((100cqh - 560px)*.1),4px);background:var(--gb-wordmark);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.gb-auth-header p{margin:0;font-size:13px;color:var(--gb-muted)}@container gb-auth (max-height: 599.98px){.gb-auth-header p{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}.gb-auth-form{display:flex;flex-direction:column;gap:clamp(8px,1.5cqh,12px)}.gb-auth-form label{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-input{box-sizing:border-box;height:32px;min-height:44px;min-width:0;padding:0 12px;font:inherit;font-size:13px;line-height:20px;border:1px solid;border-radius:8px}@media (max-width: 47.9975em){.gb-auth-input{font-size:16px}}@media (pointer: coarse){.gb-auth-input{height:auto}}.gb-auth-form input{width:100%;box-sizing:border-box;background-color:var(--gb-field-bg);border-color:var(--gb-field-line);color:var(--gb-ink)}.gb-auth-form input::placeholder{color:var(--gb-placeholder)}.gb-auth-form input:hover:not(:disabled){background-color:var(--gb-field-hover);border-color:var(--gb-hover-line)}.gb-auth-form input:focus-visible{outline:2px solid var(--gb-ink);outline-offset:1px;border-color:var(--gb-ink)}.gb-auth-field{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-pw{position:relative;display:flex}.gb-auth-pw input{width:100%;padding-right:48px}.gb-auth-pw-toggle{min-height:44px;min-width:44px;position:absolute;right:0;top:0;bottom:0;display:inline-flex;align-items:center;justify-content:center;padding:0;margin:0;background:none;border:none;border-radius:8px;cursor:pointer;color:var(--gb-muted);transition:none}.gb-auth-pw-toggle:hover{color:var(--gb-ink)}.gb-auth-pw-toggle:focus-visible{outline:2px solid var(--gemboss-primary, #1b1c1e);outline-offset:-2px}.gb-auth-error{background:var(--gb-err-bg);border:1px solid var(--gb-err-line);color:var(--gb-err-ink);padding:8px 10px;font-size:13px;border-radius:6px}.gb-auth-form>.gb-auth-submit{margin-top:clamp(2px,.75cqh,6px);min-height:44px;font-size:14px;font-weight:600;border:none;border-radius:8px;background:var(--gb-btn);color:var(--gb-btn-ink);cursor:pointer;font-family:inherit;transition:opacity .15s ease,transform .15s ease}.gb-auth-form>.gb-auth-submit:hover:not(:disabled){transform:translateY(-1px)}.gb-auth-form>.gb-auth-submit:disabled{opacity:.6;cursor:not-allowed}.gb-auth-sso-btn{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 16px;border:1px solid var(--gb-field-line);border-radius:8px;background:var(--gb-surface);color:var(--gb-ink);font-size:14px;font-weight:600;text-decoration:none;transition:background .15s,border-color .15s}.gb-auth-sso-btn:hover{background:var(--gb-hover);border-color:var(--gb-hover-line)}.gb-auth-sso-btn:focus-visible{outline:2px solid var(--gb-ink);outline-offset:1px}.gb-auth-sso-why{margin:8px 0 0;font-size:12px;line-height:1.5;color:var(--gb-muted);text-align:center}.gb-auth-sso .gb-auth-or{display:flex;align-items:center;gap:12px;margin:clamp(8px,1.75cqh,14px) 0;color:var(--gb-muted);font-size:12px}.gb-auth-sso .gb-auth-or:before,.gb-auth-sso .gb-auth-or:after{content:"";flex:1;height:1px;background:var(--gb-line)}.gb-auth-foot{margin:clamp(10px,2cqh,16px) 0 0;font-size:13px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-foot a{display:inline-block;min-height:24px;line-height:24px;padding:0 2px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-foot a:hover,.gb-auth-foot a:focus-visible{text-decoration:underline}.gb-auth-card .gb-auth-help{margin:clamp(8px,1.75cqh,14px) 0 0;font-size:12px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-card .gb-auth-help a{display:inline-block;min-height:24px;line-height:24px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-card .gb-auth-help a:hover,.gb-auth-card .gb-auth-help a:focus-visible{text-decoration:underline}@media (max-width: 480px){.gb-auth{background:var(--gb-page-flat)}.gb-auth-stage{padding:max(clamp(10px,3cqh,20px),env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(clamp(10px,3cqh,20px),env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left))}.gb-auth-card{border:none;border-radius:0;box-shadow:none;padding:0}}@container gb-auth (max-height: 399.98px){.gb-auth-header{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}@container gb-auth (max-height: 359.98px){.gb-auth-card .gb-auth-help,.gb-auth-foot{display:none}.gb-auth-stage{padding-top:max(8px,env(safe-area-inset-top));padding-bottom:max(8px,env(safe-area-inset-bottom))}}@container gb-auth (max-height: 359.98px) and (min-width: 481px){.gb-auth-card{padding-top:14px;padding-bottom:14px}}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}}:root[data-theme=dark] .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}
package/src/auth.tsx CHANGED
@@ -37,7 +37,7 @@ const BACKDROP: Record<AuthBackdrop, string> = { facet: "", grid: "gb-auth-panel
37
37
  * The whole screen. `children` is everything inside the card below the heading: the form, then any
38
38
  * lines under it.
39
39
  */
40
- export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", className, children }: {
40
+ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", art, className, children }: {
41
41
  /** The page heading (h1) in the card. */
42
42
  brand: React.ReactNode;
43
43
  /** One line under the heading; the first thing shed on a short screen. */
@@ -48,6 +48,9 @@ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", cl
48
48
  panel?: { eyebrow?: React.ReactNode; heading: React.ReactNode; body?: React.ReactNode };
49
49
  /** The panel's ground pattern; see `AuthBackdrop`. Only drawn where the panel is (900 wide AND 520 tall). */
50
50
  backdrop?: AuthBackdrop;
51
+ /** Drawn on the panel, under its words (16/10/2026): `AuthPageField`, or anything else that is decoration. Pair it
52
+ * with `backdrop="none"`. Only drawn where the panel is. */
53
+ art?: React.ReactNode;
51
54
  className?: string;
52
55
  children?: React.ReactNode;
53
56
  }) {
@@ -105,6 +108,7 @@ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", cl
105
108
  them. Nothing in it is focusable — it is decoration beside the form, not a second path. */}
106
109
  {panel ? (
107
110
  <aside className={cx("gb-auth-panel", BACKDROP[backdrop])}>
111
+ {art}
108
112
  <div className="gb-auth-panel-in">
109
113
  {panel.eyebrow ? <p className="gb-auth-eyebrow">{panel.eyebrow}</p> : null}
110
114
  <h2 className="gb-auth-panel-h">{panel.heading}</h2>
@@ -117,6 +121,65 @@ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", cl
117
121
  );
118
122
  }
119
123
 
124
+ /**
125
+ * "Continue with GemBoss" (16/10/2026): the internal tools' second door, above their password form (Chris, 16/10/2026: "có
126
+ * cả continue với gemboss hoặc nhập mật khẩu"). Protocol: gemboss docs/fleet-sso.md. It links to GemBoss's sign-in
127
+ * door for this `service`; GemBoss sends a person who is signed in there and on the internal list straight back, with a
128
+ * one-use token the tool redeems at its own route. Below it, "or" and the form the tool always had.
129
+ *
130
+ * Once a browser has come in through GemBoss the tool sets `gb_sso=1`, and from then on this page continues by itself,
131
+ * so a person still signed in to GemBoss never sees a form. It does not when the tool sent a reason back (`?sso=…`:
132
+ * that sign-in did not work, so the page stays and says why) or `?password=1` (the person asked for the form).
133
+ */
134
+ export const GEMBOSS_ISSUER = "https://admin.gemboss.ai";
135
+ const SSO_REASONS: Record<string, string> = {
136
+ not_member: "Your GemBoss account does not have access here. Use the password.",
137
+ invalid: "That sign-in did not go through. Try again, or use the password.",
138
+ off: "Signing in with GemBoss is not available here yet. Use the password.",
139
+ };
140
+
141
+ /** The GemBoss door for one tool, with the path on the tool to come back to. */
142
+ export function gemBossSignInUrl(service: string, next = "/", issuer = GEMBOSS_ISSUER): string {
143
+ return `${issuer}/api/auth/sso/authorize?service=${encodeURIComponent(service)}&next=${encodeURIComponent(next)}`;
144
+ }
145
+
146
+ /** Whether this visit should go to GemBoss without a click: the browser came in that way before, and nothing says stay. */
147
+ export function continuesByItself(cookie: string, search: string): boolean {
148
+ const q = new URLSearchParams(search);
149
+ if (q.has("sso") || q.get("password") === "1") return false;
150
+ return /(?:^|;\s*)gb_sso=1(?:;|$)/.test(cookie);
151
+ }
152
+
153
+ export function AuthContinueWithGemBoss({ service, next = "/", issuer = GEMBOSS_ISSUER }: {
154
+ /** This tool's id in GemBoss's list of tools that redeem (FLEET_SSO_SERVICES). */
155
+ service: string;
156
+ /** Where on this tool to land afterwards: a path. */
157
+ next?: string;
158
+ issuer?: string;
159
+ }) {
160
+ const href = gemBossSignInUrl(service, next, issuer);
161
+ const [going, setGoing] = useState(false);
162
+ const [reason, setReason] = useState<string | null>(null);
163
+ useEffect(() => {
164
+ const r = new URLSearchParams(window.location.search).get("sso");
165
+ if (r) setReason(SSO_REASONS[r] ?? SSO_REASONS.invalid);
166
+ if (continuesByItself(document.cookie, window.location.search)) {
167
+ setGoing(true);
168
+ window.location.replace(href);
169
+ }
170
+ }, [href]);
171
+ return (
172
+ <div className="gb-auth-sso">
173
+ <a className="gb-auth-sso-btn" href={href} onClick={() => setGoing(true)}>
174
+ <GemMark size={18} tile="var(--gb-mark-bg)" />
175
+ {going ? "Continuing with GemBoss…" : "Continue with GemBoss"}
176
+ </a>
177
+ {reason ? <p className="gb-auth-sso-why" role="status">{reason}</p> : null}
178
+ <p className="gb-auth-or">or use the password</p>
179
+ </div>
180
+ );
181
+ }
182
+
120
183
  export function AuthForm({ className, children, ...rest }: React.FormHTMLAttributes<HTMLFormElement>) {
121
184
  return <form className={cx("gb-auth-form", className)} {...rest}>{children}</form>;
122
185
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The lockup's gem: the logo file's paths and stroke weights at the wordmark's rendered size (a 32×40 box drawn 26px
3
+ * tall). Its own module (0.40.0) so `BrandLockup` (topbar, app size) and `SiteBrand` (public site size) draw the same
4
+ * gem, and `SiteBrand` does not import brand.tsx: that module brings the ServiceSwitcher, which a public page must not
5
+ * carry. No stylesheet: `.gb-brand-gem` is in the core (app-shell.css).
6
+ */
7
+ import React from "react";
8
+
9
+ export function BrandGem() {
10
+ return (
11
+ <svg className="gb-brand-gem" viewBox="0 0 32 40" width="20.8" height="26" aria-hidden="true" focusable="false">
12
+ <g transform="translate(0,0.8) scale(0.31)">
13
+ <polygon points="26,14 74,14 66,50 34,50" fill="#5661F5" fillOpacity="0.92" />
14
+ <path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="currentColor" strokeWidth="8.75" strokeLinejoin="round" />
15
+ <path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="currentColor" strokeWidth="5.45" strokeLinejoin="round" />
16
+ </g>
17
+ </svg>
18
+ );
19
+ }
package/src/brand.tsx CHANGED
@@ -13,9 +13,12 @@
13
13
  * `switcher` (0.36.0): the ServiceSwitcher button right after the logo, which opens every other Gem service. The logo
14
14
  * still goes to `href`, as without it. Without the prop the lockup renders exactly as before. The import below brings
15
15
  * service-switcher.css with this module whether or not a surface passes it (README "ServiceSwitcher").
16
+ *
17
+ * The gem lives in brand-gem.tsx (0.40.0), shared with `SiteBrand` (the public site's lockup, site.tsx).
16
18
  */
17
19
  import React from "react";
18
20
  import { ServiceSwitcher, type ServiceSwitcherProps } from "./service-switcher";
21
+ import { BrandGem } from "./brand-gem";
19
22
 
20
23
  type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>;
21
24
 
@@ -23,13 +26,7 @@ export function BrandLockup({ name, href = "/", label, className, switcher, ...r
23
26
  { name: string; label?: string; switcher?: Omit<ServiceSwitcherProps, "className"> } & AnchorProps) {
24
27
  const link = (
25
28
  <a className={className ? `gb-brand ${className}` : "gb-brand"} href={href} aria-label={label ?? `${name} home`} {...rest}>
26
- <svg className="gb-brand-gem" viewBox="0 0 32 40" width="20.8" height="26" aria-hidden="true" focusable="false">
27
- <g transform="translate(0,0.8) scale(0.31)">
28
- <polygon points="26,14 74,14 66,50 34,50" fill="#5661F5" fillOpacity="0.92" />
29
- <path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="currentColor" strokeWidth="8.75" strokeLinejoin="round" />
30
- <path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="currentColor" strokeWidth="5.45" strokeLinejoin="round" />
31
- </g>
32
- </svg>
29
+ <BrandGem />
33
30
  <span className="gb-brand-name">{name}</span>
34
31
  </a>
35
32
  );
package/src/chat-plain.js CHANGED
@@ -1,6 +1,6 @@
1
- (function(O){"use strict";var N=O.gembossUI;if(!N){O.console&&O.console.error("@gemboss/ui chat-plain.js: load kit-plain.js first (it defines gembossUI)");return}if(N.chat)return;var b={thread:"Conversation",message:"Message",send:"Send",stop:"Stop",attach:"Attach a file",copy:"Copy",copied:"Copied",copyCommand:"Copy command",originalError:"Original error",stopped:"Stopped",steps:"What it is doing",thought:"Thought",thinking:"Thinking",working:"Working",showLess:"Show less",showAll:"Show all {n} lines",openImage:"Open image"},A="http://www.w3.org/2000/svg",k=function(e){return typeof Node<"u"&&e instanceof Node};function l(e,n,r){var t=document.createElement(e);if(n)for(var a in n){var i=n[a];i==null||i===!1||(a==="text"?t.textContent=String(i):a==="className"?t.className=i:t.setAttribute(a,i===!0?"":String(i)))}return R(t,r),t}function R(e,n){return n==null||n===!1?e:Array.isArray(n)?(n.forEach(function(r){R(e,r)}),e):(e.appendChild(k(n)?n:document.createTextNode(String(n))),e)}function M(e,n,r){var t=document.createElementNS(A,"svg");if(t.setAttribute("viewBox",e),t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false"),n.forEach(function(i){var s=document.createElementNS(A,i.tag||"path");for(var o in i)o!=="tag"&&s.setAttribute(o,i[o]);t.appendChild(s)}),r)for(var a in r)t.setAttribute(a,r[a]);return t}var ae=[{host:"gemwatcher-api-production.up.railway.app",path:"/watch/artifacts/"},{host:"gemmedia-api-production.up.railway.app",path:"/"},{host:"media.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"gemmedia.ops.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"gemmedia.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"cdn.shopify.com",path:"/"}],q=/[\u0000-\u001f\u007f]/g;function C(e){var n=String(e).replace(q,"").trim();return n?n.charAt(0)==="/"?n.charAt(1)==="/"||n.charAt(1)==="\\"?null:{href:n,internal:!0}:/^(https?:\/\/|mailto:)/i.test(n)?{href:n,internal:!1}:null:null}var D="https://same-origin.invalid",ie=/^\/[^/]+(\/[^/]+)*\/$/;function H(e,n){var r=String(e).replace(q,"").trim(),t;if(r.charAt(0)==="/"){var a=(n||[]).filter(function(s){return!s.host&&ie.test(s.path)});if(!a.length||r.charAt(1)==="/"||r.indexOf("\\")>=0||/%(2f|5c|25)|;/i.test(r))return null;try{t=new URL(r,D)}catch{return null}return t.origin!==D||/\.\.|%2e/i.test(t.pathname)?null:a.some(function(s){return t.pathname.indexOf(s.path)===0})?t.href.slice(D.length):null}try{t=new URL(r)}catch{return null}if(t.protocol!=="https:"||t.username||t.password||t.port)return null;var i=t.hostname.toLowerCase();return ae.concat(n||[]).some(function(s){return s.host===i&&t.pathname.indexOf(s.path)===0})?t.href:null}var T=function(e,n){return e.split(n).length-1};function P(e,n){var r=e.length,t,a,i,s,o=T(e,"("),d=T(e,")"),f=T(e,"["),c=T(e,"]");for(n=n!==!1;n&&r>0;)t=e.charAt(r-1),/[.,:;!?_~'"]/.test(t)?r-=1:t===")"&&o<d?(r-=1,d-=1):t==="]"&&f<c?(r-=1,c-=1):n=!1;if(s=e.slice(0,r),a=C(s),!a||a.internal)return null;try{i=new URL(a.href)}catch{return null}return!/^https?:$/.test(i.protocol)||!i.hostname?null:{href:a.href,rest:e.slice(r)}}var le=/(`([^`]+)`)|(\*\*([^*]+)\*\*)|(\*([^*\n]+)\*)|(!\[([^\]]*)\]\(([^)\s]+)\))|(\[([^\]]+)\]\(([^)\s]+)\))|(<(https?:\/\/[^\s<>]+)>)|(https?:\/\/[^\s<>`"*\u2000-\u206f\u3000-\u9fff\uff00-\uffef]+)/gi;function F(e,n){n=n||{};for(var r=[],t=function(m){if(m){var v=r[r.length-1];v&&v.t==="text"?v.text+=m:r.push({t:"text",text:m})}},a=new RegExp(le.source,"gi"),i=0,s;(s=a.exec(e))!==null;){if(t(e.slice(i,s.index)),s[2]!=null)r.push({t:"code",text:s[2]});else if(s[4]!=null)r.push({t:"bold",text:s[4]});else if(s[6]!=null)r.push({t:"italic",text:s[6]});else if(s[7]!=null){var o=H(s[9],n.imageHosts),d=s[8].trim();if(o)r.push({t:"image",alt:d,src:o});else{var f=C(s[9]);f&&!f.internal?r.push({t:"link",label:d||"image",href:f.href,internal:!1}):t(d)}}else if(s[10]!=null){var c=s[12],p=n.ownLink&&n.ownLink(c)?{href:c,internal:!0,own:!0}:C(c);p?r.push({t:"link",label:s[11],href:p.href,internal:p.internal}):t(s[11])}else{var h=s[15]!=null&&s.index>0&&/[a-z\d]/i.test(e.charAt(s.index-1)),g=h?null:s[14]!=null?P(s[14],!1):P(s[15]);g?(r.push({t:"link",label:g.href,href:g.href,internal:!1}),t(g.rest)):t(s[0])}i=s.index+s[0].length}return t(e.slice(i)),r}var $=function(e){return/^\s*\|.*\|\s*$/.test(e)},se=function(e){return/^\s*\|?[\s:-]*-[-\s:|]*\|?\s*$/.test(e)&&e.indexOf("-")>=0},U=function(e){return e.trim().replace(/^\||\|$/g,"").split("|").map(function(n){return n.trim()})};function K(e){for(var n=String(e??"").split(`
1
+ (function(O){"use strict";var w=O.gembossUI;if(!w){O.console&&O.console.error("@gemboss/ui chat-plain.js: load kit-plain.js first (it defines gembossUI)");return}if(w.chat)return;var b={thread:"Conversation",message:"Message",send:"Send",stop:"Stop",attach:"Attach a file",copy:"Copy",copied:"Copied",copyCommand:"Copy command",originalError:"Original error",stopped:"Stopped",steps:"What it is doing",thought:"Thought",thinking:"Thinking",working:"Working",showLess:"Show less",showAll:"Show all {n} lines",openImage:"Open image"},A="http://www.w3.org/2000/svg",k=function(e){return typeof Node<"u"&&e instanceof Node};function l(e,n,r){var t=document.createElement(e);if(n)for(var a in n){var i=n[a];i==null||i===!1||(a==="text"?t.textContent=String(i):a==="className"?t.className=i:t.setAttribute(a,i===!0?"":String(i)))}return R(t,r),t}function R(e,n){return n==null||n===!1?e:Array.isArray(n)?(n.forEach(function(r){R(e,r)}),e):(e.appendChild(k(n)?n:document.createTextNode(String(n))),e)}function M(e,n,r){var t=document.createElementNS(A,"svg");if(t.setAttribute("viewBox",e),t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false"),n.forEach(function(i){var s=document.createElementNS(A,i.tag||"path");for(var o in i)o!=="tag"&&s.setAttribute(o,i[o]);t.appendChild(s)}),r)for(var a in r)t.setAttribute(a,r[a]);return t}var ae=[{host:"admin.gemboss.ai",path:"/api/gemboss/market-image/"},{host:"gemmedia-api-production.up.railway.app",path:"/"},{host:"media.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"gemmedia.ops.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"gemmedia.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"cdn.shopify.com",path:"/"}],q=/[\u0000-\u001f\u007f]/g;function C(e){var n=String(e).replace(q,"").trim();return n?n.charAt(0)==="/"?n.charAt(1)==="/"||n.charAt(1)==="\\"?null:{href:n,internal:!0}:/^(https?:\/\/|mailto:)/i.test(n)?{href:n,internal:!1}:null:null}var D="https://same-origin.invalid",ie=/^\/[^/]+(\/[^/]+)*\/$/;function H(e,n){var r=String(e).replace(q,"").trim(),t;if(r.charAt(0)==="/"){var a=(n||[]).filter(function(i){return!i.host&&ie.test(i.path)});if(!a.length||r.charAt(1)==="/"||r.indexOf("\\")>=0||/%(2f|5c|25)|;/i.test(r))return null;try{t=new URL(r,D)}catch{return null}return t.origin!==D||/\.\.|%2e/i.test(t.pathname)?null:a.some(function(i){return t.pathname.indexOf(i.path)===0})?t.href.slice(D.length):null}try{t=new URL(r)}catch{return null}return t.protocol!=="https:"||t.username||t.password||t.port?null:ae.concat(n||[]).some(function(i){return i.host===t.hostname&&t.pathname.indexOf(i.path)===0})?t.href:null}var T=function(e,n){return e.split(n).length-1};function P(e,n){var r=e.length,t,a,i,s,o=T(e,"("),d=T(e,")"),f=T(e,"["),c=T(e,"]");for(n=n!==!1;n&&r>0;)t=e.charAt(r-1),/[.,:;!?_~'"]/.test(t)?r-=1:t===")"&&o<d?(r-=1,d-=1):t==="]"&&f<c?(r-=1,c-=1):n=!1;if(s=e.slice(0,r),a=C(s),!a||a.internal)return null;try{i=new URL(a.href)}catch{return null}return!/^https?:$/.test(i.protocol)||!i.hostname?null:{href:a.href,rest:e.slice(r)}}var le=/(`([^`]+)`)|(\*\*([^*]+)\*\*)|(\*([^*\n]+)\*)|(!\[([^\]]*)\]\(([^)\s]+)\))|(\[([^\]]+)\]\(([^)\s]+)\))|(<(https?:\/\/[^\s<>]+)>)|(https?:\/\/[^\s<>`"*\u2000-\u206f\u3000-\u9fff\uff00-\uffef]+)/gi;function F(e,n){n=n||{};for(var r=[],t=function(m){if(m){var v=r[r.length-1];v&&v.t==="text"?v.text+=m:r.push({t:"text",text:m})}},a=new RegExp(le.source,"gi"),i=0,s;(s=a.exec(e))!==null;){if(t(e.slice(i,s.index)),s[2]!=null)r.push({t:"code",text:s[2]});else if(s[4]!=null)r.push({t:"bold",text:s[4]});else if(s[6]!=null)r.push({t:"italic",text:s[6]});else if(s[7]!=null){var o=H(s[9],n.imageHosts),d=s[8].trim();if(o)r.push({t:"image",alt:d,src:o});else{var f=C(s[9]);f&&!f.internal?r.push({t:"link",label:d||"image",href:f.href,internal:!1}):t(d)}}else if(s[10]!=null){var c=s[12],p=n.ownLink&&n.ownLink(c)?{href:c,internal:!0,own:!0}:C(c);p?r.push({t:"link",label:s[11],href:p.href,internal:p.internal}):t(s[11])}else{var h=s[15]!=null&&s.index>0&&/[a-z\d]/i.test(e.charAt(s.index-1)),g=h?null:s[14]!=null?P(s[14],!1):P(s[15]);g?(r.push({t:"link",label:g.href,href:g.href,internal:!1}),t(g.rest)):t(s[0])}i=s.index+s[0].length}return t(e.slice(i)),r}var $=function(e){return/^\s*\|.*\|\s*$/.test(e)},se=function(e){return/^\s*\|?[\s:-]*-[-\s:|]*\|?\s*$/.test(e)&&e.indexOf("-")>=0},U=function(e){return e.trim().replace(/^\||\|$/g,"").split("|").map(function(n){return n.trim()})};function K(e){for(var n=String(e??"").split(`
2
2
  `),r=[],t=0,a=[],i=function(){a.length&&r.push({t:"para",lines:a.slice()}),a.length=0};t<n.length;){var s=n[t],o;if(o=/^\s*```([\w#+.-]*)\s*$/.exec(s)){i();var d=[];for(t+=1;t<n.length&&!/^\s*```\s*$/.test(n[t]);)d.push(n[t]),t+=1;t+=1,r.push({t:"code",lang:o[1]||"",body:d.join(`
3
3
  `)});continue}if(o=/^(#{1,6})\s+(.*)$/.exec(s)){i(),o[2].trim()&&r.push({t:"heading",level:Math.min(o[1].length,3),text:o[2].trim()}),t+=1;continue}if(/^\s*(---|\*\*\*|___)\s*$/.test(s)){i(),r.push({t:"rule"}),t+=1;continue}if($(s)&&t+1<n.length&&se(n[t+1])){i();var f=U(s),c=[];for(t+=2;t<n.length&&$(n[t]);)c.push(U(n[t])),t+=1;r.push({t:"table",head:f,rows:c});continue}if(o=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(s)){i();for(var p=/\d/.test(o[1]),h=p?parseInt(o[1],10):void 0,g=[];t<n.length;){var m=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(n[t]);if(!m||/\d/.test(m[1])!==p)break;g.push(m[2]),t+=1}var v={t:"list",ordered:p,items:g};h!==void 0&&h!==1&&(v.start=h),r.push(v);continue}if(/^\s*>\s?/.test(s)){i();for(var y=[];t<n.length&&/^\s*>\s?/.test(n[t]);)y.push(n[t].replace(/^\s*>\s?/,"")),t+=1;r.push({t:"quote",lines:y});continue}if(s.trim()===""){i(),t+=1;continue}a.push(s),t+=1}return i(),r}var j=12;function x(e,n,r){return F(e,n).map(function(t){if(t.t==="text")return document.createTextNode(t.text);if(t.t==="code")return l("code",{className:"gemboss-md-code",text:t.text});if(t.t==="bold")return l("strong",0,x(t.text,n,r));if(t.t==="italic")return l("em",0,x(t.text,n,r));if(t.t==="link"){if(n.ownLink&&n.ownLink(t.href)&&n.renderLink)return n.renderLink(t.href,t.label)||document.createTextNode(t.label);var a=l("a",{className:"gemboss-ec-md-link",href:t.href,target:t.internal?null:"_blank",rel:t.internal?null:"noopener noreferrer",text:t.label});return t.internal&&n.onNavigate&&a.addEventListener("click",function(i){i.metaKey||i.ctrlKey||i.shiftKey||(i.preventDefault(),n.onNavigate(t.href))}),a}return l("a",{className:"gemboss-md-imglink",href:t.src,target:"_blank",rel:"noopener noreferrer","aria-label":t.alt?null:r.openImage},l("img",{className:"gemboss-md-img",src:t.src,alt:t.alt,loading:"lazy",referrerpolicy:"no-referrer"}))})}function z(e,n,r){var t=[];return e.forEach(function(a,i){t=t.concat(x(a,n,r)),i<e.length-1&&t.push(l("br"))}),t}function oe(e,n){var r=e.body.split(`
4
4
  `),t=r.length>j,a=!1,i=l("code",{text:t?r.slice(0,j).join(`
5
5
  `):e.body}),s=l("div",{className:"gemboss-md-codeblock"},[e.lang?l("span",{className:"gemboss-md-codelang",text:e.lang}):null,l("pre",null,i)]);if(t){var o=l("button",{type:"button",className:"gemboss-md-codemore","aria-expanded":"false",text:n.showAll.replace("{n}",String(r.length))});o.addEventListener("click",function(){a=!a,i.textContent=a?e.body:r.slice(0,j).join(`
6
- `),o.textContent=a?n.showLess:n.showAll.replace("{n}",String(r.length)),o.setAttribute("aria-expanded",String(a))}),s.appendChild(o)}return s}var ue={1:"h3",2:"h4",3:"h5"};function G(e,n,r){n=n||{};var t=Object.assign({},b,r||n.labels||{}),a=document.createDocumentFragment();return K(e).forEach(function(i){var s;i.t==="heading"?s=l(ue[i.level],{className:"gemboss-md-h gemboss-md-h"+i.level},x(i.text,n,t)):i.t==="code"?s=oe(i,t):i.t==="table"?s=l("div",{className:"gemboss-md-tablewrap"},l("table",{className:"gemboss-md-table"},[l("thead",null,l("tr",null,i.head.map(function(o){return l("th",null,x(o,n,t))}))),l("tbody",null,i.rows.map(function(o){return l("tr",null,i.head.map(function(d,f){return l("td",null,x(o[f]||"",n,t))}))}))])):i.t==="list"?s=l(i.ordered?"ol":"ul",{className:"gemboss-md-list",start:i.ordered&&i.start!==void 0?i.start:null},i.items.map(function(o){return l("li",null,x(o,n,t))})):i.t==="quote"?s=l("blockquote",{className:"gemboss-md-quote"},z(i.lines,n,t)):i.t==="rule"?s=l("hr",{className:"gemboss-md-rule"}):s=l("p",{className:"gemboss-md-p"},z(i.lines,n,t)),a.appendChild(s)}),a}function ce(){for(var e=12,n=1.7,r=.5,t=9.6,a=[],i=function(g){return Math.round(g*100)/100},s=function(g,m){return i(g)+" "+i(m)},o=0;o<8;o++){var d=o*Math.PI/4,f=Math.cos(d),c=Math.sin(d),p=-c,h=f;a.push(["M"+s(e+p*n,e+h*n),"L"+s(e+f*t+p*r,e+c*t+h*r),"Q"+s(e+f*(t+.6),e+c*(t+.6))+" "+s(e+f*t-p*r,e+c*t-h*r),"L"+s(e-p*n,e-h*n),"Z"].join(""))}return a.join(" ")}var V={claude:{path:ce(),label:"Claude Code"},codex:{path:"M12 2.6 20.1 7.3V16.7L12 21.4 3.9 16.7V7.3ZM12 6.9 7.6 9.45v5.1L12 17.1l4.4-2.55v-5.1Z",label:"Codex"}};function Y(e,n){var r=Object.prototype.hasOwnProperty.call(V,e)?V[e]:null;if(!r)return null;n=n||{};var t=document.createElementNS(A,"svg");if(t.setAttribute("class",n.className||"gemboss-engine-mark"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","currentColor"),n.decorative)t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false");else{t.setAttribute("role","img"),t.setAttribute("aria-label",n.title||r.label);var a=document.createElementNS(A,"title");a.textContent=n.title||r.label,t.appendChild(a)}var i=document.createElementNS(A,"path");return i.setAttribute("d",r.path),i.setAttribute("fill-rule","nonzero"),t.appendChild(i),t}function Z(e,n){var r=Object.assign({},b,n||{});return!e||!e.length?null:l("ul",{className:"gemboss-narr","aria-label":r.steps},e.map(function(t){var a=t.state||"ok",i;if(t.kind==="thinking")return i=[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:"\u2733"}),a==="running"||!t.detail?l("span",{className:"gemboss-narr-text gemboss-narr-thinking-live"},t.label||r.thinking):l("details",{className:"gemboss-narr-thinking"},[l("summary",null,t.label||r.thought),l("div",{className:"gemboss-narr-thinking-body",text:t.detail})])],l("li",{className:"gemboss-narr-row thinking "+a},i);if(t.kind==="steer")return l("li",{className:"gemboss-narr-row steer "+a},[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:"\u276F"}),l("span",{className:"gemboss-narr-text gemboss-narr-steer"},t.label)]);if(t.kind==="trace")return l("li",{className:"gemboss-narr-row trace "+a,title:t.error||null},[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:a==="failed"?"\u2715":"\u23FA"}),t.detail?l("details",{className:"gemboss-narr-trace"},[l("summary",null,l("code",null,t.label)),l("div",{className:"gemboss-narr-trace-body"},l("code",{text:t.detail}))]):l("code",{className:"gemboss-narr-text gemboss-narr-trace-call"},t.label)]);var s=t.engine?Y(t.engine):null;return l("li",{className:"gemboss-narr-row "+a,title:t.error||null},[s?l("span",{className:"gemboss-narr-dot gemboss-narr-dot-engine"},s):l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:a==="ok"?"\u2713":a==="failed"?"\u2715":"\xB7"}),l("span",{className:"gemboss-narr-text"},[t.label,t.target?l("span",{className:"gb-chat-target"},[" ",t.target]):null])])}))}function J(e,n){e=e||{};var r=Object.assign({},b,n||{}),t=e.verbs&&e.verbs.length?e.verbs:[r.working],a=l("span",{className:"gemboss-ec-pending-verb","aria-hidden":"true",text:t[0]+"\u2026"}),i=l("span",{className:"gemboss-ec-pending-meta","aria-hidden":"true",text:"0s"}),s=l("div",{className:"gemboss-ec-pending",role:"status"},[l("span",{className:"gemboss-assistant-sronly",text:e.label||t[0]}),l("span",{className:"gemboss-ec-pending-star","aria-hidden":"true",text:"\u2733"}),e.compact?null:a,i]),o=e.since||Date.now(),d=!1,f=-1,c=function(){var h=Math.max(0,Math.floor((Date.now()-o)/1e3));i.textContent=(e.tokens>0?e.tokens+" token"+(e.tokens===1?"":"s")+" \xB7 ":"")+h+"s";var g=t.length>1?Math.floor(h/2)%t.length:0;if(g!==f&&!e.compact){f=g;var m=l("span",{className:"gemboss-ec-pending-verb","aria-hidden":"true",text:t[f]+"\u2026"});a.replaceWith(m),a=m}};c();var p=setInterval(function(){if(s.isConnected)d=!0;else if(d||Date.now()-o>6e5){clearInterval(p);return}c()},250);return s}function I(e,n,r){r=r||{};var t=document.createDocumentFragment();return!e||!e.length||(r.title&&t.appendChild(l("p",{className:"gb-chat-label"},r.title)),t.appendChild(l("div",{className:"gemboss-ec-starters"},e.map(function(a){var i=l("button",{type:"button",className:"gemboss-ec-starter gb-chat-starter"},[a.hint?l("span",{className:"gb-chat-starter-hint",text:a.hint}):null,a.label]);return i.addEventListener("click",function(){n(a)}),i})))),t}function de(e){var n=function(){try{var r=l("textarea",{readonly:!0});r.value=e,r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();var t=document.execCommand("copy");return r.remove(),t}catch{return!1}};try{if(navigator.clipboard&&navigator.clipboard.writeText)return navigator.clipboard.writeText(e).then(function(){return!0},n)}catch{}return Promise.resolve(n())}function Q(e,n,r){var t=l("button",{type:"button",className:"ui-btn ui-btn--ghost gb-chat-copy",text:n}),a=0;return t.addEventListener("click",function(){de(e).then(function(i){i&&(t.textContent=r,clearTimeout(a),a=setTimeout(function(){t.textContent=n},1500))})}),t}function X(e,n,r){var t=Object.assign({},b,r||{}),a=(n||[]).filter(function(i){return i!=null&&i!==!1&&i!==""});return!e&&!a.length?null:l("div",{className:"gb-chat-meta"},[e?Q(e,t.copy,t.copied):null].concat(a.map(function(i){return l("span",null,i)})))}function ee(e,n,r){var t=Object.assign({},b,r||{});return n?l("div",{className:"ui-notice ui-notice--danger gb-chat-error",role:"alert"},[l("div",null,n.text),n.command?l("code",{className:"gb-chat-cmd",text:n.command}):null,n.command?l("div",null,Q(n.command,t.copyCommand,t.copied)):null,l("details",{className:"gb-chat-original"},[l("summary",{text:t.originalError}),l("span",null,e)])]):l("p",{className:"ui-notice ui-notice--danger gb-chat-error",role:"alert"},e)}function _(e){return l("p",{className:"gb-chat-note"},e)}var fe={warn:"gb-engine-notice gb-engine-notice--warn",down:"gb-engine-notice gb-engine-notice--down"},he={warn:"gb-engine-dot gb-engine-dot--warn",down:"gb-engine-dot gb-engine-dot--down"};function te(e,n,r,t){if(N.bridgeNotice)return N.bridgeNotice({text:k(e)?void 0:e,node:k(e)?e:void 0,tone:n,action:r,onOpenSetup:t});var a=n==="warn"?"warn":"down",i=l("p",{className:fe[a],role:"status"},[l("span",{className:he[a],"aria-hidden":"true"}),l("span",{className:"gb-engine-notice-text"},e)]);if(t){var s=l("button",{type:"button",className:"gb-engine-notice-link",text:r||"Open setup"});s.addEventListener("click",t),i.appendChild(s)}return i}function B(e,n){return l("div",{className:"gemboss-ec-bubble"},[e,n?l("span",{className:"gemboss-ec-cursor","aria-hidden":"true"}):null])}function ne(e,n){n=n||{};var r=Object.assign({},b,n.labels||{});if(e.role==="note")return e.tone==="warn"||e.tone==="down"?te(e.text,e.tone,e.action&&e.action.label,e.action&&e.action.onClick):_(e.text);if(e.role==="user")return l("div",{className:"gemboss-ec-msg user",lang:e.lang||null},B(e.text));var t=!!e.text;return l("div",{className:"gemboss-ec-msg assistant",lang:e.lang||null},[e.steps&&e.steps.length?Z(e.steps,r):null,t?B(e.markdown===!1?e.text:G(e.text,n,r),e.pending):e.pending?J({verbs:n.pendingVerbs,since:n.since},r):null,n.renderExtra?n.renderExtra(e):null,e.warn?l("p",{className:"ui-notice ui-notice--warning gb-chat-notice"},e.warn):null,e.error?e.bridge?te(e.error,"down",null,n.onOpenSetup):ee(e.error,e.fix,r):null,e.stopped?_(r.stopped):null,!e.pending&&t?X(e.text,e.meta,r):null])}function ge(e){try{return JSON.stringify(e,function(n,r){return typeof r=="function"?"fn":k(r)?"node:"+(r.textContent||""):r})}catch{return String(Math.random())}}function pe(e,n){var r=e.querySelectorAll("details"),t=n.querySelectorAll("details"),a;for(a=0;a<r.length&&a<t.length;a++)r[a].open&&(t[a].open=!0);for(r=e.querySelectorAll(".gemboss-md-codemore"),t=n.querySelectorAll(".gemboss-md-codemore"),a=0;a<r.length&&a<t.length;a++)r[a].getAttribute("aria-expanded")==="true"&&t[a].click()}function me(e,n,r){r=r||{};var t=Object.assign({},b,r.labels||{}),a=e.__gbChat||(e.__gbChat={els:new Map,since:new Map}),i=[],s=new Map;if(!n.length&&(r.intro||r.starters&&r.starters.length)){var o=function(d){r.onStarter&&r.onStarter(d)};i.push(l("div",{className:"gemboss-ec-msg assistant"},[r.intro?B(r.intro):null,r.starters&&r.starters.length?I(r.starters,o,{title:r.startersTitle}):null,r.moreStarters&&r.moreStarters.length?I(r.moreStarters,o,{title:r.moreStartersTitle}):null]))}return n.forEach(function(d,f){var c=d.id!==void 0&&d.id!==null?"id:"+d.id:"at:"+f,p=ge(d),h=a.els.get(c);d.pending&&!d.text&&!a.since.has(c)&&a.since.set(c,Date.now());var g;h&&h.look===p?g=h.el:(g=ne(d,Object.assign({},r,{labels:t,since:a.since.get(c)})),h&&pe(h.el,g)),s.set(c,{el:g,look:p}),i.push(g)}),a.els=s,a.since.forEach(function(d,f){s.has(f)||a.since.delete(f)}),e.replaceChildren.apply(e,i),e}function ve(e,n){n=n||{};var r=Object.assign({},b,n.labels||{});e.classList.add("gemboss-ec-scroll"),e.setAttribute("role","log"),e.hasAttribute("aria-label")||e.setAttribute("aria-label",n.label||r.thread);var t=!0,a=0,i=0,s=0,o=!1,d=null,f=function(){e.scrollTop=e.scrollHeight,d=e.scrollTop},c=function(){!t||a||(a=requestAnimationFrame(function(){a=0,t&&f()}))},p=function(){i=Date.now(),o=!0,t=!1},h=function(){o=!1},g=function(){var u=e.scrollHeight-e.clientHeight-e.scrollTop,w=d!==null&&e.scrollTop===d;d=null,u>24&&!w?t=!1:u<=4&&(!o||Date.now()-i>400)&&(t=!0)},m=function(u){u.deltaY<0?p():u.deltaY>0&&h()},v=function(u){s=u.touches[0]?u.touches[0].clientY:0},y=function(u){var w=u.touches[0]?u.touches[0].clientY:0;w>s+2?p():w<s-2&&h()},L=function(u){u.key==="ArrowUp"||u.key==="PageUp"||u.key==="Home"?p():(u.key==="ArrowDown"||u.key==="PageDown"||u.key==="End")&&h()};e.addEventListener("scroll",g,{passive:!0}),e.addEventListener("wheel",m,{passive:!0}),e.addEventListener("touchstart",v,{passive:!0}),e.addEventListener("touchmove",y,{passive:!0}),e.addEventListener("keydown",L),e.addEventListener("load",c,!0);var E=new MutationObserver(c);E.observe(e,{childList:!0,subtree:!0,characterData:!0});var S=typeof ResizeObserver>"u"?null:new ResizeObserver(c);return S&&S.observe(e),f(),{el:e,setBusy:function(u){u?e.setAttribute("aria-busy","true"):e.removeAttribute("aria-busy")},toEnd:function(){t=!0,f()},destroy:function(){cancelAnimationFrame(a),e.removeEventListener("scroll",g),e.removeEventListener("wheel",m),e.removeEventListener("touchstart",v),e.removeEventListener("touchmove",y),e.removeEventListener("keydown",L),e.removeEventListener("load",c,!0),E.disconnect(),S&&S.disconnect()}}}function be(){return M("0 0 24 24",[{d:"M21.4 11.1l-8.5 8.5a5.5 5.5 0 01-7.8-7.8l8.5-8.5a3.7 3.7 0 015.2 5.2l-8.5 8.5a1.8 1.8 0 01-2.6-2.6l7.8-7.8",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}])}function ye(e){e=e||{};var n=e.label||b.attach,r=l("input",{type:"file",hidden:!0,accept:e.accept||null,multiple:e.multiple||null,tabindex:"-1"}),t=l("button",{type:"button",className:"gemboss-ec-attach-btn","aria-label":n,title:e.title||n,disabled:e.disabled||null},be());t.addEventListener("click",function(){r.click()}),r.addEventListener("change",function(){var i=Array.prototype.slice.call(r.files||[]);r.value="",i.length&&e.onFiles&&e.onFiles(i)});var a=document.createDocumentFragment();return a.appendChild(t),a.appendChild(r),a}var W=["full","compact","icon","tight"];function we(e){var n=e.querySelector(".gemboss-ec-toolbar-lead"),r=e.querySelector(".gemboss-ec-toolbar");if(n&&n.scrollWidth>n.clientWidth+1||r&&r.scrollWidth>r.clientWidth+1)return!0;var t,a=e.querySelectorAll(".gemboss-ec-chiplabel, .gb-engine-chiplabel");for(t=0;t<a.length;t++)if(a[t].offsetParent!==null&&a[t].scrollWidth>a[t].clientWidth+1)return!0;for(a=e.querySelectorAll(".gemboss-ec-chipctl, .gb-engine-chip"),t=0;t<a.length;t++)if(a[t].offsetParent!==null&&a[t].tagName!=="SELECT"&&a[t].scrollWidth>a[t].clientWidth+1)return!0;return!1}function Ne(e,n){e&&!k(e)&&(n=e,e=null),n=n||{};var r=Object.assign({},b,n.labels||{}),t=!1,a=l("textarea",{rows:n.rows||1,maxlength:n.maxLength||null,"aria-label":n.label||r.message,placeholder:n.placeholder||null}),i=l("div",{className:"gemboss-ec-toolbar-lead"},n.leading||null),s=n.tools?l("div",{className:"gemboss-ec-toolbar-tools"},n.tools):null,o=l("button",{type:"submit",disabled:!0,"aria-label":r.send,title:r.send},M("0 0 20 20",[{d:"M10.53 4.47a.75.75 0 0 0-1.06 0l-4.5 4.5a.75.75 0 0 0 1.06 1.06l3.22-3.22v8.69a.75.75 0 0 0 1.5 0v-8.69l3.22 3.22a.75.75 0 1 0 1.06-1.06l-4.5-4.5Z"}])),d=l("button",{type:"button",className:"gemboss-ec-stop","aria-label":r.stop,title:r.stop},M("0 0 12 12",[{tag:"rect",x:"1",y:"1",width:"10",height:"10",rx:"2"}])),f=l("div",{className:"gemboss-ec-toolbar"},[i,s,n.status||null,o]),c=l("div",{className:"gemboss-ec-input","data-density":"full"},[n.top||null,a,f]);e&&e.appendChild(c);var p=function(){return!a.disabled&&a.value.trim()!==""&&(!t||n.sendWhileBusy||!n.onStop)},h=function(){var u=t&&!!n.onStop,w=u?d:o,re=u?o:d;re.parentNode&&re.replaceWith(w),o.disabled=!p()},g=function(){p()&&(n.onSend&&n.onSend(a.value),n.thread&&n.thread.toEnd&&n.thread.toEnd(),n.keepValue||(a.value="",m(),h()))},m=function(){if(!(a.offsetParent===null||a.scrollHeight===0)){var u=parseFloat(getComputedStyle(a).maxHeight)||84;a.style.height="auto";var w=a.scrollHeight+(a.offsetHeight-a.clientHeight);a.style.height=Math.min(w,u)+"px",a.style.overflowY=w>u?"auto":"hidden"}};a.addEventListener("input",function(){m(),h(),n.onChange&&n.onChange(a.value)}),a.addEventListener("keydown",function(u){n.onKeyDown&&n.onKeyDown(u),!u.defaultPrevented&&u.key==="Enter"&&!u.shiftKey&&!u.isComposing&&u.keyCode!==229&&(u.preventDefault(),g())}),o.addEventListener("click",function(u){u.preventDefault(),g()}),d.addEventListener("click",function(){n.onStop&&n.onStop(),a.focus()});var v=!1,y=function(){if(!(v||c.offsetParent===null)){v=!0;for(var u=0;u<W.length&&(c.setAttribute("data-density",W[u]),!(u===W.length-1||!we(c)));u++);v=!1,n.onDensity&&n.onDensity(c.getAttribute("data-density"))}},L=-1,E=typeof ResizeObserver>"u"?null:new ResizeObserver(function(){c.clientWidth!==L&&(L=c.clientWidth,y(),m())});E&&E.observe(c);var S=new MutationObserver(function(){v||y()});return S.observe(i,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-label","title","aria-label"]}),document.fonts&&document.fonts.ready&&document.fonts.ready.then(y),requestAnimationFrame(function(){y(),m()}),{el:c,textarea:a,value:function(){return a.value},setValue:function(u){a.value=u==null?"":String(u),m(),h()},setBusy:function(u){t=!!u,h()},setDisabled:function(u){a.disabled=!!u,h()},focus:function(){a.focus()},measure:y,destroy:function(){E&&E.disconnect(),S.disconnect(),c.remove()}}}var xe="The bridge on your machine is not responding: it was stopped, or the machine just slept. The panel is checking again; rerun the install command if it does not come back.",Ee="The bridge on your machine rejected this browser's pairing code (it was installed with another code). Pair again in Setup.";function Se(e,n){return e&&typeof e=="object"&&(e.atBridge=!0,n!==void 0&&(e.status=n)),e}function Ae(e,n){return n=n||{},e&&e.name==="AbortError"?{error:null,bridge:!1,stopped:!0}:e&&e.atBridge&&e.status===401?{error:n.rejected||Ee,bridge:!0,stopped:!1}:e&&e.atBridge&&(e instanceof TypeError||e.name==="TimeoutError")?{error:n.gone||xe,bridge:!0,stopped:!1}:{error:e&&e.message||String(e),bridge:!1,stopped:!1}}N.engineMark||(N.engineMark=Y),N.chat={markdown:G,parseBlocks:K,parseInline:F,linkTarget:C,imageSource:H,message:ne,render:me,thread:ve,steps:Z,pending:J,starters:I,meta:X,error:ee,note:_,composer:Ne,attach:ye,labels:b,atBridge:Se,turnError:Ae}})(typeof globalThis<"u"?globalThis:this);
6
+ `),o.textContent=a?n.showLess:n.showAll.replace("{n}",String(r.length)),o.setAttribute("aria-expanded",String(a))}),s.appendChild(o)}return s}var ue={1:"h3",2:"h4",3:"h5"};function G(e,n,r){n=n||{};var t=Object.assign({},b,r||n.labels||{}),a=document.createDocumentFragment();return K(e).forEach(function(i){var s;i.t==="heading"?s=l(ue[i.level],{className:"gemboss-md-h gemboss-md-h"+i.level},x(i.text,n,t)):i.t==="code"?s=oe(i,t):i.t==="table"?s=l("div",{className:"gemboss-md-tablewrap"},l("table",{className:"gemboss-md-table"},[l("thead",null,l("tr",null,i.head.map(function(o){return l("th",null,x(o,n,t))}))),l("tbody",null,i.rows.map(function(o){return l("tr",null,i.head.map(function(d,f){return l("td",null,x(o[f]||"",n,t))}))}))])):i.t==="list"?s=l(i.ordered?"ol":"ul",{className:"gemboss-md-list",start:i.ordered&&i.start!==void 0?i.start:null},i.items.map(function(o){return l("li",null,x(o,n,t))})):i.t==="quote"?s=l("blockquote",{className:"gemboss-md-quote"},z(i.lines,n,t)):i.t==="rule"?s=l("hr",{className:"gemboss-md-rule"}):s=l("p",{className:"gemboss-md-p"},z(i.lines,n,t)),a.appendChild(s)}),a}function ce(){for(var e=12,n=1.7,r=.5,t=9.6,a=[],i=function(g){return Math.round(g*100)/100},s=function(g,m){return i(g)+" "+i(m)},o=0;o<8;o++){var d=o*Math.PI/4,f=Math.cos(d),c=Math.sin(d),p=-c,h=f;a.push(["M"+s(e+p*n,e+h*n),"L"+s(e+f*t+p*r,e+c*t+h*r),"Q"+s(e+f*(t+.6),e+c*(t+.6))+" "+s(e+f*t-p*r,e+c*t-h*r),"L"+s(e-p*n,e-h*n),"Z"].join(""))}return a.join(" ")}var V={claude:{path:ce(),label:"Claude Code"},codex:{path:"M12 2.6 20.1 7.3V16.7L12 21.4 3.9 16.7V7.3ZM12 6.9 7.6 9.45v5.1L12 17.1l4.4-2.55v-5.1Z",label:"Codex"}};function Y(e,n){var r=Object.prototype.hasOwnProperty.call(V,e)?V[e]:null;if(!r)return null;n=n||{};var t=document.createElementNS(A,"svg");if(t.setAttribute("class",n.className||"gemboss-engine-mark"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","currentColor"),n.decorative)t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false");else{t.setAttribute("role","img"),t.setAttribute("aria-label",n.title||r.label);var a=document.createElementNS(A,"title");a.textContent=n.title||r.label,t.appendChild(a)}var i=document.createElementNS(A,"path");return i.setAttribute("d",r.path),i.setAttribute("fill-rule","nonzero"),t.appendChild(i),t}function Z(e,n){var r=Object.assign({},b,n||{});return!e||!e.length?null:l("ul",{className:"gemboss-narr","aria-label":r.steps},e.map(function(t){var a=t.state||"ok",i;if(t.kind==="thinking")return i=[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:"\u2733"}),a==="running"||!t.detail?l("span",{className:"gemboss-narr-text gemboss-narr-thinking-live"},t.label||r.thinking):l("details",{className:"gemboss-narr-thinking"},[l("summary",null,t.label||r.thought),l("div",{className:"gemboss-narr-thinking-body",text:t.detail})])],l("li",{className:"gemboss-narr-row thinking "+a},i);if(t.kind==="steer")return l("li",{className:"gemboss-narr-row steer "+a},[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:"\u276F"}),l("span",{className:"gemboss-narr-text gemboss-narr-steer"},t.label)]);if(t.kind==="trace")return l("li",{className:"gemboss-narr-row trace "+a,title:t.error||null},[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:a==="failed"?"\u2715":"\u23FA"}),t.detail?l("details",{className:"gemboss-narr-trace"},[l("summary",null,l("code",null,t.label)),l("div",{className:"gemboss-narr-trace-body"},l("code",{text:t.detail}))]):l("code",{className:"gemboss-narr-text gemboss-narr-trace-call"},t.label)]);var s=t.engine?Y(t.engine):null;return l("li",{className:"gemboss-narr-row "+a,title:t.error||null},[s?l("span",{className:"gemboss-narr-dot gemboss-narr-dot-engine"},s):l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:a==="ok"?"\u2713":a==="failed"?"\u2715":"\xB7"}),l("span",{className:"gemboss-narr-text"},[t.label,t.target?l("span",{className:"gb-chat-target"},[" ",t.target]):null])])}))}function J(e,n){e=e||{};var r=Object.assign({},b,n||{}),t=e.verbs&&e.verbs.length?e.verbs:[r.working],a=l("span",{className:"gemboss-ec-pending-verb","aria-hidden":"true",text:t[0]+"\u2026"}),i=l("span",{className:"gemboss-ec-pending-meta","aria-hidden":"true",text:"0s"}),s=l("div",{className:"gemboss-ec-pending",role:"status"},[l("span",{className:"gemboss-assistant-sronly",text:e.label||t[0]}),l("span",{className:"gemboss-ec-pending-star","aria-hidden":"true",text:"\u2733"}),e.compact?null:a,i]),o=e.since||Date.now(),d=!1,f=-1,c=function(){var h=Math.max(0,Math.floor((Date.now()-o)/1e3));i.textContent=(e.tokens>0?e.tokens+" token"+(e.tokens===1?"":"s")+" \xB7 ":"")+h+"s";var g=t.length>1?Math.floor(h/2)%t.length:0;if(g!==f&&!e.compact){f=g;var m=l("span",{className:"gemboss-ec-pending-verb","aria-hidden":"true",text:t[f]+"\u2026"});a.replaceWith(m),a=m}};c();var p=setInterval(function(){if(s.isConnected)d=!0;else if(d||Date.now()-o>6e5){clearInterval(p);return}c()},250);return s}function I(e,n,r){r=r||{};var t=document.createDocumentFragment();return!e||!e.length||(r.title&&t.appendChild(l("p",{className:"gb-chat-label"},r.title)),t.appendChild(l("div",{className:"gemboss-ec-starters"},e.map(function(a){var i=l("button",{type:"button",className:"gemboss-ec-starter gb-chat-starter"},[a.hint?l("span",{className:"gb-chat-starter-hint",text:a.hint}):null,a.label]);return i.addEventListener("click",function(){n(a)}),i})))),t}function de(e){var n=function(){try{var r=l("textarea",{readonly:!0});r.value=e,r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();var t=document.execCommand("copy");return r.remove(),t}catch{return!1}};try{if(navigator.clipboard&&navigator.clipboard.writeText)return navigator.clipboard.writeText(e).then(function(){return!0},n)}catch{}return Promise.resolve(n())}function Q(e,n,r){var t=l("button",{type:"button",className:"ui-btn ui-btn--ghost gb-chat-copy",text:n}),a=0;return t.addEventListener("click",function(){de(e).then(function(i){i&&(t.textContent=r,clearTimeout(a),a=setTimeout(function(){t.textContent=n},1500))})}),t}function X(e,n,r){var t=Object.assign({},b,r||{}),a=(n||[]).filter(function(i){return i!=null&&i!==!1&&i!==""});return!e&&!a.length?null:l("div",{className:"gb-chat-meta"},[e?Q(e,t.copy,t.copied):null].concat(a.map(function(i){return l("span",null,i)})))}function ee(e,n,r){var t=Object.assign({},b,r||{});return n?l("div",{className:"ui-notice ui-notice--danger gb-chat-error",role:"alert"},[l("div",null,n.text),n.command?l("code",{className:"gb-chat-cmd",text:n.command}):null,n.command?l("div",null,Q(n.command,t.copyCommand,t.copied)):null,l("details",{className:"gb-chat-original"},[l("summary",{text:t.originalError}),l("span",null,e)])]):l("p",{className:"ui-notice ui-notice--danger gb-chat-error",role:"alert"},e)}function _(e){return l("p",{className:"gb-chat-note"},e)}var fe={warn:"gb-engine-notice gb-engine-notice--warn",down:"gb-engine-notice gb-engine-notice--down"},he={warn:"gb-engine-dot gb-engine-dot--warn",down:"gb-engine-dot gb-engine-dot--down"};function te(e,n,r,t){if(w.bridgeNotice)return w.bridgeNotice({text:k(e)?void 0:e,node:k(e)?e:void 0,tone:n,action:r,onOpenSetup:t});var a=n==="warn"?"warn":"down",i=l("p",{className:fe[a],role:"status"},[l("span",{className:he[a],"aria-hidden":"true"}),l("span",{className:"gb-engine-notice-text"},e)]);if(t){var s=l("button",{type:"button",className:"gb-engine-notice-link",text:r||"Open setup"});s.addEventListener("click",t),i.appendChild(s)}return i}function B(e,n){return l("div",{className:"gemboss-ec-bubble"},[e,n?l("span",{className:"gemboss-ec-cursor","aria-hidden":"true"}):null])}function ne(e,n){n=n||{};var r=Object.assign({},b,n.labels||{});if(e.role==="note")return e.tone==="warn"||e.tone==="down"?te(e.text,e.tone,e.action&&e.action.label,e.action&&e.action.onClick):_(e.text);if(e.role==="user")return l("div",{className:"gemboss-ec-msg user",lang:e.lang||null},B(e.text));var t=!!e.text;return l("div",{className:"gemboss-ec-msg assistant",lang:e.lang||null},[e.steps&&e.steps.length?Z(e.steps,r):null,t?B(e.markdown===!1?e.text:G(e.text,n,r),e.pending):e.pending?J({verbs:n.pendingVerbs,since:n.since},r):null,n.renderExtra?n.renderExtra(e):null,e.warn?l("p",{className:"ui-notice ui-notice--warning gb-chat-notice"},e.warn):null,e.error?e.bridge?te(e.error,"down",null,n.onOpenSetup):ee(e.error,e.fix,r):null,e.stopped?_(r.stopped):null,!e.pending&&t?X(e.text,e.meta,r):null])}function ge(e){try{return JSON.stringify(e,function(n,r){return typeof r=="function"?"fn":k(r)?"node:"+(r.textContent||""):r})}catch{return String(Math.random())}}function pe(e,n){var r=e.querySelectorAll("details"),t=n.querySelectorAll("details"),a;for(a=0;a<r.length&&a<t.length;a++)r[a].open&&(t[a].open=!0);for(r=e.querySelectorAll(".gemboss-md-codemore"),t=n.querySelectorAll(".gemboss-md-codemore"),a=0;a<r.length&&a<t.length;a++)r[a].getAttribute("aria-expanded")==="true"&&t[a].click()}function me(e,n,r){r=r||{};var t=Object.assign({},b,r.labels||{}),a=e.__gbChat||(e.__gbChat={els:new Map,since:new Map}),i=[],s=new Map;if(!n.length&&(r.intro||r.starters&&r.starters.length)){var o=function(d){r.onStarter&&r.onStarter(d)};i.push(l("div",{className:"gemboss-ec-msg assistant"},[r.intro?B(r.intro):null,r.starters&&r.starters.length?I(r.starters,o,{title:r.startersTitle}):null,r.moreStarters&&r.moreStarters.length?I(r.moreStarters,o,{title:r.moreStartersTitle}):null]))}return n.forEach(function(d,f){var c=d.id!==void 0&&d.id!==null?"id:"+d.id:"at:"+f,p=ge(d),h=a.els.get(c);d.pending&&!d.text&&!a.since.has(c)&&a.since.set(c,Date.now());var g;h&&h.look===p?g=h.el:(g=ne(d,Object.assign({},r,{labels:t,since:a.since.get(c)})),h&&pe(h.el,g)),s.set(c,{el:g,look:p}),i.push(g)}),a.els=s,a.since.forEach(function(d,f){s.has(f)||a.since.delete(f)}),e.replaceChildren.apply(e,i),e}function ve(e,n){n=n||{};var r=Object.assign({},b,n.labels||{});e.classList.add("gemboss-ec-scroll"),e.setAttribute("role","log"),e.hasAttribute("aria-label")||e.setAttribute("aria-label",n.label||r.thread);var t=!0,a=0,i=0,s=0,o=!1,d=null,f=function(){e.scrollTop=e.scrollHeight,d=e.scrollTop},c=function(){!t||a||(a=requestAnimationFrame(function(){a=0,t&&f()}))},p=function(){i=Date.now(),o=!0,t=!1},h=function(){o=!1},g=function(){var u=e.scrollHeight-e.clientHeight-e.scrollTop,N=d!==null&&e.scrollTop===d;d=null,u>24&&!N?t=!1:u<=4&&(!o||Date.now()-i>400)&&(t=!0)},m=function(u){u.deltaY<0?p():u.deltaY>0&&h()},v=function(u){s=u.touches[0]?u.touches[0].clientY:0},y=function(u){var N=u.touches[0]?u.touches[0].clientY:0;N>s+2?p():N<s-2&&h()},L=function(u){u.key==="ArrowUp"||u.key==="PageUp"||u.key==="Home"?p():(u.key==="ArrowDown"||u.key==="PageDown"||u.key==="End")&&h()};e.addEventListener("scroll",g,{passive:!0}),e.addEventListener("wheel",m,{passive:!0}),e.addEventListener("touchstart",v,{passive:!0}),e.addEventListener("touchmove",y,{passive:!0}),e.addEventListener("keydown",L),e.addEventListener("load",c,!0);var E=new MutationObserver(c);E.observe(e,{childList:!0,subtree:!0,characterData:!0});var S=typeof ResizeObserver>"u"?null:new ResizeObserver(c);return S&&S.observe(e),f(),{el:e,setBusy:function(u){u?e.setAttribute("aria-busy","true"):e.removeAttribute("aria-busy")},toEnd:function(){t=!0,f()},destroy:function(){cancelAnimationFrame(a),e.removeEventListener("scroll",g),e.removeEventListener("wheel",m),e.removeEventListener("touchstart",v),e.removeEventListener("touchmove",y),e.removeEventListener("keydown",L),e.removeEventListener("load",c,!0),E.disconnect(),S&&S.disconnect()}}}function be(){return M("0 0 24 24",[{d:"M21.4 11.1l-8.5 8.5a5.5 5.5 0 01-7.8-7.8l8.5-8.5a3.7 3.7 0 015.2 5.2l-8.5 8.5a1.8 1.8 0 01-2.6-2.6l7.8-7.8",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}])}function ye(e){e=e||{};var n=e.label||b.attach,r=l("input",{type:"file",hidden:!0,accept:e.accept||null,multiple:e.multiple||null,tabindex:"-1"}),t=l("button",{type:"button",className:"gemboss-ec-attach-btn","aria-label":n,title:e.title||n,disabled:e.disabled||null},be());t.addEventListener("click",function(){r.click()}),r.addEventListener("change",function(){var i=Array.prototype.slice.call(r.files||[]);r.value="",i.length&&e.onFiles&&e.onFiles(i)});var a=document.createDocumentFragment();return a.appendChild(t),a.appendChild(r),a}var W=["full","compact","icon","tight"];function Ne(e){var n=e.querySelector(".gemboss-ec-toolbar-lead"),r=e.querySelector(".gemboss-ec-toolbar");if(n&&n.scrollWidth>n.clientWidth+1||r&&r.scrollWidth>r.clientWidth+1)return!0;var t,a=e.querySelectorAll(".gemboss-ec-chiplabel, .gb-engine-chiplabel");for(t=0;t<a.length;t++)if(a[t].offsetParent!==null&&a[t].scrollWidth>a[t].clientWidth+1)return!0;for(a=e.querySelectorAll(".gemboss-ec-chipctl, .gb-engine-chip"),t=0;t<a.length;t++)if(a[t].offsetParent!==null&&a[t].tagName!=="SELECT"&&a[t].scrollWidth>a[t].clientWidth+1)return!0;return!1}function we(e,n){e&&!k(e)&&(n=e,e=null),n=n||{};var r=Object.assign({},b,n.labels||{}),t=!1,a=l("textarea",{rows:n.rows||1,maxlength:n.maxLength||null,"aria-label":n.label||r.message,placeholder:n.placeholder||null}),i=l("div",{className:"gemboss-ec-toolbar-lead"},n.leading||null),s=n.tools?l("div",{className:"gemboss-ec-toolbar-tools"},n.tools):null,o=l("button",{type:"submit",disabled:!0,"aria-label":r.send,title:r.send},M("0 0 20 20",[{d:"M10.53 4.47a.75.75 0 0 0-1.06 0l-4.5 4.5a.75.75 0 0 0 1.06 1.06l3.22-3.22v8.69a.75.75 0 0 0 1.5 0v-8.69l3.22 3.22a.75.75 0 1 0 1.06-1.06l-4.5-4.5Z"}])),d=l("button",{type:"button",className:"gemboss-ec-stop","aria-label":r.stop,title:r.stop},M("0 0 12 12",[{tag:"rect",x:"1",y:"1",width:"10",height:"10",rx:"2"}])),f=l("div",{className:"gemboss-ec-toolbar"},[i,s,n.status||null,o]),c=l("div",{className:"gemboss-ec-input","data-density":"full"},[n.top||null,a,f]);e&&e.appendChild(c);var p=function(){return!a.disabled&&a.value.trim()!==""&&(!t||n.sendWhileBusy||!n.onStop)},h=function(){var u=t&&!!n.onStop,N=u?d:o,re=u?o:d;re.parentNode&&re.replaceWith(N),o.disabled=!p()},g=function(){p()&&(n.onSend&&n.onSend(a.value),n.thread&&n.thread.toEnd&&n.thread.toEnd(),n.keepValue||(a.value="",m(),h()))},m=function(){if(!(a.offsetParent===null||a.scrollHeight===0)){var u=parseFloat(getComputedStyle(a).maxHeight)||84;a.style.height="auto";var N=a.scrollHeight+(a.offsetHeight-a.clientHeight);a.style.height=Math.min(N,u)+"px",a.style.overflowY=N>u?"auto":"hidden"}};a.addEventListener("input",function(){m(),h(),n.onChange&&n.onChange(a.value)}),a.addEventListener("keydown",function(u){n.onKeyDown&&n.onKeyDown(u),!u.defaultPrevented&&u.key==="Enter"&&!u.shiftKey&&!u.isComposing&&u.keyCode!==229&&(u.preventDefault(),g())}),o.addEventListener("click",function(u){u.preventDefault(),g()}),d.addEventListener("click",function(){n.onStop&&n.onStop(),a.focus()});var v=!1,y=function(){if(!(v||c.offsetParent===null)){v=!0;for(var u=0;u<W.length&&(c.setAttribute("data-density",W[u]),!(u===W.length-1||!Ne(c)));u++);v=!1,n.onDensity&&n.onDensity(c.getAttribute("data-density"))}},L=-1,E=typeof ResizeObserver>"u"?null:new ResizeObserver(function(){c.clientWidth!==L&&(L=c.clientWidth,y(),m())});E&&E.observe(c);var S=new MutationObserver(function(){v||y()});return S.observe(i,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-label","title","aria-label"]}),document.fonts&&document.fonts.ready&&document.fonts.ready.then(y),requestAnimationFrame(function(){y(),m()}),{el:c,textarea:a,value:function(){return a.value},setValue:function(u){a.value=u==null?"":String(u),m(),h()},setBusy:function(u){t=!!u,h()},setDisabled:function(u){a.disabled=!!u,h()},focus:function(){a.focus()},measure:y,destroy:function(){E&&E.disconnect(),S.disconnect(),c.remove()}}}var xe="The bridge on your machine is not responding: it was stopped, or the machine just slept. The panel is checking again; rerun the install command if it does not come back.",Ee="The bridge on your machine rejected this browser's pairing code (it was installed with another code). Pair again in Setup.";function Se(e,n){return e&&typeof e=="object"&&(e.atBridge=!0,n!==void 0&&(e.status=n)),e}function Ae(e,n){return n=n||{},e&&e.name==="AbortError"?{error:null,bridge:!1,stopped:!0}:e&&e.atBridge&&e.status===401?{error:n.rejected||Ee,bridge:!0,stopped:!1}:e&&e.atBridge&&(e instanceof TypeError||e.name==="TimeoutError")?{error:n.gone||xe,bridge:!0,stopped:!1}:{error:e&&e.message||String(e),bridge:!1,stopped:!1}}w.engineMark||(w.engineMark=Y),w.chat={markdown:G,parseBlocks:K,parseInline:F,linkTarget:C,imageSource:H,message:ne,render:me,thread:ve,steps:Z,pending:J,starters:I,meta:X,error:ee,note:_,composer:we,attach:ye,labels:b,atBridge:Se,turnError:Ae}})(typeof globalThis<"u"?globalThis:this);
@@ -11,10 +11,10 @@
11
11
  // · the edge box hands each keystroke to the caller (`onChange(side, raw)`) and says when to commit (`onCommit`, on
12
12
  // blur): the caller decides what an empty edge means, and the admin has three answers to that on purpose.
13
13
  import "../editor.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
14
- import { useEffect, useState } from "react";
14
+ import { useEffect, useId, useRef, useState } from "react";
15
15
  import type React from "react";
16
16
  import { cssUrl } from "./css-url";
17
- import { swatchState } from "./swatch";
17
+ import { swatchState, swatchWhy } from "./swatch";
18
18
  import { Segmented } from "../segmented";
19
19
 
20
20
  const blurOnEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
@@ -27,6 +27,8 @@ export interface SegOption<T extends string = string> {
27
27
  value: T;
28
28
  /** Default: the value itself. */
29
29
  label?: React.ReactNode;
30
+ /** The button's own name, for a label that is a glyph (an arrow), said by a screen reader and shown on hover. */
31
+ name?: string;
30
32
  }
31
33
 
32
34
  export interface SegProps<T extends string = string> {
@@ -49,7 +51,93 @@ export interface SegProps<T extends string = string> {
49
51
  export function Seg<T extends string = string>({ options, value, onChange, disabled, label, style }: SegProps<T>) {
50
52
  return (
51
53
  <Segmented<T> fill className="gemboss-ei-seg" style={style} ariaLabel={label ?? ""} value={(value ?? "") as T | ""} onChange={onChange} disabled={disabled}
52
- options={options.map((o) => ({ value: o.value, label: o.label ?? o.value }))} />
54
+ options={options.map((o) => ({ value: o.value, label: o.label ?? o.value, ...(o.name ? { ariaLabel: o.name, title: o.name } : {}) }))} />
55
+ );
56
+ }
57
+
58
+ // ── ValueControl ────────────────────────────────────────────────────────────────────────────────────────────────────
59
+
60
+ export interface ValueControlProps {
61
+ /** The number box's id (the Field's `htmlFor`). */
62
+ id?: string;
63
+ /** The field's name: the chips are announced as "<label> presets". */
64
+ label: string;
65
+ /** The named values, smallest first, each `value` as the box would hold it ("" = none). Shown as "name · number". */
66
+ presets: ReadonlyArray<{ value: string; label: string; title?: string }>;
67
+ /** What the box holds now: the stored value or the text being typed. */
68
+ text: string;
69
+ /** What an empty box follows (another screen's value, the theme's), greyed. */
70
+ placeholder?: string;
71
+ /** The unit after the box ("px", "%", "ms"). */
72
+ suffix?: string;
73
+ /** A slider under the box, for a bounded range of ≤ ~100 stops. `value` is where its thumb sits. */
74
+ slider?: { min: number; max: number; step?: number; value: number };
75
+ /** A chip: the caller saves it at once. */
76
+ onPreset: (value: string) => void;
77
+ /** Each key typed. */
78
+ onText: (raw: string) => void;
79
+ /** The box let go (blur, Enter). */
80
+ onCommit: () => void;
81
+ /** Each move of the slider. */
82
+ onSlide?: (value: number) => void;
83
+ /** Keys in the box (↑ ↓ nudges are the caller's). */
84
+ onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
85
+ /** A line under it (e.g. why a typed value was not kept as typed). */
86
+ note?: string;
87
+ /** The keyboard a phone shows: "decimal" (default) has no minus key on iOS, so a value that goes below 0 asks for "text". */
88
+ inputMode?: "decimal" | "text";
89
+ disabled?: boolean;
90
+ }
91
+
92
+ /**
93
+ * `.gemboss-ei-value` (0.38.0): a setting you can click, drag or type (Chris 15/10/2026: "vừa bấm được vừa nhập được, lười thì
94
+ * bấm"). The named values first, as the kit's segmented control (one lights when the box holds it; a value of its own lights
95
+ * none), then the number box with its unit and, for a bounded range, a slider. The caller owns the value: it turns chips, keys
96
+ * and moves into saves.
97
+ */
98
+ export function ValueControl({ id, label, presets, text, placeholder, suffix, slider, onPreset, onText, onCommit, onSlide, onKeyDown, note, inputMode = "decimal", disabled }: ValueControlProps) {
99
+ const lit = presets.find((p) => p.value === text.trim())?.value;
100
+ return (
101
+ // A chip pressed right after typing keeps the box's focus: its blur would save what was typed, the save locks the field, and
102
+ // the chip's click landed on a disabled chip (the spacing box's own guard, review of slice 5). The chip is the choice.
103
+ <div className="gemboss-ei-value" onMouseDown={(e) => { if ((e.target as HTMLElement).closest('[role="group"] button')) e.preventDefault(); }}>
104
+ {presets.length ? <Seg label={`${label} presets`} value={lit} disabled={disabled} onChange={onPreset}
105
+ options={presets.map((p) => ({ value: p.value, label: p.label }))} /> : null}
106
+ <div className="gemboss-ei-value-row">
107
+ <UnitField className="gemboss-ei-value-box" unit={suffix} id={id} inputMode={inputMode} value={text} placeholder={placeholder}
108
+ disabled={disabled} aria-label={label} onChange={(e) => onText(e.target.value)} onBlur={onCommit}
109
+ onKeyDown={(e) => { onKeyDown?.(e); if (!e.defaultPrevented) blurOnEnter(e); }} />
110
+ {slider && onSlide ? <RangeControl min={slider.min} max={slider.max} step={slider.step} value={slider.value} disabled={disabled} onChange={onSlide} /> : null}
111
+ </div>
112
+ {note ? <p className="gemboss-ei-hint" role="status">{note}</p> : null}
113
+ </div>
114
+ );
115
+ }
116
+
117
+ // ── UnitField ───────────────────────────────────────────────────────────────────────────────────────────────────────
118
+
119
+ export interface UnitFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className" | "style"> {
120
+ /** The unit after the value, inside the box ("px", "ms", "%"). Empty draws none. */
121
+ unit?: string;
122
+ /** Classes on the box, e.g. `gemboss-ei-inp` for a row's full-width control, `gemboss-ei-value-box` in ValueControl. */
123
+ className?: string;
124
+ /** Style on the box (a fixed width where a row lays out several controls). */
125
+ style?: React.CSSProperties;
126
+ }
127
+
128
+ /**
129
+ * A number box with its unit INSIDE (0.40.0; control standard, research pickers-2026-10-16 §13b U1), as Polaris TextField's
130
+ * `suffix`: the kit's field group (`.gemboss-field--group`, the box) around a bare input and `.gemboss-field__suffix`. Drawn beside
131
+ * the box, the unit was a second edge: 71 rows of the element panel stopped short of the panel's right edge. The box is a <label>,
132
+ * so a click or a tap anywhere in it, the unit included, focuses the input (one 44px target under a finger), as the kit's other
133
+ * field groups do. One owner for the shape: FieldRenderer's number, ValueControl's box and the theme inspector's design rows.
134
+ */
135
+ export function UnitField({ unit, className, style, ...input }: UnitFieldProps) {
136
+ return (
137
+ <label className={`gemboss-field gemboss-field--group${className ? ` ${className}` : ""}`} style={style}>
138
+ <input {...input} className="gemboss-field__bare" />
139
+ {unit ? <span className="gemboss-field__suffix">{unit}</span> : null}
140
+ </label>
53
141
  );
54
142
  }
55
143
 
@@ -75,15 +163,25 @@ export interface ColorControlProps {
75
163
  export function ColorControl({ id, value, onChange, disabled, label, placeholder }: ColorControlProps) {
76
164
  const [draft, setDraft] = useState(value);
77
165
  useEffect(() => { setDraft(value); }, [value]);
78
- const { swatch, usable } = swatchState(draft);
166
+ // NOT SET IS NOT BLACK (control standard §13b U7, Chris 20/10/2026): an empty colour drew the swatch black beside "Not set", so a
167
+ // seller read a colour nobody chose. Empty, the swatch is white with the slash a colour picker draws for "none" (editor.css
168
+ // `[data-empty]`), and opens on white.
169
+ const empty = !draft.trim();
170
+ const { swatch, usable } = swatchState(draft, "#ffffff");
171
+ // Why the swatch is off, said under it, read with it (a tooltip alone reached neither a finger nor the keys). The COMMITTED
172
+ // value's reason, and kept while the panel saves (it disables every field): taken from the draft or dropped while saving, the
173
+ // line came and went on every write and while a hex was typed (review of #4636). A draft that is a whole hex has none.
174
+ const why = usable ? null : swatchWhy(value);
175
+ const whyId = useId();
79
176
  return (
80
177
  <div className="gemboss-ei-color">
81
- <input type="color" className="gemboss-ei-swatch" aria-label={`${label} swatch`} value={swatch}
178
+ <input type="color" className="gemboss-ei-swatch" aria-label={`${label} swatch`} value={swatch} data-empty={empty ? "" : undefined}
82
179
  disabled={disabled || !usable}
83
- title={usable ? undefined : `${draft} — not a plain 6-digit hex; edit it in the box below`}
180
+ title={usable ? undefined : swatchWhy(draft) ?? undefined} aria-describedby={why ? whyId : undefined}
84
181
  onChange={(e) => { setDraft(e.target.value); onChange(e.target.value); }} />
85
- <input id={id} className="gemboss-field gemboss-ei-inp" placeholder={placeholder ?? "#000000 / var(--…)"} value={draft} disabled={disabled}
182
+ <input id={id} className="gemboss-field gemboss-ei-inp" placeholder={placeholder ?? "Not set"} value={draft} disabled={disabled}
86
183
  onChange={(e) => setDraft(e.target.value)} onBlur={() => onChange(draft)} onKeyDown={blurOnEnter} />
184
+ {why ? <p id={whyId} className="gemboss-ei-color-why">{why}</p> : null}
87
185
  </div>
88
186
  );
89
187
  }
@@ -132,11 +230,26 @@ export interface EdgeBoxProps {
132
230
  narrow?: boolean;
133
231
  /** Ids for the boxes, per side. */
134
232
  ids?: Partial<Record<EdgeSide, string>>;
233
+ /**
234
+ * A side's letter dragged sideways (Figma's and Webflow's scrub, 0.37.0): `dx`, the pixels moved since the press, and the keys
235
+ * held now, for the caller to turn into a value. A mouse or a pen only: a finger on the letter scrolls the panel as before, and
236
+ * the box takes the number (its 44px under a finger is the control there). Present, each letter is a 24px drag row.
237
+ */
238
+ onScrub?: (side: EdgeSide, dx: number, keys: { shiftKey: boolean; altKey: boolean }) => void;
239
+ /** The drag let go: `moved` when it changed anything (the caller saves once, one Undo step); not moved, it was a click. */
240
+ onScrubEnd?: (side: EdgeSide, moved: boolean) => void;
135
241
  }
136
242
 
137
243
  /** `.gemboss-ei-edgebox`: four px boxes, T · R · B · L, mono and centred. */
138
- export function EdgeBox({ label, values, placeholders, onChange, onCommit, disabled, narrow = true, ids }: EdgeBoxProps) {
244
+ export function EdgeBox({ label, values, placeholders, onChange, onCommit, disabled, narrow = true, ids, onScrub, onScrubEnd }: EdgeBoxProps) {
139
245
  const cls = narrow ? "gemboss-field gemboss-field--narrow gemboss-ei-inp" : "gemboss-field gemboss-ei-inp";
246
+ const drag = useRef<{ side: EdgeSide; id: number; x: number; moved: boolean } | null>(null);
247
+ const end = (e: React.PointerEvent<HTMLSpanElement>) => {
248
+ const d = drag.current;
249
+ if (!d || d.id !== e.pointerId) return;
250
+ drag.current = null;
251
+ onScrubEnd?.(d.side, d.moved);
252
+ };
140
253
  return (
141
254
  <div className="gemboss-ei-edgebox">
142
255
  {SIDES.map((s) => (
@@ -144,7 +257,29 @@ export function EdgeBox({ label, values, placeholders, onChange, onCommit, disab
144
257
  <input className={cls} inputMode="numeric" placeholder={placeholders?.[s] ?? "0"}
145
258
  aria-label={`${label} ${SIDE_NAME[s]}`} id={ids?.[s]} value={values[s] ?? ""} disabled={disabled}
146
259
  onChange={(e) => onChange(s, e.target.value)} onBlur={onCommit} onKeyDown={blurOnEnter} />
147
- <span>{s.toUpperCase()}</span>
260
+ {onScrub ? (
261
+ // Rendered while disabled too: a field that locks in the middle of a drag (another save landing) must not drop the
262
+ // drag's handlers, or it never ends and nothing is saved (review of 3a). A drag only refuses to START when disabled.
263
+ <span className="gemboss-ei-edge-scrub" title={`Drag to change ${SIDE_NAME[s]}`} aria-disabled={disabled || undefined}
264
+ onPointerDown={(e) => {
265
+ if (disabled || e.pointerType === "touch" || e.button !== 0) return;
266
+ e.preventDefault();
267
+ e.currentTarget.setPointerCapture(e.pointerId);
268
+ drag.current = { side: s, id: e.pointerId, x: e.clientX, moved: false };
269
+ }}
270
+ onPointerMove={(e) => {
271
+ const d = drag.current;
272
+ if (!d || d.id !== e.pointerId) return;
273
+ const dx = e.clientX - d.x;
274
+ // A press that wanders a pixel is still a click.
275
+ if (!d.moved && Math.abs(dx) < 2) return;
276
+ d.moved = true;
277
+ onScrub(s, dx, { shiftKey: e.shiftKey, altKey: e.altKey });
278
+ }}
279
+ onPointerUp={end} onPointerCancel={end}
280
+ // Its own capture only (the event bubbles from nothing here, but the check is the fleet's rule).
281
+ onLostPointerCapture={(e) => { if (e.target === e.currentTarget) end(e); }}>{s.toUpperCase()}</span>
282
+ ) : <span>{s.toUpperCase()}</span>}
148
283
  </div>
149
284
  ))}
150
285
  </div>
@@ -153,7 +288,9 @@ export function EdgeBox({ label, values, placeholders, onChange, onCommit, disab
153
288
 
154
289
  // ── ImageControl ────────────────────────────────────────────────────────────────────────────────────────────────────
155
290
 
156
- /** A dashed pill button (`.gemboss-ei-addchip`): an image slot's Library / Generate / Clear, a panel's "+ Add". */
291
+ /** A field's own button (an image slot's Library / Generate / Clear, a link's Choose, a panel's "+ Add"): the kit's `.ui-btn`, a Polaris
292
+ * secondary button (28px, 12px / 550, radius 8; 44px under a finger). It was a dashed pill (`.gemboss-ei-addchip`, 27px, 11px / 600,
293
+ * radius 999): control standard U3, research pickers-2026-10-16 §13b. */
157
294
  export function ChipButton({ disabled, expanded, onClick, children }: {
158
295
  disabled?: boolean;
159
296
  /** `aria-expanded`, for a chip that opens something under it (the Library grid). */
@@ -161,7 +298,7 @@ export function ChipButton({ disabled, expanded, onClick, children }: {
161
298
  onClick?: React.MouseEventHandler<HTMLButtonElement>;
162
299
  children: React.ReactNode;
163
300
  }) {
164
- return <button type="button" className="gemboss-ei-addchip" disabled={disabled} aria-expanded={expanded} onClick={onClick}>{children}</button>;
301
+ return <button type="button" className="ui-btn" disabled={disabled} aria-expanded={expanded} onClick={onClick}>{children}</button>;
165
302
  }
166
303
 
167
304
  export interface ImageControlProps {
@@ -156,20 +156,24 @@ export function EditorBack({ as: Comp = "button", label = "Back", ...rest }:
156
156
 
157
157
  /**
158
158
  * The auto-save pill: "Saving…" with a spinner while an edit is in flight, "✓ Draft saved" once it lands.
159
- * `idle` draws nothing unless `idleText` says what autosave means here (the section editor's "Autosaves", dimmed).
159
+ * `idle` draws nothing unless `idleText` says what autosave means here (the section editor's "Autosaves", muted).
160
+ * `live` (default true): "Saving…" and "✓ Draft saved" are a polite live region. `live={false}` for a surface that speaks
161
+ * through a live region of its own, one that is in the page from its first render and says only what changed (the page
162
+ * editor's save pill): the pill is then words with a title, and nothing is announced twice.
160
163
  */
161
164
  export function EditorSaveState({
162
165
  state, savedText = "✓ Draft saved", savingText = "Saving…", savingTitle = "Saving draft…",
163
- savedTitle = "Every change is saved to the draft automatically", idleText,
166
+ savedTitle = "Every change is saved to the draft automatically", idleText, live = true,
164
167
  }: {
165
168
  state: "idle" | "saving" | "saved";
166
169
  savedText?: React.ReactNode; savingText?: React.ReactNode; savingTitle?: string; savedTitle?: string; idleText?: React.ReactNode;
170
+ live?: boolean;
167
171
  }) {
168
172
  if (state === "idle") {
169
- return idleText != null && idleText !== false ? <span className="gemboss-editor-savestate" title={savedTitle} style={{ opacity: 0.55 }}>{idleText}</span> : null;
173
+ return idleText != null && idleText !== false ? <span className="gemboss-editor-savestate is-idle" title={savedTitle}>{idleText}</span> : null;
170
174
  }
171
175
  return (
172
- <span className={`gemboss-editor-savestate is-${state}`} role="status" aria-live="polite" title={state === "saving" ? savingTitle : savedTitle}>
176
+ <span className={`gemboss-editor-savestate is-${state}`} {...(live ? { role: "status", "aria-live": "polite" as const } : null)} title={state === "saving" ? savingTitle : savedTitle}>
173
177
  {state === "saving" ? <><span className="gemboss-narr-spin" aria-hidden />{savingText}</> : savedText}
174
178
  </span>
175
179
  );