@liveroom-tech/react-immersive 1.1.0 → 1.1.1

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-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-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: 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');
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";
@@ -5053,7 +5104,7 @@ function consumeInitialAutoFitOverride(controls) {
5053
5104
  }
5054
5105
 
5055
5106
  // src/components/ModelViewer/ModelViewer.tsx
5056
- import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5107
+ import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5057
5108
  function findInfluencingBone(hit) {
5058
5109
  const mesh = hit.object;
5059
5110
  if (!mesh.isSkinnedMesh || !hit.face || !mesh.skeleton) return null;
@@ -5112,8 +5163,8 @@ function GuidedTourCameraFollow({
5112
5163
  offsetRef
5113
5164
  }) {
5114
5165
  const scene = useThree10((state) => state.scene);
5115
- const nodeRef = useRef10(null);
5116
- const hasPrev = useRef10(false);
5166
+ const nodeRef = useRef11(null);
5167
+ const hasPrev = useRef11(false);
5117
5168
  const live = useMemo13(() => new Vector37(), []);
5118
5169
  const prev = useMemo13(() => new Vector37(), []);
5119
5170
  const goal = useMemo13(() => new Vector37(), []);
@@ -5262,17 +5313,17 @@ function ModelViewer({
5262
5313
  () => shouldReduceGpuLoad(performanceProfile),
5263
5314
  [performanceProfile]
5264
5315
  );
5265
- const controlsRef = useRef10(null);
5316
+ const controlsRef = useRef11(null);
5266
5317
  useEffect14(() => {
5267
5318
  if (!controlsRef.current) return;
5268
5319
  controlsRef.current.dollySpeed = Math.max(zoomSensitivity, 0);
5269
5320
  }, [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({});
5321
+ const tourCameraOffsetRef = useRef11(null);
5322
+ const annotationWorldPositionsRef = useRef11(/* @__PURE__ */ new Map());
5323
+ const fileInputRef = useRef11(null);
5324
+ const pendingObjectId = useRef11(null);
5325
+ const rendererCaptureRef = useRef11(null);
5326
+ const createdBlobUrls = useRef11({});
5276
5327
  useEffect14(() => {
5277
5328
  return () => {
5278
5329
  for (const url of Object.values(createdBlobUrls.current)) {
@@ -5280,12 +5331,12 @@ function ModelViewer({
5280
5331
  }
5281
5332
  };
5282
5333
  }, []);
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);
5334
+ const nodeRefsMap = useRef11({});
5335
+ const materialRefsOut = useRef11({});
5336
+ const viewerLeftRef = useRef11(null);
5337
+ const canvasAreaRef = useRef11(null);
5338
+ const xrPresenterRef = useRef11(null);
5339
+ const viewAnnotationPopupRef = useRef11(null);
5289
5340
  const [internalObjectBindings, setInternalObjectBindings] = useState10(objectBindings);
5290
5341
  const [itemMaterials, setItemMaterials] = useState10({});
5291
5342
  const [currentAction, setCurrentAction] = useState10(
@@ -5299,12 +5350,12 @@ function ModelViewer({
5299
5350
  null
5300
5351
  );
5301
5352
  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));
5353
+ const sceneRef = useRef11(null);
5354
+ const fitAttemptedRef = useRef11(false);
5355
+ const fitInFlightRef = useRef11(false);
5356
+ const cameraProvidedRef = useRef11(Boolean(camera));
5306
5357
  cameraProvidedRef.current = Boolean(camera);
5307
- const initialCameraStateRef = useRef10(null);
5358
+ const initialCameraStateRef = useRef11(null);
5308
5359
  const [isAutoFraming, setIsAutoFraming] = useState10(Boolean(modelUrl));
5309
5360
  const [cameraPositioned, setCameraPositioned] = useState10(
5310
5361
  !modelUrl || Boolean(onAutoFit) || Boolean(camera)
@@ -5314,7 +5365,7 @@ function ModelViewer({
5314
5365
  const [modelLoadFailed, setModelLoadFailed] = useState10(false);
5315
5366
  const [bindingsMismatch, setBindingsMismatch] = useState10(false);
5316
5367
  const [mismatchDismissed, setMismatchDismissed] = useState10(false);
5317
- const currentObjectBindingsRef = useRef10({});
5368
+ const currentObjectBindingsRef = useRef11({});
5318
5369
  const captureInitialCameraState = useCallback4(() => {
5319
5370
  const controls = controlsRef.current;
5320
5371
  if (!controls || initialCameraStateRef.current) {
@@ -5332,10 +5383,10 @@ function ModelViewer({
5332
5383
  const [measurePoints, setMeasurePoints] = useState10([]);
5333
5384
  const [showDimensions, setShowDimensions] = useState10(false);
5334
5385
  const [measureBox, setMeasureBox] = useState10(null);
5335
- const measureModeRef = useRef10(false);
5386
+ const measureModeRef = useRef11(false);
5336
5387
  measureModeRef.current = measureMode;
5337
- const measurePointCounter = useRef10(0);
5338
- const measureDownRef = useRef10(null);
5388
+ const measurePointCounter = useRef11(0);
5389
+ const measureDownRef = useRef11(null);
5339
5390
  const [explodeFactor, setExplodeFactor] = useState10(0);
5340
5391
  const [explodeOpen, setExplodeOpen] = useState10(false);
5341
5392
  useEffect14(() => {
@@ -5358,7 +5409,7 @@ function ModelViewer({
5358
5409
  return { ...base ?? {}, ...cinematic };
5359
5410
  }, [cinematic, resolvedSceneConfig]);
5360
5411
  const [cinematicPlaying, setCinematicPlaying] = useState10(false);
5361
- const cinematicAutoStartedRef = useRef10(false);
5412
+ const cinematicAutoStartedRef = useRef11(false);
5362
5413
  useEffect14(() => {
5363
5414
  setCinematicPlaying(false);
5364
5415
  cinematicAutoStartedRef.current = false;
@@ -5453,7 +5504,7 @@ function ModelViewer({
5453
5504
  const arHintText = arOverlayState.isModelPlaced && !arOverlayState.isPlacementMode ? "Pinch to resize \xB7 Twist to rotate" : null;
5454
5505
  const arOverlayRoot = xrStore?.getState().domOverlayRoot ?? null;
5455
5506
  const arOverlay = inARSession && arOverlayRoot ? createPortal(
5456
- /* @__PURE__ */ jsxs15(Fragment6, { children: [
5507
+ /* @__PURE__ */ jsxs15(Fragment7, { children: [
5457
5508
  arHintText && /* @__PURE__ */ jsx19("div", { className: "ri-arHintOverlay", children: /* @__PURE__ */ jsx19("div", { className: "ri-arHint", children: arHintText }) }),
5458
5509
  /* @__PURE__ */ jsx19("div", { className: "ri-arOverlay", children: /* @__PURE__ */ jsxs15("div", { className: "ri-arControls", children: [
5459
5510
  arStatusText && /* @__PURE__ */ jsx19("div", { className: "ri-arStatus", children: arStatusText }),
@@ -5514,11 +5565,11 @@ function ModelViewer({
5514
5565
  title: "",
5515
5566
  description: ""
5516
5567
  });
5517
- const annotationCounterRef = useRef10(0);
5568
+ const annotationCounterRef = useRef11(0);
5518
5569
  const [internalViewingAnnotation, setInternalViewingAnnotation] = useState10(null);
5519
5570
  const [currentAnnotationIndex, setCurrentAnnotationIndex] = useState10(-1);
5520
5571
  const [isNavigating, setIsNavigating] = useState10(false);
5521
- const annotationSmoothRestoreTimeoutRef = useRef10(null);
5572
+ const annotationSmoothRestoreTimeoutRef = useRef11(null);
5522
5573
  const sortedAnnotations = useMemo13(() => {
5523
5574
  return [...annotations].sort((a, b) => a.id - b.id);
5524
5575
  }, [annotations]);
@@ -6078,7 +6129,7 @@ function ModelViewer({
6078
6129
  delete createdBlobUrls.current[targetKey];
6079
6130
  }
6080
6131
  };
6081
- const onViewerReadyRef = useRef10(onViewerReady);
6132
+ const onViewerReadyRef = useRef11(onViewerReady);
6082
6133
  onViewerReadyRef.current = onViewerReady;
6083
6134
  const notifyViewerReady = useCallback4(() => {
6084
6135
  const controls = controlsRef.current;
@@ -6597,7 +6648,34 @@ function ModelViewer({
6597
6648
  selectedObject: currentPanelObject,
6598
6649
  currentAction,
6599
6650
  onClose: handleClosePanel,
6600
- onAction: handleAction
6651
+ onAction: handleAction,
6652
+ renderActionExtra: (actionId) => {
6653
+ if (actionId === "change-color" && colorPicker) {
6654
+ return /* @__PURE__ */ jsx19(
6655
+ ColorPicker,
6656
+ {
6657
+ inline: true,
6658
+ colorPicker,
6659
+ onClose: closeColorPicker,
6660
+ itemMaterials,
6661
+ setItemMaterials
6662
+ }
6663
+ );
6664
+ }
6665
+ if (actionId === "change-material" && materialPopup) {
6666
+ return /* @__PURE__ */ jsx19(
6667
+ MaterialPicker,
6668
+ {
6669
+ inline: true,
6670
+ triggerFileUpload,
6671
+ materialPopup,
6672
+ textureUrl: materialTextureUrl,
6673
+ clearTexture
6674
+ }
6675
+ );
6676
+ }
6677
+ return null;
6678
+ }
6601
6679
  }
6602
6680
  ),
6603
6681
  /* @__PURE__ */ jsxs15(
@@ -6680,7 +6758,7 @@ function ModelViewer({
6680
6758
  {
6681
6759
  onLoadError: handleLoadErrorInternal,
6682
6760
  children: /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ (() => {
6683
- const modelContent = /* @__PURE__ */ jsxs15(Fragment6, { children: [
6761
+ const modelContent = /* @__PURE__ */ jsxs15(Fragment7, { children: [
6684
6762
  /* @__PURE__ */ jsx19(
6685
6763
  Model,
6686
6764
  {
@@ -6911,7 +6989,7 @@ function ModelViewer({
6911
6989
  ] }),
6912
6990
  arOverlay,
6913
6991
  (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 ? (
6992
+ /* @__PURE__ */ jsx19("div", { className: "ri-tourControls", children: showAnnotationNavigation && sortedAnnotations.length > 0 && /* @__PURE__ */ jsx19(Fragment7, { children: !isGuidedTourActive ? (
6915
6993
  // Show "Guided Tour" button when tour is not active
6916
6994
  /* @__PURE__ */ jsx19(
6917
6995
  "button",
@@ -6925,7 +7003,7 @@ function ModelViewer({
6925
7003
  )
6926
7004
  ) : (
6927
7005
  // Show Previous, Next, Stop, Reset buttons when tour is active
6928
- /* @__PURE__ */ jsxs15(Fragment6, { children: [
7006
+ /* @__PURE__ */ jsxs15(Fragment7, { children: [
6929
7007
  /* @__PURE__ */ jsxs15(
6930
7008
  "button",
6931
7009
  {
@@ -7019,10 +7097,10 @@ function ModelViewer({
7019
7097
  onClick: () => setDownloadMenuOpen((v) => !v),
7020
7098
  disabled: isDownloading || !sceneRef.current,
7021
7099
  title: "Download options",
7022
- children: isDownloading ? /* @__PURE__ */ jsxs15(Fragment6, { children: [
7100
+ children: isDownloading ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
7023
7101
  /* @__PURE__ */ jsx19("span", { className: "ri-downloadButton__spinner" }),
7024
7102
  "Exporting\u2026"
7025
- ] }) : /* @__PURE__ */ jsxs15(Fragment6, { children: [
7103
+ ] }) : /* @__PURE__ */ jsxs15(Fragment7, { children: [
7026
7104
  /* @__PURE__ */ jsx19(Download, { size: 15 }),
7027
7105
  "Download"
7028
7106
  ] })
@@ -7100,7 +7178,7 @@ function ModelViewer({
7100
7178
  ]
7101
7179
  }
7102
7180
  ),
7103
- colorPicker && /* @__PURE__ */ jsx19(
7181
+ customObjectBindingDataPanel && colorPicker && /* @__PURE__ */ jsx19(
7104
7182
  ColorPicker,
7105
7183
  {
7106
7184
  colorPicker,
@@ -7109,7 +7187,7 @@ function ModelViewer({
7109
7187
  setItemMaterials
7110
7188
  }
7111
7189
  ),
7112
- materialPopup && /* @__PURE__ */ jsx19(
7190
+ customObjectBindingDataPanel && materialPopup && /* @__PURE__ */ jsx19(
7113
7191
  MaterialPicker,
7114
7192
  {
7115
7193
  triggerFileUpload,
@@ -7147,7 +7225,7 @@ function ModelViewer({
7147
7225
  }
7148
7226
 
7149
7227
  // src/components/BindingBuilder/BindingBuilder.tsx
7150
- import { useCallback as useCallback8, useEffect as useEffect19, useMemo as useMemo16, useRef as useRef17, useState as useState24 } from "react";
7228
+ import { useCallback as useCallback8, useEffect as useEffect19, useMemo as useMemo16, useRef as useRef18, useState as useState24 } from "react";
7151
7229
  import {
7152
7230
  Redo2,
7153
7231
  Undo2,
@@ -7161,7 +7239,7 @@ import {
7161
7239
  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
7240
 
7163
7241
  // src/hooks/useViewerCamera.ts
7164
- import { useCallback as useCallback5, useRef as useRef11, useState as useState11 } from "react";
7242
+ import { useCallback as useCallback5, useRef as useRef12, useState as useState11 } from "react";
7165
7243
  import { Vector3 as Vector38 } from "three";
7166
7244
 
7167
7245
  // src/utils/resolveBindingKey.ts
@@ -7213,7 +7291,7 @@ async function runSmoothCameraTransition2(controls, action, smoothTime = 0.6) {
7213
7291
  }
7214
7292
  }
7215
7293
  function useViewerCamera() {
7216
- const viewerRef = useRef11(null);
7294
+ const viewerRef = useRef12(null);
7217
7295
  const [cameraState, setCameraStateValue] = useState11(
7218
7296
  null
7219
7297
  );
@@ -7228,8 +7306,8 @@ function useViewerCamera() {
7228
7306
  },
7229
7307
  [updateCameraState]
7230
7308
  );
7231
- const homeCameraStateRef = useRef11(null);
7232
- const homeSceneRef = useRef11(null);
7309
+ const homeCameraStateRef = useRef12(null);
7310
+ const homeSceneRef = useRef12(null);
7233
7311
  const handleViewerReady = useCallback5((viewer) => {
7234
7312
  viewerRef.current = viewer;
7235
7313
  updateCameraState(buildCameraState(viewer.controls.camera, viewer.controls));
@@ -7399,11 +7477,11 @@ function useViewerCamera() {
7399
7477
  }
7400
7478
 
7401
7479
  // src/hooks/useViewerAnimations.ts
7402
- import { useCallback as useCallback6, useEffect as useEffect15, useRef as useRef12, useState as useState12 } from "react";
7480
+ import { useCallback as useCallback6, useEffect as useEffect15, useRef as useRef13, useState as useState12 } from "react";
7403
7481
  function useViewerAnimations() {
7404
- const controlsRef = useRef12(null);
7482
+ const controlsRef = useRef13(null);
7405
7483
  const [clips, setClips] = useState12([]);
7406
- const unsubscribeRef = useRef12(null);
7484
+ const unsubscribeRef = useRef13(null);
7407
7485
  const [clipDetails, setClipDetails] = useState12([]);
7408
7486
  const [currentClip, setCurrentClip] = useState12(null);
7409
7487
  const [isPlaying, setIsPlaying] = useState12(false);
@@ -7685,7 +7763,7 @@ import {
7685
7763
  import { HexColorInput as HexColorInput2, HexColorPicker as HexColorPicker3 } from "react-colorful";
7686
7764
 
7687
7765
  // src/components/BindingBuilder/SceneSettings/SceneControls.tsx
7688
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef13, useState as useState13 } from "react";
7766
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef14, useState as useState13 } from "react";
7689
7767
  import { createPortal as createPortal2 } from "react-dom";
7690
7768
  import { ChevronDown, Info } from "lucide-react";
7691
7769
  import { HexColorInput, HexColorPicker as HexColorPicker2 } from "react-colorful";
@@ -7726,7 +7804,7 @@ function ColorPopover({
7726
7804
  onClose,
7727
7805
  children
7728
7806
  }) {
7729
- const popoverRef = useRef13(null);
7807
+ const popoverRef = useRef14(null);
7730
7808
  const [position, setPosition] = useState13(null);
7731
7809
  useClickOutside([popoverRef, anchorRef], onClose, true);
7732
7810
  useLayoutEffect2(() => {
@@ -7922,7 +8000,7 @@ function ColorRow({
7922
8000
  onChange
7923
8001
  }) {
7924
8002
  const [open, setOpen] = useState13(false);
7925
- const anchorRef = useRef13(null);
8003
+ const anchorRef = useRef14(null);
7926
8004
  return /* @__PURE__ */ jsxs16("div", { className: "se-field", children: [
7927
8005
  /* @__PURE__ */ jsxs16("div", { className: "se-fieldInline", children: [
7928
8006
  /* @__PURE__ */ jsx20("span", { className: "se-fieldLabel", children: label }),
@@ -8046,7 +8124,7 @@ function TierLock({
8046
8124
  }
8047
8125
 
8048
8126
  // src/components/BindingBuilder/SceneSettings/GeneralSceneSettings.tsx
8049
- import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8127
+ import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8050
8128
  var SHADING_OPTIONS = ["lit", "unlit", "normals"];
8051
8129
  var BACKGROUND_TYPES = ["color", "image", "environment"];
8052
8130
  function normalizeRotation(value) {
@@ -8251,7 +8329,7 @@ function GeneralSceneSettings({ config, onChange }) {
8251
8329
  ),
8252
8330
  /* @__PURE__ */ jsx22("span", { className: "se-switchTrack", children: /* @__PURE__ */ jsx22("span", { className: "se-switchThumb" }) })
8253
8331
  ] }),
8254
- children: canUseStarterFeatures ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
8332
+ children: canUseStarterFeatures ? /* @__PURE__ */ jsxs18(Fragment8, { children: [
8255
8333
  /* @__PURE__ */ jsx22(
8256
8334
  SliderRow,
8257
8335
  {
@@ -8291,7 +8369,7 @@ function GeneralSceneSettings({ config, onChange }) {
8291
8369
  ),
8292
8370
  /* @__PURE__ */ jsx22("span", { className: "se-switchTrack", children: /* @__PURE__ */ jsx22("span", { className: "se-switchThumb" }) })
8293
8371
  ] }),
8294
- children: background.enabled ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
8372
+ children: background.enabled ? /* @__PURE__ */ jsxs18(Fragment8, { children: [
8295
8373
  /* @__PURE__ */ jsxs18("div", { className: "se-field", children: [
8296
8374
  /* @__PURE__ */ jsx22("span", { className: "se-fieldLabel", children: "Background type" }),
8297
8375
  /* @__PURE__ */ jsx22("div", { className: "se-segmentedControl", children: BACKGROUND_TYPES.map((type) => /* @__PURE__ */ jsx22(
@@ -8311,7 +8389,7 @@ function GeneralSceneSettings({ config, onChange }) {
8311
8389
  requiredTier: "starter",
8312
8390
  feature: "Environment backgrounds"
8313
8391
  }
8314
- ) : /* @__PURE__ */ jsxs18(Fragment7, { children: [
8392
+ ) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
8315
8393
  /* @__PURE__ */ jsxs18("div", { className: "se-field", children: [
8316
8394
  /* @__PURE__ */ jsx22("span", { className: "se-fieldLabel", children: "Environment source" }),
8317
8395
  /* @__PURE__ */ jsxs18("div", { className: "se-segmentedControl", children: [
@@ -10329,7 +10407,7 @@ function PostProcessingTab({ config, onChange }) {
10329
10407
  // src/components/BindingBuilder/SceneSettings/LightingTab.tsx
10330
10408
  import { useState as useState16 } from "react";
10331
10409
  import { Eye, EyeOff, Plus, Trash2 } from "lucide-react";
10332
- import { Fragment as Fragment8, jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
10410
+ import { Fragment as Fragment9, jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
10333
10411
  var SHADOW_MAP_SIZES = ["512", "1024", "2048", "4096"];
10334
10412
  var LIGHT_TYPE_LABELS = {
10335
10413
  none: "None",
@@ -10698,7 +10776,7 @@ function LightingTab({ config, onChange }) {
10698
10776
  title: "Environment",
10699
10777
  open: open.environment,
10700
10778
  onToggle: () => toggleOpen("environment"),
10701
- children: !canUseStarterFeatures ? /* @__PURE__ */ jsx28(TierLock, { requiredTier: "starter", feature: "Environment lighting" }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
10779
+ children: !canUseStarterFeatures ? /* @__PURE__ */ jsx28(TierLock, { requiredTier: "starter", feature: "Environment lighting" }) : /* @__PURE__ */ jsxs24(Fragment9, { children: [
10702
10780
  /* @__PURE__ */ jsx28(
10703
10781
  SliderRow,
10704
10782
  {
@@ -11711,7 +11789,7 @@ function MaterialPanelGroup({
11711
11789
  }
11712
11790
 
11713
11791
  // src/components/BindingBuilder/components/MaterialFields.tsx
11714
- import { useRef as useRef14, useState as useState20 } from "react";
11792
+ import { useRef as useRef15, useState as useState20 } from "react";
11715
11793
  import { HexColorInput as HexColorInput3, HexColorPicker as HexColorPicker4 } from "react-colorful";
11716
11794
  import { FileUp } from "lucide-react";
11717
11795
  import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
@@ -11721,7 +11799,7 @@ function MaterialTexturePathField({
11721
11799
  placeholder,
11722
11800
  onChange
11723
11801
  }) {
11724
- const inputRef = useRef14(null);
11802
+ const inputRef = useRef15(null);
11725
11803
  return /* @__PURE__ */ jsxs30("div", { className: "bb-field bb-field--full", children: [
11726
11804
  /* @__PURE__ */ jsx35("label", { className: "bb-label", children: label }),
11727
11805
  /* @__PURE__ */ jsxs30("div", { className: "bb-fileField", children: [
@@ -11780,7 +11858,7 @@ function MaterialColorField({
11780
11858
  }) {
11781
11859
  const [open, setOpen] = useState20(false);
11782
11860
  const color = value || fallback;
11783
- const anchorRef = useRef14(null);
11861
+ const anchorRef = useRef15(null);
11784
11862
  return /* @__PURE__ */ jsxs30("div", { className: "bb-field", children: [
11785
11863
  /* @__PURE__ */ jsx35("span", { className: "bb-label", children: label }),
11786
11864
  /* @__PURE__ */ jsx35("div", { className: "se-fieldInline", children: /* @__PURE__ */ jsx35("span", { ref: anchorRef, style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx35(
@@ -11907,7 +11985,7 @@ function MaterialSliderField({
11907
11985
  }
11908
11986
 
11909
11987
  // src/components/BindingBuilder/components/MaterialSection.tsx
11910
- import { Fragment as Fragment9, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
11988
+ import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
11911
11989
  function MaterialSection({
11912
11990
  selectedItem,
11913
11991
  selectedMaterial,
@@ -11936,7 +12014,7 @@ function MaterialSection({
11936
12014
  const [anisotropyMode, setAnisotropyMode] = useState21(
11937
12015
  "factor"
11938
12016
  );
11939
- return /* @__PURE__ */ jsxs31(Fragment9, { children: [
12017
+ return /* @__PURE__ */ jsxs31(Fragment10, { children: [
11940
12018
  /* @__PURE__ */ jsx36(
11941
12019
  MaterialPanelGroup,
11942
12020
  {
@@ -11975,7 +12053,7 @@ function MaterialSection({
11975
12053
  }))
11976
12054
  }
11977
12055
  ),
11978
- pbrWorkflow === "metalness" ? /* @__PURE__ */ jsxs31(Fragment9, { children: [
12056
+ pbrWorkflow === "metalness" ? /* @__PURE__ */ jsxs31(Fragment10, { children: [
11979
12057
  /* @__PURE__ */ jsx36(
11980
12058
  MaterialSliderField,
11981
12059
  {
@@ -11999,7 +12077,7 @@ function MaterialSection({
11999
12077
  onChange: (value) => setSelectedTexturePath(selectedItem, "metalnessMap", value)
12000
12078
  }
12001
12079
  )
12002
- ] }) : /* @__PURE__ */ jsxs31(Fragment9, { children: [
12080
+ ] }) : /* @__PURE__ */ jsxs31(Fragment10, { children: [
12003
12081
  /* @__PURE__ */ jsx36(
12004
12082
  MaterialSliderField,
12005
12083
  {
@@ -12972,7 +13050,7 @@ function MaterialPresetGallery({
12972
13050
  }
12973
13051
 
12974
13052
  // src/components/BindingBuilder/components/ToolbarExportMenu.tsx
12975
- import { useEffect as useEffect18, useRef as useRef15, useState as useState22 } from "react";
13053
+ import { useEffect as useEffect18, useRef as useRef16, useState as useState22 } from "react";
12976
13054
  import { ChevronDown as ChevronDown5, Download as Download2, FileCode2, FileJson } from "lucide-react";
12977
13055
  import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
12978
13056
  function ToolbarExportMenu({
@@ -12982,7 +13060,7 @@ function ToolbarExportMenu({
12982
13060
  onExportTs
12983
13061
  }) {
12984
13062
  const [open, setOpen] = useState22(false);
12985
- const wrapperRef = useRef15(null);
13063
+ const wrapperRef = useRef16(null);
12986
13064
  useEffect18(() => {
12987
13065
  if (!open) return;
12988
13066
  const close = (event) => {
@@ -13315,7 +13393,7 @@ function ActionsPanel({
13315
13393
 
13316
13394
  // src/components/BindingBuilder/components/CameraPositionPanel.tsx
13317
13395
  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";
13396
+ import { Fragment as Fragment11, jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
13319
13397
  function CameraPositionPanel({
13320
13398
  selectedBinding,
13321
13399
  open,
@@ -13334,7 +13412,7 @@ function CameraPositionPanel({
13334
13412
  /* @__PURE__ */ jsx42("span", { className: "bb-cameraLiveBadge", children: "LIVE" }),
13335
13413
  /* @__PURE__ */ jsxs37("div", { className: "se-waypointBody", children: [
13336
13414
  /* @__PURE__ */ jsx42("div", { className: "bb-cameraWaypointLabel", children: "Current view" }),
13337
- cameraState ? /* @__PURE__ */ jsxs37(Fragment10, { children: [
13415
+ cameraState ? /* @__PURE__ */ jsxs37(Fragment11, { children: [
13338
13416
  /* @__PURE__ */ jsxs37("div", { className: "se-waypointCoords", children: [
13339
13417
  "pos ",
13340
13418
  formattedCameraState?.position
@@ -13538,7 +13616,7 @@ function collectModelMetadata(modelUrl) {
13538
13616
  }
13539
13617
 
13540
13618
  // src/components/BindingBuilder/components/SceneNodesPanel.tsx
13541
- import { Fragment as Fragment11, jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
13619
+ import { Fragment as Fragment12, jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
13542
13620
  function SceneNodesPanel({
13543
13621
  bindings,
13544
13622
  selectedItem,
@@ -13574,7 +13652,7 @@ function SceneNodesPanel({
13574
13652
  children: "\u2190"
13575
13653
  }
13576
13654
  ),
13577
- isOpen && /* @__PURE__ */ jsxs38(Fragment11, { children: [
13655
+ isOpen && /* @__PURE__ */ jsxs38(Fragment12, { children: [
13578
13656
  /* @__PURE__ */ jsxs38("div", { children: [
13579
13657
  /* @__PURE__ */ jsx43("div", { className: "bb-sectionKicker", children: "Scene Nodes" }),
13580
13658
  /* @__PURE__ */ jsxs38("div", { className: "bb-sectionHeading", children: [
@@ -13692,7 +13770,7 @@ function mergeAnimationConfig(sceneConfig, animationDetails) {
13692
13770
  }
13693
13771
 
13694
13772
  // src/components/BindingBuilder/hooks/useUndoableState.ts
13695
- import { useCallback as useCallback7, useReducer, useRef as useRef16 } from "react";
13773
+ import { useCallback as useCallback7, useReducer, useRef as useRef17 } from "react";
13696
13774
  var MAX_HISTORY = 100;
13697
13775
  function historyReducer(state, action) {
13698
13776
  switch (action.type) {
@@ -13736,7 +13814,7 @@ function useUndoableState(initial, coalesceWindowMs = 600) {
13736
13814
  present: initial,
13737
13815
  future: []
13738
13816
  });
13739
- const lastSetAt = useRef16(0);
13817
+ const lastSetAt = useRef17(0);
13740
13818
  const setValue = useCallback7(
13741
13819
  (updater) => {
13742
13820
  const now = Date.now();
@@ -13983,7 +14061,7 @@ function removeMaterialPanelFields(material, panel) {
13983
14061
  }
13984
14062
 
13985
14063
  // src/components/BindingBuilder/BindingBuilder.tsx
13986
- import { Fragment as Fragment12, jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
14064
+ import { Fragment as Fragment13, jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
13987
14065
  var DEMO_MODEL_URL = "/room.glb";
13988
14066
  function isPlainObject(value) {
13989
14067
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -14000,9 +14078,9 @@ function mergeSceneConfigSection(current, incoming) {
14000
14078
  return next;
14001
14079
  }
14002
14080
  function BindingBuilder({ licenseKey }) {
14003
- const modelInputRef = useRef17(null);
14004
- const bindingsInputRef = useRef17(null);
14005
- const sceneConfigInputRef = useRef17(null);
14081
+ const modelInputRef = useRef18(null);
14082
+ const bindingsInputRef = useRef18(null);
14083
+ const sceneConfigInputRef = useRef18(null);
14006
14084
  const [modelUrl, setModelUrl] = useState24(null);
14007
14085
  const [modelName, setModelName] = useState24("");
14008
14086
  const [selectedItem, setSelectedItem] = useState24(null);
@@ -14054,7 +14132,7 @@ function BindingBuilder({ licenseKey }) {
14054
14132
  const [activeSubTab, setActiveSubTab] = useState24("General");
14055
14133
  const [pbrWorkflow, setPbrWorkflow] = useState24("metalness");
14056
14134
  const [materialPanelEnabled, setMaterialPanelEnabled] = useState24(createMaterialPanelEnabledState());
14057
- const materialPanelItemRef = useRef17(null);
14135
+ const materialPanelItemRef = useRef18(null);
14058
14136
  const [zoomOnSelected, setZoomOnSelected] = useState24(false);
14059
14137
  const [highlightOnHover, setHighlightOnHover] = useState24(true);
14060
14138
  const [resetDialogOpen, setResetDialogOpen] = useState24(false);
@@ -14077,9 +14155,9 @@ function BindingBuilder({ licenseKey }) {
14077
14155
  }),
14078
14156
  [activeEditorTab, activeSubTab, tier]
14079
14157
  );
14080
- const uploadedModelRef = useRef17(null);
14081
- const previewDragDepthRef = useRef17(0);
14082
- const loadRequestRef = useRef17(0);
14158
+ const uploadedModelRef = useRef18(null);
14159
+ const previewDragDepthRef = useRef18(0);
14160
+ const loadRequestRef = useRef18(0);
14083
14161
  const {
14084
14162
  cameraState,
14085
14163
  resetView,
@@ -14734,7 +14812,7 @@ function BindingBuilder({ licenseKey }) {
14734
14812
  }
14735
14813
  )
14736
14814
  ] }),
14737
- !isEditorCollapsed && /* @__PURE__ */ jsxs40(Fragment12, { children: [
14815
+ !isEditorCollapsed && /* @__PURE__ */ jsxs40(Fragment13, { children: [
14738
14816
  /* @__PURE__ */ jsxs40("div", { className: "bb-tabRow", children: [
14739
14817
  /* @__PURE__ */ jsx45(
14740
14818
  "button",
@@ -14755,7 +14833,7 @@ function BindingBuilder({ licenseKey }) {
14755
14833
  }
14756
14834
  )
14757
14835
  ] }),
14758
- /* @__PURE__ */ jsx45("section", { className: "bb-editor", children: activeEditorTab === "scene" ? /* @__PURE__ */ jsx45(Fragment12, { children: modelUrl ? /* @__PURE__ */ jsx45(
14836
+ /* @__PURE__ */ jsx45("section", { className: "bb-editor", children: activeEditorTab === "scene" ? /* @__PURE__ */ jsx45(Fragment13, { children: modelUrl ? /* @__PURE__ */ jsx45(
14759
14837
  SceneSettingsTab,
14760
14838
  {
14761
14839
  config: sceneConfig,
@@ -14775,7 +14853,7 @@ function BindingBuilder({ licenseKey }) {
14775
14853
  animationClipDetails: viewerAnimations.clipDetails,
14776
14854
  animationPlayback: viewerAnimations
14777
14855
  }
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: [
14856
+ ) : /* @__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
14857
  /* @__PURE__ */ jsx45("div", { className: "bb-editorHeader", children: /* @__PURE__ */ jsxs40("div", { children: [
14780
14858
  /* @__PURE__ */ jsx45("div", { className: "bb-sectionKicker", children: "Editing Binding" }),
14781
14859
  /* @__PURE__ */ jsx45("h2", { className: "bb-editorTitle", children: selectedBinding.label || selectedItem }),
@@ -15191,7 +15269,7 @@ function BindingBuilder({ licenseKey }) {
15191
15269
 
15192
15270
  // src/components/SimpleModelViewer/SimpleModelViewer.tsx
15193
15271
  import {
15194
- useRef as useRef18,
15272
+ useRef as useRef19,
15195
15273
  useState as useState25,
15196
15274
  useCallback as useCallback9,
15197
15275
  useEffect as useEffect20,
@@ -15222,7 +15300,7 @@ import {
15222
15300
  Trash2 as Trash26,
15223
15301
  Upload as Upload2
15224
15302
  } from "lucide-react";
15225
- import { Fragment as Fragment13, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
15303
+ import { Fragment as Fragment14, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
15226
15304
  var HIGHLIGHT2 = { color: "#93c5fd", intensity: 0.05 };
15227
15305
  var ENV_PRESETS = [
15228
15306
  "apartment",
@@ -15328,7 +15406,7 @@ function InnerModel({
15328
15406
  },
15329
15407
  [perKeyMaterials]
15330
15408
  );
15331
- const notifiedUrl = useRef18(null);
15409
+ const notifiedUrl = useRef19(null);
15332
15410
  useEffect20(() => {
15333
15411
  if (notifiedUrl.current === url) return;
15334
15412
  notifiedUrl.current = url;
@@ -15425,10 +15503,10 @@ function CameraFitter({
15425
15503
  refitOnResize,
15426
15504
  onInitialFitComplete
15427
15505
  }) {
15428
- const fitted = useRef18(false);
15506
+ const fitted = useRef19(false);
15429
15507
  const invalidate = useThree11((state) => state.invalidate);
15430
15508
  const size = useThree11((state) => state.size);
15431
- const resizeTimerRef = useRef18(null);
15509
+ const resizeTimerRef = useRef19(null);
15432
15510
  useEffect20(() => {
15433
15511
  fitted.current = false;
15434
15512
  invalidate();
@@ -15875,11 +15953,11 @@ function SimpleModelViewer({
15875
15953
  onModelLoaded,
15876
15954
  onLoadError
15877
15955
  }) {
15878
- const cameraControlsRef = useRef18(null);
15879
- const nodeRefsOut = useRef18({});
15880
- const fileInputRef = useRef18(null);
15881
- const uploadedModelRef = useRef18(null);
15882
- const dragDepthRef = useRef18(0);
15956
+ const cameraControlsRef = useRef19(null);
15957
+ const nodeRefsOut = useRef19({});
15958
+ const fileInputRef = useRef19(null);
15959
+ const uploadedModelRef = useRef19(null);
15960
+ const dragDepthRef = useRef19(0);
15883
15961
  const [loadedScene, setLoadedScene] = useState25(null);
15884
15962
  const [meshKeys, setMeshKeys] = useState25({});
15885
15963
  const [hiddenKeys, setHiddenKeys] = useState25(/* @__PURE__ */ new Set());
@@ -16091,7 +16169,7 @@ function SimpleModelViewer({
16091
16169
  }
16092
16170
  ),
16093
16171
  /* @__PURE__ */ jsxs41("div", { className: "smv-canvasArea", children: [
16094
- enableModelUpload ? /* @__PURE__ */ jsxs41(Fragment13, { children: [
16172
+ enableModelUpload ? /* @__PURE__ */ jsxs41(Fragment14, { children: [
16095
16173
  /* @__PURE__ */ jsx46(
16096
16174
  "input",
16097
16175
  {
@@ -16105,7 +16183,7 @@ function SimpleModelViewer({
16105
16183
  }
16106
16184
  }
16107
16185
  ),
16108
- activeModelUrl ? /* @__PURE__ */ jsx46("div", { className: "smv-upload-toolbar", children: /* @__PURE__ */ jsxs41(Fragment13, { children: [
16186
+ activeModelUrl ? /* @__PURE__ */ jsx46("div", { className: "smv-upload-toolbar", children: /* @__PURE__ */ jsxs41(Fragment14, { children: [
16109
16187
  /* @__PURE__ */ jsx46("span", { className: "smv-upload-toolbar__name", children: uploadedModelName ?? "Uploaded model" }),
16110
16188
  /* @__PURE__ */ jsxs41(
16111
16189
  "button",
@@ -16533,7 +16611,7 @@ function useViewerActions(objectBindings, options = {}) {
16533
16611
  }
16534
16612
 
16535
16613
  // src/hooks/useShareableViewerState.ts
16536
- import { useCallback as useCallback15, useEffect as useEffect21, useRef as useRef19, useState as useState29 } from "react";
16614
+ import { useCallback as useCallback15, useEffect as useEffect21, useRef as useRef20, useState as useState29 } from "react";
16537
16615
  function serializeState(cameraState, objectBindings, selectedObjectBinding) {
16538
16616
  const hidden = Object.values(objectBindings).filter((binding) => binding.visible === false).map((binding) => binding.id);
16539
16617
  return {
@@ -16553,7 +16631,7 @@ function useShareableViewerState({
16553
16631
  debounceMs = 400,
16554
16632
  autoSync = true
16555
16633
  }) {
16556
- const lastWrittenRawRef = useRef19(null);
16634
+ const lastWrittenRawRef = useRef20(null);
16557
16635
  const buildHash = useCallback15(() => {
16558
16636
  const state = serializeState(
16559
16637
  cameraState,
@@ -16575,7 +16653,7 @@ function useShareableViewerState({
16575
16653
  paramKey
16576
16654
  );
16577
16655
  }, [buildHash, paramKey]);
16578
- const latestStateRef = useRef19({
16656
+ const latestStateRef = useRef20({
16579
16657
  cameraState,
16580
16658
  objectBindings,
16581
16659
  selectedObjectBinding
@@ -16586,7 +16664,7 @@ function useShareableViewerState({
16586
16664
  selectedObjectBinding
16587
16665
  };
16588
16666
  const [restoreAttempted, setRestoreAttempted] = useState29(false);
16589
- const lastSyncedHashRef = useRef19(null);
16667
+ const lastSyncedHashRef = useRef20(null);
16590
16668
  useEffect21(() => {
16591
16669
  if (!autoSync || !restoreAttempted) return;
16592
16670
  const tick = () => {
@@ -16609,8 +16687,8 @@ function useShareableViewerState({
16609
16687
  const id = window.setInterval(tick, debounceMs);
16610
16688
  return () => window.clearInterval(id);
16611
16689
  }, [autoSync, restoreAttempted, debounceMs, paramKey]);
16612
- const lastRestoredRawRef = useRef19(null);
16613
- const restoringRawRef = useRef19(null);
16690
+ const lastRestoredRawRef = useRef20(null);
16691
+ const restoringRawRef = useRef20(null);
16614
16692
  const restoreFromUrl = useCallback15(async () => {
16615
16693
  setRestoreAttempted(true);
16616
16694
  const rawHash = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : window.location.hash;