@liveroom-tech/react-immersive 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/components/ModelViewer/ModelViewer.tsx
2
2
  import {
3
- useRef as useRef10,
3
+ useRef as useRef11,
4
4
  useState as useState10,
5
5
  useEffect as useEffect14,
6
6
  useCallback as useCallback4,
@@ -42,7 +42,7 @@ function styleInject(css, { insertAt } = {}) {
42
42
  }
43
43
 
44
44
  // src/styles/ModelViewer.css
45
- styleInject('.ri-viewer--license-checking,\n.ri-viewer--license-invalid {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n background-color: #f9f9f9;\n}\n.ri-viewer {\n --ri-font-family:\n Inter,\n "Segoe UI",\n Helvetica,\n Arial,\n sans-serif;\n --ri-viewer-bg: #1c1c1d;\n --ri-viewer-text: #111827;\n --ri-panel-bg: #ffffff;\n --ri-panel-border: #e5e7eb;\n --ri-panel-title: #111827;\n --ri-panel-muted-text: #4b5563;\n --ri-panel-subtle-text: #9ca3af;\n --ri-panel-surface: #f9fafb;\n --ri-panel-surface-hover: #f3f4f6;\n --ri-panel-surface-border: #e5e7eb;\n --ri-panel-button-text: #1f2937;\n --ri-panel-accent: #2563eb;\n --ri-panel-accent-contrast: #ffffff;\n --ri-license-overlay-bg: rgba(0, 0, 0, 0.04);\n --ri-license-overlay-border: rgba(0, 0, 0, 0.08);\n --ri-license-overlay-text: #888;\n --ri-license-overlay-error-bg: rgba(192, 57, 43, 0.06);\n --ri-license-overlay-error-border: rgba(192, 57, 43, 0.2);\n --ri-license-overlay-error-text: #c0392b;\n --ri-sidepanel-font-family:\n Inter,\n "Segoe UI",\n Helvetica,\n Arial,\n sans-serif;\n --ri-sidepanel-bg: #141824;\n --ri-sidepanel-open-btn-bg: rgba(20, 20, 20, 0.82);\n --ri-sidepanel-open-btn-bg-hover: #27282b7e;\n --ri-sidepanel-border: rgba(255, 255, 255, 0.06);\n --ri-sidepanel-divider: rgba(255, 255, 255, 0.04);\n --ri-sidepanel-border-strong: rgba(255, 255, 255, 0.08);\n --ri-sidepanel-border-active: rgba(255, 255, 255, 0.18);\n --ri-sidepanel-shadow-left: 4px 0 24px rgba(0, 0, 0, 0.35);\n --ri-sidepanel-shadow-right: -4px 0 24px rgba(0, 0, 0, 0.35);\n --ri-sidepanel-text: #f1f5f9;\n --ri-sidepanel-text-emphasis: #ffffff;\n --ri-sidepanel-text-muted: #94a3b8;\n --ri-sidepanel-text-subtle: #64748b;\n --ri-sidepanel-placeholder: #475569;\n --ri-sidepanel-surface: rgba(255, 255, 255, 0.05);\n --ri-sidepanel-surface-hover: rgba(255, 255, 255, 0.1);\n --ri-sidepanel-accent: #3b82f6;\n --ri-sidepanel-accent-soft: rgba(59, 130, 246, 0.12);\n --ri-databinding-bg: #111318;\n --ri-databinding-border: rgba(255, 255, 255, 0.06);\n --ri-databinding-border-strong: rgba(255, 255, 255, 0.08);\n --ri-databinding-border-hover: rgba(255, 255, 255, 0.15);\n --ri-databinding-shadow: 4px 0 24px rgba(0, 0, 0, 0.35);\n --ri-databinding-font-family:\n "Inter",\n "Segoe UI",\n sans-serif;\n --ri-databinding-mono-font-family:\n "JetBrains Mono",\n "Fira Code",\n "Menlo",\n monospace;\n --ri-databinding-text: #f1f5f9;\n --ri-databinding-text-muted: #94a3b8;\n --ri-databinding-text-subtle: #64748b;\n --ri-databinding-text-faint: #475569;\n --ri-databinding-text-hover: #cbd5e1;\n --ri-databinding-surface: rgba(255, 255, 255, 0.03);\n --ri-databinding-surface-hover: rgba(255, 255, 255, 0.06);\n --ri-databinding-accent: #93c5fd;\n --ri-databinding-accent-glow: rgba(147, 197, 253, 0.8);\n --ri-databinding-accent-border: rgba(96, 165, 250, 0.55);\n --ri-databinding-accent-gradient:\n linear-gradient(\n \n 135deg,\n #1e3a8a 0%,\n #1d4ed8 60%,\n #2563eb 100% );\n --ri-databinding-accent-gradient-active:\n linear-gradient(\n \n 135deg,\n #1e3a8a 0%,\n #1e40af 100% );\n display: flex;\n flex-direction: row;\n width: 100%;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n background: var(--ri-viewer-bg);\n position: relative;\n color: var(--ri-viewer-text);\n font-family: var(--ri-font-family);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n font-synthesis: none;\n}\n.ri-viewer * {\n box-sizing: border-box;\n}\n.ri-viewerLeft {\n display: flex;\n flex: 1;\n min-height: 0;\n min-width: 0;\n position: relative;\n}\n.ri-viewerRight {\n display: flex;\n flex-shrink: 0;\n min-width: 0;\n}\n.ri-panel {\n width: 280px;\n min-height: 0;\n background: var(--ri-panel-bg);\n border-right: 1px solid var(--ri-panel-border);\n display: flex;\n flex-direction: column;\n padding: 20px;\n overflow-y: auto;\n flex-shrink: 0;\n transition: margin-left 0.3s ease, transform 0.3s ease;\n}\n.ri-panel--open {\n transform: translateX(0);\n margin-left: 0;\n}\n.ri-panel--closed {\n transform: translateX(-100%);\n margin-left: -280px;\n}\n.ri-panelHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n}\n.ri-panelTitle {\n margin: 0;\n font-size: 15px;\n font-weight: 700;\n color: var(--ri-panel-title);\n line-height: 1.4;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ri-closeButton {\n border: 0;\n background: transparent;\n color: var(--ri-panel-subtle-text);\n font-size: 22px;\n line-height: 1;\n padding: 0;\n cursor: pointer;\n flex-shrink: 0;\n transition: color 0.2s ease;\n}\n.ri-closeButton:hover {\n color: var(--ri-panel-muted-text);\n}\n.ri-json {\n margin: 0 0 16px;\n padding: 12px;\n background: var(--ri-panel-surface);\n border: 1px solid var(--ri-panel-surface-border);\n border-radius: 12px;\n font-size: 12px;\n line-height: 1.55;\n color: var(--ri-panel-button-text);\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n.ri-divider {\n border-top: 1px solid var(--ri-panel-border);\n margin-bottom: 12px;\n}\n.ri-sectionLabel {\n margin-bottom: 8px;\n font-size: 11px;\n font-weight: 700;\n color: var(--ri-panel-subtle-text);\n text-transform: uppercase;\n letter-spacing: 0.16em;\n}\n.ri-actionList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.ri-actionButton {\n width: 100%;\n border-radius: 8px;\n border: 1px solid var(--ri-panel-surface-border);\n background: var(--ri-panel-surface);\n color: var(--ri-panel-button-text);\n padding: 10px 12px;\n text-align: left;\n font-size: 14px;\n line-height: 1.4;\n cursor: pointer;\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease,\n color 0.2s ease;\n}\n.ri-actionButton:hover {\n background: var(--ri-panel-surface-hover);\n border-color: var(--ri-panel-border);\n}\n.ri-actionButton--active {\n background: var(--ri-panel-accent);\n border-color: var(--ri-panel-accent);\n color: var(--ri-panel-accent-contrast);\n}\n.ri-actionButton--active:hover {\n background: var(--ri-panel-accent);\n border-color: var(--ri-panel-accent);\n}\n.ri-canvasArea {\n flex: 1 1 auto;\n position: relative;\n min-width: 0;\n}\n.ri-canvasArea--measuring {\n cursor: crosshair;\n}\n.ri-canvasArea canvas {\n opacity: 1;\n transition: opacity 0.18s ease;\n}\n.ri-canvasArea--positioning canvas {\n opacity: 0;\n transition: none;\n}\n.ri-bindingsMismatchBanner {\n position: absolute;\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 20;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 12px 7px 10px;\n border-radius: 8px;\n background: rgba(30, 20, 0, 0.88);\n border: 1px solid rgba(251, 191, 36, 0.35);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n color: rgb(251, 191, 36);\n font-size: 12px;\n font-weight: 500;\n line-height: 1.4;\n white-space: nowrap;\n pointer-events: auto;\n max-width: calc(100% - 32px);\n white-space: normal;\n text-align: center;\n}\n.ri-bindingsMismatchBanner__icon {\n flex-shrink: 0;\n}\n.ri-bindingsMismatchBanner__dismiss {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: 4px;\n padding: 2px;\n background: none;\n border: none;\n border-radius: 4px;\n color: rgba(251, 191, 36, 0.7);\n cursor: pointer;\n transition: color 0.15s ease, background 0.15s ease;\n}\n.ri-bindingsMismatchBanner__dismiss:hover {\n color: rgb(251, 191, 36);\n background: rgba(251, 191, 36, 0.12);\n}\n.ri-measureTools {\n position: absolute;\n top: 16px;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-measureButton {\n width: 34px;\n height: 34px;\n padding: 0;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.75);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n touch-action: manipulation;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n transition:\n background 0.15s ease,\n color 0.15s ease,\n border-color 0.15s ease;\n}\n.ri-measureButton:hover {\n background: rgba(40, 40, 40, 0.92);\n color: #fff;\n border-color: rgba(255, 255, 255, 0.25);\n}\n.ri-measureButton:active {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-measureButton--active {\n background: #22d3ee;\n border-color: #22d3ee;\n color: #06343c;\n}\n.ri-measureButton--active:hover {\n background: #38dbf0;\n color: #06343c;\n}\n.ri-measureHint {\n padding: 6px 10px;\n border-radius: 8px;\n font-size: 12px;\n line-height: 1;\n color: #fff;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n white-space: nowrap;\n}\n.ri-explodeTools {\n position: absolute;\n top: 16px;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-explodeTools--stacked {\n top: 58px;\n}\n.ri-explodeSlider {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 34px;\n padding: 0 12px;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 8px;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n}\n.ri-explodeSlider input[type=range] {\n width: 120px;\n accent-color: #22d3ee;\n cursor: pointer;\n}\n.ri-cinematicTools {\n position: absolute;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-measureDot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #22d3ee;\n border: 2px solid #fff;\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);\n pointer-events: none;\n}\n.ri-measureLabel {\n padding: 3px 7px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n white-space: nowrap;\n color: #06343c;\n background: #22d3ee;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);\n pointer-events: none;\n user-select: none;\n}\n.ri-xrTools {\n position: absolute;\n top: 16px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-xrButton {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 34px;\n padding: 0 10px;\n font-size: 13px;\n font-weight: 500;\n color: #fff;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.16);\n border-radius: 10px;\n cursor: pointer;\n touch-action: manipulation;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n.ri-xrButton:hover {\n background: rgba(40, 40, 40, 0.92);\n border-color: rgba(255, 255, 255, 0.3);\n}\n.ri-arHintOverlay {\n position: absolute;\n top: 18px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n width: min(calc(100% - 32px), 360px);\n pointer-events: none;\n}\n.ri-arHint {\n margin: 0 auto;\n width: fit-content;\n max-width: 100%;\n padding: 6px 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1.2;\n text-align: center;\n color: rgba(255, 255, 255, 0.92);\n background: rgba(20, 20, 20, 0.58);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 999px;\n user-select: none;\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n.ri-arOverlay {\n position: absolute;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n width: min(calc(100% - 32px), 420px);\n pointer-events: none;\n}\n.ri-arControls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n}\n.ri-arStatus,\n.ri-arActionButton {\n max-width: 100%;\n padding: 8px 16px;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n text-align: center;\n white-space: nowrap;\n color: #fff;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.16);\n border-radius: 19px;\n user-select: none;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n}\n.ri-arStatus {\n pointer-events: none;\n}\n.ri-arActionButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n cursor: pointer;\n pointer-events: auto;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n transition:\n background 0.15s ease,\n border-color 0.15s ease,\n color 0.15s ease,\n transform 0.15s ease;\n}\n.ri-arActionButton svg {\n flex-shrink: 0;\n}\n.ri-arActionButton:hover {\n background: rgba(40, 40, 40, 0.92);\n border-color: rgba(255, 255, 255, 0.3);\n}\n.ri-arActionButton:active {\n transform: scale(0.98);\n}\n.ri-arActionButton--primary {\n color: #06343c;\n background: #22d3ee;\n border-color: transparent;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);\n}\n.ri-arActionButton--primary:hover {\n background: #67e8f9;\n border-color: transparent;\n}\n.ri-arActionButton.ri-arActionButton--active,\n.ri-arActionButton[aria-pressed=true],\n.ri-arActionButton.ri-arActionButton--active:hover,\n.ri-arActionButton[aria-pressed=true]:hover,\n.ri-arActionButton.ri-arActionButton--active:active,\n.ri-arActionButton[aria-pressed=true]:active {\n color: #06343c;\n background: #22d3ee;\n border-color: transparent;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);\n}\n.ri-hiddenInput {\n display: none;\n}\n.ri-popover {\n position: absolute;\n z-index: 50;\n background: #ffffff;\n border: 1px solid #e5e7eb;\n border-radius: 16px;\n box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18);\n color: #111827;\n}\n.ri-popoverHeader {\n padding: 12px 16px;\n border-bottom: 1px solid #f3f4f6;\n}\n.ri-popoverLabel {\n margin: 0 0 8px;\n font-size: 11px;\n font-weight: 700;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.16em;\n}\n.ri-inlineRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 8px;\n}\n.ri-colorCode {\n font-size: 12px;\n color: #9ca3af;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n text-transform: uppercase;\n}\n.ri-secondaryButton {\n border: 1px solid #e5e7eb;\n background: #f3f4f6;\n color: #374151;\n border-radius: 8px;\n padding: 6px 10px;\n font-size: 12px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.ri-secondaryButton:hover {\n background: #e5e7eb;\n}\n.ri-materialBody {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px;\n}\n.ri-previewFrame {\n position: relative;\n height: 112px;\n border-radius: 12px;\n overflow: hidden;\n border: 1px solid #e5e7eb;\n}\n.ri-previewImage {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n.ri-previewCaption {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n padding: 4px 8px;\n color: #ffffff;\n font-size: 10px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ri-emptyState {\n height: 112px;\n border-radius: 12px;\n border: 2px dashed #e5e7eb;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 4px;\n color: #d1d5db;\n text-align: center;\n}\n.ri-uploadButton {\n width: 100%;\n border: 0;\n border-radius: 10px;\n background: #111827;\n color: #ffffff;\n padding: 10px 12px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.ri-uploadButton:hover {\n background: #374151;\n}\n.ri-removeButton {\n width: 100%;\n border-radius: 10px;\n border: 1px solid #e5e7eb;\n background: #ffffff;\n color: #6b7280;\n padding: 8px 12px;\n font-size: 12px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.ri-removeButton:hover {\n background: #f9fafb;\n}\n.ri-formatHint {\n margin: 0;\n text-align: center;\n font-size: 10px;\n color: #d1d5db;\n}\n.ri-buttonContainer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n gap: 8px;\n position: absolute;\n bottom: 12px;\n left: 12px;\n right: 12px;\n z-index: 10;\n}\n.ri-tourControls {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-shrink: 0;\n}\n.ri-rightControls {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-shrink: 0;\n margin-left: auto;\n}\n.ri-rightControls:only-child {\n margin-left: auto;\n}\n.ri-navButtonSingle,\n.ri-tourButton,\n.ri-resetButton,\n.ri-downloadButton {\n height: 34px;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.75);\n border-radius: 8px;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n cursor: pointer;\n transition:\n background 0.15s ease,\n color 0.15s ease,\n border-color 0.15s ease,\n transform 0.15s ease;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n.ri-navButtonSingle:hover:not(:disabled),\n.ri-tourButton:hover:not(:disabled),\n.ri-resetButton:hover:not(:disabled) {\n background: rgba(40, 40, 40, 0.92);\n color: #fff;\n border-color: rgba(255, 255, 255, 0.25);\n}\n.ri-navButtonSingle:active:not(:disabled),\n.ri-tourButton:active:not(:disabled),\n.ri-resetButton:active:not(:disabled) {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-navButtonSingle:disabled,\n.ri-tourButton:disabled,\n.ri-resetButton:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.ri-navButtonSingle {\n padding: 0 16px;\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n}\n.ri-tourButton {\n padding: 0 12px;\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n.ri-tourButton svg {\n width: 15px;\n height: 15px;\n flex-shrink: 0;\n}\n.ri-tourButton--stop {\n border-color: rgba(255, 68, 68, 0.4);\n color: #ff6b6b;\n}\n.ri-tourButton--stop:hover:not(:disabled) {\n background: rgba(255, 68, 68, 0.15);\n border-color: rgba(255, 68, 68, 0.6);\n color: #ff6b6b;\n}\n.ri-tourButton--stop:active:not(:disabled) {\n background: #ff4444;\n color: #fff;\n border-color: #ff4444;\n}\n.ri-tourButton--next {\n border-color: rgba(56, 219, 240, 0.3);\n color: #38dbf0;\n}\n.ri-tourButton--next:hover:not(:disabled) {\n background: rgba(56, 219, 240, 0.12);\n border-color: rgba(56, 219, 240, 0.5);\n color: #38dbf0;\n}\n.ri-tourButton--next:active:not(:disabled) {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-resetButton {\n width: 34px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.ri-resetButton svg {\n width: 15px;\n height: 15px;\n pointer-events: none;\n flex-shrink: 0;\n}\n.ri-resetButton:focus-visible {\n outline: 2px solid rgba(255, 255, 255, 0.5);\n outline-offset: 2px;\n}\n.ri-downloadWrapper {\n position: relative;\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n}\n.ri-downloadButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 0 16px;\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n}\n.ri-downloadButton:hover:not(:disabled) {\n background: rgba(0, 0, 0, 0.72);\n border-color: rgba(255, 255, 255, 0.3);\n color: #fff;\n}\n.ri-downloadButton:active:not(:disabled) {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-downloadButton:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.ri-downloadButton__spinner {\n display: inline-block;\n width: 13px;\n height: 13px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: ri-spin 0.7s linear infinite;\n flex-shrink: 0;\n}\n.ri-downloadMenu {\n position: absolute;\n bottom: calc(100% + 6px);\n right: 0;\n min-width: 168px;\n background: rgba(20, 20, 20, 0.92);\n border: 1px solid rgba(255, 255, 255, 0.14);\n border-radius: 10px;\n overflow: hidden;\n z-index: 100;\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n animation: ri-menuReveal 0.12s ease;\n}\n@keyframes ri-menuReveal {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ri-downloadMenuItem {\n display: flex;\n align-items: center;\n gap: 9px;\n width: 100%;\n padding: 10px 14px;\n font-size: 13px;\n font-weight: 400;\n color: #fff;\n background: transparent;\n border: none;\n cursor: pointer;\n text-align: left;\n transition: background 0.1s ease;\n}\n.ri-downloadMenuItem:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.1);\n}\n.ri-downloadMenuItem:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.ri-downloadMenuDivider {\n height: 1px;\n background: rgba(255, 255, 255, 0.1);\n margin: 0 10px;\n}\n@keyframes ri-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.ri-annotationMarker {\n position: relative;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: rgba(20, 20, 20, 0.82);\n border: 2px solid rgba(255, 255, 255, 0.9);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n font-weight: 700;\n cursor: pointer;\n z-index: 20;\n user-select: none;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);\n pointer-events: auto;\n transition: opacity 0.3s ease, transform 0.3s ease;\n}\n.ri-annotationMarker:hover {\n transform: scale(1.08);\n box-shadow: 0 12px 28px rgba(15, 23, 42, 0.18);\n background: rgba(40, 40, 40, 0.92);\n}\n.ri-annotationPopup {\n position: absolute;\n width: min(270px, calc(100vw - 32px));\n background: rgba(20, 20, 20, 0.85);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 16px;\n padding: 16px;\n z-index: 30;\n display: flex;\n flex-direction: column;\n gap: 12px;\n box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n}\n.ri-annotationInput,\n.ri-annotationTextarea {\n width: 100%;\n border: 1px solid rgba(255, 255, 255, 0.12);\n background: rgba(255, 255, 255, 0.05);\n color: #e5e7eb;\n border-radius: 10px;\n padding: 10px 12px;\n outline: none;\n font-family: inherit;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n}\n.ri-annotationInput {\n font-size: 14px;\n font-weight: 500;\n}\n.ri-annotationTextarea {\n font-size: 13px;\n resize: vertical;\n min-height: 110px;\n}\n.ri-annotationInput:focus,\n.ri-annotationTextarea:focus {\n border-color: #38dbf0;\n box-shadow: 0 0 0 3px rgba(56, 219, 240, 0.12);\n}\n.ri-annotationActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.ri-annotationOkBtn {\n border: 0;\n border-radius: 8px;\n background: rgba(56, 219, 240, 0.8);\n color: #06343c;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s ease, opacity 0.2s ease;\n}\n.ri-annotationOkBtn:hover:not(:disabled) {\n background: #38dbf0;\n}\n.ri-annotationOkBtn:disabled,\n.ri-annotationOkBtn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ri-annotationCancelBtn {\n border: 1px solid rgba(255, 255, 255, 0.12);\n background: transparent;\n color: #9ca3af;\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 13px;\n cursor: pointer;\n transition: background-color 0.2s ease, border-color 0.2s ease;\n}\n.ri-annotationCancelBtn:hover {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.2);\n}\n.ri-annotationIcons {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 12px;\n color: #9ca3af;\n}\n.ri-annotationIcons svg {\n flex-shrink: 0;\n}\n.ri-viewAnnotationPopup {\n position: relative;\n background: rgba(20, 20, 20, 0.85);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 8px;\n padding: 12px 16px;\n min-width: 200px;\n max-width: min(280px, calc(100vw - 48px));\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);\n pointer-events: auto;\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n animation: ri-viewAnnotationFadeIn 0.15s ease-out;\n margin-left: 24px;\n margin-top: -20px;\n isolation: isolate;\n z-index: 1000;\n}\n.ri-viewAnnotationHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n.ri-viewAnnotationTitle {\n margin: 0;\n color: #e2e8f0;\n font-size: 14px;\n font-weight: 600;\n}\n.ri-viewAnnotationClose {\n background: transparent;\n border: none;\n color: #b7bdc6;\n cursor: pointer;\n font-size: 18px;\n padding: 0 4px;\n transition: color 0.2s;\n line-height: 1;\n}\n.ri-viewAnnotationClose:hover {\n color: #e2e8f0;\n}\n.ri-viewAnnotationDescription {\n margin: 0;\n color: #cbd5e1;\n font-size: 13px;\n line-height: 1.4;\n word-wrap: break-word;\n}\n@keyframes ri-viewAnnotationFadeIn {\n from {\n opacity: 0;\n transform: translateY(-6px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ri-annotationNavSingle {\n position: absolute;\n bottom: 120px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n pointer-events: none;\n}\n.ri-annotationNavSingle > * {\n pointer-events: auto;\n}\n.ri-navBadge {\n background: rgba(255, 255, 255, 0.1);\n padding: 2px 10px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 400;\n color: rgba(255, 255, 255, 0.7);\n}\n.ri-annotationTitleHint {\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: white;\n padding: 8px 20px;\n border-radius: 8px;\n font-size: 13px;\n border: 1px solid rgba(255, 255, 255, 0.08);\n text-align: center;\n max-width: 350px;\n animation: slideUp 0.3s ease;\n}\n.ri-annotationHintTitle {\n font-weight: 600;\n color: #e5e7eb;\n}\n.ri-annotationHintDesc {\n font-size: 12px;\n opacity: 0.6;\n margin-top: 2px;\n color: #d1d5db;\n}\n@keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@media (max-width: 768px) {\n .ri-xrTools {\n gap: 6px;\n }\n .ri-xrButton {\n height: 30px;\n gap: 6px;\n padding: 0 8px;\n font-size: 11px;\n }\n .ri-xrButton svg {\n width: 14px;\n height: 14px;\n }\n .ri-xrButtonPrefix {\n display: none;\n }\n .ri-annotationNavSingle {\n bottom: 100px;\n }\n .ri-navButtonSingle {\n padding: 8px 20px;\n font-size: 13px;\n min-width: 110px;\n }\n .ri-annotationTitleHint {\n padding: 6px 14px;\n font-size: 12px;\n max-width: 250px;\n }\n .ri-viewAnnotationPopup {\n min-width: 160px;\n max-width: 220px;\n padding: 10px 12px;\n }\n .ri-viewAnnotationTitle {\n font-size: 13px;\n }\n .ri-viewAnnotationDescription {\n font-size: 12px;\n }\n .ri-buttonContainer {\n flex-wrap: wrap;\n gap: 6px;\n }\n .ri-tourControls {\n flex-wrap: wrap;\n }\n .ri-rightControls {\n flex-wrap: wrap;\n }\n}\n@media (max-width: 480px) {\n .ri-xrTools {\n top: 12px;\n gap: 5px;\n }\n .ri-xrButton {\n height: 28px;\n gap: 5px;\n padding: 0 7px;\n font-size: 10px;\n }\n .ri-xrButton svg {\n width: 13px;\n height: 13px;\n }\n .ri-annotationNavSingle {\n bottom: 80px;\n }\n .ri-navButtonSingle {\n padding: 6px 16px;\n font-size: 12px;\n min-width: 90px;\n gap: 6px;\n }\n .ri-annotationTitleHint {\n padding: 4px 10px;\n font-size: 11px;\n max-width: 200px;\n }\n .ri-navBadge {\n font-size: 10px;\n padding: 1px 6px;\n }\n .ri-tourButton {\n padding: 0 8px;\n font-size: 12px;\n }\n .ri-tourButton span {\n display: none;\n }\n .ri-downloadButton {\n padding: 0 10px;\n font-size: 12px;\n }\n .ri-downloadButton span {\n display: none;\n }\n}\n.ri-canvasArea .bb-loadingOverlay {\n position: absolute;\n inset: 0;\n z-index: 12;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n padding: 24px;\n text-align: center;\n border-radius: 14px;\n background: rgba(15, 23, 42, 0.46);\n backdrop-filter: blur(1px);\n}\n.ri-canvasArea .bb-loadingSpinner {\n width: 40px;\n height: 40px;\n border-radius: 999px;\n border: 3px solid rgba(226, 232, 240, 0.24);\n border-top-color: #93c5fd;\n animation: bb-spin 0.8s linear infinite;\n}\n.ri-canvasArea .bb-loadingMessage {\n max-width: 320px;\n color: #f7f8f9;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.5;\n}\n@keyframes bb-spin {\n to {\n transform: rotate(360deg);\n }\n}\n');
45
+ styleInject('.ri-viewer--license-checking,\n.ri-viewer--license-invalid {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n background-color: #f9f9f9;\n}\n.ri-viewer {\n --ri-font-family:\n Inter,\n "Segoe UI",\n Helvetica,\n Arial,\n sans-serif;\n --ri-viewer-bg: #1c1c1d;\n --ri-viewer-text: #111827;\n --ri-panel-bg: #ffffff;\n --ri-panel-border: #e5e7eb;\n --ri-panel-title: #111827;\n --ri-panel-muted-text: #4b5563;\n --ri-panel-subtle-text: #9ca3af;\n --ri-panel-surface: #f9fafb;\n --ri-panel-surface-hover: #f3f4f6;\n --ri-panel-surface-border: #e5e7eb;\n --ri-panel-button-text: #1f2937;\n --ri-panel-accent: #2563eb;\n --ri-panel-accent-contrast: #ffffff;\n --ri-license-overlay-bg: rgba(0, 0, 0, 0.04);\n --ri-license-overlay-border: rgba(0, 0, 0, 0.08);\n --ri-license-overlay-text: #888;\n --ri-license-overlay-error-bg: rgba(192, 57, 43, 0.06);\n --ri-license-overlay-error-border: rgba(192, 57, 43, 0.2);\n --ri-license-overlay-error-text: #c0392b;\n --ri-sidepanel-font-family:\n Inter,\n "Segoe UI",\n Helvetica,\n Arial,\n sans-serif;\n --ri-sidepanel-bg: #141824;\n --ri-sidepanel-open-btn-bg: rgba(20, 20, 20, 0.82);\n --ri-sidepanel-open-btn-bg-hover: #27282b7e;\n --ri-sidepanel-border: rgba(255, 255, 255, 0.06);\n --ri-sidepanel-divider: rgba(255, 255, 255, 0.04);\n --ri-sidepanel-border-strong: rgba(255, 255, 255, 0.08);\n --ri-sidepanel-border-active: rgba(255, 255, 255, 0.18);\n --ri-sidepanel-shadow-left: 4px 0 24px rgba(0, 0, 0, 0.35);\n --ri-sidepanel-shadow-right: -4px 0 24px rgba(0, 0, 0, 0.35);\n --ri-sidepanel-text: #f1f5f9;\n --ri-sidepanel-text-emphasis: #ffffff;\n --ri-sidepanel-text-muted: #94a3b8;\n --ri-sidepanel-text-subtle: #64748b;\n --ri-sidepanel-placeholder: #475569;\n --ri-sidepanel-surface: rgba(255, 255, 255, 0.05);\n --ri-sidepanel-surface-hover: rgba(255, 255, 255, 0.1);\n --ri-sidepanel-accent: #3b82f6;\n --ri-sidepanel-accent-soft: rgba(59, 130, 246, 0.12);\n --ri-databinding-bg: #111318;\n --ri-databinding-border: rgba(255, 255, 255, 0.06);\n --ri-databinding-border-strong: rgba(255, 255, 255, 0.08);\n --ri-databinding-border-hover: rgba(255, 255, 255, 0.15);\n --ri-databinding-shadow: 4px 0 24px rgba(0, 0, 0, 0.35);\n --ri-databinding-font-family:\n "Inter",\n "Segoe UI",\n sans-serif;\n --ri-databinding-mono-font-family:\n "JetBrains Mono",\n "Fira Code",\n "Menlo",\n monospace;\n --ri-databinding-text: #f1f5f9;\n --ri-databinding-text-muted: #94a3b8;\n --ri-databinding-text-subtle: #64748b;\n --ri-databinding-text-faint: #475569;\n --ri-databinding-text-hover: #cbd5e1;\n --ri-databinding-surface: rgba(255, 255, 255, 0.03);\n --ri-databinding-surface-hover: rgba(255, 255, 255, 0.06);\n --ri-databinding-accent: #93c5fd;\n --ri-databinding-accent-glow: rgba(147, 197, 253, 0.8);\n --ri-databinding-accent-border: rgba(96, 165, 250, 0.55);\n --ri-databinding-accent-gradient:\n linear-gradient(\n \n 135deg,\n #1e3a8a 0%,\n #1d4ed8 60%,\n #2563eb 100% );\n --ri-databinding-accent-gradient-active:\n linear-gradient(\n \n 135deg,\n #1e3a8a 0%,\n #1e40af 100% );\n display: flex;\n flex-direction: row;\n width: 100%;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n background: var(--ri-viewer-bg);\n position: relative;\n color: var(--ri-viewer-text);\n font-family: var(--ri-font-family);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n font-synthesis: none;\n}\n.ri-viewer * {\n box-sizing: border-box;\n}\n.ri-viewerLeft {\n display: flex;\n flex: 1;\n min-height: 0;\n min-width: 0;\n position: relative;\n}\n.ri-viewerRight {\n display: flex;\n flex-shrink: 0;\n min-width: 0;\n}\n.ri-panel {\n width: 280px;\n min-height: 0;\n background: var(--ri-panel-bg);\n border-right: 1px solid var(--ri-panel-border);\n display: flex;\n flex-direction: column;\n padding: 20px;\n overflow-y: auto;\n flex-shrink: 0;\n transition: margin-left 0.3s ease, transform 0.3s ease;\n}\n.ri-panel--open {\n transform: translateX(0);\n margin-left: 0;\n}\n.ri-panel--closed {\n transform: translateX(-100%);\n margin-left: -280px;\n}\n.ri-panelHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n}\n.ri-panelTitle {\n margin: 0;\n font-size: 15px;\n font-weight: 700;\n color: var(--ri-panel-title);\n line-height: 1.4;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ri-closeButton {\n border: 0;\n background: transparent;\n color: var(--ri-panel-subtle-text);\n font-size: 22px;\n line-height: 1;\n padding: 0;\n cursor: pointer;\n flex-shrink: 0;\n transition: color 0.2s ease;\n}\n.ri-closeButton:hover {\n color: var(--ri-panel-muted-text);\n}\n.ri-json {\n margin: 0 0 16px;\n padding: 12px;\n background: var(--ri-panel-surface);\n border: 1px solid var(--ri-panel-surface-border);\n border-radius: 12px;\n font-size: 12px;\n line-height: 1.55;\n color: var(--ri-panel-button-text);\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n.ri-divider {\n border-top: 1px solid var(--ri-panel-border);\n margin-bottom: 12px;\n}\n.ri-sectionLabel {\n margin-bottom: 8px;\n font-size: 11px;\n font-weight: 700;\n color: var(--ri-panel-subtle-text);\n text-transform: uppercase;\n letter-spacing: 0.16em;\n}\n.ri-actionList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.ri-actionButton {\n width: 100%;\n border-radius: 8px;\n border: 1px solid var(--ri-panel-surface-border);\n background: var(--ri-panel-surface);\n color: var(--ri-panel-button-text);\n padding: 10px 12px;\n text-align: left;\n font-size: 14px;\n line-height: 1.4;\n cursor: pointer;\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease,\n color 0.2s ease;\n}\n.ri-actionButton:hover {\n background: var(--ri-panel-surface-hover);\n border-color: var(--ri-panel-border);\n}\n.ri-actionButton--active {\n background: var(--ri-panel-accent);\n border-color: var(--ri-panel-accent);\n color: var(--ri-panel-accent-contrast);\n}\n.ri-actionButton--active:hover {\n background: var(--ri-panel-accent);\n border-color: var(--ri-panel-accent);\n}\n.ri-canvasArea {\n flex: 1 1 auto;\n position: relative;\n min-width: 0;\n}\n.ri-canvasArea--measuring {\n cursor: crosshair;\n}\n.ri-canvasArea canvas {\n opacity: 1;\n transition: opacity 0.18s ease;\n}\n.ri-canvasArea--positioning canvas {\n opacity: 0;\n transition: none;\n}\n.ri-bindingsMismatchBanner {\n position: absolute;\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 20;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 12px 7px 10px;\n border-radius: 8px;\n background: rgba(30, 20, 0, 0.88);\n border: 1px solid rgba(251, 191, 36, 0.35);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n color: rgb(251, 191, 36);\n font-size: 12px;\n font-weight: 500;\n line-height: 1.4;\n white-space: nowrap;\n pointer-events: auto;\n max-width: calc(100% - 32px);\n white-space: normal;\n text-align: center;\n}\n.ri-bindingsMismatchBanner__icon {\n flex-shrink: 0;\n}\n.ri-bindingsMismatchBanner__dismiss {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: 4px;\n padding: 2px;\n background: none;\n border: none;\n border-radius: 4px;\n color: rgba(251, 191, 36, 0.7);\n cursor: pointer;\n transition: color 0.15s ease, background 0.15s ease;\n}\n.ri-bindingsMismatchBanner__dismiss:hover {\n color: rgb(251, 191, 36);\n background: rgba(251, 191, 36, 0.12);\n}\n.ri-measureTools {\n position: absolute;\n top: 16px;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-measureButton {\n width: 34px;\n height: 34px;\n padding: 0;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.75);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n touch-action: manipulation;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n transition:\n background 0.15s ease,\n color 0.15s ease,\n border-color 0.15s ease;\n}\n.ri-measureButton:hover {\n background: rgba(40, 40, 40, 0.92);\n color: #fff;\n border-color: rgba(255, 255, 255, 0.25);\n}\n.ri-measureButton:active {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-measureButton--active {\n background: #22d3ee;\n border-color: #22d3ee;\n color: #06343c;\n}\n.ri-measureButton--active:hover {\n background: #38dbf0;\n color: #06343c;\n}\n.ri-measureHint {\n padding: 6px 10px;\n border-radius: 8px;\n font-size: 12px;\n line-height: 1;\n color: #fff;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n white-space: nowrap;\n}\n.ri-explodeTools {\n position: absolute;\n top: 16px;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-explodeSlider {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 34px;\n padding: 0 12px;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 8px;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n}\n.ri-explodeSlider input[type=range] {\n width: 120px;\n accent-color: #22d3ee;\n cursor: pointer;\n}\n.ri-cinematicTools {\n position: absolute;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-measureDot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #22d3ee;\n border: 2px solid #fff;\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);\n pointer-events: none;\n}\n.ri-measureLabel {\n padding: 3px 7px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n white-space: nowrap;\n color: #06343c;\n background: #22d3ee;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);\n pointer-events: none;\n user-select: none;\n}\n.ri-xrTools {\n position: absolute;\n left: 16px;\n z-index: 10;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.ri-xrButton {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 34px;\n padding: 0 10px;\n font-size: 13px;\n font-weight: 500;\n color: #fff;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.16);\n border-radius: 8px;\n cursor: pointer;\n touch-action: manipulation;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n.ri-xrButton:hover {\n background: rgba(40, 40, 40, 0.92);\n border-color: rgba(255, 255, 255, 0.3);\n}\n.ri-arHintOverlay {\n position: absolute;\n top: 18px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n width: min(calc(100% - 32px), 360px);\n pointer-events: none;\n}\n.ri-arHint {\n margin: 0 auto;\n width: fit-content;\n max-width: 100%;\n padding: 6px 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1.2;\n text-align: center;\n color: rgba(255, 255, 255, 0.92);\n background: rgba(20, 20, 20, 0.58);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 999px;\n user-select: none;\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n.ri-arOverlay {\n position: absolute;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n width: min(calc(100% - 32px), 420px);\n pointer-events: none;\n}\n.ri-arControls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n}\n.ri-arStatus,\n.ri-arActionButton {\n max-width: 100%;\n padding: 8px 16px;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n text-align: center;\n white-space: nowrap;\n color: #fff;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.16);\n border-radius: 19px;\n user-select: none;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n}\n.ri-arStatus {\n pointer-events: none;\n}\n.ri-arActionButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n cursor: pointer;\n pointer-events: auto;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n transition:\n background 0.15s ease,\n border-color 0.15s ease,\n color 0.15s ease,\n transform 0.15s ease;\n}\n.ri-arActionButton svg {\n flex-shrink: 0;\n}\n.ri-arActionButton:hover {\n background: rgba(40, 40, 40, 0.92);\n border-color: rgba(255, 255, 255, 0.3);\n}\n.ri-arActionButton:active {\n transform: scale(0.98);\n}\n.ri-arActionButton--primary {\n color: #06343c;\n background: #22d3ee;\n border-color: transparent;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);\n}\n.ri-arActionButton--primary:hover {\n background: #67e8f9;\n border-color: transparent;\n}\n.ri-arActionButton.ri-arActionButton--active,\n.ri-arActionButton[aria-pressed=true],\n.ri-arActionButton.ri-arActionButton--active:hover,\n.ri-arActionButton[aria-pressed=true]:hover,\n.ri-arActionButton.ri-arActionButton--active:active,\n.ri-arActionButton[aria-pressed=true]:active {\n color: #06343c;\n background: #22d3ee;\n border-color: transparent;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);\n}\n.ri-hiddenInput {\n display: none;\n}\n.ri-popover {\n position: absolute;\n z-index: 50;\n background: #ffffff;\n border: 1px solid #e5e7eb;\n border-radius: 16px;\n box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18);\n color: #111827;\n}\n.ri-popover--inline {\n position: static;\n z-index: auto;\n width: 100%;\n border-radius: 10px;\n box-shadow: none;\n}\n.ri-popover--inline .react-colorful {\n width: 100%;\n}\n.ri-popover--inline {\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n color: var(--ri-databinding-text, #f1f5f9);\n}\n.ri-popover--inline .ri-popoverHeader {\n border-bottom-color: var( --ri-databinding-border-strong, rgba(255, 255, 255, 0.08) );\n}\n.ri-popover--inline .ri-popoverLabel {\n color: var(--ri-databinding-text-muted, #94a3b8);\n}\n.ri-popover--inline .ri-colorCode {\n color: var(--ri-databinding-text-muted, #94a3b8);\n}\n.ri-popover--inline .ri-secondaryButton {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n color: var(--ri-databinding-text, #f1f5f9);\n}\n.ri-popover--inline .ri-secondaryButton:hover {\n background: rgba(255, 255, 255, 0.12);\n}\n.ri-popover--inline .ri-previewFrame {\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.ri-popover--inline .ri-emptyState {\n border-color: var(--ri-databinding-border-hover, rgba(255, 255, 255, 0.15));\n color: var(--ri-databinding-text-subtle, #64748b);\n}\n.ri-popover--inline .ri-uploadButton {\n background: var(--ri-databinding-accent-gradient, #2563eb);\n color: #ffffff;\n}\n.ri-popover--inline .ri-uploadButton:hover {\n background: var(--ri-databinding-accent-gradient-active, #1d4ed8);\n}\n.ri-popover--inline .ri-removeButton {\n background: transparent;\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n color: var(--ri-databinding-text-muted, #94a3b8);\n}\n.ri-popover--inline .ri-removeButton:hover {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n}\n.ri-popover--inline .ri-formatHint {\n color: var(--ri-databinding-text-subtle, #64748b);\n}\n.ri-popoverHeader {\n padding: 12px 16px;\n}\n.ri-popoverLabel {\n margin: 0 0 8px;\n font-size: 11px;\n font-weight: 700;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.16em;\n}\n.ri-inlineRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 8px;\n}\n.ri-colorCode {\n font-size: 12px;\n color: #9ca3af;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n text-transform: uppercase;\n}\n.ri-secondaryButton {\n border: 1px solid #e5e7eb;\n background: #f3f4f6;\n color: #374151;\n border-radius: 8px;\n padding: 6px 10px;\n font-size: 12px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.ri-secondaryButton:hover {\n background: #e5e7eb;\n}\n.ri-materialBody {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding-left: 12px;\n padding-right: 12px;\n padding-bottom: 12px;\n}\n.ri-previewFrame {\n position: relative;\n height: 112px;\n border-radius: 12px;\n overflow: hidden;\n border: 1px solid #e5e7eb;\n}\n.ri-previewImage {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n.ri-previewCaption {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n padding: 4px 8px;\n color: #ffffff;\n font-size: 10px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ri-emptyState {\n height: 112px;\n border-radius: 12px;\n border: 2px dashed #e5e7eb;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 4px;\n color: #d1d5db;\n text-align: center;\n}\n.ri-uploadButton {\n width: 100%;\n border: 0;\n border-radius: 10px;\n background: #111827;\n color: #ffffff;\n padding: 10px 12px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.ri-uploadButton:hover {\n background: #374151;\n}\n.ri-removeButton {\n width: 100%;\n border-radius: 10px;\n border: 1px solid #e5e7eb;\n background: #ffffff;\n color: #6b7280;\n padding: 8px 12px;\n font-size: 12px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.ri-removeButton:hover {\n background: #f9fafb;\n}\n.ri-formatHint {\n margin: 0;\n text-align: center;\n font-size: 10px;\n color: #d1d5db;\n}\n.ri-buttonContainer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n gap: 8px;\n position: absolute;\n bottom: 12px;\n left: 12px;\n right: 12px;\n z-index: 10;\n}\n.ri-tourControls {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-shrink: 0;\n}\n.ri-rightControls {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-shrink: 0;\n margin-left: auto;\n}\n.ri-rightControls:only-child {\n margin-left: auto;\n}\n.ri-navButtonSingle,\n.ri-tourButton,\n.ri-resetButton,\n.ri-downloadButton {\n height: 34px;\n background: rgba(20, 20, 20, 0.82);\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.75);\n border-radius: 8px;\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n cursor: pointer;\n transition:\n background 0.15s ease,\n color 0.15s ease,\n border-color 0.15s ease,\n transform 0.15s ease;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n.ri-navButtonSingle:hover:not(:disabled),\n.ri-tourButton:hover:not(:disabled),\n.ri-resetButton:hover:not(:disabled) {\n background: rgba(40, 40, 40, 0.92);\n color: #fff;\n border-color: rgba(255, 255, 255, 0.25);\n}\n.ri-navButtonSingle:active:not(:disabled),\n.ri-tourButton:active:not(:disabled),\n.ri-resetButton:active:not(:disabled) {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-navButtonSingle:disabled,\n.ri-tourButton:disabled,\n.ri-resetButton:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.ri-navButtonSingle {\n padding: 0 16px;\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n}\n.ri-tourButton {\n padding: 0 12px;\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n.ri-tourButton svg {\n width: 15px;\n height: 15px;\n flex-shrink: 0;\n}\n.ri-tourButton--stop {\n border-color: rgba(255, 68, 68, 0.4);\n color: #ff6b6b;\n}\n.ri-tourButton--stop:hover:not(:disabled) {\n background: rgba(255, 68, 68, 0.15);\n border-color: rgba(255, 68, 68, 0.6);\n color: #ff6b6b;\n}\n.ri-tourButton--stop:active:not(:disabled) {\n background: #ff4444;\n color: #fff;\n border-color: #ff4444;\n}\n.ri-tourButton--next {\n border-color: rgba(56, 219, 240, 0.3);\n color: #38dbf0;\n}\n.ri-tourButton--next:hover:not(:disabled) {\n background: rgba(56, 219, 240, 0.12);\n border-color: rgba(56, 219, 240, 0.5);\n color: #38dbf0;\n}\n.ri-tourButton--next:active:not(:disabled) {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-resetButton {\n width: 34px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.ri-resetButton svg {\n width: 15px;\n height: 15px;\n pointer-events: none;\n flex-shrink: 0;\n}\n.ri-resetButton:focus-visible {\n outline: 2px solid rgba(255, 255, 255, 0.5);\n outline-offset: 2px;\n}\n.ri-downloadWrapper {\n position: relative;\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n}\n.ri-downloadButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 0 16px;\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n}\n.ri-downloadButton:hover:not(:disabled) {\n background: rgba(0, 0, 0, 0.72);\n border-color: rgba(255, 255, 255, 0.3);\n color: #fff;\n}\n.ri-downloadButton:active:not(:disabled) {\n background: #38dbf0;\n color: #06343c;\n border-color: #38dbf0;\n}\n.ri-downloadButton:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.ri-downloadButton__spinner {\n display: inline-block;\n width: 13px;\n height: 13px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: ri-spin 0.7s linear infinite;\n flex-shrink: 0;\n}\n.ri-downloadMenu {\n position: absolute;\n bottom: calc(100% + 6px);\n right: 0;\n min-width: 168px;\n background: rgba(20, 20, 20, 0.92);\n border: 1px solid rgba(255, 255, 255, 0.14);\n border-radius: 10px;\n overflow: hidden;\n z-index: 100;\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n animation: ri-menuReveal 0.12s ease;\n}\n@keyframes ri-menuReveal {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ri-downloadMenuItem {\n display: flex;\n align-items: center;\n gap: 9px;\n width: 100%;\n padding: 10px 14px;\n font-size: 13px;\n font-weight: 400;\n color: #fff;\n background: transparent;\n border: none;\n cursor: pointer;\n text-align: left;\n transition: background 0.1s ease;\n}\n.ri-downloadMenuItem:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.1);\n}\n.ri-downloadMenuItem:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.ri-downloadMenuDivider {\n height: 1px;\n background: rgba(255, 255, 255, 0.1);\n margin: 0 10px;\n}\n@keyframes ri-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.ri-annotationMarker {\n position: relative;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: rgba(20, 20, 20, 0.82);\n border: 2px solid rgba(255, 255, 255, 0.9);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n font-weight: 700;\n cursor: pointer;\n z-index: 20;\n user-select: none;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);\n pointer-events: auto;\n transition: opacity 0.3s ease, transform 0.3s ease;\n}\n.ri-annotationMarker:hover {\n transform: scale(1.08);\n box-shadow: 0 12px 28px rgba(15, 23, 42, 0.18);\n background: rgba(40, 40, 40, 0.92);\n}\n.ri-annotationPopup {\n position: absolute;\n width: min(270px, calc(100vw - 32px));\n background: rgba(20, 20, 20, 0.85);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 16px;\n padding: 16px;\n z-index: 30;\n display: flex;\n flex-direction: column;\n gap: 12px;\n box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n}\n.ri-annotationInput,\n.ri-annotationTextarea {\n width: 100%;\n border: 1px solid rgba(255, 255, 255, 0.12);\n background: rgba(255, 255, 255, 0.05);\n color: #e5e7eb;\n border-radius: 10px;\n padding: 10px 12px;\n outline: none;\n font-family: inherit;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n}\n.ri-annotationInput {\n font-size: 14px;\n font-weight: 500;\n}\n.ri-annotationTextarea {\n font-size: 13px;\n resize: vertical;\n min-height: 110px;\n}\n.ri-annotationInput:focus,\n.ri-annotationTextarea:focus {\n border-color: #38dbf0;\n box-shadow: 0 0 0 3px rgba(56, 219, 240, 0.12);\n}\n.ri-annotationActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.ri-annotationOkBtn {\n border: 0;\n border-radius: 8px;\n background: rgba(56, 219, 240, 0.8);\n color: #06343c;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.2s ease, opacity 0.2s ease;\n}\n.ri-annotationOkBtn:hover:not(:disabled) {\n background: #38dbf0;\n}\n.ri-annotationOkBtn:disabled,\n.ri-annotationOkBtn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ri-annotationCancelBtn {\n border: 1px solid rgba(255, 255, 255, 0.12);\n background: transparent;\n color: #9ca3af;\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 13px;\n cursor: pointer;\n transition: background-color 0.2s ease, border-color 0.2s ease;\n}\n.ri-annotationCancelBtn:hover {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.2);\n}\n.ri-annotationIcons {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 12px;\n color: #9ca3af;\n}\n.ri-annotationIcons svg {\n flex-shrink: 0;\n}\n.ri-viewAnnotationPopup {\n position: relative;\n background: rgba(20, 20, 20, 0.85);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 8px;\n padding: 12px 16px;\n min-width: 200px;\n max-width: min(280px, calc(100vw - 48px));\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);\n pointer-events: auto;\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n animation: ri-viewAnnotationFadeIn 0.15s ease-out;\n margin-left: 24px;\n margin-top: -20px;\n isolation: isolate;\n z-index: 1000;\n}\n.ri-viewAnnotationHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n.ri-viewAnnotationTitle {\n margin: 0;\n color: #e2e8f0;\n font-size: 14px;\n font-weight: 600;\n}\n.ri-viewAnnotationClose {\n background: transparent;\n border: none;\n color: #b7bdc6;\n cursor: pointer;\n font-size: 18px;\n padding: 0 4px;\n transition: color 0.2s;\n line-height: 1;\n}\n.ri-viewAnnotationClose:hover {\n color: #e2e8f0;\n}\n.ri-viewAnnotationDescription {\n margin: 0;\n color: #cbd5e1;\n font-size: 13px;\n line-height: 1.4;\n word-wrap: break-word;\n}\n@keyframes ri-viewAnnotationFadeIn {\n from {\n opacity: 0;\n transform: translateY(-6px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ri-annotationNavSingle {\n position: absolute;\n bottom: 120px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n pointer-events: none;\n}\n.ri-annotationNavSingle > * {\n pointer-events: auto;\n}\n.ri-navBadge {\n background: rgba(255, 255, 255, 0.1);\n padding: 2px 10px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 400;\n color: rgba(255, 255, 255, 0.7);\n}\n.ri-annotationTitleHint {\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: white;\n padding: 8px 20px;\n border-radius: 8px;\n font-size: 13px;\n border: 1px solid rgba(255, 255, 255, 0.08);\n text-align: center;\n max-width: 350px;\n animation: slideUp 0.3s ease;\n}\n.ri-annotationHintTitle {\n font-weight: 600;\n color: #e5e7eb;\n}\n.ri-annotationHintDesc {\n font-size: 12px;\n opacity: 0.6;\n margin-top: 2px;\n color: #d1d5db;\n}\n@keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@media (max-width: 768px) {\n .ri-xrTools {\n gap: 6px;\n }\n .ri-xrButton {\n height: 34px;\n gap: 6px;\n padding: 0 8px;\n font-size: 11px;\n }\n .ri-xrButton svg {\n width: 14px;\n height: 14px;\n }\n .ri-xrButtonPrefix {\n display: none;\n }\n .ri-annotationNavSingle {\n bottom: 100px;\n }\n .ri-navButtonSingle {\n padding: 8px 20px;\n font-size: 13px;\n min-width: 110px;\n }\n .ri-annotationTitleHint {\n padding: 6px 14px;\n font-size: 12px;\n max-width: 250px;\n }\n .ri-viewAnnotationPopup {\n min-width: 160px;\n max-width: 220px;\n padding: 10px 12px;\n }\n .ri-viewAnnotationTitle {\n font-size: 13px;\n }\n .ri-viewAnnotationDescription {\n font-size: 12px;\n }\n .ri-buttonContainer {\n flex-wrap: wrap;\n gap: 6px;\n }\n .ri-tourControls {\n flex-wrap: wrap;\n }\n .ri-rightControls {\n flex-wrap: wrap;\n }\n}\n@media (max-width: 480px) {\n .ri-xrTools {\n gap: 5px;\n }\n .ri-xrButton {\n height: 34px;\n gap: 5px;\n font-size: 10px;\n }\n .ri-xrButton svg {\n width: 13px;\n height: 13px;\n }\n .ri-annotationNavSingle {\n bottom: 80px;\n }\n .ri-navButtonSingle {\n padding: 6px 16px;\n font-size: 12px;\n min-width: 90px;\n gap: 6px;\n }\n .ri-annotationTitleHint {\n padding: 4px 10px;\n font-size: 11px;\n max-width: 200px;\n }\n .ri-navBadge {\n font-size: 10px;\n padding: 1px 6px;\n }\n .ri-tourButton {\n padding: 0 8px;\n font-size: 12px;\n }\n .ri-tourButton span {\n display: none;\n }\n .ri-downloadButton {\n padding: 0 10px;\n font-size: 12px;\n }\n .ri-downloadButton span {\n display: none;\n }\n}\n.ri-canvasArea .bb-loadingOverlay {\n position: absolute;\n inset: 0;\n z-index: 12;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n padding: 24px;\n text-align: center;\n border-radius: 14px;\n background: rgba(15, 23, 42, 0.46);\n backdrop-filter: blur(1px);\n}\n.ri-canvasArea .bb-loadingSpinner {\n width: 40px;\n height: 40px;\n border-radius: 999px;\n border: 3px solid rgba(226, 232, 240, 0.24);\n border-top-color: #93c5fd;\n animation: bb-spin 0.8s linear infinite;\n}\n.ri-canvasArea .bb-loadingMessage {\n max-width: 320px;\n color: #f7f8f9;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.5;\n}\n@keyframes bb-spin {\n to {\n transform: rotate(360deg);\n }\n}\n');
46
46
 
47
47
  // src/components/LicenseOverlay.tsx
48
48
  import { AlertTriangle } from "lucide-react";
@@ -4584,13 +4584,14 @@ var ColorPicker = ({
4584
4584
  colorPicker,
4585
4585
  onClose,
4586
4586
  itemMaterials,
4587
- setItemMaterials
4587
+ setItemMaterials,
4588
+ inline = false
4588
4589
  }) => {
4589
4590
  return /* @__PURE__ */ jsxs9(
4590
4591
  "div",
4591
4592
  {
4592
- className: "ri-popover",
4593
- style: {
4593
+ className: `ri-popover${inline ? " ri-popover--inline" : ""}`,
4594
+ style: inline ? { padding: 12 } : {
4594
4595
  left: colorPicker.x,
4595
4596
  top: colorPicker.y,
4596
4597
  width: "min(225px, calc(100vw - 24px))",
@@ -4627,13 +4628,14 @@ var MaterialPicker = ({
4627
4628
  materialPopup,
4628
4629
  textureUrl,
4629
4630
  triggerFileUpload,
4630
- clearTexture
4631
+ clearTexture,
4632
+ inline = false
4631
4633
  }) => {
4632
4634
  return /* @__PURE__ */ jsxs10(
4633
4635
  "div",
4634
4636
  {
4635
- className: "ri-popover",
4636
- style: {
4637
+ className: `ri-popover${inline ? " ri-popover--inline" : ""}`,
4638
+ style: inline ? { overflow: "hidden" } : {
4637
4639
  left: materialPopup.x,
4638
4640
  top: materialPopup.y,
4639
4641
  width: "min(300px, calc(100vw - 24px))",
@@ -4696,19 +4698,74 @@ var MaterialPicker = ({
4696
4698
  };
4697
4699
 
4698
4700
  // src/components/ModelViewer/ObjectBindingDataPanel.tsx
4699
- import { useEffect as useEffect13, useState as useState7 } from "react";
4701
+ import { Fragment as Fragment5, useEffect as useEffect13, useRef as useRef10, useState as useState7 } from "react";
4700
4702
 
4701
4703
  // src/styles/ObjectBindingDataPanel.css
4702
- styleInject('.left-panel {\n width: 280px;\n min-height: 0;\n background: var(--ri-databinding-bg, #111318);\n border-right: 1px solid var(--ri-databinding-border, rgba(255, 255, 255, 0.06));\n display: flex;\n flex-direction: column;\n padding: 24px 18px;\n overflow-y: auto;\n font-family: var( --ri-databinding-font-family, "Inter", "Segoe UI", sans-serif );\n flex-shrink: 0;\n transition: margin-left 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--ri-databinding-shadow, 4px 0 24px rgba(0, 0, 0, 0.35));\n}\n.left-panel--open {\n margin-left: 0;\n}\n.left-panel--closed {\n margin-left: -280px;\n}\n.left-panel::-webkit-scrollbar {\n width: 4px;\n}\n.left-panel::-webkit-scrollbar-track {\n background: transparent;\n}\n.left-panel::-webkit-scrollbar-thumb {\n background: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n border-radius: 4px;\n}\n.left-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n padding-bottom: 14px;\n border-bottom: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.left-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: var(--ri-databinding-text, #f1f5f9);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding-right: 8px;\n margin: 0;\n letter-spacing: 0.02em;\n}\n.left-panel__close-btn {\n width: 26px;\n height: 26px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n border-radius: 6px;\n color: var(--ri-databinding-text-subtle, #64748b);\n font-size: 13px;\n flex-shrink: 0;\n cursor: pointer;\n transition:\n background 0.15s ease,\n color 0.15s ease,\n border-color 0.15s ease;\n}\n.left-panel__close-btn:hover {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n color: var(--ri-databinding-text-hover, #cbd5e1);\n border-color: var(--ri-databinding-border-hover, rgba(255, 255, 255, 0.15));\n}\n.left-panel__data {\n padding: 12px 6px;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n border-radius: 10px;\n font-size: 11px;\n font-family: var( --ri-databinding-mono-font-family, "JetBrains Mono", "Fira Code", "Menlo", monospace );\n color: var(--ri-databinding-text-muted, #94a3b8);\n line-height: 1.7;\n overflow-x: auto;\n margin-bottom: 18px;\n}\n.left-panel__divider {\n border: none;\n border-top: 1px solid var(--ri-databinding-border, rgba(255, 255, 255, 0.06));\n margin-bottom: 16px;\n}\n.left-panel__actions-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--ri-databinding-text-faint, #475569);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n margin-bottom: 10px;\n}\n.left-panel__actions-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.left-panel__action-btn {\n position: relative;\n padding: 9px 14px;\n border-radius: 8px;\n text-align: left;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n overflow: hidden;\n border: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n color: var(--ri-databinding-text-muted, #94a3b8);\n letter-spacing: 0.01em;\n}\n.left-panel__action-btn:active {\n transform: scale(0.97);\n}\n.left-panel__action-btn--active::before {\n content: "";\n position: absolute;\n left: 0;\n top: 20%;\n bottom: 20%;\n width: 3px;\n background: var(--ri-databinding-accent, #93c5fd);\n border-radius: 0 3px 3px 0;\n box-shadow: 0 0 8px var(--ri-databinding-accent-glow, rgba(147, 197, 253, 0.8));\n}\n.left-panel__action-btn--active:hover {\n background: var( --ri-databinding-accent-gradient, linear-gradient(135deg, #1e3a8a 0%, #1d4ed8 60%, #2563eb 100%) );\n border-color: var(--ri-databinding-accent-border, rgba(96, 165, 250, 0.55));\n}\n.left-panel__action-btn--active:active {\n transform: scale(0.97);\n background: var( --ri-databinding-accent-gradient-active, linear-gradient(135deg, #1e3a8a 0%, #1e40af 100%) );\n}\n.left-panel__data {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-bottom: 18px;\n}\n.left-panel__data-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 10px;\n padding: 7px 10px;\n border-radius: 7px;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid transparent;\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n.left-panel__data-row:hover {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.left-panel__data-key {\n font-size: 11px;\n font-weight: 600;\n color: var(--ri-databinding-text-faint, #475569);\n text-transform: uppercase;\n letter-spacing: 0.07em;\n white-space: nowrap;\n flex-shrink: 0;\n}\n.left-panel__data-value {\n font-size: 12px;\n font-family: var( --ri-databinding-mono-font-family, "JetBrains Mono", "Fira Code", "Menlo", monospace );\n text-align: right;\n word-break: break-all;\n max-width: 150px;\n}\n@media (max-width: 900px) {\n .left-panel {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: min(280px, 85vw);\n z-index: 200;\n min-height: 0;\n margin-left: 0;\n transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .left-panel--open {\n margin-left: 0;\n transform: translateX(0);\n }\n .left-panel--closed {\n margin-left: 0;\n transform: translateX(-100%);\n }\n}\n');
4704
+ styleInject('.left-panel {\n width: 280px;\n min-height: 0;\n background: var(--ri-databinding-bg, #111318);\n border-right: 1px solid var(--ri-databinding-border, rgba(255, 255, 255, 0.06));\n display: flex;\n flex-direction: column;\n padding: 24px 18px;\n overflow-y: auto;\n font-family: var( --ri-databinding-font-family, "Inter", "Segoe UI", sans-serif );\n flex-shrink: 0;\n transition: margin-left 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--ri-databinding-shadow, 4px 0 24px rgba(0, 0, 0, 0.35));\n}\n.left-panel--open {\n margin-left: 0;\n}\n.left-panel--closed {\n margin-left: -280px;\n}\n.left-panel::-webkit-scrollbar {\n width: 4px;\n}\n.left-panel::-webkit-scrollbar-track {\n background: transparent;\n}\n.left-panel::-webkit-scrollbar-thumb {\n background: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n border-radius: 4px;\n}\n.left-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n padding-bottom: 14px;\n border-bottom: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.left-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: var(--ri-databinding-text, #f1f5f9);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding-right: 8px;\n margin: 0;\n letter-spacing: 0.02em;\n}\n.left-panel__close-btn {\n width: 26px;\n height: 26px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n border-radius: 6px;\n color: var(--ri-databinding-text-subtle, #64748b);\n font-size: 13px;\n flex-shrink: 0;\n cursor: pointer;\n transition:\n background 0.15s ease,\n color 0.15s ease,\n border-color 0.15s ease;\n}\n.left-panel__close-btn:hover {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n color: var(--ri-databinding-text-hover, #cbd5e1);\n border-color: var(--ri-databinding-border-hover, rgba(255, 255, 255, 0.15));\n}\n.left-panel__data {\n padding: 12px 6px;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n border-radius: 10px;\n font-size: 11px;\n font-family: var( --ri-databinding-mono-font-family, "JetBrains Mono", "Fira Code", "Menlo", monospace );\n color: var(--ri-databinding-text-muted, #94a3b8);\n line-height: 1.7;\n overflow-x: auto;\n margin-bottom: 18px;\n}\n.left-panel__divider {\n border: none;\n border-top: 1px solid var(--ri-databinding-border, rgba(255, 255, 255, 0.06));\n margin-bottom: 16px;\n}\n.left-panel__actions-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--ri-databinding-text-faint, #475569);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n margin-bottom: 10px;\n}\n.left-panel__actions-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.left-panel__action-extra {\n display: grid;\n grid-template-rows: 0fr;\n opacity: 0;\n margin-top: 0;\n transition:\n grid-template-rows 0.28s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease,\n margin-top 0.28s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.left-panel__action-extra--open {\n grid-template-rows: 1fr;\n opacity: 1;\n margin-top: 4px;\n}\n.left-panel__action-extra-inner {\n overflow: hidden;\n min-height: 0;\n}\n.left-panel__action-btn {\n position: relative;\n padding: 9px 14px;\n border-radius: 8px;\n text-align: left;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n overflow: hidden;\n border: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n color: var(--ri-databinding-text-muted, #94a3b8);\n letter-spacing: 0.01em;\n}\n.left-panel__action-btn:active {\n transform: scale(0.97);\n}\n.left-panel__action-btn--active::before {\n content: "";\n position: absolute;\n left: 0;\n top: 20%;\n bottom: 20%;\n width: 3px;\n background: var(--ri-databinding-accent, #93c5fd);\n border-radius: 0 3px 3px 0;\n box-shadow: 0 0 8px var(--ri-databinding-accent-glow, rgba(147, 197, 253, 0.8));\n}\n.left-panel__action-btn--active:hover {\n background: var( --ri-databinding-accent-gradient, linear-gradient(135deg, #1e3a8a 0%, #1d4ed8 60%, #2563eb 100%) );\n border-color: var(--ri-databinding-accent-border, rgba(96, 165, 250, 0.55));\n}\n.left-panel__action-btn--active:active {\n transform: scale(0.97);\n background: var( --ri-databinding-accent-gradient-active, linear-gradient(135deg, #1e3a8a 0%, #1e40af 100%) );\n}\n.left-panel__data {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-bottom: 18px;\n}\n.left-panel__data-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 10px;\n padding: 7px 10px;\n border-radius: 7px;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid transparent;\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n.left-panel__data-row:hover {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.left-panel__data-key {\n font-size: 11px;\n font-weight: 600;\n color: var(--ri-databinding-text-faint, #475569);\n text-transform: uppercase;\n letter-spacing: 0.07em;\n white-space: nowrap;\n flex-shrink: 0;\n}\n.left-panel__data-value {\n font-size: 12px;\n font-family: var( --ri-databinding-mono-font-family, "JetBrains Mono", "Fira Code", "Menlo", monospace );\n text-align: right;\n overflow-wrap: anywhere;\n word-break: break-word;\n min-width: 0;\n}\n.left-panel__data-group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 7px 10px;\n border-radius: 7px;\n background: var(--ri-databinding-surface, rgba(255, 255, 255, 0.03));\n border: 1px solid transparent;\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n.left-panel__data-group:hover {\n background: var(--ri-databinding-surface-hover, rgba(255, 255, 255, 0.06));\n border-color: var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.left-panel__data-children {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 4px;\n padding-left: 10px;\n border-left: 1px solid var(--ri-databinding-border-strong, rgba(255, 255, 255, 0.08));\n}\n.left-panel__data-children .left-panel__data-row,\n.left-panel__data-children .left-panel__data-group {\n padding: 3px 0;\n background: transparent;\n border-color: transparent;\n}\n.left-panel__data-children .left-panel__data-row:hover,\n.left-panel__data-children .left-panel__data-group:hover {\n background: transparent;\n}\n@media (max-width: 900px) {\n .left-panel {\n width: 50vw;\n }\n .left-panel--open {\n margin-left: 0;\n }\n .left-panel--closed {\n margin-left: -50vw;\n }\n .left-panel {\n padding: 18px 12px;\n }\n .left-panel__data-row {\n flex-direction: column;\n align-items: stretch;\n gap: 2px;\n padding: 6px 8px;\n }\n .left-panel__data-group {\n padding: 6px 8px;\n }\n .left-panel__data-value {\n text-align: left;\n font-size: 11.5px;\n }\n .left-panel__data-children {\n padding-left: 8px;\n }\n}\n');
4703
4705
 
4704
4706
  // src/components/ModelViewer/ObjectBindingDataPanel.tsx
4705
- import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4707
+ import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4708
+ function DataEntries({ entries }) {
4709
+ return /* @__PURE__ */ jsx15(Fragment6, { children: entries.map(([key, value]) => {
4710
+ const isObject = value !== null && typeof value === "object";
4711
+ const childEntries = isObject ? Object.entries(value) : [];
4712
+ if (isObject && childEntries.length > 0) {
4713
+ return /* @__PURE__ */ jsxs11("div", { className: "left-panel__data-group", children: [
4714
+ /* @__PURE__ */ jsx15("span", { className: "left-panel__data-key", children: key }),
4715
+ /* @__PURE__ */ jsx15("div", { className: "left-panel__data-children", children: /* @__PURE__ */ jsx15(DataEntries, { entries: childEntries }) })
4716
+ ] }, key);
4717
+ }
4718
+ return /* @__PURE__ */ jsxs11("div", { className: "left-panel__data-row", children: [
4719
+ /* @__PURE__ */ jsx15("span", { className: "left-panel__data-key", children: key }),
4720
+ /* @__PURE__ */ jsx15(
4721
+ "span",
4722
+ {
4723
+ className: `left-panel__data-value left-panel__data-value--${typeof value}`,
4724
+ children: isObject ? Array.isArray(value) ? "[]" : "{}" : String(value)
4725
+ }
4726
+ )
4727
+ ] }, key);
4728
+ }) });
4729
+ }
4730
+ function ActionExtra({ content }) {
4731
+ const hasContent = content != null;
4732
+ const [mounted, setMounted] = useState7(hasContent);
4733
+ const [expanded, setExpanded] = useState7(hasContent);
4734
+ const cachedRef = useRef10(content);
4735
+ if (hasContent) cachedRef.current = content;
4736
+ useEffect13(() => {
4737
+ if (hasContent) {
4738
+ setMounted(true);
4739
+ return;
4740
+ }
4741
+ if (mounted) {
4742
+ setExpanded(false);
4743
+ const timer = setTimeout(() => setMounted(false), 300);
4744
+ return () => clearTimeout(timer);
4745
+ }
4746
+ }, [hasContent, mounted]);
4747
+ useEffect13(() => {
4748
+ if (mounted && hasContent) {
4749
+ const frame = requestAnimationFrame(() => setExpanded(true));
4750
+ return () => cancelAnimationFrame(frame);
4751
+ }
4752
+ }, [mounted, hasContent]);
4753
+ if (!mounted) return null;
4754
+ return /* @__PURE__ */ jsx15(
4755
+ "div",
4756
+ {
4757
+ className: `left-panel__action-extra${expanded ? " left-panel__action-extra--open" : ""}`,
4758
+ children: /* @__PURE__ */ jsx15("div", { className: "left-panel__action-extra-inner", children: content ?? cachedRef.current })
4759
+ }
4760
+ );
4761
+ }
4706
4762
  function ObjectBindingDataPanel({
4707
4763
  isOpen,
4708
4764
  selectedObject,
4709
4765
  currentAction,
4710
4766
  onClose,
4711
- onAction
4767
+ onAction,
4768
+ renderActionExtra
4712
4769
  }) {
4713
4770
  const [displayedObject, setDisplayedObject] = useState7(selectedObject);
4714
4771
  useEffect13(() => {
@@ -4720,7 +4777,7 @@ function ObjectBindingDataPanel({
4720
4777
  "div",
4721
4778
  {
4722
4779
  className: `left-panel ${isOpen ? "left-panel--open" : "left-panel--closed"}`,
4723
- children: objectToRender && /* @__PURE__ */ jsxs11(Fragment5, { children: [
4780
+ children: objectToRender && /* @__PURE__ */ jsxs11(Fragment6, { children: [
4724
4781
  /* @__PURE__ */ jsxs11("div", { className: "left-panel__header", children: [
4725
4782
  /* @__PURE__ */ jsx15("p", { className: "left-panel__title", children: objectToRender.label }),
4726
4783
  /* @__PURE__ */ jsx15(
@@ -4733,42 +4790,36 @@ function ObjectBindingDataPanel({
4733
4790
  }
4734
4791
  )
4735
4792
  ] }),
4736
- dataEntries.length > 0 && /* @__PURE__ */ jsx15("div", { className: "left-panel__data", children: dataEntries.map(([key, value]) => /* @__PURE__ */ jsxs11("div", { className: "left-panel__data-row", children: [
4737
- /* @__PURE__ */ jsx15("span", { className: "left-panel__data-key", children: key }),
4738
- /* @__PURE__ */ jsx15(
4739
- "span",
4740
- {
4741
- className: `left-panel__data-value left-panel__data-value--${typeof value}`,
4742
- children: typeof value === "object" ? JSON.stringify(value) : String(value)
4743
- }
4744
- )
4745
- ] }, key)) }),
4793
+ dataEntries.length > 0 && /* @__PURE__ */ jsx15("div", { className: "left-panel__data", children: /* @__PURE__ */ jsx15(DataEntries, { entries: dataEntries }) }),
4746
4794
  /* @__PURE__ */ jsx15("hr", { className: "left-panel__divider" }),
4747
- objectToRender.actions && objectToRender.actions.length > 0 && /* @__PURE__ */ jsxs11(Fragment5, { children: [
4795
+ objectToRender.actions && objectToRender.actions.length > 0 && /* @__PURE__ */ jsxs11(Fragment6, { children: [
4748
4796
  /* @__PURE__ */ jsx15("div", { className: "left-panel__actions-label", children: "Actions" }),
4749
4797
  /* @__PURE__ */ jsx15("div", { className: "left-panel__actions-list", children: objectToRender.actions.map((action) => {
4750
4798
  const isActive = currentAction?.action.id === action.id && (currentAction.binding === objectToRender || currentAction.binding?.id === objectToRender.id || currentAction.binding?.modelObjectId === objectToRender.modelObjectId || currentAction.objectId === objectToRender.id || currentAction.objectId === objectToRender.modelObjectId);
4751
- return /* @__PURE__ */ jsx15(
4752
- "button",
4753
- {
4754
- onClick: (e) => onAction({
4755
- objectId: objectToRender.modelObjectId || objectToRender.id || "",
4756
- action,
4757
- binding: objectToRender,
4758
- screenX: e.clientX,
4759
- screenY: e.clientY
4760
- }),
4761
- className: [
4762
- "left-panel__action-btn",
4763
- `left-panel__action-btn--${action.id}`,
4764
- isActive ? "left-panel__action-btn--active" : ""
4765
- ].filter(Boolean).join(" "),
4766
- "data-action-id": action.id,
4767
- "data-label": action.label,
4768
- children: action.label
4769
- },
4770
- action.id
4771
- );
4799
+ const extra = renderActionExtra?.(action.id);
4800
+ return /* @__PURE__ */ jsxs11(Fragment5, { children: [
4801
+ /* @__PURE__ */ jsx15(
4802
+ "button",
4803
+ {
4804
+ onClick: (e) => onAction({
4805
+ objectId: objectToRender.modelObjectId || objectToRender.id || "",
4806
+ action,
4807
+ binding: objectToRender,
4808
+ screenX: e.clientX,
4809
+ screenY: e.clientY
4810
+ }),
4811
+ className: [
4812
+ "left-panel__action-btn",
4813
+ `left-panel__action-btn--${action.id}`,
4814
+ isActive ? "left-panel__action-btn--active" : ""
4815
+ ].filter(Boolean).join(" "),
4816
+ "data-action-id": action.id,
4817
+ "data-label": action.label,
4818
+ children: action.label
4819
+ }
4820
+ ),
4821
+ /* @__PURE__ */ jsx15(ActionExtra, { content: extra })
4822
+ ] }, action.id);
4772
4823
  }) })
4773
4824
  ] })
4774
4825
  ] })
@@ -4784,7 +4835,7 @@ import { Boxes } from "lucide-react";
4784
4835
  import { useState as useState8 } from "react";
4785
4836
 
4786
4837
  // src/styles/SceneObjectsPanel.css
4787
- styleInject('.ri-sidepanel-wrap {\n height: 100%;\n transition: width 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: visible;\n}\n.ri-sidepanel-wrap--open {\n width: 300px;\n flex-shrink: 0;\n}\n.ri-sidepanel-wrap--closed {\n width: 0;\n flex-shrink: 0;\n overflow: hidden;\n}\n.ri-sidepanel__open-btn {\n position: absolute;\n top: 12px;\n right: 12px;\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 7px 13px;\n border-radius: 7px;\n border: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-sidepanel-open-btn-bg, rgba(20, 20, 20, 0.82));\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--ri-sidepanel-text, #e2e8f0);\n z-index: 190;\n transition: background 0.15s;\n}\n.ri-sidepanel__open-btn:hover {\n background: var(--ri-sidepanel-open-btn-bg-hover, #27282b7e);\n}\n.ri-sidepanel {\n position: absolute;\n top: 0;\n right: 0;\n width: 300px;\n height: 100%;\n background: var(--ri-sidepanel-bg, #141824);\n display: flex;\n flex-direction: column;\n font-family: var( --ri-sidepanel-font-family, Inter, "Segoe UI", Helvetica, Arial, sans-serif );\n transform: translateX(100%);\n transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n z-index: 200;\n border-left: 1px solid var(--ri-sidepanel-border, rgba(255, 255, 255, 0.06));\n box-shadow: var(--ri-sidepanel-shadow-right, -4px 0 24px rgba(0, 0, 0, 0.35));\n}\n.ri-sidepanel--open {\n transform: translateX(0);\n}\n.ri-sidepanel--closed {\n transform: translateX(100%);\n}\n.ri-sidepanel__header {\n padding: 24px 20px 16px 20px;\n border-bottom: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n}\n.ri-sidepanel__header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n}\n.ri-sidepanel__eyebrow {\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.12em;\n color: var(--ri-sidepanel-text-subtle, #64748b);\n text-transform: uppercase;\n}\n.ri-sidepanel__title {\n font-size: 22px;\n font-weight: 700;\n color: var(--ri-sidepanel-text, #f1f5f9);\n margin: 0;\n line-height: 1.2;\n}\n.ri-sidepanel__close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border-radius: 8px;\n border: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-sidepanel-surface, rgba(255, 255, 255, 0.05));\n cursor: pointer;\n color: var(--ri-sidepanel-text-muted, #94a3b8);\n transition: background 0.15s, color 0.15s;\n flex-shrink: 0;\n}\n.ri-sidepanel__close-btn:hover {\n background: var(--ri-sidepanel-surface-hover, rgba(255, 255, 255, 0.1));\n color: var(--ri-sidepanel-text, #f1f5f9);\n}\n.ri-sidepanel__search-wrap {\n padding: 14px 16px;\n border-bottom: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n}\n.ri-sidepanel__search {\n width: 100%;\n padding: 10px 14px;\n border-radius: 10px;\n border: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-sidepanel-surface, rgba(255, 255, 255, 0.05));\n color: var(--ri-sidepanel-text, #e2e8f0);\n font-size: 13px;\n outline: none;\n box-sizing: border-box;\n transition: border-color 0.15s, background 0.15s;\n}\n.ri-sidepanel__search::placeholder {\n color: var(--ri-sidepanel-placeholder, #475569);\n}\n.ri-sidepanel__search:focus {\n border-color: var(--ri-sidepanel-border-active, rgba(255, 255, 255, 0.18));\n background: var(--ri-sidepanel-surface-hover, rgba(255, 255, 255, 0.08));\n}\n.ri-sidepanel__list {\n display: flex;\n flex-direction: column;\n padding: 10px 0;\n overflow-y: auto;\n flex: 1;\n}\n.ri-sidepanel__list::-webkit-scrollbar {\n width: 4px;\n}\n.ri-sidepanel__list::-webkit-scrollbar-track {\n background: transparent;\n}\n.ri-sidepanel__list::-webkit-scrollbar-thumb {\n background: var(--ri-sidepanel-surface-hover, rgba(255, 255, 255, 0.1));\n border-radius: 4px;\n}\n.ri-sidepanel__row {\n display: flex;\n justify-content: space-between;\n padding: 12px 20px;\n cursor: pointer;\n width: 100%;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n appearance: none;\n -webkit-appearance: none;\n transition: background 0.12s;\n border-bottom: 1px solid var(--ri-sidepanel-divider, rgba(255, 255, 255, 0.04));\n}\n.ri-sidepanel__row:hover,\n.ri-sidepanel__row--hovered {\n background: var(--ri-sidepanel-surface, rgba(255, 255, 255, 0.05));\n}\n.ri-sidepanel__row--selected {\n background: var(--ri-sidepanel-accent-soft, rgba(59, 130, 246, 0.12));\n}\n.ri-sidepanel__label {\n font-size: 14px;\n font-weight: 600;\n color: var(--ri-sidepanel-text, #e2e8f0);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ri-sidepanel__label--hovered {\n color: var(--ri-sidepanel-text-emphasis, #ffffff);\n}\n.ri-sidepanel__label--selected {\n color: var(--ri-sidepanel-text-emphasis, #ffffff);\n}\n.ri-sidepanel__meta {\n font-size: 12px;\n color: var(--ri-sidepanel-text-muted, #94a3b8);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ri-sidepanel__vis-btn {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n cursor: pointer;\n background: none;\n border: none;\n padding: 0;\n margin-left: 10px;\n}\n.ri-sidepanel__checkbox {\n width: 16px;\n height: 16px;\n border-radius: 4px;\n border: 1.5px solid var(--ri-sidepanel-border-active, rgba(255, 255, 255, 0.2));\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, border-color 0.15s;\n}\n.ri-sidepanel__checkbox--checked {\n background: var(--ri-sidepanel-accent, #3b82f6);\n border-color: var(--ri-sidepanel-accent, #3b82f6);\n}\n@media (max-width: 900px) {\n .ri-sidepanel-wrap--open {\n width: 0;\n }\n .ri-sidepanel {\n width: min(300px, 85vw);\n }\n}\n');
4838
+ styleInject('.ri-sidepanel-wrap {\n height: 100%;\n transition: width 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: visible;\n}\n.ri-sidepanel-wrap--open {\n width: 300px;\n flex-shrink: 0;\n}\n.ri-sidepanel-wrap--closed {\n width: 0;\n flex-shrink: 0;\n overflow: hidden;\n}\n.ri-sidepanel__open-btn {\n position: absolute;\n top: 12px;\n right: 12px;\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 7px 13px;\n border-radius: 7px;\n border: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-sidepanel-open-btn-bg, rgba(20, 20, 20, 0.82));\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--ri-sidepanel-text, #e2e8f0);\n z-index: 190;\n transition: background 0.15s;\n}\n.ri-sidepanel__open-btn:hover {\n background: var(--ri-sidepanel-open-btn-bg-hover, #27282b7e);\n}\n.ri-sidepanel {\n position: absolute;\n top: 0;\n right: 0;\n width: 300px;\n height: 100%;\n background: var(--ri-sidepanel-bg, #141824);\n display: flex;\n flex-direction: column;\n font-family: var( --ri-sidepanel-font-family, Inter, "Segoe UI", Helvetica, Arial, sans-serif );\n transform: translateX(100%);\n transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);\n z-index: 200;\n border-left: 1px solid var(--ri-sidepanel-border, rgba(255, 255, 255, 0.06));\n box-shadow: var(--ri-sidepanel-shadow-right, -4px 0 24px rgba(0, 0, 0, 0.35));\n}\n.ri-sidepanel--open {\n transform: translateX(0);\n}\n.ri-sidepanel--closed {\n transform: translateX(100%);\n}\n.ri-sidepanel__header {\n padding: 24px 20px 16px 20px;\n border-bottom: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n}\n.ri-sidepanel__header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n}\n.ri-sidepanel__eyebrow {\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.12em;\n color: var(--ri-sidepanel-text-subtle, #64748b);\n text-transform: uppercase;\n}\n.ri-sidepanel__title {\n font-size: 22px;\n font-weight: 700;\n color: var(--ri-sidepanel-text, #f1f5f9);\n margin: 0;\n line-height: 1.2;\n}\n.ri-sidepanel__close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border-radius: 8px;\n border: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-sidepanel-surface, rgba(255, 255, 255, 0.05));\n cursor: pointer;\n color: var(--ri-sidepanel-text-muted, #94a3b8);\n transition: background 0.15s, color 0.15s;\n flex-shrink: 0;\n}\n.ri-sidepanel__close-btn:hover {\n background: var(--ri-sidepanel-surface-hover, rgba(255, 255, 255, 0.1));\n color: var(--ri-sidepanel-text, #f1f5f9);\n}\n.ri-sidepanel__search-wrap {\n padding: 14px 16px;\n border-bottom: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n}\n.ri-sidepanel__search {\n width: 100%;\n padding: 10px 14px;\n border-radius: 10px;\n border: 1px solid var(--ri-sidepanel-border-strong, rgba(255, 255, 255, 0.08));\n background: var(--ri-sidepanel-surface, rgba(255, 255, 255, 0.05));\n color: var(--ri-sidepanel-text, #e2e8f0);\n font-size: 13px;\n outline: none;\n box-sizing: border-box;\n transition: border-color 0.15s, background 0.15s;\n}\n.ri-sidepanel__search::placeholder {\n color: var(--ri-sidepanel-placeholder, #475569);\n}\n.ri-sidepanel__search:focus {\n border-color: var(--ri-sidepanel-border-active, rgba(255, 255, 255, 0.18));\n background: var(--ri-sidepanel-surface-hover, rgba(255, 255, 255, 0.08));\n}\n.ri-sidepanel__list {\n display: flex;\n flex-direction: column;\n padding: 10px 0;\n overflow-y: auto;\n flex: 1;\n}\n.ri-sidepanel__list::-webkit-scrollbar {\n width: 4px;\n}\n.ri-sidepanel__list::-webkit-scrollbar-track {\n background: transparent;\n}\n.ri-sidepanel__list::-webkit-scrollbar-thumb {\n background: var(--ri-sidepanel-surface-hover, rgba(255, 255, 255, 0.1));\n border-radius: 4px;\n}\n.ri-sidepanel__row {\n display: flex;\n justify-content: space-between;\n padding: 12px 20px;\n cursor: pointer;\n width: 100%;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n appearance: none;\n -webkit-appearance: none;\n transition: background 0.12s;\n border-bottom: 1px solid var(--ri-sidepanel-divider, rgba(255, 255, 255, 0.04));\n}\n.ri-sidepanel__row:hover,\n.ri-sidepanel__row--hovered {\n background: var(--ri-sidepanel-surface, rgba(255, 255, 255, 0.05));\n}\n.ri-sidepanel__row--selected {\n background: var(--ri-sidepanel-accent-soft, rgba(59, 130, 246, 0.12));\n}\n.ri-sidepanel__label {\n font-size: 14px;\n font-weight: 600;\n color: var(--ri-sidepanel-text, #e2e8f0);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ri-sidepanel__label--hovered {\n color: var(--ri-sidepanel-text-emphasis, #ffffff);\n}\n.ri-sidepanel__label--selected {\n color: var(--ri-sidepanel-text-emphasis, #ffffff);\n}\n.ri-sidepanel__meta {\n font-size: 12px;\n color: var(--ri-sidepanel-text-muted, #94a3b8);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ri-sidepanel__vis-btn {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n cursor: pointer;\n background: none;\n border: none;\n padding: 0;\n margin-left: 10px;\n}\n.ri-sidepanel__checkbox {\n width: 16px;\n height: 16px;\n border-radius: 4px;\n border: 1.5px solid var(--ri-sidepanel-border-active, rgba(255, 255, 255, 0.2));\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, border-color 0.15s;\n}\n.ri-sidepanel__checkbox--checked {\n background: var(--ri-sidepanel-accent, #3b82f6);\n border-color: var(--ri-sidepanel-accent, #3b82f6);\n}\n@media (max-width: 900px) {\n .ri-sidepanel-wrap--open {\n width: 50vw;\n }\n .ri-sidepanel {\n width: 50vw;\n }\n}\n');
4788
4839
 
4789
4840
  // src/components/shared/SearchableSidePanel.tsx
4790
4841
  import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
@@ -5000,7 +5051,6 @@ import {
5000
5051
  Download,
5001
5052
  Eraser,
5002
5053
  MapPin,
5003
- Ruler,
5004
5054
  RotateCcw,
5005
5055
  ChevronLeft,
5006
5056
  Square,
@@ -5009,7 +5059,10 @@ import {
5009
5059
  X,
5010
5060
  Expand,
5011
5061
  Play,
5012
- Pause
5062
+ Pause,
5063
+ Smartphone,
5064
+ PencilRuler,
5065
+ RulerDimensionLine
5013
5066
  } from "lucide-react";
5014
5067
 
5015
5068
  // src/components/BindingBuilder/BindingBuilderContext.tsx
@@ -5053,7 +5106,7 @@ function consumeInitialAutoFitOverride(controls) {
5053
5106
  }
5054
5107
 
5055
5108
  // src/components/ModelViewer/ModelViewer.tsx
5056
- import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5109
+ import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5057
5110
  function findInfluencingBone(hit) {
5058
5111
  const mesh = hit.object;
5059
5112
  if (!mesh.isSkinnedMesh || !hit.face || !mesh.skeleton) return null;
@@ -5112,8 +5165,8 @@ function GuidedTourCameraFollow({
5112
5165
  offsetRef
5113
5166
  }) {
5114
5167
  const scene = useThree10((state) => state.scene);
5115
- const nodeRef = useRef10(null);
5116
- const hasPrev = useRef10(false);
5168
+ const nodeRef = useRef11(null);
5169
+ const hasPrev = useRef11(false);
5117
5170
  const live = useMemo13(() => new Vector37(), []);
5118
5171
  const prev = useMemo13(() => new Vector37(), []);
5119
5172
  const goal = useMemo13(() => new Vector37(), []);
@@ -5262,17 +5315,17 @@ function ModelViewer({
5262
5315
  () => shouldReduceGpuLoad(performanceProfile),
5263
5316
  [performanceProfile]
5264
5317
  );
5265
- const controlsRef = useRef10(null);
5318
+ const controlsRef = useRef11(null);
5266
5319
  useEffect14(() => {
5267
5320
  if (!controlsRef.current) return;
5268
5321
  controlsRef.current.dollySpeed = Math.max(zoomSensitivity, 0);
5269
5322
  }, [zoomSensitivity]);
5270
- const tourCameraOffsetRef = useRef10(null);
5271
- const annotationWorldPositionsRef = useRef10(/* @__PURE__ */ new Map());
5272
- const fileInputRef = useRef10(null);
5273
- const pendingObjectId = useRef10(null);
5274
- const rendererCaptureRef = useRef10(null);
5275
- const createdBlobUrls = useRef10({});
5323
+ const tourCameraOffsetRef = useRef11(null);
5324
+ const annotationWorldPositionsRef = useRef11(/* @__PURE__ */ new Map());
5325
+ const fileInputRef = useRef11(null);
5326
+ const pendingObjectId = useRef11(null);
5327
+ const rendererCaptureRef = useRef11(null);
5328
+ const createdBlobUrls = useRef11({});
5276
5329
  useEffect14(() => {
5277
5330
  return () => {
5278
5331
  for (const url of Object.values(createdBlobUrls.current)) {
@@ -5280,12 +5333,12 @@ function ModelViewer({
5280
5333
  }
5281
5334
  };
5282
5335
  }, []);
5283
- const nodeRefsMap = useRef10({});
5284
- const materialRefsOut = useRef10({});
5285
- const viewerLeftRef = useRef10(null);
5286
- const canvasAreaRef = useRef10(null);
5287
- const xrPresenterRef = useRef10(null);
5288
- const viewAnnotationPopupRef = useRef10(null);
5336
+ const nodeRefsMap = useRef11({});
5337
+ const materialRefsOut = useRef11({});
5338
+ const viewerLeftRef = useRef11(null);
5339
+ const canvasAreaRef = useRef11(null);
5340
+ const xrPresenterRef = useRef11(null);
5341
+ const viewAnnotationPopupRef = useRef11(null);
5289
5342
  const [internalObjectBindings, setInternalObjectBindings] = useState10(objectBindings);
5290
5343
  const [itemMaterials, setItemMaterials] = useState10({});
5291
5344
  const [currentAction, setCurrentAction] = useState10(
@@ -5299,12 +5352,12 @@ function ModelViewer({
5299
5352
  null
5300
5353
  );
5301
5354
  const [isDownloading, setIsDownloading] = useState10(false);
5302
- const sceneRef = useRef10(null);
5303
- const fitAttemptedRef = useRef10(false);
5304
- const fitInFlightRef = useRef10(false);
5305
- const cameraProvidedRef = useRef10(Boolean(camera));
5355
+ const sceneRef = useRef11(null);
5356
+ const fitAttemptedRef = useRef11(false);
5357
+ const fitInFlightRef = useRef11(false);
5358
+ const cameraProvidedRef = useRef11(Boolean(camera));
5306
5359
  cameraProvidedRef.current = Boolean(camera);
5307
- const initialCameraStateRef = useRef10(null);
5360
+ const initialCameraStateRef = useRef11(null);
5308
5361
  const [isAutoFraming, setIsAutoFraming] = useState10(Boolean(modelUrl));
5309
5362
  const [cameraPositioned, setCameraPositioned] = useState10(
5310
5363
  !modelUrl || Boolean(onAutoFit) || Boolean(camera)
@@ -5314,7 +5367,7 @@ function ModelViewer({
5314
5367
  const [modelLoadFailed, setModelLoadFailed] = useState10(false);
5315
5368
  const [bindingsMismatch, setBindingsMismatch] = useState10(false);
5316
5369
  const [mismatchDismissed, setMismatchDismissed] = useState10(false);
5317
- const currentObjectBindingsRef = useRef10({});
5370
+ const currentObjectBindingsRef = useRef11({});
5318
5371
  const captureInitialCameraState = useCallback4(() => {
5319
5372
  const controls = controlsRef.current;
5320
5373
  if (!controls || initialCameraStateRef.current) {
@@ -5332,10 +5385,10 @@ function ModelViewer({
5332
5385
  const [measurePoints, setMeasurePoints] = useState10([]);
5333
5386
  const [showDimensions, setShowDimensions] = useState10(false);
5334
5387
  const [measureBox, setMeasureBox] = useState10(null);
5335
- const measureModeRef = useRef10(false);
5388
+ const measureModeRef = useRef11(false);
5336
5389
  measureModeRef.current = measureMode;
5337
- const measurePointCounter = useRef10(0);
5338
- const measureDownRef = useRef10(null);
5390
+ const measurePointCounter = useRef11(0);
5391
+ const measureDownRef = useRef11(null);
5339
5392
  const [explodeFactor, setExplodeFactor] = useState10(0);
5340
5393
  const [explodeOpen, setExplodeOpen] = useState10(false);
5341
5394
  useEffect14(() => {
@@ -5358,7 +5411,7 @@ function ModelViewer({
5358
5411
  return { ...base ?? {}, ...cinematic };
5359
5412
  }, [cinematic, resolvedSceneConfig]);
5360
5413
  const [cinematicPlaying, setCinematicPlaying] = useState10(false);
5361
- const cinematicAutoStartedRef = useRef10(false);
5414
+ const cinematicAutoStartedRef = useRef11(false);
5362
5415
  useEffect14(() => {
5363
5416
  setCinematicPlaying(false);
5364
5417
  cinematicAutoStartedRef.current = false;
@@ -5453,7 +5506,7 @@ function ModelViewer({
5453
5506
  const arHintText = arOverlayState.isModelPlaced && !arOverlayState.isPlacementMode ? "Pinch to resize \xB7 Twist to rotate" : null;
5454
5507
  const arOverlayRoot = xrStore?.getState().domOverlayRoot ?? null;
5455
5508
  const arOverlay = inARSession && arOverlayRoot ? createPortal(
5456
- /* @__PURE__ */ jsxs15(Fragment6, { children: [
5509
+ /* @__PURE__ */ jsxs15(Fragment7, { children: [
5457
5510
  arHintText && /* @__PURE__ */ jsx19("div", { className: "ri-arHintOverlay", children: /* @__PURE__ */ jsx19("div", { className: "ri-arHint", children: arHintText }) }),
5458
5511
  /* @__PURE__ */ jsx19("div", { className: "ri-arOverlay", children: /* @__PURE__ */ jsxs15("div", { className: "ri-arControls", children: [
5459
5512
  arStatusText && /* @__PURE__ */ jsx19("div", { className: "ri-arStatus", children: arStatusText }),
@@ -5514,11 +5567,11 @@ function ModelViewer({
5514
5567
  title: "",
5515
5568
  description: ""
5516
5569
  });
5517
- const annotationCounterRef = useRef10(0);
5570
+ const annotationCounterRef = useRef11(0);
5518
5571
  const [internalViewingAnnotation, setInternalViewingAnnotation] = useState10(null);
5519
5572
  const [currentAnnotationIndex, setCurrentAnnotationIndex] = useState10(-1);
5520
5573
  const [isNavigating, setIsNavigating] = useState10(false);
5521
- const annotationSmoothRestoreTimeoutRef = useRef10(null);
5574
+ const annotationSmoothRestoreTimeoutRef = useRef11(null);
5522
5575
  const sortedAnnotations = useMemo13(() => {
5523
5576
  return [...annotations].sort((a, b) => a.id - b.id);
5524
5577
  }, [annotations]);
@@ -6078,7 +6131,7 @@ function ModelViewer({
6078
6131
  delete createdBlobUrls.current[targetKey];
6079
6132
  }
6080
6133
  };
6081
- const onViewerReadyRef = useRef10(onViewerReady);
6134
+ const onViewerReadyRef = useRef11(onViewerReady);
6082
6135
  onViewerReadyRef.current = onViewerReady;
6083
6136
  const notifyViewerReady = useCallback4(() => {
6084
6137
  const controls = controlsRef.current;
@@ -6582,6 +6635,8 @@ function ModelViewer({
6582
6635
  const pendingPopupX = pendingAnnotation ? Math.min(pendingAnnotation.screenX + 12, canvasW - popupW - 8) : 0;
6583
6636
  const pendingPopupY = pendingAnnotation ? Math.min(pendingAnnotation.screenY, canvasH - popupH - 8) : 0;
6584
6637
  const showModelLoader = showLoadingOverlay && Boolean(modelUrl) && !modelLoadFailed && (!modelLoaded || !cameraPositioned || isAutoFraming);
6638
+ const xrToolsVisible = enableXR && (xrStore && (arSupported || vrSupported) || quickLookSupported);
6639
+ const topLeftRow = (top) => 16 + top * 42;
6585
6640
  return /* @__PURE__ */ jsxs15("div", { className: "ri-viewer", style: { background: viewerBackdropColor }, children: [
6586
6641
  /* @__PURE__ */ jsxs15("div", { className: "ri-viewerLeft", ref: viewerLeftRef, children: [
6587
6642
  customObjectBindingDataPanel ? customObjectBindingDataPanel({
@@ -6597,7 +6652,34 @@ function ModelViewer({
6597
6652
  selectedObject: currentPanelObject,
6598
6653
  currentAction,
6599
6654
  onClose: handleClosePanel,
6600
- onAction: handleAction
6655
+ onAction: handleAction,
6656
+ renderActionExtra: (actionId) => {
6657
+ if (actionId === "change-color" && colorPicker) {
6658
+ return /* @__PURE__ */ jsx19(
6659
+ ColorPicker,
6660
+ {
6661
+ inline: true,
6662
+ colorPicker,
6663
+ onClose: closeColorPicker,
6664
+ itemMaterials,
6665
+ setItemMaterials
6666
+ }
6667
+ );
6668
+ }
6669
+ if (actionId === "change-material" && materialPopup) {
6670
+ return /* @__PURE__ */ jsx19(
6671
+ MaterialPicker,
6672
+ {
6673
+ inline: true,
6674
+ triggerFileUpload,
6675
+ materialPopup,
6676
+ textureUrl: materialTextureUrl,
6677
+ clearTexture
6678
+ }
6679
+ );
6680
+ }
6681
+ return null;
6682
+ }
6601
6683
  }
6602
6684
  ),
6603
6685
  /* @__PURE__ */ jsxs15(
@@ -6680,7 +6762,7 @@ function ModelViewer({
6680
6762
  {
6681
6763
  onLoadError: handleLoadErrorInternal,
6682
6764
  children: /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ (() => {
6683
- const modelContent = /* @__PURE__ */ jsxs15(Fragment6, { children: [
6765
+ const modelContent = /* @__PURE__ */ jsxs15(Fragment7, { children: [
6684
6766
  /* @__PURE__ */ jsx19(
6685
6767
  Model,
6686
6768
  {
@@ -6770,45 +6852,110 @@ function ModelViewer({
6770
6852
  message: "Loading model..."
6771
6853
  }
6772
6854
  ),
6773
- showMeasureTools && /* @__PURE__ */ jsxs15("div", { className: "ri-measureTools", children: [
6774
- /* @__PURE__ */ jsx19(
6775
- "button",
6776
- {
6777
- type: "button",
6778
- className: `ri-measureButton ${measureMode ? "ri-measureButton--active" : ""}`,
6779
- onClick: () => setMeasureMode((prev) => !prev),
6780
- title: measureMode ? "Stop measuring" : "Measure distance",
6781
- "aria-pressed": measureMode,
6782
- children: /* @__PURE__ */ jsx19(Ruler, { size: 16 })
6783
- }
6784
- ),
6785
- /* @__PURE__ */ jsx19(
6786
- "button",
6787
- {
6788
- type: "button",
6789
- className: `ri-measureButton ${showDimensions ? "ri-measureButton--active" : ""}`,
6790
- onClick: () => setShowDimensions((prev) => !prev),
6791
- title: "Toggle bounding dimensions",
6792
- "aria-pressed": showDimensions,
6793
- children: /* @__PURE__ */ jsx19(Box, { size: 16 })
6794
- }
6795
- ),
6796
- measurePoints.length > 0 && /* @__PURE__ */ jsx19(
6797
- "button",
6798
- {
6799
- type: "button",
6800
- className: "ri-measureButton",
6801
- onClick: clearMeasurements,
6802
- title: "Clear measurements",
6803
- children: /* @__PURE__ */ jsx19(Eraser, { size: 16 })
6804
- }
6805
- ),
6806
- measureMode && /* @__PURE__ */ jsx19("span", { className: "ri-measureHint", children: "Click points on the model to measure" })
6807
- ] }),
6855
+ xrToolsVisible && /* @__PURE__ */ jsxs15(
6856
+ "div",
6857
+ {
6858
+ className: "ri-xrTools",
6859
+ style: { top: `${topLeftRow(0)}px` },
6860
+ children: [
6861
+ !arSupported && quickLookSupported && /* @__PURE__ */ jsxs15(
6862
+ "button",
6863
+ {
6864
+ type: "button",
6865
+ className: "ri-xrButton",
6866
+ onClick: openQuickLook,
6867
+ title: "View this model in AR with Apple Quick Look",
6868
+ children: [
6869
+ /* @__PURE__ */ jsx19(Box, { size: 16 }),
6870
+ "View in AR"
6871
+ ]
6872
+ }
6873
+ ),
6874
+ xrStore && arSupported && /* @__PURE__ */ jsxs15(
6875
+ "button",
6876
+ {
6877
+ type: "button",
6878
+ className: "ri-xrButton",
6879
+ onClick: () => xrStore.enterAR().catch((err) => {
6880
+ console.error("Failed to enter AR session:", err);
6881
+ }),
6882
+ title: "View this model in your space",
6883
+ children: [
6884
+ /* @__PURE__ */ jsx19(Smartphone, { size: 16 }),
6885
+ /* @__PURE__ */ jsx19("span", { className: "ri-xrButtonPrefix", children: "Enter" }),
6886
+ /* @__PURE__ */ jsx19("span", { children: "AR" })
6887
+ ]
6888
+ }
6889
+ ),
6890
+ xrStore && vrSupported && /* @__PURE__ */ jsxs15(
6891
+ "button",
6892
+ {
6893
+ type: "button",
6894
+ className: "ri-xrButton",
6895
+ onClick: () => xrStore.enterVR().catch((err) => {
6896
+ console.error("Failed to enter VR session:", err);
6897
+ }),
6898
+ title: "View this model in VR",
6899
+ children: [
6900
+ /* @__PURE__ */ jsx19(RectangleGoggles, { size: 16 }),
6901
+ /* @__PURE__ */ jsx19("span", { className: "ri-xrButtonPrefix", children: "Enter" }),
6902
+ /* @__PURE__ */ jsx19("span", { children: "VR" })
6903
+ ]
6904
+ }
6905
+ )
6906
+ ]
6907
+ }
6908
+ ),
6909
+ arOverlay,
6910
+ showMeasureTools && /* @__PURE__ */ jsxs15(
6911
+ "div",
6912
+ {
6913
+ className: "ri-measureTools",
6914
+ style: { top: `${topLeftRow(xrToolsVisible ? 1 : 0)}px` },
6915
+ children: [
6916
+ /* @__PURE__ */ jsx19(
6917
+ "button",
6918
+ {
6919
+ type: "button",
6920
+ className: `ri-measureButton ${measureMode ? "ri-measureButton--active" : ""}`,
6921
+ onClick: () => setMeasureMode((prev) => !prev),
6922
+ title: measureMode ? "Stop measuring" : "Measure distance",
6923
+ "aria-pressed": measureMode,
6924
+ children: /* @__PURE__ */ jsx19(PencilRuler, { size: 16 })
6925
+ }
6926
+ ),
6927
+ /* @__PURE__ */ jsx19(
6928
+ "button",
6929
+ {
6930
+ type: "button",
6931
+ className: `ri-measureButton ${showDimensions ? "ri-measureButton--active" : ""}`,
6932
+ onClick: () => setShowDimensions((prev) => !prev),
6933
+ title: "Toggle bounding dimensions",
6934
+ "aria-pressed": showDimensions,
6935
+ children: /* @__PURE__ */ jsx19(RulerDimensionLine, { size: 16 })
6936
+ }
6937
+ ),
6938
+ measurePoints.length > 0 && /* @__PURE__ */ jsx19(
6939
+ "button",
6940
+ {
6941
+ type: "button",
6942
+ className: "ri-measureButton",
6943
+ onClick: clearMeasurements,
6944
+ title: "Clear measurements",
6945
+ children: /* @__PURE__ */ jsx19(Eraser, { size: 16 })
6946
+ }
6947
+ ),
6948
+ measureMode && /* @__PURE__ */ jsx19("span", { className: "ri-measureHint", children: "Click points on the model to measure" })
6949
+ ]
6950
+ }
6951
+ ),
6808
6952
  showExplodeControls && /* @__PURE__ */ jsxs15(
6809
6953
  "div",
6810
6954
  {
6811
- className: `ri-explodeTools ${showMeasureTools ? "ri-explodeTools--stacked" : ""}`,
6955
+ className: "ri-explodeTools",
6956
+ style: {
6957
+ top: `${topLeftRow((xrToolsVisible ? 1 : 0) + (showMeasureTools ? 1 : 0))}px`
6958
+ },
6812
6959
  children: [
6813
6960
  /* @__PURE__ */ jsx19(
6814
6961
  "button",
@@ -6847,7 +6994,7 @@ function ModelViewer({
6847
6994
  {
6848
6995
  className: "ri-cinematicTools",
6849
6996
  style: {
6850
- top: `${16 + ((showMeasureTools ? 1 : 0) + (showExplodeControls ? 1 : 0)) * 42}px`
6997
+ top: `${topLeftRow((xrToolsVisible ? 1 : 0) + (showMeasureTools ? 1 : 0) + (showExplodeControls ? 1 : 0))}px`
6851
6998
  },
6852
6999
  children: /* @__PURE__ */ jsx19(
6853
7000
  "button",
@@ -6862,56 +7009,8 @@ function ModelViewer({
6862
7009
  )
6863
7010
  }
6864
7011
  ),
6865
- enableXR && (xrStore && (arSupported || vrSupported) || quickLookSupported) && /* @__PURE__ */ jsxs15("div", { className: "ri-xrTools", children: [
6866
- !arSupported && quickLookSupported && /* @__PURE__ */ jsxs15(
6867
- "button",
6868
- {
6869
- type: "button",
6870
- className: "ri-xrButton",
6871
- onClick: openQuickLook,
6872
- title: "View this model in AR with Apple Quick Look",
6873
- children: [
6874
- /* @__PURE__ */ jsx19(Box, { size: 16 }),
6875
- "View in AR"
6876
- ]
6877
- }
6878
- ),
6879
- xrStore && arSupported && /* @__PURE__ */ jsxs15(
6880
- "button",
6881
- {
6882
- type: "button",
6883
- className: "ri-xrButton",
6884
- onClick: () => xrStore.enterAR().catch((err) => {
6885
- console.error("Failed to enter AR session:", err);
6886
- }),
6887
- title: "View this model in your space",
6888
- children: [
6889
- /* @__PURE__ */ jsx19(Box, { size: 16 }),
6890
- /* @__PURE__ */ jsx19("span", { className: "ri-xrButtonPrefix", children: "Enter" }),
6891
- /* @__PURE__ */ jsx19("span", { children: "AR" })
6892
- ]
6893
- }
6894
- ),
6895
- xrStore && vrSupported && /* @__PURE__ */ jsxs15(
6896
- "button",
6897
- {
6898
- type: "button",
6899
- className: "ri-xrButton",
6900
- onClick: () => xrStore.enterVR().catch((err) => {
6901
- console.error("Failed to enter VR session:", err);
6902
- }),
6903
- title: "View this model in VR",
6904
- children: [
6905
- /* @__PURE__ */ jsx19(RectangleGoggles, { size: 16 }),
6906
- /* @__PURE__ */ jsx19("span", { className: "ri-xrButtonPrefix", children: "Enter" }),
6907
- /* @__PURE__ */ jsx19("span", { children: "VR" })
6908
- ]
6909
- }
6910
- )
6911
- ] }),
6912
- arOverlay,
6913
7012
  (showResetButton || showDownloadButtons || showAnnotationNavigation && sortedAnnotations.length > 0) && /* @__PURE__ */ jsxs15("div", { className: "ri-buttonContainer", children: [
6914
- /* @__PURE__ */ jsx19("div", { className: "ri-tourControls", children: showAnnotationNavigation && sortedAnnotations.length > 0 && /* @__PURE__ */ jsx19(Fragment6, { children: !isGuidedTourActive ? (
7013
+ /* @__PURE__ */ jsx19("div", { className: "ri-tourControls", children: showAnnotationNavigation && sortedAnnotations.length > 0 && /* @__PURE__ */ jsx19(Fragment7, { children: !isGuidedTourActive ? (
6915
7014
  // Show "Guided Tour" button when tour is not active
6916
7015
  /* @__PURE__ */ jsx19(
6917
7016
  "button",
@@ -6925,7 +7024,7 @@ function ModelViewer({
6925
7024
  )
6926
7025
  ) : (
6927
7026
  // Show Previous, Next, Stop, Reset buttons when tour is active
6928
- /* @__PURE__ */ jsxs15(Fragment6, { children: [
7027
+ /* @__PURE__ */ jsxs15(Fragment7, { children: [
6929
7028
  /* @__PURE__ */ jsxs15(
6930
7029
  "button",
6931
7030
  {
@@ -7019,10 +7118,10 @@ function ModelViewer({
7019
7118
  onClick: () => setDownloadMenuOpen((v) => !v),
7020
7119
  disabled: isDownloading || !sceneRef.current,
7021
7120
  title: "Download options",
7022
- children: isDownloading ? /* @__PURE__ */ jsxs15(Fragment6, { children: [
7121
+ children: isDownloading ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
7023
7122
  /* @__PURE__ */ jsx19("span", { className: "ri-downloadButton__spinner" }),
7024
7123
  "Exporting\u2026"
7025
- ] }) : /* @__PURE__ */ jsxs15(Fragment6, { children: [
7124
+ ] }) : /* @__PURE__ */ jsxs15(Fragment7, { children: [
7026
7125
  /* @__PURE__ */ jsx19(Download, { size: 15 }),
7027
7126
  "Download"
7028
7127
  ] })
@@ -7100,7 +7199,7 @@ function ModelViewer({
7100
7199
  ]
7101
7200
  }
7102
7201
  ),
7103
- colorPicker && /* @__PURE__ */ jsx19(
7202
+ customObjectBindingDataPanel && colorPicker && /* @__PURE__ */ jsx19(
7104
7203
  ColorPicker,
7105
7204
  {
7106
7205
  colorPicker,
@@ -7109,7 +7208,7 @@ function ModelViewer({
7109
7208
  setItemMaterials
7110
7209
  }
7111
7210
  ),
7112
- materialPopup && /* @__PURE__ */ jsx19(
7211
+ customObjectBindingDataPanel && materialPopup && /* @__PURE__ */ jsx19(
7113
7212
  MaterialPicker,
7114
7213
  {
7115
7214
  triggerFileUpload,
@@ -7147,7 +7246,7 @@ function ModelViewer({
7147
7246
  }
7148
7247
 
7149
7248
  // src/components/BindingBuilder/BindingBuilder.tsx
7150
- import { useCallback as useCallback8, useEffect as useEffect19, useMemo as useMemo16, useRef as useRef17, useState as useState24 } from "react";
7249
+ import { useCallback as useCallback8, useEffect as useEffect19, useMemo as useMemo16, useRef as useRef18, useState as useState24 } from "react";
7151
7250
  import {
7152
7251
  Redo2,
7153
7252
  Undo2,
@@ -7161,7 +7260,7 @@ import {
7161
7260
  styleInject('.bb-root {\n --bb-font-family:\n Inter,\n "Segoe UI",\n Helvetica,\n Arial,\n sans-serif;\n --bb-app-bg:\n radial-gradient(\n \n circle at top left,\n rgba(226, 232, 240, 0.8),\n transparent 30% ),\n linear-gradient(\n 135deg,\n #f6f1e8 0%,\n #ebe8df 40%,\n #e9edf2 100%);\n --bb-app-text: #111827;\n --bb-sidebar-bg:\n linear-gradient(\n 180deg,\n rgba(20, 27, 45, 0.98),\n rgba(25, 34, 57, 0.95)),\n #121826;\n --bb-sidebar-text: #f8fafc;\n --bb-sidebar-muted-text: #b3bfd2;\n --bb-sidebar-subtle-text: #94a3b8;\n --bb-sidebar-border: rgba(148, 163, 184, 0.18);\n --bb-sidebar-border-hover: rgba(148, 163, 184, 0.32);\n --bb-sidebar-divider: rgba(148, 163, 184, 0.14);\n --bb-sidebar-surface: rgba(255, 255, 255, 0.04);\n --bb-sidebar-surface-hover: rgba(255, 255, 255, 0.08);\n --bb-sidebar-surface-strong: rgba(255, 255, 255, 0.05);\n --bb-sidebar-eyebrow-bg: rgba(148, 163, 184, 0.16);\n --bb-sidebar-eyebrow-text: #cbd5e1;\n --bb-sidebar-left-shadow: 18px 0 42px rgba(15, 23, 42, 0.12);\n --bb-sidebar-right-shadow: -4px 0 24px rgba(0, 0, 0, 0.35);\n --bb-sidebar-chip-bg: rgba(15, 23, 42, 0.42);\n --bb-sidebar-chip-border: rgba(148, 163, 184, 0.14);\n --bb-sidebar-accent: rgba(99, 102, 241, 0.18);\n --bb-sidebar-accent-border: rgba(99, 102, 241, 0.4);\n --bb-sidebar-accent-text: #f8fafc;\n --bb-menu-bg: #1a1f2e;\n --bb-menu-shadow: 0 16px 32px rgba(15, 23, 42, 0.4);\n display: flex;\n height: 100%;\n min-height: 0;\n width: 100%;\n background: var(--bb-app-bg);\n color: var(--bb-app-text);\n font-family: var(--bb-font-family);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n font-synthesis: none;\n}\n.bb-root * {\n box-sizing: border-box;\n}\n.bb-root input,\n.bb-root select,\n.bb-root textarea,\n.bb-root button {\n font-family: inherit;\n}\n.bb-sidebar {\n width: 400px;\n min-height: 0;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--bb-sidebar-bg);\n color: var(--bb-sidebar-text);\n transition: width 0.24s ease;\n}\n.bb-sidebar--left {\n border-right: 1px solid var(--bb-sidebar-border);\n box-shadow: var(--bb-sidebar-left-shadow);\n}\n.bb-sidebar--right {\n width: 300px;\n border-left: 1px solid var(--bb-sidebar-border);\n box-shadow: var(--bb-sidebar-right-shadow);\n}\n.bb-sidebar--collapsed {\n width: 36px;\n}\n.bb-sidebar--collapsed .bb-header {\n padding: 5px;\n display: flex;\n justify-content: center;\n}\n.bb-sidebar--collapsed .bb-header--sidebar {\n min-height: 36px;\n}\n.bb-sidebar--collapsed .bb-sidebarToggle {\n width: 26px;\n height: 26px;\n font-size: 12px;\n}\n.bb-header {\n padding: 5px 20px;\n border-bottom: 1px solid var(--bb-sidebar-divider);\n}\n.bb-header--sidebar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n min-height: 55px;\n}\n.bb-eyebrow {\n display: inline-block;\n margin-bottom: 12px;\n padding: 6px 10px;\n border-radius: 999px;\n background: var(--bb-sidebar-eyebrow-bg);\n color: var(--bb-sidebar-eyebrow-text);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.18em;\n text-transform: uppercase;\n}\n.bb-title {\n margin: 0 0 0px;\n font-size: 20px;\n line-height: 0.95;\n letter-spacing: -0.04em;\n font-weight: 800;\n color: var(--bb-sidebar-text);\n}\n.bb-sidebarToggle {\n width: 36px;\n height: 36px;\n flex-shrink: 0;\n border-radius: 6px;\n border: 1px solid var(--bb-sidebar-border);\n background: var(--bb-sidebar-surface-strong);\n color: var(--bb-sidebar-text);\n font-size: 16px;\n font-weight: 800;\n cursor: pointer;\n transition:\n transform 0.18s ease,\n background-color 0.18s ease,\n border-color 0.18s ease;\n}\n.bb-sidebarToggle:hover {\n transform: translateY(-1px);\n background: var(--bb-sidebar-surface-hover);\n border-color: var(--bb-sidebar-border-hover);\n}\n.bb-subtitle {\n margin: 0;\n max-width: 32ch;\n font-size: 15px;\n line-height: 1.7;\n color: var(--bb-sidebar-muted-text);\n}\n.bb-statRow {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 10px;\n margin-top: 22px;\n}\n.bb-statChip {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n padding: 12px 14px;\n border-radius: 8px;\n background: var(--bb-sidebar-chip-bg);\n border: 1px solid var(--bb-sidebar-chip-border);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);\n}\n.bb-statChip strong {\n font-size: 13px;\n color: var(--bb-sidebar-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.bb-statLabel {\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--bb-sidebar-subtle-text);\n}\n.bb-tabRow {\n display: flex;\n gap: 6px;\n padding: 10px 20px 10px;\n}\n.bb-tab {\n flex: 1;\n padding: 6px 10px;\n border-radius: 6px;\n border: 1px solid var(--bb-sidebar-border);\n background: var(--bb-sidebar-surface);\n color: var(--bb-sidebar-muted-text);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n cursor: pointer;\n transition:\n background-color 0.18s ease,\n border-color 0.18s ease,\n color 0.18s ease;\n}\n.bb-tab:hover {\n background: var(--bb-sidebar-surface-hover);\n border-color: var(--bb-sidebar-border-hover);\n}\n.bb-tab--active {\n background: var(--bb-sidebar-accent);\n border-color: var(--bb-sidebar-accent-border);\n color: var(--bb-sidebar-accent-text);\n}\n.bb-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 10px;\n padding: 8px 20px 8px;\n border-bottom: 1px solid var(--bb-sidebar-divider);\n flex-wrap: wrap;\n}\n.bb-toolbarGroup {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n.bb-toolbarDivider {\n width: 1px;\n align-self: stretch;\n background: var(--bb-sidebar-divider);\n margin: 0;\n}\n.bb-iconButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border-radius: 7px;\n border: 1px solid var(--bb-sidebar-border);\n background: var(--bb-sidebar-surface);\n color: var(--bb-sidebar-text);\n cursor: pointer;\n transition: background-color 0.18s ease, border-color 0.18s ease;\n}\n.bb-iconButton:hover:not(:disabled) {\n background: var(--bb-sidebar-surface-hover);\n border-color: var(--bb-sidebar-border-hover);\n}\n.bb-iconButton:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.bb-exportMenuWrapper {\n position: relative;\n display: inline-flex;\n}\n.bb-exportMenu {\n position: absolute;\n bottom: calc(100% + 6px);\n right: 0;\n z-index: 20;\n display: flex;\n flex-direction: column;\n min-width: 150px;\n padding: 6px;\n border-radius: 9px;\n border: 1px solid var(--bb-sidebar-border);\n background: var(--bb-menu-bg);\n box-shadow: var(--bb-menu-shadow);\n}\n.bb-exportMenuItem {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--bb-sidebar-text);\n font-size: 12px;\n font-weight: 600;\n text-align: left;\n cursor: pointer;\n}\n.bb-exportMenuItem:hover {\n background: var(--bb-sidebar-surface-hover);\n}\n@media (max-width: 640px) {\n .bb-toolbarDivider {\n width: 100%;\n height: 1px;\n }\n}\n.bb-button,\n.bb-fileLabel {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: 32px;\n padding: 0 12px;\n border-radius: 7px;\n border: 1px solid var(--bb-sidebar-border);\n background: var(--bb-sidebar-surface);\n color: var(--bb-sidebar-text);\n font-size: 12px;\n font-weight: 700;\n cursor: pointer;\n transition:\n transform 0.18s ease,\n background-color 0.18s ease,\n border-color 0.18s ease,\n box-shadow 0.18s ease;\n}\n.bb-button:hover,\n.bb-fileLabel:hover {\n transform: translateY(-1px);\n background: rgba(255, 255, 255, 0.08);\n border-color: rgba(148, 163, 184, 0.32);\n box-shadow: 0 10px 18px rgba(15, 23, 42, 0.18);\n}\n.bb-button:disabled,\n.bb-fileLabel:has(.bb-hiddenInput:disabled) {\n opacity: 0.55;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n}\n.bb-button--primary {\n background: #135bc0;\n border-color: transparent;\n color: #ffffff;\n}\n.bb-button--primary:hover {\n background: #1a68d6;\n}\n.bb-button--ghost {\n background: rgba(248, 250, 252, 0.08);\n}\n.bb-hiddenInput {\n display: none;\n}\n.bb-statusCard {\n margin-top: 4px;\n padding: 14px 16px;\n border-radius: 9px;\n background: rgba(15, 23, 42, 0.44);\n border: 1px solid rgba(148, 163, 184, 0.15);\n}\n.bb-statusCard--error {\n background: rgba(127, 29, 29, 0.32);\n border-color: rgba(248, 113, 113, 0.24);\n}\n.bb-statusCard--success {\n background: rgba(6, 78, 59, 0.34);\n border-color: rgba(52, 211, 153, 0.24);\n}\n.bb-statusTitle {\n margin-bottom: 6px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: #cbd5e1;\n}\n.bb-status {\n font-size: 13px;\n line-height: 1.55;\n color: #e2e8f0;\n}\n.bb-status--error {\n color: #fecaca;\n}\n.bb-status--success {\n color: #bbf7d0;\n}\n.bb-input--error {\n border-color: #dc2626;\n}\n.bb-nodeList {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n overflow: hidden;\n background: #141824;\n}\n.bb-sectionHead {\n padding: 24px 20px 16px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\n}\n.bb-sectionKicker {\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: #64748b;\n}\n.bb-sectionHeading {\n margin-top: 4px;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n color: #f1f5f9;\n}\n.bb-search {\n padding: 14px 16px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\n}\n.bb-input,\n.bb-select,\n.bb-textarea {\n width: 100%;\n border-radius: 10px;\n border: 1px solid rgba(255, 255, 255, 0.08);\n background: rgba(255, 255, 255, 0.05);\n color: #e2e8f0;\n padding: 10px 14px;\n font-size: 13px;\n line-height: 1.45;\n}\n.bb-input::placeholder,\n.bb-textarea::placeholder {\n color: #475569;\n}\n.bb-input--compact {\n width: 64px;\n max-width: 64px;\n flex: 0 0 auto;\n padding: 7px 4px;\n text-align: center;\n}\n.bb-input:focus,\n.bb-select:focus,\n.bb-textarea:focus {\n outline: none;\n border-color: rgba(255, 255, 255, 0.18);\n background: rgba(255, 255, 255, 0.08);\n box-shadow: none;\n}\n.bb-textarea {\n min-height: 110px;\n resize: vertical;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n}\n.bb-nodeItems {\n min-height: 0;\n overflow-y: auto;\n padding: 10px 0;\n}\n.bb-nodeButton {\n width: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n padding: 12px 20px;\n margin-bottom: 0;\n text-align: left;\n cursor: pointer;\n transition: background-color 0.12s ease, color 0.12s ease;\n border-bottom: 1px solid rgba(255, 255, 255, 0.04);\n}\n.bb-nodeButton:hover {\n background: rgba(255, 255, 255, 0.05);\n}\n.bb-nodeButton--active {\n background: rgba(255, 255, 255, 0.05);\n box-shadow: none;\n}\n.bb-nodeName {\n display: block;\n margin-bottom: 2px;\n font-size: 14px;\n font-weight: 600;\n color: #e2e8f0;\n}\n.bb-nodeMeta {\n display: block;\n font-size: 11px;\n color: #94a3b8;\n}\n.bb-editor {\n flex: 1 1 auto;\n min-height: 0;\n height: 100%;\n overflow-y: auto;\n padding: 16px 16px 28px;\n overscroll-behavior: contain;\n}\n.bb-editorHeader {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 18px;\n padding: 18px;\n border-radius: 11px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid rgba(148, 163, 184, 0.12);\n}\n.bb-editorTitle {\n margin: 8px 0 0;\n font-size: 24px;\n line-height: 1.1;\n color: #f8fafc;\n}\n.bb-editorMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 8px 12px;\n margin-top: 10px;\n font-size: 12px;\n color: #94a3b8;\n}\n.bb-editorBadge {\n flex-shrink: 0;\n padding: 8px 12px;\n border-radius: 999px;\n background: rgba(251, 191, 36, 0.12);\n border: 1px solid rgba(251, 191, 36, 0.2);\n color: #fcd34d;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n}\n.bb-emptyEditor {\n padding: 28px 8px;\n font-size: 14px;\n color: #a7b1c3;\n}\n.bb-section {\n margin-bottom: 10px;\n border-radius: 7px;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(148, 163, 184, 0.12);\n overflow: hidden;\n}\n.bb-sectionHeaderButton {\n display: flex;\n width: 100%;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border: none;\n background: rgba(255, 255, 255, 0.03);\n padding: 11px 14px;\n cursor: pointer;\n text-align: left;\n color: inherit;\n}\n.bb-sectionHeaderButton:hover {\n background: rgba(255, 255, 255, 0.06);\n}\n.bb-sectionHeaderMain {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 8px;\n}\n.bb-sectionChevron {\n flex-shrink: 0;\n color: #8b97ab;\n transform: rotate(-90deg);\n transition: transform 0.18s ease;\n}\n.bb-sectionChevron--open {\n transform: rotate(0deg);\n}\n.bb-sectionBody {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 14px;\n border-top: 1px solid rgba(148, 163, 184, 0.1);\n}\n.bb-sectionTitle {\n margin: 0;\n font-size: 11px;\n font-weight: 700;\n color: #c3cbdb;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n}\n.bb-sectionHelp {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n margin-left: 2px;\n border-radius: 999px;\n color: #b9c0ca;\n cursor: help;\n transition:\n background 0.18s ease,\n color 0.18s ease,\n transform 0.18s ease;\n}\n.bb-sectionHelp:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #eef2ff;\n transform: translateY(-0.5px);\n}\n.bb-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 10px;\n}\n.bb-presetGallery {\n display: flex;\n justify-items: center;\n flex-wrap: wrap;\n gap: 4px;\n margin-bottom: 14px;\n}\n.bb-presetSwatch {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 5px;\n width: 64px;\n padding: 6px 4px;\n border-radius: 8px;\n border: 1px solid rgba(148, 163, 184, 0.18);\n background: rgba(148, 163, 184, 0.06);\n cursor: pointer;\n transition: border-color 0.15s, background 0.15s;\n}\n.bb-presetSwatch:hover:not(:disabled) {\n border-color: rgba(148, 163, 184, 0.4);\n background: rgba(148, 163, 184, 0.12);\n}\n.bb-presetSwatch:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.bb-presetSwatchColor {\n width: 32px;\n height: 32px;\n border-radius: 999px;\n border: 1px solid rgba(255, 255, 255, 0.18);\n}\n.bb-presetSwatchLabel {\n font-size: 10px;\n font-weight: 600;\n color: #cbd5e1;\n text-align: center;\n line-height: 1.2;\n}\n.bb-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n}\n.bb-field--full {\n grid-column: 1 / -1;\n}\n.bb-label {\n font-size: 12px;\n font-weight: 700;\n color: #d7dee9;\n}\n.bb-note {\n font-size: 11px;\n color: #8b97ab;\n}\n.bb-tierLock {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 16px 14px;\n border-radius: 7px;\n background: rgba(251, 191, 36, 0.08);\n border: 1px dashed rgba(251, 191, 36, 0.3);\n color: #fcd34d;\n}\n.bb-tierLockMessage {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n}\n.bb-root--licenseChecking,\n.bb-root--licenseInvalid {\n align-items: center;\n justify-content: center;\n}\n.bb-readonly {\n background: rgba(148, 163, 184, 0.08);\n color: #9ca3af;\n}\n.bb-checkboxRow {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n}\n.bb-checkbox {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 5px;\n border-radius: 7px;\n background: rgba(15, 23, 42, 0.22);\n border: 1px solid rgba(148, 163, 184, 0.12);\n font-size: 13px;\n color: #d7dee9;\n}\n.bb-checkbox input {\n accent-color: #f59e0b;\n}\n.bb-sliderField {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.bb-slider {\n flex: 1 1 auto;\n min-width: 0;\n accent-color: #2aa8d8;\n}\n.bb-slider--unset {\n opacity: 0.45;\n}\n.bb-fileField {\n position: relative;\n display: flex;\n align-items: center;\n}\n.bb-fileField-input {\n width: 100%;\n padding-right: 40px;\n}\n.bb-fileFieldButton {\n position: absolute;\n right: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 5px;\n background: transparent;\n color: #aab4c5;\n cursor: pointer;\n}\n.bb-fileFieldButton:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #f8fafc;\n}\n.bb-materialPanel {\n margin-top: 8px;\n border: 1px solid rgba(148, 163, 184, 0.14);\n border-radius: 6px;\n background: rgba(15, 23, 42, 0.28);\n overflow: hidden;\n}\n.bb-materialPanel:first-of-type {\n margin-top: 0;\n}\n.bb-materialPanelHeader {\n display: flex;\n width: 100%;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border: none;\n padding: 10px 12px;\n background: rgba(255, 255, 255, 0.03);\n cursor: pointer;\n text-align: left;\n color: inherit;\n}\n.bb-materialPanelHeader:hover {\n background: rgba(255, 255, 255, 0.06);\n}\n.bb-materialPanelTitleWrap {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: #dbe4f0;\n}\n.bb-materialPanelChevron {\n flex-shrink: 0;\n color: #8b97ab;\n transform: rotate(-90deg);\n transition: transform 0.18s ease;\n}\n.bb-materialPanelChevron--open {\n transform: rotate(0deg);\n}\n.bb-materialPanelTitle {\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.bb-materialPanelHelp {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n margin-left: 2px;\n border-radius: 999px;\n color: #b9c0ca;\n cursor: help;\n transition:\n background 0.18s ease,\n color 0.18s ease,\n transform 0.18s ease;\n}\n.bb-materialPanelHelp:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #eef2ff;\n transform: translateY(-0.5px);\n}\n.bb-materialPanelBody {\n padding: 12px;\n border-top: 1px solid rgba(148, 163, 184, 0.1);\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.bb-actionList {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.bb-actionCard {\n border: 1px solid rgba(148, 163, 184, 0.14);\n border-radius: 9px;\n padding: 14px;\n background: rgba(15, 23, 42, 0.2);\n}\n.bb-actionCardHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 12px;\n}\n.bb-actionCardTitle {\n font-size: 13px;\n font-weight: 700;\n color: #f8fafc;\n}\n.bb-actionCardMeta {\n flex-shrink: 0;\n padding: 5px 9px;\n border-radius: 999px;\n background: rgba(148, 163, 184, 0.12);\n color: #94a3b8;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n}\n.bb-actionGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 10px;\n}\n.bb-actionFooter {\n margin-top: 12px;\n}\n.bb-actionRemove {\n width: 100%;\n}\n.bb-previewShell {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding: 5px;\n overflow: hidden;\n}\n.bb-previewHeader {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding: 0 4px 10px;\n}\n.bb-previewControls {\n display: flex;\n align-items: flex-start;\n justify-content: flex-end;\n gap: 10px;\n flex-wrap: wrap;\n}\n.bb-previewTitle {\n margin: 2px 0 0;\n font-size: 20px;\n line-height: 1.05;\n letter-spacing: -0.03em;\n color: #1f2937;\n}\n.bb-previewToggles {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n}\n.bb-checkbox--compact {\n gap: 5px;\n padding: 0;\n background: transparent;\n border: none;\n font-size: 10px;\n font-weight: 500;\n line-height: 1;\n color: #4b5563;\n}\n.bb-checkbox--compact:hover {\n background: transparent;\n transform: none;\n}\n.bb-checkbox--compact input[type=checkbox] {\n width: 11px;\n height: 11px;\n}\n.bb-previewMeta {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 8px;\n}\n.bb-removeModelButton {\n background-color: rgb(174, 54, 54);\n min-height: 34px;\n padding: 0 14px;\n}\n.bb-removeModelButton:hover {\n background-color: rgb(163, 20, 20);\n}\n.bb-previewMeta span {\n display: inline-flex;\n align-items: center;\n min-height: 34px;\n padding: 0 12px;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.7);\n border: 1px solid rgba(148, 163, 184, 0.18);\n color: #475569;\n font-size: 12px;\n font-weight: 700;\n}\n.bb-preview {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n border-radius: 14px;\n background:\n radial-gradient(\n circle at top left,\n rgba(255, 255, 255, 0.92),\n rgba(236, 240, 244, 0.82)),\n #f8fafc;\n border: 1px solid rgba(148, 163, 184, 0.24);\n box-shadow: 0 24px 48px rgba(148, 163, 184, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.7);\n}\n.bb-loadingOverlay {\n position: absolute;\n inset: 0;\n z-index: 5;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n padding: 24px;\n text-align: center;\n border-radius: 14px;\n background: rgba(248, 250, 252, 0.82);\n backdrop-filter: blur(2px);\n}\n.bb-loadingSpinner {\n width: 40px;\n height: 40px;\n border-radius: 999px;\n border: 3px solid rgba(148, 163, 184, 0.3);\n border-top-color: #2563eb;\n animation: bb-spin 0.8s linear infinite;\n}\n@keyframes bb-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.bb-loadingMessage {\n max-width: 320px;\n color: #475569;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.5;\n}\n.bb-previewStatus {\n max-width: 280px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bb-previewStatus--success {\n background: rgba(34, 197, 94, 0.12) !important;\n border-color: rgba(34, 197, 94, 0.3) !important;\n color: #15803d !important;\n}\n.bb-previewStatus--error {\n background: rgba(239, 68, 68, 0.12) !important;\n border-color: rgba(239, 68, 68, 0.3) !important;\n color: #b91c1c !important;\n}\n.bb-previewModelName {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bb-previewPlaceholder {\n position: relative;\n display: flex;\n height: 100%;\n width: 100%;\n align-items: center;\n justify-content: center;\n padding: 40px;\n text-align: center;\n color: #64748b;\n font-size: 15px;\n line-height: 1.7;\n border-radius: 14px;\n border: 2px dashed rgba(148, 163, 184, 0.24);\n background:\n radial-gradient(\n circle at top,\n rgba(251, 191, 36, 0.12),\n transparent 30%),\n linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0.82),\n rgba(238, 242, 248, 0.9));\n transition:\n border-color 0.2s ease,\n background 0.2s ease,\n transform 0.2s ease,\n box-shadow 0.2s ease;\n}\n.bb-previewPlaceholder > div {\n max-width: 420px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n}\n.bb-previewPlaceholderTitle {\n font-size: 28px;\n line-height: 1.05;\n letter-spacing: -0.03em;\n font-weight: 800;\n color: #1f2937;\n}\n.bb-previewPlaceholderButton {\n margin-top: 8px;\n border: 0;\n border-radius: 999px;\n padding: 13px 22px;\n background: #135bc0;\n color: #ffffff;\n font-size: 14px;\n font-weight: 800;\n cursor: pointer;\n transition:\n transform 0.18s ease,\n box-shadow 0.18s ease,\n opacity 0.18s ease;\n}\n.bb-previewPlaceholderButton:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 14px 30px rgba(19, 91, 192, 0.28);\n}\n.bb-previewPlaceholderButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.bb-previewPlaceholder--dragActive {\n border-color: rgba(245, 158, 11, 0.75);\n background:\n radial-gradient(\n circle at top,\n rgba(251, 191, 36, 0.22),\n transparent 32%),\n linear-gradient(\n 180deg,\n rgba(255, 252, 245, 0.95),\n rgba(255, 244, 230, 0.92));\n transform: scale(0.995);\n box-shadow: inset 0 0 0 1px rgba(245, 158, 11, 0.14);\n}\n.bb-sectionHeader {\n cursor: pointer;\n user-select: none;\n}\n.bb-iconButton {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 16px;\n color: var(--bb-sidebar-subtle-text);\n transition: color 0.2s ease;\n padding: 4px 8px;\n border-radius: 4px;\n}\n.bb-iconButton:hover {\n color: var(--bb-sidebar-text);\n background: var(--bb-sidebar-surface-strong);\n}\n.bb-cameraLive,\n.bb-cameraSaved {\n background: rgba(15, 23, 42, 0.44);\n border-radius: 8px;\n padding: 14px;\n margin-bottom: 16px;\n border: 1px solid rgba(148, 163, 184, 0.15);\n transition: all 0.2s ease;\n}\n.bb-cameraLive:hover,\n.bb-cameraSaved:hover {\n border-color: rgba(148, 163, 184, 0.25);\n background: rgba(15, 23, 42, 0.52);\n}\n.bb-cameraLiveHeader,\n.bb-cameraSavedHeader {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid rgba(148, 163, 184, 0.15);\n}\n.bb-cameraLiveBadge {\n background:\n linear-gradient(\n 135deg,\n #10b981,\n #059669);\n color: white;\n font-size: 10px;\n font-weight: 700;\n padding: 3px 8px;\n border-radius: 10px;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n}\n.bb-cameraSavedBadge {\n background:\n linear-gradient(\n 135deg,\n #3b82f6,\n #2563eb);\n color: white;\n font-size: 10px;\n font-weight: 700;\n padding: 3px 8px;\n border-radius: 10px;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n}\n.bb-cameraLiveLabel,\n.bb-cameraSavedLabel {\n font-size: 12px;\n font-weight: 600;\n color: #cbd5e1;\n}\n.bb-cameraValues {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bb-cameraRow {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n flex-wrap: wrap;\n}\n.bb-cameraLabel {\n font-weight: 600;\n color: #94a3b8;\n min-width: 58px;\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n.bb-cameraCode {\n font-family:\n "Monaco",\n "Menlo",\n "Ubuntu Mono",\n "Consolas",\n monospace;\n font-size: 11px;\n background: rgba(0, 0, 0, 0.3);\n padding: 3px 8px;\n border-radius: 4px;\n color: #fcd34d;\n letter-spacing: 0.02em;\n word-break: break-all;\n}\n.bb-cameraPlaceholder {\n color: #94a3b8;\n font-size: 12px;\n text-align: center;\n padding: 16px;\n font-style: italic;\n}\n.bb-cameraControls {\n display: flex;\n gap: 10px;\n margin-bottom: 14px;\n flex-wrap: wrap;\n}\n.bb-button--primary {\n background: #135bc0;\n border-color: transparent;\n color: #ffffff;\n}\n.bb-button--primary:hover:not(:disabled) {\n background: #1a68d6;\n transform: translateY(-1px);\n}\n.bb-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n}\n.bb-cameraMessage {\n padding: 10px 14px;\n border-radius: 6px;\n margin-bottom: 14px;\n font-size: 12px;\n font-weight: 500;\n animation: slideIn 0.3s ease-out;\n}\n.bb-cameraMessage--success {\n background: rgba(16, 185, 129, 0.15);\n color: #6ee7b7;\n border: 1px solid rgba(16, 185, 129, 0.3);\n}\n.bb-cameraMessage--error {\n background: rgba(239, 68, 68, 0.15);\n color: #ffe5e55c;\n border: 1px solid rgba(255, 248, 248, 0.3);\n}\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.bb-readonly {\n background: rgba(148, 163, 184, 0.08);\n color: #9ca3af;\n cursor: default;\n}\n@media (max-width: 1280px) {\n .bb-cameraRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n .bb-cameraLabel {\n min-width: auto;\n }\n .bb-cameraControls {\n flex-direction: column;\n }\n .bb-cameraControls .bb-button {\n width: 100%;\n }\n}\n@media (max-width: 980px) {\n .bb-sidebar--left {\n width: 100%;\n max-height: 42vh;\n }\n .bb-sidebar--collapsed {\n width: 100%;\n }\n .bb-previewShell {\n padding: 14px;\n }\n .bb-preview {\n min-height: 44vh;\n }\n .bb-previewHeader {\n flex-direction: column;\n align-items: flex-start;\n }\n .bb-previewControls {\n width: 100%;\n justify-content: flex-start;\n }\n .bb-previewMeta {\n justify-content: flex-start;\n }\n .bb-grid,\n .bb-actionGrid,\n .bb-statRow {\n grid-template-columns: 1fr;\n }\n}\n.bb-annotationsInfo {\n margin-top: 8px;\n}\n.bb-emptyAnnotations {\n padding: 32px;\n text-align: center;\n background: #f5f5f5;\n border-radius: 4px;\n color: #666;\n font-size: 14px;\n}\n.bb-annotationsList {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.bb-annotationCard {\n background: #f9f9f9;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 12px;\n transition: all 0.2s ease;\n}\n.bb-annotationCard:hover {\n background: #ffffff;\n border-color: #4caf50;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.bb-annotationHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n.bb-annotationBadge {\n background: #4caf50;\n color: white;\n padding: 2px 8px;\n border-radius: 2px;\n font-size: 11px;\n font-weight: 600;\n}\n.bb-annotationActions {\n display: flex;\n gap: 8px;\n}\n.bb-annotationEdit,\n.bb-annotationDelete {\n background: transparent;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 2px;\n font-size: 14px;\n transition: all 0.2s ease;\n}\n.bb-annotationEdit:hover {\n background: #e8f5e9;\n transform: scale(1.05);\n}\n.bb-annotationDelete:hover {\n background: #ffebee;\n transform: scale(1.05);\n}\n.bb-annotationTitle {\n font-weight: 600;\n font-size: 14px;\n color: #333;\n margin-bottom: 6px;\n}\n.bb-annotationDescription {\n font-size: 13px;\n color: #666;\n margin-bottom: 8px;\n line-height: 1.4;\n}\n.bb-annotationPosition {\n font-size: 11px;\n font-family: monospace;\n color: #999;\n background: #f0f0f0;\n padding: 4px 6px;\n border-radius: 2px;\n display: inline-block;\n}\n.bb-modalOverlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n.bb-modal {\n background: white;\n border-radius: 6px;\n width: 500px;\n max-width: 90%;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n animation: modalSlideIn 0.2s ease;\n}\n@keyframes modalSlideIn {\n from {\n transform: translateY(-20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n.bb-modalHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n}\n.bb-modalHeader h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n.bb-modalClose {\n background: transparent;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #999;\n transition: color 0.2s ease;\n}\n.bb-modalClose:hover {\n color: #333;\n}\n.bb-modalBody {\n padding: 20px;\n}\n.bb-modalFooter {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n}\n.bb-annotationsInfo {\n margin-top: 8px;\n}\n.bb-emptyAnnotations {\n padding: 32px;\n text-align: center;\n background: rgba(15, 23, 42, 0.44);\n border-radius: 10px;\n border: 1px solid rgba(148, 163, 184, 0.15);\n color: #94a3b8;\n font-size: 14px;\n}\n.bb-annotationsList {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.bb-annotationCard {\n background: rgba(15, 23, 42, 0.44);\n border-left: 4px solid #22d3ee;\n border-radius: 8px;\n padding: 16px;\n transition: all 0.2s ease;\n border: 1px solid rgba(148, 163, 184, 0.15);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\n}\n.bb-annotationCard:hover {\n transform: translateX(4px);\n background: rgba(15, 23, 42, 0.6);\n border-color: rgba(148, 163, 184, 0.25);\n box-shadow: 0 4px 12px rgba(15, 23, 42, 0.3);\n}\n.bb-annotationBadge {\n display: inline-block;\n background: #22d3ee;\n color: #06343c;\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.5px;\n margin-bottom: 12px;\n text-transform: uppercase;\n}\n.bb-annotationTitle {\n font-weight: 700;\n font-size: 15px;\n color: #f8fafc;\n margin-bottom: 8px;\n line-height: 1.3;\n}\n.bb-annotationDescription {\n font-size: 13px;\n color: #cbd5e1;\n margin-bottom: 12px;\n line-height: 1.5;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n.bb-annotationPosition {\n font-size: 11px;\n font-family:\n "Monaco",\n "Menlo",\n "Ubuntu Mono",\n "Consolas",\n monospace;\n color: #94a3b8;\n background: rgba(0, 0, 0, 0.3);\n padding: 4px 8px;\n border-radius: 4px;\n display: inline-block;\n margin-top: 4px;\n letter-spacing: 0.02em;\n}\n.bb-annotationHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n.bb-annotationActions {\n display: flex;\n gap: 4px;\n}\n.bb-annotationAction {\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 4px;\n border-radius: 2px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n}\n.bb-annotationAction--edit:hover {\n border-radius: 50%;\n background: rgba(59, 130, 246, 0.2);\n color: #3b82f6;\n}\n.bb-annotationAction--delete:hover {\n border-radius: 50%;\n background: rgba(239, 68, 68, 0.2);\n color: #ef4444;\n}\n.bb-editSpotOverlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n.bb-editSpotPopup {\n background:\n linear-gradient(\n 180deg,\n rgba(20, 27, 45, 0.98),\n rgba(25, 34, 57, 0.95)),\n #121826;\n border-radius: 8px;\n padding: 24px;\n min-width: 400px;\n max-width: 500px;\n border: 1px solid rgba(148, 163, 184, 0.18);\n box-shadow: 0 24px 48px rgba(15, 23, 42, 0.3);\n}\n.bb-editSpotHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n.bb-editSpotTitle {\n color: #f8fafc;\n font-size: 18px;\n font-weight: 600;\n margin: 0;\n}\n.bb-editSpotClose {\n background: none;\n border: none;\n color: #94a3b8;\n font-size: 24px;\n cursor: pointer;\n padding: 0 4px;\n transition: color 0.2s ease;\n}\n.bb-editSpotClose:hover {\n color: #f8fafc;\n}\n.bb-editSpotBody {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.bb-editSpotBody .bb-input,\n.bb-editSpotBody .bb-textarea {\n background: rgba(15, 23, 42, 0.4);\n border-color: rgba(148, 163, 184, 0.2);\n color: #f8fafc;\n}\n.bb-editSpotBody .bb-input:focus,\n.bb-editSpotBody .bb-textarea:focus {\n border-color: rgba(251, 191, 36, 0.65);\n box-shadow: 0 0 0 4px rgba(251, 191, 36, 0.12);\n}\n.bb-editSpotBody .bb-label {\n color: #d7dee9;\n}\n.bb-editSpotActions {\n display: flex;\n gap: 8px;\n margin-top: 8px;\n}\n.bb-editSpotActions .bb-button {\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(148, 163, 184, 0.18);\n color: #e5edf7;\n}\n.bb-editSpotActions .bb-button:hover {\n background: rgba(255, 255, 255, 0.08);\n border-color: rgba(148, 163, 184, 0.32);\n transform: translateY(-1px);\n}\n.bb-button--danger {\n background: #ef4444;\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: 7px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 700;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n}\n.bb-button--danger:hover {\n background: #dc2626;\n transform: translateY(-1px);\n box-shadow: 0 10px 18px rgba(239, 68, 68, 0.25);\n}\n.bb-button--primary {\n background: #135bc0;\n border-color: transparent;\n color: #ffffff;\n}\n.bb-button--primary:hover {\n background: #1a68d6;\n}\n.bb-annotationCard {\n background: rgba(15, 23, 42, 0.44);\n border-left: 4px solid #22d3ee;\n border-radius: 8px;\n padding: 16px;\n transition: all 0.2s ease;\n border: 1px solid rgba(148, 163, 184, 0.15);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\n}\n.bb-annotationCard:hover {\n transform: translateX(4px);\n background: rgba(15, 23, 42, 0.6);\n border-color: rgba(148, 163, 184, 0.25);\n box-shadow: 0 4px 12px rgba(15, 23, 42, 0.3);\n}\n.bb-annotationBadge {\n display: inline-block;\n background: #22d3ee;\n color: #06343c;\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.5px;\n margin-bottom: 12px;\n text-transform: uppercase;\n}\n.bb-annotationTitle {\n font-weight: 700;\n font-size: 15px;\n color: #f8fafc;\n margin-bottom: 8px;\n line-height: 1.3;\n}\n.bb-annotationDescription {\n font-size: 13px;\n color: #cbd5e1;\n margin-bottom: 12px;\n line-height: 1.5;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n.bb-annotationPosition {\n font-size: 11px;\n font-family:\n "Monaco",\n "Menlo",\n "Ubuntu Mono",\n "Consolas",\n monospace;\n color: #94a3b8;\n background: rgba(0, 0, 0, 0.3);\n padding: 4px 8px;\n border-radius: 4px;\n display: inline-block;\n margin-top: 4px;\n letter-spacing: 0.02em;\n}\n.bb-emptyAnnotations {\n padding: 32px;\n text-align: center;\n background: rgba(15, 23, 42, 0.44);\n border-radius: 10px;\n border: 1px solid rgba(148, 163, 184, 0.15);\n color: #94a3b8;\n font-size: 14px;\n}\n@media (max-width: 1280px) {\n .bb-cameraRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n .bb-cameraLabel {\n min-width: auto;\n }\n .bb-cameraControls {\n flex-direction: column;\n }\n .bb-cameraControls .bb-button {\n width: 100%;\n }\n}\n@media (max-width: 1120px) {\n .bb-sidebar--left {\n width: 320px;\n }\n .bb-sidebar--right {\n width: 220px;\n }\n .bb-grid {\n grid-template-columns: 1fr;\n }\n .bb-statRow {\n grid-template-columns: 1fr;\n }\n}\n@media (max-width: 980px) {\n .bb-root {\n flex-direction: column;\n height: auto;\n min-height: 0;\n }\n .bb-sidebar--left {\n width: 100% !important;\n max-height: 45vh;\n border-right: none;\n border-bottom: 1px solid rgba(148, 163, 184, 0.18);\n box-shadow: 0 18px 42px rgba(15, 23, 42, 0.12);\n }\n .bb-sidebar--right {\n width: 100% !important;\n max-height: 45vh;\n border-left: none;\n border-top: 1px solid rgba(148, 163, 184, 0.18);\n box-shadow: 0 -18px 42px rgba(15, 23, 42, 0.12);\n order: 3;\n }\n .bb-sidebar--collapsed {\n width: 100% !important;\n max-height: 72px;\n overflow: hidden;\n }\n .bb-sidebar--collapsed .bb-nodeList,\n .bb-sidebar--collapsed .bb-tabRow,\n .bb-sidebar--collapsed .bb-toolbar {\n display: none;\n }\n .bb-previewShell {\n flex: 1 1 auto;\n min-height: 50vh;\n padding: 14px;\n order: 2;\n }\n .bb-preview {\n min-height: 44vh;\n border-radius: 10px;\n }\n .bb-previewHeader {\n flex-direction: column;\n align-items: flex-start;\n gap: 12px;\n }\n .bb-previewControls {\n width: 100%;\n justify-content: flex-start;\n flex-wrap: wrap;\n }\n .bb-previewMeta {\n justify-content: flex-start;\n }\n .bb-previewMeta span {\n font-size: 11px;\n padding: 0 10px;\n min-height: 30px;\n }\n .bb-grid,\n .bb-actionGrid,\n .bb-statRow {\n grid-template-columns: 1fr;\n }\n .bb-editor {\n padding: 12px 12px 20px;\n }\n .bb-editorHeader {\n flex-direction: column;\n align-items: stretch;\n padding: 14px;\n }\n .bb-editorTitle {\n font-size: 20px;\n }\n .bb-editorBadge {\n align-self: flex-start;\n }\n .bb-toolbar {\n flex-direction: column;\n gap: 12px;\n padding: 16px 20px 18px;\n }\n .bb-toolbarDivider {\n width: 100%;\n height: 1px;\n margin: 0;\n }\n .bb-tabRow {\n padding: 12px 16px 0;\n gap: 6px;\n }\n .bb-tab {\n font-size: 10px;\n padding: 8px 10px;\n }\n .bb-header {\n padding: 14px 16px 12px;\n }\n .bb-header--sidebar {\n min-height: 60px;\n }\n .bb-title {\n font-size: 17px;\n }\n .bb-subtitle {\n font-size: 13px;\n }\n .bb-statChip {\n padding: 10px 12px;\n }\n .bb-statChip strong {\n font-size: 12px;\n }\n .bb-nodeButton {\n padding: 10px 12px;\n }\n .bb-nodeName {\n font-size: 12px;\n }\n .bb-nodeMeta {\n font-size: 10px;\n }\n .bb-section {\n padding: 14px;\n }\n .bb-sectionTitle {\n font-size: 9px;\n }\n .bb-field {\n gap: 4px;\n }\n .bb-label {\n font-size: 11px;\n }\n .bb-input,\n .bb-select,\n .bb-textarea {\n padding: 9px 11px;\n font-size: 12px;\n }\n .bb-textarea {\n min-height: 80px;\n }\n .bb-button,\n .bb-fileLabel {\n min-height: 36px;\n padding: 0 14px;\n font-size: 12px;\n }\n .bb-previewPlaceholderTitle {\n font-size: 22px;\n }\n .bb-previewPlaceholderButton {\n padding: 10px 18px;\n font-size: 13px;\n }\n .bb-editSpotPopup {\n min-width: 90%;\n max-width: 90%;\n padding: 20px;\n }\n .bb-modal {\n width: 95%;\n max-width: 95%;\n }\n .bb-annotationCard {\n padding: 12px;\n }\n .bb-annotationTitle {\n font-size: 14px;\n }\n .bb-annotationDescription {\n font-size: 12px;\n }\n}\n@media (max-width: 640px) {\n .bb-root {\n flex-direction: column;\n height: auto;\n min-height: 0;\n }\n .bb-sidebar--left {\n max-height: 40vh;\n width: 100% !important;\n }\n .bb-sidebar--right {\n max-height: 40vh;\n width: 100% !important;\n }\n .bb-previewShell {\n min-height: 40vh;\n padding: 10px;\n }\n .bb-preview {\n min-height: 35vh;\n border-radius: 8px;\n }\n .bb-previewHeader {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n padding: 0 0 12px;\n }\n .bb-previewTitle {\n font-size: 17px;\n }\n .bb-previewControls {\n gap: 6px;\n }\n .bb-previewMeta span {\n font-size: 10px;\n padding: 0 8px;\n min-height: 26px;\n }\n .bb-editor {\n padding: 10px 10px 16px;\n }\n .bb-editorHeader {\n padding: 12px;\n flex-direction: column;\n align-items: stretch;\n }\n .bb-editorTitle {\n font-size: 18px;\n }\n .bb-editorMeta {\n font-size: 11px;\n gap: 6px 8px;\n }\n .bb-editorBadge {\n font-size: 9px;\n padding: 4px 10px;\n align-self: flex-start;\n }\n .bb-section {\n padding: 12px;\n margin-bottom: 12px;\n }\n .bb-sectionTitle {\n font-size: 9px;\n margin-bottom: 10px;\n }\n .bb-grid {\n gap: 8px;\n }\n .bb-field--full {\n grid-column: 1 / -1;\n }\n .bb-label {\n font-size: 11px;\n }\n .bb-input,\n .bb-select,\n .bb-textarea {\n padding: 8px 10px;\n font-size: 12px;\n border-radius: 6px;\n }\n .bb-textarea {\n min-height: 70px;\n }\n .bb-button,\n .bb-fileLabel {\n min-height: 34px;\n padding: 0 12px;\n font-size: 11px;\n border-radius: 6px;\n }\n .bb-toolbar {\n padding: 12px 14px 14px;\n gap: 10px;\n }\n .bb-tabRow {\n padding: 10px 12px 0;\n gap: 4px;\n }\n .bb-tab {\n font-size: 9px;\n padding: 6px 8px;\n border-radius: 4px;\n }\n .bb-header {\n padding: 10px 12px 8px;\n }\n .bb-header--sidebar {\n min-height: 52px;\n }\n .bb-title {\n font-size: 15px;\n }\n .bb-subtitle {\n font-size: 12px;\n }\n .bb-eyebrow {\n font-size: 9px;\n padding: 4px 8px;\n margin-bottom: 8px;\n }\n .bb-statRow {\n gap: 6px;\n margin-top: 14px;\n }\n .bb-statChip {\n padding: 8px 10px;\n border-radius: 6px;\n }\n .bb-statChip strong {\n font-size: 11px;\n }\n .bb-statLabel {\n font-size: 9px;\n }\n .bb-sidebarToggle {\n width: 30px;\n height: 30px;\n font-size: 14px;\n border-radius: 5px;\n }\n .bb-nodeItems {\n padding: 4px 6px;\n }\n .bb-nodeButton {\n padding: 8px 10px;\n border-radius: 6px;\n margin-bottom: 4px;\n }\n .bb-nodeName {\n font-size: 11px;\n }\n .bb-nodeMeta {\n font-size: 10px;\n }\n .bb-search {\n padding: 8px 10px;\n }\n .bb-statusCard {\n padding: 10px 12px;\n border-radius: 7px;\n }\n .bb-status {\n font-size: 12px;\n }\n .bb-statusTitle {\n font-size: 10px;\n }\n .bb-checkboxRow {\n gap: 6px;\n }\n .bb-checkbox {\n padding: 6px 10px;\n font-size: 12px;\n border-radius: 5px;\n }\n .bb-actionCard {\n padding: 10px;\n border-radius: 7px;\n }\n .bb-actionCardTitle {\n font-size: 12px;\n }\n .bb-actionCardMeta {\n font-size: 9px;\n padding: 3px 7px;\n }\n .bb-previewPlaceholder {\n padding: 24px;\n border-radius: 8px;\n }\n .bb-previewPlaceholderTitle {\n font-size: 18px;\n }\n .bb-previewPlaceholderButton {\n padding: 8px 14px;\n font-size: 12px;\n border-radius: 999px;\n }\n .bb-editSpotPopup {\n min-width: 95%;\n max-width: 95%;\n padding: 16px;\n border-radius: 6px;\n }\n .bb-editSpotTitle {\n font-size: 16px;\n }\n .bb-editSpotActions .bb-button {\n padding: 8px 12px;\n font-size: 12px;\n }\n .bb-modal {\n width: 98%;\n max-width: 98%;\n border-radius: 5px;\n }\n .bb-modalHeader {\n padding: 12px 16px;\n }\n .bb-modalHeader h3 {\n font-size: 16px;\n }\n .bb-modalBody {\n padding: 14px;\n }\n .bb-modalFooter {\n padding: 12px 16px;\n flex-direction: column;\n gap: 8px;\n }\n .bb-modalFooter .bb-button {\n width: 100%;\n justify-content: center;\n }\n .bb-annotationCard {\n padding: 10px;\n border-left-width: 3px;\n border-radius: 6px;\n }\n .bb-annotationTitle {\n font-size: 13px;\n }\n .bb-annotationDescription {\n font-size: 11px;\n }\n .bb-annotationPosition {\n font-size: 10px;\n padding: 3px 6px;\n }\n .bb-annotationBadge {\n font-size: 9px;\n padding: 2px 8px;\n }\n .bb-emptyAnnotations {\n padding: 20px;\n font-size: 12px;\n border-radius: 7px;\n }\n .bb-removeModelButton {\n min-height: 30px;\n padding: 0 10px;\n font-size: 11px;\n }\n .bb-annotationsList {\n gap: 8px;\n }\n .bb-cameraLive,\n .bb-cameraSaved {\n padding: 10px;\n border-radius: 6px;\n }\n .bb-cameraLiveHeader,\n .bb-cameraSavedHeader {\n flex-wrap: wrap;\n }\n .bb-cameraLiveLabel,\n .bb-cameraSavedLabel {\n font-size: 11px;\n }\n .bb-cameraRow {\n font-size: 11px;\n gap: 4px;\n }\n .bb-cameraCode {\n font-size: 10px;\n padding: 2px 6px;\n }\n .bb-cameraControls {\n flex-direction: column;\n gap: 6px;\n }\n .bb-cameraControls .bb-button {\n width: 100%;\n justify-content: center;\n }\n .bb-cameraMessage {\n font-size: 11px;\n padding: 8px 12px;\n }\n .bb-readonly {\n font-size: 11px;\n padding: 6px 8px;\n }\n}\n@media (max-width: 420px) {\n .bb-sidebar--left {\n max-height: 35vh;\n }\n .bb-sidebar--right {\n max-height: 35vh;\n }\n .bb-previewShell {\n min-height: 35vh;\n padding: 6px;\n }\n .bb-preview {\n min-height: 30vh;\n border-radius: 6px;\n }\n .bb-previewTitle {\n font-size: 15px;\n }\n .bb-previewMeta span {\n font-size: 9px;\n padding: 0 6px;\n min-height: 22px;\n }\n .bb-editorTitle {\n font-size: 16px;\n }\n .bb-title {\n font-size: 13px;\n }\n .bb-tab {\n font-size: 8px;\n padding: 5px 6px;\n }\n .bb-button,\n .bb-fileLabel {\n font-size: 10px;\n min-height: 30px;\n padding: 0 10px;\n }\n .bb-input,\n .bb-select,\n .bb-textarea {\n font-size: 11px;\n padding: 6px 8px;\n }\n .bb-statChip {\n padding: 6px 8px;\n }\n .bb-statChip strong {\n font-size: 10px;\n }\n .bb-previewPlaceholderTitle {\n font-size: 15px;\n }\n .bb-previewPlaceholderButton {\n font-size: 11px;\n padding: 6px 12px;\n }\n .bb-editSpotPopup {\n padding: 14px;\n border-radius: 5px;\n }\n .bb-editSpotTitle {\n font-size: 14px;\n }\n .bb-editSpotBody .bb-input,\n .bb-editSpotBody .bb-textarea {\n font-size: 12px;\n padding: 6px 8px;\n }\n .bb-modalHeader h3 {\n font-size: 14px;\n }\n .bb-annotationTitle {\n font-size: 12px;\n }\n}\n@media (max-width: 980px) {\n .bb-sidebar--collapsed .bb-header--sidebar {\n min-height: 52px;\n }\n .bb-sidebar--collapsed .bb-title {\n font-size: 14px;\n }\n .bb-sidebar--collapsed .bb-sidebarToggle {\n width: 28px;\n height: 28px;\n font-size: 12px;\n }\n}\n@media (hover: none) and (pointer: coarse) {\n .bb-nodeButton:hover,\n .bb-button:hover,\n .bb-fileLabel:hover,\n .bb-tab:hover,\n .bb-sidebarToggle:hover,\n .bb-annotationCard:hover {\n transform: none;\n }\n .bb-nodeButton:active,\n .bb-button:active,\n .bb-fileLabel:active,\n .bb-tab:active,\n .bb-sidebarToggle:active {\n transform: scale(0.97);\n transition: transform 0.1s ease;\n }\n}\n@media print {\n .bb-root {\n height: auto;\n min-height: 0;\n background: white;\n }\n .bb-sidebar--left,\n .bb-sidebar--right {\n width: 100% !important;\n max-height: none !important;\n background: white !important;\n color: black !important;\n border: 1px solid #ddd !important;\n box-shadow: none !important;\n }\n .bb-previewShell {\n min-height: auto !important;\n padding: 10px !important;\n }\n .bb-preview {\n min-height: auto !important;\n border-radius: 4px !important;\n border: 1px solid #ddd !important;\n box-shadow: none !important;\n }\n .bb-button,\n .bb-fileLabel,\n .bb-sidebarToggle,\n .bb-tab,\n .bb-annotationAction,\n .bb-iconButton {\n display: none !important;\n }\n .bb-nodeList {\n overflow: visible !important;\n }\n .bb-previewPlaceholderButton {\n display: none !important;\n }\n}\n.bb-checkboxRow {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n align-items: center;\n padding: 4px 0;\n}\n.bb-checkbox {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border-radius: 7px;\n font-weight: 600;\n font-size: 13px;\n color: #f3eeee;\n cursor: pointer;\n user-select: none;\n transition: all 0.2s ease;\n}\n.bb-checkbox input[type=checkbox] {\n width: 16px;\n height: 16px;\n accent-color: #f59e0b;\n cursor: pointer;\n flex-shrink: 0;\n}\n.bb-editorDivider {\n height: 1px;\n background: rgba(148, 163, 184, 0.14);\n margin: 4px 0 16px 0;\n width: 100%;\n}\n.bb-preview {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.ri-viewer {\n width: 100% !important;\n height: 100% !important;\n position: relative !important;\n}\n.ri-buttonContainer {\n position: absolute !important;\n bottom: 20px !important;\n right: 20px !important;\n z-index: 10000 !important;\n display: flex !important;\n gap: 10px !important;\n pointer-events: auto !important;\n}\n.ri-downloadButton {\n display: flex !important;\n align-items: center !important;\n gap: 6px !important;\n padding: 10px 12px !important;\n background: #2f302f74 !important;\n color: white !important;\n border: none !important;\n border-radius: 6px !important;\n cursor: pointer !important;\n font-size: 12px !important;\n font-weight: 500 !important;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;\n opacity: 1 !important;\n visibility: visible !important;\n}\n.ri-downloadButton svg {\n width: 14px !important;\n height: 14px !important;\n}\n.ri-resetButton {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n padding: 6px !important;\n background: #2f302f74 !important;\n border: none !important;\n border-radius: 6px !important;\n cursor: pointer !important;\n opacity: 1 !important;\n visibility: visible !important;\n}\n.ri-resetButton svg {\n width: 14px !important;\n height: 14px !important;\n}\n.bb-reset-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n backdrop-filter: blur(4px);\n animation: bb-fade-in 0.2s ease;\n}\n.bb-reset-dialog {\n background: #1a1f2e;\n border-radius: 12px;\n max-width: 480px;\n width: 90%;\n border: 1px solid rgba(148, 163, 184, 0.18);\n box-shadow: 0 24px 48px rgba(0, 0, 0, 0.5);\n animation: bb-slide-up 0.25s ease;\n}\n.bb-reset-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px 16px;\n border-bottom: 1px solid rgba(148, 163, 184, 0.1);\n}\n.bb-reset-title {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n color: #f8fafc;\n}\n.bb-reset-title .bb-icon-warning {\n color: #f59e0b;\n flex-shrink: 0;\n}\n.bb-reset-close {\n background: transparent;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bb-reset-close:hover {\n color: #f8fafc;\n background: rgba(255, 255, 255, 0.06);\n}\n.bb-reset-body {\n padding: 20px 24px 24px;\n}\n.bb-reset-message {\n margin: 0 0 12px 0;\n font-size: 15px;\n color: #e2e8f0;\n line-height: 1.5;\n}\n.bb-reset-message strong {\n color: #f8fafc;\n}\n.bb-reset-details {\n color: #94a3b8;\n text-align: center;\n font-size: 13px;\n line-height: 1.6;\n margin: 0 0 12px 0;\n}\n.bb-reset-warning {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #f59e0b;\n font-size: 13px;\n font-weight: 600;\n margin: 4px 0 0 0;\n padding: 10px 12px;\n background: rgba(245, 158, 11, 0.08);\n border-radius: 6px;\n border: 1px solid rgba(245, 158, 11, 0.15);\n}\n.bb-reset-footer {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n padding: 16px 24px 20px;\n border-top: 1px solid rgba(148, 163, 184, 0.1);\n}\n.bb-reset-btn {\n padding: 8px 20px;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 1px solid rgba(148, 163, 184, 0.18);\n background: rgba(255, 255, 255, 0.04);\n color: #e2e8f0;\n}\n.bb-reset-btn:hover {\n background: rgba(255, 255, 255, 0.08);\n transform: translateY(-1px);\n}\n.bb-reset-btn-danger {\n padding: 8px 20px;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n border: none;\n background: #dc2626;\n color: white;\n}\n.bb-reset-btn-danger:hover {\n background: #b91c1c;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3);\n}\n@keyframes bb-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes bb-slide-up {\n from {\n opacity: 0;\n transform: translateY(20px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n');
7162
7261
 
7163
7262
  // src/hooks/useViewerCamera.ts
7164
- import { useCallback as useCallback5, useRef as useRef11, useState as useState11 } from "react";
7263
+ import { useCallback as useCallback5, useRef as useRef12, useState as useState11 } from "react";
7165
7264
  import { Vector3 as Vector38 } from "three";
7166
7265
 
7167
7266
  // src/utils/resolveBindingKey.ts
@@ -7213,7 +7312,7 @@ async function runSmoothCameraTransition2(controls, action, smoothTime = 0.6) {
7213
7312
  }
7214
7313
  }
7215
7314
  function useViewerCamera() {
7216
- const viewerRef = useRef11(null);
7315
+ const viewerRef = useRef12(null);
7217
7316
  const [cameraState, setCameraStateValue] = useState11(
7218
7317
  null
7219
7318
  );
@@ -7228,8 +7327,8 @@ function useViewerCamera() {
7228
7327
  },
7229
7328
  [updateCameraState]
7230
7329
  );
7231
- const homeCameraStateRef = useRef11(null);
7232
- const homeSceneRef = useRef11(null);
7330
+ const homeCameraStateRef = useRef12(null);
7331
+ const homeSceneRef = useRef12(null);
7233
7332
  const handleViewerReady = useCallback5((viewer) => {
7234
7333
  viewerRef.current = viewer;
7235
7334
  updateCameraState(buildCameraState(viewer.controls.camera, viewer.controls));
@@ -7399,11 +7498,11 @@ function useViewerCamera() {
7399
7498
  }
7400
7499
 
7401
7500
  // src/hooks/useViewerAnimations.ts
7402
- import { useCallback as useCallback6, useEffect as useEffect15, useRef as useRef12, useState as useState12 } from "react";
7501
+ import { useCallback as useCallback6, useEffect as useEffect15, useRef as useRef13, useState as useState12 } from "react";
7403
7502
  function useViewerAnimations() {
7404
- const controlsRef = useRef12(null);
7503
+ const controlsRef = useRef13(null);
7405
7504
  const [clips, setClips] = useState12([]);
7406
- const unsubscribeRef = useRef12(null);
7505
+ const unsubscribeRef = useRef13(null);
7407
7506
  const [clipDetails, setClipDetails] = useState12([]);
7408
7507
  const [currentClip, setCurrentClip] = useState12(null);
7409
7508
  const [isPlaying, setIsPlaying] = useState12(false);
@@ -7685,7 +7784,7 @@ import {
7685
7784
  import { HexColorInput as HexColorInput2, HexColorPicker as HexColorPicker3 } from "react-colorful";
7686
7785
 
7687
7786
  // src/components/BindingBuilder/SceneSettings/SceneControls.tsx
7688
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef13, useState as useState13 } from "react";
7787
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef14, useState as useState13 } from "react";
7689
7788
  import { createPortal as createPortal2 } from "react-dom";
7690
7789
  import { ChevronDown, Info } from "lucide-react";
7691
7790
  import { HexColorInput, HexColorPicker as HexColorPicker2 } from "react-colorful";
@@ -7726,7 +7825,7 @@ function ColorPopover({
7726
7825
  onClose,
7727
7826
  children
7728
7827
  }) {
7729
- const popoverRef = useRef13(null);
7828
+ const popoverRef = useRef14(null);
7730
7829
  const [position, setPosition] = useState13(null);
7731
7830
  useClickOutside([popoverRef, anchorRef], onClose, true);
7732
7831
  useLayoutEffect2(() => {
@@ -7922,7 +8021,7 @@ function ColorRow({
7922
8021
  onChange
7923
8022
  }) {
7924
8023
  const [open, setOpen] = useState13(false);
7925
- const anchorRef = useRef13(null);
8024
+ const anchorRef = useRef14(null);
7926
8025
  return /* @__PURE__ */ jsxs16("div", { className: "se-field", children: [
7927
8026
  /* @__PURE__ */ jsxs16("div", { className: "se-fieldInline", children: [
7928
8027
  /* @__PURE__ */ jsx20("span", { className: "se-fieldLabel", children: label }),
@@ -8046,7 +8145,7 @@ function TierLock({
8046
8145
  }
8047
8146
 
8048
8147
  // src/components/BindingBuilder/SceneSettings/GeneralSceneSettings.tsx
8049
- import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8148
+ import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8050
8149
  var SHADING_OPTIONS = ["lit", "unlit", "normals"];
8051
8150
  var BACKGROUND_TYPES = ["color", "image", "environment"];
8052
8151
  function normalizeRotation(value) {
@@ -8251,7 +8350,7 @@ function GeneralSceneSettings({ config, onChange }) {
8251
8350
  ),
8252
8351
  /* @__PURE__ */ jsx22("span", { className: "se-switchTrack", children: /* @__PURE__ */ jsx22("span", { className: "se-switchThumb" }) })
8253
8352
  ] }),
8254
- children: canUseStarterFeatures ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
8353
+ children: canUseStarterFeatures ? /* @__PURE__ */ jsxs18(Fragment8, { children: [
8255
8354
  /* @__PURE__ */ jsx22(
8256
8355
  SliderRow,
8257
8356
  {
@@ -8291,7 +8390,7 @@ function GeneralSceneSettings({ config, onChange }) {
8291
8390
  ),
8292
8391
  /* @__PURE__ */ jsx22("span", { className: "se-switchTrack", children: /* @__PURE__ */ jsx22("span", { className: "se-switchThumb" }) })
8293
8392
  ] }),
8294
- children: background.enabled ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
8393
+ children: background.enabled ? /* @__PURE__ */ jsxs18(Fragment8, { children: [
8295
8394
  /* @__PURE__ */ jsxs18("div", { className: "se-field", children: [
8296
8395
  /* @__PURE__ */ jsx22("span", { className: "se-fieldLabel", children: "Background type" }),
8297
8396
  /* @__PURE__ */ jsx22("div", { className: "se-segmentedControl", children: BACKGROUND_TYPES.map((type) => /* @__PURE__ */ jsx22(
@@ -8311,7 +8410,7 @@ function GeneralSceneSettings({ config, onChange }) {
8311
8410
  requiredTier: "starter",
8312
8411
  feature: "Environment backgrounds"
8313
8412
  }
8314
- ) : /* @__PURE__ */ jsxs18(Fragment7, { children: [
8413
+ ) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
8315
8414
  /* @__PURE__ */ jsxs18("div", { className: "se-field", children: [
8316
8415
  /* @__PURE__ */ jsx22("span", { className: "se-fieldLabel", children: "Environment source" }),
8317
8416
  /* @__PURE__ */ jsxs18("div", { className: "se-segmentedControl", children: [
@@ -10329,7 +10428,7 @@ function PostProcessingTab({ config, onChange }) {
10329
10428
  // src/components/BindingBuilder/SceneSettings/LightingTab.tsx
10330
10429
  import { useState as useState16 } from "react";
10331
10430
  import { Eye, EyeOff, Plus, Trash2 } from "lucide-react";
10332
- import { Fragment as Fragment8, jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
10431
+ import { Fragment as Fragment9, jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
10333
10432
  var SHADOW_MAP_SIZES = ["512", "1024", "2048", "4096"];
10334
10433
  var LIGHT_TYPE_LABELS = {
10335
10434
  none: "None",
@@ -10698,7 +10797,7 @@ function LightingTab({ config, onChange }) {
10698
10797
  title: "Environment",
10699
10798
  open: open.environment,
10700
10799
  onToggle: () => toggleOpen("environment"),
10701
- children: !canUseStarterFeatures ? /* @__PURE__ */ jsx28(TierLock, { requiredTier: "starter", feature: "Environment lighting" }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
10800
+ children: !canUseStarterFeatures ? /* @__PURE__ */ jsx28(TierLock, { requiredTier: "starter", feature: "Environment lighting" }) : /* @__PURE__ */ jsxs24(Fragment9, { children: [
10702
10801
  /* @__PURE__ */ jsx28(
10703
10802
  SliderRow,
10704
10803
  {
@@ -11711,7 +11810,7 @@ function MaterialPanelGroup({
11711
11810
  }
11712
11811
 
11713
11812
  // src/components/BindingBuilder/components/MaterialFields.tsx
11714
- import { useRef as useRef14, useState as useState20 } from "react";
11813
+ import { useRef as useRef15, useState as useState20 } from "react";
11715
11814
  import { HexColorInput as HexColorInput3, HexColorPicker as HexColorPicker4 } from "react-colorful";
11716
11815
  import { FileUp } from "lucide-react";
11717
11816
  import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
@@ -11721,7 +11820,7 @@ function MaterialTexturePathField({
11721
11820
  placeholder,
11722
11821
  onChange
11723
11822
  }) {
11724
- const inputRef = useRef14(null);
11823
+ const inputRef = useRef15(null);
11725
11824
  return /* @__PURE__ */ jsxs30("div", { className: "bb-field bb-field--full", children: [
11726
11825
  /* @__PURE__ */ jsx35("label", { className: "bb-label", children: label }),
11727
11826
  /* @__PURE__ */ jsxs30("div", { className: "bb-fileField", children: [
@@ -11780,7 +11879,7 @@ function MaterialColorField({
11780
11879
  }) {
11781
11880
  const [open, setOpen] = useState20(false);
11782
11881
  const color = value || fallback;
11783
- const anchorRef = useRef14(null);
11882
+ const anchorRef = useRef15(null);
11784
11883
  return /* @__PURE__ */ jsxs30("div", { className: "bb-field", children: [
11785
11884
  /* @__PURE__ */ jsx35("span", { className: "bb-label", children: label }),
11786
11885
  /* @__PURE__ */ jsx35("div", { className: "se-fieldInline", children: /* @__PURE__ */ jsx35("span", { ref: anchorRef, style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx35(
@@ -11907,7 +12006,7 @@ function MaterialSliderField({
11907
12006
  }
11908
12007
 
11909
12008
  // src/components/BindingBuilder/components/MaterialSection.tsx
11910
- import { Fragment as Fragment9, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
12009
+ import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
11911
12010
  function MaterialSection({
11912
12011
  selectedItem,
11913
12012
  selectedMaterial,
@@ -11936,7 +12035,7 @@ function MaterialSection({
11936
12035
  const [anisotropyMode, setAnisotropyMode] = useState21(
11937
12036
  "factor"
11938
12037
  );
11939
- return /* @__PURE__ */ jsxs31(Fragment9, { children: [
12038
+ return /* @__PURE__ */ jsxs31(Fragment10, { children: [
11940
12039
  /* @__PURE__ */ jsx36(
11941
12040
  MaterialPanelGroup,
11942
12041
  {
@@ -11975,7 +12074,7 @@ function MaterialSection({
11975
12074
  }))
11976
12075
  }
11977
12076
  ),
11978
- pbrWorkflow === "metalness" ? /* @__PURE__ */ jsxs31(Fragment9, { children: [
12077
+ pbrWorkflow === "metalness" ? /* @__PURE__ */ jsxs31(Fragment10, { children: [
11979
12078
  /* @__PURE__ */ jsx36(
11980
12079
  MaterialSliderField,
11981
12080
  {
@@ -11999,7 +12098,7 @@ function MaterialSection({
11999
12098
  onChange: (value) => setSelectedTexturePath(selectedItem, "metalnessMap", value)
12000
12099
  }
12001
12100
  )
12002
- ] }) : /* @__PURE__ */ jsxs31(Fragment9, { children: [
12101
+ ] }) : /* @__PURE__ */ jsxs31(Fragment10, { children: [
12003
12102
  /* @__PURE__ */ jsx36(
12004
12103
  MaterialSliderField,
12005
12104
  {
@@ -12972,7 +13071,7 @@ function MaterialPresetGallery({
12972
13071
  }
12973
13072
 
12974
13073
  // src/components/BindingBuilder/components/ToolbarExportMenu.tsx
12975
- import { useEffect as useEffect18, useRef as useRef15, useState as useState22 } from "react";
13074
+ import { useEffect as useEffect18, useRef as useRef16, useState as useState22 } from "react";
12976
13075
  import { ChevronDown as ChevronDown5, Download as Download2, FileCode2, FileJson } from "lucide-react";
12977
13076
  import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
12978
13077
  function ToolbarExportMenu({
@@ -12982,7 +13081,7 @@ function ToolbarExportMenu({
12982
13081
  onExportTs
12983
13082
  }) {
12984
13083
  const [open, setOpen] = useState22(false);
12985
- const wrapperRef = useRef15(null);
13084
+ const wrapperRef = useRef16(null);
12986
13085
  useEffect18(() => {
12987
13086
  if (!open) return;
12988
13087
  const close = (event) => {
@@ -13315,7 +13414,7 @@ function ActionsPanel({
13315
13414
 
13316
13415
  // src/components/BindingBuilder/components/CameraPositionPanel.tsx
13317
13416
  import { MapPin as MapPin3, Trash2 as Trash25 } from "lucide-react";
13318
- import { Fragment as Fragment10, jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
13417
+ import { Fragment as Fragment11, jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
13319
13418
  function CameraPositionPanel({
13320
13419
  selectedBinding,
13321
13420
  open,
@@ -13334,7 +13433,7 @@ function CameraPositionPanel({
13334
13433
  /* @__PURE__ */ jsx42("span", { className: "bb-cameraLiveBadge", children: "LIVE" }),
13335
13434
  /* @__PURE__ */ jsxs37("div", { className: "se-waypointBody", children: [
13336
13435
  /* @__PURE__ */ jsx42("div", { className: "bb-cameraWaypointLabel", children: "Current view" }),
13337
- cameraState ? /* @__PURE__ */ jsxs37(Fragment10, { children: [
13436
+ cameraState ? /* @__PURE__ */ jsxs37(Fragment11, { children: [
13338
13437
  /* @__PURE__ */ jsxs37("div", { className: "se-waypointCoords", children: [
13339
13438
  "pos ",
13340
13439
  formattedCameraState?.position
@@ -13538,7 +13637,7 @@ function collectModelMetadata(modelUrl) {
13538
13637
  }
13539
13638
 
13540
13639
  // src/components/BindingBuilder/components/SceneNodesPanel.tsx
13541
- import { Fragment as Fragment11, jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
13640
+ import { Fragment as Fragment12, jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
13542
13641
  function SceneNodesPanel({
13543
13642
  bindings,
13544
13643
  selectedItem,
@@ -13574,7 +13673,7 @@ function SceneNodesPanel({
13574
13673
  children: "\u2190"
13575
13674
  }
13576
13675
  ),
13577
- isOpen && /* @__PURE__ */ jsxs38(Fragment11, { children: [
13676
+ isOpen && /* @__PURE__ */ jsxs38(Fragment12, { children: [
13578
13677
  /* @__PURE__ */ jsxs38("div", { children: [
13579
13678
  /* @__PURE__ */ jsx43("div", { className: "bb-sectionKicker", children: "Scene Nodes" }),
13580
13679
  /* @__PURE__ */ jsxs38("div", { className: "bb-sectionHeading", children: [
@@ -13692,7 +13791,7 @@ function mergeAnimationConfig(sceneConfig, animationDetails) {
13692
13791
  }
13693
13792
 
13694
13793
  // src/components/BindingBuilder/hooks/useUndoableState.ts
13695
- import { useCallback as useCallback7, useReducer, useRef as useRef16 } from "react";
13794
+ import { useCallback as useCallback7, useReducer, useRef as useRef17 } from "react";
13696
13795
  var MAX_HISTORY = 100;
13697
13796
  function historyReducer(state, action) {
13698
13797
  switch (action.type) {
@@ -13736,7 +13835,7 @@ function useUndoableState(initial, coalesceWindowMs = 600) {
13736
13835
  present: initial,
13737
13836
  future: []
13738
13837
  });
13739
- const lastSetAt = useRef16(0);
13838
+ const lastSetAt = useRef17(0);
13740
13839
  const setValue = useCallback7(
13741
13840
  (updater) => {
13742
13841
  const now = Date.now();
@@ -13983,7 +14082,7 @@ function removeMaterialPanelFields(material, panel) {
13983
14082
  }
13984
14083
 
13985
14084
  // src/components/BindingBuilder/BindingBuilder.tsx
13986
- import { Fragment as Fragment12, jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
14085
+ import { Fragment as Fragment13, jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
13987
14086
  var DEMO_MODEL_URL = "/room.glb";
13988
14087
  function isPlainObject(value) {
13989
14088
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -14000,9 +14099,9 @@ function mergeSceneConfigSection(current, incoming) {
14000
14099
  return next;
14001
14100
  }
14002
14101
  function BindingBuilder({ licenseKey }) {
14003
- const modelInputRef = useRef17(null);
14004
- const bindingsInputRef = useRef17(null);
14005
- const sceneConfigInputRef = useRef17(null);
14102
+ const modelInputRef = useRef18(null);
14103
+ const bindingsInputRef = useRef18(null);
14104
+ const sceneConfigInputRef = useRef18(null);
14006
14105
  const [modelUrl, setModelUrl] = useState24(null);
14007
14106
  const [modelName, setModelName] = useState24("");
14008
14107
  const [selectedItem, setSelectedItem] = useState24(null);
@@ -14054,7 +14153,7 @@ function BindingBuilder({ licenseKey }) {
14054
14153
  const [activeSubTab, setActiveSubTab] = useState24("General");
14055
14154
  const [pbrWorkflow, setPbrWorkflow] = useState24("metalness");
14056
14155
  const [materialPanelEnabled, setMaterialPanelEnabled] = useState24(createMaterialPanelEnabledState());
14057
- const materialPanelItemRef = useRef17(null);
14156
+ const materialPanelItemRef = useRef18(null);
14058
14157
  const [zoomOnSelected, setZoomOnSelected] = useState24(false);
14059
14158
  const [highlightOnHover, setHighlightOnHover] = useState24(true);
14060
14159
  const [resetDialogOpen, setResetDialogOpen] = useState24(false);
@@ -14077,9 +14176,9 @@ function BindingBuilder({ licenseKey }) {
14077
14176
  }),
14078
14177
  [activeEditorTab, activeSubTab, tier]
14079
14178
  );
14080
- const uploadedModelRef = useRef17(null);
14081
- const previewDragDepthRef = useRef17(0);
14082
- const loadRequestRef = useRef17(0);
14179
+ const uploadedModelRef = useRef18(null);
14180
+ const previewDragDepthRef = useRef18(0);
14181
+ const loadRequestRef = useRef18(0);
14083
14182
  const {
14084
14183
  cameraState,
14085
14184
  resetView,
@@ -14734,7 +14833,7 @@ function BindingBuilder({ licenseKey }) {
14734
14833
  }
14735
14834
  )
14736
14835
  ] }),
14737
- !isEditorCollapsed && /* @__PURE__ */ jsxs40(Fragment12, { children: [
14836
+ !isEditorCollapsed && /* @__PURE__ */ jsxs40(Fragment13, { children: [
14738
14837
  /* @__PURE__ */ jsxs40("div", { className: "bb-tabRow", children: [
14739
14838
  /* @__PURE__ */ jsx45(
14740
14839
  "button",
@@ -14755,7 +14854,7 @@ function BindingBuilder({ licenseKey }) {
14755
14854
  }
14756
14855
  )
14757
14856
  ] }),
14758
- /* @__PURE__ */ jsx45("section", { className: "bb-editor", children: activeEditorTab === "scene" ? /* @__PURE__ */ jsx45(Fragment12, { children: modelUrl ? /* @__PURE__ */ jsx45(
14857
+ /* @__PURE__ */ jsx45("section", { className: "bb-editor", children: activeEditorTab === "scene" ? /* @__PURE__ */ jsx45(Fragment13, { children: modelUrl ? /* @__PURE__ */ jsx45(
14759
14858
  SceneSettingsTab,
14760
14859
  {
14761
14860
  config: sceneConfig,
@@ -14775,7 +14874,7 @@ function BindingBuilder({ licenseKey }) {
14775
14874
  animationClipDetails: viewerAnimations.clipDetails,
14776
14875
  animationPlayback: viewerAnimations
14777
14876
  }
14778
- ) : /* @__PURE__ */ jsx45("div", { className: "bb-emptyEditor", children: "Upload a model to edit its scene settings." }) }) : !selectedBinding || !selectedItem ? /* @__PURE__ */ jsx45("div", { className: "bb-emptyEditor", children: "Select a generated node binding to edit its values." }) : /* @__PURE__ */ jsxs40(Fragment12, { children: [
14877
+ ) : /* @__PURE__ */ jsx45("div", { className: "bb-emptyEditor", children: "Upload a model to edit its scene settings." }) }) : !selectedBinding || !selectedItem ? /* @__PURE__ */ jsx45("div", { className: "bb-emptyEditor", children: "Select a generated node binding to edit its values." }) : /* @__PURE__ */ jsxs40(Fragment13, { children: [
14779
14878
  /* @__PURE__ */ jsx45("div", { className: "bb-editorHeader", children: /* @__PURE__ */ jsxs40("div", { children: [
14780
14879
  /* @__PURE__ */ jsx45("div", { className: "bb-sectionKicker", children: "Editing Binding" }),
14781
14880
  /* @__PURE__ */ jsx45("h2", { className: "bb-editorTitle", children: selectedBinding.label || selectedItem }),
@@ -15191,7 +15290,7 @@ function BindingBuilder({ licenseKey }) {
15191
15290
 
15192
15291
  // src/components/SimpleModelViewer/SimpleModelViewer.tsx
15193
15292
  import {
15194
- useRef as useRef18,
15293
+ useRef as useRef19,
15195
15294
  useState as useState25,
15196
15295
  useCallback as useCallback9,
15197
15296
  useEffect as useEffect20,
@@ -15222,7 +15321,7 @@ import {
15222
15321
  Trash2 as Trash26,
15223
15322
  Upload as Upload2
15224
15323
  } from "lucide-react";
15225
- import { Fragment as Fragment13, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
15324
+ import { Fragment as Fragment14, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
15226
15325
  var HIGHLIGHT2 = { color: "#93c5fd", intensity: 0.05 };
15227
15326
  var ENV_PRESETS = [
15228
15327
  "apartment",
@@ -15328,7 +15427,7 @@ function InnerModel({
15328
15427
  },
15329
15428
  [perKeyMaterials]
15330
15429
  );
15331
- const notifiedUrl = useRef18(null);
15430
+ const notifiedUrl = useRef19(null);
15332
15431
  useEffect20(() => {
15333
15432
  if (notifiedUrl.current === url) return;
15334
15433
  notifiedUrl.current = url;
@@ -15425,10 +15524,10 @@ function CameraFitter({
15425
15524
  refitOnResize,
15426
15525
  onInitialFitComplete
15427
15526
  }) {
15428
- const fitted = useRef18(false);
15527
+ const fitted = useRef19(false);
15429
15528
  const invalidate = useThree11((state) => state.invalidate);
15430
15529
  const size = useThree11((state) => state.size);
15431
- const resizeTimerRef = useRef18(null);
15530
+ const resizeTimerRef = useRef19(null);
15432
15531
  useEffect20(() => {
15433
15532
  fitted.current = false;
15434
15533
  invalidate();
@@ -15875,11 +15974,11 @@ function SimpleModelViewer({
15875
15974
  onModelLoaded,
15876
15975
  onLoadError
15877
15976
  }) {
15878
- const cameraControlsRef = useRef18(null);
15879
- const nodeRefsOut = useRef18({});
15880
- const fileInputRef = useRef18(null);
15881
- const uploadedModelRef = useRef18(null);
15882
- const dragDepthRef = useRef18(0);
15977
+ const cameraControlsRef = useRef19(null);
15978
+ const nodeRefsOut = useRef19({});
15979
+ const fileInputRef = useRef19(null);
15980
+ const uploadedModelRef = useRef19(null);
15981
+ const dragDepthRef = useRef19(0);
15883
15982
  const [loadedScene, setLoadedScene] = useState25(null);
15884
15983
  const [meshKeys, setMeshKeys] = useState25({});
15885
15984
  const [hiddenKeys, setHiddenKeys] = useState25(/* @__PURE__ */ new Set());
@@ -16091,7 +16190,7 @@ function SimpleModelViewer({
16091
16190
  }
16092
16191
  ),
16093
16192
  /* @__PURE__ */ jsxs41("div", { className: "smv-canvasArea", children: [
16094
- enableModelUpload ? /* @__PURE__ */ jsxs41(Fragment13, { children: [
16193
+ enableModelUpload ? /* @__PURE__ */ jsxs41(Fragment14, { children: [
16095
16194
  /* @__PURE__ */ jsx46(
16096
16195
  "input",
16097
16196
  {
@@ -16105,7 +16204,7 @@ function SimpleModelViewer({
16105
16204
  }
16106
16205
  }
16107
16206
  ),
16108
- activeModelUrl ? /* @__PURE__ */ jsx46("div", { className: "smv-upload-toolbar", children: /* @__PURE__ */ jsxs41(Fragment13, { children: [
16207
+ activeModelUrl ? /* @__PURE__ */ jsx46("div", { className: "smv-upload-toolbar", children: /* @__PURE__ */ jsxs41(Fragment14, { children: [
16109
16208
  /* @__PURE__ */ jsx46("span", { className: "smv-upload-toolbar__name", children: uploadedModelName ?? "Uploaded model" }),
16110
16209
  /* @__PURE__ */ jsxs41(
16111
16210
  "button",
@@ -16533,7 +16632,7 @@ function useViewerActions(objectBindings, options = {}) {
16533
16632
  }
16534
16633
 
16535
16634
  // src/hooks/useShareableViewerState.ts
16536
- import { useCallback as useCallback15, useEffect as useEffect21, useRef as useRef19, useState as useState29 } from "react";
16635
+ import { useCallback as useCallback15, useEffect as useEffect21, useRef as useRef20, useState as useState29 } from "react";
16537
16636
  function serializeState(cameraState, objectBindings, selectedObjectBinding) {
16538
16637
  const hidden = Object.values(objectBindings).filter((binding) => binding.visible === false).map((binding) => binding.id);
16539
16638
  return {
@@ -16553,7 +16652,7 @@ function useShareableViewerState({
16553
16652
  debounceMs = 400,
16554
16653
  autoSync = true
16555
16654
  }) {
16556
- const lastWrittenRawRef = useRef19(null);
16655
+ const lastWrittenRawRef = useRef20(null);
16557
16656
  const buildHash = useCallback15(() => {
16558
16657
  const state = serializeState(
16559
16658
  cameraState,
@@ -16575,7 +16674,7 @@ function useShareableViewerState({
16575
16674
  paramKey
16576
16675
  );
16577
16676
  }, [buildHash, paramKey]);
16578
- const latestStateRef = useRef19({
16677
+ const latestStateRef = useRef20({
16579
16678
  cameraState,
16580
16679
  objectBindings,
16581
16680
  selectedObjectBinding
@@ -16586,7 +16685,7 @@ function useShareableViewerState({
16586
16685
  selectedObjectBinding
16587
16686
  };
16588
16687
  const [restoreAttempted, setRestoreAttempted] = useState29(false);
16589
- const lastSyncedHashRef = useRef19(null);
16688
+ const lastSyncedHashRef = useRef20(null);
16590
16689
  useEffect21(() => {
16591
16690
  if (!autoSync || !restoreAttempted) return;
16592
16691
  const tick = () => {
@@ -16609,8 +16708,8 @@ function useShareableViewerState({
16609
16708
  const id = window.setInterval(tick, debounceMs);
16610
16709
  return () => window.clearInterval(id);
16611
16710
  }, [autoSync, restoreAttempted, debounceMs, paramKey]);
16612
- const lastRestoredRawRef = useRef19(null);
16613
- const restoringRawRef = useRef19(null);
16711
+ const lastRestoredRawRef = useRef20(null);
16712
+ const restoringRawRef = useRef20(null);
16614
16713
  const restoreFromUrl = useCallback15(async () => {
16615
16714
  setRestoreAttempted(true);
16616
16715
  const rawHash = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : window.location.hash;