hyperframes 0.8.70 → 0.8.71

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.
@@ -69159,6 +69159,22 @@ function ProjectUnreachableBanner({ projectId }) {
69159
69159
  );
69160
69160
  }
69161
69161
 
69162
+ // src/components/CompositionMissingBanner.tsx
69163
+ import { jsx as jsx199, jsxs as jsxs158 } from "react/jsx-runtime";
69164
+ function CompositionMissingBanner({ path }) {
69165
+ return /* @__PURE__ */ jsx199(
69166
+ "div",
69167
+ {
69168
+ role: "alert",
69169
+ 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",
69170
+ children: /* @__PURE__ */ jsxs158("span", { children: [
69171
+ /* @__PURE__ */ jsx199("strong", { children: path }),
69172
+ " is no longer on disk. Select another composition to keep editing."
69173
+ ] })
69174
+ }
69175
+ );
69176
+ }
69177
+
69162
69178
  // src/captions/hooks/useCaptionSync.ts
69163
69179
  import { useCallback as useCallback92, useRef as useRef127 } from "react";
69164
69180
  function buildOverrides(model) {
@@ -79885,7 +79901,7 @@ function disposeSdkSession(session) {
79885
79901
  });
79886
79902
  }
79887
79903
  }
79888
- function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded = false) {
79904
+ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded = false, onAbsentRead) {
79889
79905
  const [ownedSession, setOwnedSession] = useState117(null);
79890
79906
  const ownedSessionRef = useRef154(null);
79891
79907
  const sessionOwnersRef = useRef154(/* @__PURE__ */ new WeakMap());
@@ -79898,6 +79914,21 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79898
79914
  const reloadTokenRef = useRef154(reloadToken);
79899
79915
  reloadTokenRef.current = reloadToken;
79900
79916
  const [unreachableProject, setUnreachableProject] = useState117(null);
79917
+ const [compositionMissing, setCompositionMissing] = useState117(false);
79918
+ const refreshedAbsentPathsRef = useRef154(/* @__PURE__ */ new Set());
79919
+ useEffect118(() => {
79920
+ refreshedAbsentPathsRef.current.clear();
79921
+ }, [projectId]);
79922
+ function handleReadFailure(read, forProjectId, forPath) {
79923
+ const pathInTree = fileTreeLoaded ? fileTree.includes(forPath) : null;
79924
+ setUnreachableProject(reportReadFailure(read, forProjectId, pathInTree));
79925
+ setCompositionMissing(read.reason === "absent");
79926
+ if (read.reason !== "absent") return;
79927
+ const key2 = `${forProjectId}:${forPath}`;
79928
+ if (refreshedAbsentPathsRef.current.has(key2)) return;
79929
+ refreshedAbsentPathsRef.current.add(key2);
79930
+ onAbsentRead?.(forPath);
79931
+ }
79901
79932
  useEffect118(
79902
79933
  () => addExternalFileReloadListener((changedPath) => {
79903
79934
  if (changedPath === activeCompPathRef.current) setReloadToken((token) => token + 1);
@@ -79913,6 +79944,7 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79913
79944
  if (previous) disposeSdkSession(previous.session);
79914
79945
  if (!projectId || !activeCompPath) {
79915
79946
  setUnreachableProject(null);
79947
+ setCompositionMissing(false);
79916
79948
  return () => {
79917
79949
  cancelled = true;
79918
79950
  };
@@ -79926,11 +79958,11 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79926
79958
  readProjectFileOptional(projectId, activeCompPath).then(async (read) => {
79927
79959
  if (cancelled) return;
79928
79960
  if (!read.ok) {
79929
- const pathInTree = fileTreeLoaded ? fileTree.includes(activeCompPath) : null;
79930
- setUnreachableProject(reportReadFailure(read, projectId, pathInTree));
79961
+ handleReadFailure(read, projectId, activeCompPath);
79931
79962
  return;
79932
79963
  }
79933
79964
  setUnreachableProject(null);
79965
+ setCompositionMissing(false);
79934
79966
  const content = read.content;
79935
79967
  const comp = await openComposition3(content, { history: false });
79936
79968
  if (cancelled) {
@@ -79996,16 +80028,17 @@ function useSdkSession(projectId, activeCompPath, fileTree = [], fileTreeLoaded
79996
80028
  return "published";
79997
80029
  }, []);
79998
80030
  const session = ownedSession?.projectId === projectId && ownedSession.path === activeCompPath && ownedSession.reloadToken === reloadToken ? ownedSession.session : null;
79999
- return { session, publish, forceReload, unreachableProject };
80031
+ return { session, publish, forceReload, unreachableProject, compositionMissing };
80000
80032
  }
80001
80033
 
80002
80034
  // src/hooks/useStudioSdkSessions.ts
80003
- function useStudioSdkSessions(projectId, activeCompPath, masterCompPath, fileTree = [], fileTreeLoaded = false) {
80035
+ function useStudioSdkSessions(projectId, activeCompPath, masterCompPath, fileTree = [], fileTreeLoaded = false, refreshFileTree) {
80004
80036
  const sdkHandle = useSdkSession(
80005
80037
  projectId,
80006
80038
  activeCompPath ?? masterCompPath,
80007
80039
  fileTree,
80008
- fileTreeLoaded
80040
+ fileTreeLoaded,
80041
+ refreshFileTree
80009
80042
  );
80010
80043
  const editFlowSdkSession = activeCompPath ? sdkHandle.session : null;
80011
80044
  useEffect119(() => {
@@ -80165,7 +80198,8 @@ function useExternalFileChangeCoordinator({
80165
80198
  readProjectFile,
80166
80199
  onUseExternalFile,
80167
80200
  resetSaveQueues,
80168
- onAcceptedPersistedFileChange
80201
+ onAcceptedPersistedFileChange,
80202
+ refreshFileTree
80169
80203
  }) {
80170
80204
  const [blocked, setBlocked] = useState118(null);
80171
80205
  const generationRef = useRef155(0);
@@ -80231,8 +80265,9 @@ function useExternalFileChangeCoordinator({
80231
80265
  logReload("reload", { path, by: "external-change coordinator" });
80232
80266
  reloadPreview();
80233
80267
  reloadSdkSession(path);
80268
+ void refreshFileTree?.();
80234
80269
  },
80235
- [reloadPreview, reloadSdkSession]
80270
+ [reloadPreview, reloadSdkSession, refreshFileTree]
80236
80271
  );
80237
80272
  const persistSnapshotInOrder = useCallback137(async (write) => {
80238
80273
  const next = snapshotWriteTailRef.current.catch(() => void 0).then(write);
@@ -80533,7 +80568,8 @@ function useStudioExternalFileChanges({
80533
80568
  readProjectFile: fileManager.readProjectFile,
80534
80569
  onUseExternalFile: fileManager.updateEditingFileContent,
80535
80570
  resetSaveQueues: resetDomEditSaveQueueBreaker,
80536
- onAcceptedPersistedFileChange
80571
+ onAcceptedPersistedFileChange,
80572
+ refreshFileTree: fileManager.refreshFileTree
80537
80573
  });
80538
80574
  }
80539
80575
 
@@ -83534,7 +83570,7 @@ function useGestureCommit({
83534
83570
 
83535
83571
  // src/components/editor/GestureTrailOverlay.tsx
83536
83572
  import { memo as memo40, useMemo as useMemo72 } from "react";
83537
- import { Fragment as Fragment52, jsx as jsx199, jsxs as jsxs158 } from "react/jsx-runtime";
83573
+ import { Fragment as Fragment52, jsx as jsx200, jsxs as jsxs159 } from "react/jsx-runtime";
83538
83574
  var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83539
83575
  samples,
83540
83576
  sampleCount,
@@ -83576,7 +83612,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83576
83612
  return pts.sort((a, b) => a.pct - b.pct);
83577
83613
  }, [simplifiedPoints]);
83578
83614
  if (!canvasRect || samples.length < 2 && !simplifiedPoints) return null;
83579
- return /* @__PURE__ */ jsxs158(
83615
+ return /* @__PURE__ */ jsxs159(
83580
83616
  "svg",
83581
83617
  {
83582
83618
  className: "pointer-events-none fixed z-50",
@@ -83588,7 +83624,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83588
83624
  },
83589
83625
  viewBox: trail2 && trail2.length > 1 ? `0 0 ${canvasRect.width} ${canvasRect.height}` : `0 0 ${compositionSize?.width ?? canvasRect.width} ${compositionSize?.height ?? canvasRect.height}`,
83590
83626
  children: [
83591
- mode === "recording" && trailPoints && /* @__PURE__ */ jsx199(
83627
+ mode === "recording" && trailPoints && /* @__PURE__ */ jsx200(
83592
83628
  "polyline",
83593
83629
  {
83594
83630
  points: trailPoints,
@@ -83600,8 +83636,8 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83600
83636
  strokeLinejoin: "round"
83601
83637
  }
83602
83638
  ),
83603
- mode === "preview" && /* @__PURE__ */ jsxs158(Fragment52, { children: [
83604
- trailPoints && /* @__PURE__ */ jsx199(
83639
+ mode === "preview" && /* @__PURE__ */ jsxs159(Fragment52, { children: [
83640
+ trailPoints && /* @__PURE__ */ jsx200(
83605
83641
  "polyline",
83606
83642
  {
83607
83643
  points: trailPoints,
@@ -83613,7 +83649,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83613
83649
  strokeLinecap: "round"
83614
83650
  }
83615
83651
  ),
83616
- simplifiedPath && /* @__PURE__ */ jsx199(
83652
+ simplifiedPath && /* @__PURE__ */ jsx200(
83617
83653
  "polyline",
83618
83654
  {
83619
83655
  points: simplifiedPath,
@@ -83625,7 +83661,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
83625
83661
  strokeLinejoin: "round"
83626
83662
  }
83627
83663
  ),
83628
- diamondPositions.map((pt) => /* @__PURE__ */ jsx199("g", { transform: `translate(${pt.x}, ${pt.y})`, children: /* @__PURE__ */ jsx199(
83664
+ diamondPositions.map((pt) => /* @__PURE__ */ jsx200("g", { transform: `translate(${pt.x}, ${pt.y})`, children: /* @__PURE__ */ jsx200(
83629
83665
  "rect",
83630
83666
  {
83631
83667
  x: "-4",
@@ -83649,10 +83685,10 @@ import { useCallback as useCallback158 } from "react";
83649
83685
 
83650
83686
  // src/components/MediaPreview.tsx
83651
83687
  import { useState as useState127 } from "react";
83652
- import { jsx as jsx200, jsxs as jsxs159 } from "react/jsx-runtime";
83688
+ import { jsx as jsx201, jsxs as jsxs160 } from "react/jsx-runtime";
83653
83689
  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(
83690
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-2", children: [
83691
+ /* @__PURE__ */ jsxs160(
83656
83692
  "svg",
83657
83693
  {
83658
83694
  width: "40",
@@ -83664,15 +83700,15 @@ function MediaErrorPanel({ name, filePath }) {
83664
83700
  className: "text-neutral-600",
83665
83701
  "aria-hidden": "true",
83666
83702
  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" })
83703
+ /* @__PURE__ */ jsx201("circle", { cx: "12", cy: "12", r: "10" }),
83704
+ /* @__PURE__ */ jsx201("line", { x1: "12", y1: "8", x2: "12", y2: "12", strokeLinecap: "round" }),
83705
+ /* @__PURE__ */ jsx201("line", { x1: "12", y1: "16", x2: "12.01", y2: "16", strokeLinecap: "round" })
83670
83706
  ]
83671
83707
  }
83672
83708
  ),
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" })
83709
+ /* @__PURE__ */ jsx201("span", { className: "text-sm text-neutral-400 font-medium", children: name }),
83710
+ /* @__PURE__ */ jsx201("span", { className: "text-[11px] text-neutral-600 font-mono", children: filePath }),
83711
+ /* @__PURE__ */ jsx201("span", { className: "text-[10px] text-neutral-500", children: "Couldn't load this file \u2014 it may be missing or corrupt" })
83676
83712
  ] });
83677
83713
  }
83678
83714
  function MediaPreview({ projectId, filePath }) {
@@ -83681,10 +83717,10 @@ function MediaPreview({ projectId, filePath }) {
83681
83717
  const [failedPath, setFailedPath] = useState127(null);
83682
83718
  const failed2 = failedPath === filePath;
83683
83719
  const setFailed = () => setFailedPath(filePath);
83684
- if (failed2) return /* @__PURE__ */ jsx200(MediaErrorPanel, { name, filePath });
83720
+ if (failed2) return /* @__PURE__ */ jsx201(MediaErrorPanel, { name, filePath });
83685
83721
  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(
83722
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950", children: [
83723
+ /* @__PURE__ */ jsx201(
83688
83724
  "img",
83689
83725
  {
83690
83726
  src: serveUrl,
@@ -83693,12 +83729,12 @@ function MediaPreview({ projectId, filePath }) {
83693
83729
  className: "max-w-full max-h-[70%] object-contain rounded-sm border border-neutral-800"
83694
83730
  }
83695
83731
  ),
83696
- /* @__PURE__ */ jsx200("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83732
+ /* @__PURE__ */ jsx201("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83697
83733
  ] });
83698
83734
  }
83699
83735
  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(
83736
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950", children: [
83737
+ /* @__PURE__ */ jsx201(
83702
83738
  "video",
83703
83739
  {
83704
83740
  src: serveUrl,
@@ -83707,12 +83743,12 @@ function MediaPreview({ projectId, filePath }) {
83707
83743
  className: "max-w-full max-h-[70%] rounded-sm border border-neutral-800"
83708
83744
  }
83709
83745
  ),
83710
- /* @__PURE__ */ jsx200("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83746
+ /* @__PURE__ */ jsx201("span", { className: "mt-3 text-[11px] text-neutral-500 font-mono", children: filePath })
83711
83747
  ] });
83712
83748
  }
83713
83749
  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(
83750
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-3", children: [
83751
+ /* @__PURE__ */ jsxs160(
83716
83752
  "svg",
83717
83753
  {
83718
83754
  width: "48",
@@ -83723,18 +83759,18 @@ function MediaPreview({ projectId, filePath }) {
83723
83759
  strokeWidth: "1.5",
83724
83760
  className: "text-neutral-600",
83725
83761
  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" })
83762
+ /* @__PURE__ */ jsx201("path", { d: "M9 18V5l12-2v13", strokeLinecap: "round", strokeLinejoin: "round" }),
83763
+ /* @__PURE__ */ jsx201("circle", { cx: "6", cy: "18", r: "3" }),
83764
+ /* @__PURE__ */ jsx201("circle", { cx: "18", cy: "16", r: "3" })
83729
83765
  ]
83730
83766
  }
83731
83767
  ),
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 })
83768
+ /* @__PURE__ */ jsx201("audio", { src: serveUrl, controls: true, onError: setFailed, className: "w-full max-w-[280px]" }),
83769
+ /* @__PURE__ */ jsx201("span", { className: "text-[11px] text-neutral-500 font-mono", children: filePath })
83734
83770
  ] });
83735
83771
  }
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(
83772
+ return /* @__PURE__ */ jsxs160("div", { className: "flex flex-col items-center justify-center h-full p-4 bg-neutral-950 gap-2", children: [
83773
+ /* @__PURE__ */ jsxs160(
83738
83774
  "svg",
83739
83775
  {
83740
83776
  width: "40",
@@ -83745,7 +83781,7 @@ function MediaPreview({ projectId, filePath }) {
83745
83781
  strokeWidth: "1.5",
83746
83782
  className: "text-neutral-600",
83747
83783
  children: [
83748
- /* @__PURE__ */ jsx200(
83784
+ /* @__PURE__ */ jsx201(
83749
83785
  "path",
83750
83786
  {
83751
83787
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
@@ -83753,13 +83789,13 @@ function MediaPreview({ projectId, filePath }) {
83753
83789
  strokeLinejoin: "round"
83754
83790
  }
83755
83791
  ),
83756
- /* @__PURE__ */ jsx200("polyline", { points: "14 2 14 8 20 8", strokeLinecap: "round", strokeLinejoin: "round" })
83792
+ /* @__PURE__ */ jsx201("polyline", { points: "14 2 14 8 20 8", strokeLinecap: "round", strokeLinejoin: "round" })
83757
83793
  ]
83758
83794
  }
83759
83795
  ),
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" })
83796
+ /* @__PURE__ */ jsx201("span", { className: "text-sm text-neutral-400 font-medium", children: name }),
83797
+ /* @__PURE__ */ jsx201("span", { className: "text-[11px] text-neutral-600 font-mono", children: filePath }),
83798
+ /* @__PURE__ */ jsx201("span", { className: "text-[10px] text-neutral-600", children: "Binary file \u2014 preview not available" })
83763
83799
  ] });
83764
83800
  }
83765
83801
 
@@ -83767,14 +83803,14 @@ function MediaPreview({ projectId, filePath }) {
83767
83803
  import { memo as memo41, useState as useState133, useCallback as useCallback154, useRef as useRef170, useMemo as useMemo74, useEffect as useEffect133 } from "react";
83768
83804
 
83769
83805
  // src/components/ui/SearchInput.tsx
83770
- import { jsx as jsx201, jsxs as jsxs160 } from "react/jsx-runtime";
83806
+ import { jsx as jsx202, jsxs as jsxs161 } from "react/jsx-runtime";
83771
83807
  function SearchInput({ className = "", ...props }) {
83772
- return /* @__PURE__ */ jsxs160(
83808
+ return /* @__PURE__ */ jsxs161(
83773
83809
  "div",
83774
83810
  {
83775
83811
  className: `flex items-center gap-1.5 rounded-md bg-panel-input px-2.5 py-[5px] ${className}`,
83776
83812
  children: [
83777
- /* @__PURE__ */ jsxs160(
83813
+ /* @__PURE__ */ jsxs161(
83778
83814
  "svg",
83779
83815
  {
83780
83816
  width: "12",
@@ -83784,7 +83820,7 @@ function SearchInput({ className = "", ...props }) {
83784
83820
  className: "shrink-0",
83785
83821
  "aria-hidden": "true",
83786
83822
  children: [
83787
- /* @__PURE__ */ jsx201(
83823
+ /* @__PURE__ */ jsx202(
83788
83824
  "circle",
83789
83825
  {
83790
83826
  cx: "116",
@@ -83795,7 +83831,7 @@ function SearchInput({ className = "", ...props }) {
83795
83831
  className: "text-panel-text-5"
83796
83832
  }
83797
83833
  ),
83798
- /* @__PURE__ */ jsx201(
83834
+ /* @__PURE__ */ jsx202(
83799
83835
  "line",
83800
83836
  {
83801
83837
  x1: "170",
@@ -83811,7 +83847,7 @@ function SearchInput({ className = "", ...props }) {
83811
83847
  ]
83812
83848
  }
83813
83849
  ),
83814
- /* @__PURE__ */ jsx201(
83850
+ /* @__PURE__ */ jsx202(
83815
83851
  "input",
83816
83852
  {
83817
83853
  type: "text",
@@ -83880,7 +83916,7 @@ import { classifyWebAudioMediaRoute } from "@hyperframes/core/runtime/web-audio-
83880
83916
 
83881
83917
  // src/components/sidebar/AssetContextMenu.tsx
83882
83918
  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";
83919
+ import { Fragment as Fragment53, jsx as jsx203, jsxs as jsxs162 } from "react/jsx-runtime";
83884
83920
  function isValidAssetName(name) {
83885
83921
  return name.length > 0 && !/[/\\]/.test(name) && !name.includes("..");
83886
83922
  }
@@ -83954,7 +83990,7 @@ function ContextMenu3({
83954
83990
  onClose();
83955
83991
  }, [renameDraft, asset, onRename, onClose]);
83956
83992
  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(
83993
+ return /* @__PURE__ */ jsx203(
83958
83994
  "div",
83959
83995
  {
83960
83996
  className: "fixed inset-0 z-200",
@@ -83963,7 +83999,7 @@ function ContextMenu3({
83963
83999
  e.preventDefault();
83964
84000
  onClose();
83965
84001
  },
83966
- children: /* @__PURE__ */ jsxs161(
84002
+ children: /* @__PURE__ */ jsxs162(
83967
84003
  "div",
83968
84004
  {
83969
84005
  ref: menuRef,
@@ -83973,8 +84009,8 @@ function ContextMenu3({
83973
84009
  style: { left: pos.x, top: pos.y },
83974
84010
  onClick: (e) => e.stopPropagation(),
83975
84011
  children: [
83976
- mode === "menu" && /* @__PURE__ */ jsxs161(Fragment53, { children: [
83977
- onAddAtPlayhead && /* @__PURE__ */ jsx202(
84012
+ mode === "menu" && /* @__PURE__ */ jsxs162(Fragment53, { children: [
84013
+ onAddAtPlayhead && /* @__PURE__ */ jsx203(
83978
84014
  "button",
83979
84015
  {
83980
84016
  role: "menuitem",
@@ -83986,7 +84022,7 @@ function ContextMenu3({
83986
84022
  children: "Add at playhead"
83987
84023
  }
83988
84024
  ),
83989
- /* @__PURE__ */ jsx202(
84025
+ /* @__PURE__ */ jsx203(
83990
84026
  "button",
83991
84027
  {
83992
84028
  role: "menuitem",
@@ -83998,8 +84034,8 @@ function ContextMenu3({
83998
84034
  children: "Copy path"
83999
84035
  }
84000
84036
  ),
84001
- onRename && /* @__PURE__ */ jsx202("button", { role: "menuitem", onClick: () => setMode("rename"), className: itemCls, children: "Rename" }),
84002
- onDelete && /* @__PURE__ */ jsx202(
84037
+ onRename && /* @__PURE__ */ jsx203("button", { role: "menuitem", onClick: () => setMode("rename"), className: itemCls, children: "Rename" }),
84038
+ onDelete && /* @__PURE__ */ jsx203(
84003
84039
  "button",
84004
84040
  {
84005
84041
  role: "menuitem",
@@ -84009,7 +84045,7 @@ function ContextMenu3({
84009
84045
  }
84010
84046
  )
84011
84047
  ] }),
84012
- mode === "confirm-delete" && /* @__PURE__ */ jsx202(
84048
+ mode === "confirm-delete" && /* @__PURE__ */ jsx203(
84013
84049
  DeleteConfirm2,
84014
84050
  {
84015
84051
  name: filename(asset),
@@ -84020,8 +84056,8 @@ function ContextMenu3({
84020
84056
  onCancel: () => setMode("menu")
84021
84057
  }
84022
84058
  ),
84023
- mode === "rename" && /* @__PURE__ */ jsxs161("div", { className: "px-2 py-1.5 flex flex-col gap-1", children: [
84024
- /* @__PURE__ */ jsx202(
84059
+ mode === "rename" && /* @__PURE__ */ jsxs162("div", { className: "px-2 py-1.5 flex flex-col gap-1", children: [
84060
+ /* @__PURE__ */ jsx203(
84025
84061
  "input",
84026
84062
  {
84027
84063
  autoFocus: true,
@@ -84041,9 +84077,9 @@ function ContextMenu3({
84041
84077
  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
84078
  }
84043
84079
  ),
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(
84080
+ renameError && /* @__PURE__ */ jsx203("span", { className: "text-[10px] text-red-400", children: renameError }),
84081
+ /* @__PURE__ */ jsxs162("div", { className: "flex items-center justify-end gap-1", children: [
84082
+ /* @__PURE__ */ jsx203(
84047
84083
  "button",
84048
84084
  {
84049
84085
  onClick: () => setMode("menu"),
@@ -84051,7 +84087,7 @@ function ContextMenu3({
84051
84087
  children: "Cancel"
84052
84088
  }
84053
84089
  ),
84054
- /* @__PURE__ */ jsx202(
84090
+ /* @__PURE__ */ jsx203(
84055
84091
  "button",
84056
84092
  {
84057
84093
  onClick: commitRename,
@@ -84072,14 +84108,14 @@ function DeleteConfirm2({
84072
84108
  onConfirm,
84073
84109
  onCancel
84074
84110
  }) {
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: [
84111
+ 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: [
84112
+ /* @__PURE__ */ jsxs162("span", { className: "text-[10px] text-red-400 truncate", children: [
84077
84113
  "Delete ",
84078
84114
  name,
84079
84115
  "?"
84080
84116
  ] }),
84081
- /* @__PURE__ */ jsxs161("div", { className: "flex items-center gap-1 shrink-0", children: [
84082
- /* @__PURE__ */ jsx202(
84117
+ /* @__PURE__ */ jsxs162("div", { className: "flex items-center gap-1 shrink-0", children: [
84118
+ /* @__PURE__ */ jsx203(
84083
84119
  "button",
84084
84120
  {
84085
84121
  onClick: onConfirm,
@@ -84087,7 +84123,7 @@ function DeleteConfirm2({
84087
84123
  children: "Delete"
84088
84124
  }
84089
84125
  ),
84090
- /* @__PURE__ */ jsx202(
84126
+ /* @__PURE__ */ jsx203(
84091
84127
  "button",
84092
84128
  {
84093
84129
  onClick: onCancel,
@@ -84129,7 +84165,7 @@ function isPointerClick(dx, dy) {
84129
84165
  }
84130
84166
 
84131
84167
  // src/components/sidebar/AudioRow.tsx
84132
- import { Fragment as Fragment54, jsx as jsx203, jsxs as jsxs162 } from "react/jsx-runtime";
84168
+ import { Fragment as Fragment54, jsx as jsx204, jsxs as jsxs163 } from "react/jsx-runtime";
84133
84169
  var stopCurrentPreview = null;
84134
84170
  function AudioRow({
84135
84171
  projectId,
@@ -84276,8 +84312,8 @@ function AudioRow({
84276
84312
  if (stopCurrentPreview === stopPlayback) stopCurrentPreview = null;
84277
84313
  }
84278
84314
  }, [serveUrl, playing, stopPlayback]);
84279
- return /* @__PURE__ */ jsxs162(Fragment54, { children: [
84280
- /* @__PURE__ */ jsxs162(
84315
+ return /* @__PURE__ */ jsxs163(Fragment54, { children: [
84316
+ /* @__PURE__ */ jsxs163(
84281
84317
  "div",
84282
84318
  {
84283
84319
  draggable: true,
@@ -84304,7 +84340,7 @@ function AudioRow({
84304
84340
  },
84305
84341
  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
84342
  children: [
84307
- /* @__PURE__ */ jsx203(
84343
+ /* @__PURE__ */ jsx204(
84308
84344
  "button",
84309
84345
  {
84310
84346
  "aria-label": playing ? `Pause preview of ${name}` : `Play preview of ${name}`,
@@ -84314,27 +84350,27 @@ function AudioRow({
84314
84350
  e.stopPropagation();
84315
84351
  togglePlay();
84316
84352
  },
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" }) })
84353
+ children: playing ? /* @__PURE__ */ jsxs163("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: [
84354
+ /* @__PURE__ */ jsx204("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
84355
+ /* @__PURE__ */ jsx204("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
84356
+ ] }) : /* @__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
84357
  }
84322
84358
  ),
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(
84359
+ /* @__PURE__ */ jsxs163("div", { className: "min-w-0 flex-1", children: [
84360
+ /* @__PURE__ */ jsxs163("div", { className: "flex items-center gap-1.5", children: [
84361
+ /* @__PURE__ */ jsx204(
84326
84362
  "span",
84327
84363
  {
84328
84364
  className: `text-[12px] font-medium truncate ${used ? "text-panel-text-1" : "text-panel-text-3"}`,
84329
84365
  children: name
84330
84366
  }
84331
84367
  ),
84332
- !playing && /* @__PURE__ */ jsxs162("span", { className: "text-[11px] text-panel-text-5 shrink-0", children: [
84368
+ !playing && /* @__PURE__ */ jsxs163("span", { className: "text-[11px] text-panel-text-5 shrink-0", children: [
84333
84369
  meta?.duration ? `${meta.duration}s \xB7 ` : "",
84334
84370
  subtype
84335
84371
  ] }),
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(
84372
+ 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" }),
84373
+ (isCopied || copyFailed) && /* @__PURE__ */ jsx204(
84338
84374
  "span",
84339
84375
  {
84340
84376
  role: "status",
@@ -84343,7 +84379,7 @@ function AudioRow({
84343
84379
  }
84344
84380
  )
84345
84381
  ] }),
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(
84382
+ 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
84383
  "div",
84348
84384
  {
84349
84385
  className: "flex-1 rounded-[1px]",
@@ -84359,7 +84395,7 @@ function AudioRow({
84359
84395
  ]
84360
84396
  }
84361
84397
  ),
84362
- contextMenu && /* @__PURE__ */ jsx203(
84398
+ contextMenu && /* @__PURE__ */ jsx204(
84363
84399
  ContextMenu3,
84364
84400
  {
84365
84401
  x: contextMenu.x,
@@ -84377,7 +84413,7 @@ function AudioRow({
84377
84413
 
84378
84414
  // src/components/sidebar/GlobalAssetsView.tsx
84379
84415
  import { useEffect as useEffect130, useMemo as useMemo73, useState as useState130 } from "react";
84380
- import { jsx as jsx204, jsxs as jsxs163 } from "react/jsx-runtime";
84416
+ import { jsx as jsx205, jsxs as jsxs164 } from "react/jsx-runtime";
84381
84417
  function globalAssetRows(records, query = "") {
84382
84418
  const q = query.trim().toLowerCase();
84383
84419
  return records.filter(
@@ -84405,28 +84441,28 @@ function GlobalAssetsView({ searchQuery }) {
84405
84441
  }, []);
84406
84442
  const rows = useMemo73(() => globalAssetRows(records ?? [], searchQuery), [records, searchQuery]);
84407
84443
  if (records === null) {
84408
- return /* @__PURE__ */ jsx204("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: "Loading global assets\u2026" });
84444
+ return /* @__PURE__ */ jsx205("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: "Loading global assets\u2026" });
84409
84445
  }
84410
84446
  if (rows.length === 0) {
84411
- return /* @__PURE__ */ jsxs163("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: [
84447
+ return /* @__PURE__ */ jsxs164("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: [
84412
84448
  "No assets in the global cache yet. Resolved media is promoted to ",
84413
- /* @__PURE__ */ jsx204("code", { children: "~/.media" }),
84449
+ /* @__PURE__ */ jsx205("code", { children: "~/.media" }),
84414
84450
  " and becomes reusable across projects."
84415
84451
  ] });
84416
84452
  }
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: [
84453
+ return /* @__PURE__ */ jsxs164("div", { children: [
84454
+ /* @__PURE__ */ jsxs164("div", { className: "px-4 py-2 border-t border-panel-border text-[11px] text-panel-text-5", children: [
84419
84455
  rows.length,
84420
84456
  " reusable across all projects"
84421
84457
  ] }),
84422
- rows.map((row) => /* @__PURE__ */ jsxs163(
84458
+ rows.map((row) => /* @__PURE__ */ jsxs164(
84423
84459
  "div",
84424
84460
  {
84425
84461
  className: "px-4 py-1.5 flex items-center gap-2.5 border-l-2 border-transparent hover:bg-neutral-800/50",
84426
84462
  title: `${row.id} \xB7 ${row.type}`,
84427
84463
  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 })
84464
+ /* @__PURE__ */ jsx205("span", { className: "text-[9px] font-medium text-neutral-600 uppercase w-10 shrink-0", children: row.type }),
84465
+ /* @__PURE__ */ jsx205("span", { className: "text-xs text-panel-text-1 truncate", children: row.label })
84430
84466
  ]
84431
84467
  },
84432
84468
  row.id
@@ -84439,7 +84475,7 @@ import { useState as useState132, useEffect as useEffect132, useRef as useRef169
84439
84475
 
84440
84476
  // src/components/ui/VideoFrameThumbnail.tsx
84441
84477
  import { useState as useState131, useEffect as useEffect131 } from "react";
84442
- import { jsx as jsx205 } from "react/jsx-runtime";
84478
+ import { jsx as jsx206 } from "react/jsx-runtime";
84443
84479
  function VideoFrameThumbnail({
84444
84480
  src,
84445
84481
  fallbackLabel
@@ -84481,16 +84517,16 @@ function VideoFrameThumbnail({
84481
84517
  return cleanup;
84482
84518
  }, [src]);
84483
84519
  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" }) });
84520
+ 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
84521
  }
84486
84522
  if (!frame) {
84487
- return /* @__PURE__ */ jsx205("div", { className: "w-full h-full bg-neutral-800 animate-pulse motion-reduce:animate-none" });
84523
+ return /* @__PURE__ */ jsx206("div", { className: "w-full h-full bg-neutral-800 animate-pulse motion-reduce:animate-none" });
84488
84524
  }
84489
- return /* @__PURE__ */ jsx205("img", { src: frame, alt: "", draggable: false, className: "w-full h-full object-contain" });
84525
+ return /* @__PURE__ */ jsx206("img", { src: frame, alt: "", draggable: false, className: "w-full h-full object-contain" });
84490
84526
  }
84491
84527
 
84492
84528
  // src/components/sidebar/AssetCard.tsx
84493
- import { Fragment as Fragment55, jsx as jsx206, jsxs as jsxs164 } from "react/jsx-runtime";
84529
+ import { Fragment as Fragment55, jsx as jsx207, jsxs as jsxs165 } from "react/jsx-runtime";
84494
84530
  function writeAssetDragData(e, asset) {
84495
84531
  e.dataTransfer.effectAllowed = "copy";
84496
84532
  e.dataTransfer.setData(TIMELINE_ASSET_MIME, JSON.stringify({ path: asset }));
@@ -84498,7 +84534,7 @@ function writeAssetDragData(e, asset) {
84498
84534
  }
84499
84535
  function CopyChip({ feedback, asset }) {
84500
84536
  if (feedback?.path !== asset) return null;
84501
- return /* @__PURE__ */ jsx206(
84537
+ return /* @__PURE__ */ jsx207(
84502
84538
  "span",
84503
84539
  {
84504
84540
  role: "status",
@@ -84617,8 +84653,8 @@ function AssetCard({
84617
84653
  },
84618
84654
  [activateCard]
84619
84655
  );
84620
- return /* @__PURE__ */ jsxs164(Fragment55, { children: [
84621
- /* @__PURE__ */ jsxs164(
84656
+ return /* @__PURE__ */ jsxs165(Fragment55, { children: [
84657
+ /* @__PURE__ */ jsxs165(
84622
84658
  "div",
84623
84659
  {
84624
84660
  draggable: true,
@@ -84640,8 +84676,8 @@ function AssetCard({
84640
84676
  onPointerLeave: () => setHovered(false),
84641
84677
  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
84678
  children: [
84643
- /* @__PURE__ */ jsxs164("div", { className: "w-full aspect-video rounded-sm overflow-hidden bg-neutral-900 relative", children: [
84644
- isImage && !imgError && /* @__PURE__ */ jsx206(
84679
+ /* @__PURE__ */ jsxs165("div", { className: "w-full aspect-video rounded-sm overflow-hidden bg-neutral-900 relative", children: [
84680
+ isImage && !imgError && /* @__PURE__ */ jsx207(
84645
84681
  "img",
84646
84682
  {
84647
84683
  src: serveUrl,
@@ -84651,9 +84687,9 @@ function AssetCard({
84651
84687
  onError: () => setImgError(true)
84652
84688
  }
84653
84689
  ),
84654
- isVideo && /* @__PURE__ */ jsxs164(Fragment55, { children: [
84655
- /* @__PURE__ */ jsx206(VideoFrameThumbnail, { src: serveUrl }),
84656
- hovered && /* @__PURE__ */ jsx206(
84690
+ isVideo && /* @__PURE__ */ jsxs165(Fragment55, { children: [
84691
+ /* @__PURE__ */ jsx207(VideoFrameThumbnail, { src: serveUrl }),
84692
+ hovered && /* @__PURE__ */ jsx207(
84657
84693
  "video",
84658
84694
  {
84659
84695
  src: serveUrl,
@@ -84665,12 +84701,12 @@ function AssetCard({
84665
84701
  }
84666
84702
  )
84667
84703
  ] }),
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 })
84704
+ (!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 }) }),
84705
+ 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" }),
84706
+ 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
84707
  ] }),
84672
- /* @__PURE__ */ jsxs164("div", { className: "flex items-center justify-center gap-1", children: [
84673
- /* @__PURE__ */ jsx206(
84708
+ /* @__PURE__ */ jsxs165("div", { className: "flex items-center justify-center gap-1", children: [
84709
+ /* @__PURE__ */ jsx207(
84674
84710
  "span",
84675
84711
  {
84676
84712
  className: `text-[10px] leading-tight text-center ${used ? "text-panel-text-2" : "text-panel-text-4"}`,
@@ -84678,12 +84714,12 @@ function AssetCard({
84678
84714
  children: truncateMiddle(fullName, 22)
84679
84715
  }
84680
84716
  ),
84681
- /* @__PURE__ */ jsx206(CopyChip, { feedback: copyFeedback, asset })
84717
+ /* @__PURE__ */ jsx207(CopyChip, { feedback: copyFeedback, asset })
84682
84718
  ] })
84683
84719
  ]
84684
84720
  }
84685
84721
  ),
84686
- contextMenu && /* @__PURE__ */ jsx206(
84722
+ contextMenu && /* @__PURE__ */ jsx207(
84687
84723
  ContextMenu3,
84688
84724
  {
84689
84725
  x: contextMenu.x,
@@ -84711,8 +84747,8 @@ function FontRow({
84711
84747
  const name = basename2(asset);
84712
84748
  const extension = ext(asset);
84713
84749
  const isCopied = copyFeedback?.path === asset && copyFeedback.ok;
84714
- return /* @__PURE__ */ jsxs164(Fragment55, { children: [
84715
- /* @__PURE__ */ jsxs164(
84750
+ return /* @__PURE__ */ jsxs165(Fragment55, { children: [
84751
+ /* @__PURE__ */ jsxs165(
84716
84752
  "div",
84717
84753
  {
84718
84754
  draggable: true,
@@ -84731,25 +84767,25 @@ function FontRow({
84731
84767
  onContextMenu: (e) => openAssetContextMenu(e, setContextMenu),
84732
84768
  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
84769
  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(
84770
+ /* @__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 }) }),
84771
+ /* @__PURE__ */ jsxs165("div", { className: "min-w-0 flex-1", children: [
84772
+ /* @__PURE__ */ jsx207(
84737
84773
  "span",
84738
84774
  {
84739
84775
  className: `text-xs font-medium truncate block ${used ? "text-panel-text-1" : "text-panel-text-3"}`,
84740
84776
  children: name
84741
84777
  }
84742
84778
  ),
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 })
84779
+ /* @__PURE__ */ jsxs165("div", { className: "flex items-center gap-1.5", children: [
84780
+ /* @__PURE__ */ jsx207("span", { className: "text-[10px] text-neutral-600 truncate", children: extension }),
84781
+ 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" }),
84782
+ /* @__PURE__ */ jsx207(CopyChip, { feedback: copyFeedback, asset })
84747
84783
  ] })
84748
84784
  ] })
84749
84785
  ]
84750
84786
  }
84751
84787
  ),
84752
- contextMenu && /* @__PURE__ */ jsx206(
84788
+ contextMenu && /* @__PURE__ */ jsx207(
84753
84789
  ContextMenu3,
84754
84790
  {
84755
84791
  x: contextMenu.x,
@@ -84766,7 +84802,7 @@ function FontRow({
84766
84802
  }
84767
84803
 
84768
84804
  // src/components/sidebar/AssetsTab.tsx
84769
- import { Fragment as Fragment56, jsx as jsx207, jsxs as jsxs165 } from "react/jsx-runtime";
84805
+ import { Fragment as Fragment56, jsx as jsx208, jsxs as jsxs166 } from "react/jsx-runtime";
84770
84806
  function filterByUsage(assets, usedPaths, usageFilter) {
84771
84807
  if (usageFilter === "used") return assets.filter((a) => usedPaths.has(a));
84772
84808
  if (usageFilter === "unused") return assets.filter((a) => !usedPaths.has(a));
@@ -84797,7 +84833,7 @@ function deriveUsedPaths(elements) {
84797
84833
  return paths;
84798
84834
  }
84799
84835
  function ImportButton({ importing, onClick }) {
84800
- return /* @__PURE__ */ jsxs165(
84836
+ return /* @__PURE__ */ jsxs166(
84801
84837
  "button",
84802
84838
  {
84803
84839
  onClick,
@@ -84805,8 +84841,8 @@ function ImportButton({ importing, onClick }) {
84805
84841
  "aria-busy": importing,
84806
84842
  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
84843
  children: [
84808
- importing ? /* @__PURE__ */ jsxs165("svg", { className: "animate-spin", width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: [
84809
- /* @__PURE__ */ jsx207(
84844
+ importing ? /* @__PURE__ */ jsxs166("svg", { className: "animate-spin", width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: [
84845
+ /* @__PURE__ */ jsx208(
84810
84846
  "circle",
84811
84847
  {
84812
84848
  className: "opacity-25",
@@ -84817,7 +84853,7 @@ function ImportButton({ importing, onClick }) {
84817
84853
  strokeWidth: "4"
84818
84854
  }
84819
84855
  ),
84820
- /* @__PURE__ */ jsx207(
84856
+ /* @__PURE__ */ jsx208(
84821
84857
  "path",
84822
84858
  {
84823
84859
  className: "opacity-75",
@@ -84825,7 +84861,7 @@ function ImportButton({ importing, onClick }) {
84825
84861
  d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
84826
84862
  }
84827
84863
  )
84828
- ] }) : /* @__PURE__ */ jsx207(
84864
+ ] }) : /* @__PURE__ */ jsx208(
84829
84865
  "svg",
84830
84866
  {
84831
84867
  width: "11",
@@ -84835,7 +84871,7 @@ function ImportButton({ importing, onClick }) {
84835
84871
  stroke: "currentColor",
84836
84872
  strokeWidth: "2.5",
84837
84873
  strokeLinecap: "round",
84838
- children: /* @__PURE__ */ jsx207("path", { d: "M12 5v14M5 12h14" })
84874
+ children: /* @__PURE__ */ jsx208("path", { d: "M12 5v14M5 12h14" })
84839
84875
  }
84840
84876
  ),
84841
84877
  importing ? "Importing\u2026" : "Import media"
@@ -84848,13 +84884,13 @@ function EmptyState({
84848
84884
  onClearSearch
84849
84885
  }) {
84850
84886
  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: [
84887
+ return /* @__PURE__ */ jsxs166("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84888
+ /* @__PURE__ */ jsxs166("p", { className: "text-[11px] text-neutral-500 text-center", children: [
84853
84889
  "No assets match \u201C",
84854
84890
  searchQuery,
84855
84891
  "\u201D"
84856
84892
  ] }),
84857
- /* @__PURE__ */ jsx207(
84893
+ /* @__PURE__ */ jsx208(
84858
84894
  "button",
84859
84895
  {
84860
84896
  type: "button",
@@ -84865,8 +84901,8 @@ function EmptyState({
84865
84901
  )
84866
84902
  ] });
84867
84903
  }
84868
- return /* @__PURE__ */ jsxs165("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84869
- /* @__PURE__ */ jsxs165(
84904
+ return /* @__PURE__ */ jsxs166("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
84905
+ /* @__PURE__ */ jsxs166(
84870
84906
  "svg",
84871
84907
  {
84872
84908
  width: "24",
@@ -84877,7 +84913,7 @@ function EmptyState({
84877
84913
  strokeWidth: "1.5",
84878
84914
  className: "text-neutral-700",
84879
84915
  children: [
84880
- /* @__PURE__ */ jsx207(
84916
+ /* @__PURE__ */ jsx208(
84881
84917
  "path",
84882
84918
  {
84883
84919
  d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4",
@@ -84885,12 +84921,12 @@ function EmptyState({
84885
84921
  strokeLinejoin: "round"
84886
84922
  }
84887
84923
  ),
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" })
84924
+ /* @__PURE__ */ jsx208("polyline", { points: "17 8 12 3 7 8", strokeLinecap: "round", strokeLinejoin: "round" }),
84925
+ /* @__PURE__ */ jsx208("line", { x1: "12", y1: "3", x2: "12", y2: "15", strokeLinecap: "round" })
84890
84926
  ]
84891
84927
  }
84892
84928
  ),
84893
- /* @__PURE__ */ jsx207("p", { className: "text-[10px] text-neutral-600 text-center", children: "Drop media files here" })
84929
+ /* @__PURE__ */ jsx208("p", { className: "text-[10px] text-neutral-600 text-center", children: "Drop media files here" })
84894
84930
  ] });
84895
84931
  }
84896
84932
  var AssetsTab = memo41(function AssetsTab2({
@@ -85008,7 +85044,7 @@ var AssetsTab = memo41(function AssetsTab2({
85008
85044
  [assets, usedPaths]
85009
85045
  );
85010
85046
  const visibleCategories = activeFilter === "all" ? FILTER_ORDER.filter((c) => categorized[c].length > 0) : [activeFilter].filter((c) => categorized[c].length > 0);
85011
- return /* @__PURE__ */ jsxs165(
85047
+ return /* @__PURE__ */ jsxs166(
85012
85048
  "div",
85013
85049
  {
85014
85050
  className: `flex-1 flex flex-col min-h-0 transition-colors ${dragOver ? "bg-studio-accent/5" : ""}`,
@@ -85019,8 +85055,8 @@ var AssetsTab = memo41(function AssetsTab2({
85019
85055
  onDragLeave: () => setDragOver(false),
85020
85056
  onDrop: handleDrop,
85021
85057
  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(
85058
+ /* @__PURE__ */ jsxs166("div", { className: "px-4 pt-2.5 pb-1.5 shrink-0", children: [
85059
+ /* @__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
85060
  "button",
85025
85061
  {
85026
85062
  onClick: () => setViewMode(m),
@@ -85029,9 +85065,9 @@ var AssetsTab = memo41(function AssetsTab2({
85029
85065
  },
85030
85066
  m
85031
85067
  )) }),
85032
- onImport && /* @__PURE__ */ jsxs165(Fragment56, { children: [
85033
- /* @__PURE__ */ jsx207(ImportButton, { importing, onClick: () => fileInputRef.current?.click() }),
85034
- /* @__PURE__ */ jsx207(
85068
+ onImport && /* @__PURE__ */ jsxs166(Fragment56, { children: [
85069
+ /* @__PURE__ */ jsx208(ImportButton, { importing, onClick: () => fileInputRef.current?.click() }),
85070
+ /* @__PURE__ */ jsx208(
85035
85071
  "input",
85036
85072
  {
85037
85073
  ref: fileInputRef,
@@ -85048,7 +85084,7 @@ var AssetsTab = memo41(function AssetsTab2({
85048
85084
  }
85049
85085
  )
85050
85086
  ] }),
85051
- allMediaAssets.length > 0 && /* @__PURE__ */ jsx207(
85087
+ allMediaAssets.length > 0 && /* @__PURE__ */ jsx208(
85052
85088
  SearchInput,
85053
85089
  {
85054
85090
  value: searchQuery,
@@ -85058,8 +85094,8 @@ var AssetsTab = memo41(function AssetsTab2({
85058
85094
  className: "mb-2"
85059
85095
  }
85060
85096
  ),
85061
- viewMode === "local" && allMediaAssets.length > 0 && /* @__PURE__ */ jsxs165("div", { className: "flex gap-1.5 flex-wrap", children: [
85062
- /* @__PURE__ */ jsxs165(
85097
+ viewMode === "local" && allMediaAssets.length > 0 && /* @__PURE__ */ jsxs166("div", { className: "flex gap-1.5 flex-wrap", children: [
85098
+ /* @__PURE__ */ jsxs166(
85063
85099
  "button",
85064
85100
  {
85065
85101
  onClick: () => setActiveFilter("all"),
@@ -85072,7 +85108,7 @@ var AssetsTab = memo41(function AssetsTab2({
85072
85108
  }
85073
85109
  ),
85074
85110
  FILTER_ORDER.map(
85075
- (cat) => counts[cat] > 0 ? /* @__PURE__ */ jsxs165(
85111
+ (cat) => counts[cat] > 0 ? /* @__PURE__ */ jsxs166(
85076
85112
  "button",
85077
85113
  {
85078
85114
  onClick: () => setActiveFilter(activeFilter === cat ? "all" : cat),
@@ -85087,9 +85123,9 @@ var AssetsTab = memo41(function AssetsTab2({
85087
85123
  cat
85088
85124
  ) : null
85089
85125
  ),
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(
85126
+ usageCounts.used > 0 && usageCounts.unused > 0 && /* @__PURE__ */ jsxs166(Fragment56, { children: [
85127
+ /* @__PURE__ */ jsx208("span", { className: "w-px self-stretch bg-panel-input mx-0.5", "aria-hidden": "true" }),
85128
+ /* @__PURE__ */ jsxs166(
85093
85129
  "button",
85094
85130
  {
85095
85131
  onClick: () => setUsageFilter(usageFilter === "used" ? "all" : "used"),
@@ -85100,7 +85136,7 @@ var AssetsTab = memo41(function AssetsTab2({
85100
85136
  ]
85101
85137
  }
85102
85138
  ),
85103
- /* @__PURE__ */ jsxs165(
85139
+ /* @__PURE__ */ jsxs166(
85104
85140
  "button",
85105
85141
  {
85106
85142
  onClick: () => setUsageFilter(usageFilter === "unused" ? "all" : "unused"),
@@ -85114,12 +85150,12 @@ var AssetsTab = memo41(function AssetsTab2({
85114
85150
  ] })
85115
85151
  ] })
85116
85152
  ] }),
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 })
85153
+ /* @__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: [
85154
+ activeFilter === "all" && /* @__PURE__ */ jsxs166("div", { className: "flex items-center gap-2 px-4 py-2 border-t border-panel-border", children: [
85155
+ /* @__PURE__ */ jsx208("h3", { className: "text-[12px] font-semibold text-panel-text-1", children: CATEGORY_LABELS[cat] }),
85156
+ /* @__PURE__ */ jsx208("span", { className: "text-[11px] text-panel-text-5", children: categorized[cat].length })
85121
85157
  ] }),
85122
- cat === "audio" && categorized[cat].map((a) => /* @__PURE__ */ jsx207(
85158
+ cat === "audio" && categorized[cat].map((a) => /* @__PURE__ */ jsx208(
85123
85159
  AudioRow,
85124
85160
  {
85125
85161
  projectId,
@@ -85134,7 +85170,7 @@ var AssetsTab = memo41(function AssetsTab2({
85134
85170
  },
85135
85171
  a
85136
85172
  )),
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(
85173
+ (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
85174
  AssetCard,
85139
85175
  {
85140
85176
  projectId,
@@ -85149,7 +85185,7 @@ var AssetsTab = memo41(function AssetsTab2({
85149
85185
  },
85150
85186
  a
85151
85187
  )) }),
85152
- cat === "fonts" && categorized[cat].map((a) => /* @__PURE__ */ jsx207(
85188
+ cat === "fonts" && categorized[cat].map((a) => /* @__PURE__ */ jsx208(
85153
85189
  FontRow,
85154
85190
  {
85155
85191
  asset: a,
@@ -85174,7 +85210,7 @@ import { createPortal as createPortal9 } from "react-dom";
85174
85210
 
85175
85211
  // src/components/sidebar/PromptPreviewModal.tsx
85176
85212
  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";
85213
+ import { jsx as jsx209, jsxs as jsxs167 } from "react/jsx-runtime";
85178
85214
  function PromptPreviewModal({
85179
85215
  title,
85180
85216
  prompt,
@@ -85208,12 +85244,12 @@ function PromptPreviewModal({
85208
85244
  }
85209
85245
  setTimeout(() => setCopyState("idle"), 1500);
85210
85246
  }, []);
85211
- return /* @__PURE__ */ jsx208(
85247
+ return /* @__PURE__ */ jsx209(
85212
85248
  "div",
85213
85249
  {
85214
85250
  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
85251
  onClick: requestClose,
85216
- children: /* @__PURE__ */ jsxs166(
85252
+ children: /* @__PURE__ */ jsxs167(
85217
85253
  "div",
85218
85254
  {
85219
85255
  ref: containerRef,
@@ -85224,18 +85260,18 @@ function PromptPreviewModal({
85224
85260
  className: "w-[560px] max-h-[80vh] flex flex-col rounded-2xl border border-neutral-800 bg-neutral-950 shadow-2xl outline-hidden",
85225
85261
  onClick: (e) => e.stopPropagation(),
85226
85262
  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 })
85263
+ /* @__PURE__ */ jsxs167("div", { className: "flex items-center justify-between px-5 py-4 border-b border-neutral-800/60", children: [
85264
+ /* @__PURE__ */ jsxs167("div", { children: [
85265
+ /* @__PURE__ */ jsx209("h3", { className: "text-sm font-medium text-neutral-200", children: "Ask agent" }),
85266
+ /* @__PURE__ */ jsx209("p", { className: "text-xs text-neutral-500 mt-0.5", children: title })
85231
85267
  ] }),
85232
- /* @__PURE__ */ jsx208(
85268
+ /* @__PURE__ */ jsx209(
85233
85269
  "button",
85234
85270
  {
85235
85271
  "aria-label": "Close",
85236
85272
  className: "p-1 rounded-md text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800/50 active:scale-[0.95]",
85237
85273
  onClick: onClose,
85238
- children: /* @__PURE__ */ jsxs166(
85274
+ children: /* @__PURE__ */ jsxs167(
85239
85275
  "svg",
85240
85276
  {
85241
85277
  width: "14",
@@ -85247,17 +85283,17 @@ function PromptPreviewModal({
85247
85283
  strokeLinecap: "round",
85248
85284
  "aria-hidden": "true",
85249
85285
  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" })
85286
+ /* @__PURE__ */ jsx209("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
85287
+ /* @__PURE__ */ jsx209("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
85252
85288
  ]
85253
85289
  }
85254
85290
  )
85255
85291
  }
85256
85292
  )
85257
85293
  ] }),
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(
85294
+ /* @__PURE__ */ jsxs167("div", { className: "flex-1 overflow-y-auto px-5 py-4", children: [
85295
+ /* @__PURE__ */ jsx209("p", { className: "text-[11px] text-neutral-500 mb-2", children: "Edit the prompt below, then copy and paste into your AI agent" }),
85296
+ /* @__PURE__ */ jsx209(
85261
85297
  "textarea",
85262
85298
  {
85263
85299
  ref: textareaRef,
@@ -85270,12 +85306,12 @@ function PromptPreviewModal({
85270
85306
  }
85271
85307
  )
85272
85308
  ] }),
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: [
85309
+ /* @__PURE__ */ jsxs167("div", { className: "flex items-center justify-between px-5 py-3 border-t border-neutral-800/60", children: [
85310
+ /* @__PURE__ */ jsxs167("span", { className: "text-[11px] text-neutral-600", children: [
85275
85311
  navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
85276
85312
  "+Enter to copy"
85277
85313
  ] }),
85278
- /* @__PURE__ */ jsx208(
85314
+ /* @__PURE__ */ jsx209(
85279
85315
  "button",
85280
85316
  {
85281
85317
  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 +85328,18 @@ function PromptPreviewModal({
85292
85328
  }
85293
85329
 
85294
85330
  // src/components/sidebar/BlocksTab.tsx
85295
- import { jsx as jsx209, jsxs as jsxs167 } from "react/jsx-runtime";
85331
+ import { jsx as jsx210, jsxs as jsxs168 } from "react/jsx-runtime";
85296
85332
  var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85297
85333
  const { loading, error, search, setSearch, category, setCategory, filteredBlocks } = useBlockCatalog();
85298
85334
  const [promptModal, setPromptModal] = useState135(null);
85299
85335
  if (loading) {
85300
- return /* @__PURE__ */ jsx209("div", { className: "flex flex-1 items-center justify-center text-neutral-600 text-xs", children: "Loading blocks\u2026" });
85336
+ return /* @__PURE__ */ jsx210("div", { className: "flex flex-1 items-center justify-center text-neutral-600 text-xs", children: "Loading blocks\u2026" });
85301
85337
  }
85302
85338
  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 });
85339
+ return /* @__PURE__ */ jsx210("div", { className: "flex flex-1 items-center justify-center text-red-400 text-xs px-4 text-center", children: error });
85304
85340
  }
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(
85341
+ return /* @__PURE__ */ jsxs168("div", { className: "flex flex-col flex-1 min-h-0", children: [
85342
+ /* @__PURE__ */ jsx210("div", { className: "px-3 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx210(
85307
85343
  SearchInput,
85308
85344
  {
85309
85345
  value: search,
@@ -85312,9 +85348,9 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85312
85348
  "aria-label": "Search blocks"
85313
85349
  }
85314
85350
  ) }),
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(
85351
+ /* @__PURE__ */ jsx210("div", { className: "px-3 pt-1 pb-2 shrink-0 overflow-x-auto", children: /* @__PURE__ */ jsxs168("div", { className: "flex gap-1", children: [
85352
+ /* @__PURE__ */ jsx210(CategoryPill, { label: "All", active: category === null, onClick: () => setCategory(null) }),
85353
+ BLOCK_CATEGORIES.map((cat) => /* @__PURE__ */ jsx210(
85318
85354
  CategoryPill,
85319
85355
  {
85320
85356
  label: cat.label,
@@ -85325,21 +85361,21 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85325
85361
  cat.id
85326
85362
  ))
85327
85363
  ] }) }),
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: [
85364
+ /* @__PURE__ */ jsxs168("div", { className: "flex-1 overflow-y-auto min-h-0 px-2 pb-2", children: [
85365
+ 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
85366
  "VFX blocks use WebGL via HTML-in-Canvas. Enable",
85331
85367
  " ",
85332
- /* @__PURE__ */ jsx209("span", { className: "font-mono text-purple-200", children: "chrome://flags/#html-in-canvas" }),
85368
+ /* @__PURE__ */ jsx210("span", { className: "font-mono text-purple-200", children: "chrome://flags/#html-in-canvas" }),
85333
85369
  " for preview."
85334
85370
  ] }),
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(
85371
+ 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
85372
  "div",
85337
85373
  {
85338
85374
  className: "grid gap-1.5",
85339
85375
  style: { gridTemplateColumns: "repeat(auto-fill, minmax(120px, 1fr))" },
85340
85376
  children: filteredBlocks.map((block) => {
85341
85377
  const dur = "duration" in block ? block.duration : void 0;
85342
- return /* @__PURE__ */ jsx209(
85378
+ return /* @__PURE__ */ jsx210(
85343
85379
  BlockCard,
85344
85380
  {
85345
85381
  name: block.name,
@@ -85362,7 +85398,7 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85362
85398
  )
85363
85399
  ] }),
85364
85400
  promptModal && createPortal9(
85365
- /* @__PURE__ */ jsx209(
85401
+ /* @__PURE__ */ jsx210(
85366
85402
  PromptPreviewModal,
85367
85403
  {
85368
85404
  title: promptModal.title,
@@ -85381,7 +85417,7 @@ function CategoryPill({
85381
85417
  onClick
85382
85418
  }) {
85383
85419
  const colors = category ? getCategoryColors(category) : null;
85384
- return /* @__PURE__ */ jsx209(
85420
+ return /* @__PURE__ */ jsx210(
85385
85421
  "button",
85386
85422
  {
85387
85423
  type: "button",
@@ -85551,7 +85587,7 @@ function BlockCard({
85551
85587
  onShowPrompt
85552
85588
  ]
85553
85589
  );
85554
- return /* @__PURE__ */ jsxs167(
85590
+ return /* @__PURE__ */ jsxs168(
85555
85591
  "div",
85556
85592
  {
85557
85593
  className: "group/card rounded-md overflow-hidden cursor-pointer transition-colors bg-neutral-900 hover:bg-neutral-800",
@@ -85565,8 +85601,8 @@ function BlockCard({
85565
85601
  onPointerEnter: handleEnter,
85566
85602
  onPointerLeave: handleLeave,
85567
85603
  children: [
85568
- /* @__PURE__ */ jsxs167("div", { className: "aspect-video w-full overflow-hidden relative", children: [
85569
- hovered && videoUrl ? /* @__PURE__ */ jsx209(
85604
+ /* @__PURE__ */ jsxs168("div", { className: "aspect-video w-full overflow-hidden relative", children: [
85605
+ hovered && videoUrl ? /* @__PURE__ */ jsx210(
85570
85606
  "video",
85571
85607
  {
85572
85608
  src: videoUrl,
@@ -85576,7 +85612,7 @@ function BlockCard({
85576
85612
  playsInline: true,
85577
85613
  className: "w-full h-full object-cover"
85578
85614
  }
85579
- ) : posterUrl ? /* @__PURE__ */ jsx209("img", { src: posterUrl, alt: title, loading: "lazy", className: "w-full h-full object-cover" }) : videoUrl ? /* @__PURE__ */ jsx209(
85615
+ ) : posterUrl ? /* @__PURE__ */ jsx210("img", { src: posterUrl, alt: title, loading: "lazy", className: "w-full h-full object-cover" }) : videoUrl ? /* @__PURE__ */ jsx210(
85580
85616
  "video",
85581
85617
  {
85582
85618
  src: videoUrl,
@@ -85585,9 +85621,9 @@ function BlockCard({
85585
85621
  preload: "metadata",
85586
85622
  className: "w-full h-full object-cover"
85587
85623
  }
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(
85624
+ ) : /* @__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() }) }),
85625
+ /* @__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: [
85626
+ onAdd && /* @__PURE__ */ jsxs168(
85591
85627
  "button",
85592
85628
  {
85593
85629
  type: "button",
@@ -85595,7 +85631,7 @@ function BlockCard({
85595
85631
  title: "Add to composition at current time",
85596
85632
  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
85633
  children: [
85598
- /* @__PURE__ */ jsx209(
85634
+ /* @__PURE__ */ jsx210(
85599
85635
  "svg",
85600
85636
  {
85601
85637
  width: "10",
@@ -85604,14 +85640,14 @@ function BlockCard({
85604
85640
  fill: "none",
85605
85641
  stroke: "currentColor",
85606
85642
  strokeWidth: "2.5",
85607
- children: /* @__PURE__ */ jsx209("path", { d: "M12 5v14M5 12h14" })
85643
+ children: /* @__PURE__ */ jsx210("path", { d: "M12 5v14M5 12h14" })
85608
85644
  }
85609
85645
  ),
85610
85646
  addState === "adding" ? "Adding\u2026" : addState === "added" ? "Added!" : addState === "failed" ? "Failed" : "Add"
85611
85647
  ]
85612
85648
  }
85613
85649
  ),
85614
- /* @__PURE__ */ jsxs167(
85650
+ /* @__PURE__ */ jsxs168(
85615
85651
  "button",
85616
85652
  {
85617
85653
  type: "button",
@@ -85619,7 +85655,7 @@ function BlockCard({
85619
85655
  title: "Generate a prompt to paste into your AI agent",
85620
85656
  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
85657
  children: [
85622
- /* @__PURE__ */ jsxs167(
85658
+ /* @__PURE__ */ jsxs168(
85623
85659
  "svg",
85624
85660
  {
85625
85661
  width: onAdd ? 9 : 11,
@@ -85629,8 +85665,8 @@ function BlockCard({
85629
85665
  stroke: "currentColor",
85630
85666
  strokeWidth: "2",
85631
85667
  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" })
85668
+ /* @__PURE__ */ jsx210("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
85669
+ /* @__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
85670
  ]
85635
85671
  }
85636
85672
  ),
@@ -85639,19 +85675,19 @@ function BlockCard({
85639
85675
  }
85640
85676
  )
85641
85677
  ] }),
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: [
85678
+ /* @__PURE__ */ jsxs168("div", { className: "absolute top-1 right-1 flex items-center gap-0.5 pointer-events-none", children: [
85679
+ needsWebGL && /* @__PURE__ */ jsx210("span", { className: "px-1 py-px rounded-sm text-[7px] font-semibold text-purple-300 bg-purple-900/70", children: "WebGL" }),
85680
+ duration != null && /* @__PURE__ */ jsxs168("span", { className: "px-1 py-px rounded-sm text-[8px] font-medium text-white/80 bg-black/50", children: [
85645
85681
  duration,
85646
85682
  "s"
85647
85683
  ] })
85648
85684
  ] })
85649
85685
  ] }),
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 })
85686
+ /* @__PURE__ */ jsxs168("div", { className: "px-1.5 py-1.5", children: [
85687
+ /* @__PURE__ */ jsx210("div", { className: "text-[10px] font-medium text-neutral-200 truncate leading-tight", children: title }),
85688
+ /* @__PURE__ */ jsxs168("div", { className: "flex items-center gap-1 mt-0.5", children: [
85689
+ /* @__PURE__ */ jsx210("span", { className: `w-1.5 h-1.5 rounded-full shrink-0 ${colors.dot}` }),
85690
+ /* @__PURE__ */ jsx210("span", { className: `text-[8px] ${colors.text}`, children: BLOCK_CATEGORIES.find((c) => c.id === category)?.label })
85655
85691
  ] })
85656
85692
  ] })
85657
85693
  ]
@@ -85661,7 +85697,7 @@ function BlockCard({
85661
85697
 
85662
85698
  // src/components/sidebar/CompositionsTab.tsx
85663
85699
  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";
85700
+ import { jsx as jsx211, jsxs as jsxs169 } from "react/jsx-runtime";
85665
85701
  var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
85666
85702
  var CARD_W = 80;
85667
85703
  var CARD_H = 45;
@@ -85791,7 +85827,7 @@ function CompCard({
85791
85827
  if (syncTimer.current) clearTimeout(syncTimer.current);
85792
85828
  };
85793
85829
  }, []);
85794
- return /* @__PURE__ */ jsxs168(
85830
+ return /* @__PURE__ */ jsxs169(
85795
85831
  "div",
85796
85832
  {
85797
85833
  role: "button",
@@ -85823,8 +85859,8 @@ function CompCard({
85823
85859
  onPointerLeave: handleLeave,
85824
85860
  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
85861
  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(
85862
+ /* @__PURE__ */ jsxs169("div", { className: "w-20 h-[45px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 relative", children: [
85863
+ 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
85864
  "img",
85829
85865
  {
85830
85866
  src: thumbnailUrl2,
@@ -85836,7 +85872,7 @@ function CompCard({
85836
85872
  className: `absolute inset-0 h-full w-full object-contain transition-opacity ${livePreviewLoaded ? "opacity-0" : "opacity-100"}`
85837
85873
  }
85838
85874
  ),
85839
- hovered && /* @__PURE__ */ jsx210(
85875
+ hovered && /* @__PURE__ */ jsx211(
85840
85876
  "iframe",
85841
85877
  {
85842
85878
  ref: iframeRef,
@@ -85869,15 +85905,15 @@ function CompCard({
85869
85905
  }
85870
85906
  )
85871
85907
  ] }),
85872
- /* @__PURE__ */ jsxs168(
85908
+ /* @__PURE__ */ jsxs169(
85873
85909
  "div",
85874
85910
  {
85875
85911
  className: "min-w-0 flex-1",
85876
85912
  title: lintInfo && lintInfo.count > 0 ? lintInfo.messages.join("\n") : void 0,
85877
85913
  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(
85914
+ /* @__PURE__ */ jsxs169("div", { className: "flex items-center gap-1", children: [
85915
+ /* @__PURE__ */ jsx211("span", { className: "text-[11px] font-medium text-neutral-300 truncate", children: name }),
85916
+ isRoot && /* @__PURE__ */ jsx211(
85881
85917
  "span",
85882
85918
  {
85883
85919
  "aria-label": "Root composition \u2014 opens automatically on load",
@@ -85886,7 +85922,7 @@ function CompCard({
85886
85922
  children: "Root"
85887
85923
  }
85888
85924
  ),
85889
- lintInfo && lintInfo.count > 0 && /* @__PURE__ */ jsx210(
85925
+ lintInfo && lintInfo.count > 0 && /* @__PURE__ */ jsx211(
85890
85926
  "span",
85891
85927
  {
85892
85928
  "aria-label": `${lintInfo.count} lint finding${lintInfo.count === 1 ? "" : "s"}`,
@@ -85895,11 +85931,11 @@ function CompCard({
85895
85931
  }
85896
85932
  )
85897
85933
  ] }),
85898
- /* @__PURE__ */ jsx210("span", { className: "text-[9px] text-neutral-600 truncate block", children: comp })
85934
+ /* @__PURE__ */ jsx211("span", { className: "text-[9px] text-neutral-600 truncate block", children: comp })
85899
85935
  ]
85900
85936
  }
85901
85937
  ),
85902
- onAddToTimeline && /* @__PURE__ */ jsx210(
85938
+ onAddToTimeline && /* @__PURE__ */ jsx211(
85903
85939
  "button",
85904
85940
  {
85905
85941
  type: "button",
@@ -85910,10 +85946,10 @@ function CompCard({
85910
85946
  onAddToTimeline();
85911
85947
  },
85912
85948
  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: "+" })
85949
+ children: /* @__PURE__ */ jsx211("span", { "aria-hidden": "true", children: "+" })
85914
85950
  }
85915
85951
  ),
85916
- onRender && /* @__PURE__ */ jsx210(Tooltip, { label: isRendering ? "A render is already in progress" : `Render ${name}`, children: /* @__PURE__ */ jsx210(
85952
+ onRender && /* @__PURE__ */ jsx211(Tooltip, { label: isRendering ? "A render is already in progress" : `Render ${name}`, children: /* @__PURE__ */ jsx211(
85917
85953
  "button",
85918
85954
  {
85919
85955
  type: "button",
@@ -85924,7 +85960,7 @@ function CompCard({
85924
85960
  onRender();
85925
85961
  },
85926
85962
  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(
85963
+ children: /* @__PURE__ */ jsxs169(
85928
85964
  "svg",
85929
85965
  {
85930
85966
  width: "14",
@@ -85937,9 +85973,9 @@ function CompCard({
85937
85973
  strokeLinejoin: "round",
85938
85974
  "aria-hidden": "true",
85939
85975
  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" })
85976
+ /* @__PURE__ */ jsx211("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
85977
+ /* @__PURE__ */ jsx211("polyline", { points: "7 10 12 15 17 10" }),
85978
+ /* @__PURE__ */ jsx211("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
85943
85979
  ]
85944
85980
  }
85945
85981
  )
@@ -85962,9 +85998,9 @@ var CompositionsTab = memo43(function CompositionsTab2({
85962
85998
  }) {
85963
85999
  const thumbnailRevisions = usePlayerStore((state) => state.thumbnailRevisions);
85964
86000
  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" }) });
86001
+ 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
86002
  }
85967
- return /* @__PURE__ */ jsx210("div", { className: "flex-1 overflow-y-auto", children: compositions.map((comp) => /* @__PURE__ */ jsx210(
86003
+ return /* @__PURE__ */ jsx211("div", { className: "flex-1 overflow-y-auto", children: compositions.map((comp) => /* @__PURE__ */ jsx211(
85968
86004
  CompCard,
85969
86005
  {
85970
86006
  projectId,
@@ -85983,9 +86019,9 @@ var CompositionsTab = memo43(function CompositionsTab2({
85983
86019
  });
85984
86020
 
85985
86021
  // src/components/sidebar/CompositionsPanel.tsx
85986
- import { jsx as jsx211 } from "react/jsx-runtime";
86022
+ import { jsx as jsx212 } from "react/jsx-runtime";
85987
86023
  function CompositionsPanel(props) {
85988
- return /* @__PURE__ */ jsx211(
86024
+ return /* @__PURE__ */ jsx212(
85989
86025
  CompositionsTab,
85990
86026
  {
85991
86027
  ...props,
@@ -85995,14 +86031,14 @@ function CompositionsPanel(props) {
85995
86031
  }
85996
86032
 
85997
86033
  // src/components/sidebar/SidebarLintButton.tsx
85998
- import { jsx as jsx212, jsxs as jsxs169 } from "react/jsx-runtime";
86034
+ import { jsx as jsx213, jsxs as jsxs170 } from "react/jsx-runtime";
85999
86035
  function SidebarLintButton({
86000
86036
  onLint,
86001
86037
  linting,
86002
86038
  findingCount,
86003
86039
  hasError
86004
86040
  }) {
86005
- return /* @__PURE__ */ jsx212("div", { className: "border-t border-neutral-800 p-2 shrink-0", children: /* @__PURE__ */ jsxs169(
86041
+ return /* @__PURE__ */ jsx213("div", { className: "border-t border-neutral-800 p-2 shrink-0", children: /* @__PURE__ */ jsxs170(
86006
86042
  "button",
86007
86043
  {
86008
86044
  type: "button",
@@ -86010,7 +86046,7 @@ function SidebarLintButton({
86010
86046
  disabled: linting,
86011
86047
  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
86048
  children: [
86013
- /* @__PURE__ */ jsxs169(
86049
+ /* @__PURE__ */ jsxs170(
86014
86050
  "svg",
86015
86051
  {
86016
86052
  width: "12",
@@ -86020,20 +86056,20 @@ function SidebarLintButton({
86020
86056
  stroke: "currentColor",
86021
86057
  strokeWidth: "2",
86022
86058
  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" })
86059
+ /* @__PURE__ */ jsx213("path", { d: "M9 11l3 3L22 4" }),
86060
+ /* @__PURE__ */ jsx213("path", { d: "M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11" })
86025
86061
  ]
86026
86062
  }
86027
86063
  ),
86028
86064
  linting ? "Linting\u2026" : "Lint",
86029
- !linting && findingCount != null && findingCount > 0 && /* @__PURE__ */ jsxs169(
86065
+ !linting && findingCount != null && findingCount > 0 && /* @__PURE__ */ jsxs170(
86030
86066
  "span",
86031
86067
  {
86032
86068
  "data-lint-badge": hasError ? "error" : "warning",
86033
86069
  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
86070
  children: [
86035
86071
  findingCount,
86036
- /* @__PURE__ */ jsx212("span", { className: "sr-only", children: hasError ? " lint findings, including errors" : " lint findings, warnings only" })
86072
+ /* @__PURE__ */ jsx213("span", { className: "sr-only", children: hasError ? " lint findings, including errors" : " lint findings, warnings only" })
86037
86073
  ]
86038
86074
  }
86039
86075
  )
@@ -86067,10 +86103,10 @@ function persistRenderSettings(format, quality, fps) {
86067
86103
  }
86068
86104
 
86069
86105
  // src/components/StudioLeftPanels.tsx
86070
- import { Fragment as Fragment57, jsx as jsx213, jsxs as jsxs170 } from "react/jsx-runtime";
86106
+ import { Fragment as Fragment57, jsx as jsx214, jsxs as jsxs171 } from "react/jsx-runtime";
86071
86107
  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 }),
86108
+ return /* @__PURE__ */ jsxs171("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
86109
+ /* @__PURE__ */ jsx214("div", { className: "flex min-h-0 flex-1 flex-col", children }),
86074
86110
  footer
86075
86111
  ] });
86076
86112
  }
@@ -86118,7 +86154,7 @@ function StudioLeftPanels({
86118
86154
  const importFiles = async (files, dir) => {
86119
86155
  await handleImportFiles(files, dir);
86120
86156
  };
86121
- const lintButton = /* @__PURE__ */ jsx213(
86157
+ const lintButton = /* @__PURE__ */ jsx214(
86122
86158
  SidebarLintButton,
86123
86159
  {
86124
86160
  onLint,
@@ -86127,8 +86163,8 @@ function StudioLeftPanels({
86127
86163
  hasError: lintHasError
86128
86164
  }
86129
86165
  );
86130
- return /* @__PURE__ */ jsxs170(Fragment57, { children: [
86131
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "compositions", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx213(
86166
+ return /* @__PURE__ */ jsxs171(Fragment57, { children: [
86167
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "compositions", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx214(
86132
86168
  CompositionsPanel,
86133
86169
  {
86134
86170
  projectId,
@@ -86141,7 +86177,7 @@ function StudioLeftPanels({
86141
86177
  lintFindingsByFile
86142
86178
  }
86143
86179
  ) }) }),
86144
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "assets", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx213(
86180
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "assets", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx214(
86145
86181
  AssetsTab,
86146
86182
  {
86147
86183
  projectId,
@@ -86152,8 +86188,8 @@ function StudioLeftPanels({
86152
86188
  onAddAssetToTimeline
86153
86189
  }
86154
86190
  ) }) }),
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(
86191
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "code", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsxs171("div", { className: "flex min-h-0 flex-1", children: [
86192
+ fileTree.length > 0 && /* @__PURE__ */ jsx214("div", { className: "w-[160px] shrink-0 border-r border-neutral-800 overflow-y-auto", children: /* @__PURE__ */ jsx214(
86157
86193
  FileTree,
86158
86194
  {
86159
86195
  files: fileTree,
@@ -86169,7 +86205,7 @@ function StudioLeftPanels({
86169
86205
  lintFindingsByFile
86170
86206
  }
86171
86207
  ) }),
86172
- /* @__PURE__ */ jsx213("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx213(
86208
+ /* @__PURE__ */ jsx214("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx214(
86173
86209
  CodeBody,
86174
86210
  {
86175
86211
  projectId,
@@ -86179,7 +86215,7 @@ function StudioLeftPanels({
86179
86215
  }
86180
86216
  ) })
86181
86217
  ] }) }) }),
86182
- /* @__PURE__ */ jsx213(Dock.Panel, { id: "catalog", children: /* @__PURE__ */ jsx213(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx213(BlocksTab, { onAddBlock, onPreviewBlock }) }) })
86218
+ /* @__PURE__ */ jsx214(Dock.Panel, { id: "catalog", children: /* @__PURE__ */ jsx214(PanelColumn, { footer: lintButton, children: /* @__PURE__ */ jsx214(BlocksTab, { onAddBlock, onPreviewBlock }) }) })
86183
86219
  ] });
86184
86220
  }
86185
86221
  function CodeBody({
@@ -86189,19 +86225,19 @@ function CodeBody({
86189
86225
  onChange
86190
86226
  }) {
86191
86227
  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" });
86228
+ return /* @__PURE__ */ jsx214("div", { className: "flex items-center justify-center h-full text-neutral-600 text-sm", children: "Select a file to edit" });
86193
86229
  }
86194
86230
  if (isMediaFile(editingFile.path)) {
86195
- return /* @__PURE__ */ jsx213(MediaPreview, { projectId, filePath: editingFile.path });
86231
+ return /* @__PURE__ */ jsx214(MediaPreview, { projectId, filePath: editingFile.path });
86196
86232
  }
86197
86233
  if (editingFile.content == null) {
86198
- return /* @__PURE__ */ jsxs170("div", { className: "flex h-full items-center justify-center text-[11px] text-neutral-600", children: [
86234
+ return /* @__PURE__ */ jsxs171("div", { className: "flex h-full items-center justify-center text-[11px] text-neutral-600", children: [
86199
86235
  "Loading ",
86200
86236
  editingFile.path,
86201
86237
  "\u2026"
86202
86238
  ] });
86203
86239
  }
86204
- return /* @__PURE__ */ jsx213(
86240
+ return /* @__PURE__ */ jsx214(
86205
86241
  SourceEditor,
86206
86242
  {
86207
86243
  content: editingFile.content,
@@ -86427,7 +86463,7 @@ function getVisibleLayers(layers, collapsed) {
86427
86463
  }
86428
86464
 
86429
86465
  // src/components/editor/LayersPanel.tsx
86430
- import { jsx as jsx214, jsxs as jsxs171 } from "react/jsx-runtime";
86466
+ import { jsx as jsx215, jsxs as jsxs172 } from "react/jsx-runtime";
86431
86467
  var LAYERS_PANEL_MAX_ROWS = 80;
86432
86468
  var TAG_ICONS = {
86433
86469
  video: "Vi",
@@ -86714,24 +86750,24 @@ var LayersPanel = memo44(function LayersPanel2() {
86714
86750
  onSingleSibling: handleSingleSibling
86715
86751
  });
86716
86752
  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" })
86753
+ return /* @__PURE__ */ jsxs172("div", { className: "flex h-full flex-col items-center justify-center bg-panel-bg px-6 text-center", children: [
86754
+ /* @__PURE__ */ jsx215(Layers, { size: 18, className: "mb-3 text-panel-text-5" }),
86755
+ /* @__PURE__ */ jsx215("p", { className: "text-sm font-medium text-panel-text-1", children: "No layers" }),
86756
+ /* @__PURE__ */ jsx215("p", { className: "mt-1 text-xs text-neutral-500", children: "Load a composition to see its element tree" })
86721
86757
  ] });
86722
86758
  }
86723
- return /* @__PURE__ */ jsxs171(
86759
+ return /* @__PURE__ */ jsxs172(
86724
86760
  "div",
86725
86761
  {
86726
86762
  className: "flex h-full min-h-0 flex-col overflow-hidden bg-panel-bg",
86727
86763
  onPointerLeave: () => handleLayerHover(null),
86728
86764
  children: [
86729
- /* @__PURE__ */ jsxs171("div", { className: "border-b border-panel-border px-3 py-2 text-[11px] text-panel-text-3", children: [
86765
+ /* @__PURE__ */ jsxs172("div", { className: "border-b border-panel-border px-3 py-2 text-[11px] text-panel-text-3", children: [
86730
86766
  layers.length,
86731
86767
  " layer",
86732
86768
  layers.length === 1 ? "" : "s"
86733
86769
  ] }),
86734
- /* @__PURE__ */ jsxs171(
86770
+ /* @__PURE__ */ jsxs172(
86735
86771
  "div",
86736
86772
  {
86737
86773
  ref: scrollContainerRef,
@@ -86740,15 +86776,15 @@ var LayersPanel = memo44(function LayersPanel2() {
86740
86776
  onPointerUp: handleContainerPointerUp,
86741
86777
  onPointerCancel: handleContainerPointerUp,
86742
86778
  children: [
86743
- activeGroupElement && /* @__PURE__ */ jsxs171(
86779
+ activeGroupElement && /* @__PURE__ */ jsxs172(
86744
86780
  "button",
86745
86781
  {
86746
86782
  type: "button",
86747
86783
  onClick: () => setActiveGroupElement(null),
86748
86784
  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
86785
  children: [
86750
- /* @__PURE__ */ jsx214("span", { "aria-hidden": "true", children: "\u2190" }),
86751
- /* @__PURE__ */ jsx214("span", { className: "truncate", children: activeGroupElement.getAttribute("data-hf-group") || "Group" })
86786
+ /* @__PURE__ */ jsx215("span", { "aria-hidden": "true", children: "\u2190" }),
86787
+ /* @__PURE__ */ jsx215("span", { className: "truncate", children: activeGroupElement.getAttribute("data-hf-group") || "Group" })
86752
86788
  ]
86753
86789
  }
86754
86790
  ),
@@ -86759,7 +86795,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86759
86795
  const isCollapsed = collapsed[layer.key] ?? false;
86760
86796
  const hasChildren = layer.childCount > 0;
86761
86797
  const isCompHost = isCompositionHost(layer.element);
86762
- return /* @__PURE__ */ jsxs171(
86798
+ return /* @__PURE__ */ jsxs172(
86763
86799
  "div",
86764
86800
  {
86765
86801
  "data-layer-index": index,
@@ -86779,7 +86815,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86779
86815
  style: { paddingLeft: 8 + layer.depth * 16 },
86780
86816
  title: draggable ? layer.element.hasAttribute("data-hf-group") ? "Double-click to enter group" : void 0 : "This layer can't be reordered",
86781
86817
  children: [
86782
- hasChildren ? /* @__PURE__ */ jsx214(
86818
+ hasChildren ? /* @__PURE__ */ jsx215(
86783
86819
  "button",
86784
86820
  {
86785
86821
  type: "button",
@@ -86787,7 +86823,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86787
86823
  "aria-expanded": !isCollapsed,
86788
86824
  "aria-label": isCollapsed ? "Expand children" : "Collapse children",
86789
86825
  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(
86826
+ children: /* @__PURE__ */ jsx215(
86791
86827
  "svg",
86792
86828
  {
86793
86829
  width: "8",
@@ -86795,26 +86831,26 @@ var LayersPanel = memo44(function LayersPanel2() {
86795
86831
  viewBox: "0 0 8 8",
86796
86832
  fill: "currentColor",
86797
86833
  className: `transition-transform ${isCollapsed ? "" : "rotate-90"}`,
86798
- children: /* @__PURE__ */ jsx214("path", { d: "M2 1l4 3-4 3z" })
86834
+ children: /* @__PURE__ */ jsx215("path", { d: "M2 1l4 3-4 3z" })
86799
86835
  }
86800
86836
  )
86801
86837
  }
86802
- ) : /* @__PURE__ */ jsx214("span", { className: "w-4 shrink-0" }),
86803
- /* @__PURE__ */ jsx214(
86838
+ ) : /* @__PURE__ */ jsx215("span", { className: "w-4 shrink-0" }),
86839
+ /* @__PURE__ */ jsx215(
86804
86840
  "span",
86805
86841
  {
86806
86842
  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
86843
  children: getTagBadge(layer.tagName)
86808
86844
  }
86809
86845
  ),
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 })
86846
+ /* @__PURE__ */ jsx215("span", { className: "min-w-0 flex-1 truncate text-[11px]", children: layer.label }),
86847
+ hasChildren && /* @__PURE__ */ jsx215("span", { className: "text-[9px] tabular-nums text-panel-text-5", children: layer.childCount })
86812
86848
  ]
86813
86849
  },
86814
86850
  layer.key
86815
86851
  );
86816
86852
  }),
86817
- insertionLineY != null && /* @__PURE__ */ jsx214(
86853
+ insertionLineY != null && /* @__PURE__ */ jsx215(
86818
86854
  "div",
86819
86855
  {
86820
86856
  className: "pointer-events-none absolute left-2 right-2 h-0.5 bg-studio-accent",
@@ -86837,18 +86873,18 @@ import { memo as memo45, useCallback as useCallback161 } from "react";
86837
86873
 
86838
86874
  // src/captions/components/shared.tsx
86839
86875
  import { useEffect as useEffect138, useRef as useRef176, useState as useState139 } from "react";
86840
- import { jsx as jsx215, jsxs as jsxs172 } from "react/jsx-runtime";
86876
+ import { jsx as jsx216, jsxs as jsxs173 } from "react/jsx-runtime";
86841
86877
  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
86878
  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 })
86879
+ return /* @__PURE__ */ jsxs173("div", { className: "mb-3", children: [
86880
+ /* @__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 }) }),
86881
+ /* @__PURE__ */ jsx216("div", { className: "space-y-1", children })
86846
86882
  ] });
86847
86883
  }
86848
86884
  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 })
86885
+ return /* @__PURE__ */ jsxs173("div", { className: "flex items-center gap-2", children: [
86886
+ /* @__PURE__ */ jsx216("span", { className: "text-2xs text-neutral-600 w-14 text-right shrink-0", children: label }),
86887
+ /* @__PURE__ */ jsx216("div", { className: "flex-1 min-w-0", children })
86852
86888
  ] });
86853
86889
  }
86854
86890
  function NumberField2({
@@ -86878,7 +86914,7 @@ function NumberField2({
86878
86914
  onCommit(clamped);
86879
86915
  }
86880
86916
  };
86881
- return /* @__PURE__ */ jsx215(
86917
+ return /* @__PURE__ */ jsx216(
86882
86918
  "input",
86883
86919
  {
86884
86920
  type: "number",
@@ -86903,7 +86939,7 @@ function NumberField2({
86903
86939
  }
86904
86940
 
86905
86941
  // src/captions/components/CaptionAnimationPanel.tsx
86906
- import { jsx as jsx216, jsxs as jsxs173 } from "react/jsx-runtime";
86942
+ import { jsx as jsx217, jsxs as jsxs174 } from "react/jsx-runtime";
86907
86943
  var ENTRANCE_PRESETS = [
86908
86944
  "none",
86909
86945
  "fade",
@@ -86969,8 +87005,8 @@ function AnimationPhase({
86969
87005
  const ease = animation?.ease ?? "power2.out";
86970
87006
  const stagger = animation?.stagger ?? 0;
86971
87007
  const intensity = animation?.intensity ?? 1;
86972
- return /* @__PURE__ */ jsxs173(Section2, { label, children: [
86973
- /* @__PURE__ */ jsx216(Row, { label: "Preset", children: /* @__PURE__ */ jsx216(
87008
+ return /* @__PURE__ */ jsxs174(Section2, { label, children: [
87009
+ /* @__PURE__ */ jsx217(Row, { label: "Preset", children: /* @__PURE__ */ jsx217(
86974
87010
  "select",
86975
87011
  {
86976
87012
  value: preset,
@@ -86978,10 +87014,10 @@ function AnimationPhase({
86978
87014
  "aria-label": `${label} preset`,
86979
87015
  onChange: (e) => onChange({ preset: e.target.value }),
86980
87016
  className: inputCls,
86981
- children: presets.map((p) => /* @__PURE__ */ jsx216("option", { value: p, children: p }, p))
87017
+ children: presets.map((p) => /* @__PURE__ */ jsx217("option", { value: p, children: p }, p))
86982
87018
  }
86983
87019
  ) }),
86984
- /* @__PURE__ */ jsx216(Row, { label: "Duration", children: /* @__PURE__ */ jsx216(
87020
+ /* @__PURE__ */ jsx217(Row, { label: "Duration", children: /* @__PURE__ */ jsx217(
86985
87021
  NumberField2,
86986
87022
  {
86987
87023
  value: duration,
@@ -86993,7 +87029,7 @@ function AnimationPhase({
86993
87029
  onCommit: (v) => onChange({ duration: v })
86994
87030
  }
86995
87031
  ) }),
86996
- /* @__PURE__ */ jsx216(Row, { label: "Ease", children: /* @__PURE__ */ jsx216(
87032
+ /* @__PURE__ */ jsx217(Row, { label: "Ease", children: /* @__PURE__ */ jsx217(
86997
87033
  "select",
86998
87034
  {
86999
87035
  value: ease,
@@ -87001,10 +87037,10 @@ function AnimationPhase({
87001
87037
  "aria-label": `${label} ease`,
87002
87038
  onChange: (e) => onChange({ ease: e.target.value }),
87003
87039
  className: inputCls,
87004
- children: EASE_PRESETS2.map((e) => /* @__PURE__ */ jsx216("option", { value: e, children: e }, e))
87040
+ children: EASE_PRESETS2.map((e) => /* @__PURE__ */ jsx217("option", { value: e, children: e }, e))
87005
87041
  }
87006
87042
  ) }),
87007
- /* @__PURE__ */ jsx216(Row, { label: "Stagger", children: /* @__PURE__ */ jsx216(
87043
+ /* @__PURE__ */ jsx217(Row, { label: "Stagger", children: /* @__PURE__ */ jsx217(
87008
87044
  NumberField2,
87009
87045
  {
87010
87046
  value: stagger,
@@ -87016,8 +87052,8 @@ function AnimationPhase({
87016
87052
  onCommit: (v) => onChange({ stagger: v })
87017
87053
  }
87018
87054
  ) }),
87019
- showIntensity && /* @__PURE__ */ jsx216(Row, { label: "Intensity", children: /* @__PURE__ */ jsxs173("div", { className: "flex items-center gap-2", children: [
87020
- /* @__PURE__ */ jsx216(
87055
+ showIntensity && /* @__PURE__ */ jsx217(Row, { label: "Intensity", children: /* @__PURE__ */ jsxs174("div", { className: "flex items-center gap-2", children: [
87056
+ /* @__PURE__ */ jsx217(
87021
87057
  "input",
87022
87058
  {
87023
87059
  type: "range",
@@ -87034,7 +87070,7 @@ function AnimationPhase({
87034
87070
  className: "flex-1 accent-studio-accent disabled:opacity-40"
87035
87071
  }
87036
87072
  ),
87037
- /* @__PURE__ */ jsx216("span", { className: "text-2xs text-neutral-400 font-mono w-8 text-right shrink-0", children: intensity.toFixed(2) })
87073
+ /* @__PURE__ */ jsx217("span", { className: "text-2xs text-neutral-400 font-mono w-8 text-right shrink-0", children: intensity.toFixed(2) })
87038
87074
  ] }) })
87039
87075
  ] });
87040
87076
  }
@@ -87080,13 +87116,13 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87080
87116
  if (animation) applyAnimationToAll(animation);
87081
87117
  }, [animation, applyAnimationToAll]);
87082
87118
  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" }) });
87119
+ 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
87120
  }
87085
87121
  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(
87122
+ return /* @__PURE__ */ jsxs174("div", { className: "flex flex-col h-full min-h-0", children: [
87123
+ 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." }) }),
87124
+ /* @__PURE__ */ jsxs174("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
87125
+ /* @__PURE__ */ jsx217(
87090
87126
  AnimationPhase,
87091
87127
  {
87092
87128
  label: "Entrance",
@@ -87096,7 +87132,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87096
87132
  onChange: handleEntranceChange
87097
87133
  }
87098
87134
  ),
87099
- /* @__PURE__ */ jsx216(
87135
+ /* @__PURE__ */ jsx217(
87100
87136
  AnimationPhase,
87101
87137
  {
87102
87138
  label: "Highlight",
@@ -87107,7 +87143,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87107
87143
  onChange: handleHighlightChange
87108
87144
  }
87109
87145
  ),
87110
- /* @__PURE__ */ jsx216(
87146
+ /* @__PURE__ */ jsx217(
87111
87147
  AnimationPhase,
87112
87148
  {
87113
87149
  label: "Exit",
@@ -87118,7 +87154,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87118
87154
  }
87119
87155
  )
87120
87156
  ] }),
87121
- /* @__PURE__ */ jsx216("div", { className: "shrink-0 px-3 py-2 border-t border-neutral-800", children: /* @__PURE__ */ jsx216(
87157
+ /* @__PURE__ */ jsx217("div", { className: "shrink-0 px-3 py-2 border-t border-neutral-800", children: /* @__PURE__ */ jsx217(
87122
87158
  "button",
87123
87159
  {
87124
87160
  type: "button",
@@ -87133,7 +87169,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
87133
87169
  });
87134
87170
 
87135
87171
  // src/captions/components/CaptionPropertyPanel.tsx
87136
- import { jsx as jsx217, jsxs as jsxs174 } from "react/jsx-runtime";
87172
+ import { jsx as jsx218, jsxs as jsxs175 } from "react/jsx-runtime";
87137
87173
  function isMixedValue(model, selectedSegmentIds, key2, fallback) {
87138
87174
  if (!model || selectedSegmentIds.size < 2) return false;
87139
87175
  let first2;
@@ -87262,7 +87298,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87262
87298
  [selectedGroupId, updateGroupStyle, updateSelectedStyle, applyToIframeDom]
87263
87299
  );
87264
87300
  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" }) });
87301
+ 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
87302
  }
87267
87303
  const x = effectiveStyle.x ?? 0;
87268
87304
  const y = effectiveStyle.y ?? 0;
@@ -87273,11 +87309,11 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87273
87309
  const scaleMixed = isMixedValue(model, selectedSegmentIds, "scaleX", 1);
87274
87310
  const rotationMixed = isMixedValue(model, selectedSegmentIds, "rotation", 0);
87275
87311
  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(
87312
+ return /* @__PURE__ */ jsxs175("div", { className: "flex flex-col h-full min-h-0", children: [
87313
+ /* @__PURE__ */ jsxs175("div", { className: "px-3 py-2 border-b border-neutral-800 shrink-0", children: [
87314
+ /* @__PURE__ */ jsx218("div", { className: "flex items-center justify-between mb-1.5", children: /* @__PURE__ */ jsx218("span", { className: "text-2xs text-neutral-500", children: countLabel }) }),
87315
+ /* @__PURE__ */ jsxs175("div", { className: "flex gap-1", role: "tablist", "aria-label": "Caption editing tabs", children: [
87316
+ /* @__PURE__ */ jsx218(
87281
87317
  "button",
87282
87318
  {
87283
87319
  type: "button",
@@ -87291,7 +87327,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87291
87327
  children: "Style"
87292
87328
  }
87293
87329
  ),
87294
- /* @__PURE__ */ jsx217(
87330
+ /* @__PURE__ */ jsx218(
87295
87331
  "button",
87296
87332
  {
87297
87333
  type: "button",
@@ -87307,10 +87343,10 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87307
87343
  )
87308
87344
  ] })
87309
87345
  ] }),
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(
87346
+ activeTab === "animation" && /* @__PURE__ */ jsx218(CaptionAnimationPanel, {}),
87347
+ activeTab === "style" && /* @__PURE__ */ jsxs175("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
87348
+ /* @__PURE__ */ jsxs175(Section2, { label: "Position", children: [
87349
+ /* @__PURE__ */ jsx218(Row, { label: "X", children: /* @__PURE__ */ jsx218(
87314
87350
  NumberField2,
87315
87351
  {
87316
87352
  value: x,
@@ -87319,7 +87355,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87319
87355
  onCommit: (v) => handleStyleChange({ x: v })
87320
87356
  }
87321
87357
  ) }),
87322
- /* @__PURE__ */ jsx217(Row, { label: "Y", children: /* @__PURE__ */ jsx217(
87358
+ /* @__PURE__ */ jsx218(Row, { label: "Y", children: /* @__PURE__ */ jsx218(
87323
87359
  NumberField2,
87324
87360
  {
87325
87361
  value: y,
@@ -87329,8 +87365,8 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87329
87365
  }
87330
87366
  ) })
87331
87367
  ] }),
87332
- /* @__PURE__ */ jsxs174(Section2, { label: "Transform", children: [
87333
- /* @__PURE__ */ jsx217(Row, { label: "Scale", children: /* @__PURE__ */ jsx217(
87368
+ /* @__PURE__ */ jsxs175(Section2, { label: "Transform", children: [
87369
+ /* @__PURE__ */ jsx218(Row, { label: "Scale", children: /* @__PURE__ */ jsx218(
87334
87370
  NumberField2,
87335
87371
  {
87336
87372
  value: scaleX,
@@ -87340,7 +87376,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87340
87376
  onCommit: (v) => handleStyleChange({ scaleX: v, scaleY: v })
87341
87377
  }
87342
87378
  ) }),
87343
- /* @__PURE__ */ jsx217(Row, { label: "Rotation", children: /* @__PURE__ */ jsx217(
87379
+ /* @__PURE__ */ jsx218(Row, { label: "Rotation", children: /* @__PURE__ */ jsx218(
87344
87380
  NumberField2,
87345
87381
  {
87346
87382
  value: rotation,
@@ -87356,7 +87392,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87356
87392
 
87357
87393
  // src/components/editor/BlockParamsPanel.tsx
87358
87394
  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";
87395
+ import { jsx as jsx219, jsxs as jsxs176 } from "react/jsx-runtime";
87360
87396
  var BlockParamsPanel = memo47(function BlockParamsPanel2({
87361
87397
  blockName,
87362
87398
  blockTitle,
@@ -87455,17 +87491,17 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87455
87491
  commitTimersRef.current.clear();
87456
87492
  };
87457
87493
  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(
87494
+ return /* @__PURE__ */ jsxs176("div", { className: "flex flex-col h-full", children: [
87495
+ /* @__PURE__ */ jsxs176("div", { className: "flex items-center justify-between px-3 py-2 border-b border-neutral-800", children: [
87496
+ /* @__PURE__ */ jsx219("div", { className: "text-[11px] font-semibold text-neutral-200 truncate", children: blockTitle }),
87497
+ /* @__PURE__ */ jsx219(
87462
87498
  "button",
87463
87499
  {
87464
87500
  type: "button",
87465
87501
  onClick: onClose,
87466
87502
  "aria-label": "Close block parameters",
87467
87503
  className: "p-1.5 -m-1 text-neutral-500 hover:text-neutral-300 active:scale-[0.97] transition-colors",
87468
- children: /* @__PURE__ */ jsxs175(
87504
+ children: /* @__PURE__ */ jsxs176(
87469
87505
  "svg",
87470
87506
  {
87471
87507
  width: "14",
@@ -87477,19 +87513,19 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87477
87513
  strokeLinecap: "round",
87478
87514
  strokeLinejoin: "round",
87479
87515
  children: [
87480
- /* @__PURE__ */ jsx218("path", { d: "M18 6 6 18" }),
87481
- /* @__PURE__ */ jsx218("path", { d: "m6 6 12 12" })
87516
+ /* @__PURE__ */ jsx219("path", { d: "M18 6 6 18" }),
87517
+ /* @__PURE__ */ jsx219("path", { d: "m6 6 12 12" })
87482
87518
  ]
87483
87519
  }
87484
87520
  )
87485
87521
  }
87486
87522
  )
87487
87523
  ] }),
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(
87524
+ /* @__PURE__ */ jsxs176("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
87525
+ /* @__PURE__ */ jsx219("div", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider", children: "Parameters" }),
87526
+ params.length === 0 && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-neutral-500", children: "This block has no editable parameters." }),
87527
+ !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." }),
87528
+ params.map((param) => /* @__PURE__ */ jsx219(
87493
87529
  ParamControl,
87494
87530
  {
87495
87531
  param,
@@ -87499,12 +87535,12 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87499
87535
  },
87500
87536
  param.key
87501
87537
  )),
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: [
87538
+ commitState.tone === "saving" && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-neutral-500", role: "status", children: "Saving\u2026" }),
87539
+ commitState.tone === "saved" && /* @__PURE__ */ jsxs176("div", { className: "text-[10px] text-emerald-500/90", role: "status", children: [
87504
87540
  "Saved to ",
87505
87541
  compositionPath
87506
87542
  ] }),
87507
- commitState.tone === "error" && /* @__PURE__ */ jsx218("div", { className: "text-[10px] text-red-400", role: "alert", children: commitState.message })
87543
+ commitState.tone === "error" && /* @__PURE__ */ jsx219("div", { className: "text-[10px] text-red-400", role: "alert", children: commitState.message })
87508
87544
  ] })
87509
87545
  ] });
87510
87546
  });
@@ -87514,10 +87550,10 @@ function ParamControl({
87514
87550
  disabled,
87515
87551
  onChange
87516
87552
  }) {
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(
87553
+ return /* @__PURE__ */ jsxs176("div", { className: "space-y-1", children: [
87554
+ /* @__PURE__ */ jsx219("label", { className: "text-[10px] font-medium text-neutral-400", children: param.label }),
87555
+ param.type === "color" && /* @__PURE__ */ jsxs176("div", { className: "flex items-center gap-2", children: [
87556
+ /* @__PURE__ */ jsx219(
87521
87557
  "input",
87522
87558
  {
87523
87559
  type: "color",
@@ -87528,7 +87564,7 @@ function ParamControl({
87528
87564
  className: "w-7 h-7 rounded-sm border border-neutral-700 bg-transparent cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
87529
87565
  }
87530
87566
  ),
87531
- /* @__PURE__ */ jsx218(
87567
+ /* @__PURE__ */ jsx219(
87532
87568
  "input",
87533
87569
  {
87534
87570
  type: "text",
@@ -87540,8 +87576,8 @@ function ParamControl({
87540
87576
  }
87541
87577
  )
87542
87578
  ] }),
87543
- param.type === "number" && /* @__PURE__ */ jsxs175("div", { className: "flex items-center gap-2", children: [
87544
- /* @__PURE__ */ jsx218(
87579
+ param.type === "number" && /* @__PURE__ */ jsxs176("div", { className: "flex items-center gap-2", children: [
87580
+ /* @__PURE__ */ jsx219(
87545
87581
  "input",
87546
87582
  {
87547
87583
  type: "range",
@@ -87555,9 +87591,9 @@ function ParamControl({
87555
87591
  className: "flex-1 disabled:cursor-not-allowed disabled:opacity-50"
87556
87592
  }
87557
87593
  ),
87558
- /* @__PURE__ */ jsx218("span", { className: "text-[10px] text-neutral-400 w-8 text-right tabular-nums", children: value })
87594
+ /* @__PURE__ */ jsx219("span", { className: "text-[10px] text-neutral-400 w-8 text-right tabular-nums", children: value })
87559
87595
  ] }),
87560
- param.type === "text" && /* @__PURE__ */ jsx218(
87596
+ param.type === "text" && /* @__PURE__ */ jsx219(
87561
87597
  "input",
87562
87598
  {
87563
87599
  type: "text",
@@ -87568,7 +87604,7 @@ function ParamControl({
87568
87604
  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
87605
  }
87570
87606
  ),
87571
- param.type === "select" && param.options && /* @__PURE__ */ jsx218(
87607
+ param.type === "select" && param.options && /* @__PURE__ */ jsx219(
87572
87608
  "select",
87573
87609
  {
87574
87610
  value,
@@ -87576,7 +87612,7 @@ function ParamControl({
87576
87612
  "aria-label": param.label,
87577
87613
  onChange: (e) => onChange(e.target.value),
87578
87614
  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))
87615
+ children: param.options.map((opt) => /* @__PURE__ */ jsx219("option", { value: opt.value, children: opt.label }, opt.value))
87580
87616
  }
87581
87617
  )
87582
87618
  ] });
@@ -87592,7 +87628,7 @@ import { CANVAS_DIMENSIONS } from "@hyperframes/parsers";
87592
87628
 
87593
87629
  // src/components/renders/RenderQueueItem.tsx
87594
87630
  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";
87631
+ import { Fragment as Fragment58, jsx as jsx220, jsxs as jsxs177 } from "react/jsx-runtime";
87596
87632
  function formatDuration2(ms) {
87597
87633
  if (ms < 1e3) return `${ms}ms`;
87598
87634
  const s = Math.round(ms / 1e3);
@@ -87630,7 +87666,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87630
87666
  const viewSrc = fileSrc;
87631
87667
  const isComplete = job.status === "complete";
87632
87668
  const isRendering = job.status === "rendering";
87633
- return /* @__PURE__ */ jsx219(
87669
+ return /* @__PURE__ */ jsx220(
87634
87670
  "div",
87635
87671
  {
87636
87672
  onPointerEnter: () => setHovered(true),
@@ -87640,8 +87676,8 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87640
87676
  setConfirmingDelete(false);
87641
87677
  },
87642
87678
  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(
87679
+ children: /* @__PURE__ */ jsxs177("div", { className: "flex items-center gap-2.5", children: [
87680
+ /* @__PURE__ */ jsxs177(
87645
87681
  "button",
87646
87682
  {
87647
87683
  type: "button",
@@ -87654,8 +87690,8 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87654
87690
  isComplete ? "cursor-pointer" : "cursor-default"
87655
87691
  ].join(" "),
87656
87692
  children: [
87657
- isComplete && /* @__PURE__ */ jsxs176(Fragment58, { children: [
87658
- hovered && /* @__PURE__ */ jsx219(
87693
+ isComplete && /* @__PURE__ */ jsxs177(Fragment58, { children: [
87694
+ hovered && /* @__PURE__ */ jsx220(
87659
87695
  "video",
87660
87696
  {
87661
87697
  src: viewSrc,
@@ -87668,35 +87704,35 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87668
87704
  style: { opacity: videoReady ? 1 : 0 }
87669
87705
  }
87670
87706
  ),
87671
- /* @__PURE__ */ jsx219(
87707
+ /* @__PURE__ */ jsx220(
87672
87708
  "div",
87673
87709
  {
87674
87710
  className: "absolute inset-0 transition-opacity duration-150",
87675
87711
  style: { opacity: hovered && videoReady ? 0 : 1 },
87676
- children: /* @__PURE__ */ jsx219(VideoFrameThumbnail, { src: viewSrc })
87712
+ children: /* @__PURE__ */ jsx220(VideoFrameThumbnail, { src: viewSrc })
87677
87713
  }
87678
87714
  )
87679
87715
  ] }),
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" }) })
87716
+ 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" }) }),
87717
+ 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" }) }),
87718
+ 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
87719
  ]
87684
87720
  }
87685
87721
  ),
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) })
87722
+ /* @__PURE__ */ jsxs177("div", { className: "flex-1 min-w-0", children: [
87723
+ /* @__PURE__ */ jsxs177("div", { className: "flex items-center gap-1.5", children: [
87724
+ /* @__PURE__ */ jsx220("span", { className: "text-step-11 font-medium text-text-2 truncate", children: job.filename }),
87725
+ job.durationMs && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-5 shrink-0", children: formatDuration2(job.durationMs) })
87690
87726
  ] }),
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: [
87727
+ isRendering && /* @__PURE__ */ jsxs177("div", { className: "mt-1", children: [
87728
+ /* @__PURE__ */ jsxs177("div", { className: "flex items-center justify-between mb-0.5", children: [
87729
+ /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-4", children: job.stage || "Rendering" }),
87730
+ /* @__PURE__ */ jsxs177("span", { className: "text-step-9 font-mono text-accent", children: [
87695
87731
  job.progress,
87696
87732
  "%"
87697
87733
  ] })
87698
87734
  ] }),
87699
- /* @__PURE__ */ jsx219(
87735
+ /* @__PURE__ */ jsx220(
87700
87736
  "div",
87701
87737
  {
87702
87738
  className: "w-full h-1 bg-border rounded-full overflow-hidden",
@@ -87705,7 +87741,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87705
87741
  "aria-valuemin": 0,
87706
87742
  "aria-valuemax": 100,
87707
87743
  "aria-label": `Render progress: ${job.progress}%`,
87708
- children: /* @__PURE__ */ jsx219(
87744
+ children: /* @__PURE__ */ jsx220(
87709
87745
  "div",
87710
87746
  {
87711
87747
  className: "h-full bg-accent rounded-full transition-all duration-300",
@@ -87715,11 +87751,11 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87715
87751
  }
87716
87752
  )
87717
87753
  ] }),
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) })
87754
+ job.status === "failed" && job.error && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-danger mt-0.5 block", children: job.error }),
87755
+ job.status === "cancelled" && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-4 mt-0.5 block", children: "Cancelled" }),
87756
+ !isRendering && /* @__PURE__ */ jsx220("span", { className: "text-step-9 text-text-5", children: formatTimeAgo(job.createdAt) })
87721
87757
  ] }),
87722
- /* @__PURE__ */ jsx219("div", { className: "flex items-center gap-1.5 shrink-0", children: isRendering ? /* @__PURE__ */ jsx219(
87758
+ /* @__PURE__ */ jsx220("div", { className: "flex items-center gap-1.5 shrink-0", children: isRendering ? /* @__PURE__ */ jsx220(
87723
87759
  Button,
87724
87760
  {
87725
87761
  size: "sm",
@@ -87730,8 +87766,8 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87730
87766
  },
87731
87767
  children: "Cancel"
87732
87768
  }
87733
- ) : confirmingDelete ? /* @__PURE__ */ jsxs176(Fragment58, { children: [
87734
- /* @__PURE__ */ jsx219(
87769
+ ) : confirmingDelete ? /* @__PURE__ */ jsxs177(Fragment58, { children: [
87770
+ /* @__PURE__ */ jsx220(
87735
87771
  Button,
87736
87772
  {
87737
87773
  size: "sm",
@@ -87744,7 +87780,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87744
87780
  children: "Delete?"
87745
87781
  }
87746
87782
  ),
87747
- /* @__PURE__ */ jsx219(
87783
+ /* @__PURE__ */ jsx220(
87748
87784
  Button,
87749
87785
  {
87750
87786
  size: "sm",
@@ -87756,15 +87792,15 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87756
87792
  children: "Keep"
87757
87793
  }
87758
87794
  )
87759
- ] }) : /* @__PURE__ */ jsxs176(Fragment58, { children: [
87760
- /* @__PURE__ */ jsx219(Tooltip, { label: isComplete ? "Download" : "Available when the render finishes", children: /* @__PURE__ */ jsx219(
87795
+ ] }) : /* @__PURE__ */ jsxs177(Fragment58, { children: [
87796
+ /* @__PURE__ */ jsx220(Tooltip, { label: isComplete ? "Download" : "Available when the render finishes", children: /* @__PURE__ */ jsx220(
87761
87797
  IconButton,
87762
87798
  {
87763
87799
  size: "sm",
87764
87800
  onClick: handleDownload,
87765
87801
  disabled: !isComplete,
87766
87802
  "aria-label": `Download ${job.filename}`,
87767
- icon: /* @__PURE__ */ jsxs176(
87803
+ icon: /* @__PURE__ */ jsxs177(
87768
87804
  "svg",
87769
87805
  {
87770
87806
  width: "12",
@@ -87777,15 +87813,15 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87777
87813
  strokeLinejoin: "round",
87778
87814
  "aria-hidden": "true",
87779
87815
  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" })
87816
+ /* @__PURE__ */ jsx220("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
87817
+ /* @__PURE__ */ jsx220("polyline", { points: "7 10 12 15 17 10" }),
87818
+ /* @__PURE__ */ jsx220("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
87783
87819
  ]
87784
87820
  }
87785
87821
  )
87786
87822
  }
87787
87823
  ) }),
87788
- /* @__PURE__ */ jsx219(Tooltip, { label: "Delete render file", children: /* @__PURE__ */ jsx219(
87824
+ /* @__PURE__ */ jsx220(Tooltip, { label: "Delete render file", children: /* @__PURE__ */ jsx220(
87789
87825
  IconButton,
87790
87826
  {
87791
87827
  size: "sm",
@@ -87794,7 +87830,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87794
87830
  setConfirmingDelete(true);
87795
87831
  },
87796
87832
  "aria-label": `Delete ${job.filename}`,
87797
- icon: /* @__PURE__ */ jsx219(
87833
+ icon: /* @__PURE__ */ jsx220(
87798
87834
  "svg",
87799
87835
  {
87800
87836
  width: "12",
@@ -87805,7 +87841,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87805
87841
  strokeWidth: "2",
87806
87842
  strokeLinecap: "round",
87807
87843
  "aria-hidden": "true",
87808
- children: /* @__PURE__ */ jsx219("path", { d: "M18 6L6 18M6 6l12 12" })
87844
+ children: /* @__PURE__ */ jsx220("path", { d: "M18 6L6 18M6 6l12 12" })
87809
87845
  }
87810
87846
  )
87811
87847
  }
@@ -87818,7 +87854,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87818
87854
 
87819
87855
  // src/components/renders/FfmpegRequiredNotice.tsx
87820
87856
  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";
87857
+ import { jsx as jsx221, jsxs as jsxs178 } from "react/jsx-runtime";
87822
87858
  var DOWNLOAD_URL = "https://ffmpeg.org/download.html";
87823
87859
  var CUE_MS = 1600;
87824
87860
  var FOCUS_RING = "outline-hidden focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-studio-accent";
@@ -87847,19 +87883,19 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87847
87883
  setCopied(true);
87848
87884
  window.setTimeout(() => setCopied(false), CUE_MS);
87849
87885
  };
87850
- return /* @__PURE__ */ jsxs177(
87886
+ return /* @__PURE__ */ jsxs178(
87851
87887
  "div",
87852
87888
  {
87853
87889
  role: "alert",
87854
87890
  className: "flex flex-col gap-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-2.5",
87855
87891
  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." })
87892
+ /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-0.5", children: [
87893
+ /* @__PURE__ */ jsx221("span", { className: "text-[11px] font-semibold text-amber-300", children: status.title ?? "FFmpeg not found" }),
87894
+ /* @__PURE__ */ jsx221("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.detail ?? "FFmpeg is required to encode video." })
87859
87895
  ] }),
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(
87896
+ status.command ? /* @__PURE__ */ jsxs178("div", { className: "flex items-center gap-1.5", children: [
87897
+ /* @__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 }),
87898
+ /* @__PURE__ */ jsx221(
87863
87899
  "button",
87864
87900
  {
87865
87901
  type: "button",
@@ -87868,9 +87904,9 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87868
87904
  children: copied ? "Copied" : "Copy"
87869
87905
  }
87870
87906
  )
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(
87907
+ ] }) : status.hint && /* @__PURE__ */ jsx221("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.hint }),
87908
+ /* @__PURE__ */ jsxs178("div", { className: "flex items-center gap-3", children: [
87909
+ /* @__PURE__ */ jsx221(
87874
87910
  "button",
87875
87911
  {
87876
87912
  type: "button",
@@ -87880,7 +87916,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87880
87916
  children: checking ? "Checking\u2026" : "Recheck"
87881
87917
  }
87882
87918
  ),
87883
- /* @__PURE__ */ jsx220(
87919
+ /* @__PURE__ */ jsx221(
87884
87920
  "a",
87885
87921
  {
87886
87922
  href: DOWNLOAD_URL,
@@ -87890,7 +87926,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87890
87926
  children: "Other install options"
87891
87927
  }
87892
87928
  ),
87893
- /* @__PURE__ */ jsx220(
87929
+ /* @__PURE__ */ jsx221(
87894
87930
  "span",
87895
87931
  {
87896
87932
  "aria-live": "polite",
@@ -87905,7 +87941,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87905
87941
  });
87906
87942
 
87907
87943
  // src/components/renders/RenderQueue.tsx
87908
- import { jsx as jsx221, jsxs as jsxs178 } from "react/jsx-runtime";
87944
+ import { jsx as jsx222, jsxs as jsxs179 } from "react/jsx-runtime";
87909
87945
  var SCALE_OPTION_ORDER = ["auto", "1080p", "4k"];
87910
87946
  var SCALE_LABEL = {
87911
87947
  auto: "Auto",
@@ -87993,8 +88029,8 @@ function FormatInfoTooltip({ format }) {
87993
88029
  return () => document.removeEventListener("keydown", onKeyDown);
87994
88030
  }, [open]);
87995
88031
  const info = FORMAT_INFO[format];
87996
- return /* @__PURE__ */ jsxs178("div", { ref: triggerRef, className: "relative", onPointerEnter: show, onPointerLeave: hide, children: [
87997
- /* @__PURE__ */ jsx221(
88032
+ return /* @__PURE__ */ jsxs179("div", { ref: triggerRef, className: "relative", onPointerEnter: show, onPointerLeave: hide, children: [
88033
+ /* @__PURE__ */ jsx222(
87998
88034
  "button",
87999
88035
  {
88000
88036
  type: "button",
@@ -88005,7 +88041,7 @@ function FormatInfoTooltip({ format }) {
88005
88041
  onBlur: hide,
88006
88042
  onClick: () => setOpen((prev) => !prev),
88007
88043
  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(
88044
+ children: /* @__PURE__ */ jsxs179(
88009
88045
  "svg",
88010
88046
  {
88011
88047
  width: "12",
@@ -88018,16 +88054,16 @@ function FormatInfoTooltip({ format }) {
88018
88054
  strokeLinejoin: "round",
88019
88055
  "aria-hidden": "true",
88020
88056
  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" })
88057
+ /* @__PURE__ */ jsx222("circle", { cx: "12", cy: "12", r: "10" }),
88058
+ /* @__PURE__ */ jsx222("path", { d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" }),
88059
+ /* @__PURE__ */ jsx222("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
88024
88060
  ]
88025
88061
  }
88026
88062
  )
88027
88063
  }
88028
88064
  ),
88029
88065
  open && createPortal10(
88030
- /* @__PURE__ */ jsxs178(
88066
+ /* @__PURE__ */ jsxs179(
88031
88067
  "div",
88032
88068
  {
88033
88069
  id: panelId,
@@ -88037,10 +88073,10 @@ function FormatInfoTooltip({ format }) {
88037
88073
  className: "fixed w-52 p-2 rounded-sm bg-input border border-border-input shadow-menu z-200",
88038
88074
  style: { left: position?.left ?? -9999, top: position?.top ?? -9999 },
88039
88075
  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 }),
88076
+ /* @__PURE__ */ jsx222("p", { className: "text-step-10 font-semibold text-text-1 mb-0.5", children: info.label }),
88077
+ /* @__PURE__ */ jsx222("p", { className: "text-step-9 text-text-3 leading-tight", children: info.desc }),
88078
+ /* @__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: [
88079
+ /* @__PURE__ */ jsx222("span", { className: "text-text-3 font-medium", children: FORMAT_INFO[f].label }),
88044
88080
  " \u2014 ",
88045
88081
  FORMAT_INFO[f].desc
88046
88082
  ] }, f)) })
@@ -88086,8 +88122,8 @@ function FormatExportButton({
88086
88122
  const [fps, setFps] = useState144(persisted.fps);
88087
88123
  const missingFfmpeg = ffmpeg && !ffmpeg.ok ? ffmpeg : null;
88088
88124
  const showQuality = format !== "mov";
88089
- return /* @__PURE__ */ jsxs178("div", { className: "flex flex-col gap-3", children: [
88090
- missingFfmpeg && /* @__PURE__ */ jsx221(
88125
+ return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-3", children: [
88126
+ missingFfmpeg && /* @__PURE__ */ jsx222(
88091
88127
  FfmpegRequiredNotice,
88092
88128
  {
88093
88129
  status: missingFfmpeg,
@@ -88095,13 +88131,13 @@ function FormatExportButton({
88095
88131
  onRecheck: onRecheckFfmpeg
88096
88132
  }
88097
88133
  ),
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 })
88134
+ /* @__PURE__ */ jsxs179("div", { className: "grid grid-cols-2 gap-2", children: [
88135
+ /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88136
+ /* @__PURE__ */ jsxs179("div", { className: "flex items-center gap-1", children: [
88137
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Format" }),
88138
+ /* @__PURE__ */ jsx222(FormatInfoTooltip, { format })
88103
88139
  ] }),
88104
- /* @__PURE__ */ jsx221(
88140
+ /* @__PURE__ */ jsx222(
88105
88141
  Select,
88106
88142
  {
88107
88143
  label: "Format",
@@ -88116,9 +88152,9 @@ function FormatExportButton({
88116
88152
  }
88117
88153
  )
88118
88154
  ] }),
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(
88155
+ /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88156
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Resolution" }),
88157
+ /* @__PURE__ */ jsx222(
88122
88158
  Select,
88123
88159
  {
88124
88160
  label: "Resolution",
@@ -88133,9 +88169,9 @@ function FormatExportButton({
88133
88169
  }
88134
88170
  )
88135
88171
  ] }),
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(
88172
+ /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88173
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Frame rate" }),
88174
+ /* @__PURE__ */ jsx222(
88139
88175
  Select,
88140
88176
  {
88141
88177
  label: "Frame rate",
@@ -88150,9 +88186,9 @@ function FormatExportButton({
88150
88186
  }
88151
88187
  )
88152
88188
  ] }),
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(
88189
+ showQuality && /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-1", children: [
88190
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-text-4", children: "Quality" }),
88191
+ /* @__PURE__ */ jsx222(
88156
88192
  Select,
88157
88193
  {
88158
88194
  label: "Quality",
@@ -88168,7 +88204,7 @@ function FormatExportButton({
88168
88204
  )
88169
88205
  ] })
88170
88206
  ] }),
88171
- /* @__PURE__ */ jsx221(
88207
+ /* @__PURE__ */ jsx222(
88172
88208
  Button,
88173
88209
  {
88174
88210
  variant: "primary",
@@ -88187,7 +88223,7 @@ function FormatExportButton({
88187
88223
  children: isRendering ? "Rendering\u2026" : "Export"
88188
88224
  }
88189
88225
  ),
88190
- lastRenderDurationMs !== void 0 && !isRendering && /* @__PURE__ */ jsxs178("p", { className: "text-step-9 text-text-5 text-center -mt-1.5", children: [
88226
+ lastRenderDurationMs !== void 0 && !isRendering && /* @__PURE__ */ jsxs179("p", { className: "text-step-9 text-text-5 text-center -mt-1.5", children: [
88191
88227
  "Last render took ",
88192
88228
  formatEta(lastRenderDurationMs)
88193
88229
  ] })
@@ -88218,8 +88254,8 @@ var RenderQueue = memo50(function RenderQueue2({
88218
88254
  }, [jobs.length]);
88219
88255
  const completedCount = jobs.filter((j) => j.status !== "rendering").length;
88220
88256
  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(
88257
+ return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col h-full", children: [
88258
+ /* @__PURE__ */ jsx222("div", { className: "px-3 py-3 border-b border-border shrink-0", children: /* @__PURE__ */ jsx222(
88223
88259
  FormatExportButton,
88224
88260
  {
88225
88261
  onStartRender,
@@ -88231,21 +88267,21 @@ var RenderQueue = memo50(function RenderQueue2({
88231
88267
  onRecheckFfmpeg
88232
88268
  }
88233
88269
  ) }),
88234
- actionError && /* @__PURE__ */ jsxs178(
88270
+ actionError && /* @__PURE__ */ jsxs179(
88235
88271
  "div",
88236
88272
  {
88237
88273
  role: "alert",
88238
88274
  className: "flex items-start justify-between gap-2 px-3 py-2 border-b border-border bg-danger/10",
88239
88275
  children: [
88240
- /* @__PURE__ */ jsx221("span", { className: "text-step-10 text-danger", children: actionError }),
88241
- onDismissActionError && /* @__PURE__ */ jsx221(
88276
+ /* @__PURE__ */ jsx222("span", { className: "text-step-10 text-danger", children: actionError }),
88277
+ onDismissActionError && /* @__PURE__ */ jsx222(
88242
88278
  IconButton,
88243
88279
  {
88244
88280
  size: "sm",
88245
88281
  onClick: onDismissActionError,
88246
88282
  "aria-label": "Dismiss error",
88247
88283
  className: "shrink-0",
88248
- icon: /* @__PURE__ */ jsx221(
88284
+ icon: /* @__PURE__ */ jsx222(
88249
88285
  "svg",
88250
88286
  {
88251
88287
  width: "10",
@@ -88256,7 +88292,7 @@ var RenderQueue = memo50(function RenderQueue2({
88256
88292
  strokeWidth: "2",
88257
88293
  strokeLinecap: "round",
88258
88294
  "aria-hidden": "true",
88259
- children: /* @__PURE__ */ jsx221("path", { d: "M18 6L6 18M6 6l12 12" })
88295
+ children: /* @__PURE__ */ jsx222("path", { d: "M18 6L6 18M6 6l12 12" })
88260
88296
  }
88261
88297
  )
88262
88298
  }
@@ -88264,11 +88300,11 @@ var RenderQueue = memo50(function RenderQueue2({
88264
88300
  ]
88265
88301
  }
88266
88302
  ),
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(
88303
+ /* @__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: [
88304
+ /* @__PURE__ */ jsx222("p", { className: "text-step-10 text-danger text-center", children: loadError }),
88305
+ onRetryLoad && /* @__PURE__ */ jsx222(Button, { size: "sm", variant: "secondary", onClick: onRetryLoad, children: "Retry" })
88306
+ ] }) : jobs.length === 0 ? /* @__PURE__ */ jsxs179("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
88307
+ /* @__PURE__ */ jsxs179(
88272
88308
  "svg",
88273
88309
  {
88274
88310
  width: "20",
@@ -88279,7 +88315,7 @@ var RenderQueue = memo50(function RenderQueue2({
88279
88315
  strokeWidth: "1.5",
88280
88316
  className: "text-text-5",
88281
88317
  children: [
88282
- /* @__PURE__ */ jsx221(
88318
+ /* @__PURE__ */ jsx222(
88283
88319
  "rect",
88284
88320
  {
88285
88321
  x: "2",
@@ -88292,7 +88328,7 @@ var RenderQueue = memo50(function RenderQueue2({
88292
88328
  strokeLinejoin: "round"
88293
88329
  }
88294
88330
  ),
88295
- /* @__PURE__ */ jsx221(
88331
+ /* @__PURE__ */ jsx222(
88296
88332
  "path",
88297
88333
  {
88298
88334
  d: "M7 2v20M17 2v20M2 12h20M2 7h5M2 17h5M17 17h5M17 7h5",
@@ -88303,17 +88339,17 @@ var RenderQueue = memo50(function RenderQueue2({
88303
88339
  ]
88304
88340
  }
88305
88341
  ),
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: [
88342
+ /* @__PURE__ */ jsx222("p", { className: "text-step-10 text-text-5 text-center", children: "No renders yet" })
88343
+ ] }) : /* @__PURE__ */ jsxs179("div", { children: [
88344
+ completedCount > 0 && /* @__PURE__ */ jsxs179("div", { className: "flex items-center justify-between px-3 py-1.5 border-b border-border", children: [
88345
+ /* @__PURE__ */ jsxs179("span", { className: "text-step-10 text-text-4", children: [
88310
88346
  jobs.length,
88311
88347
  " render",
88312
88348
  jobs.length === 1 ? "" : "s"
88313
88349
  ] }),
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" }) })
88350
+ /* @__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
88351
  ] }),
88316
- jobs.map((job) => /* @__PURE__ */ jsx221(
88352
+ jobs.map((job) => /* @__PURE__ */ jsx222(
88317
88353
  RenderQueueItem,
88318
88354
  {
88319
88355
  job,
@@ -88328,10 +88364,10 @@ var RenderQueue = memo50(function RenderQueue2({
88328
88364
  });
88329
88365
 
88330
88366
  // src/components/renders/RenderQueuePanel.tsx
88331
- import { jsx as jsx222 } from "react/jsx-runtime";
88367
+ import { jsx as jsx223 } from "react/jsx-runtime";
88332
88368
  var RenderQueuePanel = memo51(function RenderQueuePanel2() {
88333
88369
  const { projectId, compositionDimensions, waitForPendingDomEditSaves, renderQueue } = useStudioShellContext();
88334
- return /* @__PURE__ */ jsx222(
88370
+ return /* @__PURE__ */ jsx223(
88335
88371
  RenderQueue,
88336
88372
  {
88337
88373
  jobs: renderQueue.jobs,
@@ -88370,13 +88406,13 @@ import { parseSlideshowManifest } from "@hyperframes/core/slideshow";
88370
88406
 
88371
88407
  // src/components/panels/SlideshowSubPanels.tsx
88372
88408
  import { useState as useState145, useCallback as useCallback165, useId as useId8 } from "react";
88373
- import { jsx as jsx223, jsxs as jsxs179 } from "react/jsx-runtime";
88409
+ import { jsx as jsx224, jsxs as jsxs180 } from "react/jsx-runtime";
88374
88410
  function SectionHeader({
88375
88411
  children,
88376
88412
  expanded,
88377
88413
  onToggle
88378
88414
  }) {
88379
- return /* @__PURE__ */ jsxs179(
88415
+ return /* @__PURE__ */ jsxs180(
88380
88416
  "button",
88381
88417
  {
88382
88418
  type: "button",
@@ -88384,8 +88420,8 @@ function SectionHeader({
88384
88420
  onClick: onToggle,
88385
88421
  "aria-expanded": expanded,
88386
88422
  children: [
88387
- /* @__PURE__ */ jsx223("span", { children }),
88388
- /* @__PURE__ */ jsx223("span", { className: "text-[10px] text-neutral-600", children: expanded ? "\u25B2" : "\u25BC" })
88423
+ /* @__PURE__ */ jsx224("span", { children }),
88424
+ /* @__PURE__ */ jsx224("span", { className: "text-[10px] text-neutral-600", children: expanded ? "\u25B2" : "\u25BC" })
88389
88425
  ]
88390
88426
  }
88391
88427
  );
@@ -88403,12 +88439,12 @@ function SlideList({
88403
88439
  const orderedSlideScenes = slides.map((sl) => sceneById.get(sl.sceneId)).filter((s) => s !== void 0);
88404
88440
  const nonSlideScenes = scenes.filter((sc) => !slideIds.has(sc.id));
88405
88441
  const rows = [...orderedSlideScenes, ...nonSlideScenes];
88406
- return /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-px", children: [
88442
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-px", children: [
88407
88443
  rows.map((scene) => {
88408
88444
  const isSlide = slideIds.has(scene.id);
88409
88445
  const isSelected = selectedSceneId === scene.id;
88410
88446
  const slideIndex = slides.findIndex((s) => s.sceneId === scene.id);
88411
- return /* @__PURE__ */ jsxs179(
88447
+ return /* @__PURE__ */ jsxs180(
88412
88448
  "div",
88413
88449
  {
88414
88450
  role: "button",
@@ -88423,7 +88459,7 @@ function SlideList({
88423
88459
  }
88424
88460
  },
88425
88461
  children: [
88426
- /* @__PURE__ */ jsx223(
88462
+ /* @__PURE__ */ jsx224(
88427
88463
  "input",
88428
88464
  {
88429
88465
  type: "checkbox",
@@ -88434,9 +88470,9 @@ function SlideList({
88434
88470
  className: "accent-studio-accent shrink-0"
88435
88471
  }
88436
88472
  ),
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(
88473
+ /* @__PURE__ */ jsx224("span", { className: "flex-1 truncate", children: scene.label || scene.id }),
88474
+ isSlide && /* @__PURE__ */ jsxs180("span", { className: "flex gap-0.5 shrink-0", children: [
88475
+ /* @__PURE__ */ jsx224(
88440
88476
  "button",
88441
88477
  {
88442
88478
  type: "button",
@@ -88451,7 +88487,7 @@ function SlideList({
88451
88487
  children: "\u25B2"
88452
88488
  }
88453
88489
  ),
88454
- /* @__PURE__ */ jsx223(
88490
+ /* @__PURE__ */ jsx224(
88455
88491
  "button",
88456
88492
  {
88457
88493
  type: "button",
@@ -88472,7 +88508,7 @@ function SlideList({
88472
88508
  scene.id
88473
88509
  );
88474
88510
  }),
88475
- scenes.length === 0 && /* @__PURE__ */ jsx223("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "No scenes found" })
88511
+ scenes.length === 0 && /* @__PURE__ */ jsx224("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "No scenes found" })
88476
88512
  ] });
88477
88513
  }
88478
88514
  function SlideInspector({
@@ -88484,14 +88520,14 @@ function SlideInspector({
88484
88520
  onRemoveFragment
88485
88521
  }) {
88486
88522
  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: [
88523
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88524
+ /* @__PURE__ */ jsxs180("p", { className: "text-[10px] text-neutral-500 font-medium uppercase tracking-wide truncate", children: [
88489
88525
  "Scene: ",
88490
88526
  sceneId
88491
88527
  ] }),
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(
88528
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1", children: [
88529
+ /* @__PURE__ */ jsx224("label", { className: "text-[11px] text-neutral-400", children: "Notes" }),
88530
+ /* @__PURE__ */ jsx224(
88495
88531
  "textarea",
88496
88532
  {
88497
88533
  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 +88538,10 @@ function SlideInspector({
88502
88538
  }
88503
88539
  )
88504
88540
  ] }),
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(
88541
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1.5", children: [
88542
+ /* @__PURE__ */ jsxs180("div", { className: "flex items-center justify-between", children: [
88543
+ /* @__PURE__ */ jsx224("span", { className: "text-[11px] text-neutral-400", children: "Fragment hold-points" }),
88544
+ /* @__PURE__ */ jsxs180(
88509
88545
  "button",
88510
88546
  {
88511
88547
  type: "button",
@@ -88520,14 +88556,14 @@ function SlideInspector({
88520
88556
  }
88521
88557
  )
88522
88558
  ] }),
88523
- fragments.length > 0 ? /* @__PURE__ */ jsx223("div", { className: "flex flex-wrap gap-1", children: fragments.map((t, i) => /* @__PURE__ */ jsxs179(
88559
+ fragments.length > 0 ? /* @__PURE__ */ jsx224("div", { className: "flex flex-wrap gap-1", children: fragments.map((t, i) => /* @__PURE__ */ jsxs180(
88524
88560
  "span",
88525
88561
  {
88526
88562
  className: "inline-flex items-center gap-1 bg-neutral-700 rounded-sm px-1.5 py-0.5 text-[10px] text-neutral-200",
88527
88563
  children: [
88528
88564
  t.toFixed(2),
88529
88565
  "s",
88530
- /* @__PURE__ */ jsx223(
88566
+ /* @__PURE__ */ jsx224(
88531
88567
  "button",
88532
88568
  {
88533
88569
  type: "button",
@@ -88540,7 +88576,7 @@ function SlideInspector({
88540
88576
  ]
88541
88577
  },
88542
88578
  `frag-${i}`
88543
- )) }) : /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-600 italic", children: "No hold-points yet" })
88579
+ )) }) : /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-600 italic", children: "No hold-points yet" })
88544
88580
  ] })
88545
88581
  ] });
88546
88582
  }
@@ -88563,9 +88599,9 @@ function BranchTree({
88563
88599
  onCreateSequence(label);
88564
88600
  setNewLabel("");
88565
88601
  }, [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(
88602
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88603
+ /* @__PURE__ */ jsxs180("div", { className: "flex gap-1.5", children: [
88604
+ /* @__PURE__ */ jsx224(
88569
88605
  "input",
88570
88606
  {
88571
88607
  id: inputId,
@@ -88580,7 +88616,7 @@ function BranchTree({
88580
88616
  "aria-label": "New branch sequence name"
88581
88617
  }
88582
88618
  ),
88583
- /* @__PURE__ */ jsx223(
88619
+ /* @__PURE__ */ jsx224(
88584
88620
  "button",
88585
88621
  {
88586
88622
  type: "button",
@@ -88590,7 +88626,7 @@ function BranchTree({
88590
88626
  }
88591
88627
  )
88592
88628
  ] }),
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(
88629
+ 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
88630
  BranchItem,
88595
88631
  {
88596
88632
  seq,
@@ -88624,9 +88660,9 @@ function BranchItem({
88624
88660
  if (label && label !== seq.label) onRename(seq.id, label);
88625
88661
  setEditing(false);
88626
88662
  }, [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(
88663
+ return /* @__PURE__ */ jsxs180("div", { className: "border border-neutral-700/60 rounded-sm p-2 flex flex-col gap-2", children: [
88664
+ /* @__PURE__ */ jsxs180("div", { className: "flex items-center gap-1", children: [
88665
+ editing ? /* @__PURE__ */ jsx224(
88630
88666
  "input",
88631
88667
  {
88632
88668
  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 +88676,7 @@ function BranchItem({
88640
88676
  },
88641
88677
  "aria-label": `Rename branch ${seq.label}`
88642
88678
  }
88643
- ) : /* @__PURE__ */ jsx223(
88679
+ ) : /* @__PURE__ */ jsx224(
88644
88680
  "span",
88645
88681
  {
88646
88682
  role: "button",
@@ -88657,7 +88693,7 @@ function BranchItem({
88657
88693
  children: seq.label
88658
88694
  }
88659
88695
  ),
88660
- /* @__PURE__ */ jsx223(
88696
+ /* @__PURE__ */ jsx224(
88661
88697
  "button",
88662
88698
  {
88663
88699
  type: "button",
@@ -88668,16 +88704,16 @@ function BranchItem({
88668
88704
  }
88669
88705
  )
88670
88706
  ] }),
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: [
88707
+ 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: [
88708
+ /* @__PURE__ */ jsxs180("span", { className: "text-[10px] text-red-400", children: [
88673
88709
  "Delete branch \u201C",
88674
88710
  seq.label,
88675
88711
  "\u201D",
88676
88712
  seq.slides.length > 0 ? ` and its ${seq.slides.length} slide${seq.slides.length === 1 ? "" : "s"}` : "",
88677
88713
  "? Hotspots pointing to it will no longer resolve."
88678
88714
  ] }),
88679
- /* @__PURE__ */ jsxs179("div", { className: "flex items-center justify-end gap-1", children: [
88680
- /* @__PURE__ */ jsx223(
88715
+ /* @__PURE__ */ jsxs180("div", { className: "flex items-center justify-end gap-1", children: [
88716
+ /* @__PURE__ */ jsx224(
88681
88717
  "button",
88682
88718
  {
88683
88719
  type: "button",
@@ -88689,7 +88725,7 @@ function BranchItem({
88689
88725
  children: "Delete"
88690
88726
  }
88691
88727
  ),
88692
- /* @__PURE__ */ jsx223(
88728
+ /* @__PURE__ */ jsx224(
88693
88729
  "button",
88694
88730
  {
88695
88731
  type: "button",
@@ -88700,16 +88736,16 @@ function BranchItem({
88700
88736
  )
88701
88737
  ] })
88702
88738
  ] }),
88703
- /* @__PURE__ */ jsxs179("div", { className: "flex flex-col gap-px pl-2", children: [
88739
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-px pl-2", children: [
88704
88740
  scenes.map((scene) => {
88705
88741
  const assigned = seq.slides.some((s) => s.sceneId === scene.id);
88706
88742
  const isSelected = selectedSequenceId === seq.id && selectedSceneId === scene.id;
88707
- return /* @__PURE__ */ jsxs179(
88743
+ return /* @__PURE__ */ jsxs180(
88708
88744
  "div",
88709
88745
  {
88710
88746
  className: "flex items-center gap-1.5 py-0.5 text-[11px] text-neutral-400",
88711
88747
  children: [
88712
- /* @__PURE__ */ jsx223(
88748
+ /* @__PURE__ */ jsx224(
88713
88749
  "input",
88714
88750
  {
88715
88751
  type: "checkbox",
@@ -88719,7 +88755,7 @@ function BranchItem({
88719
88755
  className: "accent-studio-accent shrink-0"
88720
88756
  }
88721
88757
  ),
88722
- assigned ? /* @__PURE__ */ jsx223(
88758
+ assigned ? /* @__PURE__ */ jsx224(
88723
88759
  "button",
88724
88760
  {
88725
88761
  type: "button",
@@ -88728,13 +88764,13 @@ function BranchItem({
88728
88764
  onClick: () => onSelectBranchSlide(seq.id, scene.id),
88729
88765
  children: scene.label || scene.id
88730
88766
  }
88731
- ) : /* @__PURE__ */ jsx223("span", { className: "flex-1 truncate", children: scene.label || scene.id })
88767
+ ) : /* @__PURE__ */ jsx224("span", { className: "flex-1 truncate", children: scene.label || scene.id })
88732
88768
  ]
88733
88769
  },
88734
88770
  scene.id
88735
88771
  );
88736
88772
  }),
88737
- scenes.length === 0 && /* @__PURE__ */ jsx223("p", { className: "text-[10px] text-neutral-600 italic", children: "No scenes" })
88773
+ scenes.length === 0 && /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-600 italic", children: "No scenes" })
88738
88774
  ] })
88739
88775
  ] });
88740
88776
  }
@@ -88760,19 +88796,19 @@ function HotspotTool({
88760
88796
  setHotspotLabel("");
88761
88797
  }, [selectedSceneId, targetSequenceId, elementKey3, hotspotLabel, onAddHotspot]);
88762
88798
  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" }) });
88799
+ 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
88800
  }
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: [
88801
+ return /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-3 px-3 py-2", children: [
88802
+ /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1.5", children: [
88803
+ /* @__PURE__ */ jsxs180("p", { className: "text-[11px] text-neutral-400", children: [
88768
88804
  "Selected element:",
88769
88805
  " ",
88770
- /* @__PURE__ */ jsx223("span", { className: "text-neutral-200 font-mono", children: elementKey3 ?? "none" })
88806
+ /* @__PURE__ */ jsx224("span", { className: "text-neutral-200 font-mono", children: elementKey3 ?? "none" })
88771
88807
  ] }),
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(
88808
+ !elementKey3 && /* @__PURE__ */ jsx224("p", { className: "text-[10px] text-neutral-500 italic", children: "Click an element on the canvas to choose the hotspot target." }),
88809
+ 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." }),
88810
+ /* @__PURE__ */ jsx224("label", { className: "text-[11px] text-neutral-400", children: "Hotspot label" }),
88811
+ /* @__PURE__ */ jsx224(
88776
88812
  "input",
88777
88813
  {
88778
88814
  type: "text",
@@ -88783,8 +88819,8 @@ function HotspotTool({
88783
88819
  "aria-label": "Hotspot label"
88784
88820
  }
88785
88821
  ),
88786
- /* @__PURE__ */ jsx223("label", { className: "text-[11px] text-neutral-400", children: "Target branch" }),
88787
- /* @__PURE__ */ jsxs179(
88822
+ /* @__PURE__ */ jsx224("label", { className: "text-[11px] text-neutral-400", children: "Target branch" }),
88823
+ /* @__PURE__ */ jsxs180(
88788
88824
  "select",
88789
88825
  {
88790
88826
  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 +88828,12 @@ function HotspotTool({
88792
88828
  onChange: (e) => setTargetSequenceId(e.target.value),
88793
88829
  "aria-label": "Target branch sequence",
88794
88830
  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))
88831
+ /* @__PURE__ */ jsx224("option", { value: "", children: "\u2014 select branch \u2014" }),
88832
+ sequences.map((seq) => /* @__PURE__ */ jsx224("option", { value: seq.id, children: seq.label }, seq.id))
88797
88833
  ]
88798
88834
  }
88799
88835
  ),
88800
- /* @__PURE__ */ jsx223(
88836
+ /* @__PURE__ */ jsx224(
88801
88837
  "button",
88802
88838
  {
88803
88839
  type: "button",
@@ -88809,21 +88845,21 @@ function HotspotTool({
88809
88845
  }
88810
88846
  )
88811
88847
  ] }),
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" }),
88848
+ hotspots.length > 0 && /* @__PURE__ */ jsxs180("div", { className: "flex flex-col gap-1.5", children: [
88849
+ /* @__PURE__ */ jsx224("p", { className: "text-[11px] text-neutral-400 font-medium", children: "Hotspots on this slide" }),
88814
88850
  hotspots.map((h) => {
88815
88851
  const seqLabel = sequences.find((s) => s.id === h.target)?.label ?? h.target;
88816
- return /* @__PURE__ */ jsxs179(
88852
+ return /* @__PURE__ */ jsxs180(
88817
88853
  "div",
88818
88854
  {
88819
88855
  className: "flex items-center gap-2 bg-neutral-800 rounded-sm px-2 py-1",
88820
88856
  children: [
88821
- /* @__PURE__ */ jsxs179("span", { className: "flex-1 text-[11px] text-neutral-200 truncate", children: [
88857
+ /* @__PURE__ */ jsxs180("span", { className: "flex-1 text-[11px] text-neutral-200 truncate", children: [
88822
88858
  h.label,
88823
88859
  " \u2192 ",
88824
- /* @__PURE__ */ jsx223("span", { className: "text-neutral-400", children: seqLabel })
88860
+ /* @__PURE__ */ jsx224("span", { className: "text-neutral-400", children: seqLabel })
88825
88861
  ] }),
88826
- /* @__PURE__ */ jsx223(
88862
+ /* @__PURE__ */ jsx224(
88827
88863
  "button",
88828
88864
  {
88829
88865
  type: "button",
@@ -88973,7 +89009,7 @@ function removeHotspot(manifest, sceneId, hotspotId, sequenceId) {
88973
89009
  }
88974
89010
 
88975
89011
  // src/components/panels/SlideshowPanel.tsx
88976
- import { Fragment as Fragment59, jsx as jsx224, jsxs as jsxs180 } from "react/jsx-runtime";
89012
+ import { Fragment as Fragment59, jsx as jsx225, jsxs as jsxs181 } from "react/jsx-runtime";
88977
89013
  function safeParseManifest(html2) {
88978
89014
  try {
88979
89015
  return parseSlideshowManifest(html2) ?? { slides: [] };
@@ -89237,7 +89273,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89237
89273
  },
89238
89274
  [selectedSequenceId, applyManifest]
89239
89275
  );
89240
- return /* @__PURE__ */ jsxs180(
89276
+ return /* @__PURE__ */ jsxs181(
89241
89277
  "div",
89242
89278
  {
89243
89279
  className: "flex flex-col h-full overflow-y-auto text-white",
@@ -89251,14 +89287,14 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89251
89287
  }
89252
89288
  },
89253
89289
  children: [
89254
- persistError && /* @__PURE__ */ jsxs180(
89290
+ persistError && /* @__PURE__ */ jsxs181(
89255
89291
  "div",
89256
89292
  {
89257
89293
  role: "alert",
89258
89294
  className: "flex items-center justify-between gap-2 px-3 py-2 bg-red-950/40 border-b border-red-500/40",
89259
89295
  children: [
89260
- /* @__PURE__ */ jsx224("span", { className: "text-[11px] text-red-300", children: "Changes not saved" }),
89261
- /* @__PURE__ */ jsx224(
89296
+ /* @__PURE__ */ jsx225("span", { className: "text-[11px] text-red-300", children: "Changes not saved" }),
89297
+ /* @__PURE__ */ jsx225(
89262
89298
  "button",
89263
89299
  {
89264
89300
  type: "button",
@@ -89271,7 +89307,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89271
89307
  ]
89272
89308
  }
89273
89309
  ),
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(
89310
+ 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
89311
  "button",
89276
89312
  {
89277
89313
  type: "button",
@@ -89285,7 +89321,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89285
89321
  ]
89286
89322
  }
89287
89323
  ) }),
89288
- /* @__PURE__ */ jsxs180(
89324
+ /* @__PURE__ */ jsxs181(
89289
89325
  SectionHeader,
89290
89326
  {
89291
89327
  expanded: expandedSections.has("slides"),
@@ -89297,7 +89333,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89297
89333
  ]
89298
89334
  }
89299
89335
  ),
89300
- expandedSections.has("slides") && /* @__PURE__ */ jsx224("div", { className: "py-1", children: /* @__PURE__ */ jsx224(
89336
+ expandedSections.has("slides") && /* @__PURE__ */ jsx225("div", { className: "py-1", children: /* @__PURE__ */ jsx225(
89301
89337
  SlideList,
89302
89338
  {
89303
89339
  scenes,
@@ -89311,7 +89347,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89311
89347
  onReorder: handleReorder
89312
89348
  }
89313
89349
  ) }),
89314
- /* @__PURE__ */ jsx224(
89350
+ /* @__PURE__ */ jsx225(
89315
89351
  SectionHeader,
89316
89352
  {
89317
89353
  expanded: expandedSections.has("inspector"),
@@ -89319,7 +89355,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89319
89355
  children: "Slide Inspector"
89320
89356
  }
89321
89357
  ),
89322
- expandedSections.has("inspector") && /* @__PURE__ */ jsx224(Fragment59, { children: selectedSceneId ? /* @__PURE__ */ jsx224(
89358
+ expandedSections.has("inspector") && /* @__PURE__ */ jsx225(Fragment59, { children: selectedSceneId ? /* @__PURE__ */ jsx225(
89323
89359
  SlideInspector,
89324
89360
  {
89325
89361
  sceneId: selectedSceneId,
@@ -89329,8 +89365,8 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89329
89365
  onMarkFragment: handleMarkFragment,
89330
89366
  onRemoveFragment: handleRemoveFragment
89331
89367
  }
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(
89368
+ ) : /* @__PURE__ */ jsx225("p", { className: "px-3 py-2 text-[11px] text-neutral-500 italic", children: "Select a scene above to inspect" }) }),
89369
+ /* @__PURE__ */ jsxs181(
89334
89370
  SectionHeader,
89335
89371
  {
89336
89372
  expanded: expandedSections.has("branches"),
@@ -89342,7 +89378,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89342
89378
  ]
89343
89379
  }
89344
89380
  ),
89345
- expandedSections.has("branches") && /* @__PURE__ */ jsx224(
89381
+ expandedSections.has("branches") && /* @__PURE__ */ jsx225(
89346
89382
  BranchTree,
89347
89383
  {
89348
89384
  sequences,
@@ -89356,7 +89392,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89356
89392
  onSelectBranchSlide: handleSelectBranchSlide
89357
89393
  }
89358
89394
  ),
89359
- /* @__PURE__ */ jsx224(
89395
+ /* @__PURE__ */ jsx225(
89360
89396
  SectionHeader,
89361
89397
  {
89362
89398
  expanded: expandedSections.has("hotspot"),
@@ -89364,7 +89400,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89364
89400
  children: "Hotspot Tool"
89365
89401
  }
89366
89402
  ),
89367
- expandedSections.has("hotspot") && /* @__PURE__ */ jsx224(
89403
+ expandedSections.has("hotspot") && /* @__PURE__ */ jsx225(
89368
89404
  HotspotTool,
89369
89405
  {
89370
89406
  selectedSceneId,
@@ -89506,7 +89542,7 @@ function useEditVariablesInFile(deps) {
89506
89542
 
89507
89543
  // src/components/panels/VariablesDeclarationForm.tsx
89508
89544
  import { useState as useState148 } from "react";
89509
- import { jsx as jsx225, jsxs as jsxs181 } from "react/jsx-runtime";
89545
+ import { jsx as jsx226, jsxs as jsxs182 } from "react/jsx-runtime";
89510
89546
  var VARIABLE_TYPES = [
89511
89547
  "string",
89512
89548
  "number",
@@ -89608,8 +89644,8 @@ function declarationFromDraft(draft) {
89608
89644
  }
89609
89645
  }
89610
89646
  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 }),
89647
+ return /* @__PURE__ */ jsxs182("div", { className: "space-y-1", children: [
89648
+ /* @__PURE__ */ jsx226("label", { className: "text-[9px] font-medium text-neutral-500", children: label }),
89613
89649
  children
89614
89650
  ] });
89615
89651
  }
@@ -89618,20 +89654,20 @@ function DefaultField({
89618
89654
  onChange
89619
89655
  }) {
89620
89656
  if (draft.type === "boolean") {
89621
- return /* @__PURE__ */ jsxs181(
89657
+ return /* @__PURE__ */ jsxs182(
89622
89658
  "select",
89623
89659
  {
89624
89660
  value: draft.defaultRaw === "true" ? "true" : "false",
89625
89661
  onChange: (e) => onChange(e.target.value),
89626
89662
  className: VARIABLES_INPUT_CLASS,
89627
89663
  children: [
89628
- /* @__PURE__ */ jsx225("option", { value: "false", children: "false" }),
89629
- /* @__PURE__ */ jsx225("option", { value: "true", children: "true" })
89664
+ /* @__PURE__ */ jsx226("option", { value: "false", children: "false" }),
89665
+ /* @__PURE__ */ jsx226("option", { value: "true", children: "true" })
89630
89666
  ]
89631
89667
  }
89632
89668
  );
89633
89669
  }
89634
- return /* @__PURE__ */ jsx225(
89670
+ return /* @__PURE__ */ jsx226(
89635
89671
  "input",
89636
89672
  {
89637
89673
  type: "text",
@@ -89660,9 +89696,9 @@ function DeclarationForm({
89660
89696
  setError(null);
89661
89697
  onSubmit(result);
89662
89698
  };
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(
89699
+ return /* @__PURE__ */ jsxs182("div", { className: "space-y-2 rounded-lg border border-neutral-800 bg-neutral-900/60 p-2", children: [
89700
+ /* @__PURE__ */ jsxs182("div", { className: "grid grid-cols-2 gap-2", children: [
89701
+ /* @__PURE__ */ jsx226(Field, { label: "ID", children: /* @__PURE__ */ jsx226(
89666
89702
  "input",
89667
89703
  {
89668
89704
  type: "text",
@@ -89673,7 +89709,7 @@ function DeclarationForm({
89673
89709
  className: `${VARIABLES_INPUT_CLASS} font-mono disabled:opacity-50`
89674
89710
  }
89675
89711
  ) }),
89676
- /* @__PURE__ */ jsx225(Field, { label: "Label", children: /* @__PURE__ */ jsx225(
89712
+ /* @__PURE__ */ jsx226(Field, { label: "Label", children: /* @__PURE__ */ jsx226(
89677
89713
  "input",
89678
89714
  {
89679
89715
  type: "text",
@@ -89684,8 +89720,8 @@ function DeclarationForm({
89684
89720
  }
89685
89721
  ) })
89686
89722
  ] }),
89687
- /* @__PURE__ */ jsxs181("div", { className: "grid grid-cols-2 gap-2", children: [
89688
- /* @__PURE__ */ jsx225(Field, { label: "Type", children: /* @__PURE__ */ jsx225(
89723
+ /* @__PURE__ */ jsxs182("div", { className: "grid grid-cols-2 gap-2", children: [
89724
+ /* @__PURE__ */ jsx226(Field, { label: "Type", children: /* @__PURE__ */ jsx226(
89689
89725
  "select",
89690
89726
  {
89691
89727
  value: draft.type,
@@ -89694,12 +89730,12 @@ function DeclarationForm({
89694
89730
  if (type) set({ type });
89695
89731
  },
89696
89732
  className: VARIABLES_INPUT_CLASS,
89697
- children: VARIABLE_TYPES.map((t) => /* @__PURE__ */ jsx225("option", { value: t, children: t }, t))
89733
+ children: VARIABLE_TYPES.map((t) => /* @__PURE__ */ jsx226("option", { value: t, children: t }, t))
89698
89734
  }
89699
89735
  ) }),
89700
- /* @__PURE__ */ jsx225(Field, { label: "Default", children: /* @__PURE__ */ jsx225(DefaultField, { draft, onChange: (defaultRaw) => set({ defaultRaw }) }) })
89736
+ /* @__PURE__ */ jsx226(Field, { label: "Default", children: /* @__PURE__ */ jsx226(DefaultField, { draft, onChange: (defaultRaw) => set({ defaultRaw }) }) })
89701
89737
  ] }),
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(
89738
+ 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
89739
  "input",
89704
89740
  {
89705
89741
  type: "text",
@@ -89708,7 +89744,7 @@ function DeclarationForm({
89708
89744
  className: `${VARIABLES_INPUT_CLASS} tabular-nums`
89709
89745
  }
89710
89746
  ) }, key2)) }),
89711
- draft.type === "enum" && /* @__PURE__ */ jsx225(Field, { label: "Options (one per line, value:Label)", children: /* @__PURE__ */ jsx225(
89747
+ draft.type === "enum" && /* @__PURE__ */ jsx226(Field, { label: "Options (one per line, value:Label)", children: /* @__PURE__ */ jsx226(
89712
89748
  "textarea",
89713
89749
  {
89714
89750
  value: draft.optionsRaw,
@@ -89717,7 +89753,7 @@ function DeclarationForm({
89717
89753
  className: `${VARIABLES_INPUT_CLASS} resize-y font-mono`
89718
89754
  }
89719
89755
  ) }),
89720
- /* @__PURE__ */ jsx225(Field, { label: "Description (optional)", children: /* @__PURE__ */ jsx225(
89756
+ /* @__PURE__ */ jsx226(Field, { label: "Description (optional)", children: /* @__PURE__ */ jsx226(
89721
89757
  "input",
89722
89758
  {
89723
89759
  type: "text",
@@ -89726,9 +89762,9 @@ function DeclarationForm({
89726
89762
  className: VARIABLES_INPUT_CLASS
89727
89763
  }
89728
89764
  ) }),
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(
89765
+ error && /* @__PURE__ */ jsx226("p", { className: "text-[10px] text-red-400", children: error }),
89766
+ /* @__PURE__ */ jsxs182("div", { className: "flex items-center justify-end gap-2 pt-1", children: [
89767
+ /* @__PURE__ */ jsx226(
89732
89768
  "button",
89733
89769
  {
89734
89770
  type: "button",
@@ -89737,7 +89773,7 @@ function DeclarationForm({
89737
89773
  children: "Cancel"
89738
89774
  }
89739
89775
  ),
89740
- /* @__PURE__ */ jsx225(
89776
+ /* @__PURE__ */ jsx226(
89741
89777
  "button",
89742
89778
  {
89743
89779
  type: "button",
@@ -89751,14 +89787,14 @@ function DeclarationForm({
89751
89787
  }
89752
89788
 
89753
89789
  // src/components/panels/VariablesRowAction.tsx
89754
- import { jsx as jsx226 } from "react/jsx-runtime";
89790
+ import { jsx as jsx227 } from "react/jsx-runtime";
89755
89791
  function RowAction({
89756
89792
  label,
89757
89793
  title,
89758
89794
  danger,
89759
89795
  onClick
89760
89796
  }) {
89761
- return /* @__PURE__ */ jsx226(
89797
+ return /* @__PURE__ */ jsx227(
89762
89798
  "button",
89763
89799
  {
89764
89800
  type: "button",
@@ -89771,7 +89807,7 @@ function RowAction({
89771
89807
  }
89772
89808
 
89773
89809
  // src/components/panels/VariablesOtherCompositions.tsx
89774
- import { jsx as jsx227, jsxs as jsxs182 } from "react/jsx-runtime";
89810
+ import { jsx as jsx228, jsxs as jsxs183 } from "react/jsx-runtime";
89775
89811
  function CompositionSection({
89776
89812
  group,
89777
89813
  editingKey,
@@ -89779,8 +89815,8 @@ function CompositionSection({
89779
89815
  onSave,
89780
89816
  onRemove
89781
89817
  }) {
89782
- return /* @__PURE__ */ jsxs182("div", { className: "space-y-1.5", children: [
89783
- /* @__PURE__ */ jsx227(
89818
+ return /* @__PURE__ */ jsxs183("div", { className: "space-y-1.5", children: [
89819
+ /* @__PURE__ */ jsx228(
89784
89820
  "p",
89785
89821
  {
89786
89822
  className: "truncate text-[9px] font-medium uppercase tracking-wider text-neutral-500",
@@ -89791,12 +89827,12 @@ function CompositionSection({
89791
89827
  group.variables.map((decl) => {
89792
89828
  const key2 = `${group.path}::${decl.id}`;
89793
89829
  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(
89830
+ return /* @__PURE__ */ jsxs183("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 p-2", children: [
89831
+ /* @__PURE__ */ jsxs183("div", { className: "flex items-center gap-1.5", children: [
89832
+ /* @__PURE__ */ jsx228("span", { className: "truncate text-[10px] font-medium text-neutral-300", children: decl.label }),
89833
+ /* @__PURE__ */ jsx228("span", { className: "rounded-sm bg-neutral-800 px-1 py-px font-mono text-[8px] text-neutral-500", children: decl.type }),
89834
+ /* @__PURE__ */ jsxs183("span", { className: "ml-auto flex items-center gap-1", children: [
89835
+ /* @__PURE__ */ jsx228(
89800
89836
  RowAction,
89801
89837
  {
89802
89838
  label: "Edit",
@@ -89804,7 +89840,7 @@ function CompositionSection({
89804
89840
  onClick: () => onToggleEdit(editing ? null : key2)
89805
89841
  }
89806
89842
  ),
89807
- /* @__PURE__ */ jsx227(
89843
+ /* @__PURE__ */ jsx228(
89808
89844
  RowAction,
89809
89845
  {
89810
89846
  label: "\u2715",
@@ -89815,8 +89851,8 @@ function CompositionSection({
89815
89851
  )
89816
89852
  ] })
89817
89853
  ] }),
89818
- decl.description && /* @__PURE__ */ jsx227("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89819
- editing && /* @__PURE__ */ jsx227(
89854
+ decl.description && /* @__PURE__ */ jsx228("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89855
+ editing && /* @__PURE__ */ jsx228(
89820
89856
  DeclarationForm,
89821
89857
  {
89822
89858
  initial: draftFromDeclaration(decl),
@@ -89874,9 +89910,9 @@ function VariablesOtherCompositions({
89874
89910
  [editInFile]
89875
89911
  );
89876
89912
  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(
89913
+ return /* @__PURE__ */ jsxs183("div", { className: "space-y-3 border-t border-neutral-800 pt-3", children: [
89914
+ /* @__PURE__ */ jsx228("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-600", children: "Other compositions" }),
89915
+ groups.map((group) => /* @__PURE__ */ jsx228(
89880
89916
  CompositionSection,
89881
89917
  {
89882
89918
  group,
@@ -89892,7 +89928,7 @@ function VariablesOtherCompositions({
89892
89928
 
89893
89929
  // src/components/panels/VariablesPanel.tsx
89894
89930
  import { isScalarVariableValue as isScalar } from "@hyperframes/core/variables";
89895
- import { jsx as jsx228, jsxs as jsxs183 } from "react/jsx-runtime";
89931
+ import { jsx as jsx229, jsxs as jsxs184 } from "react/jsx-runtime";
89896
89932
  function shellSingleQuote(value) {
89897
89933
  return `'${value.replace(/'/g, `'\\''`)}'`;
89898
89934
  }
@@ -89908,7 +89944,7 @@ function formatIssue(issue) {
89908
89944
  }
89909
89945
  function ValidationStrip({ issues }) {
89910
89946
  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}`)) });
89947
+ 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
89948
  }
89913
89949
  function VariableRow({
89914
89950
  decl,
@@ -89922,11 +89958,11 @@ function VariableRow({
89922
89958
  onSaveEdit,
89923
89959
  onRemove
89924
89960
  }) {
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(
89961
+ return /* @__PURE__ */ jsxs184("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 p-2", children: [
89962
+ /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-1.5", children: [
89963
+ /* @__PURE__ */ jsx229("span", { className: "truncate text-[10px] font-medium text-neutral-300", children: decl.label }),
89964
+ /* @__PURE__ */ jsx229("span", { className: "rounded-sm bg-neutral-800 px-1 py-px font-mono text-[8px] text-neutral-500", children: decl.type }),
89965
+ unused && /* @__PURE__ */ jsx229(
89930
89966
  "span",
89931
89967
  {
89932
89968
  className: "rounded-sm bg-amber-900/40 px-1 py-px text-[8px] text-amber-400",
@@ -89934,9 +89970,9 @@ function VariableRow({
89934
89970
  children: "unused"
89935
89971
  }
89936
89972
  ),
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(
89973
+ overridden && /* @__PURE__ */ jsx229("span", { className: "h-1.5 w-1.5 rounded-full bg-studio-accent" }),
89974
+ /* @__PURE__ */ jsxs184("span", { className: "ml-auto flex items-center gap-1", children: [
89975
+ overridden && isScalar(value) && /* @__PURE__ */ jsx229(
89940
89976
  RowAction,
89941
89977
  {
89942
89978
  label: "Set default",
@@ -89944,12 +89980,12 @@ function VariableRow({
89944
89980
  onClick: () => onSetDefault(value)
89945
89981
  }
89946
89982
  ),
89947
- /* @__PURE__ */ jsx228(RowAction, { label: "Edit", title: "Edit declaration", onClick: onToggleEdit }),
89948
- /* @__PURE__ */ jsx228(RowAction, { label: "\u2715", title: "Remove declaration", danger: true, onClick: onRemove })
89983
+ /* @__PURE__ */ jsx229(RowAction, { label: "Edit", title: "Edit declaration", onClick: onToggleEdit }),
89984
+ /* @__PURE__ */ jsx229(RowAction, { label: "\u2715", title: "Remove declaration", danger: true, onClick: onRemove })
89949
89985
  ] })
89950
89986
  ] }),
89951
- decl.description && /* @__PURE__ */ jsx228("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89952
- editing ? /* @__PURE__ */ jsx228(
89987
+ decl.description && /* @__PURE__ */ jsx229("p", { className: "text-[9px] text-neutral-500", children: decl.description }),
89988
+ editing ? /* @__PURE__ */ jsx229(
89953
89989
  DeclarationForm,
89954
89990
  {
89955
89991
  initial: draftFromDeclaration(decl),
@@ -89957,7 +89993,7 @@ function VariableRow({
89957
89993
  onSubmit: (edited) => onSaveEdit(mergeDeclarationEdit(decl, edited)),
89958
89994
  onCancel: onToggleEdit
89959
89995
  }
89960
- ) : /* @__PURE__ */ jsx228(PreviewValueControl, { decl, value, onCommit: onCommitPreview })
89996
+ ) : /* @__PURE__ */ jsx229(PreviewValueControl, { decl, value, onCommit: onCommitPreview })
89961
89997
  ] });
89962
89998
  }
89963
89999
  function UndeclaredReads({
@@ -89965,11 +90001,11 @@ function UndeclaredReads({
89965
90001
  onDeclare
89966
90002
  }) {
89967
90003
  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(
90004
+ return /* @__PURE__ */ jsxs184("div", { className: "space-y-1 rounded-lg border border-neutral-800/70 bg-neutral-900/40 p-2", children: [
90005
+ /* @__PURE__ */ jsx229("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-500", children: "Read by scripts, not declared" }),
90006
+ usage.undeclaredReads.map((id) => /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-2", children: [
90007
+ /* @__PURE__ */ jsx229("code", { className: "font-mono text-[10px] text-neutral-400", children: id }),
90008
+ /* @__PURE__ */ jsx229(
89973
90009
  RowAction,
89974
90010
  {
89975
90011
  label: "Declare",
@@ -89985,10 +90021,10 @@ function PreviewModeHeader({
89985
90021
  onReset
89986
90022
  }) {
89987
90023
  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(
90024
+ return /* @__PURE__ */ jsxs184("div", { className: "flex items-center justify-between border-b border-neutral-800 px-3 py-2", children: [
90025
+ /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-2", children: [
90026
+ /* @__PURE__ */ jsx229("span", { className: "text-[11px] font-semibold text-neutral-200", children: "Variables" }),
90027
+ /* @__PURE__ */ jsx229(
89992
90028
  "span",
89993
90029
  {
89994
90030
  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 +90032,7 @@ function PreviewModeHeader({
89996
90032
  }
89997
90033
  )
89998
90034
  ] }),
89999
- hasOverrides && /* @__PURE__ */ jsx228(
90035
+ hasOverrides && /* @__PURE__ */ jsx229(
90000
90036
  "button",
90001
90037
  {
90002
90038
  type: "button",
@@ -90014,11 +90050,11 @@ function HandoffFooter({
90014
90050
  }) {
90015
90051
  const json = JSON.stringify(effectiveValues);
90016
90052
  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(
90053
+ return /* @__PURE__ */ jsxs184("div", { className: "space-y-1.5 rounded-lg border border-neutral-800/70 bg-neutral-900/40 p-2", children: [
90054
+ /* @__PURE__ */ jsx229("p", { className: "text-[9px] font-medium uppercase tracking-wider text-neutral-500", children: "Use this template" }),
90055
+ /* @__PURE__ */ jsx229("code", { className: "block truncate font-mono text-[9px] text-neutral-500", title: command, children: command }),
90056
+ /* @__PURE__ */ jsxs184("div", { className: "flex items-center gap-2", children: [
90057
+ /* @__PURE__ */ jsx229(
90022
90058
  RowAction,
90023
90059
  {
90024
90060
  label: "Copy render command",
@@ -90026,7 +90062,7 @@ function HandoffFooter({
90026
90062
  onClick: () => onCopy(command, "Render command")
90027
90063
  }
90028
90064
  ),
90029
- /* @__PURE__ */ jsx228(
90065
+ /* @__PURE__ */ jsx229(
90030
90066
  RowAction,
90031
90067
  {
90032
90068
  label: "Copy values JSON",
@@ -90037,15 +90073,15 @@ function HandoffFooter({
90037
90073
  ] })
90038
90074
  ] });
90039
90075
  }
90040
- var EMPTY_STATE = /* @__PURE__ */ jsxs183("p", { className: "text-[10px] leading-relaxed text-neutral-500", children: [
90076
+ var EMPTY_STATE = /* @__PURE__ */ jsxs184("p", { className: "text-[10px] leading-relaxed text-neutral-500", children: [
90041
90077
  "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" }),
90078
+ /* @__PURE__ */ jsx229("code", { className: "font-mono", children: "data-composition-variables" }),
90043
90079
  "), read them with",
90044
90080
  " ",
90045
- /* @__PURE__ */ jsx228("code", { className: "font-mono", children: "getVariables()" }),
90081
+ /* @__PURE__ */ jsx229("code", { className: "font-mono", children: "getVariables()" }),
90046
90082
  ", and pass values at render time with",
90047
90083
  " ",
90048
- /* @__PURE__ */ jsx228("code", { className: "font-mono", children: "--variables" }),
90084
+ /* @__PURE__ */ jsx229("code", { className: "font-mono", children: "--variables" }),
90049
90085
  "."
90050
90086
  ] });
90051
90087
  var VariablesPanel = memo52(function VariablesPanel2({
@@ -90229,18 +90265,18 @@ var VariablesPanel = memo52(function VariablesPanel2({
90229
90265
  );
90230
90266
  const bindableSelection = domEditSelection?.hfId && domEditSelection.sourceFile === (activeCompPath ?? "index.html") ? domEditSelection : null;
90231
90267
  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." }) });
90268
+ 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
90269
  }
90234
- return /* @__PURE__ */ jsxs183("div", { className: "flex h-full flex-col", children: [
90235
- /* @__PURE__ */ jsx228(
90270
+ return /* @__PURE__ */ jsxs184("div", { className: "flex h-full flex-col", children: [
90271
+ /* @__PURE__ */ jsx229(
90236
90272
  PreviewModeHeader,
90237
90273
  {
90238
90274
  overrideCount: previewValues ? Object.keys(previewValues).length : 0,
90239
90275
  onReset: resetPreview
90240
90276
  }
90241
90277
  ),
90242
- /* @__PURE__ */ jsxs183("div", { className: "flex-1 space-y-3 overflow-y-auto p-3", children: [
90243
- bindableSelection && /* @__PURE__ */ jsx228(
90278
+ /* @__PURE__ */ jsxs184("div", { className: "flex-1 space-y-3 overflow-y-auto p-3", children: [
90279
+ bindableSelection && /* @__PURE__ */ jsx229(
90244
90280
  VariablesBindElement,
90245
90281
  {
90246
90282
  selection: bindableSelection,
@@ -90249,9 +90285,9 @@ var VariablesPanel = memo52(function VariablesPanel2({
90249
90285
  },
90250
90286
  bindableSelection.hfId
90251
90287
  ),
90252
- /* @__PURE__ */ jsx228(ValidationStrip, { issues }),
90288
+ /* @__PURE__ */ jsx229(ValidationStrip, { issues }),
90253
90289
  declarations.length === 0 && !addOpen && EMPTY_STATE,
90254
- declarations.map((decl) => /* @__PURE__ */ jsx228(
90290
+ declarations.map((decl) => /* @__PURE__ */ jsx229(
90255
90291
  VariableRow,
90256
90292
  {
90257
90293
  decl,
@@ -90267,15 +90303,15 @@ var VariablesPanel = memo52(function VariablesPanel2({
90267
90303
  },
90268
90304
  decl.id
90269
90305
  )),
90270
- /* @__PURE__ */ jsx228(
90306
+ /* @__PURE__ */ jsx229(
90271
90307
  UndeclaredReads,
90272
90308
  {
90273
90309
  usage,
90274
90310
  onDeclare: (id) => handleAdd({ id, type: "string", label: id, default: "" })
90275
90311
  }
90276
90312
  ),
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(
90313
+ usage?.scanIncomplete && /* @__PURE__ */ jsx229("p", { className: "text-[9px] text-neutral-600", children: "Scripts access variables dynamically \u2014 usage info may be incomplete." }),
90314
+ declarations.length > 0 && /* @__PURE__ */ jsx229(
90279
90315
  HandoffFooter,
90280
90316
  {
90281
90317
  effectiveValues,
@@ -90283,7 +90319,7 @@ var VariablesPanel = memo52(function VariablesPanel2({
90283
90319
  onCopy: copyToClipboard
90284
90320
  }
90285
90321
  ),
90286
- addOpen ? /* @__PURE__ */ jsx228(
90322
+ addOpen ? /* @__PURE__ */ jsx229(
90287
90323
  DeclarationForm,
90288
90324
  {
90289
90325
  initial: EMPTY_DRAFT,
@@ -90291,7 +90327,7 @@ var VariablesPanel = memo52(function VariablesPanel2({
90291
90327
  onSubmit: handleAdd,
90292
90328
  onCancel: () => setAddOpen(false)
90293
90329
  }
90294
- ) : /* @__PURE__ */ jsx228(
90330
+ ) : /* @__PURE__ */ jsx229(
90295
90331
  "button",
90296
90332
  {
90297
90333
  type: "button",
@@ -90300,7 +90336,7 @@ var VariablesPanel = memo52(function VariablesPanel2({
90300
90336
  children: "+ Add variable"
90301
90337
  }
90302
90338
  ),
90303
- /* @__PURE__ */ jsx228(
90339
+ /* @__PURE__ */ jsx229(
90304
90340
  VariablesOtherCompositions,
90305
90341
  {
90306
90342
  fileTree,
@@ -90433,7 +90469,7 @@ function useSlideshowTabState(params) {
90433
90469
 
90434
90470
  // src/components/DesignPanelPromoteProvider.tsx
90435
90471
  import { useCallback as useCallback172 } from "react";
90436
- import { jsx as jsx229 } from "react/jsx-runtime";
90472
+ import { jsx as jsx230 } from "react/jsx-runtime";
90437
90473
  function DesignPanelPromoteProvider({
90438
90474
  selection,
90439
90475
  projectId,
@@ -90463,7 +90499,7 @@ function DesignPanelPromoteProvider({
90463
90499
  (error) => showToast(getStudioSaveErrorMessage(error), "error"),
90464
90500
  [showToast]
90465
90501
  );
90466
- return /* @__PURE__ */ jsx229(
90502
+ return /* @__PURE__ */ jsx230(
90467
90503
  VariablePromoteProvider,
90468
90504
  {
90469
90505
  session: handle.session,
@@ -90740,7 +90776,7 @@ function useRemoveBackground(projectId, refreshFileTree, showToast) {
90740
90776
  }
90741
90777
 
90742
90778
  // src/components/StudioRightPanels.tsx
90743
- import { Fragment as Fragment60, jsx as jsx230, jsxs as jsxs184 } from "react/jsx-runtime";
90779
+ import { Fragment as Fragment60, jsx as jsx231, jsxs as jsxs185 } from "react/jsx-runtime";
90744
90780
  function StudioRightPanels({
90745
90781
  activeBlockParams,
90746
90782
  onCloseBlockParams,
@@ -90903,7 +90939,7 @@ function StudioRightPanels({
90903
90939
  const keys = timelineKeysForSelections(domEditGroupSelections, elements, activeCompPath);
90904
90940
  if (keys.length > 0) void onToggleElementHidden?.(keys, true);
90905
90941
  };
90906
- const propertyPanel = /* @__PURE__ */ jsx230(
90942
+ const propertyPanel = /* @__PURE__ */ jsx231(
90907
90943
  DesignPanelPromoteProvider,
90908
90944
  {
90909
90945
  selection: domEditGroupSelections.length > 1 ? null : domEditSelection,
@@ -90915,7 +90951,7 @@ function StudioRightPanels({
90915
90951
  recordEdit,
90916
90952
  reloadPreview,
90917
90953
  forceReloadSharedSdkSession: forceReloadSdkSession,
90918
- children: /* @__PURE__ */ jsx230(
90954
+ children: /* @__PURE__ */ jsx231(
90919
90955
  PropertyPanel,
90920
90956
  {
90921
90957
  projectId,
@@ -90985,9 +91021,9 @@ function StudioRightPanels({
90985
91021
  );
90986
91022
  let designBody = propertyPanel;
90987
91023
  if (captionEditMode) {
90988
- designBody = /* @__PURE__ */ jsx230(CaptionPropertyPanel, { iframeRef: previewIframeRef });
91024
+ designBody = /* @__PURE__ */ jsx231(CaptionPropertyPanel, { iframeRef: previewIframeRef });
90989
91025
  } else if (activeBlockParams) {
90990
- designBody = /* @__PURE__ */ jsx230(
91026
+ designBody = /* @__PURE__ */ jsx231(
90991
91027
  BlockParamsPanel,
90992
91028
  {
90993
91029
  blockName: activeBlockParams.blockName,
@@ -90999,18 +91035,18 @@ function StudioRightPanels({
90999
91035
  }
91000
91036
  );
91001
91037
  }
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(
91038
+ return /* @__PURE__ */ jsxs185(Fragment60, { children: [
91039
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "design", children: designBody }),
91040
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "layers", children: /* @__PURE__ */ jsx231(LayersPanel, {}) }),
91041
+ /* @__PURE__ */ jsx231(
91006
91042
  Dock.Panel,
91007
91043
  {
91008
91044
  id: "renders",
91009
91045
  title: renderJobs.length > 0 ? `Renders (${renderJobs.length})` : void 0,
91010
- children: /* @__PURE__ */ jsx230(RenderQueuePanel, {})
91046
+ children: /* @__PURE__ */ jsx231(RenderQueuePanel, {})
91011
91047
  }
91012
91048
  ),
91013
- /* @__PURE__ */ jsx230(Dock.Panel, { id: "variables", children: /* @__PURE__ */ jsx230(
91049
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "variables", children: /* @__PURE__ */ jsx231(
91014
91050
  VariablesPanel,
91015
91051
  {
91016
91052
  sdkSession,
@@ -91019,7 +91055,7 @@ function StudioRightPanels({
91019
91055
  recordEdit
91020
91056
  }
91021
91057
  ) }),
91022
- /* @__PURE__ */ jsx230(Dock.Panel, { id: "slideshow", children: /* @__PURE__ */ jsx230(
91058
+ /* @__PURE__ */ jsx231(Dock.Panel, { id: "slideshow", children: /* @__PURE__ */ jsx231(
91023
91059
  SlideshowPanel,
91024
91060
  {
91025
91061
  scenes: slideshowScenes,
@@ -91446,9 +91482,9 @@ function useKeyframeKeyboard({
91446
91482
  }
91447
91483
 
91448
91484
  // src/components/icons/AudioMetersIcon.tsx
91449
- import { jsx as jsx231 } from "react/jsx-runtime";
91485
+ import { jsx as jsx232 } from "react/jsx-runtime";
91450
91486
  function AudioMetersIcon({ size = 16 }) {
91451
- return /* @__PURE__ */ jsx231(
91487
+ return /* @__PURE__ */ jsx232(
91452
91488
  "svg",
91453
91489
  {
91454
91490
  width: size,
@@ -91459,15 +91495,15 @@ function AudioMetersIcon({ size = 16 }) {
91459
91495
  strokeWidth: 1.5,
91460
91496
  strokeLinecap: "round",
91461
91497
  "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" })
91498
+ children: /* @__PURE__ */ jsx232("path", { d: "M2.5 13h2m-2-3h2M7 13h2m-2-3h2m-2-3h2m-2-3h2M11.5 13h2m-2-3h2m-2-3h2" })
91463
91499
  }
91464
91500
  );
91465
91501
  }
91466
91502
 
91467
91503
  // src/components/icons/RippleEditIcon.tsx
91468
- import { jsx as jsx232, jsxs as jsxs185 } from "react/jsx-runtime";
91504
+ import { jsx as jsx233, jsxs as jsxs186 } from "react/jsx-runtime";
91469
91505
  function RippleEditIcon({ size = 16 }) {
91470
- return /* @__PURE__ */ jsxs185(
91506
+ return /* @__PURE__ */ jsxs186(
91471
91507
  "svg",
91472
91508
  {
91473
91509
  width: size,
@@ -91480,9 +91516,9 @@ function RippleEditIcon({ size = 16 }) {
91480
91516
  strokeLinejoin: "round",
91481
91517
  "aria-hidden": "true",
91482
91518
  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" })
91519
+ /* @__PURE__ */ jsx233("rect", { x: "1.5", y: "8", width: "4", height: "5", rx: "0.5" }),
91520
+ /* @__PURE__ */ jsx233("rect", { x: "10.5", y: "8", width: "4", height: "5", rx: "0.5" }),
91521
+ /* @__PURE__ */ jsx233("path", { d: "M13 4H6m2-2L6 4l2 2" })
91486
91522
  ]
91487
91523
  }
91488
91524
  );
@@ -91495,10 +91531,10 @@ var flatActive = `${flatBtn} bg-white/8 text-neutral-100 active:scale-[0.98]`;
91495
91531
  var flatDisabled = `${flatBtn} text-neutral-700 cursor-not-allowed`;
91496
91532
 
91497
91533
  // src/components/TimelineHistoryButtons.tsx
91498
- import { Fragment as Fragment61, jsx as jsx233, jsxs as jsxs186 } from "react/jsx-runtime";
91534
+ import { Fragment as Fragment61, jsx as jsx234, jsxs as jsxs187 } from "react/jsx-runtime";
91499
91535
  function HistoryButton({ action, enabled, label, onClick }) {
91500
91536
  const Icon = action === "undo" ? RotateCcw : RotateCw;
91501
- return /* @__PURE__ */ jsx233(Tooltip, { label: historyTooltipLabel(action, label), children: /* @__PURE__ */ jsx233(
91537
+ return /* @__PURE__ */ jsx234(Tooltip, { label: historyTooltipLabel(action, label), children: /* @__PURE__ */ jsx234(
91502
91538
  "button",
91503
91539
  {
91504
91540
  type: "button",
@@ -91509,14 +91545,14 @@ function HistoryButton({ action, enabled, label, onClick }) {
91509
91545
  trackStudioEvent("toolbar_action", { action });
91510
91546
  void onClick();
91511
91547
  },
91512
- children: /* @__PURE__ */ jsx233(Icon, { size: 16 })
91548
+ children: /* @__PURE__ */ jsx234(Icon, { size: 16 })
91513
91549
  }
91514
91550
  ) });
91515
91551
  }
91516
91552
  function TimelineHistoryButtons() {
91517
91553
  const { editHistory, handleUndo, handleRedo } = useStudioShellContext();
91518
- return /* @__PURE__ */ jsxs186(Fragment61, { children: [
91519
- /* @__PURE__ */ jsx233(
91554
+ return /* @__PURE__ */ jsxs187(Fragment61, { children: [
91555
+ /* @__PURE__ */ jsx234(
91520
91556
  HistoryButton,
91521
91557
  {
91522
91558
  action: "undo",
@@ -91525,7 +91561,7 @@ function TimelineHistoryButtons() {
91525
91561
  onClick: handleUndo
91526
91562
  }
91527
91563
  ),
91528
- /* @__PURE__ */ jsx233(
91564
+ /* @__PURE__ */ jsx234(
91529
91565
  HistoryButton,
91530
91566
  {
91531
91567
  action: "redo",
@@ -91538,7 +91574,7 @@ function TimelineHistoryButtons() {
91538
91574
  }
91539
91575
 
91540
91576
  // src/components/TimelineToolbar.tsx
91541
- import { jsx as jsx234, jsxs as jsxs187 } from "react/jsx-runtime";
91577
+ import { jsx as jsx235, jsxs as jsxs188 } from "react/jsx-runtime";
91542
91578
  var NO_KEYFRAME_TOGGLE = {
91543
91579
  state: "none",
91544
91580
  isMotionPath: false,
@@ -91647,10 +91683,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91647
91683
  return (
91648
91684
  // The "TIMELINE" label is dropped for CapCut-like density — the pane's
91649
91685
  // 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(
91686
+ /* @__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: [
91687
+ /* @__PURE__ */ jsxs188("div", { className: "flex items-center gap-0.5", children: [
91688
+ /* @__PURE__ */ jsx235(TimelineHistoryButtons, {}),
91689
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Selection tool (V)", children: /* @__PURE__ */ jsx235(
91654
91690
  "button",
91655
91691
  {
91656
91692
  type: "button",
@@ -91658,10 +91694,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91658
91694
  "aria-label": "Selection tool",
91659
91695
  "aria-pressed": activeTool === "select",
91660
91696
  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" }) })
91697
+ 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
91698
  }
91663
91699
  ) }),
91664
- /* @__PURE__ */ jsx234(Tooltip, { label: "Razor tool (B) \u2014 Shift+click splits all tracks", children: /* @__PURE__ */ jsx234(
91700
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Razor tool (B) \u2014 Shift+click splits all tracks", children: /* @__PURE__ */ jsx235(
91665
91701
  "button",
91666
91702
  {
91667
91703
  type: "button",
@@ -91669,11 +91705,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91669
91705
  "aria-label": "Razor tool",
91670
91706
  "aria-pressed": activeTool === "razor",
91671
91707
  className: activeTool === "razor" ? flatActive : flatIdle,
91672
- children: /* @__PURE__ */ jsx234(Scissors, { size: 16 })
91708
+ children: /* @__PURE__ */ jsx235(Scissors, { size: 16 })
91673
91709
  }
91674
91710
  ) }),
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(
91711
+ /* @__PURE__ */ jsx235("div", { "aria-hidden": "true", className: "mx-1 h-4 w-px bg-neutral-800" }),
91712
+ /* @__PURE__ */ jsx235(Tooltip, { label: timelineSnapEnabled ? "Snapping on (N)" : "Snapping off (N)", children: /* @__PURE__ */ jsx235(
91677
91713
  "button",
91678
91714
  {
91679
91715
  type: "button",
@@ -91681,14 +91717,14 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91681
91717
  "aria-label": "Toggle timeline snapping",
91682
91718
  "aria-pressed": timelineSnapEnabled,
91683
91719
  className: timelineSnapEnabled ? flatActive : flatIdle,
91684
- children: /* @__PURE__ */ jsx234(Magnet, { size: 16, weight: "bold", "aria-hidden": "true" })
91720
+ children: /* @__PURE__ */ jsx235(Magnet, { size: 16, weight: "bold", "aria-hidden": "true" })
91685
91721
  }
91686
91722
  ) }),
91687
- /* @__PURE__ */ jsx234(
91723
+ /* @__PURE__ */ jsx235(
91688
91724
  Tooltip,
91689
91725
  {
91690
91726
  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(
91727
+ children: /* @__PURE__ */ jsx235(
91692
91728
  "button",
91693
91729
  {
91694
91730
  type: "button",
@@ -91696,12 +91732,12 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91696
91732
  "aria-label": "Toggle ripple edit",
91697
91733
  "aria-pressed": rippleEditEnabled,
91698
91734
  className: rippleEditEnabled ? flatActive : flatIdle,
91699
- children: /* @__PURE__ */ jsx234(RippleEditIcon, { size: 16 })
91735
+ children: /* @__PURE__ */ jsx235(RippleEditIcon, { size: 16 })
91700
91736
  }
91701
91737
  )
91702
91738
  }
91703
91739
  ),
91704
- projectHasAudio && /* @__PURE__ */ jsx234(Tooltip, { label: audioMetersVisible ? "Hide audio meters" : "Show audio meters", children: /* @__PURE__ */ jsx234(
91740
+ projectHasAudio && /* @__PURE__ */ jsx235(Tooltip, { label: audioMetersVisible ? "Hide audio meters" : "Show audio meters", children: /* @__PURE__ */ jsx235(
91705
91741
  "button",
91706
91742
  {
91707
91743
  type: "button",
@@ -91709,14 +91745,14 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91709
91745
  "aria-label": "Toggle audio meters",
91710
91746
  "aria-pressed": audioMetersVisible,
91711
91747
  className: audioMetersVisible ? flatActive : flatIdle,
91712
- children: /* @__PURE__ */ jsx234(AudioMetersIcon, { size: 16 })
91748
+ children: /* @__PURE__ */ jsx235(AudioMetersIcon, { size: 16 })
91713
91749
  }
91714
91750
  ) }),
91715
- /* @__PURE__ */ jsx234(
91751
+ /* @__PURE__ */ jsx235(
91716
91752
  Tooltip,
91717
91753
  {
91718
91754
  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(
91755
+ children: /* @__PURE__ */ jsx235(
91720
91756
  "button",
91721
91757
  {
91722
91758
  type: "button",
@@ -91724,7 +91760,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91724
91760
  onClick: onToggleKeyframe,
91725
91761
  "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
91762
  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(
91763
+ 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
91764
  "path",
91729
91765
  {
91730
91766
  d: "M5 1.2L8.8 5L5 8.8L1.2 5Z",
@@ -91737,11 +91773,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91737
91773
  )
91738
91774
  }
91739
91775
  ),
91740
- /* @__PURE__ */ jsx234(
91776
+ /* @__PURE__ */ jsx235(
91741
91777
  Tooltip,
91742
91778
  {
91743
91779
  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(
91780
+ children: /* @__PURE__ */ jsx235(
91745
91781
  "button",
91746
91782
  {
91747
91783
  type: "button",
@@ -91749,9 +91785,9 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91749
91785
  "aria-label": "Auto-record manual edits as keyframes",
91750
91786
  "aria-pressed": autoKeyframeEnabled,
91751
91787
  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(
91788
+ children: /* @__PURE__ */ jsxs188("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "none", children: [
91789
+ /* @__PURE__ */ jsx235("path", { d: "M5 0.7L9.3 5L5 9.3L0.7 5Z", stroke: "currentColor", strokeWidth: "1" }),
91790
+ /* @__PURE__ */ jsx235(
91755
91791
  "circle",
91756
91792
  {
91757
91793
  cx: "5",
@@ -91771,11 +91807,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91771
91807
  const el = selectedElementId ? elements.find((e) => (e.key ?? e.id) === selectedElementId) : null;
91772
91808
  const splittable = el != null && canSplitElement(el);
91773
91809
  const canSplit = splittable && currentTime > el.start && currentTime < el.start + el.duration;
91774
- return /* @__PURE__ */ jsx234(
91810
+ return /* @__PURE__ */ jsx235(
91775
91811
  Tooltip,
91776
91812
  {
91777
91813
  label: canSplit ? "Split at playhead (S)" : splittable ? "Move the playhead inside the clip to split" : "Select a clip to split",
91778
- children: /* @__PURE__ */ jsx234(
91814
+ children: /* @__PURE__ */ jsx235(
91779
91815
  "button",
91780
91816
  {
91781
91817
  type: "button",
@@ -91785,7 +91821,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91785
91821
  if (canSplit && el) onSplitElement(el, currentTime);
91786
91822
  },
91787
91823
  className: canSplit ? flatIdle : flatDisabled,
91788
- children: /* @__PURE__ */ jsxs187(
91824
+ children: /* @__PURE__ */ jsxs188(
91789
91825
  "svg",
91790
91826
  {
91791
91827
  width: "16",
@@ -91798,8 +91834,8 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91798
91834
  strokeLinejoin: "round",
91799
91835
  "aria-hidden": "true",
91800
91836
  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" })
91837
+ /* @__PURE__ */ jsx235("path", { d: "M5 3 L7 3 L7 13 L5 13" }),
91838
+ /* @__PURE__ */ jsx235("path", { d: "M11 3 L9 3 L9 13 L11 13" })
91803
91839
  ]
91804
91840
  }
91805
91841
  )
@@ -91810,11 +91846,11 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91810
91846
  })(),
91811
91847
  (() => {
91812
91848
  const canAdd = beatAnalysisReady && canAddBeatAt(currentTime);
91813
- return /* @__PURE__ */ jsx234(
91849
+ return /* @__PURE__ */ jsx235(
91814
91850
  Tooltip,
91815
91851
  {
91816
91852
  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(
91853
+ children: /* @__PURE__ */ jsx235(
91818
91854
  "button",
91819
91855
  {
91820
91856
  type: "button",
@@ -91824,7 +91860,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91824
91860
  if (canAdd) addBeatAtCompositionTime(currentTime);
91825
91861
  },
91826
91862
  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(
91863
+ children: /* @__PURE__ */ jsx235("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx235(
91828
91864
  "path",
91829
91865
  {
91830
91866
  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 +91876,12 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91840
91876
  );
91841
91877
  })()
91842
91878
  ] }),
91843
- /* @__PURE__ */ jsxs187("div", { className: "flex items-center gap-0.5", children: [
91844
- /* @__PURE__ */ jsx234(
91879
+ /* @__PURE__ */ jsxs188("div", { className: "flex items-center gap-0.5", children: [
91880
+ /* @__PURE__ */ jsx235(
91845
91881
  Tooltip,
91846
91882
  {
91847
91883
  label: thumbnailsVisible ? "Hide thumbnails \u2014 labels only" : "Show thumbnails \u2014 posters stay visible; richer previews appear on interaction",
91848
- children: /* @__PURE__ */ jsx234(
91884
+ children: /* @__PURE__ */ jsx235(
91849
91885
  "button",
91850
91886
  {
91851
91887
  type: "button",
@@ -91853,12 +91889,12 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91853
91889
  "aria-pressed": thumbnailsVisible,
91854
91890
  onClick: () => setThumbnailMode(thumbnailsVisible ? "hidden" : "adaptive"),
91855
91891
  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" })
91892
+ children: /* @__PURE__ */ jsx235(Image3, { size: 16, "aria-hidden": "true" })
91857
91893
  }
91858
91894
  )
91859
91895
  }
91860
91896
  ),
91861
- /* @__PURE__ */ jsx234(Tooltip, { label: "Fit timeline to width", children: /* @__PURE__ */ jsx234(
91897
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Fit timeline to width", children: /* @__PURE__ */ jsx235(
91862
91898
  "button",
91863
91899
  {
91864
91900
  type: "button",
@@ -91867,7 +91903,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91867
91903
  children: "Fit"
91868
91904
  }
91869
91905
  ) }),
91870
- /* @__PURE__ */ jsx234(Tooltip, { label: "Zoom out", children: /* @__PURE__ */ jsx234(
91906
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Zoom out", children: /* @__PURE__ */ jsx235(
91871
91907
  "button",
91872
91908
  {
91873
91909
  type: "button",
@@ -91879,10 +91915,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91879
91915
  );
91880
91916
  },
91881
91917
  className: flatIdle,
91882
- children: /* @__PURE__ */ jsx234(MagnifyingGlassMinus, { size: 16, "aria-hidden": "true" })
91918
+ children: /* @__PURE__ */ jsx235(MagnifyingGlassMinus, { size: 16, "aria-hidden": "true" })
91883
91919
  }
91884
91920
  ) }),
91885
- /* @__PURE__ */ jsx234(
91921
+ /* @__PURE__ */ jsx235(
91886
91922
  "input",
91887
91923
  {
91888
91924
  type: "range",
@@ -91900,7 +91936,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91900
91936
  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
91937
  }
91902
91938
  ),
91903
- /* @__PURE__ */ jsx234(Tooltip, { label: "Zoom in", children: /* @__PURE__ */ jsx234(
91939
+ /* @__PURE__ */ jsx235(Tooltip, { label: "Zoom in", children: /* @__PURE__ */ jsx235(
91904
91940
  "button",
91905
91941
  {
91906
91942
  type: "button",
@@ -91912,10 +91948,10 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91912
91948
  );
91913
91949
  },
91914
91950
  className: flatIdle,
91915
- children: /* @__PURE__ */ jsx234(MagnifyingGlassPlus, { size: 16, "aria-hidden": "true" })
91951
+ children: /* @__PURE__ */ jsx235(MagnifyingGlassPlus, { size: 16, "aria-hidden": "true" })
91916
91952
  }
91917
91953
  ) }),
91918
- /* @__PURE__ */ jsx234(
91954
+ /* @__PURE__ */ jsx235(
91919
91955
  "span",
91920
91956
  {
91921
91957
  className: "ml-1 w-[38px] text-right font-mono text-[11px] tabular-nums text-neutral-500 select-none",
@@ -91929,18 +91965,18 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
91929
91965
  }
91930
91966
 
91931
91967
  // src/components/StudioSplash.tsx
91932
- import { jsx as jsx235, jsxs as jsxs188 } from "react/jsx-runtime";
91968
+ import { jsx as jsx236, jsxs as jsxs189 } from "react/jsx-runtime";
91933
91969
  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: [
91970
+ 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: [
91971
+ /* @__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" }),
91972
+ /* @__PURE__ */ jsxs189("p", { className: "text-xs text-neutral-600", children: [
91937
91973
  "Waiting for preview server\u2026 run",
91938
91974
  " ",
91939
- /* @__PURE__ */ jsx235("code", { className: "text-neutral-500 font-mono", children: "npm run dev" })
91975
+ /* @__PURE__ */ jsx236("code", { className: "text-neutral-500 font-mono", children: "npm run dev" })
91940
91976
  ] })
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" })
91977
+ ] }) : /* @__PURE__ */ jsxs189("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
91978
+ /* @__PURE__ */ jsx236("div", { className: "w-4 h-4 rounded-full bg-studio-accent animate-pulse motion-reduce:animate-none" }),
91979
+ /* @__PURE__ */ jsx236("p", { className: "text-xs text-neutral-600", children: "Connecting to project\u2026" })
91944
91980
  ] }) });
91945
91981
  }
91946
91982
 
@@ -92207,7 +92243,7 @@ function useActiveComposition({
92207
92243
  }
92208
92244
 
92209
92245
  // src/App.tsx
92210
- import { Fragment as Fragment62, jsx as jsx236, jsxs as jsxs189 } from "react/jsx-runtime";
92246
+ import { Fragment as Fragment62, jsx as jsx237, jsxs as jsxs190 } from "react/jsx-runtime";
92211
92247
  var getTimelineSelectionSet = () => usePlayerStore.getState().selectedElementIds;
92212
92248
  function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92213
92249
  const { projectId, resolving, waitingForServer } = useServerConnection();
@@ -92266,7 +92302,8 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92266
92302
  activeCompPath,
92267
92303
  masterCompPath,
92268
92304
  fileManager.fileTree,
92269
- fileManager.fileTreeLoaded
92305
+ fileManager.fileTreeLoaded,
92306
+ fileManager.refreshFileTree
92270
92307
  );
92271
92308
  const activeCompPathRef = useRef185(activeCompPath);
92272
92309
  activeCompPathRef.current = activeCompPath;
@@ -92565,7 +92602,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92565
92602
  refreshPreviewDocumentVersion
92566
92603
  });
92567
92604
  const timelineToolbar = useMemo77(
92568
- () => /* @__PURE__ */ jsx236(
92605
+ () => /* @__PURE__ */ jsx237(
92569
92606
  TimelineToolbar,
92570
92607
  {
92571
92608
  domEditSession,
@@ -92575,15 +92612,15 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92575
92612
  [domEditSession, timelineEditing.handleTimelineElementSplit]
92576
92613
  );
92577
92614
  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(
92615
+ return /* @__PURE__ */ jsx237(StudioSplash, { waiting: waitingForServer });
92616
+ 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
92617
  "div",
92581
92618
  {
92582
92619
  className: "flex flex-col h-full w-full bg-neutral-950 relative",
92583
92620
  onDragOver: fileDrop.onDragOver,
92584
92621
  onDrop: fileDrop.onDrop,
92585
92622
  children: [
92586
- /* @__PURE__ */ jsx236(
92623
+ /* @__PURE__ */ jsx237(
92587
92624
  StudioHeader,
92588
92625
  {
92589
92626
  captureFrameHref: frameCapture.captureFrameHref,
@@ -92601,22 +92638,23 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92601
92638
  }
92602
92639
  }
92603
92640
  ),
92604
- previewPersistence.domEditSaveQueuePaused && !externalFileChanges.blocked && /* @__PURE__ */ jsx236(
92641
+ previewPersistence.domEditSaveQueuePaused && !externalFileChanges.blocked && /* @__PURE__ */ jsx237(
92605
92642
  SaveQueuePausedBanner,
92606
92643
  {
92607
92644
  message: previewPersistence.domEditSaveQueuePaused,
92608
92645
  onRetry: previewPersistence.resetDomEditSaveQueueBreaker
92609
92646
  }
92610
92647
  ),
92611
- /* @__PURE__ */ jsx236(ExternalFileConflictBanner, { coordinator: externalFileChanges }),
92612
- sdkHandle.unreachableProject && /* @__PURE__ */ jsx236(ProjectUnreachableBanner, { projectId: sdkHandle.unreachableProject }),
92613
- /* @__PURE__ */ jsx236(
92648
+ /* @__PURE__ */ jsx237(ExternalFileConflictBanner, { coordinator: externalFileChanges }),
92649
+ sdkHandle.unreachableProject && /* @__PURE__ */ jsx237(ProjectUnreachableBanner, { projectId: sdkHandle.unreachableProject }),
92650
+ sdkHandle.compositionMissing && activeCompPath && /* @__PURE__ */ jsx237(CompositionMissingBanner, { path: activeCompPath }),
92651
+ /* @__PURE__ */ jsx237(
92614
92652
  EditorShell,
92615
92653
  {
92616
92654
  readOnlyPreview,
92617
92655
  readOnlyPreviewReason,
92618
- panels: /* @__PURE__ */ jsxs189(Fragment62, { children: [
92619
- /* @__PURE__ */ jsx236(
92656
+ panels: /* @__PURE__ */ jsxs190(Fragment62, { children: [
92657
+ /* @__PURE__ */ jsx237(
92620
92658
  StudioLeftPanels,
92621
92659
  {
92622
92660
  onSelectComposition: handleSelectComposition,
@@ -92631,7 +92669,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92631
92669
  onAddCompositionToTimeline: handleAddCompositionAtPlayhead
92632
92670
  }
92633
92671
  ),
92634
- /* @__PURE__ */ jsx236(
92672
+ /* @__PURE__ */ jsx237(
92635
92673
  StudioRightPanels,
92636
92674
  {
92637
92675
  activeBlockParams,
@@ -92686,7 +92724,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92686
92724
  recordingState: gestureState,
92687
92725
  onToggleRecording: handleToggleRecording,
92688
92726
  blockPreview,
92689
- gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */ jsx236(
92727
+ gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */ jsx237(
92690
92728
  GestureTrailOverlay,
92691
92729
  {
92692
92730
  samples: gestureRecording.samplesRef.current,
@@ -92699,7 +92737,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92699
92737
  ) : void 0
92700
92738
  }
92701
92739
  ),
92702
- /* @__PURE__ */ jsx236(
92740
+ /* @__PURE__ */ jsx237(
92703
92741
  StudioOverlays,
92704
92742
  {
92705
92743
  projectId,