hyperframes 0.8.70 → 0.8.72

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.
@@ -29672,7 +29672,7 @@ function getPreviewPlayerKey({
29672
29672
  }
29673
29673
  var ZOOM_HUD_TIMEOUT_MS = 1200;
29674
29674
  var ZOOM_SETTLE_MS = 200;
29675
- var PREVIEW_STAGE_INSET_PX = 16;
29675
+ var PREVIEW_STAGE_INSET_PX = 8;
29676
29676
  var SHADOW_IFRAME_STYLE = {
29677
29677
  position: "absolute",
29678
29678
  inset: 0,
@@ -29691,9 +29691,9 @@ function loadInitialZoom() {
29691
29691
  panY: stored.panY
29692
29692
  } : DEFAULT_PREVIEW_ZOOM;
29693
29693
  }
29694
- function resolvePreviewStageSize(viewportWidth, viewportHeight, compositionSize, portrait, gutterPx = 0) {
29695
- const availableWidth = Math.max(0, viewportWidth - PREVIEW_STAGE_INSET_PX - 2 * gutterPx);
29696
- const availableHeight = Math.max(0, viewportHeight - PREVIEW_STAGE_INSET_PX - 2 * gutterPx);
29694
+ function resolvePreviewStageSize(viewportWidth, viewportHeight, compositionSize, portrait, gutterPx = 0, insetPx = PREVIEW_STAGE_INSET_PX) {
29695
+ const availableWidth = Math.max(0, viewportWidth - 2 * (insetPx + gutterPx));
29696
+ const availableHeight = Math.max(0, viewportHeight - 2 * (insetPx + gutterPx));
29697
29697
  const aspectRatio = compositionSize && compositionSize.width > 0 && compositionSize.height > 0 ? compositionSize.width / compositionSize.height : portrait ? 9 / 16 : 16 / 9;
29698
29698
  if (availableWidth === 0 || availableHeight === 0) {
29699
29699
  return { width: 0, height: 0 };
@@ -29724,7 +29724,8 @@ var NLEPreview = memo19(function NLEPreview2({
29724
29724
  directUrl,
29725
29725
  suppressLoadingOverlay,
29726
29726
  onStageRef,
29727
- onCompositionSizeChange
29727
+ onCompositionSizeChange,
29728
+ fillBox
29728
29729
  }) {
29729
29730
  const activeKey = getPreviewPlayerKey({ projectId, directUrl });
29730
29731
  const viewportRef = useRef56(null);
@@ -29743,6 +29744,7 @@ var NLEPreview = memo19(function NLEPreview2({
29743
29744
  const reportPreviewFirstFrame = usePreviewFirstFrameTelemetry(previewSlots);
29744
29745
  const [compositionSize, setCompositionSize] = useState37(null);
29745
29746
  const gutterPx = usePreviewGuidesStore((s) => s.rulerVisible ? RULER_GUTTER_PX : 0);
29747
+ const insetPx = fillBox ? 0 : PREVIEW_STAGE_INSET_PX;
29746
29748
  const [stageSize, setStageSize] = useState37(() => resolvePreviewStageSize(0, 0, null, portrait));
29747
29749
  const zoomRef = useRef56(loadInitialZoom());
29748
29750
  const [settledZoom, setSettledZoom] = useState37(() => zoomRef.current);
@@ -29763,14 +29765,21 @@ var NLEPreview = memo19(function NLEPreview2({
29763
29765
  const updateStageSize = () => {
29764
29766
  const rect = viewport.getBoundingClientRect();
29765
29767
  setStageSize(
29766
- resolvePreviewStageSize(rect.width, rect.height, compositionSize, portrait, gutterPx)
29768
+ resolvePreviewStageSize(
29769
+ rect.width,
29770
+ rect.height,
29771
+ compositionSize,
29772
+ portrait,
29773
+ gutterPx,
29774
+ insetPx
29775
+ )
29767
29776
  );
29768
29777
  };
29769
29778
  updateStageSize();
29770
29779
  const observer = new ResizeObserver(updateStageSize);
29771
29780
  observer.observe(viewport);
29772
29781
  return () => observer.disconnect();
29773
- }, [compositionSize, portrait, gutterPx]);
29782
+ }, [compositionSize, portrait, gutterPx, insetPx]);
29774
29783
  const onCompositionSizeChangeRef = useRef56(onCompositionSizeChange);
29775
29784
  onCompositionSizeChangeRef.current = onCompositionSizeChange;
29776
29785
  const updateCompositionSizeFromPreview = useCallback45(() => {
@@ -29996,77 +30005,84 @@ var NLEPreview = memo19(function NLEPreview2({
29996
30005
  "div",
29997
30006
  {
29998
30007
  ref: viewportRef,
29999
- className: "relative flex-1 flex items-center justify-center p-2 overflow-hidden min-h-0 outline-hidden focus:ring-1 focus:ring-studio-accent/40 bg-[var(--studio-preview-bg,var(--color-neutral-950))]",
30008
+ className: "relative flex-1 flex items-center justify-center overflow-hidden min-h-0 outline-hidden focus:ring-1 focus:ring-studio-accent/40 bg-[var(--studio-preview-bg,var(--color-neutral-950))]",
30000
30009
  tabIndex: 0,
30001
30010
  "aria-label": "Composition preview",
30002
30011
  children: [
30003
- /* @__PURE__ */ jsx86("div", { className: "absolute inset-2 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs61(
30012
+ /* @__PURE__ */ jsx86(
30004
30013
  "div",
30005
30014
  {
30006
- ref: stageRef,
30007
- className: "relative shrink-0 pointer-events-auto",
30008
- style: {
30009
- width: `${stageSize.width}px`,
30010
- height: `${stageSize.height}px`,
30011
- transform: `translate3d(${toDomPrecision(initial.panX)}px, ${toDomPrecision(initial.panY)}px, 0) scale(${toDomPrecision(initial.zoomPercent / 100)})`,
30012
- // resolvePreviewWheelZoom cursor math assumes center-center pivot
30013
- transformOrigin: "center center"
30014
- },
30015
- "data-testid": "preview-zoom-stage",
30016
- children: [
30017
- directUrl?.includes("/components/") && /* @__PURE__ */ jsx86(
30018
- Player,
30019
- {
30020
- projectId,
30021
- onLoad: () => {
30022
- },
30023
- portrait,
30024
- suppressLoadingOverlay: true,
30025
- style: { position: "absolute", inset: 0, zIndex: 0 }
30015
+ className: "absolute flex items-center justify-center pointer-events-none",
30016
+ style: { inset: insetPx },
30017
+ children: /* @__PURE__ */ jsxs61(
30018
+ "div",
30019
+ {
30020
+ ref: stageRef,
30021
+ className: "relative shrink-0 pointer-events-auto",
30022
+ style: {
30023
+ width: `${stageSize.width}px`,
30024
+ height: `${stageSize.height}px`,
30025
+ transform: `translate3d(${toDomPrecision(initial.panX)}px, ${toDomPrecision(initial.panY)}px, 0) scale(${toDomPrecision(initial.zoomPercent / 100)})`,
30026
+ // resolvePreviewWheelZoom cursor math assumes center-center pivot
30027
+ transformOrigin: "center center"
30026
30028
  },
30027
- `backdrop-${projectId}`
30028
- ),
30029
- previewSlots.map(
30030
- (slot) => slot.role === "live" ? /* @__PURE__ */ jsx86(
30031
- Player,
30032
- {
30033
- ref: setPreviewIframeRef,
30034
- projectId: directUrl ? void 0 : projectId,
30035
- directUrl,
30036
- onLoad: () => {
30037
- updateCompositionSizeFromPreview();
30038
- onIframeLoad();
30039
- applyInitialZoom();
30040
- },
30041
- onCompositionLoadingChange,
30042
- onPainted: (details) => reportPreviewFirstFrame(slot, details),
30043
- portrait,
30044
- suppressLoadingOverlay,
30045
- style: directUrl?.includes("/components/") ? { position: "absolute", inset: 0, zIndex: 1 } : void 0
30046
- },
30047
- `${activeKey}-${slot.gen}`
30048
- ) : (
30049
- // Loads hidden behind the live slot until promoted.
30050
- /* @__PURE__ */ jsx86(
30029
+ "data-testid": "preview-zoom-stage",
30030
+ children: [
30031
+ directUrl?.includes("/components/") && /* @__PURE__ */ jsx86(
30051
30032
  Player,
30052
30033
  {
30053
- ref: setShadowIframeNode,
30054
- directUrl: slot.url,
30055
- onLoad: () => onShadowIframeLoad(slot.gen),
30056
- onReadyToShowChange: (ready) => onShadowReadyChange(slot.gen, ready),
30057
- onPainted: (details) => reportPreviewFirstFrame(slot, details),
30058
- onPreviewError: (message) => onShadowError(slot.gen, message),
30034
+ projectId,
30035
+ onLoad: () => {
30036
+ },
30059
30037
  portrait,
30060
30038
  suppressLoadingOverlay: true,
30061
- style: SHADOW_IFRAME_STYLE
30039
+ style: { position: "absolute", inset: 0, zIndex: 0 }
30062
30040
  },
30063
- `${activeKey}-${slot.gen}`
30041
+ `backdrop-${projectId}`
30042
+ ),
30043
+ previewSlots.map(
30044
+ (slot) => slot.role === "live" ? /* @__PURE__ */ jsx86(
30045
+ Player,
30046
+ {
30047
+ ref: setPreviewIframeRef,
30048
+ projectId: directUrl ? void 0 : projectId,
30049
+ directUrl,
30050
+ onLoad: () => {
30051
+ updateCompositionSizeFromPreview();
30052
+ onIframeLoad();
30053
+ applyInitialZoom();
30054
+ },
30055
+ onCompositionLoadingChange,
30056
+ onPainted: (details) => reportPreviewFirstFrame(slot, details),
30057
+ portrait,
30058
+ suppressLoadingOverlay,
30059
+ style: directUrl?.includes("/components/") ? { position: "absolute", inset: 0, zIndex: 1 } : void 0
30060
+ },
30061
+ `${activeKey}-${slot.gen}`
30062
+ ) : (
30063
+ // Loads hidden behind the live slot until promoted.
30064
+ /* @__PURE__ */ jsx86(
30065
+ Player,
30066
+ {
30067
+ ref: setShadowIframeNode,
30068
+ directUrl: slot.url,
30069
+ onLoad: () => onShadowIframeLoad(slot.gen),
30070
+ onReadyToShowChange: (ready) => onShadowReadyChange(slot.gen, ready),
30071
+ onPainted: (details) => reportPreviewFirstFrame(slot, details),
30072
+ onPreviewError: (message) => onShadowError(slot.gen, message),
30073
+ portrait,
30074
+ suppressLoadingOverlay: true,
30075
+ style: SHADOW_IFRAME_STYLE
30076
+ },
30077
+ `${activeKey}-${slot.gen}`
30078
+ )
30079
+ )
30064
30080
  )
30065
- )
30066
- )
30067
- ]
30081
+ ]
30082
+ }
30083
+ )
30068
30084
  }
30069
- ) }),
30085
+ ),
30070
30086
  /* @__PURE__ */ jsx86(
30071
30087
  "div",
30072
30088
  {
@@ -69159,6 +69175,22 @@ function ProjectUnreachableBanner({ projectId }) {
69159
69175
  );
69160
69176
  }
69161
69177
 
69178
+ // src/components/CompositionMissingBanner.tsx
69179
+ import { jsx as jsx199, jsxs as jsxs158 } from "react/jsx-runtime";
69180
+ function CompositionMissingBanner({ path }) {
69181
+ return /* @__PURE__ */ jsx199(
69182
+ "div",
69183
+ {
69184
+ role: "alert",
69185
+ className: "hf-backdrop-in absolute left-1/2 top-14 z-92 flex max-w-[calc(100vw-32px)] -translate-x-1/2 items-center gap-3 rounded-md border border-amber-500/30 bg-amber-950/85 px-4 py-2 text-[12px] font-medium text-amber-100 shadow-lg shadow-black/30",
69186
+ children: /* @__PURE__ */ jsxs158("span", { children: [
69187
+ /* @__PURE__ */ jsx199("strong", { children: path }),
69188
+ " is no longer on disk. Select another composition to keep editing."
69189
+ ] })
69190
+ }
69191
+ );
69192
+ }
69193
+
69162
69194
  // src/captions/hooks/useCaptionSync.ts
69163
69195
  import { useCallback as useCallback92, useRef as useRef127 } from "react";
69164
69196
  function buildOverrides(model) {
@@ -79885,7 +79917,7 @@ function disposeSdkSession(session) {
79885
79917
  });
79886
79918
  }
79887
79919
  }
79888
- function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded = false) {
79920
+ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded = false, onAbsentRead) {
79889
79921
  const [ownedSession, setOwnedSession] = useState117(null);
79890
79922
  const ownedSessionRef = useRef154(null);
79891
79923
  const sessionOwnersRef = useRef154(/* @__PURE__ */ new WeakMap());
@@ -79898,6 +79930,21 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79898
79930
  const reloadTokenRef = useRef154(reloadToken);
79899
79931
  reloadTokenRef.current = reloadToken;
79900
79932
  const [unreachableProject, setUnreachableProject] = useState117(null);
79933
+ const [compositionMissing, setCompositionMissing] = useState117(false);
79934
+ const refreshedAbsentPathsRef = useRef154(/* @__PURE__ */ new Set());
79935
+ useEffect118(() => {
79936
+ refreshedAbsentPathsRef.current.clear();
79937
+ }, [projectId]);
79938
+ function handleReadFailure(read, forProjectId, forPath) {
79939
+ const pathInTree = fileTreeLoaded ? fileTree.includes(forPath) : null;
79940
+ setUnreachableProject(reportReadFailure(read, forProjectId, pathInTree));
79941
+ setCompositionMissing(read.reason === "absent");
79942
+ if (read.reason !== "absent") return;
79943
+ const key2 = `${forProjectId}:${forPath}`;
79944
+ if (refreshedAbsentPathsRef.current.has(key2)) return;
79945
+ refreshedAbsentPathsRef.current.add(key2);
79946
+ onAbsentRead?.(forPath);
79947
+ }
79901
79948
  useEffect118(
79902
79949
  () => addExternalFileReloadListener((changedPath) => {
79903
79950
  if (changedPath === activeCompPathRef.current) setReloadToken((token) => token + 1);
@@ -79913,6 +79960,7 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79913
79960
  if (previous) disposeSdkSession(previous.session);
79914
79961
  if (!projectId || !activeCompPath) {
79915
79962
  setUnreachableProject(null);
79963
+ setCompositionMissing(false);
79916
79964
  return () => {
79917
79965
  cancelled = true;
79918
79966
  };
@@ -79926,11 +79974,11 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79926
79974
  readProjectFileOptional(projectId, activeCompPath).then(async (read) => {
79927
79975
  if (cancelled) return;
79928
79976
  if (!read.ok) {
79929
- const pathInTree = fileTreeLoaded ? fileTree.includes(activeCompPath) : null;
79930
- setUnreachableProject(reportReadFailure(read, projectId, pathInTree));
79977
+ handleReadFailure(read, projectId, activeCompPath);
79931
79978
  return;
79932
79979
  }
79933
79980
  setUnreachableProject(null);
79981
+ setCompositionMissing(false);
79934
79982
  const content = read.content;
79935
79983
  const comp = await openComposition3(content, { history: false });
79936
79984
  if (cancelled) {
@@ -79996,16 +80044,17 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79996
80044
  return "published";
79997
80045
  }, []);
79998
80046
  const session = ownedSession?.projectId === projectId && ownedSession.path === activeCompPath && ownedSession.reloadToken === reloadToken ? ownedSession.session : null;
79999
- return { session, publish, forceReload, unreachableProject };
80047
+ return { session, publish, forceReload, unreachableProject, compositionMissing };
80000
80048
  }
80001
80049
 
80002
80050
  // src/hooks/useStudioSdkSessions.ts
80003
- function useStudioSdkSessions(projectId, activeCompPath, masterCompPath, fileTree = [], fileTreeLoaded = false) {
80051
+ function useStudioSdkSessions(projectId, activeCompPath, masterCompPath, fileTree = [], fileTreeLoaded = false, refreshFileTree) {
80004
80052
  const sdkHandle = useSdkSession(
80005
80053
  projectId,
80006
80054
  activeCompPath ?? masterCompPath,
80007
80055
  fileTree,
80008
- fileTreeLoaded
80056
+ fileTreeLoaded,
80057
+ refreshFileTree
80009
80058
  );
80010
80059
  const editFlowSdkSession = activeCompPath ? sdkHandle.session : null;
80011
80060
  useEffect119(() => {
@@ -80165,7 +80214,8 @@ function useExternalFileChangeCoordinator({
80165
80214
  readProjectFile,
80166
80215
  onUseExternalFile,
80167
80216
  resetSaveQueues,
80168
- onAcceptedPersistedFileChange
80217
+ onAcceptedPersistedFileChange,
80218
+ refreshFileTree
80169
80219
  }) {
80170
80220
  const [blocked, setBlocked] = useState118(null);
80171
80221
  const generationRef = useRef155(0);
@@ -80231,8 +80281,9 @@ function useExternalFileChangeCoordinator({
80231
80281
  logReload("reload", { path, by: "external-change coordinator" });
80232
80282
  reloadPreview();
80233
80283
  reloadSdkSession(path);
80284
+ void refreshFileTree?.();
80234
80285
  },
80235
- [reloadPreview, reloadSdkSession]
80286
+ [reloadPreview, reloadSdkSession, refreshFileTree]
80236
80287
  );
80237
80288
  const persistSnapshotInOrder = useCallback137(async (write) => {
80238
80289
  const next = snapshotWriteTailRef.current.catch(() => void 0).then(write);
@@ -80533,7 +80584,8 @@ function useStudioExternalFileChanges({
80533
80584
  readProjectFile: fileManager.readProjectFile,
80534
80585
  onUseExternalFile: fileManager.updateEditingFileContent,
80535
80586
  resetSaveQueues: resetDomEditSaveQueueBreaker,
80536
- onAcceptedPersistedFileChange
80587
+ onAcceptedPersistedFileChange,
80588
+ refreshFileTree: fileManager.refreshFileTree
80537
80589
  });
80538
80590
  }
80539
80591
 
@@ -83534,7 +83586,7 @@ function useGestureCommit({
83534
83586
 
83535
83587
  // src/components/editor/GestureTrailOverlay.tsx
83536
83588
  import { memo as memo40, useMemo as useMemo72 } from "react";
83537
- import { Fragment as Fragment52, jsx as jsx199, jsxs as jsxs158 } from "react/jsx-runtime";
83589
+ import { Fragment as Fragment52, jsx as jsx200, jsxs as jsxs159 } from "react/jsx-runtime";
83538
83590
  var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83539
83591
  samples,
83540
83592
  sampleCount,
@@ -83576,7 +83628,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83576
83628
  return pts.sort((a, b) => a.pct - b.pct);
83577
83629
  }, [simplifiedPoints]);
83578
83630
  if (!canvasRect || samples.length < 2 && !simplifiedPoints) return null;
83579
- return /* @__PURE__ */ jsxs158(
83631
+ return /* @__PURE__ */ jsxs159(
83580
83632
  "svg",
83581
83633
  {
83582
83634
  className: "pointer-events-none fixed z-50",
@@ -83588,7 +83640,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83588
83640
  },
83589
83641
  viewBox: trail2 && trail2.length > 1 ? `0 0 ${canvasRect.width} ${canvasRect.height}` : `0 0 ${compositionSize?.width ?? canvasRect.width} ${compositionSize?.height ?? canvasRect.height}`,
83590
83642
  children: [
83591
- mode === "recording" && trailPoints && /* @__PURE__ */ jsx199(
83643
+ mode === "recording" && trailPoints && /* @__PURE__ */ jsx200(
83592
83644
  "polyline",
83593
83645
  {
83594
83646
  points: trailPoints,
@@ -83600,8 +83652,8 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83600
83652
  strokeLinejoin: "round"
83601
83653
  }
83602
83654
  ),
83603
- mode === "preview" && /* @__PURE__ */ jsxs158(Fragment52, { children: [
83604
- trailPoints && /* @__PURE__ */ jsx199(
83655
+ mode === "preview" && /* @__PURE__ */ jsxs159(Fragment52, { children: [
83656
+ trailPoints && /* @__PURE__ */ jsx200(
83605
83657
  "polyline",
83606
83658
  {
83607
83659
  points: trailPoints,
@@ -83613,7 +83665,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83613
83665
  strokeLinecap: "round"
83614
83666
  }
83615
83667
  ),
83616
- simplifiedPath && /* @__PURE__ */ jsx199(
83668
+ simplifiedPath && /* @__PURE__ */ jsx200(
83617
83669
  "polyline",
83618
83670
  {
83619
83671
  points: simplifiedPath,
@@ -83625,7 +83677,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83625
83677
  strokeLinejoin: "round"
83626
83678
  }
83627
83679
  ),
83628
- diamondPositions.map((pt) => /* @__PURE__ */ jsx199("g", { transform: `translate(${pt.x}, ${pt.y})`, children: /* @__PURE__ */ jsx199(
83680
+ diamondPositions.map((pt) => /* @__PURE__ */ jsx200("g", { transform: `translate(${pt.x}, ${pt.y})`, children: /* @__PURE__ */ jsx200(
83629
83681
  "rect",
83630
83682
  {
83631
83683
  x: "-4",
@@ -83649,10 +83701,10 @@ import { useCallback as useCallback158 } from "react";
83649
83701
 
83650
83702
  // src/components/MediaPreview.tsx
83651
83703
  import { useState as useState127 } from "react";
83652
- import { jsx as jsx200, jsxs as jsxs159 } from "react/jsx-runtime";
83704
+ import { jsx as jsx201, jsxs as jsxs160 } from "react/jsx-runtime";
83653
83705
  function MediaErrorPanel({ name, filePath }) {
83654
- return /* @__PURE__ */ jsxs159("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-2", children: [
83655
- /* @__PURE__ */ jsxs159(
83706
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-2", children: [
83707
+ /* @__PURE__ */ jsxs160(
83656
83708
  "svg",
83657
83709
  {
83658
83710
  width: "40",
@@ -83664,15 +83716,15 @@ function MediaErrorPanel({ name, filePath }) {
83664
83716
  className: "text-neutral-600",
83665
83717
  "aria-hidden": "true",
83666
83718
  children: [
83667
- /* @__PURE__ */ jsx200("circle", { cx: "12", cy: "12", r: "10" }),
83668
- /* @__PURE__ */ jsx200("line", { x1: "12", y1: "8", x2: "12", y2: "12", strokeLinecap: "round" }),
83669
- /* @__PURE__ */ jsx200("line", { x1: "12", y1: "16", x2: "12.01", y2: "16", strokeLinecap: "round" })
83719
+ /* @__PURE__ */ jsx201("circle", { cx: "12", cy: "12", r: "10" }),
83720
+ /* @__PURE__ */ jsx201("line", { x1: "12", y1: "8", x2: "12", y2: "12", strokeLinecap: "round" }),
83721
+ /* @__PURE__ */ jsx201("line", { x1: "12", y1: "16", x2: "12.01", y2: "16", strokeLinecap: "round" })
83670
83722
  ]
83671
83723
  }
83672
83724
  ),
83673
- /* @__PURE__ */ jsx200("span", { className: "text-sm text-neutral-400 font-medium", children: name }),
83674
- /* @__PURE__ */ jsx200("span", { className: "text-[11px] text-neutral-600 font-mono", children: filePath }),
83675
- /* @__PURE__ */ jsx200("span", { className: "text-[10px] text-neutral-500", children: "Couldn't load this file \u2014 it may be missing or corrupt" })
83725
+ /* @__PURE__ */ jsx201("span", { className: "text-sm text-neutral-400 font-medium", children: name }),
83726
+ /* @__PURE__ */ jsx201("span", { className: "text-[11px] text-neutral-600 font-mono", children: filePath }),
83727
+ /* @__PURE__ */ jsx201("span", { className: "text-[10px] text-neutral-500", children: "Couldn't load this file \u2014 it may be missing or corrupt" })
83676
83728
  ] });
83677
83729
  }
83678
83730
  function MediaPreview({ projectId, filePath }) {
@@ -83681,10 +83733,10 @@ function MediaPreview({ projectId, filePath }) {
83681
83733
  const [failedPath, setFailedPath] = useState127(null);
83682
83734
  const failed2 = failedPath === filePath;
83683
83735
  const setFailed = () => setFailedPath(filePath);
83684
- if (failed2) return /* @__PURE__ */ jsx200(MediaErrorPanel, { name, filePath });
83736
+ if (failed2) return /* @__PURE__ */ jsx201(MediaErrorPanel, { name, filePath });
83685
83737
  if (IMAGE_EXT.test(filePath)) {
83686
- return /* @__PURE__ */ jsxs159("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950", children: [
83687
- /* @__PURE__ */ jsx200(
83738
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950", children: [
83739
+ /* @__PURE__ */ jsx201(
83688
83740
  "img",
83689
83741
  {
83690
83742
  src: serveUrl,
@@ -83693,12 +83745,12 @@ function MediaPreview({ projectId, filePath }) {
83693
83745
  className: "max-w-full max-h-[70%] object-contain rounded-sm border border-neutral-800"
83694
83746
  }
83695
83747
  ),
83696
- /* @__PURE__ */ jsx200("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83748
+ /* @__PURE__ */ jsx201("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83697
83749
  ] });
83698
83750
  }
83699
83751
  if (VIDEO_EXT.test(filePath)) {
83700
- return /* @__PURE__ */ jsxs159("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950", children: [
83701
- /* @__PURE__ */ jsx200(
83752
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950", children: [
83753
+ /* @__PURE__ */ jsx201(
83702
83754
  "video",
83703
83755
  {
83704
83756
  src: serveUrl,
@@ -83707,12 +83759,12 @@ function MediaPreview({ projectId, filePath }) {
83707
83759
  className: "max-w-full max-h-[70%] rounded-sm border border-neutral-800"
83708
83760
  }
83709
83761
  ),
83710
- /* @__PURE__ */ jsx200("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83762
+ /* @__PURE__ */ jsx201("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83711
83763
  ] });
83712
83764
  }
83713
83765
  if (AUDIO_EXT.test(filePath)) {
83714
- return /* @__PURE__ */ jsxs159("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-3", children: [
83715
- /* @__PURE__ */ jsxs159(
83766
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-3", children: [
83767
+ /* @__PURE__ */ jsxs160(
83716
83768
  "svg",
83717
83769
  {
83718
83770
  width: "48",
@@ -83723,18 +83775,18 @@ function MediaPreview({ projectId, filePath }) {
83723
83775
  strokeWidth: "1.5",
83724
83776
  className: "text-neutral-600",
83725
83777
  children: [
83726
- /* @__PURE__ */ jsx200("path", { d: "M9 18V5l12-2v13", strokeLinecap: "round", strokeLinejoin: "round" }),
83727
- /* @__PURE__ */ jsx200("circle", { cx: "6", cy: "18", r: "3" }),
83728
- /* @__PURE__ */ jsx200("circle", { cx: "18", cy: "16", r: "3" })
83778
+ /* @__PURE__ */ jsx201("path", { d: "M9 18V5l12-2v13", strokeLinecap: "round", strokeLinejoin: "round" }),
83779
+ /* @__PURE__ */ jsx201("circle", { cx: "6", cy: "18", r: "3" }),
83780
+ /* @__PURE__ */ jsx201("circle", { cx: "18", cy: "16", r: "3" })
83729
83781
  ]
83730
83782
  }
83731
83783
  ),
83732
- /* @__PURE__ */ jsx200("audio", { src: serveUrl, controls: true, onError: setFailed, className: "w-full max-w-[280px]" }),
83733
- /* @__PURE__ */ jsx200("span", { className: "text-[11px] text-neutral-500 font-mono", children: filePath })
83784
+ /* @__PURE__ */ jsx201("audio", { src: serveUrl, controls: true, onError: setFailed, className: "w-full max-w-[280px]" }),
83785
+ /* @__PURE__ */ jsx201("span", { className: "text-[11px] text-neutral-500 font-mono", children: filePath })
83734
83786
  ] });
83735
83787
  }
83736
- return /* @__PURE__ */ jsxs159("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-2", children: [
83737
- /* @__PURE__ */ jsxs159(
83788
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-2", children: [
83789
+ /* @__PURE__ */ jsxs160(
83738
83790
  "svg",
83739
83791
  {
83740
83792
  width: "40",
@@ -83745,7 +83797,7 @@ function MediaPreview({ projectId, filePath }) {
83745
83797
  strokeWidth: "1.5",
83746
83798
  className: "text-neutral-600",
83747
83799
  children: [
83748
- /* @__PURE__ */ jsx200(
83800
+ /* @__PURE__ */ jsx201(
83749
83801
  "path",
83750
83802
  {
83751
83803
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
@@ -83753,13 +83805,13 @@ function MediaPreview({ projectId, filePath }) {
83753
83805
  strokeLinejoin: "round"
83754
83806
  }
83755
83807
  ),
83756
- /* @__PURE__ */ jsx200("polyline", { points: "14 2 14 8 20 8", strokeLinecap: "round", strokeLinejoin: "round" })
83808
+ /* @__PURE__ */ jsx201("polyline", { points: "14 2 14 8 20 8", strokeLinecap: "round", strokeLinejoin: "round" })
83757
83809
  ]
83758
83810
  }
83759
83811
  ),
83760
- /* @__PURE__ */ jsx200("span", { className: "text-sm text-neutral-400 font-medium", children: name }),
83761
- /* @__PURE__ */ jsx200("span", { className: "text-[11px] text-neutral-600 font-mono", children: filePath }),
83762
- /* @__PURE__ */ jsx200("span", { className: "text-[10px] text-neutral-600", children: "Binary file \u2014 preview not available" })
83812
+ /* @__PURE__ */ jsx201("span", { className: "text-sm text-neutral-400 font-medium", children: name }),
83813
+ /* @__PURE__ */ jsx201("span", { className: "text-[11px] text-neutral-600 font-mono", children: filePath }),
83814
+ /* @__PURE__ */ jsx201("span", { className: "text-[10px] text-neutral-600", children: "Binary file \u2014 preview not available" })
83763
83815
  ] });
83764
83816
  }
83765
83817
 
@@ -83767,14 +83819,14 @@ function MediaPreview({ projectId, filePath }) {
83767
83819
  import { memo as memo41, useState as useState133, useCallback as useCallback154, useRef as useRef170, useMemo as useMemo74, useEffect as useEffect133 } from "react";
83768
83820
 
83769
83821
  // src/components/ui/SearchInput.tsx
83770
- import { jsx as jsx201, jsxs as jsxs160 } from "react/jsx-runtime";
83822
+ import { jsx as jsx202, jsxs as jsxs161 } from "react/jsx-runtime";
83771
83823
  function SearchInput({ className = "", ...props }) {
83772
- return /* @__PURE__ */ jsxs160(
83824
+ return /* @__PURE__ */ jsxs161(
83773
83825
  "div",
83774
83826
  {
83775
83827
  className: `flex items-center gap-1.5 rounded-md bg-panel-input px-2.5 py-[5px] ${className}`,
83776
83828
  children: [
83777
- /* @__PURE__ */ jsxs160(
83829
+ /* @__PURE__ */ jsxs161(
83778
83830
  "svg",
83779
83831
  {
83780
83832
  width: "12",
@@ -83784,7 +83836,7 @@ function SearchInput({ className = "", ...props }) {
83784
83836
  className: "shrink-0",
83785
83837
  "aria-hidden": "true",
83786
83838
  children: [
83787
- /* @__PURE__ */ jsx201(
83839
+ /* @__PURE__ */ jsx202(
83788
83840
  "circle",
83789
83841
  {
83790
83842
  cx: "116",
@@ -83795,7 +83847,7 @@ function SearchInput({ className = "", ...props }) {
83795
83847
  className: "text-panel-text-5"
83796
83848
  }
83797
83849
  ),
83798
- /* @__PURE__ */ jsx201(
83850
+ /* @__PURE__ */ jsx202(
83799
83851
  "line",
83800
83852
  {
83801
83853
  x1: "170",
@@ -83811,7 +83863,7 @@ function SearchInput({ className = "", ...props }) {
83811
83863
  ]
83812
83864
  }
83813
83865
  ),
83814
- /* @__PURE__ */ jsx201(
83866
+ /* @__PURE__ */ jsx202(
83815
83867
  "input",
83816
83868
  {
83817
83869
  type: "text",
@@ -83880,7 +83932,7 @@ import { classifyWebAudioMediaRoute } from "@hyperframes/core/runtime/web-audio-
83880
83932
 
83881
83933
  // src/components/sidebar/AssetContextMenu.tsx
83882
83934
  import { useCallback as useCallback151, useEffect as useEffect128, useLayoutEffect as useLayoutEffect8, useRef as useRef167, useState as useState128 } from "react";
83883
- import { Fragment as Fragment53, jsx as jsx202, jsxs as jsxs161 } from "react/jsx-runtime";
83935
+ import { Fragment as Fragment53, jsx as jsx203, jsxs as jsxs162 } from "react/jsx-runtime";
83884
83936
  function isValidAssetName(name) {
83885
83937
  return name.length > 0 && !/[/\\]/.test(name) && !name.includes("..");
83886
83938
  }
@@ -83954,7 +84006,7 @@ function ContextMenu3({
83954
84006
  onClose();
83955
84007
  }, [renameDraft, asset, onRename, onClose]);
83956
84008
  const itemCls = "w-full text-left px-3 py-1.5 text-neutral-300 hover:bg-neutral-800 focus-visible:bg-neutral-800 outline-hidden active:bg-neutral-700/70 transition-colors";
83957
- return /* @__PURE__ */ jsx202(
84009
+ return /* @__PURE__ */ jsx203(
83958
84010
  "div",
83959
84011
  {
83960
84012
  className: "fixed inset-0 z-200",
@@ -83963,7 +84015,7 @@ function ContextMenu3({
83963
84015
  e.preventDefault();
83964
84016
  onClose();
83965
84017
  },
83966
- children: /* @__PURE__ */ jsxs161(
84018
+ children: /* @__PURE__ */ jsxs162(
83967
84019
  "div",
83968
84020
  {
83969
84021
  ref: menuRef,
@@ -83973,8 +84025,8 @@ function ContextMenu3({
83973
84025
  style: { left: pos.x, top: pos.y },
83974
84026
  onClick: (e) => e.stopPropagation(),
83975
84027
  children: [
83976
- mode === "menu" && /* @__PURE__ */ jsxs161(Fragment53, { children: [
83977
- onAddAtPlayhead && /* @__PURE__ */ jsx202(
84028
+ mode === "menu" && /* @__PURE__ */ jsxs162(Fragment53, { children: [
84029
+ onAddAtPlayhead && /* @__PURE__ */ jsx203(
83978
84030
  "button",
83979
84031
  {
83980
84032
  role: "menuitem",
@@ -83986,7 +84038,7 @@ function ContextMenu3({
83986
84038
  children: "Add at playhead"
83987
84039
  }
83988
84040
  ),
83989
- /* @__PURE__ */ jsx202(
84041
+ /* @__PURE__ */ jsx203(
83990
84042
  "button",
83991
84043
  {
83992
84044
  role: "menuitem",
@@ -83998,8 +84050,8 @@ function ContextMenu3({
83998
84050
  children: "Copy path"
83999
84051
  }
84000
84052
  ),
84001
- onRename && /* @__PURE__ */ jsx202("button", { role: "menuitem", onClick: () => setMode("rename"), className: itemCls, children: "Rename" }),
84002
- onDelete && /* @__PURE__ */ jsx202(
84053
+ onRename && /* @__PURE__ */ jsx203("button", { role: "menuitem", onClick: () => setMode("rename"), className: itemCls, children: "Rename" }),
84054
+ onDelete && /* @__PURE__ */ jsx203(
84003
84055
  "button",
84004
84056
  {
84005
84057
  role: "menuitem",
@@ -84009,7 +84061,7 @@ function ContextMenu3({
84009
84061
  }
84010
84062
  )
84011
84063
  ] }),
84012
- mode === "confirm-delete" && /* @__PURE__ */ jsx202(
84064
+ mode === "confirm-delete" && /* @__PURE__ */ jsx203(
84013
84065
  DeleteConfirm2,
84014
84066
  {
84015
84067
  name: filename(asset),
@@ -84020,8 +84072,8 @@ function ContextMenu3({
84020
84072
  onCancel: () => setMode("menu")
84021
84073
  }
84022
84074
  ),
84023
- mode === "rename" && /* @__PURE__ */ jsxs161("div", { className: "px-2 py-1.5 flex flex-col gap-1", children: [
84024
- /* @__PURE__ */ jsx202(
84075
+ mode === "rename" && /* @__PURE__ */ jsxs162("div", { className: "px-2 py-1.5 flex flex-col gap-1", children: [
84076
+ /* @__PURE__ */ jsx203(
84025
84077
  "input",
84026
84078
  {
84027
84079
  autoFocus: true,
@@ -84041,9 +84093,9 @@ function ContextMenu3({
84041
84093
  className: "w-full bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-1 text-[11px] text-white focus:border-studio-accent/60 focus:outline-hidden"
84042
84094
  }
84043
84095
  ),
84044
- renameError && /* @__PURE__ */ jsx202("span", { className: "text-[10px] text-red-400", children: renameError }),
84045
- /* @__PURE__ */ jsxs161("div", { className: "flex items-center justify-end gap-1", children: [
84046
- /* @__PURE__ */ jsx202(
84096
+ renameError && /* @__PURE__ */ jsx203("span", { className: "text-[10px] text-red-400", children: renameError }),
84097
+ /* @__PURE__ */ jsxs162("div", { className: "flex items-center justify-end gap-1", children: [
84098
+ /* @__PURE__ */ jsx203(
84047
84099
  "button",
84048
84100
  {
84049
84101
  onClick: () => setMode("menu"),
@@ -84051,7 +84103,7 @@ function ContextMenu3({
84051
84103
  children: "Cancel"
84052
84104
  }
84053
84105
  ),
84054
- /* @__PURE__ */ jsx202(
84106
+ /* @__PURE__ */ jsx203(
84055
84107
  "button",
84056
84108
  {
84057
84109
  onClick: commitRename,
@@ -84072,14 +84124,14 @@ function DeleteConfirm2({
84072
84124
  onConfirm,
84073
84125
  onCancel
84074
84126
  }) {
84075
- return /* @__PURE__ */ jsxs161("div", { className: "px-2 py-1.5 bg-red-950/30 border-l-2 border-red-500 flex items-center justify-between gap-2", children: [
84076
- /* @__PURE__ */ jsxs161("span", { className: "text-[10px] text-red-400 truncate", children: [
84127
+ return /* @__PURE__ */ jsxs162("div", { className: "px-2 py-1.5 bg-red-950/30 border-l-2 border-red-500 flex items-center justify-between gap-2", children: [
84128
+ /* @__PURE__ */ jsxs162("span", { className: "text-[10px] text-red-400 truncate", children: [
84077
84129
  "Delete ",
84078
84130
  name,
84079
84131
  "?"
84080
84132
  ] }),
84081
- /* @__PURE__ */ jsxs161("div", { className: "flex items-center gap-1 shrink-0", children: [
84082
- /* @__PURE__ */ jsx202(
84133
+ /* @__PURE__ */ jsxs162("div", { className: "flex items-center gap-1 shrink-0", children: [
84134
+ /* @__PURE__ */ jsx203(
84083
84135
  "button",
84084
84136
  {
84085
84137
  onClick: onConfirm,
@@ -84087,7 +84139,7 @@ function DeleteConfirm2({
84087
84139
  children: "Delete"
84088
84140
  }
84089
84141
  ),
84090
- /* @__PURE__ */ jsx202(
84142
+ /* @__PURE__ */ jsx203(
84091
84143
  "button",
84092
84144
  {
84093
84145
  onClick: onCancel,
@@ -84129,7 +84181,7 @@ function isPointerClick(dx, dy) {
84129
84181
  }
84130
84182
 
84131
84183
  // src/components/sidebar/AudioRow.tsx
84132
- import { Fragment as Fragment54, jsx as jsx203, jsxs as jsxs162 } from "react/jsx-runtime";
84184
+ import { Fragment as Fragment54, jsx as jsx204, jsxs as jsxs163 } from "react/jsx-runtime";
84133
84185
  var stopCurrentPreview = null;
84134
84186
  function AudioRow({
84135
84187
  projectId,
@@ -84276,8 +84328,8 @@ function AudioRow({
84276
84328
  if (stopCurrentPreview === stopPlayback) stopCurrentPreview = null;
84277
84329
  }
84278
84330
  }, [serveUrl, playing, stopPlayback]);
84279
- return /* @__PURE__ */ jsxs162(Fragment54, { children: [
84280
- /* @__PURE__ */ jsxs162(
84331
+ return /* @__PURE__ */ jsxs163(Fragment54, { children: [
84332
+ /* @__PURE__ */ jsxs163(
84281
84333
  "div",
84282
84334
  {
84283
84335
  draggable: true,
@@ -84304,7 +84356,7 @@ function AudioRow({
84304
84356
  },
84305
84357
  className: `group w-full text-left px-4 py-1.5 flex items-center gap-2.5 transition-colors cursor-pointer outline-hidden focus-visible:bg-neutral-800/60 ${playing ? "bg-panel-accent/6" : isCopied ? "bg-panel-accent/10" : "hover:bg-panel-surface-hover"}`,
84306
84358
  children: [
84307
- /* @__PURE__ */ jsx203(
84359
+ /* @__PURE__ */ jsx204(
84308
84360
  "button",
84309
84361
  {
84310
84362
  "aria-label": playing ? `Pause preview of ${name}` : `Play preview of ${name}`,
@@ -84314,27 +84366,27 @@ function AudioRow({
84314
84366
  e.stopPropagation();
84315
84367
  togglePlay();
84316
84368
  },
84317
- children: playing ? /* @__PURE__ */ jsxs162("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: [
84318
- /* @__PURE__ */ jsx203("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
84319
- /* @__PURE__ */ jsx203("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
84320
- ] }) : /* @__PURE__ */ jsx203("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx203("polygon", { points: "6,4 20,12 6,20" }) })
84369
+ children: playing ? /* @__PURE__ */ jsxs163("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: [
84370
+ /* @__PURE__ */ jsx204("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
84371
+ /* @__PURE__ */ jsx204("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
84372
+ ] }) : /* @__PURE__ */ jsx204("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx204("polygon", { points: "6,4 20,12 6,20" }) })
84321
84373
  }
84322
84374
  ),
84323
- /* @__PURE__ */ jsxs162("div", { className: "min-w-0 flex-1", children: [
84324
- /* @__PURE__ */ jsxs162("div", { className: "flex items-center gap-1.5", children: [
84325
- /* @__PURE__ */ jsx203(
84375
+ /* @__PURE__ */ jsxs163("div", { className: "min-w-0 flex-1", children: [
84376
+ /* @__PURE__ */ jsxs163("div", { className: "flex items-center gap-1.5", children: [
84377
+ /* @__PURE__ */ jsx204(
84326
84378
  "span",
84327
84379
  {
84328
84380
  className: `text-[12px] font-medium truncate ${used ? "text-panel-text-1" : "text-panel-text-3"}`,
84329
84381
  children: name
84330
84382
  }
84331
84383
  ),
84332
- !playing && /* @__PURE__ */ jsxs162("span", { className: "text-[11px] text-panel-text-5 shrink-0", children: [
84384
+ !playing && /* @__PURE__ */ jsxs163("span", { className: "text-[11px] text-panel-text-5 shrink-0", children: [
84333
84385
  meta?.duration ? `${meta.duration}s \xB7 ` : "",
84334
84386
  subtype
84335
84387
  ] }),
84336
- used && /* @__PURE__ */ jsx203("span", { className: "text-[9px] font-medium text-panel-accent bg-panel-accent/10 px-1.5 py-px rounded-sm shrink-0", children: "in use" }),
84337
- (isCopied || copyFailed) && /* @__PURE__ */ jsx203(
84388
+ used && /* @__PURE__ */ jsx204("span", { className: "text-[9px] font-medium text-panel-accent bg-panel-accent/10 px-1.5 py-px rounded-sm shrink-0", children: "in use" }),
84389
+ (isCopied || copyFailed) && /* @__PURE__ */ jsx204(
84338
84390
  "span",
84339
84391
  {
84340
84392
  role: "status",
@@ -84343,7 +84395,7 @@ function AudioRow({
84343
84395
  }
84344
84396
  )
84345
84397
  ] }),
84346
- bars.length > 0 && /* @__PURE__ */ jsx203("div", { className: "flex items-end gap-[2px] h-[14px] mt-0.5", children: bars.map((v, i) => /* @__PURE__ */ jsx203(
84398
+ bars.length > 0 && /* @__PURE__ */ jsx204("div", { className: "flex items-end gap-[2px] h-[14px] mt-0.5", children: bars.map((v, i) => /* @__PURE__ */ jsx204(
84347
84399
  "div",
84348
84400
  {
84349
84401
  className: "flex-1 rounded-[1px]",
@@ -84359,7 +84411,7 @@ function AudioRow({
84359
84411
  ]
84360
84412
  }
84361
84413
  ),
84362
- contextMenu && /* @__PURE__ */ jsx203(
84414
+ contextMenu && /* @__PURE__ */ jsx204(
84363
84415
  ContextMenu3,
84364
84416
  {
84365
84417
  x: contextMenu.x,
@@ -84377,7 +84429,7 @@ function AudioRow({
84377
84429
 
84378
84430
  // src/components/sidebar/GlobalAssetsView.tsx
84379
84431
  import { useEffect as useEffect130, useMemo as useMemo73, useState as useState130 } from "react";
84380
- import { jsx as jsx204, jsxs as jsxs163 } from "react/jsx-runtime";
84432
+ import { jsx as jsx205, jsxs as jsxs164 } from "react/jsx-runtime";
84381
84433
  function globalAssetRows(records, query = "") {
84382
84434
  const q = query.trim().toLowerCase();
84383
84435
  return records.filter(
@@ -84405,28 +84457,28 @@ function GlobalAssetsView({ searchQuery }) {
84405
84457
  }, []);
84406
84458
  const rows = useMemo73(() => globalAssetRows(records ?? [], searchQuery), [records, searchQuery]);
84407
84459
  if (records === null) {
84408
- return /* @__PURE__ */ jsx204("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: "Loading global assets\u2026" });
84460
+ return /* @__PURE__ */ jsx205("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: "Loading global assets\u2026" });
84409
84461
  }
84410
84462
  if (rows.length === 0) {
84411
- return /* @__PURE__ */ jsxs163("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: [
84463
+ return /* @__PURE__ */ jsxs164("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: [
84412
84464
  "No assets in the global cache yet. Resolved media is promoted to ",
84413
- /* @__PURE__ */ jsx204("code", { children: "~/.media" }),
84465
+ /* @__PURE__ */ jsx205("code", { children: "~/.media" }),
84414
84466
  " and becomes reusable across projects."
84415
84467
  ] });
84416
84468
  }
84417
- return /* @__PURE__ */ jsxs163("div", { children: [
84418
- /* @__PURE__ */ jsxs163("div", { className: "px-4 py-2 border-t border-panel-border text-[11px] text-panel-text-5", children: [
84469
+ return /* @__PURE__ */ jsxs164("div", { children: [
84470
+ /* @__PURE__ */ jsxs164("div", { className: "px-4 py-2 border-t border-panel-border text-[11px] text-panel-text-5", children: [
84419
84471
  rows.length,
84420
84472
  " reusable across all projects"
84421
84473
  ] }),
84422
- rows.map((row) => /* @__PURE__ */ jsxs163(
84474
+ rows.map((row) => /* @__PURE__ */ jsxs164(
84423
84475
  "div",
84424
84476
  {
84425
84477
  className: "px-4 py-1.5 flex items-center gap-2.5 border-l-2 border-transparent hover:bg-neutral-800/50",
84426
84478
  title: `${row.id} \xB7 ${row.type}`,
84427
84479
  children: [
84428
- /* @__PURE__ */ jsx204("span", { className: "text-[9px] font-medium text-neutral-600 uppercase w-10 shrink-0", children: row.type }),
84429
- /* @__PURE__ */ jsx204("span", { className: "text-xs text-panel-text-1 truncate", children: row.label })
84480
+ /* @__PURE__ */ jsx205("span", { className: "text-[9px] font-medium text-neutral-600 uppercase w-10 shrink-0", children: row.type }),
84481
+ /* @__PURE__ */ jsx205("span", { className: "text-xs text-panel-text-1 truncate", children: row.label })
84430
84482
  ]
84431
84483
  },
84432
84484
  row.id
@@ -84439,7 +84491,7 @@ import { useState as useState132, useEffect as useEffect132, useRef as useRef169
84439
84491
 
84440
84492
  // src/components/ui/VideoFrameThumbnail.tsx
84441
84493
  import { useState as useState131, useEffect as useEffect131 } from "react";
84442
- import { jsx as jsx205 } from "react/jsx-runtime";
84494
+ import { jsx as jsx206 } from "react/jsx-runtime";
84443
84495
  function VideoFrameThumbnail({
84444
84496
  src,
84445
84497
  fallbackLabel
@@ -84481,16 +84533,16 @@ function VideoFrameThumbnail({
84481
84533
  return cleanup;
84482
84534
  }, [src]);
84483
84535
  if (failed2 && !frame) {
84484
- return /* @__PURE__ */ jsx205("div", { className: "w-full h-full bg-neutral-800 flex items-center justify-center", children: /* @__PURE__ */ jsx205("span", { className: "text-[9px] font-medium text-neutral-600", children: fallbackLabel ?? "VIDEO" }) });
84536
+ return /* @__PURE__ */ jsx206("div", { className: "w-full h-full bg-neutral-800 flex items-center justify-center", children: /* @__PURE__ */ jsx206("span", { className: "text-[9px] font-medium text-neutral-600", children: fallbackLabel ?? "VIDEO" }) });
84485
84537
  }
84486
84538
  if (!frame) {
84487
- return /* @__PURE__ */ jsx205("div", { className: "w-full h-full bg-neutral-800 animate-pulse motion-reduce:animate-none" });
84539
+ return /* @__PURE__ */ jsx206("div", { className: "w-full h-full bg-neutral-800 animate-pulse motion-reduce:animate-none" });
84488
84540
  }
84489
- return /* @__PURE__ */ jsx205("img", { src: frame, alt: "", draggable: false, className: "w-full h-full object-contain" });
84541
+ return /* @__PURE__ */ jsx206("img", { src: frame, alt: "", draggable: false, className: "w-full h-full object-contain" });
84490
84542
  }
84491
84543
 
84492
84544
  // src/components/sidebar/AssetCard.tsx
84493
- import { Fragment as Fragment55, jsx as jsx206, jsxs as jsxs164 } from "react/jsx-runtime";
84545
+ import { Fragment as Fragment55, jsx as jsx207, jsxs as jsxs165 } from "react/jsx-runtime";
84494
84546
  function writeAssetDragData(e, asset) {
84495
84547
  e.dataTransfer.effectAllowed = "copy";
84496
84548
  e.dataTransfer.setData(TIMELINE_ASSET_MIME, JSON.stringify({ path: asset }));
@@ -84498,7 +84550,7 @@ function writeAssetDragData(e, asset) {
84498
84550
  }
84499
84551
  function CopyChip({ feedback, asset }) {
84500
84552
  if (feedback?.path !== asset) return null;
84501
- return /* @__PURE__ */ jsx206(
84553
+ return /* @__PURE__ */ jsx207(
84502
84554
  "span",
84503
84555
  {
84504
84556
  role: "status",
@@ -84617,8 +84669,8 @@ function AssetCard({
84617
84669
  },
84618
84670
  [activateCard]
84619
84671
  );
84620
- return /* @__PURE__ */ jsxs164(Fragment55, { children: [
84621
- /* @__PURE__ */ jsxs164(
84672
+ return /* @__PURE__ */ jsxs165(Fragment55, { children: [
84673
+ /* @__PURE__ */ jsxs165(
84622
84674
  "div",
84623
84675
  {
84624
84676
  draggable: true,
@@ -84640,8 +84692,8 @@ function AssetCard({
84640
84692
  onPointerLeave: () => setHovered(false),
84641
84693
  className: `flex flex-col gap-1 cursor-pointer rounded-md p-1 transition-colors outline-hidden focus-visible:bg-neutral-800/60 ${isCopied ? "bg-studio-accent/10" : "hover:bg-neutral-800/40"}`,
84642
84694
  children: [
84643
- /* @__PURE__ */ jsxs164("div", { className: "w-full aspect-video rounded-sm overflow-hidden bg-neutral-900 relative", children: [
84644
- isImage && !imgError && /* @__PURE__ */ jsx206(
84695
+ /* @__PURE__ */ jsxs165("div", { className: "w-full aspect-video rounded-sm overflow-hidden bg-neutral-900 relative", children: [
84696
+ isImage && !imgError && /* @__PURE__ */ jsx207(
84645
84697
  "img",
84646
84698
  {
84647
84699
  src: serveUrl,
@@ -84651,9 +84703,9 @@ function AssetCard({
84651
84703
  onError: () => setImgError(true)
84652
84704
  }
84653
84705
  ),
84654
- isVideo && /* @__PURE__ */ jsxs164(Fragment55, { children: [
84655
- /* @__PURE__ */ jsx206(VideoFrameThumbnail, { src: serveUrl }),
84656
- hovered && /* @__PURE__ */ jsx206(
84706
+ isVideo && /* @__PURE__ */ jsxs165(Fragment55, { children: [
84707
+ /* @__PURE__ */ jsx207(VideoFrameThumbnail, { src: serveUrl }),
84708
+ hovered && /* @__PURE__ */ jsx207(
84657
84709
  "video",
84658
84710
  {
84659
84711
  src: serveUrl,
@@ -84665,12 +84717,12 @@ function AssetCard({
84665
84717
  }
84666
84718
  )
84667
84719
  ] }),
84668
- (!isImage && !isVideo || isImage && imgError) && /* @__PURE__ */ jsx206("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx206("span", { className: "text-[10px] font-medium text-neutral-600", children: extension }) }),
84669
- used && /* @__PURE__ */ jsx206("span", { className: "absolute top-1 left-1 text-[9px] font-semibold leading-none px-1.5 py-[3px] rounded-sm bg-neutral-950/80 text-panel-text-1", children: "Added" }),
84670
- durationLabel && /* @__PURE__ */ jsx206("span", { className: "absolute top-1 right-1 text-[9px] font-medium leading-none px-1.5 py-[3px] rounded-sm bg-neutral-950/80 text-panel-text-2 tabular-nums", children: durationLabel })
84720
+ (!isImage && !isVideo || isImage && imgError) && /* @__PURE__ */ jsx207("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx207("span", { className: "text-[10px] font-medium text-neutral-600", children: extension }) }),
84721
+ used && /* @__PURE__ */ jsx207("span", { className: "absolute top-1 left-1 text-[9px] font-semibold leading-none px-1.5 py-[3px] rounded-sm bg-neutral-950/80 text-panel-text-1", children: "Added" }),
84722
+ durationLabel && /* @__PURE__ */ jsx207("span", { className: "absolute top-1 right-1 text-[9px] font-medium leading-none px-1.5 py-[3px] rounded-sm bg-neutral-950/80 text-panel-text-2 tabular-nums", children: durationLabel })
84671
84723
  ] }),
84672
- /* @__PURE__ */ jsxs164("div", { className: "flex items-center justify-center gap-1", children: [
84673
- /* @__PURE__ */ jsx206(
84724
+ /* @__PURE__ */ jsxs165("div", { className: "flex items-center justify-center gap-1", children: [
84725
+ /* @__PURE__ */ jsx207(
84674
84726
  "span",
84675
84727
  {
84676
84728
  className: `text-[10px] leading-tight text-center ${used ? "text-panel-text-2" : "text-panel-text-4"}`,
@@ -84678,12 +84730,12 @@ function AssetCard({
84678
84730
  children: truncateMiddle(fullName, 22)
84679
84731
  }
84680
84732
  ),
84681
- /* @__PURE__ */ jsx206(CopyChip, { feedback: copyFeedback, asset })
84733
+ /* @__PURE__ */ jsx207(CopyChip, { feedback: copyFeedback, asset })
84682
84734
  ] })
84683
84735
  ]
84684
84736
  }
84685
84737
  ),
84686
- contextMenu && /* @__PURE__ */ jsx206(
84738
+ contextMenu && /* @__PURE__ */ jsx207(
84687
84739
  ContextMenu3,
84688
84740
  {
84689
84741
  x: contextMenu.x,
@@ -84711,8 +84763,8 @@ function FontRow({
84711
84763
  const name = basename2(asset);
84712
84764
  const extension = ext(asset);
84713
84765
  const isCopied = copyFeedback?.path === asset && copyFeedback.ok;
84714
- return /* @__PURE__ */ jsxs164(Fragment55, { children: [
84715
- /* @__PURE__ */ jsxs164(
84766
+ return /* @__PURE__ */ jsxs165(Fragment55, { children: [
84767
+ /* @__PURE__ */ jsxs165(
84716
84768
  "div",
84717
84769
  {
84718
84770
  draggable: true,
@@ -84731,25 +84783,25 @@ function FontRow({
84731
84783
  onContextMenu: (e) => openAssetContextMenu(e, setContextMenu),
84732
84784
  className: `px-2.5 py-1.5 flex items-center gap-2.5 cursor-pointer transition-colors outline-hidden focus-visible:bg-neutral-800/60 ${isCopied ? "bg-studio-accent/10 border-l-2 border-studio-accent" : "border-l-2 border-transparent hover:bg-neutral-800/50"}`,
84733
84785
  children: [
84734
- /* @__PURE__ */ jsx206("div", { className: "w-[50px] h-[32px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx206("span", { className: "text-[9px] font-medium text-neutral-700", children: extension }) }),
84735
- /* @__PURE__ */ jsxs164("div", { className: "min-w-0 flex-1", children: [
84736
- /* @__PURE__ */ jsx206(
84786
+ /* @__PURE__ */ jsx207("div", { className: "w-[50px] h-[32px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx207("span", { className: "text-[9px] font-medium text-neutral-700", children: extension }) }),
84787
+ /* @__PURE__ */ jsxs165("div", { className: "min-w-0 flex-1", children: [
84788
+ /* @__PURE__ */ jsx207(
84737
84789
  "span",
84738
84790
  {
84739
84791
  className: `text-xs font-medium truncate block ${used ? "text-panel-text-1" : "text-panel-text-3"}`,
84740
84792
  children: name
84741
84793
  }
84742
84794
  ),
84743
- /* @__PURE__ */ jsxs164("div", { className: "flex items-center gap-1.5", children: [
84744
- /* @__PURE__ */ jsx206("span", { className: "text-[10px] text-neutral-600 truncate", children: extension }),
84745
- used && /* @__PURE__ */ jsx206("span", { className: "text-[9px] font-medium text-panel-accent bg-panel-accent/10 px-1.5 py-px rounded-sm", children: "in use" }),
84746
- /* @__PURE__ */ jsx206(CopyChip, { feedback: copyFeedback, asset })
84795
+ /* @__PURE__ */ jsxs165("div", { className: "flex items-center gap-1.5", children: [
84796
+ /* @__PURE__ */ jsx207("span", { className: "text-[10px] text-neutral-600 truncate", children: extension }),
84797
+ used && /* @__PURE__ */ jsx207("span", { className: "text-[9px] font-medium text-panel-accent bg-panel-accent/10 px-1.5 py-px rounded-sm", children: "in use" }),
84798
+ /* @__PURE__ */ jsx207(CopyChip, { feedback: copyFeedback, asset })
84747
84799
  ] })
84748
84800
  ] })
84749
84801
  ]
84750
84802
  }
84751
84803
  ),
84752
- contextMenu && /* @__PURE__ */ jsx206(
84804
+ contextMenu && /* @__PURE__ */ jsx207(
84753
84805
  ContextMenu3,
84754
84806
  {
84755
84807
  x: contextMenu.x,
@@ -84766,7 +84818,7 @@ function FontRow({
84766
84818
  }
84767
84819
 
84768
84820
  // src/components/sidebar/AssetsTab.tsx
84769
- import { Fragment as Fragment56, jsx as jsx207, jsxs as jsxs165 } from "react/jsx-runtime";
84821
+ import { Fragment as Fragment56, jsx as jsx208, jsxs as jsxs166 } from "react/jsx-runtime";
84770
84822
  function filterByUsage(assets, usedPaths, usageFilter) {
84771
84823
  if (usageFilter === "used") return assets.filter((a) => usedPaths.has(a));
84772
84824
  if (usageFilter === "unused") return assets.filter((a) => !usedPaths.has(a));
@@ -84797,7 +84849,7 @@ function deriveUsedPaths(elements) {
84797
84849
  return paths;
84798
84850
  }
84799
84851
  function ImportButton({ importing, onClick }) {
84800
- return /* @__PURE__ */ jsxs165(
84852
+ return /* @__PURE__ */ jsxs166(
84801
84853
  "button",
84802
84854
  {
84803
84855
  onClick,
@@ -84805,8 +84857,8 @@ function ImportButton({ importing, onClick }) {
84805
84857
  "aria-busy": importing,
84806
84858
  className: "w-full flex items-center justify-center gap-1.5 rounded-md bg-panel-input px-3 py-[7px] text-[11px] font-medium text-panel-text-3 enabled:hover:text-panel-text-1 enabled:active:scale-[0.98] disabled:opacity-60 transition-colors mb-2.5",
84807
84859
  children: [
84808
- importing ? /* @__PURE__ */ jsxs165("svg", { className: "animate-spin", width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: [
84809
- /* @__PURE__ */ jsx207(
84860
+ importing ? /* @__PURE__ */ jsxs166("svg", { className: "animate-spin", width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: [
84861
+ /* @__PURE__ */ jsx208(
84810
84862
  "circle",
84811
84863
  {
84812
84864
  className: "opacity-25",
@@ -84817,7 +84869,7 @@ function ImportButton({ importing, onClick }) {
84817
84869
  strokeWidth: "4"
84818
84870
  }
84819
84871
  ),
84820
- /* @__PURE__ */ jsx207(
84872
+ /* @__PURE__ */ jsx208(
84821
84873
  "path",
84822
84874
  {
84823
84875
  className: "opacity-75",
@@ -84825,7 +84877,7 @@ function ImportButton({ importing, onClick }) {
84825
84877
  d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
84826
84878
  }
84827
84879
  )
84828
- ] }) : /* @__PURE__ */ jsx207(
84880
+ ] }) : /* @__PURE__ */ jsx208(
84829
84881
  "svg",
84830
84882
  {
84831
84883
  width: "11",
@@ -84835,7 +84887,7 @@ function ImportButton({ importing, onClick }) {
84835
84887
  stroke: "currentColor",
84836
84888
  strokeWidth: "2.5",
84837
84889
  strokeLinecap: "round",
84838
- children: /* @__PURE__ */ jsx207("path", { d: "M12 5v14M5 12h14" })
84890
+ children: /* @__PURE__ */ jsx208("path", { d: "M12 5v14M5 12h14" })
84839
84891
  }
84840
84892
  ),
84841
84893
  importing ? "Importing\u2026" : "Import media"
@@ -84848,13 +84900,13 @@ function EmptyState({
84848
84900
  onClearSearch
84849
84901
  }) {
84850
84902
  if (searchQuery) {
84851
- return /* @__PURE__ */ jsxs165("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84852
- /* @__PURE__ */ jsxs165("p", { className: "text-[11px] text-neutral-500 text-center", children: [
84903
+ return /* @__PURE__ */ jsxs166("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84904
+ /* @__PURE__ */ jsxs166("p", { className: "text-[11px] text-neutral-500 text-center", children: [
84853
84905
  "No assets match \u201C",
84854
84906
  searchQuery,
84855
84907
  "\u201D"
84856
84908
  ] }),
84857
- /* @__PURE__ */ jsx207(
84909
+ /* @__PURE__ */ jsx208(
84858
84910
  "button",
84859
84911
  {
84860
84912
  type: "button",
@@ -84865,8 +84917,8 @@ function EmptyState({
84865
84917
  )
84866
84918
  ] });
84867
84919
  }
84868
- return /* @__PURE__ */ jsxs165("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84869
- /* @__PURE__ */ jsxs165(
84920
+ return /* @__PURE__ */ jsxs166("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84921
+ /* @__PURE__ */ jsxs166(
84870
84922
  "svg",
84871
84923
  {
84872
84924
  width: "24",
@@ -84877,7 +84929,7 @@ function EmptyState({
84877
84929
  strokeWidth: "1.5",
84878
84930
  className: "text-neutral-700",
84879
84931
  children: [
84880
- /* @__PURE__ */ jsx207(
84932
+ /* @__PURE__ */ jsx208(
84881
84933
  "path",
84882
84934
  {
84883
84935
  d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4",
@@ -84885,12 +84937,12 @@ function EmptyState({
84885
84937
  strokeLinejoin: "round"
84886
84938
  }
84887
84939
  ),
84888
- /* @__PURE__ */ jsx207("polyline", { points: "17 8 12 3 7 8", strokeLinecap: "round", strokeLinejoin: "round" }),
84889
- /* @__PURE__ */ jsx207("line", { x1: "12", y1: "3", x2: "12", y2: "15", strokeLinecap: "round" })
84940
+ /* @__PURE__ */ jsx208("polyline", { points: "17 8 12 3 7 8", strokeLinecap: "round", strokeLinejoin: "round" }),
84941
+ /* @__PURE__ */ jsx208("line", { x1: "12", y1: "3", x2: "12", y2: "15", strokeLinecap: "round" })
84890
84942
  ]
84891
84943
  }
84892
84944
  ),
84893
- /* @__PURE__ */ jsx207("p", { className: "text-[10px] text-neutral-600 text-center", children: "Drop media files here" })
84945
+ /* @__PURE__ */ jsx208("p", { className: "text-[10px] text-neutral-600 text-center", children: "Drop media files here" })
84894
84946
  ] });
84895
84947
  }
84896
84948
  var AssetsTab = memo41(function AssetsTab2({
@@ -85008,7 +85060,7 @@ var AssetsTab = memo41(function AssetsTab2({
85008
85060
  [assets, usedPaths]
85009
85061
  );
85010
85062
  const visibleCategories = activeFilter === "all" ? FILTER_ORDER.filter((c) => categorized[c].length > 0) : [activeFilter].filter((c) => categorized[c].length > 0);
85011
- return /* @__PURE__ */ jsxs165(
85063
+ return /* @__PURE__ */ jsxs166(
85012
85064
  "div",
85013
85065
  {
85014
85066
  className: `flex-1 flex flex-col min-h-0 transition-colors ${dragOver ? "bg-studio-accent/5" : ""}`,
@@ -85019,8 +85071,8 @@ var AssetsTab = memo41(function AssetsTab2({
85019
85071
  onDragLeave: () => setDragOver(false),
85020
85072
  onDrop: handleDrop,
85021
85073
  children: [
85022
- /* @__PURE__ */ jsxs165("div", { className: "px-4 pt-2.5 pb-1.5 shrink-0", children: [
85023
- /* @__PURE__ */ jsx207("div", { className: "flex gap-1 mb-2.5 p-0.5 rounded-md bg-panel-input", children: ["local", "global"].map((m) => /* @__PURE__ */ jsx207(
85074
+ /* @__PURE__ */ jsxs166("div", { className: "px-4 pt-2.5 pb-1.5 shrink-0", children: [
85075
+ /* @__PURE__ */ jsx208("div", { className: "flex gap-1 mb-2.5 p-0.5 rounded-md bg-panel-input", children: ["local", "global"].map((m) => /* @__PURE__ */ jsx208(
85024
85076
  "button",
85025
85077
  {
85026
85078
  onClick: () => setViewMode(m),
@@ -85029,9 +85081,9 @@ var AssetsTab = memo41(function AssetsTab2({
85029
85081
  },
85030
85082
  m
85031
85083
  )) }),
85032
- onImport && /* @__PURE__ */ jsxs165(Fragment56, { children: [
85033
- /* @__PURE__ */ jsx207(ImportButton, { importing, onClick: () => fileInputRef.current?.click() }),
85034
- /* @__PURE__ */ jsx207(
85084
+ onImport && /* @__PURE__ */ jsxs166(Fragment56, { children: [
85085
+ /* @__PURE__ */ jsx208(ImportButton, { importing, onClick: () => fileInputRef.current?.click() }),
85086
+ /* @__PURE__ */ jsx208(
85035
85087
  "input",
85036
85088
  {
85037
85089
  ref: fileInputRef,
@@ -85048,7 +85100,7 @@ var AssetsTab = memo41(function AssetsTab2({
85048
85100
  }
85049
85101
  )
85050
85102
  ] }),
85051
- allMediaAssets.length > 0 && /* @__PURE__ */ jsx207(
85103
+ allMediaAssets.length > 0 && /* @__PURE__ */ jsx208(
85052
85104
  SearchInput,
85053
85105
  {
85054
85106
  value: searchQuery,
@@ -85058,8 +85110,8 @@ var AssetsTab = memo41(function AssetsTab2({
85058
85110
  className: "mb-2"
85059
85111
  }
85060
85112
  ),
85061
- viewMode === "local" && allMediaAssets.length > 0 && /* @__PURE__ */ jsxs165("div", { className: "flex gap-1.5 flex-wrap", children: [
85062
- /* @__PURE__ */ jsxs165(
85113
+ viewMode === "local" && allMediaAssets.length > 0 && /* @__PURE__ */ jsxs166("div", { className: "flex gap-1.5 flex-wrap", children: [
85114
+ /* @__PURE__ */ jsxs166(
85063
85115
  "button",
85064
85116
  {
85065
85117
  onClick: () => setActiveFilter("all"),
@@ -85072,7 +85124,7 @@ var AssetsTab = memo41(function AssetsTab2({
85072
85124
  }
85073
85125
  ),
85074
85126
  FILTER_ORDER.map(
85075
- (cat) => counts[cat] > 0 ? /* @__PURE__ */ jsxs165(
85127
+ (cat) => counts[cat] > 0 ? /* @__PURE__ */ jsxs166(
85076
85128
  "button",
85077
85129
  {
85078
85130
  onClick: () => setActiveFilter(activeFilter === cat ? "all" : cat),
@@ -85087,9 +85139,9 @@ var AssetsTab = memo41(function AssetsTab2({
85087
85139
  cat
85088
85140
  ) : null
85089
85141
  ),
85090
- usageCounts.used > 0 && usageCounts.unused > 0 && /* @__PURE__ */ jsxs165(Fragment56, { children: [
85091
- /* @__PURE__ */ jsx207("span", { className: "w-px self-stretch bg-panel-input mx-0.5", "aria-hidden": "true" }),
85092
- /* @__PURE__ */ jsxs165(
85142
+ usageCounts.used > 0 && usageCounts.unused > 0 && /* @__PURE__ */ jsxs166(Fragment56, { children: [
85143
+ /* @__PURE__ */ jsx208("span", { className: "w-px self-stretch bg-panel-input mx-0.5", "aria-hidden": "true" }),
85144
+ /* @__PURE__ */ jsxs166(
85093
85145
  "button",
85094
85146
  {
85095
85147
  onClick: () => setUsageFilter(usageFilter === "used" ? "all" : "used"),
@@ -85100,7 +85152,7 @@ var AssetsTab = memo41(function AssetsTab2({
85100
85152
  ]
85101
85153
  }
85102
85154
  ),
85103
- /* @__PURE__ */ jsxs165(
85155
+ /* @__PURE__ */ jsxs166(
85104
85156
  "button",
85105
85157
  {
85106
85158
  onClick: () => setUsageFilter(usageFilter === "unused" ? "all" : "unused"),
@@ -85114,12 +85166,12 @@ var AssetsTab = memo41(function AssetsTab2({
85114
85166
  ] })
85115
85167
  ] })
85116
85168
  ] }),
85117
- /* @__PURE__ */ jsx207("div", { className: "flex-1 overflow-y-auto mt-1", children: viewMode === "global" ? /* @__PURE__ */ jsx207(GlobalAssetsView, { searchQuery }) : mediaAssets.length === 0 ? /* @__PURE__ */ jsx207(EmptyState, { searchQuery, onClearSearch: () => setSearchQuery("") }) : visibleCategories.map((cat) => /* @__PURE__ */ jsxs165("div", { className: "mb-1", children: [
85118
- activeFilter === "all" && /* @__PURE__ */ jsxs165("div", { className: "flex items-center gap-2 px-4 py-2 border-t border-panel-border", children: [
85119
- /* @__PURE__ */ jsx207("h3", { className: "text-[12px] font-semibold text-panel-text-1", children: CATEGORY_LABELS[cat] }),
85120
- /* @__PURE__ */ jsx207("span", { className: "text-[11px] text-panel-text-5", children: categorized[cat].length })
85169
+ /* @__PURE__ */ jsx208("div", { className: "flex-1 overflow-y-auto mt-1", children: viewMode === "global" ? /* @__PURE__ */ jsx208(GlobalAssetsView, { searchQuery }) : mediaAssets.length === 0 ? /* @__PURE__ */ jsx208(EmptyState, { searchQuery, onClearSearch: () => setSearchQuery("") }) : visibleCategories.map((cat) => /* @__PURE__ */ jsxs166("div", { className: "mb-1", children: [
85170
+ activeFilter === "all" && /* @__PURE__ */ jsxs166("div", { className: "flex items-center gap-2 px-4 py-2 border-t border-panel-border", children: [
85171
+ /* @__PURE__ */ jsx208("h3", { className: "text-[12px] font-semibold text-panel-text-1", children: CATEGORY_LABELS[cat] }),
85172
+ /* @__PURE__ */ jsx208("span", { className: "text-[11px] text-panel-text-5", children: categorized[cat].length })
85121
85173
  ] }),
85122
- cat === "audio" && categorized[cat].map((a) => /* @__PURE__ */ jsx207(
85174
+ cat === "audio" && categorized[cat].map((a) => /* @__PURE__ */ jsx208(
85123
85175
  AudioRow,
85124
85176
  {
85125
85177
  projectId,
@@ -85134,7 +85186,7 @@ var AssetsTab = memo41(function AssetsTab2({
85134
85186
  },
85135
85187
  a
85136
85188
  )),
85137
- (cat === "images" || cat === "video") && /* @__PURE__ */ jsx207("div", { className: "grid grid-cols-2 gap-1 px-2 pb-1", children: categorized[cat].map((a) => /* @__PURE__ */ jsx207(
85189
+ (cat === "images" || cat === "video") && /* @__PURE__ */ jsx208("div", { className: "grid grid-cols-2 gap-1 px-2 pb-1", children: categorized[cat].map((a) => /* @__PURE__ */ jsx208(
85138
85190
  AssetCard,
85139
85191
  {
85140
85192
  projectId,
@@ -85149,7 +85201,7 @@ var AssetsTab = memo41(function AssetsTab2({
85149
85201
  },
85150
85202
  a
85151
85203
  )) }),
85152
- cat === "fonts" && categorized[cat].map((a) => /* @__PURE__ */ jsx207(
85204
+ cat === "fonts" && categorized[cat].map((a) => /* @__PURE__ */ jsx208(
85153
85205
  FontRow,
85154
85206
  {
85155
85207
  asset: a,
@@ -85174,7 +85226,7 @@ import { createPortal as createPortal9 } from "react-dom";
85174
85226
 
85175
85227
  // src/components/sidebar/PromptPreviewModal.tsx
85176
85228
  import { useState as useState134, useCallback as useCallback155, useEffect as useEffect134, useRef as useRef171 } from "react";
85177
- import { jsx as jsx208, jsxs as jsxs166 } from "react/jsx-runtime";
85229
+ import { jsx as jsx209, jsxs as jsxs167 } from "react/jsx-runtime";
85178
85230
  function PromptPreviewModal({
85179
85231
  title,
85180
85232
  prompt,
@@ -85208,12 +85260,12 @@ function PromptPreviewModal({
85208
85260
  }
85209
85261
  setTimeout(() => setCopyState("idle"), 1500);
85210
85262
  }, []);
85211
- return /* @__PURE__ */ jsx208(
85263
+ return /* @__PURE__ */ jsx209(
85212
85264
  "div",
85213
85265
  {
85214
85266
  className: `fixed inset-0 z-100 flex items-center justify-center bg-black/60 backdrop-blur-xs transition-opacity duration-150 ease-out ${entered ? "opacity-100" : "opacity-0"}`,
85215
85267
  onClick: requestClose,
85216
- children: /* @__PURE__ */ jsxs166(
85268
+ children: /* @__PURE__ */ jsxs167(
85217
85269
  "div",
85218
85270
  {
85219
85271
  ref: containerRef,
@@ -85224,18 +85276,18 @@ function PromptPreviewModal({
85224
85276
  className: "w-[560px] max-h-[80vh] flex flex-col rounded-2xl border border-neutral-800 bg-neutral-950 shadow-2xl outline-hidden",
85225
85277
  onClick: (e) => e.stopPropagation(),
85226
85278
  children: [
85227
- /* @__PURE__ */ jsxs166("div", { className: "flex items-center justify-between px-5 py-4 border-b border-neutral-800/60", children: [
85228
- /* @__PURE__ */ jsxs166("div", { children: [
85229
- /* @__PURE__ */ jsx208("h3", { className: "text-sm font-medium text-neutral-200", children: "Ask agent" }),
85230
- /* @__PURE__ */ jsx208("p", { className: "text-xs text-neutral-500 mt-0.5", children: title })
85279
+ /* @__PURE__ */ jsxs167("div", { className: "flex items-center justify-between px-5 py-4 border-b border-neutral-800/60", children: [
85280
+ /* @__PURE__ */ jsxs167("div", { children: [
85281
+ /* @__PURE__ */ jsx209("h3", { className: "text-sm font-medium text-neutral-200", children: "Ask agent" }),
85282
+ /* @__PURE__ */ jsx209("p", { className: "text-xs text-neutral-500 mt-0.5", children: title })
85231
85283
  ] }),
85232
- /* @__PURE__ */ jsx208(
85284
+ /* @__PURE__ */ jsx209(
85233
85285
  "button",
85234
85286
  {
85235
85287
  "aria-label": "Close",
85236
85288
  className: "p-1 rounded-md text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800/50 active:scale-[0.95]",
85237
85289
  onClick: onClose,
85238
- children: /* @__PURE__ */ jsxs166(
85290
+ children: /* @__PURE__ */ jsxs167(
85239
85291
  "svg",
85240
85292
  {
85241
85293
  width: "14",
@@ -85247,17 +85299,17 @@ function PromptPreviewModal({
85247
85299
  strokeLinecap: "round",
85248
85300
  "aria-hidden": "true",
85249
85301
  children: [
85250
- /* @__PURE__ */ jsx208("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
85251
- /* @__PURE__ */ jsx208("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
85302
+ /* @__PURE__ */ jsx209("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
85303
+ /* @__PURE__ */ jsx209("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
85252
85304
  ]
85253
85305
  }
85254
85306
  )
85255
85307
  }
85256
85308
  )
85257
85309
  ] }),
85258
- /* @__PURE__ */ jsxs166("div", { className: "flex-1 overflow-y-auto px-5 py-4", children: [
85259
- /* @__PURE__ */ jsx208("p", { className: "text-[11px] text-neutral-500 mb-2", children: "Edit the prompt below, then copy and paste into your AI agent" }),
85260
- /* @__PURE__ */ jsx208(
85310
+ /* @__PURE__ */ jsxs167("div", { className: "flex-1 overflow-y-auto px-5 py-4", children: [
85311
+ /* @__PURE__ */ jsx209("p", { className: "text-[11px] text-neutral-500 mb-2", children: "Edit the prompt below, then copy and paste into your AI agent" }),
85312
+ /* @__PURE__ */ jsx209(
85261
85313
  "textarea",
85262
85314
  {
85263
85315
  ref: textareaRef,
@@ -85270,12 +85322,12 @@ function PromptPreviewModal({
85270
85322
  }
85271
85323
  )
85272
85324
  ] }),
85273
- /* @__PURE__ */ jsxs166("div", { className: "flex items-center justify-between px-5 py-3 border-t border-neutral-800/60", children: [
85274
- /* @__PURE__ */ jsxs166("span", { className: "text-[11px] text-neutral-600", children: [
85325
+ /* @__PURE__ */ jsxs167("div", { className: "flex items-center justify-between px-5 py-3 border-t border-neutral-800/60", children: [
85326
+ /* @__PURE__ */ jsxs167("span", { className: "text-[11px] text-neutral-600", children: [
85275
85327
  navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
85276
85328
  "+Enter to copy"
85277
85329
  ] }),
85278
- /* @__PURE__ */ jsx208(
85330
+ /* @__PURE__ */ jsx209(
85279
85331
  "button",
85280
85332
  {
85281
85333
  className: `px-4 py-1.5 rounded-lg text-xs font-medium transition-colors active:scale-[0.97] ${copyState === "copied" ? "bg-emerald-500 text-white" : copyState === "failed" ? "bg-red-500 text-white" : "bg-studio-accent/90 text-neutral-950 hover:bg-studio-accent"}`,
@@ -85292,18 +85344,18 @@ function PromptPreviewModal({
85292
85344
  }
85293
85345
 
85294
85346
  // src/components/sidebar/BlocksTab.tsx
85295
- import { jsx as jsx209, jsxs as jsxs167 } from "react/jsx-runtime";
85347
+ import { jsx as jsx210, jsxs as jsxs168 } from "react/jsx-runtime";
85296
85348
  var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85297
85349
  const { loading, error, search, setSearch, category, setCategory, filteredBlocks } = useBlockCatalog();
85298
85350
  const [promptModal, setPromptModal] = useState135(null);
85299
85351
  if (loading) {
85300
- return /* @__PURE__ */ jsx209("div", { className: "flex flex-1 items-center justify-center text-neutral-600 text-xs", children: "Loading blocks\u2026" });
85352
+ return /* @__PURE__ */ jsx210("div", { className: "flex flex-1 items-center justify-center text-neutral-600 text-xs", children: "Loading blocks\u2026" });
85301
85353
  }
85302
85354
  if (error) {
85303
- return /* @__PURE__ */ jsx209("div", { className: "flex flex-1 items-center justify-center text-red-400 text-xs px-4 text-center", children: error });
85355
+ return /* @__PURE__ */ jsx210("div", { className: "flex flex-1 items-center justify-center text-red-400 text-xs px-4 text-center", children: error });
85304
85356
  }
85305
- return /* @__PURE__ */ jsxs167("div", { className: "flex flex-col flex-1 min-h-0", children: [
85306
- /* @__PURE__ */ jsx209("div", { className: "px-3 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx209(
85357
+ return /* @__PURE__ */ jsxs168("div", { className: "flex flex-col flex-1 min-h-0", children: [
85358
+ /* @__PURE__ */ jsx210("div", { className: "px-3 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx210(
85307
85359
  SearchInput,
85308
85360
  {
85309
85361
  value: search,
@@ -85312,9 +85364,9 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85312
85364
  "aria-label": "Search blocks"
85313
85365
  }
85314
85366
  ) }),
85315
- /* @__PURE__ */ jsx209("div", { className: "px-3 pt-1 pb-2 shrink-0 overflow-x-auto", children: /* @__PURE__ */ jsxs167("div", { className: "flex gap-1", children: [
85316
- /* @__PURE__ */ jsx209(CategoryPill, { label: "All", active: category === null, onClick: () => setCategory(null) }),
85317
- BLOCK_CATEGORIES.map((cat) => /* @__PURE__ */ jsx209(
85367
+ /* @__PURE__ */ jsx210("div", { className: "px-3 pt-1 pb-2 shrink-0 overflow-x-auto", children: /* @__PURE__ */ jsxs168("div", { className: "flex gap-1", children: [
85368
+ /* @__PURE__ */ jsx210(CategoryPill, { label: "All", active: category === null, onClick: () => setCategory(null) }),
85369
+ BLOCK_CATEGORIES.map((cat) => /* @__PURE__ */ jsx210(
85318
85370
  CategoryPill,
85319
85371
  {
85320
85372
  label: cat.label,
@@ -85325,21 +85377,21 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85325
85377
  cat.id
85326
85378
  ))
85327
85379
  ] }) }),
85328
- /* @__PURE__ */ jsxs167("div", { className: "flex-1 overflow-y-auto min-h-0 px-2 pb-2", children: [
85329
- category === "vfx" && /* @__PURE__ */ jsxs167("div", { className: "mb-2 px-2 py-1.5 rounded-md bg-purple-500/10 border border-purple-500/20 text-[9px] text-purple-300 leading-relaxed", children: [
85380
+ /* @__PURE__ */ jsxs168("div", { className: "flex-1 overflow-y-auto min-h-0 px-2 pb-2", children: [
85381
+ category === "vfx" && /* @__PURE__ */ jsxs168("div", { className: "mb-2 px-2 py-1.5 rounded-md bg-purple-500/10 border border-purple-500/20 text-[9px] text-purple-300 leading-relaxed", children: [
85330
85382
  "VFX blocks use WebGL via HTML-in-Canvas. Enable",
85331
85383
  " ",
85332
- /* @__PURE__ */ jsx209("span", { className: "font-mono text-purple-200", children: "chrome://flags/#html-in-canvas" }),
85384
+ /* @__PURE__ */ jsx210("span", { className: "font-mono text-purple-200", children: "chrome://flags/#html-in-canvas" }),
85333
85385
  " for preview."
85334
85386
  ] }),
85335
- filteredBlocks.length === 0 ? /* @__PURE__ */ jsx209("div", { className: "flex items-center justify-center h-32 text-neutral-600 text-xs", children: "No blocks match your search" }) : /* @__PURE__ */ jsx209(
85387
+ filteredBlocks.length === 0 ? /* @__PURE__ */ jsx210("div", { className: "flex items-center justify-center h-32 text-neutral-600 text-xs", children: "No blocks match your search" }) : /* @__PURE__ */ jsx210(
85336
85388
  "div",
85337
85389
  {
85338
85390
  className: "grid gap-1.5",
85339
85391
  style: { gridTemplateColumns: "repeat(auto-fill, minmax(120px, 1fr))" },
85340
85392
  children: filteredBlocks.map((block) => {
85341
85393
  const dur = "duration" in block ? block.duration : void 0;
85342
- return /* @__PURE__ */ jsx209(
85394
+ return /* @__PURE__ */ jsx210(
85343
85395
  BlockCard,
85344
85396
  {
85345
85397
  name: block.name,
@@ -85362,7 +85414,7 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85362
85414
  )
85363
85415
  ] }),
85364
85416
  promptModal && createPortal9(
85365
- /* @__PURE__ */ jsx209(
85417
+ /* @__PURE__ */ jsx210(
85366
85418
  PromptPreviewModal,
85367
85419
  {
85368
85420
  title: promptModal.title,
@@ -85381,7 +85433,7 @@ function CategoryPill({
85381
85433
  onClick
85382
85434
  }) {
85383
85435
  const colors = category ? getCategoryColors(category) : null;
85384
- return /* @__PURE__ */ jsx209(
85436
+ return /* @__PURE__ */ jsx210(
85385
85437
  "button",
85386
85438
  {
85387
85439
  type: "button",
@@ -85551,7 +85603,7 @@ function BlockCard({
85551
85603
  onShowPrompt
85552
85604
  ]
85553
85605
  );
85554
- return /* @__PURE__ */ jsxs167(
85606
+ return /* @__PURE__ */ jsxs168(
85555
85607
  "div",
85556
85608
  {
85557
85609
  className: "group/card rounded-md overflow-hidden cursor-pointer transition-colors bg-neutral-900 hover:bg-neutral-800",
@@ -85565,8 +85617,8 @@ function BlockCard({
85565
85617
  onPointerEnter: handleEnter,
85566
85618
  onPointerLeave: handleLeave,
85567
85619
  children: [
85568
- /* @__PURE__ */ jsxs167("div", { className: "aspect-video w-full overflow-hidden relative", children: [
85569
- hovered && videoUrl ? /* @__PURE__ */ jsx209(
85620
+ /* @__PURE__ */ jsxs168("div", { className: "aspect-video w-full overflow-hidden relative", children: [
85621
+ hovered && videoUrl ? /* @__PURE__ */ jsx210(
85570
85622
  "video",
85571
85623
  {
85572
85624
  src: videoUrl,
@@ -85576,7 +85628,7 @@ function BlockCard({
85576
85628
  playsInline: true,
85577
85629
  className: "w-full h-full object-cover"
85578
85630
  }
85579
- ) : posterUrl ? /* @__PURE__ */ jsx209("img", { src: posterUrl, alt: title, loading: "lazy", className: "w-full h-full object-cover" }) : videoUrl ? /* @__PURE__ */ jsx209(
85631
+ ) : posterUrl ? /* @__PURE__ */ jsx210("img", { src: posterUrl, alt: title, loading: "lazy", className: "w-full h-full object-cover" }) : videoUrl ? /* @__PURE__ */ jsx210(
85580
85632
  "video",
85581
85633
  {
85582
85634
  src: videoUrl,
@@ -85585,9 +85637,9 @@ function BlockCard({
85585
85637
  preload: "metadata",
85586
85638
  className: "w-full h-full object-cover"
85587
85639
  }
85588
- ) : /* @__PURE__ */ jsx209("div", { className: `w-full h-full flex items-center justify-center ${colors.bg}`, children: /* @__PURE__ */ jsx209("span", { className: `text-[9px] font-medium ${colors.text}`, children: category.toUpperCase() }) }),
85589
- /* @__PURE__ */ jsxs167("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-1.5 bg-black/60 opacity-0 group-hover/card:opacity-100 group-focus-within/card:opacity-100 transition-opacity", children: [
85590
- onAdd && /* @__PURE__ */ jsxs167(
85640
+ ) : /* @__PURE__ */ jsx210("div", { className: `w-full h-full flex items-center justify-center ${colors.bg}`, children: /* @__PURE__ */ jsx210("span", { className: `text-[9px] font-medium ${colors.text}`, children: category.toUpperCase() }) }),
85641
+ /* @__PURE__ */ jsxs168("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-1.5 bg-black/60 opacity-0 group-hover/card:opacity-100 group-focus-within/card:opacity-100 transition-opacity", children: [
85642
+ onAdd && /* @__PURE__ */ jsxs168(
85591
85643
  "button",
85592
85644
  {
85593
85645
  type: "button",
@@ -85595,7 +85647,7 @@ function BlockCard({
85595
85647
  title: "Add to composition at current time",
85596
85648
  className: `flex items-center gap-1 px-3 py-1.5 rounded-md text-[10px] font-semibold transition-colors active:scale-[0.97] ${addState === "failed" ? "bg-red-500 text-white" : "bg-white text-black hover:bg-neutral-200"}`,
85597
85649
  children: [
85598
- /* @__PURE__ */ jsx209(
85650
+ /* @__PURE__ */ jsx210(
85599
85651
  "svg",
85600
85652
  {
85601
85653
  width: "10",
@@ -85604,14 +85656,14 @@ function BlockCard({
85604
85656
  fill: "none",
85605
85657
  stroke: "currentColor",
85606
85658
  strokeWidth: "2.5",
85607
- children: /* @__PURE__ */ jsx209("path", { d: "M12 5v14M5 12h14" })
85659
+ children: /* @__PURE__ */ jsx210("path", { d: "M12 5v14M5 12h14" })
85608
85660
  }
85609
85661
  ),
85610
85662
  addState === "adding" ? "Adding\u2026" : addState === "added" ? "Added!" : addState === "failed" ? "Failed" : "Add"
85611
85663
  ]
85612
85664
  }
85613
85665
  ),
85614
- /* @__PURE__ */ jsxs167(
85666
+ /* @__PURE__ */ jsxs168(
85615
85667
  "button",
85616
85668
  {
85617
85669
  type: "button",
@@ -85619,7 +85671,7 @@ function BlockCard({
85619
85671
  title: "Generate a prompt to paste into your AI agent",
85620
85672
  className: `flex items-center gap-1.5 px-3 ${onAdd ? "py-1" : "py-1.5"} rounded-md transition-colors active:scale-[0.97] ${onAdd ? "bg-white/15 text-white/90 hover:bg-white/25 text-[9px]" : "bg-white text-black hover:bg-neutral-200 text-[10px] font-semibold"}`,
85621
85673
  children: [
85622
- /* @__PURE__ */ jsxs167(
85674
+ /* @__PURE__ */ jsxs168(
85623
85675
  "svg",
85624
85676
  {
85625
85677
  width: onAdd ? 9 : 11,
@@ -85629,8 +85681,8 @@ function BlockCard({
85629
85681
  stroke: "currentColor",
85630
85682
  strokeWidth: "2",
85631
85683
  children: [
85632
- /* @__PURE__ */ jsx209("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
85633
- /* @__PURE__ */ jsx209("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
85684
+ /* @__PURE__ */ jsx210("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
85685
+ /* @__PURE__ */ jsx210("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
85634
85686
  ]
85635
85687
  }
85636
85688
  ),
@@ -85639,19 +85691,19 @@ function BlockCard({
85639
85691
  }
85640
85692
  )
85641
85693
  ] }),
85642
- /* @__PURE__ */ jsxs167("div", { className: "absolute top-1 right-1 flex items-center gap-0.5 pointer-events-none", children: [
85643
- needsWebGL && /* @__PURE__ */ jsx209("span", { className: "px-1 py-px rounded-sm text-[7px] font-semibold text-purple-300 bg-purple-900/70", children: "WebGL" }),
85644
- duration != null && /* @__PURE__ */ jsxs167("span", { className: "px-1 py-px rounded-sm text-[8px] font-medium text-white/80 bg-black/50", children: [
85694
+ /* @__PURE__ */ jsxs168("div", { className: "absolute top-1 right-1 flex items-center gap-0.5 pointer-events-none", children: [
85695
+ needsWebGL && /* @__PURE__ */ jsx210("span", { className: "px-1 py-px rounded-sm text-[7px] font-semibold text-purple-300 bg-purple-900/70", children: "WebGL" }),
85696
+ duration != null && /* @__PURE__ */ jsxs168("span", { className: "px-1 py-px rounded-sm text-[8px] font-medium text-white/80 bg-black/50", children: [
85645
85697
  duration,
85646
85698
  "s"
85647
85699
  ] })
85648
85700
  ] })
85649
85701
  ] }),
85650
- /* @__PURE__ */ jsxs167("div", { className: "px-1.5 py-1.5", children: [
85651
- /* @__PURE__ */ jsx209("div", { className: "text-[10px] font-medium text-neutral-200 truncate leading-tight", children: title }),
85652
- /* @__PURE__ */ jsxs167("div", { className: "flex items-center gap-1 mt-0.5", children: [
85653
- /* @__PURE__ */ jsx209("span", { className: `w-1.5 h-1.5 rounded-full shrink-0 ${colors.dot}` }),
85654
- /* @__PURE__ */ jsx209("span", { className: `text-[8px] ${colors.text}`, children: BLOCK_CATEGORIES.find((c) => c.id === category)?.label })
85702
+ /* @__PURE__ */ jsxs168("div", { className: "px-1.5 py-1.5", children: [
85703
+ /* @__PURE__ */ jsx210("div", { className: "text-[10px] font-medium text-neutral-200 truncate leading-tight", children: title }),
85704
+ /* @__PURE__ */ jsxs168("div", { className: "flex items-center gap-1 mt-0.5", children: [
85705
+ /* @__PURE__ */ jsx210("span", { className: `w-1.5 h-1.5 rounded-full shrink-0 ${colors.dot}` }),
85706
+ /* @__PURE__ */ jsx210("span", { className: `text-[8px] ${colors.text}`, children: BLOCK_CATEGORIES.find((c) => c.id === category)?.label })
85655
85707
  ] })
85656
85708
  ] })
85657
85709
  ]
@@ -85661,7 +85713,7 @@ function BlockCard({
85661
85713
 
85662
85714
  // src/components/sidebar/CompositionsTab.tsx
85663
85715
  import { memo as memo43, useCallback as useCallback157, useEffect as useEffect136, useRef as useRef173, useState as useState136 } from "react";
85664
- import { jsx as jsx210, jsxs as jsxs168 } from "react/jsx-runtime";
85716
+ import { jsx as jsx211, jsxs as jsxs169 } from "react/jsx-runtime";
85665
85717
  var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
85666
85718
  var CARD_W = 80;
85667
85719
  var CARD_H = 45;
@@ -85791,7 +85843,7 @@ function CompCard({
85791
85843
  if (syncTimer.current) clearTimeout(syncTimer.current);
85792
85844
  };
85793
85845
  }, []);
85794
- return /* @__PURE__ */ jsxs168(
85846
+ return /* @__PURE__ */ jsxs169(
85795
85847
  "div",
85796
85848
  {
85797
85849
  role: "button",
@@ -85823,8 +85875,8 @@ function CompCard({
85823
85875
  onPointerLeave: handleLeave,
85824
85876
  className: `group/card w-full select-none text-left px-2 py-1.5 flex items-center gap-2.5 transition-colors cursor-grab active:cursor-grabbing outline-hidden focus-visible:bg-neutral-800/60 ${isActive ? "bg-studio-accent/10 border-l-2 border-studio-accent" : "border-l-2 border-transparent hover:bg-neutral-800/50"}`,
85825
85877
  children: [
85826
- /* @__PURE__ */ jsxs168("div", { className: "w-20 h-[45px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 relative", children: [
85827
- thumbnailFailed ? /* @__PURE__ */ jsx210("div", { className: "absolute inset-0 flex items-center justify-center px-1 text-center text-[8px] leading-tight text-neutral-600", children: "Preview unavailable" }) : /* @__PURE__ */ jsx210(
85878
+ /* @__PURE__ */ jsxs169("div", { className: "w-20 h-[45px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 relative", children: [
85879
+ thumbnailFailed ? /* @__PURE__ */ jsx211("div", { className: "absolute inset-0 flex items-center justify-center px-1 text-center text-[8px] leading-tight text-neutral-600", children: "Preview unavailable" }) : /* @__PURE__ */ jsx211(
85828
85880
  "img",
85829
85881
  {
85830
85882
  src: thumbnailUrl2,
@@ -85836,7 +85888,7 @@ function CompCard({
85836
85888
  className: `absolute inset-0 h-full w-full object-contain transition-opacity ${livePreviewLoaded ? "opacity-0" : "opacity-100"}`
85837
85889
  }
85838
85890
  ),
85839
- hovered && /* @__PURE__ */ jsx210(
85891
+ hovered && /* @__PURE__ */ jsx211(
85840
85892
  "iframe",
85841
85893
  {
85842
85894
  ref: iframeRef,
@@ -85869,15 +85921,15 @@ function CompCard({
85869
85921
  }
85870
85922
  )
85871
85923
  ] }),
85872
- /* @__PURE__ */ jsxs168(
85924
+ /* @__PURE__ */ jsxs169(
85873
85925
  "div",
85874
85926
  {
85875
85927
  className: "min-w-0 flex-1",
85876
85928
  title: lintInfo && lintInfo.count > 0 ? lintInfo.messages.join("\n") : void 0,
85877
85929
  children: [
85878
- /* @__PURE__ */ jsxs168("div", { className: "flex items-center gap-1", children: [
85879
- /* @__PURE__ */ jsx210("span", { className: "text-[11px] font-medium text-neutral-300 truncate", children: name }),
85880
- isRoot && /* @__PURE__ */ jsx210(
85930
+ /* @__PURE__ */ jsxs169("div", { className: "flex items-center gap-1", children: [
85931
+ /* @__PURE__ */ jsx211("span", { className: "text-[11px] font-medium text-neutral-300 truncate", children: name }),
85932
+ isRoot && /* @__PURE__ */ jsx211(
85881
85933
  "span",
85882
85934
  {
85883
85935
  "aria-label": "Root composition \u2014 opens automatically on load",
@@ -85886,7 +85938,7 @@ function CompCard({
85886
85938
  children: "Root"
85887
85939
  }
85888
85940
  ),
85889
- lintInfo && lintInfo.count > 0 && /* @__PURE__ */ jsx210(
85941
+ lintInfo && lintInfo.count > 0 && /* @__PURE__ */ jsx211(
85890
85942
  "span",
85891
85943
  {
85892
85944
  "aria-label": `${lintInfo.count} lint finding${lintInfo.count === 1 ? "" : "s"}`,
@@ -85895,11 +85947,11 @@ function CompCard({
85895
85947
  }
85896
85948
  )
85897
85949
  ] }),
85898
- /* @__PURE__ */ jsx210("span", { className: "text-[9px] text-neutral-600 truncate block", children: comp })
85950
+ /* @__PURE__ */ jsx211("span", { className: "text-[9px] text-neutral-600 truncate block", children: comp })
85899
85951
  ]
85900
85952
  }
85901
85953
  ),
85902
- onAddToTimeline && /* @__PURE__ */ jsx210(
85954
+ onAddToTimeline && /* @__PURE__ */ jsx211(
85903
85955
  "button",
85904
85956
  {
85905
85957
  type: "button",
@@ -85910,10 +85962,10 @@ function CompCard({
85910
85962
  onAddToTimeline();
85911
85963
  },
85912
85964
  className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-sm text-neutral-600 opacity-0 transition-[color,background-color,opacity] hover:bg-neutral-800 hover:text-studio-accent group-hover/card:opacity-100 group-focus-within/card:opacity-100 focus:opacity-100",
85913
- children: /* @__PURE__ */ jsx210("span", { "aria-hidden": "true", children: "+" })
85965
+ children: /* @__PURE__ */ jsx211("span", { "aria-hidden": "true", children: "+" })
85914
85966
  }
85915
85967
  ),
85916
- onRender && /* @__PURE__ */ jsx210(Tooltip, { label: isRendering ? "A render is already in progress" : `Render ${name}`, children: /* @__PURE__ */ jsx210(
85968
+ onRender && /* @__PURE__ */ jsx211(Tooltip, { label: isRendering ? "A render is already in progress" : `Render ${name}`, children: /* @__PURE__ */ jsx211(
85917
85969
  "button",
85918
85970
  {
85919
85971
  type: "button",
@@ -85924,7 +85976,7 @@ function CompCard({
85924
85976
  onRender();
85925
85977
  },
85926
85978
  className: `flex h-6 w-6 shrink-0 items-center justify-center rounded transition-colors ${isRendering ? "text-neutral-600 cursor-not-allowed" : "text-neutral-600 hover:text-studio-accent hover:bg-neutral-800"}`,
85927
- children: /* @__PURE__ */ jsxs168(
85979
+ children: /* @__PURE__ */ jsxs169(
85928
85980
  "svg",
85929
85981
  {
85930
85982
  width: "14",
@@ -85937,9 +85989,9 @@ function CompCard({
85937
85989
  strokeLinejoin: "round",
85938
85990
  "aria-hidden": "true",
85939
85991
  children: [
85940
- /* @__PURE__ */ jsx210("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
85941
- /* @__PURE__ */ jsx210("polyline", { points: "7 10 12 15 17 10" }),
85942
- /* @__PURE__ */ jsx210("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
85992
+ /* @__PURE__ */ jsx211("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
85993
+ /* @__PURE__ */ jsx211("polyline", { points: "7 10 12 15 17 10" }),
85994
+ /* @__PURE__ */ jsx211("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
85943
85995
  ]
85944
85996
  }
85945
85997
  )
@@ -85962,9 +86014,9 @@ var CompositionsTab = memo43(function CompositionsTab2({
85962
86014
  }) {
85963
86015
  const thumbnailRevisions = usePlayerStore((state) => state.thumbnailRevisions);
85964
86016
  if (compositions.length === 0) {
85965
- return /* @__PURE__ */ jsx210("div", { className: "flex-1 flex items-center justify-center px-4", children: /* @__PURE__ */ jsx210("p", { className: "text-xs text-neutral-600 text-center", children: "No compositions found" }) });
86017
+ return /* @__PURE__ */ jsx211("div", { className: "flex-1 flex items-center justify-center px-4", children: /* @__PURE__ */ jsx211("p", { className: "text-xs text-neutral-600 text-center", children: "No compositions found" }) });
85966
86018
  }
85967
- return /* @__PURE__ */ jsx210("div", { className: "flex-1 overflow-y-auto", children: compositions.map((comp) => /* @__PURE__ */ jsx210(
86019
+ return /* @__PURE__ */ jsx211("div", { className: "flex-1 overflow-y-auto", children: compositions.map((comp) => /* @__PURE__ */ jsx211(
85968
86020
  CompCard,
85969
86021
  {
85970
86022
  projectId,
@@ -85983,9 +86035,9 @@ var CompositionsTab = memo43(function CompositionsTab2({
85983
86035
  });
85984
86036
 
85985
86037
  // src/components/sidebar/CompositionsPanel.tsx
85986
- import { jsx as jsx211 } from "react/jsx-runtime";
86038
+ import { jsx as jsx212 } from "react/jsx-runtime";
85987
86039
  function CompositionsPanel(props) {
85988
- return /* @__PURE__ */ jsx211(
86040
+ return /* @__PURE__ */ jsx212(
85989
86041
  CompositionsTab,
85990
86042
  {
85991
86043
  ...props,
@@ -85995,14 +86047,14 @@ function CompositionsPanel(props) {
85995
86047
  }
85996
86048
 
85997
86049
  // src/components/sidebar/SidebarLintButton.tsx
85998
- import { jsx as jsx212, jsxs as jsxs169 } from "react/jsx-runtime";
86050
+ import { jsx as jsx213, jsxs as jsxs170 } from "react/jsx-runtime";
85999
86051
  function SidebarLintButton({
86000
86052
  onLint,
86001
86053
  linting,
86002
86054
  findingCount,
86003
86055
  hasError
86004
86056
  }) {
86005
- return /* @__PURE__ */ jsx212("div", { className: "border-t border-neutral-800 p-2 shrink-0", children: /* @__PURE__ */ jsxs169(
86057
+ return /* @__PURE__ */ jsx213("div", { className: "border-t border-neutral-800 p-2 shrink-0", children: /* @__PURE__ */ jsxs170(
86006
86058
  "button",
86007
86059
  {
86008
86060
  type: "button",
@@ -86010,7 +86062,7 @@ function SidebarLintButton({
86010
86062
  disabled: linting,
86011
86063
  className: "w-full flex items-center justify-center gap-1.5 px-2 py-1.5 rounded-md text-[11px] font-medium text-neutral-500 enabled:hover:text-amber-300 enabled:hover:bg-neutral-800 enabled:active:scale-[0.98] transition-colors disabled:opacity-40",
86012
86064
  children: [
86013
- /* @__PURE__ */ jsxs169(
86065
+ /* @__PURE__ */ jsxs170(
86014
86066
  "svg",
86015
86067
  {
86016
86068
  width: "12",
@@ -86020,20 +86072,20 @@ function SidebarLintButton({
86020
86072
  stroke: "currentColor",
86021
86073
  strokeWidth: "2",
86022
86074
  children: [
86023
- /* @__PURE__ */ jsx212("path", { d: "M9 11l3 3L22 4" }),
86024
- /* @__PURE__ */ jsx212("path", { d: "M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11" })
86075
+ /* @__PURE__ */ jsx213("path", { d: "M9 11l3 3L22 4" }),
86076
+ /* @__PURE__ */ jsx213("path", { d: "M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11" })
86025
86077
  ]
86026
86078
  }
86027
86079
  ),
86028
86080
  linting ? "Linting\u2026" : "Lint",
86029
- !linting && findingCount != null && findingCount > 0 && /* @__PURE__ */ jsxs169(
86081
+ !linting && findingCount != null && findingCount > 0 && /* @__PURE__ */ jsxs170(
86030
86082
  "span",
86031
86083
  {
86032
86084
  "data-lint-badge": hasError ? "error" : "warning",
86033
86085
  className: hasError ? "ml-1 min-w-[16px] rounded-full bg-panel-danger/25 px-1 text-[9px] font-bold text-panel-danger animate-pulse motion-reduce:animate-none" : "ml-1 min-w-[16px] rounded-full bg-amber-500/20 px-1 text-[9px] font-bold text-amber-400",
86034
86086
  children: [
86035
86087
  findingCount,
86036
- /* @__PURE__ */ jsx212("span", { className: "sr-only", children: hasError ? " lint findings, including errors" : " lint findings, warnings only" })
86088
+ /* @__PURE__ */ jsx213("span", { className: "sr-only", children: hasError ? " lint findings, including errors" : " lint findings, warnings only" })
86037
86089
  ]
86038
86090
  }
86039
86091
  )
@@ -86067,10 +86119,10 @@ function persistRenderSettings(format, quality, fps) {
86067
86119
  }
86068
86120
 
86069
86121
  // src/components/StudioLeftPanels.tsx
86070
- import { Fragment as Fragment57, jsx as jsx213, jsxs as jsxs170 } from "react/jsx-runtime";
86122
+ import { Fragment as Fragment57, jsx as jsx214, jsxs as jsxs171 } from "react/jsx-runtime";
86071
86123
  function PanelColumn({ footer, children }) {
86072
- return /* @__PURE__ */ jsxs170("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
86073
- /* @__PURE__ */ jsx213("div", { className: "flex min-h-0 flex-1 flex-col", children }),
86124
+ return /* @__PURE__ */ jsxs171("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
86125
+ /* @__PURE__ */ jsx214("div", { className: "flex min-h-0 flex-1 flex-col", children }),
86074
86126
  footer
86075
86127
  ] });
86076
86128
  }
@@ -86118,7 +86170,7 @@ function StudioLeftPanels({
86118
86170
  const importFiles = async (files, dir) => {
86119
86171
  await handleImportFiles(files, dir);
86120
86172
  };
86121
- const lintButton = /* @__PURE__ */ jsx213(
86173
+ const lintButton = /* @__PURE__ */ jsx214(
86122
86174
  SidebarLintButton,
86123
86175
  {
86124
86176
  onLint,
@@ -86127,8 +86179,8 @@ function StudioLeftPanels({
86127
86179
  hasError: lintHasError
86128
86180
  }
86129
86181
  );
86130
- return /* @__PURE__ */ jsxs170(Fragment57, { children: [
86131
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "compositions", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx213(
86182
+ return /* @__PURE__ */ jsxs171(Fragment57, { children: [
86183
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "compositions", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx214(
86132
86184
  CompositionsPanel,
86133
86185
  {
86134
86186
  projectId,
@@ -86141,7 +86193,7 @@ function StudioLeftPanels({
86141
86193
  lintFindingsByFile
86142
86194
  }
86143
86195
  ) }) }),
86144
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "assets", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx213(
86196
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "assets", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx214(
86145
86197
  AssetsTab,
86146
86198
  {
86147
86199
  projectId,
@@ -86152,8 +86204,8 @@ function StudioLeftPanels({
86152
86204
  onAddAssetToTimeline
86153
86205
  }
86154
86206
  ) }) }),
86155
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "code", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsxs170("div", { className: "flex min-h-0 flex-1", children: [
86156
- fileTree.length > 0 && /* @__PURE__ */ jsx213("div", { className: "w-[160px] shrink-0 border-r border-neutral-800 overflow-y-auto", children: /* @__PURE__ */ jsx213(
86207
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "code", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsxs171("div", { className: "flex min-h-0 flex-1", children: [
86208
+ fileTree.length > 0 && /* @__PURE__ */ jsx214("div", { className: "w-[160px] shrink-0 border-r border-neutral-800 overflow-y-auto", children: /* @__PURE__ */ jsx214(
86157
86209
  FileTree,
86158
86210
  {
86159
86211
  files: fileTree,
@@ -86169,7 +86221,7 @@ function StudioLeftPanels({
86169
86221
  lintFindingsByFile
86170
86222
  }
86171
86223
  ) }),
86172
- /* @__PURE__ */ jsx213("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx213(
86224
+ /* @__PURE__ */ jsx214("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx214(
86173
86225
  CodeBody,
86174
86226
  {
86175
86227
  projectId,
@@ -86179,7 +86231,7 @@ function StudioLeftPanels({
86179
86231
  }
86180
86232
  ) })
86181
86233
  ] }) }) }),
86182
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "catalog", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx213(BlocksTab, { onAddBlock, onPreviewBlock }) }) })
86234
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "catalog", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx214(BlocksTab, { onAddBlock, onPreviewBlock }) }) })
86183
86235
  ] });
86184
86236
  }
86185
86237
  function CodeBody({
@@ -86189,19 +86241,19 @@ function CodeBody({
86189
86241
  onChange
86190
86242
  }) {
86191
86243
  if (!editingFile) {
86192
- return /* @__PURE__ */ jsx213("div", { className: "flex items-center justify-center h-full text-neutral-600 text-sm", children: "Select a file to edit" });
86244
+ return /* @__PURE__ */ jsx214("div", { className: "flex items-center justify-center h-full text-neutral-600 text-sm", children: "Select a file to edit" });
86193
86245
  }
86194
86246
  if (isMediaFile(editingFile.path)) {
86195
- return /* @__PURE__ */ jsx213(MediaPreview, { projectId, filePath: editingFile.path });
86247
+ return /* @__PURE__ */ jsx214(MediaPreview, { projectId, filePath: editingFile.path });
86196
86248
  }
86197
86249
  if (editingFile.content == null) {
86198
- return /* @__PURE__ */ jsxs170("div", { className: "flex h-full items-center justify-center text-[11px] text-neutral-600", children: [
86250
+ return /* @__PURE__ */ jsxs171("div", { className: "flex h-full items-center justify-center text-[11px] text-neutral-600", children: [
86199
86251
  "Loading ",
86200
86252
  editingFile.path,
86201
86253
  "\u2026"
86202
86254
  ] });
86203
86255
  }
86204
- return /* @__PURE__ */ jsx213(
86256
+ return /* @__PURE__ */ jsx214(
86205
86257
  SourceEditor,
86206
86258
  {
86207
86259
  content: editingFile.content,
@@ -86427,7 +86479,7 @@ function getVisibleLayers(layers, collapsed) {
86427
86479
  }
86428
86480
 
86429
86481
  // src/components/editor/LayersPanel.tsx
86430
- import { jsx as jsx214, jsxs as jsxs171 } from "react/jsx-runtime";
86482
+ import { jsx as jsx215, jsxs as jsxs172 } from "react/jsx-runtime";
86431
86483
  var LAYERS_PANEL_MAX_ROWS = 80;
86432
86484
  var TAG_ICONS = {
86433
86485
  video: "Vi",
@@ -86714,24 +86766,24 @@ var LayersPanel = memo44(function LayersPanel2() {
86714
86766
  onSingleSibling: handleSingleSibling
86715
86767
  });
86716
86768
  if (layers.length === 0) {
86717
- return /* @__PURE__ */ jsxs171("div", { className: "flex h-full flex-col items-center justify-center bg-panel-bg px-6 text-center", children: [
86718
- /* @__PURE__ */ jsx214(Layers, { size: 18, className: "mb-3 text-panel-text-5" }),
86719
- /* @__PURE__ */ jsx214("p", { className: "text-sm font-medium text-panel-text-1", children: "No layers" }),
86720
- /* @__PURE__ */ jsx214("p", { className: "mt-1 text-xs text-neutral-500", children: "Load a composition to see its element tree" })
86769
+ return /* @__PURE__ */ jsxs172("div", { className: "flex h-full flex-col items-center justify-center bg-panel-bg px-6 text-center", children: [
86770
+ /* @__PURE__ */ jsx215(Layers, { size: 18, className: "mb-3 text-panel-text-5" }),
86771
+ /* @__PURE__ */ jsx215("p", { className: "text-sm font-medium text-panel-text-1", children: "No layers" }),
86772
+ /* @__PURE__ */ jsx215("p", { className: "mt-1 text-xs text-neutral-500", children: "Load a composition to see its element tree" })
86721
86773
  ] });
86722
86774
  }
86723
- return /* @__PURE__ */ jsxs171(
86775
+ return /* @__PURE__ */ jsxs172(
86724
86776
  "div",
86725
86777
  {
86726
86778
  className: "flex h-full min-h-0 flex-col overflow-hidden bg-panel-bg",
86727
86779
  onPointerLeave: () => handleLayerHover(null),
86728
86780
  children: [
86729
- /* @__PURE__ */ jsxs171("div", { className: "border-b border-panel-border px-3 py-2 text-[11px] text-panel-text-3", children: [
86781
+ /* @__PURE__ */ jsxs172("div", { className: "border-b border-panel-border px-3 py-2 text-[11px] text-panel-text-3", children: [
86730
86782
  layers.length,
86731
86783
  " layer",
86732
86784
  layers.length === 1 ? "" : "s"
86733
86785
  ] }),
86734
- /* @__PURE__ */ jsxs171(
86786
+ /* @__PURE__ */ jsxs172(
86735
86787
  "div",
86736
86788
  {
86737
86789
  ref: scrollContainerRef,
@@ -86740,15 +86792,15 @@ var LayersPanel = memo44(function LayersPanel2() {
86740
86792
  onPointerUp: handleContainerPointerUp,
86741
86793
  onPointerCancel: handleContainerPointerUp,
86742
86794
  children: [
86743
- activeGroupElement && /* @__PURE__ */ jsxs171(
86795
+ activeGroupElement && /* @__PURE__ */ jsxs172(
86744
86796
  "button",
86745
86797
  {
86746
86798
  type: "button",
86747
86799
  onClick: () => setActiveGroupElement(null),
86748
86800
  className: "flex w-full items-center gap-1.5 px-2 py-1 text-left text-[11px] text-panel-text-3 hover:bg-panel-hover/40 hover:text-panel-text-1",
86749
86801
  children: [
86750
- /* @__PURE__ */ jsx214("span", { "aria-hidden": "true", children: "\u2190" }),
86751
- /* @__PURE__ */ jsx214("span", { className: "truncate", children: activeGroupElement.getAttribute("data-hf-group") || "Group" })
86802
+ /* @__PURE__ */ jsx215("span", { "aria-hidden": "true", children: "\u2190" }),
86803
+ /* @__PURE__ */ jsx215("span", { className: "truncate", children: activeGroupElement.getAttribute("data-hf-group") || "Group" })
86752
86804
  ]
86753
86805
  }
86754
86806
  ),
@@ -86759,7 +86811,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86759
86811
  const isCollapsed = collapsed[layer.key] ?? false;
86760
86812
  const hasChildren = layer.childCount > 0;
86761
86813
  const isCompHost = isCompositionHost(layer.element);
86762
- return /* @__PURE__ */ jsxs171(
86814
+ return /* @__PURE__ */ jsxs172(
86763
86815
  "div",
86764
86816
  {
86765
86817
  "data-layer-index": index,
@@ -86779,7 +86831,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86779
86831
  style: { paddingLeft: 8 + layer.depth * 16 },
86780
86832
  title: draggable ? layer.element.hasAttribute("data-hf-group") ? "Double-click to enter group" : void 0 : "This layer can't be reordered",
86781
86833
  children: [
86782
- hasChildren ? /* @__PURE__ */ jsx214(
86834
+ hasChildren ? /* @__PURE__ */ jsx215(
86783
86835
  "button",
86784
86836
  {
86785
86837
  type: "button",
@@ -86787,7 +86839,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86787
86839
  "aria-expanded": !isCollapsed,
86788
86840
  "aria-label": isCollapsed ? "Expand children" : "Collapse children",
86789
86841
  className: "relative flex h-4 w-4 shrink-0 items-center justify-center rounded-sm text-neutral-500 hover:text-neutral-300 before:absolute before:-inset-1.5 before:content-['']",
86790
- children: /* @__PURE__ */ jsx214(
86842
+ children: /* @__PURE__ */ jsx215(
86791
86843
  "svg",
86792
86844
  {
86793
86845
  width: "8",
@@ -86795,26 +86847,26 @@ var LayersPanel = memo44(function LayersPanel2() {
86795
86847
  viewBox: "0 0 8 8",
86796
86848
  fill: "currentColor",
86797
86849
  className: `transition-transform ${isCollapsed ? "" : "rotate-90"}`,
86798
- children: /* @__PURE__ */ jsx214("path", { d: "M2 1l4 3-4 3z" })
86850
+ children: /* @__PURE__ */ jsx215("path", { d: "M2 1l4 3-4 3z" })
86799
86851
  }
86800
86852
  )
86801
86853
  }
86802
- ) : /* @__PURE__ */ jsx214("span", { className: "w-4 shrink-0" }),
86803
- /* @__PURE__ */ jsx214(
86854
+ ) : /* @__PURE__ */ jsx215("span", { className: "w-4 shrink-0" }),
86855
+ /* @__PURE__ */ jsx215(
86804
86856
  "span",
86805
86857
  {
86806
86858
  className: `flex h-5 w-5 shrink-0 items-center justify-center rounded text-[8px] font-bold uppercase ${selected ? "bg-panel-accent/18 text-panel-accent" : isCompHost ? "bg-panel-accent/40 text-panel-accent" : "bg-panel-hover text-panel-text-4"}`,
86807
86859
  children: getTagBadge(layer.tagName)
86808
86860
  }
86809
86861
  ),
86810
- /* @__PURE__ */ jsx214("span", { className: "min-w-0 flex-1 truncate text-[11px]", children: layer.label }),
86811
- hasChildren && /* @__PURE__ */ jsx214("span", { className: "text-[9px] tabular-nums text-panel-text-5", children: layer.childCount })
86862
+ /* @__PURE__ */ jsx215("span", { className: "min-w-0 flex-1 truncate text-[11px]", children: layer.label }),
86863
+ hasChildren && /* @__PURE__ */ jsx215("span", { className: "text-[9px] tabular-nums text-panel-text-5", children: layer.childCount })
86812
86864
  ]
86813
86865
  },
86814
86866
  layer.key
86815
86867
  );
86816
86868
  }),
86817
- insertionLineY != null && /* @__PURE__ */ jsx214(
86869
+ insertionLineY != null && /* @__PURE__ */ jsx215(
86818
86870
  "div",
86819
86871
  {
86820
86872
  className: "pointer-events-none absolute left-2 right-2 h-0.5 bg-studio-accent",
@@ -86837,18 +86889,18 @@ import { memo as memo45, useCallback as useCallback161 } from "react";
86837
86889
 
86838
86890
  // src/captions/components/shared.tsx
86839
86891
  import { useEffect as useEffect138, useRef as useRef176, useState as useState139 } from "react";
86840
- import { jsx as jsx215, jsxs as jsxs172 } from "react/jsx-runtime";
86892
+ import { jsx as jsx216, jsxs as jsxs173 } from "react/jsx-runtime";
86841
86893
  var inputCls = "w-full bg-neutral-900 border border-neutral-800 rounded-sm px-1.5 py-0.5 text-2xs text-neutral-200 font-mono outline-hidden focus:border-studio-accent disabled:opacity-40 disabled:cursor-not-allowed";
86842
86894
  function Section2({ label, children }) {
86843
- return /* @__PURE__ */ jsxs172("div", { className: "mb-3", children: [
86844
- /* @__PURE__ */ jsx215("div", { className: "flex items-center gap-1.5 mt-2 mb-1.5", children: /* @__PURE__ */ jsx215("span", { className: "text-2xs font-medium text-neutral-500 uppercase tracking-wider", children: label }) }),
86845
- /* @__PURE__ */ jsx215("div", { className: "space-y-1", children })
86895
+ return /* @__PURE__ */ jsxs173("div", { className: "mb-3", children: [
86896
+ /* @__PURE__ */ jsx216("div", { className: "flex items-center gap-1.5 mt-2 mb-1.5", children: /* @__PURE__ */ jsx216("span", { className: "text-2xs font-medium text-neutral-500 uppercase tracking-wider", children: label }) }),
86897
+ /* @__PURE__ */ jsx216("div", { className: "space-y-1", children })
86846
86898
  ] });
86847
86899
  }
86848
86900
  function Row({ label, children }) {
86849
- return /* @__PURE__ */ jsxs172("div", { className: "flex items-center gap-2", children: [
86850
- /* @__PURE__ */ jsx215("span", { className: "text-2xs text-neutral-600 w-14 text-right shrink-0", children: label }),
86851
- /* @__PURE__ */ jsx215("div", { className: "flex-1 min-w-0", children })
86901
+ return /* @__PURE__ */ jsxs173("div", { className: "flex items-center gap-2", children: [
86902
+ /* @__PURE__ */ jsx216("span", { className: "text-2xs text-neutral-600 w-14 text-right shrink-0", children: label }),
86903
+ /* @__PURE__ */ jsx216("div", { className: "flex-1 min-w-0", children })
86852
86904
  ] });
86853
86905
  }
86854
86906
  function NumberField2({
@@ -86878,7 +86930,7 @@ function NumberField2({
86878
86930
  onCommit(clamped);
86879
86931
  }
86880
86932
  };
86881
- return /* @__PURE__ */ jsx215(
86933
+ return /* @__PURE__ */ jsx216(
86882
86934
  "input",
86883
86935
  {
86884
86936
  type: "number",
@@ -86903,7 +86955,7 @@ function NumberField2({
86903
86955
  }
86904
86956
 
86905
86957
  // src/captions/components/CaptionAnimationPanel.tsx
86906
- import { jsx as jsx216, jsxs as jsxs173 } from "react/jsx-runtime";
86958
+ import { jsx as jsx217, jsxs as jsxs174 } from "react/jsx-runtime";
86907
86959
  var ENTRANCE_PRESETS = [
86908
86960
  "none",
86909
86961
  "fade",
@@ -86969,8 +87021,8 @@ function AnimationPhase({
86969
87021
  const ease = animation?.ease ?? "power2.out";
86970
87022
  const stagger = animation?.stagger ?? 0;
86971
87023
  const intensity = animation?.intensity ?? 1;
86972
- return /* @__PURE__ */ jsxs173(Section2, { label, children: [
86973
- /* @__PURE__ */ jsx216(Row, { label: "Preset", children: /* @__PURE__ */ jsx216(
87024
+ return /* @__PURE__ */ jsxs174(Section2, { label, children: [
87025
+ /* @__PURE__ */ jsx217(Row, { label: "Preset", children: /* @__PURE__ */ jsx217(
86974
87026
  "select",
86975
87027
  {
86976
87028
  value: preset,
@@ -86978,10 +87030,10 @@ function AnimationPhase({
86978
87030
  "aria-label": `${label} preset`,
86979
87031
  onChange: (e) => onChange({ preset: e.target.value }),
86980
87032
  className: inputCls,
86981
- children: presets.map((p) => /* @__PURE__ */ jsx216("option", { value: p, children: p }, p))
87033
+ children: presets.map((p) => /* @__PURE__ */ jsx217("option", { value: p, children: p }, p))
86982
87034
  }
86983
87035
  ) }),
86984
- /* @__PURE__ */ jsx216(Row, { label: "Duration", children: /* @__PURE__ */ jsx216(
87036
+ /* @__PURE__ */ jsx217(Row, { label: "Duration", children: /* @__PURE__ */ jsx217(
86985
87037
  NumberField2,
86986
87038
  {
86987
87039
  value: duration,
@@ -86993,7 +87045,7 @@ function AnimationPhase({
86993
87045
  onCommit: (v) => onChange({ duration: v })
86994
87046
  }
86995
87047
  ) }),
86996
- /* @__PURE__ */ jsx216(Row, { label: "Ease", children: /* @__PURE__ */ jsx216(
87048
+ /* @__PURE__ */ jsx217(Row, { label: "Ease", children: /* @__PURE__ */ jsx217(
86997
87049
  "select",
86998
87050
  {
86999
87051
  value: ease,
@@ -87001,10 +87053,10 @@ function AnimationPhase({
87001
87053
  "aria-label": `${label} ease`,
87002
87054
  onChange: (e) => onChange({ ease: e.target.value }),
87003
87055
  className: inputCls,
87004
- children: EASE_PRESETS2.map((e) => /* @__PURE__ */ jsx216("option", { value: e, children: e }, e))
87056
+ children: EASE_PRESETS2.map((e) => /* @__PURE__ */ jsx217("option", { value: e, children: e }, e))
87005
87057
  }
87006
87058
  ) }),
87007
- /* @__PURE__ */ jsx216(Row, { label: "Stagger", children: /* @__PURE__ */ jsx216(
87059
+ /* @__PURE__ */ jsx217(Row, { label: "Stagger", children: /* @__PURE__ */ jsx217(
87008
87060
  NumberField2,
87009
87061
  {
87010
87062
  value: stagger,
@@ -87016,8 +87068,8 @@ function AnimationPhase({
87016
87068
  onCommit: (v) => onChange({ stagger: v })
87017
87069
  }
87018
87070
  ) }),
87019
- showIntensity && /* @__PURE__ */ jsx216(Row, { label: "Intensity", children: /* @__PURE__ */ jsxs173("div", { className: "flex items-center gap-2", children: [
87020
- /* @__PURE__ */ jsx216(
87071
+ showIntensity && /* @__PURE__ */ jsx217(Row, { label: "Intensity", children: /* @__PURE__ */ jsxs174("div", { className: "flex items-center gap-2", children: [
87072
+ /* @__PURE__ */ jsx217(
87021
87073
  "input",
87022
87074
  {
87023
87075
  type: "range",
@@ -87034,7 +87086,7 @@ function AnimationPhase({
87034
87086
  className: "flex-1 accent-studio-accent disabled:opacity-40"
87035
87087
  }
87036
87088
  ),
87037
- /* @__PURE__ */ jsx216("span", { className: "text-2xs text-neutral-400 font-mono w-8 text-right shrink-0", children: intensity.toFixed(2) })
87089
+ /* @__PURE__ */ jsx217("span", { className: "text-2xs text-neutral-400 font-mono w-8 text-right shrink-0", children: intensity.toFixed(2) })
87038
87090
  ] }) })
87039
87091
  ] });
87040
87092
  }
@@ -87080,13 +87132,13 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87080
87132
  if (animation) applyAnimationToAll(animation);
87081
87133
  }, [animation, applyAnimationToAll]);
87082
87134
  if (!group || !resolvedGroupId || !animation) {
87083
- return /* @__PURE__ */ jsx216("div", { className: "flex items-center justify-center h-full px-4 text-center", children: /* @__PURE__ */ jsx216("p", { className: "text-xs text-neutral-500", children: "Select a caption word to edit animations" }) });
87135
+ return /* @__PURE__ */ jsx217("div", { className: "flex items-center justify-center h-full px-4 text-center", children: /* @__PURE__ */ jsx217("p", { className: "text-xs text-neutral-500", children: "Select a caption word to edit animations" }) });
87084
87136
  }
87085
87137
  const gated = !ANIMATION_PIPELINE_WIRED;
87086
- return /* @__PURE__ */ jsxs173("div", { className: "flex flex-col h-full min-h-0", children: [
87087
- gated && /* @__PURE__ */ jsx216("div", { className: "shrink-0 mx-3 mt-2 px-2 py-1.5 rounded-sm border border-amber-500/30 bg-amber-500/10", children: /* @__PURE__ */ jsx216("p", { className: "text-2xs text-amber-300/90 leading-snug", children: "Animation editing isn't applied to playback or saved yet, so these controls are disabled." }) }),
87088
- /* @__PURE__ */ jsxs173("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
87089
- /* @__PURE__ */ jsx216(
87138
+ return /* @__PURE__ */ jsxs174("div", { className: "flex flex-col h-full min-h-0", children: [
87139
+ gated && /* @__PURE__ */ jsx217("div", { className: "shrink-0 mx-3 mt-2 px-2 py-1.5 rounded-sm border border-amber-500/30 bg-amber-500/10", children: /* @__PURE__ */ jsx217("p", { className: "text-2xs text-amber-300/90 leading-snug", children: "Animation editing isn't applied to playback or saved yet, so these controls are disabled." }) }),
87140
+ /* @__PURE__ */ jsxs174("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
87141
+ /* @__PURE__ */ jsx217(
87090
87142
  AnimationPhase,
87091
87143
  {
87092
87144
  label: "Entrance",
@@ -87096,7 +87148,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87096
87148
  onChange: handleEntranceChange
87097
87149
  }
87098
87150
  ),
87099
- /* @__PURE__ */ jsx216(
87151
+ /* @__PURE__ */ jsx217(
87100
87152
  AnimationPhase,
87101
87153
  {
87102
87154
  label: "Highlight",
@@ -87107,7 +87159,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87107
87159
  onChange: handleHighlightChange
87108
87160
  }
87109
87161
  ),
87110
- /* @__PURE__ */ jsx216(
87162
+ /* @__PURE__ */ jsx217(
87111
87163
  AnimationPhase,
87112
87164
  {
87113
87165
  label: "Exit",
@@ -87118,7 +87170,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87118
87170
  }
87119
87171
  )
87120
87172
  ] }),
87121
- /* @__PURE__ */ jsx216("div", { className: "shrink-0 px-3 py-2 border-t border-neutral-800", children: /* @__PURE__ */ jsx216(
87173
+ /* @__PURE__ */ jsx217("div", { className: "shrink-0 px-3 py-2 border-t border-neutral-800", children: /* @__PURE__ */ jsx217(
87122
87174
  "button",
87123
87175
  {
87124
87176
  type: "button",
@@ -87133,7 +87185,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87133
87185
  });
87134
87186
 
87135
87187
  // src/captions/components/CaptionPropertyPanel.tsx
87136
- import { jsx as jsx217, jsxs as jsxs174 } from "react/jsx-runtime";
87188
+ import { jsx as jsx218, jsxs as jsxs175 } from "react/jsx-runtime";
87137
87189
  function isMixedValue(model, selectedSegmentIds, key2, fallback) {
87138
87190
  if (!model || selectedSegmentIds.size < 2) return false;
87139
87191
  let first2;
@@ -87262,7 +87314,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87262
87314
  [selectedGroupId, updateGroupStyle, updateSelectedStyle, applyToIframeDom]
87263
87315
  );
87264
87316
  if (selectedSegmentIds.size === 0) {
87265
- return /* @__PURE__ */ jsx217("div", { className: "flex items-center justify-center h-full px-4 text-center", children: /* @__PURE__ */ jsx217("p", { className: "text-xs text-neutral-500", children: "Select caption words to edit their style" }) });
87317
+ return /* @__PURE__ */ jsx218("div", { className: "flex items-center justify-center h-full px-4 text-center", children: /* @__PURE__ */ jsx218("p", { className: "text-xs text-neutral-500", children: "Select caption words to edit their style" }) });
87266
87318
  }
87267
87319
  const x = effectiveStyle.x ?? 0;
87268
87320
  const y = effectiveStyle.y ?? 0;
@@ -87273,11 +87325,11 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87273
87325
  const scaleMixed = isMixedValue(model, selectedSegmentIds, "scaleX", 1);
87274
87326
  const rotationMixed = isMixedValue(model, selectedSegmentIds, "rotation", 0);
87275
87327
  const countLabel = selectedSegmentIds.size === 1 ? "1 word" : `${selectedSegmentIds.size} words`;
87276
- return /* @__PURE__ */ jsxs174("div", { className: "flex flex-col h-full min-h-0", children: [
87277
- /* @__PURE__ */ jsxs174("div", { className: "px-3 py-2 border-b border-neutral-800 shrink-0", children: [
87278
- /* @__PURE__ */ jsx217("div", { className: "flex items-center justify-between mb-1.5", children: /* @__PURE__ */ jsx217("span", { className: "text-2xs text-neutral-500", children: countLabel }) }),
87279
- /* @__PURE__ */ jsxs174("div", { className: "flex gap-1", role: "tablist", "aria-label": "Caption editing tabs", children: [
87280
- /* @__PURE__ */ jsx217(
87328
+ return /* @__PURE__ */ jsxs175("div", { className: "flex flex-col h-full min-h-0", children: [
87329
+ /* @__PURE__ */ jsxs175("div", { className: "px-3 py-2 border-b border-neutral-800 shrink-0", children: [
87330
+ /* @__PURE__ */ jsx218("div", { className: "flex items-center justify-between mb-1.5", children: /* @__PURE__ */ jsx218("span", { className: "text-2xs text-neutral-500", children: countLabel }) }),
87331
+ /* @__PURE__ */ jsxs175("div", { className: "flex gap-1", role: "tablist", "aria-label": "Caption editing tabs", children: [
87332
+ /* @__PURE__ */ jsx218(
87281
87333
  "button",
87282
87334
  {
87283
87335
  type: "button",
@@ -87291,7 +87343,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87291
87343
  children: "Style"
87292
87344
  }
87293
87345
  ),
87294
- /* @__PURE__ */ jsx217(
87346
+ /* @__PURE__ */ jsx218(
87295
87347
  "button",
87296
87348
  {
87297
87349
  type: "button",
@@ -87307,10 +87359,10 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87307
87359
  )
87308
87360
  ] })
87309
87361
  ] }),
87310
- activeTab === "animation" && /* @__PURE__ */ jsx217(CaptionAnimationPanel, {}),
87311
- activeTab === "style" && /* @__PURE__ */ jsxs174("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
87312
- /* @__PURE__ */ jsxs174(Section2, { label: "Position", children: [
87313
- /* @__PURE__ */ jsx217(Row, { label: "X", children: /* @__PURE__ */ jsx217(
87362
+ activeTab === "animation" && /* @__PURE__ */ jsx218(CaptionAnimationPanel, {}),
87363
+ activeTab === "style" && /* @__PURE__ */ jsxs175("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
87364
+ /* @__PURE__ */ jsxs175(Section2, { label: "Position", children: [
87365
+ /* @__PURE__ */ jsx218(Row, { label: "X", children: /* @__PURE__ */ jsx218(
87314
87366
  NumberField2,
87315
87367
  {
87316
87368
  value: x,
@@ -87319,7 +87371,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87319
87371
  onCommit: (v) => handleStyleChange({ x: v })
87320
87372
  }
87321
87373
  ) }),
87322
- /* @__PURE__ */ jsx217(Row, { label: "Y", children: /* @__PURE__ */ jsx217(
87374
+ /* @__PURE__ */ jsx218(Row, { label: "Y", children: /* @__PURE__ */ jsx218(
87323
87375
  NumberField2,
87324
87376
  {
87325
87377
  value: y,
@@ -87329,8 +87381,8 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87329
87381
  }
87330
87382
  ) })
87331
87383
  ] }),
87332
- /* @__PURE__ */ jsxs174(Section2, { label: "Transform", children: [
87333
- /* @__PURE__ */ jsx217(Row, { label: "Scale", children: /* @__PURE__ */ jsx217(
87384
+ /* @__PURE__ */ jsxs175(Section2, { label: "Transform", children: [
87385
+ /* @__PURE__ */ jsx218(Row, { label: "Scale", children: /* @__PURE__ */ jsx218(
87334
87386
  NumberField2,
87335
87387
  {
87336
87388
  value: scaleX,
@@ -87340,7 +87392,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87340
87392
  onCommit: (v) => handleStyleChange({ scaleX: v, scaleY: v })
87341
87393
  }
87342
87394
  ) }),
87343
- /* @__PURE__ */ jsx217(Row, { label: "Rotation", children: /* @__PURE__ */ jsx217(
87395
+ /* @__PURE__ */ jsx218(Row, { label: "Rotation", children: /* @__PURE__ */ jsx218(
87344
87396
  NumberField2,
87345
87397
  {
87346
87398
  value: rotation,
@@ -87356,7 +87408,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87356
87408
 
87357
87409
  // src/components/editor/BlockParamsPanel.tsx
87358
87410
  import { memo as memo47, useCallback as useCallback163, useEffect as useEffect139, useRef as useRef177, useState as useState141 } from "react";
87359
- import { jsx as jsx218, jsxs as jsxs175 } from "react/jsx-runtime";
87411
+ import { jsx as jsx219, jsxs as jsxs176 } from "react/jsx-runtime";
87360
87412
  var BlockParamsPanel = memo47(function BlockParamsPanel2({
87361
87413
  blockName,
87362
87414
  blockTitle,
@@ -87455,17 +87507,17 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87455
87507
  commitTimersRef.current.clear();
87456
87508
  };
87457
87509
  useEffect139(() => () => flushRef.current(), []);
87458
- return /* @__PURE__ */ jsxs175("div", { className: "flex flex-col h-full", children: [
87459
- /* @__PURE__ */ jsxs175("div", { className: "flex items-center justify-between px-3 py-2 border-b border-neutral-800", children: [
87460
- /* @__PURE__ */ jsx218("div", { className: "text-[11px] font-semibold text-neutral-200 truncate", children: blockTitle }),
87461
- /* @__PURE__ */ jsx218(
87510
+ return /* @__PURE__ */ jsxs176("div", { className: "flex flex-col h-full", children: [
87511
+ /* @__PURE__ */ jsxs176("div", { className: "flex items-center justify-between px-3 py-2 border-b border-neutral-800", children: [
87512
+ /* @__PURE__ */ jsx219("div", { className: "text-[11px] font-semibold text-neutral-200 truncate", children: blockTitle }),
87513
+ /* @__PURE__ */ jsx219(
87462
87514
  "button",
87463
87515
  {
87464
87516
  type: "button",
87465
87517
  onClick: onClose,
87466
87518
  "aria-label": "Close block parameters",
87467
87519
  className: "p-1.5 -m-1 text-neutral-500 hover:text-neutral-300 active:scale-[0.97] transition-colors",
87468
- children: /* @__PURE__ */ jsxs175(
87520
+ children: /* @__PURE__ */ jsxs176(
87469
87521
  "svg",
87470
87522
  {
87471
87523
  width: "14",
@@ -87477,19 +87529,19 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87477
87529
  strokeLinecap: "round",
87478
87530
  strokeLinejoin: "round",
87479
87531
  children: [
87480
- /* @__PURE__ */ jsx218("path", { d: "M18 6 6 18" }),
87481
- /* @__PURE__ */ jsx218("path", { d: "m6 6 12 12" })
87532
+ /* @__PURE__ */ jsx219("path", { d: "M18 6 6 18" }),
87533
+ /* @__PURE__ */ jsx219("path", { d: "m6 6 12 12" })
87482
87534
  ]
87483
87535
  }
87484
87536
  )
87485
87537
  }
87486
87538
  )
87487
87539
  ] }),
87488
- /* @__PURE__ */ jsxs175("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
87489
- /* @__PURE__ */ jsx218("div", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider", children: "Parameters" }),
87490
- params.length === 0 && /* @__PURE__ */ jsx218("div", { className: "text-[10px] text-neutral-500", children: "This block has no editable parameters." }),
87491
- !fileManager && params.length > 0 && /* @__PURE__ */ jsx218("div", { className: "text-[10px] text-amber-400/90", children: "Block params can't be edited here \u2014 no project file access." }),
87492
- params.map((param) => /* @__PURE__ */ jsx218(
87540
+ /* @__PURE__ */ jsxs176("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
87541
+ /* @__PURE__ */ jsx219("div", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider", children: "Parameters" }),
87542
+ params.length === 0 && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-neutral-500", children: "This block has no editable parameters." }),
87543
+ !fileManager && params.length > 0 && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-amber-400/90", children: "Block params can't be edited here \u2014 no project file access." }),
87544
+ params.map((param) => /* @__PURE__ */ jsx219(
87493
87545
  ParamControl,
87494
87546
  {
87495
87547
  param,
@@ -87499,12 +87551,12 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87499
87551
  },
87500
87552
  param.key
87501
87553
  )),
87502
- commitState.tone === "saving" && /* @__PURE__ */ jsx218("div", { className: "text-[10px] text-neutral-500", role: "status", children: "Saving\u2026" }),
87503
- commitState.tone === "saved" && /* @__PURE__ */ jsxs175("div", { className: "text-[10px] text-emerald-500/90", role: "status", children: [
87554
+ commitState.tone === "saving" && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-neutral-500", role: "status", children: "Saving\u2026" }),
87555
+ commitState.tone === "saved" && /* @__PURE__ */ jsxs176("div", { className: "text-[10px] text-emerald-500/90", role: "status", children: [
87504
87556
  "Saved to ",
87505
87557
  compositionPath
87506
87558
  ] }),
87507
- commitState.tone === "error" && /* @__PURE__ */ jsx218("div", { className: "text-[10px] text-red-400", role: "alert", children: commitState.message })
87559
+ commitState.tone === "error" && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-red-400", role: "alert", children: commitState.message })
87508
87560
  ] })
87509
87561
  ] });
87510
87562
  });
@@ -87514,10 +87566,10 @@ function ParamControl({
87514
87566
  disabled,
87515
87567
  onChange
87516
87568
  }) {
87517
- return /* @__PURE__ */ jsxs175("div", { className: "space-y-1", children: [
87518
- /* @__PURE__ */ jsx218("label", { className: "text-[10px] font-medium text-neutral-400", children: param.label }),
87519
- param.type === "color" && /* @__PURE__ */ jsxs175("div", { className: "flex items-center gap-2", children: [
87520
- /* @__PURE__ */ jsx218(
87569
+ return /* @__PURE__ */ jsxs176("div", { className: "space-y-1", children: [
87570
+ /* @__PURE__ */ jsx219("label", { className: "text-[10px] font-medium text-neutral-400", children: param.label }),
87571
+ param.type === "color" && /* @__PURE__ */ jsxs176("div", { className: "flex items-center gap-2", children: [
87572
+ /* @__PURE__ */ jsx219(
87521
87573
  "input",
87522
87574
  {
87523
87575
  type: "color",
@@ -87528,7 +87580,7 @@ function ParamControl({
87528
87580
  className: "w-7 h-7 rounded-sm border border-neutral-700 bg-transparent cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
87529
87581
  }
87530
87582
  ),
87531
- /* @__PURE__ */ jsx218(
87583
+ /* @__PURE__ */ jsx219(
87532
87584
  "input",
87533
87585
  {
87534
87586
  type: "text",
@@ -87540,8 +87592,8 @@ function ParamControl({
87540
87592
  }
87541
87593
  )
87542
87594
  ] }),
87543
- param.type === "number" && /* @__PURE__ */ jsxs175("div", { className: "flex items-center gap-2", children: [
87544
- /* @__PURE__ */ jsx218(
87595
+ param.type === "number" && /* @__PURE__ */ jsxs176("div", { className: "flex items-center gap-2", children: [
87596
+ /* @__PURE__ */ jsx219(
87545
87597
  "input",
87546
87598
  {
87547
87599
  type: "range",
@@ -87555,9 +87607,9 @@ function ParamControl({
87555
87607
  className: "flex-1 disabled:cursor-not-allowed disabled:opacity-50"
87556
87608
  }
87557
87609
  ),
87558
- /* @__PURE__ */ jsx218("span", { className: "text-[10px] text-neutral-400 w-8 text-right tabular-nums", children: value })
87610
+ /* @__PURE__ */ jsx219("span", { className: "text-[10px] text-neutral-400 w-8 text-right tabular-nums", children: value })
87559
87611
  ] }),
87560
- param.type === "text" && /* @__PURE__ */ jsx218(
87612
+ param.type === "text" && /* @__PURE__ */ jsx219(
87561
87613
  "input",
87562
87614
  {
87563
87615
  type: "text",
@@ -87568,7 +87620,7 @@ function ParamControl({
87568
87620
  className: "w-full bg-neutral-900 border border-neutral-800 rounded-sm px-2 py-1 text-[10px] text-neutral-200 focus:outline-hidden focus:border-neutral-700 disabled:cursor-not-allowed disabled:opacity-50"
87569
87621
  }
87570
87622
  ),
87571
- param.type === "select" && param.options && /* @__PURE__ */ jsx218(
87623
+ param.type === "select" && param.options && /* @__PURE__ */ jsx219(
87572
87624
  "select",
87573
87625
  {
87574
87626
  value,
@@ -87576,7 +87628,7 @@ function ParamControl({
87576
87628
  "aria-label": param.label,
87577
87629
  onChange: (e) => onChange(e.target.value),
87578
87630
  className: "w-full bg-neutral-900 border border-neutral-800 rounded-sm px-2 py-1 text-[10px] text-neutral-200 focus:outline-hidden focus:border-neutral-700 disabled:cursor-not-allowed disabled:opacity-50",
87579
- children: param.options.map((opt) => /* @__PURE__ */ jsx218("option", { value: opt.value, children: opt.label }, opt.value))
87631
+ children: param.options.map((opt) => /* @__PURE__ */ jsx219("option", { value: opt.value, children: opt.label }, opt.value))
87580
87632
  }
87581
87633
  )
87582
87634
  ] });
@@ -87592,7 +87644,7 @@ import { CANVAS_DIMENSIONS } from "@hyperframes/parsers";
87592
87644
 
87593
87645
  // src/components/renders/RenderQueueItem.tsx
87594
87646
  import { memo as memo48, useCallback as useCallback164, useState as useState142 } from "react";
87595
- import { Fragment as Fragment58, jsx as jsx219, jsxs as jsxs176 } from "react/jsx-runtime";
87647
+ import { Fragment as Fragment58, jsx as jsx220, jsxs as jsxs177 } from "react/jsx-runtime";
87596
87648
  function formatDuration2(ms) {
87597
87649
  if (ms < 1e3) return `${ms}ms`;
87598
87650
  const s = Math.round(ms / 1e3);
@@ -87630,7 +87682,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87630
87682
  const viewSrc = fileSrc;
87631
87683
  const isComplete = job.status === "complete";
87632
87684
  const isRendering = job.status === "rendering";
87633
- return /* @__PURE__ */ jsx219(
87685
+ return /* @__PURE__ */ jsx220(
87634
87686
  "div",
87635
87687
  {
87636
87688
  onPointerEnter: () => setHovered(true),
@@ -87640,8 +87692,8 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87640
87692
  setConfirmingDelete(false);
87641
87693
  },
87642
87694
  className: "px-3 py-2.5 border-b border-border last:border-0 transition-colors duration-150 hover:bg-hover/30",
87643
- children: /* @__PURE__ */ jsxs176("div", { className: "flex items-center gap-2.5", children: [
87644
- /* @__PURE__ */ jsxs176(
87695
+ children: /* @__PURE__ */ jsxs177("div", { className: "flex items-center gap-2.5", children: [
87696
+ /* @__PURE__ */ jsxs177(
87645
87697
  "button",
87646
87698
  {
87647
87699
  type: "button",
@@ -87654,8 +87706,8 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87654
87706
  isComplete ? "cursor-pointer" : "cursor-default"
87655
87707
  ].join(" "),
87656
87708
  children: [
87657
- isComplete && /* @__PURE__ */ jsxs176(Fragment58, { children: [
87658
- hovered && /* @__PURE__ */ jsx219(
87709
+ isComplete && /* @__PURE__ */ jsxs177(Fragment58, { children: [
87710
+ hovered && /* @__PURE__ */ jsx220(
87659
87711
  "video",
87660
87712
  {
87661
87713
  src: viewSrc,
@@ -87668,35 +87720,35 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87668
87720
  style: { opacity: videoReady ? 1 : 0 }
87669
87721
  }
87670
87722
  ),
87671
- /* @__PURE__ */ jsx219(
87723
+ /* @__PURE__ */ jsx220(
87672
87724
  "div",
87673
87725
  {
87674
87726
  className: "absolute inset-0 transition-opacity duration-150",
87675
87727
  style: { opacity: hovered && videoReady ? 0 : 1 },
87676
- children: /* @__PURE__ */ jsx219(VideoFrameThumbnail, { src: viewSrc })
87728
+ children: /* @__PURE__ */ jsx220(VideoFrameThumbnail, { src: viewSrc })
87677
87729
  }
87678
87730
  )
87679
87731
  ] }),
87680
- isRendering && /* @__PURE__ */ jsx219("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx219("div", { className: "w-2 h-2 rounded-full bg-accent animate-pulse motion-reduce:animate-none" }) }),
87681
- job.status === "failed" && /* @__PURE__ */ jsx219("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx219("div", { className: "w-2 h-2 rounded-full bg-danger" }) }),
87682
- job.status === "cancelled" && /* @__PURE__ */ jsx219("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx219("div", { className: "w-2 h-2 rounded-full bg-text-5" }) })
87732
+ isRendering && /* @__PURE__ */ jsx220("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx220("div", { className: "w-2 h-2 rounded-full bg-accent animate-pulse motion-reduce:animate-none" }) }),
87733
+ job.status === "failed" && /* @__PURE__ */ jsx220("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx220("div", { className: "w-2 h-2 rounded-full bg-danger" }) }),
87734
+ job.status === "cancelled" && /* @__PURE__ */ jsx220("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx220("div", { className: "w-2 h-2 rounded-full bg-text-5" }) })
87683
87735
  ]
87684
87736
  }
87685
87737
  ),
87686
- /* @__PURE__ */ jsxs176("div", { className: "flex-1 min-w-0", children: [
87687
- /* @__PURE__ */ jsxs176("div", { className: "flex items-center gap-1.5", children: [
87688
- /* @__PURE__ */ jsx219("span", { className: "text-step-11 font-medium text-text-2 truncate", children: job.filename }),
87689
- job.durationMs && /* @__PURE__ */ jsx219("span", { className: "text-step-9 text-text-5 shrink-0", children: formatDuration2(job.durationMs) })
87738
+ /* @__PURE__ */ jsxs177("div", { className: "flex-1 min-w-0", children: [
87739
+ /* @__PURE__ */ jsxs177("div", { className: "flex items-center gap-1.5", children: [
87740
+ /* @__PURE__ */ jsx220("span", { className: "text-step-11 font-medium text-text-2 truncate", children: job.filename }),
87741
+ job.durationMs && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-5 shrink-0", children: formatDuration2(job.durationMs) })
87690
87742
  ] }),
87691
- isRendering && /* @__PURE__ */ jsxs176("div", { className: "mt-1", children: [
87692
- /* @__PURE__ */ jsxs176("div", { className: "flex items-center justify-between mb-0.5", children: [
87693
- /* @__PURE__ */ jsx219("span", { className: "text-step-9 text-text-4", children: job.stage || "Rendering" }),
87694
- /* @__PURE__ */ jsxs176("span", { className: "text-step-9 font-mono text-accent", children: [
87743
+ isRendering && /* @__PURE__ */ jsxs177("div", { className: "mt-1", children: [
87744
+ /* @__PURE__ */ jsxs177("div", { className: "flex items-center justify-between mb-0.5", children: [
87745
+ /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-4", children: job.stage || "Rendering" }),
87746
+ /* @__PURE__ */ jsxs177("span", { className: "text-step-9 font-mono text-accent", children: [
87695
87747
  job.progress,
87696
87748
  "%"
87697
87749
  ] })
87698
87750
  ] }),
87699
- /* @__PURE__ */ jsx219(
87751
+ /* @__PURE__ */ jsx220(
87700
87752
  "div",
87701
87753
  {
87702
87754
  className: "w-full h-1 bg-border rounded-full overflow-hidden",
@@ -87705,7 +87757,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87705
87757
  "aria-valuemin": 0,
87706
87758
  "aria-valuemax": 100,
87707
87759
  "aria-label": `Render progress: ${job.progress}%`,
87708
- children: /* @__PURE__ */ jsx219(
87760
+ children: /* @__PURE__ */ jsx220(
87709
87761
  "div",
87710
87762
  {
87711
87763
  className: "h-full bg-accent rounded-full transition-all duration-300",
@@ -87715,11 +87767,11 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87715
87767
  }
87716
87768
  )
87717
87769
  ] }),
87718
- job.status === "failed" && job.error && /* @__PURE__ */ jsx219("span", { className: "text-step-9 text-danger mt-0.5 block", children: job.error }),
87719
- job.status === "cancelled" && /* @__PURE__ */ jsx219("span", { className: "text-step-9 text-text-4 mt-0.5 block", children: "Cancelled" }),
87720
- !isRendering && /* @__PURE__ */ jsx219("span", { className: "text-step-9 text-text-5", children: formatTimeAgo(job.createdAt) })
87770
+ job.status === "failed" && job.error && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-danger mt-0.5 block", children: job.error }),
87771
+ job.status === "cancelled" && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-4 mt-0.5 block", children: "Cancelled" }),
87772
+ !isRendering && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-5", children: formatTimeAgo(job.createdAt) })
87721
87773
  ] }),
87722
- /* @__PURE__ */ jsx219("div", { className: "flex items-center gap-1.5 shrink-0", children: isRendering ? /* @__PURE__ */ jsx219(
87774
+ /* @__PURE__ */ jsx220("div", { className: "flex items-center gap-1.5 shrink-0", children: isRendering ? /* @__PURE__ */ jsx220(
87723
87775
  Button,
87724
87776
  {
87725
87777
  size: "sm",
@@ -87730,8 +87782,8 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87730
87782
  },
87731
87783
  children: "Cancel"
87732
87784
  }
87733
- ) : confirmingDelete ? /* @__PURE__ */ jsxs176(Fragment58, { children: [
87734
- /* @__PURE__ */ jsx219(
87785
+ ) : confirmingDelete ? /* @__PURE__ */ jsxs177(Fragment58, { children: [
87786
+ /* @__PURE__ */ jsx220(
87735
87787
  Button,
87736
87788
  {
87737
87789
  size: "sm",
@@ -87744,7 +87796,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87744
87796
  children: "Delete?"
87745
87797
  }
87746
87798
  ),
87747
- /* @__PURE__ */ jsx219(
87799
+ /* @__PURE__ */ jsx220(
87748
87800
  Button,
87749
87801
  {
87750
87802
  size: "sm",
@@ -87756,15 +87808,15 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87756
87808
  children: "Keep"
87757
87809
  }
87758
87810
  )
87759
- ] }) : /* @__PURE__ */ jsxs176(Fragment58, { children: [
87760
- /* @__PURE__ */ jsx219(Tooltip, { label: isComplete ? "Download" : "Available when the render finishes", children: /* @__PURE__ */ jsx219(
87811
+ ] }) : /* @__PURE__ */ jsxs177(Fragment58, { children: [
87812
+ /* @__PURE__ */ jsx220(Tooltip, { label: isComplete ? "Download" : "Available when the render finishes", children: /* @__PURE__ */ jsx220(
87761
87813
  IconButton,
87762
87814
  {
87763
87815
  size: "sm",
87764
87816
  onClick: handleDownload,
87765
87817
  disabled: !isComplete,
87766
87818
  "aria-label": `Download ${job.filename}`,
87767
- icon: /* @__PURE__ */ jsxs176(
87819
+ icon: /* @__PURE__ */ jsxs177(
87768
87820
  "svg",
87769
87821
  {
87770
87822
  width: "12",
@@ -87777,15 +87829,15 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87777
87829
  strokeLinejoin: "round",
87778
87830
  "aria-hidden": "true",
87779
87831
  children: [
87780
- /* @__PURE__ */ jsx219("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
87781
- /* @__PURE__ */ jsx219("polyline", { points: "7 10 12 15 17 10" }),
87782
- /* @__PURE__ */ jsx219("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
87832
+ /* @__PURE__ */ jsx220("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
87833
+ /* @__PURE__ */ jsx220("polyline", { points: "7 10 12 15 17 10" }),
87834
+ /* @__PURE__ */ jsx220("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
87783
87835
  ]
87784
87836
  }
87785
87837
  )
87786
87838
  }
87787
87839
  ) }),
87788
- /* @__PURE__ */ jsx219(Tooltip, { label: "Delete render file", children: /* @__PURE__ */ jsx219(
87840
+ /* @__PURE__ */ jsx220(Tooltip, { label: "Delete render file", children: /* @__PURE__ */ jsx220(
87789
87841
  IconButton,
87790
87842
  {
87791
87843
  size: "sm",
@@ -87794,7 +87846,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87794
87846
  setConfirmingDelete(true);
87795
87847
  },
87796
87848
  "aria-label": `Delete ${job.filename}`,
87797
- icon: /* @__PURE__ */ jsx219(
87849
+ icon: /* @__PURE__ */ jsx220(
87798
87850
  "svg",
87799
87851
  {
87800
87852
  width: "12",
@@ -87805,7 +87857,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87805
87857
  strokeWidth: "2",
87806
87858
  strokeLinecap: "round",
87807
87859
  "aria-hidden": "true",
87808
- children: /* @__PURE__ */ jsx219("path", { d: "M18 6L6 18M6 6l12 12" })
87860
+ children: /* @__PURE__ */ jsx220("path", { d: "M18 6L6 18M6 6l12 12" })
87809
87861
  }
87810
87862
  )
87811
87863
  }
@@ -87818,7 +87870,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87818
87870
 
87819
87871
  // src/components/renders/FfmpegRequiredNotice.tsx
87820
87872
  import { memo as memo49, useEffect as useEffect140, useRef as useRef178, useState as useState143 } from "react";
87821
- import { jsx as jsx220, jsxs as jsxs177 } from "react/jsx-runtime";
87873
+ import { jsx as jsx221, jsxs as jsxs178 } from "react/jsx-runtime";
87822
87874
  var DOWNLOAD_URL = "https://ffmpeg.org/download.html";
87823
87875
  var CUE_MS = 1600;
87824
87876
  var FOCUS_RING = "outline-hidden focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-studio-accent";
@@ -87847,19 +87899,19 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87847
87899
  setCopied(true);
87848
87900
  window.setTimeout(() => setCopied(false), CUE_MS);
87849
87901
  };
87850
- return /* @__PURE__ */ jsxs177(
87902
+ return /* @__PURE__ */ jsxs178(
87851
87903
  "div",
87852
87904
  {
87853
87905
  role: "alert",
87854
87906
  className: "flex flex-col gap-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-2.5",
87855
87907
  children: [
87856
- /* @__PURE__ */ jsxs177("div", { className: "flex flex-col gap-0.5", children: [
87857
- /* @__PURE__ */ jsx220("span", { className: "text-[11px] font-semibold text-amber-300", children: status.title ?? "FFmpeg not found" }),
87858
- /* @__PURE__ */ jsx220("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.detail ?? "FFmpeg is required to encode video." })
87908
+ /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-0.5", children: [
87909
+ /* @__PURE__ */ jsx221("span", { className: "text-[11px] font-semibold text-amber-300", children: status.title ?? "FFmpeg not found" }),
87910
+ /* @__PURE__ */ jsx221("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.detail ?? "FFmpeg is required to encode video." })
87859
87911
  ] }),
87860
- status.command ? /* @__PURE__ */ jsxs177("div", { className: "flex items-center gap-1.5", children: [
87861
- /* @__PURE__ */ jsx220("code", { className: "flex-1 overflow-x-auto whitespace-nowrap rounded-xs bg-black/40 px-2 py-1 text-[10px] text-panel-text-2", children: status.command }),
87862
- /* @__PURE__ */ jsx220(
87912
+ status.command ? /* @__PURE__ */ jsxs178("div", { className: "flex items-center gap-1.5", children: [
87913
+ /* @__PURE__ */ jsx221("code", { className: "flex-1 overflow-x-auto whitespace-nowrap rounded-xs bg-black/40 px-2 py-1 text-[10px] text-panel-text-2", children: status.command }),
87914
+ /* @__PURE__ */ jsx221(
87863
87915
  "button",
87864
87916
  {
87865
87917
  type: "button",
@@ -87868,9 +87920,9 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87868
87920
  children: copied ? "Copied" : "Copy"
87869
87921
  }
87870
87922
  )
87871
- ] }) : status.hint && /* @__PURE__ */ jsx220("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.hint }),
87872
- /* @__PURE__ */ jsxs177("div", { className: "flex items-center gap-3", children: [
87873
- /* @__PURE__ */ jsx220(
87923
+ ] }) : status.hint && /* @__PURE__ */ jsx221("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.hint }),
87924
+ /* @__PURE__ */ jsxs178("div", { className: "flex items-center gap-3", children: [
87925
+ /* @__PURE__ */ jsx221(
87874
87926
  "button",
87875
87927
  {
87876
87928
  type: "button",
@@ -87880,7 +87932,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87880
87932
  children: checking ? "Checking\u2026" : "Recheck"
87881
87933
  }
87882
87934
  ),
87883
- /* @__PURE__ */ jsx220(
87935
+ /* @__PURE__ */ jsx221(
87884
87936
  "a",
87885
87937
  {
87886
87938
  href: DOWNLOAD_URL,
@@ -87890,7 +87942,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87890
87942
  children: "Other install options"
87891
87943
  }
87892
87944
  ),
87893
- /* @__PURE__ */ jsx220(
87945
+ /* @__PURE__ */ jsx221(
87894
87946
  "span",
87895
87947
  {
87896
87948
  "aria-live": "polite",
@@ -87905,7 +87957,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87905
87957
  });
87906
87958
 
87907
87959
  // src/components/renders/RenderQueue.tsx
87908
- import { jsx as jsx221, jsxs as jsxs178 } from "react/jsx-runtime";
87960
+ import { jsx as jsx222, jsxs as jsxs179 } from "react/jsx-runtime";
87909
87961
  var SCALE_OPTION_ORDER = ["auto", "1080p", "4k"];
87910
87962
  var SCALE_LABEL = {
87911
87963
  auto: "Auto",
@@ -87993,8 +88045,8 @@ function FormatInfoTooltip({ format }) {
87993
88045
  return () => document.removeEventListener("keydown", onKeyDown);
87994
88046
  }, [open]);
87995
88047
  const info = FORMAT_INFO[format];
87996
- return /* @__PURE__ */ jsxs178("div", { ref: triggerRef, className: "relative", onPointerEnter: show, onPointerLeave: hide, children: [
87997
- /* @__PURE__ */ jsx221(
88048
+ return /* @__PURE__ */ jsxs179("div", { ref: triggerRef, className: "relative", onPointerEnter: show, onPointerLeave: hide, children: [
88049
+ /* @__PURE__ */ jsx222(
87998
88050
  "button",
87999
88051
  {
88000
88052
  type: "button",
@@ -88005,7 +88057,7 @@ function FormatInfoTooltip({ format }) {
88005
88057
  onBlur: hide,
88006
88058
  onClick: () => setOpen((prev) => !prev),
88007
88059
  className: "flex items-center justify-center p-0.5 -m-0.5 rounded-sm text-text-5 hover:text-text-3 transition-colors cursor-help outline-hidden focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-accent",
88008
- children: /* @__PURE__ */ jsxs178(
88060
+ children: /* @__PURE__ */ jsxs179(
88009
88061
  "svg",
88010
88062
  {
88011
88063
  width: "12",
@@ -88018,16 +88070,16 @@ function FormatInfoTooltip({ format }) {
88018
88070
  strokeLinejoin: "round",
88019
88071
  "aria-hidden": "true",
88020
88072
  children: [
88021
- /* @__PURE__ */ jsx221("circle", { cx: "12", cy: "12", r: "10" }),
88022
- /* @__PURE__ */ jsx221("path", { d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" }),
88023
- /* @__PURE__ */ jsx221("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
88073
+ /* @__PURE__ */ jsx222("circle", { cx: "12", cy: "12", r: "10" }),
88074
+ /* @__PURE__ */ jsx222("path", { d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" }),
88075
+ /* @__PURE__ */ jsx222("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
88024
88076
  ]
88025
88077
  }
88026
88078
  )
88027
88079
  }
88028
88080
  ),
88029
88081
  open && createPortal10(
88030
- /* @__PURE__ */ jsxs178(
88082
+ /* @__PURE__ */ jsxs179(
88031
88083
  "div",
88032
88084
  {
88033
88085
  id: panelId,
@@ -88037,10 +88089,10 @@ function FormatInfoTooltip({ format }) {
88037
88089
  className: "fixed w-52 p-2 rounded-sm bg-input border border-border-input shadow-menu z-200",
88038
88090
  style: { left: position?.left ?? -9999, top: position?.top ?? -9999 },
88039
88091
  children: [
88040
- /* @__PURE__ */ jsx221("p", { className: "text-step-10 font-semibold text-text-1 mb-0.5", children: info.label }),
88041
- /* @__PURE__ */ jsx221("p", { className: "text-step-9 text-text-3 leading-tight", children: info.desc }),
88042
- /* @__PURE__ */ jsx221("div", { className: "mt-1.5 pt-1.5 border-t border-border", children: ["mp4", "mov", "webm"].filter((f) => f !== format).map((f) => /* @__PURE__ */ jsxs178("p", { className: "text-step-9 text-text-4 leading-relaxed", children: [
88043
- /* @__PURE__ */ jsx221("span", { className: "text-text-3 font-medium", children: FORMAT_INFO[f].label }),
88092
+ /* @__PURE__ */ jsx222("p", { className: "text-step-10 font-semibold text-text-1 mb-0.5", children: info.label }),
88093
+ /* @__PURE__ */ jsx222("p", { className: "text-step-9 text-text-3 leading-tight", children: info.desc }),
88094
+ /* @__PURE__ */ jsx222("div", { className: "mt-1.5 pt-1.5 border-t border-border", children: ["mp4", "mov", "webm"].filter((f) => f !== format).map((f) => /* @__PURE__ */ jsxs179("p", { className: "text-step-9 text-text-4 leading-relaxed", children: [
88095
+ /* @__PURE__ */ jsx222("span", { className: "text-text-3 font-medium", children: FORMAT_INFO[f].label }),
88044
88096
  " \u2014 ",
88045
88097
  FORMAT_INFO[f].desc
88046
88098
  ] }, f)) })
@@ -88086,8 +88138,8 @@ function FormatExportButton({
88086
88138
  const [fps, setFps] = useState144(persisted.fps);
88087
88139
  const missingFfmpeg = ffmpeg && !ffmpeg.ok ? ffmpeg : null;
88088
88140
  const showQuality = format !== "mov";
88089
- return /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-3", children: [
88090
- missingFfmpeg && /* @__PURE__ */ jsx221(
88141
+ return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-3", children: [
88142
+ missingFfmpeg && /* @__PURE__ */ jsx222(
88091
88143
  FfmpegRequiredNotice,
88092
88144
  {
88093
88145
  status: missingFfmpeg,
@@ -88095,13 +88147,13 @@ function FormatExportButton({
88095
88147
  onRecheck: onRecheckFfmpeg
88096
88148
  }
88097
88149
  ),
88098
- /* @__PURE__ */ jsxs178("div", { className: "grid grid-cols-2 gap-2", children: [
88099
- /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-1", children: [
88100
- /* @__PURE__ */ jsxs178("div", { className: "flex items-center gap-1", children: [
88101
- /* @__PURE__ */ jsx221("span", { className: "text-step-10 text-text-4", children: "Format" }),
88102
- /* @__PURE__ */ jsx221(FormatInfoTooltip, { format })
88150
+ /* @__PURE__ */ jsxs179("div", { className: "grid grid-cols-2 gap-2", children: [
88151
+ /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88152
+ /* @__PURE__ */ jsxs179("div", { className: "flex items-center gap-1", children: [
88153
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Format" }),
88154
+ /* @__PURE__ */ jsx222(FormatInfoTooltip, { format })
88103
88155
  ] }),
88104
- /* @__PURE__ */ jsx221(
88156
+ /* @__PURE__ */ jsx222(
88105
88157
  Select,
88106
88158
  {
88107
88159
  label: "Format",
@@ -88116,9 +88168,9 @@ function FormatExportButton({
88116
88168
  }
88117
88169
  )
88118
88170
  ] }),
88119
- /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-1", children: [
88120
- /* @__PURE__ */ jsx221("span", { className: "text-step-10 text-text-4", children: "Resolution" }),
88121
- /* @__PURE__ */ jsx221(
88171
+ /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88172
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Resolution" }),
88173
+ /* @__PURE__ */ jsx222(
88122
88174
  Select,
88123
88175
  {
88124
88176
  label: "Resolution",
@@ -88133,9 +88185,9 @@ function FormatExportButton({
88133
88185
  }
88134
88186
  )
88135
88187
  ] }),
88136
- /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-1", children: [
88137
- /* @__PURE__ */ jsx221("span", { className: "text-step-10 text-text-4", children: "Frame rate" }),
88138
- /* @__PURE__ */ jsx221(
88188
+ /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88189
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Frame rate" }),
88190
+ /* @__PURE__ */ jsx222(
88139
88191
  Select,
88140
88192
  {
88141
88193
  label: "Frame rate",
@@ -88150,9 +88202,9 @@ function FormatExportButton({
88150
88202
  }
88151
88203
  )
88152
88204
  ] }),
88153
- showQuality && /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-1", children: [
88154
- /* @__PURE__ */ jsx221("span", { className: "text-step-10 text-text-4", children: "Quality" }),
88155
- /* @__PURE__ */ jsx221(
88205
+ showQuality && /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88206
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Quality" }),
88207
+ /* @__PURE__ */ jsx222(
88156
88208
  Select,
88157
88209
  {
88158
88210
  label: "Quality",
@@ -88168,7 +88220,7 @@ function FormatExportButton({
88168
88220
  )
88169
88221
  ] })
88170
88222
  ] }),
88171
- /* @__PURE__ */ jsx221(
88223
+ /* @__PURE__ */ jsx222(
88172
88224
  Button,
88173
88225
  {
88174
88226
  variant: "primary",
@@ -88187,7 +88239,7 @@ function FormatExportButton({
88187
88239
  children: isRendering ? "Rendering\u2026" : "Export"
88188
88240
  }
88189
88241
  ),
88190
- lastRenderDurationMs !== void 0 && !isRendering && /* @__PURE__ */ jsxs178("p", { className: "text-step-9 text-text-5 text-center -mt-1.5", children: [
88242
+ lastRenderDurationMs !== void 0 && !isRendering && /* @__PURE__ */ jsxs179("p", { className: "text-step-9 text-text-5 text-center -mt-1.5", children: [
88191
88243
  "Last render took ",
88192
88244
  formatEta(lastRenderDurationMs)
88193
88245
  ] })
@@ -88218,8 +88270,8 @@ var RenderQueue = memo50(function RenderQueue2({
88218
88270
  }, [jobs.length]);
88219
88271
  const completedCount = jobs.filter((j) => j.status !== "rendering").length;
88220
88272
  const lastRenderDurationMs = [...jobs].reverse().find((j) => j.status === "complete" && j.durationMs !== void 0)?.durationMs;
88221
- return /* @__PURE__ */ jsxs178("div", { className: "flex flex-col h-full", children: [
88222
- /* @__PURE__ */ jsx221("div", { className: "px-3 py-3 border-b border-border shrink-0", children: /* @__PURE__ */ jsx221(
88273
+ return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col h-full", children: [
88274
+ /* @__PURE__ */ jsx222("div", { className: "px-3 py-3 border-b border-border shrink-0", children: /* @__PURE__ */ jsx222(
88223
88275
  FormatExportButton,
88224
88276
  {
88225
88277
  onStartRender,
@@ -88231,21 +88283,21 @@ var RenderQueue = memo50(function RenderQueue2({
88231
88283
  onRecheckFfmpeg
88232
88284
  }
88233
88285
  ) }),
88234
- actionError && /* @__PURE__ */ jsxs178(
88286
+ actionError && /* @__PURE__ */ jsxs179(
88235
88287
  "div",
88236
88288
  {
88237
88289
  role: "alert",
88238
88290
  className: "flex items-start justify-between gap-2 px-3 py-2 border-b border-border bg-danger/10",
88239
88291
  children: [
88240
- /* @__PURE__ */ jsx221("span", { className: "text-step-10 text-danger", children: actionError }),
88241
- onDismissActionError && /* @__PURE__ */ jsx221(
88292
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-danger", children: actionError }),
88293
+ onDismissActionError && /* @__PURE__ */ jsx222(
88242
88294
  IconButton,
88243
88295
  {
88244
88296
  size: "sm",
88245
88297
  onClick: onDismissActionError,
88246
88298
  "aria-label": "Dismiss error",
88247
88299
  className: "shrink-0",
88248
- icon: /* @__PURE__ */ jsx221(
88300
+ icon: /* @__PURE__ */ jsx222(
88249
88301
  "svg",
88250
88302
  {
88251
88303
  width: "10",
@@ -88256,7 +88308,7 @@ var RenderQueue = memo50(function RenderQueue2({
88256
88308
  strokeWidth: "2",
88257
88309
  strokeLinecap: "round",
88258
88310
  "aria-hidden": "true",
88259
- children: /* @__PURE__ */ jsx221("path", { d: "M18 6L6 18M6 6l12 12" })
88311
+ children: /* @__PURE__ */ jsx222("path", { d: "M18 6L6 18M6 6l12 12" })
88260
88312
  }
88261
88313
  )
88262
88314
  }
@@ -88264,11 +88316,11 @@ var RenderQueue = memo50(function RenderQueue2({
88264
88316
  ]
88265
88317
  }
88266
88318
  ),
88267
- /* @__PURE__ */ jsx221("div", { ref: listRef, className: "flex-1 overflow-y-auto", children: loadError && jobs.length === 0 ? /* @__PURE__ */ jsxs178("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", role: "alert", children: [
88268
- /* @__PURE__ */ jsx221("p", { className: "text-step-10 text-danger text-center", children: loadError }),
88269
- onRetryLoad && /* @__PURE__ */ jsx221(Button, { size: "sm", variant: "secondary", onClick: onRetryLoad, children: "Retry" })
88270
- ] }) : jobs.length === 0 ? /* @__PURE__ */ jsxs178("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
88271
- /* @__PURE__ */ jsxs178(
88319
+ /* @__PURE__ */ jsx222("div", { ref: listRef, className: "flex-1 overflow-y-auto", children: loadError && jobs.length === 0 ? /* @__PURE__ */ jsxs179("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", role: "alert", children: [
88320
+ /* @__PURE__ */ jsx222("p", { className: "text-step-10 text-danger text-center", children: loadError }),
88321
+ onRetryLoad && /* @__PURE__ */ jsx222(Button, { size: "sm", variant: "secondary", onClick: onRetryLoad, children: "Retry" })
88322
+ ] }) : jobs.length === 0 ? /* @__PURE__ */ jsxs179("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
88323
+ /* @__PURE__ */ jsxs179(
88272
88324
  "svg",
88273
88325
  {
88274
88326
  width: "20",
@@ -88279,7 +88331,7 @@ var RenderQueue = memo50(function RenderQueue2({
88279
88331
  strokeWidth: "1.5",
88280
88332
  className: "text-text-5",
88281
88333
  children: [
88282
- /* @__PURE__ */ jsx221(
88334
+ /* @__PURE__ */ jsx222(
88283
88335
  "rect",
88284
88336
  {
88285
88337
  x: "2",
@@ -88292,7 +88344,7 @@ var RenderQueue = memo50(function RenderQueue2({
88292
88344
  strokeLinejoin: "round"
88293
88345
  }
88294
88346
  ),
88295
- /* @__PURE__ */ jsx221(
88347
+ /* @__PURE__ */ jsx222(
88296
88348
  "path",
88297
88349
  {
88298
88350
  d: "M7 2v20M17 2v20M2 12h20M2 7h5M2 17h5M17 17h5M17 7h5",
@@ -88303,17 +88355,17 @@ var RenderQueue = memo50(function RenderQueue2({
88303
88355
  ]
88304
88356
  }
88305
88357
  ),
88306
- /* @__PURE__ */ jsx221("p", { className: "text-step-10 text-text-5 text-center", children: "No renders yet" })
88307
- ] }) : /* @__PURE__ */ jsxs178("div", { children: [
88308
- completedCount > 0 && /* @__PURE__ */ jsxs178("div", { className: "flex items-center justify-between px-3 py-1.5 border-b border-border", children: [
88309
- /* @__PURE__ */ jsxs178("span", { className: "text-step-10 text-text-4", children: [
88358
+ /* @__PURE__ */ jsx222("p", { className: "text-step-10 text-text-5 text-center", children: "No renders yet" })
88359
+ ] }) : /* @__PURE__ */ jsxs179("div", { children: [
88360
+ completedCount > 0 && /* @__PURE__ */ jsxs179("div", { className: "flex items-center justify-between px-3 py-1.5 border-b border-border", children: [
88361
+ /* @__PURE__ */ jsxs179("span", { className: "text-step-10 text-text-4", children: [
88310
88362
  jobs.length,
88311
88363
  " render",
88312
88364
  jobs.length === 1 ? "" : "s"
88313
88365
  ] }),
88314
- /* @__PURE__ */ jsx221(Tooltip, { label: "Hide finished renders from this list (files stay on disk)", children: /* @__PURE__ */ jsx221(Button, { size: "sm", variant: "ghost", onClick: onClearCompleted, children: "Hide finished" }) })
88366
+ /* @__PURE__ */ jsx222(Tooltip, { label: "Hide finished renders from this list (files stay on disk)", children: /* @__PURE__ */ jsx222(Button, { size: "sm", variant: "ghost", onClick: onClearCompleted, children: "Hide finished" }) })
88315
88367
  ] }),
88316
- jobs.map((job) => /* @__PURE__ */ jsx221(
88368
+ jobs.map((job) => /* @__PURE__ */ jsx222(
88317
88369
  RenderQueueItem,
88318
88370
  {
88319
88371
  job,
@@ -88328,10 +88380,10 @@ var RenderQueue = memo50(function RenderQueue2({
88328
88380
  });
88329
88381
 
88330
88382
  // src/components/renders/RenderQueuePanel.tsx
88331
- import { jsx as jsx222 } from "react/jsx-runtime";
88383
+ import { jsx as jsx223 } from "react/jsx-runtime";
88332
88384
  var RenderQueuePanel = memo51(function RenderQueuePanel2() {
88333
88385
  const { projectId, compositionDimensions, waitForPendingDomEditSaves, renderQueue } = useStudioShellContext();
88334
- return /* @__PURE__ */ jsx222(
88386
+ return /* @__PURE__ */ jsx223(
88335
88387
  RenderQueue,
88336
88388
  {
88337
88389
  jobs: renderQueue.jobs,
@@ -88370,13 +88422,13 @@ import { parseSlideshowManifest } from "@hyperframes/core/slideshow";
88370
88422
 
88371
88423
  // src/components/panels/SlideshowSubPanels.tsx
88372
88424
  import { useState as useState145, useCallback as useCallback165, useId as useId8 } from "react";
88373
- import { jsx as jsx223, jsxs as jsxs179 } from "react/jsx-runtime";
88425
+ import { jsx as jsx224, jsxs as jsxs180 } from "react/jsx-runtime";
88374
88426
  function SectionHeader({
88375
88427
  children,
88376
88428
  expanded,
88377
88429
  onToggle
88378
88430
  }) {
88379
- return /* @__PURE__ */ jsxs179(
88431
+ return /* @__PURE__ */ jsxs180(
88380
88432
  "button",
88381
88433
  {
88382
88434
  type: "button",
@@ -88384,8 +88436,8 @@ function SectionHeader({
88384
88436
  onClick: onToggle,
88385
88437
  "aria-expanded": expanded,
88386
88438
  children: [
88387
- /* @__PURE__ */ jsx223("span", { children }),
88388
- /* @__PURE__ */ jsx223("span", { className: "text-[10px] text-neutral-600", children: expanded ? "\u25B2" : "\u25BC" })
88439
+ /* @__PURE__ */ jsx224("span", { children }),
88440
+ /* @__PURE__ */ jsx224("span", { className: "text-[10px] text-neutral-600", children: expanded ? "\u25B2" : "\u25BC" })
88389
88441
  ]
88390
88442
  }
88391
88443
  );
@@ -88403,12 +88455,12 @@ function SlideList({
88403
88455
  const orderedSlideScenes = slides.map((sl) => sceneById.get(sl.sceneId)).filter((s) => s !== void 0);
88404
88456
  const nonSlideScenes = scenes.filter((sc) => !slideIds.has(sc.id));
88405
88457
  const rows = [...orderedSlideScenes, ...nonSlideScenes];
88406
- return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-px", children: [
88458
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-px", children: [
88407
88459
  rows.map((scene) => {
88408
88460
  const isSlide = slideIds.has(scene.id);
88409
88461
  const isSelected = selectedSceneId === scene.id;
88410
88462
  const slideIndex = slides.findIndex((s) => s.sceneId === scene.id);
88411
- return /* @__PURE__ */ jsxs179(
88463
+ return /* @__PURE__ */ jsxs180(
88412
88464
  "div",
88413
88465
  {
88414
88466
  role: "button",
@@ -88423,7 +88475,7 @@ function SlideList({
88423
88475
  }
88424
88476
  },
88425
88477
  children: [
88426
- /* @__PURE__ */ jsx223(
88478
+ /* @__PURE__ */ jsx224(
88427
88479
  "input",
88428
88480
  {
88429
88481
  type: "checkbox",
@@ -88434,9 +88486,9 @@ function SlideList({
88434
88486
  className: "accent-studio-accent shrink-0"
88435
88487
  }
88436
88488
  ),
88437
- /* @__PURE__ */ jsx223("span", { className: "flex-1 truncate", children: scene.label || scene.id }),
88438
- isSlide && /* @__PURE__ */ jsxs179("span", { className: "flex gap-0.5 shrink-0", children: [
88439
- /* @__PURE__ */ jsx223(
88489
+ /* @__PURE__ */ jsx224("span", { className: "flex-1 truncate", children: scene.label || scene.id }),
88490
+ isSlide && /* @__PURE__ */ jsxs180("span", { className: "flex gap-0.5 shrink-0", children: [
88491
+ /* @__PURE__ */ jsx224(
88440
88492
  "button",
88441
88493
  {
88442
88494
  type: "button",
@@ -88451,7 +88503,7 @@ function SlideList({
88451
88503
  children: "\u25B2"
88452
88504
  }
88453
88505
  ),
88454
- /* @__PURE__ */ jsx223(
88506
+ /* @__PURE__ */ jsx224(
88455
88507
  "button",
88456
88508
  {
88457
88509
  type: "button",
@@ -88472,7 +88524,7 @@ function SlideList({
88472
88524
  scene.id
88473
88525
  );
88474
88526
  }),
88475
- scenes.length === 0 && /* @__PURE__ */ jsx223("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "No scenes found" })
88527
+ scenes.length === 0 && /* @__PURE__ */ jsx224("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "No scenes found" })
88476
88528
  ] });
88477
88529
  }
88478
88530
  function SlideInspector({
@@ -88484,14 +88536,14 @@ function SlideInspector({
88484
88536
  onRemoveFragment
88485
88537
  }) {
88486
88538
  const fragments = slide?.fragments ?? [];
88487
- return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88488
- /* @__PURE__ */ jsxs179("p", { className: "text-[10px] text-neutral-500 font-medium uppercase tracking-wide truncate", children: [
88539
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88540
+ /* @__PURE__ */ jsxs180("p", { className: "text-[10px] text-neutral-500 font-medium uppercase tracking-wide truncate", children: [
88489
88541
  "Scene: ",
88490
88542
  sceneId
88491
88543
  ] }),
88492
- /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88493
- /* @__PURE__ */ jsx223("label", { className: "text-[11px] text-neutral-400", children: "Notes" }),
88494
- /* @__PURE__ */ jsx223(
88544
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1", children: [
88545
+ /* @__PURE__ */ jsx224("label", { className: "text-[11px] text-neutral-400", children: "Notes" }),
88546
+ /* @__PURE__ */ jsx224(
88495
88547
  "textarea",
88496
88548
  {
88497
88549
  className: "bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1.5 text-[11px] text-white resize-none placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden",
@@ -88502,10 +88554,10 @@ function SlideInspector({
88502
88554
  }
88503
88555
  )
88504
88556
  ] }),
88505
- /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1.5", children: [
88506
- /* @__PURE__ */ jsxs179("div", { className: "flex items-center justify-between", children: [
88507
- /* @__PURE__ */ jsx223("span", { className: "text-[11px] text-neutral-400", children: "Fragment hold-points" }),
88508
- /* @__PURE__ */ jsxs179(
88557
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1.5", children: [
88558
+ /* @__PURE__ */ jsxs180("div", { className: "flex items-center justify-between", children: [
88559
+ /* @__PURE__ */ jsx224("span", { className: "text-[11px] text-neutral-400", children: "Fragment hold-points" }),
88560
+ /* @__PURE__ */ jsxs180(
88509
88561
  "button",
88510
88562
  {
88511
88563
  type: "button",
@@ -88520,14 +88572,14 @@ function SlideInspector({
88520
88572
  }
88521
88573
  )
88522
88574
  ] }),
88523
- fragments.length > 0 ? /* @__PURE__ */ jsx223("div", { className: "flex flex-wrap gap-1", children: fragments.map((t, i) => /* @__PURE__ */ jsxs179(
88575
+ fragments.length > 0 ? /* @__PURE__ */ jsx224("div", { className: "flex flex-wrap gap-1", children: fragments.map((t, i) => /* @__PURE__ */ jsxs180(
88524
88576
  "span",
88525
88577
  {
88526
88578
  className: "inline-flex items-center gap-1 bg-neutral-700 rounded-sm px-1.5 py-0.5 text-[10px] text-neutral-200",
88527
88579
  children: [
88528
88580
  t.toFixed(2),
88529
88581
  "s",
88530
- /* @__PURE__ */ jsx223(
88582
+ /* @__PURE__ */ jsx224(
88531
88583
  "button",
88532
88584
  {
88533
88585
  type: "button",
@@ -88540,7 +88592,7 @@ function SlideInspector({
88540
88592
  ]
88541
88593
  },
88542
88594
  `frag-${i}`
88543
- )) }) : /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-600 italic", children: "No hold-points yet" })
88595
+ )) }) : /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-600 italic", children: "No hold-points yet" })
88544
88596
  ] })
88545
88597
  ] });
88546
88598
  }
@@ -88563,9 +88615,9 @@ function BranchTree({
88563
88615
  onCreateSequence(label);
88564
88616
  setNewLabel("");
88565
88617
  }, [newLabel, onCreateSequence]);
88566
- return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88567
- /* @__PURE__ */ jsxs179("div", { className: "flex gap-1.5", children: [
88568
- /* @__PURE__ */ jsx223(
88618
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88619
+ /* @__PURE__ */ jsxs180("div", { className: "flex gap-1.5", children: [
88620
+ /* @__PURE__ */ jsx224(
88569
88621
  "input",
88570
88622
  {
88571
88623
  id: inputId,
@@ -88580,7 +88632,7 @@ function BranchTree({
88580
88632
  "aria-label": "New branch sequence name"
88581
88633
  }
88582
88634
  ),
88583
- /* @__PURE__ */ jsx223(
88635
+ /* @__PURE__ */ jsx224(
88584
88636
  "button",
88585
88637
  {
88586
88638
  type: "button",
@@ -88590,7 +88642,7 @@ function BranchTree({
88590
88642
  }
88591
88643
  )
88592
88644
  ] }),
88593
- sequences.length === 0 ? /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-600 italic", children: "No branches yet" }) : /* @__PURE__ */ jsx223("div", { className: "flex flex-col gap-3", children: sequences.map((seq) => /* @__PURE__ */ jsx223(
88645
+ sequences.length === 0 ? /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-600 italic", children: "No branches yet" }) : /* @__PURE__ */ jsx224("div", { className: "flex flex-col gap-3", children: sequences.map((seq) => /* @__PURE__ */ jsx224(
88594
88646
  BranchItem,
88595
88647
  {
88596
88648
  seq,
@@ -88624,9 +88676,9 @@ function BranchItem({
88624
88676
  if (label && label !== seq.label) onRename(seq.id, label);
88625
88677
  setEditing(false);
88626
88678
  }, [draft, onRename, seq.id, seq.label]);
88627
- return /* @__PURE__ */ jsxs179("div", { className: "border border-neutral-700/60 rounded-sm p-2 flex flex-col gap-2", children: [
88628
- /* @__PURE__ */ jsxs179("div", { className: "flex items-center gap-1", children: [
88629
- editing ? /* @__PURE__ */ jsx223(
88679
+ return /* @__PURE__ */ jsxs180("div", { className: "border border-neutral-700/60 rounded-sm p-2 flex flex-col gap-2", children: [
88680
+ /* @__PURE__ */ jsxs180("div", { className: "flex items-center gap-1", children: [
88681
+ editing ? /* @__PURE__ */ jsx224(
88630
88682
  "input",
88631
88683
  {
88632
88684
  className: "flex-1 bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-0.5 text-[11px] text-white focus:border-studio-accent/60 focus:outline-hidden",
@@ -88640,7 +88692,7 @@ function BranchItem({
88640
88692
  },
88641
88693
  "aria-label": `Rename branch ${seq.label}`
88642
88694
  }
88643
- ) : /* @__PURE__ */ jsx223(
88695
+ ) : /* @__PURE__ */ jsx224(
88644
88696
  "span",
88645
88697
  {
88646
88698
  role: "button",
@@ -88657,7 +88709,7 @@ function BranchItem({
88657
88709
  children: seq.label
88658
88710
  }
88659
88711
  ),
88660
- /* @__PURE__ */ jsx223(
88712
+ /* @__PURE__ */ jsx224(
88661
88713
  "button",
88662
88714
  {
88663
88715
  type: "button",
@@ -88668,16 +88720,16 @@ function BranchItem({
88668
88720
  }
88669
88721
  )
88670
88722
  ] }),
88671
- confirmingDelete && /* @__PURE__ */ jsxs179("div", { className: "px-2 py-1.5 bg-red-950/30 border-l-2 border-red-500 flex flex-col gap-1 rounded-xs", children: [
88672
- /* @__PURE__ */ jsxs179("span", { className: "text-[10px] text-red-400", children: [
88723
+ confirmingDelete && /* @__PURE__ */ jsxs180("div", { className: "px-2 py-1.5 bg-red-950/30 border-l-2 border-red-500 flex flex-col gap-1 rounded-xs", children: [
88724
+ /* @__PURE__ */ jsxs180("span", { className: "text-[10px] text-red-400", children: [
88673
88725
  "Delete branch \u201C",
88674
88726
  seq.label,
88675
88727
  "\u201D",
88676
88728
  seq.slides.length > 0 ? ` and its ${seq.slides.length} slide${seq.slides.length === 1 ? "" : "s"}` : "",
88677
88729
  "? Hotspots pointing to it will no longer resolve."
88678
88730
  ] }),
88679
- /* @__PURE__ */ jsxs179("div", { className: "flex items-center justify-end gap-1", children: [
88680
- /* @__PURE__ */ jsx223(
88731
+ /* @__PURE__ */ jsxs180("div", { className: "flex items-center justify-end gap-1", children: [
88732
+ /* @__PURE__ */ jsx224(
88681
88733
  "button",
88682
88734
  {
88683
88735
  type: "button",
@@ -88689,7 +88741,7 @@ function BranchItem({
88689
88741
  children: "Delete"
88690
88742
  }
88691
88743
  ),
88692
- /* @__PURE__ */ jsx223(
88744
+ /* @__PURE__ */ jsx224(
88693
88745
  "button",
88694
88746
  {
88695
88747
  type: "button",
@@ -88700,16 +88752,16 @@ function BranchItem({
88700
88752
  )
88701
88753
  ] })
88702
88754
  ] }),
88703
- /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-px pl-2", children: [
88755
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-px pl-2", children: [
88704
88756
  scenes.map((scene) => {
88705
88757
  const assigned = seq.slides.some((s) => s.sceneId === scene.id);
88706
88758
  const isSelected = selectedSequenceId === seq.id && selectedSceneId === scene.id;
88707
- return /* @__PURE__ */ jsxs179(
88759
+ return /* @__PURE__ */ jsxs180(
88708
88760
  "div",
88709
88761
  {
88710
88762
  className: "flex items-center gap-1.5 py-0.5 text-[11px] text-neutral-400",
88711
88763
  children: [
88712
- /* @__PURE__ */ jsx223(
88764
+ /* @__PURE__ */ jsx224(
88713
88765
  "input",
88714
88766
  {
88715
88767
  type: "checkbox",
@@ -88719,7 +88771,7 @@ function BranchItem({
88719
88771
  className: "accent-studio-accent shrink-0"
88720
88772
  }
88721
88773
  ),
88722
- assigned ? /* @__PURE__ */ jsx223(
88774
+ assigned ? /* @__PURE__ */ jsx224(
88723
88775
  "button",
88724
88776
  {
88725
88777
  type: "button",
@@ -88728,13 +88780,13 @@ function BranchItem({
88728
88780
  onClick: () => onSelectBranchSlide(seq.id, scene.id),
88729
88781
  children: scene.label || scene.id
88730
88782
  }
88731
- ) : /* @__PURE__ */ jsx223("span", { className: "flex-1 truncate", children: scene.label || scene.id })
88783
+ ) : /* @__PURE__ */ jsx224("span", { className: "flex-1 truncate", children: scene.label || scene.id })
88732
88784
  ]
88733
88785
  },
88734
88786
  scene.id
88735
88787
  );
88736
88788
  }),
88737
- scenes.length === 0 && /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-600 italic", children: "No scenes" })
88789
+ scenes.length === 0 && /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-600 italic", children: "No scenes" })
88738
88790
  ] })
88739
88791
  ] });
88740
88792
  }
@@ -88760,19 +88812,19 @@ function HotspotTool({
88760
88812
  setHotspotLabel("");
88761
88813
  }, [selectedSceneId, targetSequenceId, elementKey3, hotspotLabel, onAddHotspot]);
88762
88814
  if (!selectedSceneId) {
88763
- return /* @__PURE__ */ jsx223("div", { className: "px-3 py-2", children: /* @__PURE__ */ jsx223("p", { className: "text-[11px] text-neutral-500 italic", children: "Select a scene in the Slides list" }) });
88815
+ return /* @__PURE__ */ jsx224("div", { className: "px-3 py-2", children: /* @__PURE__ */ jsx224("p", { className: "text-[11px] text-neutral-500 italic", children: "Select a scene in the Slides list" }) });
88764
88816
  }
88765
- return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88766
- /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1.5", children: [
88767
- /* @__PURE__ */ jsxs179("p", { className: "text-[11px] text-neutral-400", children: [
88817
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88818
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1.5", children: [
88819
+ /* @__PURE__ */ jsxs180("p", { className: "text-[11px] text-neutral-400", children: [
88768
88820
  "Selected element:",
88769
88821
  " ",
88770
- /* @__PURE__ */ jsx223("span", { className: "text-neutral-200 font-mono", children: elementKey3 ?? "none" })
88822
+ /* @__PURE__ */ jsx224("span", { className: "text-neutral-200 font-mono", children: elementKey3 ?? "none" })
88771
88823
  ] }),
88772
- !elementKey3 && /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-500 italic", children: "Click an element on the canvas to choose the hotspot target." }),
88773
- sequences.length === 0 && /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-500 italic", children: "Create a branch in the Branches section first \u2014 hotspots jump to a branch." }),
88774
- /* @__PURE__ */ jsx223("label", { className: "text-[11px] text-neutral-400", children: "Hotspot label" }),
88775
- /* @__PURE__ */ jsx223(
88824
+ !elementKey3 && /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-500 italic", children: "Click an element on the canvas to choose the hotspot target." }),
88825
+ sequences.length === 0 && /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-500 italic", children: "Create a branch in the Branches section first \u2014 hotspots jump to a branch." }),
88826
+ /* @__PURE__ */ jsx224("label", { className: "text-[11px] text-neutral-400", children: "Hotspot label" }),
88827
+ /* @__PURE__ */ jsx224(
88776
88828
  "input",
88777
88829
  {
88778
88830
  type: "text",
@@ -88783,8 +88835,8 @@ function HotspotTool({
88783
88835
  "aria-label": "Hotspot label"
88784
88836
  }
88785
88837
  ),
88786
- /* @__PURE__ */ jsx223("label", { className: "text-[11px] text-neutral-400", children: "Target branch" }),
88787
- /* @__PURE__ */ jsxs179(
88838
+ /* @__PURE__ */ jsx224("label", { className: "text-[11px] text-neutral-400", children: "Target branch" }),
88839
+ /* @__PURE__ */ jsxs180(
88788
88840
  "select",
88789
88841
  {
88790
88842
  className: "bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-white focus:border-studio-accent/60 focus:outline-hidden",
@@ -88792,12 +88844,12 @@ function HotspotTool({
88792
88844
  onChange: (e) => setTargetSequenceId(e.target.value),
88793
88845
  "aria-label": "Target branch sequence",
88794
88846
  children: [
88795
- /* @__PURE__ */ jsx223("option", { value: "", children: "\u2014 select branch \u2014" }),
88796
- sequences.map((seq) => /* @__PURE__ */ jsx223("option", { value: seq.id, children: seq.label }, seq.id))
88847
+ /* @__PURE__ */ jsx224("option", { value: "", children: "\u2014 select branch \u2014" }),
88848
+ sequences.map((seq) => /* @__PURE__ */ jsx224("option", { value: seq.id, children: seq.label }, seq.id))
88797
88849
  ]
88798
88850
  }
88799
88851
  ),
88800
- /* @__PURE__ */ jsx223(
88852
+ /* @__PURE__ */ jsx224(
88801
88853
  "button",
88802
88854
  {
88803
88855
  type: "button",
@@ -88809,21 +88861,21 @@ function HotspotTool({
88809
88861
  }
88810
88862
  )
88811
88863
  ] }),
88812
- hotspots.length > 0 && /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1.5", children: [
88813
- /* @__PURE__ */ jsx223("p", { className: "text-[11px] text-neutral-400 font-medium", children: "Hotspots on this slide" }),
88864
+ hotspots.length > 0 && /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1.5", children: [
88865
+ /* @__PURE__ */ jsx224("p", { className: "text-[11px] text-neutral-400 font-medium", children: "Hotspots on this slide" }),
88814
88866
  hotspots.map((h) => {
88815
88867
  const seqLabel = sequences.find((s) => s.id === h.target)?.label ?? h.target;
88816
- return /* @__PURE__ */ jsxs179(
88868
+ return /* @__PURE__ */ jsxs180(
88817
88869
  "div",
88818
88870
  {
88819
88871
  className: "flex items-center gap-2 bg-neutral-800 rounded-sm px-2 py-1",
88820
88872
  children: [
88821
- /* @__PURE__ */ jsxs179("span", { className: "flex-1 text-[11px] text-neutral-200 truncate", children: [
88873
+ /* @__PURE__ */ jsxs180("span", { className: "flex-1 text-[11px] text-neutral-200 truncate", children: [
88822
88874
  h.label,
88823
88875
  " \u2192 ",
88824
- /* @__PURE__ */ jsx223("span", { className: "text-neutral-400", children: seqLabel })
88876
+ /* @__PURE__ */ jsx224("span", { className: "text-neutral-400", children: seqLabel })
88825
88877
  ] }),
88826
- /* @__PURE__ */ jsx223(
88878
+ /* @__PURE__ */ jsx224(
88827
88879
  "button",
88828
88880
  {
88829
88881
  type: "button",
@@ -88973,7 +89025,7 @@ function removeHotspot(manifest, sceneId, hotspotId, sequenceId) {
88973
89025
  }
88974
89026
 
88975
89027
  // src/components/panels/SlideshowPanel.tsx
88976
- import { Fragment as Fragment59, jsx as jsx224, jsxs as jsxs180 } from "react/jsx-runtime";
89028
+ import { Fragment as Fragment59, jsx as jsx225, jsxs as jsxs181 } from "react/jsx-runtime";
88977
89029
  function safeParseManifest(html2) {
88978
89030
  try {
88979
89031
  return parseSlideshowManifest(html2) ?? { slides: [] };
@@ -89237,7 +89289,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89237
89289
  },
89238
89290
  [selectedSequenceId, applyManifest]
89239
89291
  );
89240
- return /* @__PURE__ */ jsxs180(
89292
+ return /* @__PURE__ */ jsxs181(
89241
89293
  "div",
89242
89294
  {
89243
89295
  className: "flex flex-col h-full overflow-y-auto text-white",
@@ -89251,14 +89303,14 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89251
89303
  }
89252
89304
  },
89253
89305
  children: [
89254
- persistError && /* @__PURE__ */ jsxs180(
89306
+ persistError && /* @__PURE__ */ jsxs181(
89255
89307
  "div",
89256
89308
  {
89257
89309
  role: "alert",
89258
89310
  className: "flex items-center justify-between gap-2 px-3 py-2 bg-red-950/40 border-b border-red-500/40",
89259
89311
  children: [
89260
- /* @__PURE__ */ jsx224("span", { className: "text-[11px] text-red-300", children: "Changes not saved" }),
89261
- /* @__PURE__ */ jsx224(
89312
+ /* @__PURE__ */ jsx225("span", { className: "text-[11px] text-red-300", children: "Changes not saved" }),
89313
+ /* @__PURE__ */ jsx225(
89262
89314
  "button",
89263
89315
  {
89264
89316
  type: "button",
@@ -89271,7 +89323,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89271
89323
  ]
89272
89324
  }
89273
89325
  ),
89274
- undoDepth > 0 && /* @__PURE__ */ jsx224("div", { className: "flex items-center justify-end px-3 py-1 border-b border-neutral-800/60", children: /* @__PURE__ */ jsxs180(
89326
+ undoDepth > 0 && /* @__PURE__ */ jsx225("div", { className: "flex items-center justify-end px-3 py-1 border-b border-neutral-800/60", children: /* @__PURE__ */ jsxs181(
89275
89327
  "button",
89276
89328
  {
89277
89329
  type: "button",
@@ -89285,7 +89337,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89285
89337
  ]
89286
89338
  }
89287
89339
  ) }),
89288
- /* @__PURE__ */ jsxs180(
89340
+ /* @__PURE__ */ jsxs181(
89289
89341
  SectionHeader,
89290
89342
  {
89291
89343
  expanded: expandedSections.has("slides"),
@@ -89297,7 +89349,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89297
89349
  ]
89298
89350
  }
89299
89351
  ),
89300
- expandedSections.has("slides") && /* @__PURE__ */ jsx224("div", { className: "py-1", children: /* @__PURE__ */ jsx224(
89352
+ expandedSections.has("slides") && /* @__PURE__ */ jsx225("div", { className: "py-1", children: /* @__PURE__ */ jsx225(
89301
89353
  SlideList,
89302
89354
  {
89303
89355
  scenes,
@@ -89311,7 +89363,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89311
89363
  onReorder: handleReorder
89312
89364
  }
89313
89365
  ) }),
89314
- /* @__PURE__ */ jsx224(
89366
+ /* @__PURE__ */ jsx225(
89315
89367
  SectionHeader,
89316
89368
  {
89317
89369
  expanded: expandedSections.has("inspector"),
@@ -89319,7 +89371,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89319
89371
  children: "Slide Inspector"
89320
89372
  }
89321
89373
  ),
89322
- expandedSections.has("inspector") && /* @__PURE__ */ jsx224(Fragment59, { children: selectedSceneId ? /* @__PURE__ */ jsx224(
89374
+ expandedSections.has("inspector") && /* @__PURE__ */ jsx225(Fragment59, { children: selectedSceneId ? /* @__PURE__ */ jsx225(
89323
89375
  SlideInspector,
89324
89376
  {
89325
89377
  sceneId: selectedSceneId,
@@ -89329,8 +89381,8 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89329
89381
  onMarkFragment: handleMarkFragment,
89330
89382
  onRemoveFragment: handleRemoveFragment
89331
89383
  }
89332
- ) : /* @__PURE__ */ jsx224("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "Select a scene above to inspect" }) }),
89333
- /* @__PURE__ */ jsxs180(
89384
+ ) : /* @__PURE__ */ jsx225("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "Select a scene above to inspect" }) }),
89385
+ /* @__PURE__ */ jsxs181(
89334
89386
  SectionHeader,
89335
89387
  {
89336
89388
  expanded: expandedSections.has("branches"),
@@ -89342,7 +89394,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89342
89394
  ]
89343
89395
  }
89344
89396
  ),
89345
- expandedSections.has("branches") && /* @__PURE__ */ jsx224(
89397
+ expandedSections.has("branches") && /* @__PURE__ */ jsx225(
89346
89398
  BranchTree,
89347
89399
  {
89348
89400
  sequences,
@@ -89356,7 +89408,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89356
89408
  onSelectBranchSlide: handleSelectBranchSlide
89357
89409
  }
89358
89410
  ),
89359
- /* @__PURE__ */ jsx224(
89411
+ /* @__PURE__ */ jsx225(
89360
89412
  SectionHeader,
89361
89413
  {
89362
89414
  expanded: expandedSections.has("hotspot"),
@@ -89364,7 +89416,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89364
89416
  children: "Hotspot Tool"
89365
89417
  }
89366
89418
  ),
89367
- expandedSections.has("hotspot") && /* @__PURE__ */ jsx224(
89419
+ expandedSections.has("hotspot") && /* @__PURE__ */ jsx225(
89368
89420
  HotspotTool,
89369
89421
  {
89370
89422
  selectedSceneId,
@@ -89506,7 +89558,7 @@ function useEditVariablesInFile(deps) {
89506
89558
 
89507
89559
  // src/components/panels/VariablesDeclarationForm.tsx
89508
89560
  import { useState as useState148 } from "react";
89509
- import { jsx as jsx225, jsxs as jsxs181 } from "react/jsx-runtime";
89561
+ import { jsx as jsx226, jsxs as jsxs182 } from "react/jsx-runtime";
89510
89562
  var VARIABLE_TYPES = [
89511
89563
  "string",
89512
89564
  "number",
@@ -89608,8 +89660,8 @@ function declarationFromDraft(draft) {
89608
89660
  }
89609
89661
  }
89610
89662
  function Field({ label, children }) {
89611
- return /* @__PURE__ */ jsxs181("div", { className: "space-y-1", children: [
89612
- /* @__PURE__ */ jsx225("label", { className: "text-[9px] font-medium text-neutral-500", children: label }),
89663
+ return /* @__PURE__ */ jsxs182("div", { className: "space-y-1", children: [
89664
+ /* @__PURE__ */ jsx226("label", { className: "text-[9px] font-medium text-neutral-500", children: label }),
89613
89665
  children
89614
89666
  ] });
89615
89667
  }
@@ -89618,20 +89670,20 @@ function DefaultField({
89618
89670
  onChange
89619
89671
  }) {
89620
89672
  if (draft.type === "boolean") {
89621
- return /* @__PURE__ */ jsxs181(
89673
+ return /* @__PURE__ */ jsxs182(
89622
89674
  "select",
89623
89675
  {
89624
89676
  value: draft.defaultRaw === "true" ? "true" : "false",
89625
89677
  onChange: (e) => onChange(e.target.value),
89626
89678
  className: VARIABLES_INPUT_CLASS,
89627
89679
  children: [
89628
- /* @__PURE__ */ jsx225("option", { value: "false", children: "false" }),
89629
- /* @__PURE__ */ jsx225("option", { value: "true", children: "true" })
89680
+ /* @__PURE__ */ jsx226("option", { value: "false", children: "false" }),
89681
+ /* @__PURE__ */ jsx226("option", { value: "true", children: "true" })
89630
89682
  ]
89631
89683
  }
89632
89684
  );
89633
89685
  }
89634
- return /* @__PURE__ */ jsx225(
89686
+ return /* @__PURE__ */ jsx226(
89635
89687
  "input",
89636
89688
  {
89637
89689
  type: "text",
@@ -89660,9 +89712,9 @@ function DeclarationForm({
89660
89712
  setError(null);
89661
89713
  onSubmit(result);
89662
89714
  };
89663
- return /* @__PURE__ */ jsxs181("div", { className: "space-y-2 rounded-lg border border-neutral-800 bg-neutral-900/60 p-2", children: [
89664
- /* @__PURE__ */ jsxs181("div", { className: "grid grid-cols-2 gap-2", children: [
89665
- /* @__PURE__ */ jsx225(Field, { label: "ID", children: /* @__PURE__ */ jsx225(
89715
+ return /* @__PURE__ */ jsxs182("div", { className: "space-y-2 rounded-lg border border-neutral-800 bg-neutral-900/60 p-2", children: [
89716
+ /* @__PURE__ */ jsxs182("div", { className: "grid grid-cols-2 gap-2", children: [
89717
+ /* @__PURE__ */ jsx226(Field, { label: "ID", children: /* @__PURE__ */ jsx226(
89666
89718
  "input",
89667
89719
  {
89668
89720
  type: "text",
@@ -89673,7 +89725,7 @@ function DeclarationForm({
89673
89725
  className: `${VARIABLES_INPUT_CLASS} font-mono disabled:opacity-50`
89674
89726
  }
89675
89727
  ) }),
89676
- /* @__PURE__ */ jsx225(Field, { label: "Label", children: /* @__PURE__ */ jsx225(
89728
+ /* @__PURE__ */ jsx226(Field, { label: "Label", children: /* @__PURE__ */ jsx226(
89677
89729
  "input",
89678
89730
  {
89679
89731
  type: "text",
@@ -89684,8 +89736,8 @@ function DeclarationForm({
89684
89736
  }
89685
89737
  ) })
89686
89738
  ] }),
89687
- /* @__PURE__ */ jsxs181("div", { className: "grid grid-cols-2 gap-2", children: [
89688
- /* @__PURE__ */ jsx225(Field, { label: "Type", children: /* @__PURE__ */ jsx225(
89739
+ /* @__PURE__ */ jsxs182("div", { className: "grid grid-cols-2 gap-2", children: [
89740
+ /* @__PURE__ */ jsx226(Field, { label: "Type", children: /* @__PURE__ */ jsx226(
89689
89741
  "select",
89690
89742
  {
89691
89743
  value: draft.type,
@@ -89694,12 +89746,12 @@ function DeclarationForm({
89694
89746
  if (type) set({ type });
89695
89747
  },
89696
89748
  className: VARIABLES_INPUT_CLASS,
89697
- children: VARIABLE_TYPES.map((t) => /* @__PURE__ */ jsx225("option", { value: t, children: t }, t))
89749
+ children: VARIABLE_TYPES.map((t) => /* @__PURE__ */ jsx226("option", { value: t, children: t }, t))
89698
89750
  }
89699
89751
  ) }),
89700
- /* @__PURE__ */ jsx225(Field, { label: "Default", children: /* @__PURE__ */ jsx225(DefaultField, { draft, onChange: (defaultRaw) => set({ defaultRaw }) }) })
89752
+ /* @__PURE__ */ jsx226(Field, { label: "Default", children: /* @__PURE__ */ jsx226(DefaultField, { draft, onChange: (defaultRaw) => set({ defaultRaw }) }) })
89701
89753
  ] }),
89702
- draft.type === "number" && /* @__PURE__ */ jsx225("div", { className: "grid grid-cols-3 gap-2", children: ["min", "max", "step"].map((key2) => /* @__PURE__ */ jsx225(Field, { label: key2, children: /* @__PURE__ */ jsx225(
89754
+ draft.type === "number" && /* @__PURE__ */ jsx226("div", { className: "grid grid-cols-3 gap-2", children: ["min", "max", "step"].map((key2) => /* @__PURE__ */ jsx226(Field, { label: key2, children: /* @__PURE__ */ jsx226(
89703
89755
  "input",
89704
89756
  {
89705
89757
  type: "text",
@@ -89708,7 +89760,7 @@ function DeclarationForm({
89708
89760
  className: `${VARIABLES_INPUT_CLASS} tabular-nums`
89709
89761
  }
89710
89762
  ) }, key2)) }),
89711
- draft.type === "enum" && /* @__PURE__ */ jsx225(Field, { label: "Options (one per line, value:Label)", children: /* @__PURE__ */ jsx225(
89763
+ draft.type === "enum" && /* @__PURE__ */ jsx226(Field, { label: "Options (one per line, value:Label)", children: /* @__PURE__ */ jsx226(
89712
89764
  "textarea",
89713
89765
  {
89714
89766
  value: draft.optionsRaw,
@@ -89717,7 +89769,7 @@ function DeclarationForm({
89717
89769
  className: `${VARIABLES_INPUT_CLASS} resize-y font-mono`
89718
89770
  }
89719
89771
  ) }),
89720
- /* @__PURE__ */ jsx225(Field, { label: "Description (optional)", children: /* @__PURE__ */ jsx225(
89772
+ /* @__PURE__ */ jsx226(Field, { label: "Description (optional)", children: /* @__PURE__ */ jsx226(
89721
89773
  "input",
89722
89774
  {
89723
89775
  type: "text",
@@ -89726,9 +89778,9 @@ function DeclarationForm({
89726
89778
  className: VARIABLES_INPUT_CLASS
89727
89779
  }
89728
89780
  ) }),
89729
- error && /* @__PURE__ */ jsx225("p", { className: "text-[10px] text-red-400", children: error }),
89730
- /* @__PURE__ */ jsxs181("div", { className: "flex items-center justify-end gap-2 pt-1", children: [
89731
- /* @__PURE__ */ jsx225(
89781
+ error && /* @__PURE__ */ jsx226("p", { className: "text-[10px] text-red-400", children: error }),
89782
+ /* @__PURE__ */ jsxs182("div", { className: "flex items-center justify-end gap-2 pt-1", children: [
89783
+ /* @__PURE__ */ jsx226(
89732
89784
  "button",
89733
89785
  {
89734
89786
  type: "button",
@@ -89737,7 +89789,7 @@ function DeclarationForm({
89737
89789
  children: "Cancel"
89738
89790
  }
89739
89791
  ),
89740
- /* @__PURE__ */ jsx225(
89792
+ /* @__PURE__ */ jsx226(
89741
89793
  "button",
89742
89794
  {
89743
89795
  type: "button",
@@ -89751,14 +89803,14 @@ function DeclarationForm({
89751
89803
  }
89752
89804
 
89753
89805
  // src/components/panels/VariablesRowAction.tsx
89754
- import { jsx as jsx226 } from "react/jsx-runtime";
89806
+ import { jsx as jsx227 } from "react/jsx-runtime";
89755
89807
  function RowAction({
89756
89808
  label,
89757
89809
  title,
89758
89810
  danger,
89759
89811
  onClick
89760
89812
  }) {
89761
- return /* @__PURE__ */ jsx226(
89813
+ return /* @__PURE__ */ jsx227(
89762
89814
  "button",
89763
89815
  {
89764
89816
  type: "button",
@@ -89771,7 +89823,7 @@ function RowAction({
89771
89823
  }
89772
89824
 
89773
89825
  // src/components/panels/VariablesOtherCompositions.tsx
89774
- import { jsx as jsx227, jsxs as jsxs182 } from "react/jsx-runtime";
89826
+ import { jsx as jsx228, jsxs as jsxs183 } from "react/jsx-runtime";
89775
89827
  function CompositionSection({
89776
89828
  group,
89777
89829
  editingKey,
@@ -89779,8 +89831,8 @@ function CompositionSection({
89779
89831
  onSave,
89780
89832
  onRemove
89781
89833
  }) {
89782
- return /* @__PURE__ */ jsxs182("div", { className: "space-y-1.5", children: [
89783
- /* @__PURE__ */ jsx227(
89834
+ return /* @__PURE__ */ jsxs183("div", { className: "space-y-1.5", children: [
89835
+ /* @__PURE__ */ jsx228(
89784
89836
  "p",
89785
89837
  {
89786
89838
  className: "truncate text-[9px] font-medium uppercase tracking-wider text-neutral-500",
@@ -89791,12 +89843,12 @@ function CompositionSection({
89791
89843
  group.variables.map((decl) => {
89792
89844
  const key2 = `${group.path}::${decl.id}`;
89793
89845
  const editing = editingKey === key2;
89794
- return /* @__PURE__ */ jsxs182("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 p-2", children: [
89795
- /* @__PURE__ */ jsxs182("div", { className: "flex items-center gap-1.5", children: [
89796
- /* @__PURE__ */ jsx227("span", { className: "truncate text-[10px] font-medium text-neutral-300", children: decl.label }),
89797
- /* @__PURE__ */ jsx227("span", { className: "rounded-sm bg-neutral-800 px-1 py-px font-mono text-[8px] text-neutral-500", children: decl.type }),
89798
- /* @__PURE__ */ jsxs182("span", { className: "ml-auto flex items-center gap-1", children: [
89799
- /* @__PURE__ */ jsx227(
89846
+ return /* @__PURE__ */ jsxs183("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 p-2", children: [
89847
+ /* @__PURE__ */ jsxs183("div", { className: "flex items-center gap-1.5", children: [
89848
+ /* @__PURE__ */ jsx228("span", { className: "truncate text-[10px] font-medium text-neutral-300", children: decl.label }),
89849
+ /* @__PURE__ */ jsx228("span", { className: "rounded-sm bg-neutral-800 px-1 py-px font-mono text-[8px] text-neutral-500", children: decl.type }),
89850
+ /* @__PURE__ */ jsxs183("span", { className: "ml-auto flex items-center gap-1", children: [
89851
+ /* @__PURE__ */ jsx228(
89800
89852
  RowAction,
89801
89853
  {
89802
89854
  label: "Edit",
@@ -89804,7 +89856,7 @@ function CompositionSection({
89804
89856
  onClick: () => onToggleEdit(editing ? null : key2)
89805
89857
  }
89806
89858
  ),
89807
- /* @__PURE__ */ jsx227(
89859
+ /* @__PURE__ */ jsx228(
89808
89860
  RowAction,
89809
89861
  {
89810
89862
  label: "\u2715",
@@ -89815,8 +89867,8 @@ function CompositionSection({
89815
89867
  )
89816
89868
  ] })
89817
89869
  ] }),
89818
- decl.description && /* @__PURE__ */ jsx227("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89819
- editing && /* @__PURE__ */ jsx227(
89870
+ decl.description && /* @__PURE__ */ jsx228("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89871
+ editing && /* @__PURE__ */ jsx228(
89820
89872
  DeclarationForm,
89821
89873
  {
89822
89874
  initial: draftFromDeclaration(decl),
@@ -89874,9 +89926,9 @@ function VariablesOtherCompositions({
89874
89926
  [editInFile]
89875
89927
  );
89876
89928
  if (groups.length === 0) return null;
89877
- return /* @__PURE__ */ jsxs182("div", { className: "space-y-3 border-t border-neutral-800 pt-3", children: [
89878
- /* @__PURE__ */ jsx227("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-600", children: "Other compositions" }),
89879
- groups.map((group) => /* @__PURE__ */ jsx227(
89929
+ return /* @__PURE__ */ jsxs183("div", { className: "space-y-3 border-t border-neutral-800 pt-3", children: [
89930
+ /* @__PURE__ */ jsx228("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-600", children: "Other compositions" }),
89931
+ groups.map((group) => /* @__PURE__ */ jsx228(
89880
89932
  CompositionSection,
89881
89933
  {
89882
89934
  group,
@@ -89892,7 +89944,7 @@ function VariablesOtherCompositions({
89892
89944
 
89893
89945
  // src/components/panels/VariablesPanel.tsx
89894
89946
  import { isScalarVariableValue as isScalar } from "@hyperframes/core/variables";
89895
- import { jsx as jsx228, jsxs as jsxs183 } from "react/jsx-runtime";
89947
+ import { jsx as jsx229, jsxs as jsxs184 } from "react/jsx-runtime";
89896
89948
  function shellSingleQuote(value) {
89897
89949
  return `'${value.replace(/'/g, `'\\''`)}'`;
89898
89950
  }
@@ -89908,7 +89960,7 @@ function formatIssue(issue) {
89908
89960
  }
89909
89961
  function ValidationStrip({ issues }) {
89910
89962
  if (issues.length === 0) return null;
89911
- return /* @__PURE__ */ jsx228("div", { className: "space-y-1 rounded-lg border border-red-900/60 bg-red-950/30 p-2", children: issues.map((issue) => /* @__PURE__ */ jsx228("p", { className: "text-[10px] text-red-300", children: formatIssue(issue) }, `${issue.kind}:${issue.variableId}`)) });
89963
+ return /* @__PURE__ */ jsx229("div", { className: "space-y-1 rounded-lg border border-red-900/60 bg-red-950/30 p-2", children: issues.map((issue) => /* @__PURE__ */ jsx229("p", { className: "text-[10px] text-red-300", children: formatIssue(issue) }, `${issue.kind}:${issue.variableId}`)) });
89912
89964
  }
89913
89965
  function VariableRow({
89914
89966
  decl,
@@ -89922,11 +89974,11 @@ function VariableRow({
89922
89974
  onSaveEdit,
89923
89975
  onRemove
89924
89976
  }) {
89925
- return /* @__PURE__ */ jsxs183("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 p-2", children: [
89926
- /* @__PURE__ */ jsxs183("div", { className: "flex items-center gap-1.5", children: [
89927
- /* @__PURE__ */ jsx228("span", { className: "truncate text-[10px] font-medium text-neutral-300", children: decl.label }),
89928
- /* @__PURE__ */ jsx228("span", { className: "rounded-sm bg-neutral-800 px-1 py-px font-mono text-[8px] text-neutral-500", children: decl.type }),
89929
- unused && /* @__PURE__ */ jsx228(
89977
+ return /* @__PURE__ */ jsxs184("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 p-2", children: [
89978
+ /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-1.5", children: [
89979
+ /* @__PURE__ */ jsx229("span", { className: "truncate text-[10px] font-medium text-neutral-300", children: decl.label }),
89980
+ /* @__PURE__ */ jsx229("span", { className: "rounded-sm bg-neutral-800 px-1 py-px font-mono text-[8px] text-neutral-500", children: decl.type }),
89981
+ unused && /* @__PURE__ */ jsx229(
89930
89982
  "span",
89931
89983
  {
89932
89984
  className: "rounded-sm bg-amber-900/40 px-1 py-px text-[8px] text-amber-400",
@@ -89934,9 +89986,9 @@ function VariableRow({
89934
89986
  children: "unused"
89935
89987
  }
89936
89988
  ),
89937
- overridden && /* @__PURE__ */ jsx228("span", { className: "h-1.5 w-1.5 rounded-full bg-studio-accent" }),
89938
- /* @__PURE__ */ jsxs183("span", { className: "ml-auto flex items-center gap-1", children: [
89939
- overridden && isScalar(value) && /* @__PURE__ */ jsx228(
89989
+ overridden && /* @__PURE__ */ jsx229("span", { className: "h-1.5 w-1.5 rounded-full bg-studio-accent" }),
89990
+ /* @__PURE__ */ jsxs184("span", { className: "ml-auto flex items-center gap-1", children: [
89991
+ overridden && isScalar(value) && /* @__PURE__ */ jsx229(
89940
89992
  RowAction,
89941
89993
  {
89942
89994
  label: "Set default",
@@ -89944,12 +89996,12 @@ function VariableRow({
89944
89996
  onClick: () => onSetDefault(value)
89945
89997
  }
89946
89998
  ),
89947
- /* @__PURE__ */ jsx228(RowAction, { label: "Edit", title: "Edit declaration", onClick: onToggleEdit }),
89948
- /* @__PURE__ */ jsx228(RowAction, { label: "\u2715", title: "Remove declaration", danger: true, onClick: onRemove })
89999
+ /* @__PURE__ */ jsx229(RowAction, { label: "Edit", title: "Edit declaration", onClick: onToggleEdit }),
90000
+ /* @__PURE__ */ jsx229(RowAction, { label: "\u2715", title: "Remove declaration", danger: true, onClick: onRemove })
89949
90001
  ] })
89950
90002
  ] }),
89951
- decl.description && /* @__PURE__ */ jsx228("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89952
- editing ? /* @__PURE__ */ jsx228(
90003
+ decl.description && /* @__PURE__ */ jsx229("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
90004
+ editing ? /* @__PURE__ */ jsx229(
89953
90005
  DeclarationForm,
89954
90006
  {
89955
90007
  initial: draftFromDeclaration(decl),
@@ -89957,7 +90009,7 @@ function VariableRow({
89957
90009
  onSubmit: (edited) => onSaveEdit(mergeDeclarationEdit(decl, edited)),
89958
90010
  onCancel: onToggleEdit
89959
90011
  }
89960
- ) : /* @__PURE__ */ jsx228(PreviewValueControl, { decl, value, onCommit: onCommitPreview })
90012
+ ) : /* @__PURE__ */ jsx229(PreviewValueControl, { decl, value, onCommit: onCommitPreview })
89961
90013
  ] });
89962
90014
  }
89963
90015
  function UndeclaredReads({
@@ -89965,11 +90017,11 @@ function UndeclaredReads({
89965
90017
  onDeclare
89966
90018
  }) {
89967
90019
  if (!usage || usage.undeclaredReads.length === 0) return null;
89968
- return /* @__PURE__ */ jsxs183("div", { className: "space-y-1 rounded-lg border border-neutral-800/70 bg-neutral-900/40 p-2", children: [
89969
- /* @__PURE__ */ jsx228("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-500", children: "Read by scripts, not declared" }),
89970
- usage.undeclaredReads.map((id) => /* @__PURE__ */ jsxs183("div", { className: "flex items-center gap-2", children: [
89971
- /* @__PURE__ */ jsx228("code", { className: "font-mono text-[10px] text-neutral-400", children: id }),
89972
- /* @__PURE__ */ jsx228(
90020
+ return /* @__PURE__ */ jsxs184("div", { className: "space-y-1 rounded-lg border border-neutral-800/70 bg-neutral-900/40 p-2", children: [
90021
+ /* @__PURE__ */ jsx229("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-500", children: "Read by scripts, not declared" }),
90022
+ usage.undeclaredReads.map((id) => /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-2", children: [
90023
+ /* @__PURE__ */ jsx229("code", { className: "font-mono text-[10px] text-neutral-400", children: id }),
90024
+ /* @__PURE__ */ jsx229(
89973
90025
  RowAction,
89974
90026
  {
89975
90027
  label: "Declare",
@@ -89985,10 +90037,10 @@ function PreviewModeHeader({
89985
90037
  onReset
89986
90038
  }) {
89987
90039
  const hasOverrides = overrideCount > 0;
89988
- return /* @__PURE__ */ jsxs183("div", { className: "flex items-center justify-between border-b border-neutral-800 px-3 py-2", children: [
89989
- /* @__PURE__ */ jsxs183("div", { className: "flex items-center gap-2", children: [
89990
- /* @__PURE__ */ jsx228("span", { className: "text-[11px] font-semibold text-neutral-200", children: "Variables" }),
89991
- /* @__PURE__ */ jsx228(
90040
+ return /* @__PURE__ */ jsxs184("div", { className: "flex items-center justify-between border-b border-neutral-800 px-3 py-2", children: [
90041
+ /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-2", children: [
90042
+ /* @__PURE__ */ jsx229("span", { className: "text-[11px] font-semibold text-neutral-200", children: "Variables" }),
90043
+ /* @__PURE__ */ jsx229(
89992
90044
  "span",
89993
90045
  {
89994
90046
  className: `rounded-full px-2 py-0.5 text-[9px] font-medium ${hasOverrides ? "bg-studio-accent/20 text-studio-accent" : "bg-neutral-800 text-neutral-500"}`,
@@ -89996,7 +90048,7 @@ function PreviewModeHeader({
89996
90048
  }
89997
90049
  )
89998
90050
  ] }),
89999
- hasOverrides && /* @__PURE__ */ jsx228(
90051
+ hasOverrides && /* @__PURE__ */ jsx229(
90000
90052
  "button",
90001
90053
  {
90002
90054
  type: "button",
@@ -90014,11 +90066,11 @@ function HandoffFooter({
90014
90066
  }) {
90015
90067
  const json = JSON.stringify(effectiveValues);
90016
90068
  const command = `npx hyperframes render ${shellSingleQuote(compPath)} --variables ${shellSingleQuote(json)}`;
90017
- return /* @__PURE__ */ jsxs183("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 bg-neutral-900/40 p-2", children: [
90018
- /* @__PURE__ */ jsx228("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-500", children: "Use this template" }),
90019
- /* @__PURE__ */ jsx228("code", { className: "block truncate font-mono text-[9px] text-neutral-500", title: command, children: command }),
90020
- /* @__PURE__ */ jsxs183("div", { className: "flex items-center gap-2", children: [
90021
- /* @__PURE__ */ jsx228(
90069
+ return /* @__PURE__ */ jsxs184("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 bg-neutral-900/40 p-2", children: [
90070
+ /* @__PURE__ */ jsx229("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-500", children: "Use this template" }),
90071
+ /* @__PURE__ */ jsx229("code", { className: "block truncate font-mono text-[9px] text-neutral-500", title: command, children: command }),
90072
+ /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-2", children: [
90073
+ /* @__PURE__ */ jsx229(
90022
90074
  RowAction,
90023
90075
  {
90024
90076
  label: "Copy render command",
@@ -90026,7 +90078,7 @@ function HandoffFooter({
90026
90078
  onClick: () => onCopy(command, "Render command")
90027
90079
  }
90028
90080
  ),
90029
- /* @__PURE__ */ jsx228(
90081
+ /* @__PURE__ */ jsx229(
90030
90082
  RowAction,
90031
90083
  {
90032
90084
  label: "Copy values JSON",
@@ -90037,15 +90089,15 @@ function HandoffFooter({
90037
90089
  ] })
90038
90090
  ] });
90039
90091
  }
90040
- var EMPTY_STATE = /* @__PURE__ */ jsxs183("p", { className: "text-[10px] leading-relaxed text-neutral-500", children: [
90092
+ var EMPTY_STATE = /* @__PURE__ */ jsxs184("p", { className: "text-[10px] leading-relaxed text-neutral-500", children: [
90041
90093
  "No variables declared. Variables make parts of this composition dynamic \u2014 declare them here (or in ",
90042
- /* @__PURE__ */ jsx228("code", { className: "font-mono", children: "data-composition-variables" }),
90094
+ /* @__PURE__ */ jsx229("code", { className: "font-mono", children: "data-composition-variables" }),
90043
90095
  "), read them with",
90044
90096
  " ",
90045
- /* @__PURE__ */ jsx228("code", { className: "font-mono", children: "getVariables()" }),
90097
+ /* @__PURE__ */ jsx229("code", { className: "font-mono", children: "getVariables()" }),
90046
90098
  ", and pass values at render time with",
90047
90099
  " ",
90048
- /* @__PURE__ */ jsx228("code", { className: "font-mono", children: "--variables" }),
90100
+ /* @__PURE__ */ jsx229("code", { className: "font-mono", children: "--variables" }),
90049
90101
  "."
90050
90102
  ] });
90051
90103
  var VariablesPanel = memo52(function VariablesPanel2({
@@ -90229,18 +90281,18 @@ var VariablesPanel = memo52(function VariablesPanel2({
90229
90281
  );
90230
90282
  const bindableSelection = domEditSelection?.hfId && domEditSelection.sourceFile === (activeCompPath ?? "index.html") ? domEditSelection : null;
90231
90283
  if (!sdkSession) {
90232
- return /* @__PURE__ */ jsx228("div", { className: "flex h-full items-center justify-center px-6 text-center", children: /* @__PURE__ */ jsx228("p", { className: "text-xs text-neutral-500", children: "Open a composition to manage its variables." }) });
90284
+ return /* @__PURE__ */ jsx229("div", { className: "flex h-full items-center justify-center px-6 text-center", children: /* @__PURE__ */ jsx229("p", { className: "text-xs text-neutral-500", children: "Open a composition to manage its variables." }) });
90233
90285
  }
90234
- return /* @__PURE__ */ jsxs183("div", { className: "flex h-full flex-col", children: [
90235
- /* @__PURE__ */ jsx228(
90286
+ return /* @__PURE__ */ jsxs184("div", { className: "flex h-full flex-col", children: [
90287
+ /* @__PURE__ */ jsx229(
90236
90288
  PreviewModeHeader,
90237
90289
  {
90238
90290
  overrideCount: previewValues ? Object.keys(previewValues).length : 0,
90239
90291
  onReset: resetPreview
90240
90292
  }
90241
90293
  ),
90242
- /* @__PURE__ */ jsxs183("div", { className: "flex-1 space-y-3 overflow-y-auto p-3", children: [
90243
- bindableSelection && /* @__PURE__ */ jsx228(
90294
+ /* @__PURE__ */ jsxs184("div", { className: "flex-1 space-y-3 overflow-y-auto p-3", children: [
90295
+ bindableSelection && /* @__PURE__ */ jsx229(
90244
90296
  VariablesBindElement,
90245
90297
  {
90246
90298
  selection: bindableSelection,
@@ -90249,9 +90301,9 @@ var VariablesPanel = memo52(function VariablesPanel2({
90249
90301
  },
90250
90302
  bindableSelection.hfId
90251
90303
  ),
90252
- /* @__PURE__ */ jsx228(ValidationStrip, { issues }),
90304
+ /* @__PURE__ */ jsx229(ValidationStrip, { issues }),
90253
90305
  declarations.length === 0 && !addOpen && EMPTY_STATE,
90254
- declarations.map((decl) => /* @__PURE__ */ jsx228(
90306
+ declarations.map((decl) => /* @__PURE__ */ jsx229(
90255
90307
  VariableRow,
90256
90308
  {
90257
90309
  decl,
@@ -90267,15 +90319,15 @@ var VariablesPanel = memo52(function VariablesPanel2({
90267
90319
  },
90268
90320
  decl.id
90269
90321
  )),
90270
- /* @__PURE__ */ jsx228(
90322
+ /* @__PURE__ */ jsx229(
90271
90323
  UndeclaredReads,
90272
90324
  {
90273
90325
  usage,
90274
90326
  onDeclare: (id) => handleAdd({ id, type: "string", label: id, default: "" })
90275
90327
  }
90276
90328
  ),
90277
- usage?.scanIncomplete && /* @__PURE__ */ jsx228("p", { className: "text-[9px] text-neutral-600", children: "Scripts access variables dynamically \u2014 usage info may be incomplete." }),
90278
- declarations.length > 0 && /* @__PURE__ */ jsx228(
90329
+ usage?.scanIncomplete && /* @__PURE__ */ jsx229("p", { className: "text-[9px] text-neutral-600", children: "Scripts access variables dynamically \u2014 usage info may be incomplete." }),
90330
+ declarations.length > 0 && /* @__PURE__ */ jsx229(
90279
90331
  HandoffFooter,
90280
90332
  {
90281
90333
  effectiveValues,
@@ -90283,7 +90335,7 @@ var VariablesPanel = memo52(function VariablesPanel2({
90283
90335
  onCopy: copyToClipboard
90284
90336
  }
90285
90337
  ),
90286
- addOpen ? /* @__PURE__ */ jsx228(
90338
+ addOpen ? /* @__PURE__ */ jsx229(
90287
90339
  DeclarationForm,
90288
90340
  {
90289
90341
  initial: EMPTY_DRAFT,
@@ -90291,7 +90343,7 @@ var VariablesPanel = memo52(function VariablesPanel2({
90291
90343
  onSubmit: handleAdd,
90292
90344
  onCancel: () => setAddOpen(false)
90293
90345
  }
90294
- ) : /* @__PURE__ */ jsx228(
90346
+ ) : /* @__PURE__ */ jsx229(
90295
90347
  "button",
90296
90348
  {
90297
90349
  type: "button",
@@ -90300,7 +90352,7 @@ var VariablesPanel = memo52(function VariablesPanel2({
90300
90352
  children: "+ Add variable"
90301
90353
  }
90302
90354
  ),
90303
- /* @__PURE__ */ jsx228(
90355
+ /* @__PURE__ */ jsx229(
90304
90356
  VariablesOtherCompositions,
90305
90357
  {
90306
90358
  fileTree,
@@ -90433,7 +90485,7 @@ function useSlideshowTabState(params) {
90433
90485
 
90434
90486
  // src/components/DesignPanelPromoteProvider.tsx
90435
90487
  import { useCallback as useCallback172 } from "react";
90436
- import { jsx as jsx229 } from "react/jsx-runtime";
90488
+ import { jsx as jsx230 } from "react/jsx-runtime";
90437
90489
  function DesignPanelPromoteProvider({
90438
90490
  selection,
90439
90491
  projectId,
@@ -90463,7 +90515,7 @@ function DesignPanelPromoteProvider({
90463
90515
  (error) => showToast(getStudioSaveErrorMessage(error), "error"),
90464
90516
  [showToast]
90465
90517
  );
90466
- return /* @__PURE__ */ jsx229(
90518
+ return /* @__PURE__ */ jsx230(
90467
90519
  VariablePromoteProvider,
90468
90520
  {
90469
90521
  session: handle.session,
@@ -90740,7 +90792,7 @@ function useRemoveBackground(projectId, refreshFileTree, showToast) {
90740
90792
  }
90741
90793
 
90742
90794
  // src/components/StudioRightPanels.tsx
90743
- import { Fragment as Fragment60, jsx as jsx230, jsxs as jsxs184 } from "react/jsx-runtime";
90795
+ import { Fragment as Fragment60, jsx as jsx231, jsxs as jsxs185 } from "react/jsx-runtime";
90744
90796
  function StudioRightPanels({
90745
90797
  activeBlockParams,
90746
90798
  onCloseBlockParams,
@@ -90903,7 +90955,7 @@ function StudioRightPanels({
90903
90955
  const keys = timelineKeysForSelections(domEditGroupSelections, elements, activeCompPath);
90904
90956
  if (keys.length > 0) void onToggleElementHidden?.(keys, true);
90905
90957
  };
90906
- const propertyPanel = /* @__PURE__ */ jsx230(
90958
+ const propertyPanel = /* @__PURE__ */ jsx231(
90907
90959
  DesignPanelPromoteProvider,
90908
90960
  {
90909
90961
  selection: domEditGroupSelections.length > 1 ? null : domEditSelection,
@@ -90915,7 +90967,7 @@ function StudioRightPanels({
90915
90967
  recordEdit,
90916
90968
  reloadPreview,
90917
90969
  forceReloadSharedSdkSession: forceReloadSdkSession,
90918
- children: /* @__PURE__ */ jsx230(
90970
+ children: /* @__PURE__ */ jsx231(
90919
90971
  PropertyPanel,
90920
90972
  {
90921
90973
  projectId,
@@ -90985,9 +91037,9 @@ function StudioRightPanels({
90985
91037
  );
90986
91038
  let designBody = propertyPanel;
90987
91039
  if (captionEditMode) {
90988
- designBody = /* @__PURE__ */ jsx230(CaptionPropertyPanel, { iframeRef: previewIframeRef });
91040
+ designBody = /* @__PURE__ */ jsx231(CaptionPropertyPanel, { iframeRef: previewIframeRef });
90989
91041
  } else if (activeBlockParams) {
90990
- designBody = /* @__PURE__ */ jsx230(
91042
+ designBody = /* @__PURE__ */ jsx231(
90991
91043
  BlockParamsPanel,
90992
91044
  {
90993
91045
  blockName: activeBlockParams.blockName,
@@ -90999,18 +91051,18 @@ function StudioRightPanels({
90999
91051
  }
91000
91052
  );
91001
91053
  }
91002
- return /* @__PURE__ */ jsxs184(Fragment60, { children: [
91003
- /* @__PURE__ */ jsx230(Dock.Panel, { id: "design", children: designBody }),
91004
- /* @__PURE__ */ jsx230(Dock.Panel, { id: "layers", children: /* @__PURE__ */ jsx230(LayersPanel, {}) }),
91005
- /* @__PURE__ */ jsx230(
91054
+ return /* @__PURE__ */ jsxs185(Fragment60, { children: [
91055
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "design", children: designBody }),
91056
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "layers", children: /* @__PURE__ */ jsx231(LayersPanel, {}) }),
91057
+ /* @__PURE__ */ jsx231(
91006
91058
  Dock.Panel,
91007
91059
  {
91008
91060
  id: "renders",
91009
91061
  title: renderJobs.length > 0 ? `Renders (${renderJobs.length})` : void 0,
91010
- children: /* @__PURE__ */ jsx230(RenderQueuePanel, {})
91062
+ children: /* @__PURE__ */ jsx231(RenderQueuePanel, {})
91011
91063
  }
91012
91064
  ),
91013
- /* @__PURE__ */ jsx230(Dock.Panel, { id: "variables", children: /* @__PURE__ */ jsx230(
91065
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "variables", children: /* @__PURE__ */ jsx231(
91014
91066
  VariablesPanel,
91015
91067
  {
91016
91068
  sdkSession,
@@ -91019,7 +91071,7 @@ function StudioRightPanels({
91019
91071
  recordEdit
91020
91072
  }
91021
91073
  ) }),
91022
- /* @__PURE__ */ jsx230(Dock.Panel, { id: "slideshow", children: /* @__PURE__ */ jsx230(
91074
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "slideshow", children: /* @__PURE__ */ jsx231(
91023
91075
  SlideshowPanel,
91024
91076
  {
91025
91077
  scenes: slideshowScenes,
@@ -91446,9 +91498,9 @@ function useKeyframeKeyboard({
91446
91498
  }
91447
91499
 
91448
91500
  // src/components/icons/AudioMetersIcon.tsx
91449
- import { jsx as jsx231 } from "react/jsx-runtime";
91501
+ import { jsx as jsx232 } from "react/jsx-runtime";
91450
91502
  function AudioMetersIcon({ size = 16 }) {
91451
- return /* @__PURE__ */ jsx231(
91503
+ return /* @__PURE__ */ jsx232(
91452
91504
  "svg",
91453
91505
  {
91454
91506
  width: size,
@@ -91459,15 +91511,15 @@ function AudioMetersIcon({ size = 16 }) {
91459
91511
  strokeWidth: 1.5,
91460
91512
  strokeLinecap: "round",
91461
91513
  "aria-hidden": "true",
91462
- children: /* @__PURE__ */ jsx231("path", { d: "M2.5 13h2m-2-3h2M7 13h2m-2-3h2m-2-3h2m-2-3h2M11.5 13h2m-2-3h2m-2-3h2" })
91514
+ children: /* @__PURE__ */ jsx232("path", { d: "M2.5 13h2m-2-3h2M7 13h2m-2-3h2m-2-3h2m-2-3h2M11.5 13h2m-2-3h2m-2-3h2" })
91463
91515
  }
91464
91516
  );
91465
91517
  }
91466
91518
 
91467
91519
  // src/components/icons/RippleEditIcon.tsx
91468
- import { jsx as jsx232, jsxs as jsxs185 } from "react/jsx-runtime";
91520
+ import { jsx as jsx233, jsxs as jsxs186 } from "react/jsx-runtime";
91469
91521
  function RippleEditIcon({ size = 16 }) {
91470
- return /* @__PURE__ */ jsxs185(
91522
+ return /* @__PURE__ */ jsxs186(
91471
91523
  "svg",
91472
91524
  {
91473
91525
  width: size,
@@ -91480,9 +91532,9 @@ function RippleEditIcon({ size = 16 }) {
91480
91532
  strokeLinejoin: "round",
91481
91533
  "aria-hidden": "true",
91482
91534
  children: [
91483
- /* @__PURE__ */ jsx232("rect", { x: "1.5", y: "8", width: "4", height: "5", rx: "0.5" }),
91484
- /* @__PURE__ */ jsx232("rect", { x: "10.5", y: "8", width: "4", height: "5", rx: "0.5" }),
91485
- /* @__PURE__ */ jsx232("path", { d: "M13 4H6m2-2L6 4l2 2" })
91535
+ /* @__PURE__ */ jsx233("rect", { x: "1.5", y: "8", width: "4", height: "5", rx: "0.5" }),
91536
+ /* @__PURE__ */ jsx233("rect", { x: "10.5", y: "8", width: "4", height: "5", rx: "0.5" }),
91537
+ /* @__PURE__ */ jsx233("path", { d: "M13 4H6m2-2L6 4l2 2" })
91486
91538
  ]
91487
91539
  }
91488
91540
  );
@@ -91495,10 +91547,10 @@ var flatActive = `${flatBtn} bg-white/8 text-neutral-100 active:scale-[0.98]`;
91495
91547
  var flatDisabled = `${flatBtn} text-neutral-700 cursor-not-allowed`;
91496
91548
 
91497
91549
  // src/components/TimelineHistoryButtons.tsx
91498
- import { Fragment as Fragment61, jsx as jsx233, jsxs as jsxs186 } from "react/jsx-runtime";
91550
+ import { Fragment as Fragment61, jsx as jsx234, jsxs as jsxs187 } from "react/jsx-runtime";
91499
91551
  function HistoryButton({ action, enabled, label, onClick }) {
91500
91552
  const Icon = action === "undo" ? RotateCcw : RotateCw;
91501
- return /* @__PURE__ */ jsx233(Tooltip, { label: historyTooltipLabel(action, label), children: /* @__PURE__ */ jsx233(
91553
+ return /* @__PURE__ */ jsx234(Tooltip, { label: historyTooltipLabel(action, label), children: /* @__PURE__ */ jsx234(
91502
91554
  "button",
91503
91555
  {
91504
91556
  type: "button",
@@ -91509,14 +91561,14 @@ function HistoryButton({ action, enabled, label, onClick }) {
91509
91561
  trackStudioEvent("toolbar_action", { action });
91510
91562
  void onClick();
91511
91563
  },
91512
- children: /* @__PURE__ */ jsx233(Icon, { size: 16 })
91564
+ children: /* @__PURE__ */ jsx234(Icon, { size: 16 })
91513
91565
  }
91514
91566
  ) });
91515
91567
  }
91516
91568
  function TimelineHistoryButtons() {
91517
91569
  const { editHistory, handleUndo, handleRedo } = useStudioShellContext();
91518
- return /* @__PURE__ */ jsxs186(Fragment61, { children: [
91519
- /* @__PURE__ */ jsx233(
91570
+ return /* @__PURE__ */ jsxs187(Fragment61, { children: [
91571
+ /* @__PURE__ */ jsx234(
91520
91572
  HistoryButton,
91521
91573
  {
91522
91574
  action: "undo",
@@ -91525,7 +91577,7 @@ function TimelineHistoryButtons() {
91525
91577
  onClick: handleUndo
91526
91578
  }
91527
91579
  ),
91528
- /* @__PURE__ */ jsx233(
91580
+ /* @__PURE__ */ jsx234(
91529
91581
  HistoryButton,
91530
91582
  {
91531
91583
  action: "redo",
@@ -91538,7 +91590,7 @@ function TimelineHistoryButtons() {
91538
91590
  }
91539
91591
 
91540
91592
  // src/components/TimelineToolbar.tsx
91541
- import { jsx as jsx234, jsxs as jsxs187 } from "react/jsx-runtime";
91593
+ import { jsx as jsx235, jsxs as jsxs188 } from "react/jsx-runtime";
91542
91594
  var NO_KEYFRAME_TOGGLE = {
91543
91595
  state: "none",
91544
91596
  isMotionPath: false,
@@ -91647,10 +91699,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91647
91699
  return (
91648
91700
  // The "TIMELINE" label is dropped for CapCut-like density — the pane's
91649
91701
  // position (tracks right below) makes it self-evident.
91650
- /* @__PURE__ */ jsx234("div", { className: "border-b border-neutral-800/60", children: /* @__PURE__ */ jsxs187("div", { className: "flex items-center justify-between px-2 py-0.5", children: [
91651
- /* @__PURE__ */ jsxs187("div", { className: "flex items-center gap-0.5", children: [
91652
- /* @__PURE__ */ jsx234(TimelineHistoryButtons, {}),
91653
- /* @__PURE__ */ jsx234(Tooltip, { label: "Selection tool (V)", children: /* @__PURE__ */ jsx234(
91702
+ /* @__PURE__ */ jsx235("div", { className: "border-b border-neutral-800/60", children: /* @__PURE__ */ jsxs188("div", { className: "flex items-center justify-between px-2 py-0.5", children: [
91703
+ /* @__PURE__ */ jsxs188("div", { className: "flex items-center gap-0.5", children: [
91704
+ /* @__PURE__ */ jsx235(TimelineHistoryButtons, {}),
91705
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Selection tool (V)", children: /* @__PURE__ */ jsx235(
91654
91706
  "button",
91655
91707
  {
91656
91708
  type: "button",
@@ -91658,10 +91710,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91658
91710
  "aria-label": "Selection tool",
91659
91711
  "aria-pressed": activeTool === "select",
91660
91712
  className: activeTool === "select" ? flatActive : flatIdle,
91661
- children: /* @__PURE__ */ jsx234("svg", { width: "16", height: "16", viewBox: "0 0 12 12", fill: "currentColor", children: /* @__PURE__ */ jsx234("path", { d: "M2 0.5L10 6L6.5 6.5L8.5 11L6.5 11.5L4.5 7L2 9Z" }) })
91713
+ children: /* @__PURE__ */ jsx235("svg", { width: "16", height: "16", viewBox: "0 0 12 12", fill: "currentColor", children: /* @__PURE__ */ jsx235("path", { d: "M2 0.5L10 6L6.5 6.5L8.5 11L6.5 11.5L4.5 7L2 9Z" }) })
91662
91714
  }
91663
91715
  ) }),
91664
- /* @__PURE__ */ jsx234(Tooltip, { label: "Razor tool (B) \u2014 Shift+click splits all tracks", children: /* @__PURE__ */ jsx234(
91716
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Razor tool (B) \u2014 Shift+click splits all tracks", children: /* @__PURE__ */ jsx235(
91665
91717
  "button",
91666
91718
  {
91667
91719
  type: "button",
@@ -91669,11 +91721,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91669
91721
  "aria-label": "Razor tool",
91670
91722
  "aria-pressed": activeTool === "razor",
91671
91723
  className: activeTool === "razor" ? flatActive : flatIdle,
91672
- children: /* @__PURE__ */ jsx234(Scissors, { size: 16 })
91724
+ children: /* @__PURE__ */ jsx235(Scissors, { size: 16 })
91673
91725
  }
91674
91726
  ) }),
91675
- /* @__PURE__ */ jsx234("div", { "aria-hidden": "true", className: "mx-1 h-4 w-px bg-neutral-800" }),
91676
- /* @__PURE__ */ jsx234(Tooltip, { label: timelineSnapEnabled ? "Snapping on (N)" : "Snapping off (N)", children: /* @__PURE__ */ jsx234(
91727
+ /* @__PURE__ */ jsx235("div", { "aria-hidden": "true", className: "mx-1 h-4 w-px bg-neutral-800" }),
91728
+ /* @__PURE__ */ jsx235(Tooltip, { label: timelineSnapEnabled ? "Snapping on (N)" : "Snapping off (N)", children: /* @__PURE__ */ jsx235(
91677
91729
  "button",
91678
91730
  {
91679
91731
  type: "button",
@@ -91681,14 +91733,14 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91681
91733
  "aria-label": "Toggle timeline snapping",
91682
91734
  "aria-pressed": timelineSnapEnabled,
91683
91735
  className: timelineSnapEnabled ? flatActive : flatIdle,
91684
- children: /* @__PURE__ */ jsx234(Magnet, { size: 16, weight: "bold", "aria-hidden": "true" })
91736
+ children: /* @__PURE__ */ jsx235(Magnet, { size: 16, weight: "bold", "aria-hidden": "true" })
91685
91737
  }
91686
91738
  ) }),
91687
- /* @__PURE__ */ jsx234(
91739
+ /* @__PURE__ */ jsx235(
91688
91740
  Tooltip,
91689
91741
  {
91690
91742
  label: rippleEditEnabled ? "Ripple on \u2014 keeps the main track gapless" : "Ripple off \u2014 deleting a main-track clip leaves a gap",
91691
- children: /* @__PURE__ */ jsx234(
91743
+ children: /* @__PURE__ */ jsx235(
91692
91744
  "button",
91693
91745
  {
91694
91746
  type: "button",
@@ -91696,12 +91748,12 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91696
91748
  "aria-label": "Toggle ripple edit",
91697
91749
  "aria-pressed": rippleEditEnabled,
91698
91750
  className: rippleEditEnabled ? flatActive : flatIdle,
91699
- children: /* @__PURE__ */ jsx234(RippleEditIcon, { size: 16 })
91751
+ children: /* @__PURE__ */ jsx235(RippleEditIcon, { size: 16 })
91700
91752
  }
91701
91753
  )
91702
91754
  }
91703
91755
  ),
91704
- projectHasAudio && /* @__PURE__ */ jsx234(Tooltip, { label: audioMetersVisible ? "Hide audio meters" : "Show audio meters", children: /* @__PURE__ */ jsx234(
91756
+ projectHasAudio && /* @__PURE__ */ jsx235(Tooltip, { label: audioMetersVisible ? "Hide audio meters" : "Show audio meters", children: /* @__PURE__ */ jsx235(
91705
91757
  "button",
91706
91758
  {
91707
91759
  type: "button",
@@ -91709,14 +91761,14 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91709
91761
  "aria-label": "Toggle audio meters",
91710
91762
  "aria-pressed": audioMetersVisible,
91711
91763
  className: audioMetersVisible ? flatActive : flatIdle,
91712
- children: /* @__PURE__ */ jsx234(AudioMetersIcon, { size: 16 })
91764
+ children: /* @__PURE__ */ jsx235(AudioMetersIcon, { size: 16 })
91713
91765
  }
91714
91766
  ) }),
91715
- /* @__PURE__ */ jsx234(
91767
+ /* @__PURE__ */ jsx235(
91716
91768
  Tooltip,
91717
91769
  {
91718
91770
  label: keyframePathEndpoint ? "Motion path endpoints cannot be removed" : !onToggleKeyframe ? "Select an animated element to add keyframes" : keyframeIsMotionPath ? keyframeWillExtend ? "Extend motion path to playhead (K)" : keyframeState === "active" ? "Remove waypoint from motion path (K)" : "Add waypoint to motion path (K)" : keyframeState === "active" ? "Remove keyframe at playhead (K)" : keyframeState === "inactive" ? keyframeWillExtend ? "Add keyframe at playhead, extends animation (K)" : "Add keyframe at playhead (K)" : "Add keyframe (K)",
91719
- children: /* @__PURE__ */ jsx234(
91771
+ children: /* @__PURE__ */ jsx235(
91720
91772
  "button",
91721
91773
  {
91722
91774
  type: "button",
@@ -91724,7 +91776,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91724
91776
  onClick: onToggleKeyframe,
91725
91777
  "aria-label": keyframePathEndpoint ? "Motion path endpoint" : keyframeIsMotionPath ? keyframeState === "active" ? "Remove motion path waypoint" : keyframeWillExtend ? "Extend motion path to playhead" : "Add motion path waypoint" : keyframeState === "active" ? "Remove keyframe at playhead" : "Add keyframe at playhead",
91726
91778
  className: !onToggleKeyframe ? flatDisabled : `${flatBtn} active:scale-[0.98] hover:bg-white/6 ${keyframeState === "active" ? "text-studio-accent" : keyframeState === "inactive" ? "text-neutral-400 hover:text-studio-accent" : "text-neutral-600 hover:text-neutral-400"}`,
91727
- children: /* @__PURE__ */ jsx234("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "currentColor", children: keyframeState === "active" ? /* @__PURE__ */ jsx234("path", { d: "M5 0.5L9.5 5L5 9.5L0.5 5Z" }) : /* @__PURE__ */ jsx234(
91779
+ children: /* @__PURE__ */ jsx235("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "currentColor", children: keyframeState === "active" ? /* @__PURE__ */ jsx235("path", { d: "M5 0.5L9.5 5L5 9.5L0.5 5Z" }) : /* @__PURE__ */ jsx235(
91728
91780
  "path",
91729
91781
  {
91730
91782
  d: "M5 1.2L8.8 5L5 8.8L1.2 5Z",
@@ -91737,11 +91789,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91737
91789
  )
91738
91790
  }
91739
91791
  ),
91740
- /* @__PURE__ */ jsx234(
91792
+ /* @__PURE__ */ jsx235(
91741
91793
  Tooltip,
91742
91794
  {
91743
91795
  label: autoKeyframeEnabled ? "Auto-record manual edits as keyframes (click to turn off)" : "Manual edits will not be recorded as keyframes (click to turn on)",
91744
- children: /* @__PURE__ */ jsx234(
91796
+ children: /* @__PURE__ */ jsx235(
91745
91797
  "button",
91746
91798
  {
91747
91799
  type: "button",
@@ -91749,9 +91801,9 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91749
91801
  "aria-label": "Auto-record manual edits as keyframes",
91750
91802
  "aria-pressed": autoKeyframeEnabled,
91751
91803
  className: `${flatBtn} active:scale-[0.98] hover:bg-white/6 ${autoKeyframeEnabled ? "text-red-400 hover:text-red-300" : "text-neutral-600 hover:text-neutral-400"}`,
91752
- children: /* @__PURE__ */ jsxs187("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "none", children: [
91753
- /* @__PURE__ */ jsx234("path", { d: "M5 0.7L9.3 5L5 9.3L0.7 5Z", stroke: "currentColor", strokeWidth: "1" }),
91754
- /* @__PURE__ */ jsx234(
91804
+ children: /* @__PURE__ */ jsxs188("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "none", children: [
91805
+ /* @__PURE__ */ jsx235("path", { d: "M5 0.7L9.3 5L5 9.3L0.7 5Z", stroke: "currentColor", strokeWidth: "1" }),
91806
+ /* @__PURE__ */ jsx235(
91755
91807
  "circle",
91756
91808
  {
91757
91809
  cx: "5",
@@ -91771,11 +91823,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91771
91823
  const el = selectedElementId ? elements.find((e) => (e.key ?? e.id) === selectedElementId) : null;
91772
91824
  const splittable = el != null && canSplitElement(el);
91773
91825
  const canSplit = splittable && currentTime > el.start && currentTime < el.start + el.duration;
91774
- return /* @__PURE__ */ jsx234(
91826
+ return /* @__PURE__ */ jsx235(
91775
91827
  Tooltip,
91776
91828
  {
91777
91829
  label: canSplit ? "Split at playhead (S)" : splittable ? "Move the playhead inside the clip to split" : "Select a clip to split",
91778
- children: /* @__PURE__ */ jsx234(
91830
+ children: /* @__PURE__ */ jsx235(
91779
91831
  "button",
91780
91832
  {
91781
91833
  type: "button",
@@ -91785,7 +91837,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91785
91837
  if (canSplit && el) onSplitElement(el, currentTime);
91786
91838
  },
91787
91839
  className: canSplit ? flatIdle : flatDisabled,
91788
- children: /* @__PURE__ */ jsxs187(
91840
+ children: /* @__PURE__ */ jsxs188(
91789
91841
  "svg",
91790
91842
  {
91791
91843
  width: "16",
@@ -91798,8 +91850,8 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91798
91850
  strokeLinejoin: "round",
91799
91851
  "aria-hidden": "true",
91800
91852
  children: [
91801
- /* @__PURE__ */ jsx234("path", { d: "M5 3 L7 3 L7 13 L5 13" }),
91802
- /* @__PURE__ */ jsx234("path", { d: "M11 3 L9 3 L9 13 L11 13" })
91853
+ /* @__PURE__ */ jsx235("path", { d: "M5 3 L7 3 L7 13 L5 13" }),
91854
+ /* @__PURE__ */ jsx235("path", { d: "M11 3 L9 3 L9 13 L11 13" })
91803
91855
  ]
91804
91856
  }
91805
91857
  )
@@ -91810,11 +91862,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91810
91862
  })(),
91811
91863
  (() => {
91812
91864
  const canAdd = beatAnalysisReady && canAddBeatAt(currentTime);
91813
- return /* @__PURE__ */ jsx234(
91865
+ return /* @__PURE__ */ jsx235(
91814
91866
  Tooltip,
91815
91867
  {
91816
91868
  label: !beatAnalysisReady ? "Add a music track with beat analysis to place beats" : canAdd ? "Add beat at playhead" : "A beat already exists at the playhead",
91817
- children: /* @__PURE__ */ jsx234(
91869
+ children: /* @__PURE__ */ jsx235(
91818
91870
  "button",
91819
91871
  {
91820
91872
  type: "button",
@@ -91824,7 +91876,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91824
91876
  if (canAdd) addBeatAtCompositionTime(currentTime);
91825
91877
  },
91826
91878
  className: canAdd ? `${flatBtn} text-neutral-400 hover:bg-white/6 hover:text-[#22c55e] active:scale-[0.98]` : flatDisabled,
91827
- children: /* @__PURE__ */ jsx234("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx234(
91879
+ children: /* @__PURE__ */ jsx235("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx235(
91828
91880
  "path",
91829
91881
  {
91830
91882
  d: "M21 10C21 12.2091 16.9706 14 12 14M21 10C21 7.79086 16.9706 6 12 6C7.02944 6 3 7.79086 3 10M21 10V16C21 18.2091 16.9706 20 12 20M12 14C7.02944 14 3 12.2091 3 10M12 14V20M3 10V16C3 18.2091 7.02944 20 12 20M7 19.3264V13.3264M17 19.3264V13.3264M12 10L20 4",
@@ -91840,12 +91892,12 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91840
91892
  );
91841
91893
  })()
91842
91894
  ] }),
91843
- /* @__PURE__ */ jsxs187("div", { className: "flex items-center gap-0.5", children: [
91844
- /* @__PURE__ */ jsx234(
91895
+ /* @__PURE__ */ jsxs188("div", { className: "flex items-center gap-0.5", children: [
91896
+ /* @__PURE__ */ jsx235(
91845
91897
  Tooltip,
91846
91898
  {
91847
91899
  label: thumbnailsVisible ? "Hide thumbnails \u2014 labels only" : "Show thumbnails \u2014 posters stay visible; richer previews appear on interaction",
91848
- children: /* @__PURE__ */ jsx234(
91900
+ children: /* @__PURE__ */ jsx235(
91849
91901
  "button",
91850
91902
  {
91851
91903
  type: "button",
@@ -91853,12 +91905,12 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91853
91905
  "aria-pressed": thumbnailsVisible,
91854
91906
  onClick: () => setThumbnailMode(thumbnailsVisible ? "hidden" : "adaptive"),
91855
91907
  className: `h-7 px-2 rounded-md text-[11px] font-medium transition-colors ${thumbnailsVisible ? "bg-studio-accent/10 text-studio-accent" : "text-neutral-400 hover:bg-white/6 hover:text-neutral-200"}`,
91856
- children: /* @__PURE__ */ jsx234(Image3, { size: 16, "aria-hidden": "true" })
91908
+ children: /* @__PURE__ */ jsx235(Image3, { size: 16, "aria-hidden": "true" })
91857
91909
  }
91858
91910
  )
91859
91911
  }
91860
91912
  ),
91861
- /* @__PURE__ */ jsx234(Tooltip, { label: "Fit timeline to width", children: /* @__PURE__ */ jsx234(
91913
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Fit timeline to width", children: /* @__PURE__ */ jsx235(
91862
91914
  "button",
91863
91915
  {
91864
91916
  type: "button",
@@ -91867,7 +91919,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91867
91919
  children: "Fit"
91868
91920
  }
91869
91921
  ) }),
91870
- /* @__PURE__ */ jsx234(Tooltip, { label: "Zoom out", children: /* @__PURE__ */ jsx234(
91922
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Zoom out", children: /* @__PURE__ */ jsx235(
91871
91923
  "button",
91872
91924
  {
91873
91925
  type: "button",
@@ -91879,10 +91931,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91879
91931
  );
91880
91932
  },
91881
91933
  className: flatIdle,
91882
- children: /* @__PURE__ */ jsx234(MagnifyingGlassMinus, { size: 16, "aria-hidden": "true" })
91934
+ children: /* @__PURE__ */ jsx235(MagnifyingGlassMinus, { size: 16, "aria-hidden": "true" })
91883
91935
  }
91884
91936
  ) }),
91885
- /* @__PURE__ */ jsx234(
91937
+ /* @__PURE__ */ jsx235(
91886
91938
  "input",
91887
91939
  {
91888
91940
  type: "range",
@@ -91900,7 +91952,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91900
91952
  className: "mx-1 h-6 w-[96px] cursor-pointer appearance-none bg-transparent [&::-webkit-slider-runnable-track]:h-[2px] [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-neutral-700 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-[10px] [&::-webkit-slider-thumb]:h-[10px] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:-mt-1 [&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#0a0a0a,0_1px_3px_rgba(0,0,0,0.5)] [&::-webkit-slider-thumb]:cursor-grab [&::-webkit-slider-thumb:active]:cursor-grabbing"
91901
91953
  }
91902
91954
  ),
91903
- /* @__PURE__ */ jsx234(Tooltip, { label: "Zoom in", children: /* @__PURE__ */ jsx234(
91955
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Zoom in", children: /* @__PURE__ */ jsx235(
91904
91956
  "button",
91905
91957
  {
91906
91958
  type: "button",
@@ -91912,10 +91964,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91912
91964
  );
91913
91965
  },
91914
91966
  className: flatIdle,
91915
- children: /* @__PURE__ */ jsx234(MagnifyingGlassPlus, { size: 16, "aria-hidden": "true" })
91967
+ children: /* @__PURE__ */ jsx235(MagnifyingGlassPlus, { size: 16, "aria-hidden": "true" })
91916
91968
  }
91917
91969
  ) }),
91918
- /* @__PURE__ */ jsx234(
91970
+ /* @__PURE__ */ jsx235(
91919
91971
  "span",
91920
91972
  {
91921
91973
  className: "ml-1 w-[38px] text-right font-mono text-[11px] tabular-nums text-neutral-500 select-none",
@@ -91929,18 +91981,18 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91929
91981
  }
91930
91982
 
91931
91983
  // src/components/StudioSplash.tsx
91932
- import { jsx as jsx235, jsxs as jsxs188 } from "react/jsx-runtime";
91984
+ import { jsx as jsx236, jsxs as jsxs189 } from "react/jsx-runtime";
91933
91985
  function StudioSplash({ waiting }) {
91934
- return /* @__PURE__ */ jsx235("div", { className: "h-full w-full bg-neutral-950 flex items-center justify-center", children: waiting ? /* @__PURE__ */ jsxs188("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
91935
- /* @__PURE__ */ jsx235("div", { className: "w-4 h-4 rounded-full border-2 border-neutral-700 border-t-neutral-500 animate-spin motion-reduce:animate-none" }),
91936
- /* @__PURE__ */ jsxs188("p", { className: "text-xs text-neutral-600", children: [
91986
+ return /* @__PURE__ */ jsx236("div", { className: "h-full w-full bg-neutral-950 flex items-center justify-center", children: waiting ? /* @__PURE__ */ jsxs189("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
91987
+ /* @__PURE__ */ jsx236("div", { className: "w-4 h-4 rounded-full border-2 border-neutral-700 border-t-neutral-500 animate-spin motion-reduce:animate-none" }),
91988
+ /* @__PURE__ */ jsxs189("p", { className: "text-xs text-neutral-600", children: [
91937
91989
  "Waiting for preview server\u2026 run",
91938
91990
  " ",
91939
- /* @__PURE__ */ jsx235("code", { className: "text-neutral-500 font-mono", children: "npm run dev" })
91991
+ /* @__PURE__ */ jsx236("code", { className: "text-neutral-500 font-mono", children: "npm run dev" })
91940
91992
  ] })
91941
- ] }) : /* @__PURE__ */ jsxs188("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
91942
- /* @__PURE__ */ jsx235("div", { className: "w-4 h-4 rounded-full bg-studio-accent animate-pulse motion-reduce:animate-none" }),
91943
- /* @__PURE__ */ jsx235("p", { className: "text-xs text-neutral-600", children: "Connecting to project\u2026" })
91993
+ ] }) : /* @__PURE__ */ jsxs189("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
91994
+ /* @__PURE__ */ jsx236("div", { className: "w-4 h-4 rounded-full bg-studio-accent animate-pulse motion-reduce:animate-none" }),
91995
+ /* @__PURE__ */ jsx236("p", { className: "text-xs text-neutral-600", children: "Connecting to project\u2026" })
91944
91996
  ] }) });
91945
91997
  }
91946
91998
 
@@ -92207,7 +92259,7 @@ function useActiveComposition({
92207
92259
  }
92208
92260
 
92209
92261
  // src/App.tsx
92210
- import { Fragment as Fragment62, jsx as jsx236, jsxs as jsxs189 } from "react/jsx-runtime";
92262
+ import { Fragment as Fragment62, jsx as jsx237, jsxs as jsxs190 } from "react/jsx-runtime";
92211
92263
  var getTimelineSelectionSet = () => usePlayerStore.getState().selectedElementIds;
92212
92264
  function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92213
92265
  const { projectId, resolving, waitingForServer } = useServerConnection();
@@ -92266,7 +92318,8 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92266
92318
  activeCompPath,
92267
92319
  masterCompPath,
92268
92320
  fileManager.fileTree,
92269
- fileManager.fileTreeLoaded
92321
+ fileManager.fileTreeLoaded,
92322
+ fileManager.refreshFileTree
92270
92323
  );
92271
92324
  const activeCompPathRef = useRef185(activeCompPath);
92272
92325
  activeCompPathRef.current = activeCompPath;
@@ -92565,7 +92618,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92565
92618
  refreshPreviewDocumentVersion
92566
92619
  });
92567
92620
  const timelineToolbar = useMemo77(
92568
- () => /* @__PURE__ */ jsx236(
92621
+ () => /* @__PURE__ */ jsx237(
92569
92622
  TimelineToolbar,
92570
92623
  {
92571
92624
  domEditSession,
@@ -92575,15 +92628,15 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92575
92628
  [domEditSession, timelineEditing.handleTimelineElementSplit]
92576
92629
  );
92577
92630
  if (resolving || waitingForServer || !projectId)
92578
- return /* @__PURE__ */ jsx236(StudioSplash, { waiting: waitingForServer });
92579
- return /* @__PURE__ */ jsx236(StudioShellProvider, { value: studioCtxValue, children: /* @__PURE__ */ jsx236(StudioPlaybackProvider, { value: studioCtxValue, children: /* @__PURE__ */ jsx236(PanelLayoutProvider, { value: layout, children: /* @__PURE__ */ jsx236(FileManagerProvider, { value: fileManager, children: /* @__PURE__ */ jsx236(DomEditProvider, { value: domEditSession, children: /* @__PURE__ */ jsxs189(
92631
+ return /* @__PURE__ */ jsx237(StudioSplash, { waiting: waitingForServer });
92632
+ return /* @__PURE__ */ jsx237(StudioShellProvider, { value: studioCtxValue, children: /* @__PURE__ */ jsx237(StudioPlaybackProvider, { value: studioCtxValue, children: /* @__PURE__ */ jsx237(PanelLayoutProvider, { value: layout, children: /* @__PURE__ */ jsx237(FileManagerProvider, { value: fileManager, children: /* @__PURE__ */ jsx237(DomEditProvider, { value: domEditSession, children: /* @__PURE__ */ jsxs190(
92580
92633
  "div",
92581
92634
  {
92582
92635
  className: "flex flex-col h-full w-full bg-neutral-950 relative",
92583
92636
  onDragOver: fileDrop.onDragOver,
92584
92637
  onDrop: fileDrop.onDrop,
92585
92638
  children: [
92586
- /* @__PURE__ */ jsx236(
92639
+ /* @__PURE__ */ jsx237(
92587
92640
  StudioHeader,
92588
92641
  {
92589
92642
  captureFrameHref: frameCapture.captureFrameHref,
@@ -92601,22 +92654,23 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92601
92654
  }
92602
92655
  }
92603
92656
  ),
92604
- previewPersistence.domEditSaveQueuePaused && !externalFileChanges.blocked && /* @__PURE__ */ jsx236(
92657
+ previewPersistence.domEditSaveQueuePaused && !externalFileChanges.blocked && /* @__PURE__ */ jsx237(
92605
92658
  SaveQueuePausedBanner,
92606
92659
  {
92607
92660
  message: previewPersistence.domEditSaveQueuePaused,
92608
92661
  onRetry: previewPersistence.resetDomEditSaveQueueBreaker
92609
92662
  }
92610
92663
  ),
92611
- /* @__PURE__ */ jsx236(ExternalFileConflictBanner, { coordinator: externalFileChanges }),
92612
- sdkHandle.unreachableProject && /* @__PURE__ */ jsx236(ProjectUnreachableBanner, { projectId: sdkHandle.unreachableProject }),
92613
- /* @__PURE__ */ jsx236(
92664
+ /* @__PURE__ */ jsx237(ExternalFileConflictBanner, { coordinator: externalFileChanges }),
92665
+ sdkHandle.unreachableProject && /* @__PURE__ */ jsx237(ProjectUnreachableBanner, { projectId: sdkHandle.unreachableProject }),
92666
+ sdkHandle.compositionMissing && activeCompPath && /* @__PURE__ */ jsx237(CompositionMissingBanner, { path: activeCompPath }),
92667
+ /* @__PURE__ */ jsx237(
92614
92668
  EditorShell,
92615
92669
  {
92616
92670
  readOnlyPreview,
92617
92671
  readOnlyPreviewReason,
92618
- panels: /* @__PURE__ */ jsxs189(Fragment62, { children: [
92619
- /* @__PURE__ */ jsx236(
92672
+ panels: /* @__PURE__ */ jsxs190(Fragment62, { children: [
92673
+ /* @__PURE__ */ jsx237(
92620
92674
  StudioLeftPanels,
92621
92675
  {
92622
92676
  onSelectComposition: handleSelectComposition,
@@ -92631,7 +92685,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92631
92685
  onAddCompositionToTimeline: handleAddCompositionAtPlayhead
92632
92686
  }
92633
92687
  ),
92634
- /* @__PURE__ */ jsx236(
92688
+ /* @__PURE__ */ jsx237(
92635
92689
  StudioRightPanels,
92636
92690
  {
92637
92691
  activeBlockParams,
@@ -92686,7 +92740,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92686
92740
  recordingState: gestureState,
92687
92741
  onToggleRecording: handleToggleRecording,
92688
92742
  blockPreview,
92689
- gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */ jsx236(
92743
+ gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */ jsx237(
92690
92744
  GestureTrailOverlay,
92691
92745
  {
92692
92746
  samples: gestureRecording.samplesRef.current,
@@ -92699,7 +92753,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92699
92753
  ) : void 0
92700
92754
  }
92701
92755
  ),
92702
- /* @__PURE__ */ jsx236(
92756
+ /* @__PURE__ */ jsx237(
92703
92757
  StudioOverlays,
92704
92758
  {
92705
92759
  projectId,