@hyperframes/studio 0.8.103 → 0.8.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/dist/assets/{hyperframes-player-DG795Hwu.js → hyperframes-player-tnfCiVdR.js} +1 -1
  2. package/dist/assets/{index-BiEtDkae.js → index-Ca6LZlVb.js} +1 -1
  3. package/dist/assets/index-Cre9X4RS.css +1 -0
  4. package/dist/assets/{index-BPJRf2X9.js → index-DEDhPmPD.js} +215 -215
  5. package/dist/assets/{index-DuCZ3pQw.js → index-zpe332hb.js} +1 -1
  6. package/dist/{chunk-62DDWOSH.js → chunk-EEXSYY5F.js} +19 -18
  7. package/dist/chunk-EEXSYY5F.js.map +1 -0
  8. package/dist/{chunk-6GAO75IU.js → chunk-NCUBAVGK.js} +10 -8
  9. package/dist/chunk-NCUBAVGK.js.map +1 -0
  10. package/dist/{chunk-HIGHVWYD.js → chunk-QADHJFDF.js} +2 -2
  11. package/dist/index.css +6 -1
  12. package/dist/index.css.map +1 -1
  13. package/dist/index.d.ts +181 -168
  14. package/dist/index.html +2 -2
  15. package/dist/index.js +1018 -919
  16. package/dist/index.js.map +1 -1
  17. package/dist/player.js +2 -2
  18. package/dist/styles/tailwind-preset.js.map +1 -1
  19. package/dist/styles.css +1 -1
  20. package/dist/ui.js +2 -2
  21. package/package.json +8 -8
  22. package/src/captions/components/CaptionAnimationPanel.tsx +2 -2
  23. package/src/captions/components/CaptionPropertyPanel.tsx +2 -2
  24. package/src/captions/components/CaptionTimeline.tsx +3 -3
  25. package/src/components/AskAgentModal.tsx +1 -1
  26. package/src/components/LintModal.tsx +35 -35
  27. package/src/components/StudioErrorBoundary.tsx +1 -1
  28. package/src/components/StudioHeader.dom.test.tsx +4 -4
  29. package/src/components/StudioHeader.tsx +2 -1
  30. package/src/components/StudioToast.tsx +7 -16
  31. package/src/components/TimelineToolPicker.tsx +1 -1
  32. package/src/components/TimelineToolbar.tsx +11 -11
  33. package/src/components/dock/Dock.tsx +1 -1
  34. package/src/components/dock/dock.css +9 -1
  35. package/src/components/editor/AnimationCard.tsx +5 -5
  36. package/src/components/editor/AnimationCardParts.tsx +1 -1
  37. package/src/components/editor/BlockParamsPanel.tsx +3 -3
  38. package/src/components/editor/BorderRadiusEditor.tsx +8 -15
  39. package/src/components/editor/CanvasContextMenu.tsx +1 -1
  40. package/src/components/editor/ComputedTweenNotice.tsx +1 -1
  41. package/src/components/editor/DomEditOverlay.tsx +5 -6
  42. package/src/components/editor/DomEditRotateHandle.tsx +1 -1
  43. package/src/components/editor/EaseCurveSection.tsx +14 -19
  44. package/src/components/editor/EaseModeControls.tsx +2 -2
  45. package/src/components/editor/EaseParamFields.tsx +8 -8
  46. package/src/components/editor/FileTree.tsx +1 -1
  47. package/src/components/editor/FileTreeIcons.tsx +47 -26
  48. package/src/components/editor/FileTreeNodes.tsx +11 -8
  49. package/src/components/editor/GestureRecordControl.tsx +3 -3
  50. package/src/components/editor/GsapAddAnimationControl.tsx +1 -1
  51. package/src/components/editor/GsapAnimationSection.tsx +2 -2
  52. package/src/components/editor/InlineTextToolbar.tsx +4 -4
  53. package/src/components/editor/InspectorHeaderActions.tsx +1 -1
  54. package/src/components/editor/KeyframeDiamond.tsx +6 -4
  55. package/src/components/editor/KeyframeNavigation.tsx +4 -4
  56. package/src/components/editor/LayersPanel.tsx +3 -3
  57. package/src/components/editor/PromotableControl.tsx +2 -2
  58. package/src/components/editor/PropertyPanel.tsx +3 -3
  59. package/src/components/editor/PropertyPanelEmptyState.tsx +4 -4
  60. package/src/components/editor/PropertyPanelFlatFooter.tsx +2 -2
  61. package/src/components/editor/PropertyPanelFlatHeader.test.tsx +1 -1
  62. package/src/components/editor/PropertyPanelFlatHeader.tsx +2 -2
  63. package/src/components/editor/SnapToolbar.tsx +5 -5
  64. package/src/components/editor/TimelineFxPopover.tsx +4 -4
  65. package/src/components/editor/Transform3DCube.tsx +1 -1
  66. package/src/components/editor/anchoredResizeCommitFeedsOffset.test.ts +46 -6
  67. package/src/components/editor/anchoredResizeReleaseShift.test.ts +0 -84
  68. package/src/components/editor/domEditOverlayGestures.ts +13 -19
  69. package/src/components/editor/domEditOverlayStartGesture.test.ts +170 -13
  70. package/src/components/editor/domEditOverlayStartGesture.ts +15 -25
  71. package/src/components/editor/easeCurveSvg.tsx +1 -1
  72. package/src/components/editor/manualEdits.test.ts +3 -9
  73. package/src/components/editor/manualEdits.ts +0 -1
  74. package/src/components/editor/manualEditsDom.ts +3 -13
  75. package/src/components/editor/manualEditsDomPatches.test.ts +3 -131
  76. package/src/components/editor/manualEditsDomPatches.ts +1 -53
  77. package/src/components/editor/manualEditsSnapshot.ts +3 -0
  78. package/src/components/editor/manualEditsTypes.ts +2 -0
  79. package/src/components/editor/manualOffsetDrag.test.ts +41 -0
  80. package/src/components/editor/manualOffsetDrag.ts +6 -27
  81. package/src/components/editor/persistSeam.integration.test.ts +0 -18
  82. package/src/components/editor/plainTranslate.ts +42 -6
  83. package/src/components/editor/propertyPanelColorCurveGraph.tsx +2 -2
  84. package/src/components/editor/propertyPanelColorGradingControls.tsx +1 -1
  85. package/src/components/editor/propertyPanelColorGradingSection.tsx +8 -8
  86. package/src/components/editor/propertyPanelColorGradingSlider.tsx +1 -1
  87. package/src/components/editor/propertyPanelColorSecondary.tsx +4 -4
  88. package/src/components/editor/propertyPanelFill.tsx +6 -6
  89. package/src/components/editor/propertyPanelFlatColorGradingAccessory.tsx +3 -3
  90. package/src/components/editor/propertyPanelFlatColorGradingSection.test.tsx +1 -1
  91. package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +6 -9
  92. package/src/components/editor/propertyPanelFlatEffectsSection.tsx +4 -4
  93. package/src/components/editor/propertyPanelFlatMediaSection.tsx +2 -2
  94. package/src/components/editor/propertyPanelFlatMotionSection.tsx +2 -2
  95. package/src/components/editor/propertyPanelFlatOverlaysSection.tsx +2 -2
  96. package/src/components/editor/propertyPanelFlatPrimitives.test.tsx +4 -3
  97. package/src/components/editor/propertyPanelFlatPrimitives.tsx +1 -1
  98. package/src/components/editor/propertyPanelFlatSliderReadout.tsx +1 -1
  99. package/src/components/editor/propertyPanelFont.tsx +2 -2
  100. package/src/components/editor/propertyPanelFxCarveModule.tsx +1 -1
  101. package/src/components/editor/propertyPanelFxControls.tsx +2 -2
  102. package/src/components/editor/propertyPanelFxEqModule.tsx +2 -2
  103. package/src/components/editor/propertyPanelFxNodeRow.tsx +1 -1
  104. package/src/components/editor/propertyPanelFxPresetRun.tsx +1 -1
  105. package/src/components/editor/propertyPanelMediaSection.tsx +1 -1
  106. package/src/components/editor/propertyPanelPrimitives.tsx +1 -1
  107. package/src/components/editor/propertyPanelSections.tsx +2 -2
  108. package/src/components/editor/propertyPanelTransformCommit.test.ts +29 -0
  109. package/src/components/editor/propertyPanelTransformCommit.ts +8 -5
  110. package/src/components/editor/propertyPanelTypes.ts +1 -0
  111. package/src/components/editor/propertyPanelValueTier.test.ts +1 -1
  112. package/src/components/editor/propertyPanelValueTier.ts +1 -1
  113. package/src/components/editor/rotateInlineSave.test.ts +111 -0
  114. package/src/components/editor/rotationDraft.test.ts +111 -0
  115. package/src/components/editor/rotationDraft.ts +145 -0
  116. package/src/components/editor/useDomEditNudge.test.tsx +33 -0
  117. package/src/components/editor/useDomEditNudge.ts +6 -2
  118. package/src/components/editor/useDomEditOverlayGestures.ts +22 -24
  119. package/src/components/feedback/StudioFeedbackCard.tsx +11 -23
  120. package/src/components/nle/AssetPreviewOverlay.tsx +1 -1
  121. package/src/components/nle/AudioMeterStrip.tsx +2 -2
  122. package/src/components/nle/NLEPreview.test.ts +8 -4
  123. package/src/components/nle/PreviewOverlays.tsx +1 -1
  124. package/src/components/nle/PreviewPane.tsx +3 -3
  125. package/src/components/nle/PreviewPoster.tsx +29 -1
  126. package/src/components/nle/PreviewZoomOverlay.tsx +1 -1
  127. package/src/components/panels/SlideshowPanel.tsx +4 -4
  128. package/src/components/panels/SlideshowSubPanels.tsx +19 -21
  129. package/src/components/panels/VariablesBindElement.tsx +1 -1
  130. package/src/components/panels/VariablesDeclarationForm.tsx +1 -1
  131. package/src/components/panels/VariablesPanel.tsx +4 -6
  132. package/src/components/panels/VariablesRowAction.tsx +1 -1
  133. package/src/components/renders/FfmpegRequiredNotice.tsx +4 -4
  134. package/src/components/renders/RenderQueue.tsx +2 -2
  135. package/src/components/renders/RenderQueueItem.tsx +3 -3
  136. package/src/components/sidebar/AssetCard.tsx +3 -3
  137. package/src/components/sidebar/AssetContextMenu.tsx +7 -7
  138. package/src/components/sidebar/AssetsTab.tsx +6 -6
  139. package/src/components/sidebar/AudioRow.tsx +5 -3
  140. package/src/components/sidebar/BlocksTab.tsx +6 -6
  141. package/src/components/sidebar/CompositionsTab.drag.test.tsx +3 -69
  142. package/src/components/sidebar/CompositionsTab.rootBadge.test.tsx +4 -50
  143. package/src/components/sidebar/CompositionsTab.thumbnails.test.tsx +256 -0
  144. package/src/components/sidebar/CompositionsTab.tsx +65 -12
  145. package/src/components/sidebar/PromptPreviewModal.tsx +3 -3
  146. package/src/components/sidebar/SidebarLintButton.tsx +3 -3
  147. package/src/components/sidebar/compositionsTabTestUtils.tsx +39 -0
  148. package/src/components/timelineToolbarStyles.ts +3 -3
  149. package/src/components/ui/Button.tsx +4 -4
  150. package/src/components/ui/HyperframesLogo.tsx +19 -18
  151. package/src/components/ui/Input.tsx +1 -1
  152. package/src/components/ui/Menu.tsx +4 -2
  153. package/src/hooks/draggedGsapPosition.ts +28 -0
  154. package/src/hooks/elementOffsetStager.ts +34 -13
  155. package/src/hooks/gsapRuntimeBridge.ts +5 -3
  156. package/src/hooks/gsapRuntimeKeyframes.ts +36 -2
  157. package/src/hooks/plainRotation.test.ts +122 -0
  158. package/src/hooks/plainRotation.ts +42 -0
  159. package/src/hooks/useClipboard.source.test.ts +42 -4
  160. package/src/hooks/useClipboard.ts +13 -3
  161. package/src/hooks/useDomEditCommits.ts +0 -3
  162. package/src/hooks/useDomEditSession.ts +5 -5
  163. package/src/hooks/useDomGeometryCommit.test.tsx +79 -1
  164. package/src/hooks/useDomGeometryCommit.ts +16 -17
  165. package/src/hooks/useDomGeometryCommits.test.tsx +233 -33
  166. package/src/hooks/useDomGeometryCommits.ts +27 -80
  167. package/src/hooks/useGsapAwareEditing.test.tsx +194 -11
  168. package/src/hooks/useGsapAwareEditing.ts +43 -42
  169. package/src/hooks/useInlineTextEdit.test.tsx +33 -3
  170. package/src/hooks/useInlineTextEdit.ts +2 -2
  171. package/src/player/components/ClipContextMenu.tsx +1 -1
  172. package/src/player/components/CompositionThumbnail.tsx +23 -11
  173. package/src/player/components/EditModal.tsx +6 -6
  174. package/src/player/components/KeyframeDiamondContextMenu.tsx +2 -2
  175. package/src/player/components/PlayerControls.tsx +3 -3
  176. package/src/player/components/ShortcutsPanel.tsx +8 -20
  177. package/src/player/components/TimelineCanvas.tsx +1 -1
  178. package/src/player/components/TimelineClip.tsx +2 -2
  179. package/src/player/components/TimelineEmptyState.tsx +2 -2
  180. package/src/player/components/TimelineLanes.tsx +0 -1
  181. package/src/player/components/TrackClipCount.tsx +1 -1
  182. package/src/player/components/VolumeControl.tsx +1 -1
  183. package/src/player/components/timelineClipChildren.tsx +1 -1
  184. package/src/player/components/timelineMotionStyles.test.ts +6 -22
  185. package/src/player/components/trackHeaderLabelRows.tsx +16 -16
  186. package/src/player/lib/thumbnailScheduler.ts +4 -5
  187. package/src/player/lib/timelineViewportBudgets.test.ts +1 -1
  188. package/src/player/lib/timelineViewportBudgets.ts +1 -1
  189. package/src/styles/hex-baseline.json +7 -19
  190. package/src/styles/studio.css +0 -9
  191. package/src/styles/tailwind-preset.shared.js +2 -1
  192. package/src/styles/theme.css +204 -147
  193. package/src/styles/theme.test.ts +13 -9
  194. package/src/utils/blockCategories.ts +41 -9
  195. package/src/utils/clipboardPayload.ts +2 -0
  196. package/dist/assets/index-CQN3M56N.css +0 -1
  197. package/dist/chunk-62DDWOSH.js.map +0 -1
  198. package/dist/chunk-6GAO75IU.js.map +0 -1
  199. package/src/hooks/gsapTargetCache.ts +0 -62
  200. /package/dist/{chunk-HIGHVWYD.js.map → chunk-QADHJFDF.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HyperframesLogo
3
- } from "./chunk-62DDWOSH.js";
3
+ } from "./chunk-EEXSYY5F.js";
4
4
  import {
5
5
  DOCK_PANEL_COMPONENT,
6
6
  LAYER_REVEAL_PRIOR_POSITION_ATTR,
@@ -67,7 +67,7 @@ import {
67
67
  whenPreviewBooted,
68
68
  wrapTimeline,
69
69
  writeStudioUiPreferences
70
- } from "./chunk-HIGHVWYD.js";
70
+ } from "./chunk-QADHJFDF.js";
71
71
  import {
72
72
  Button,
73
73
  ContextMenu,
@@ -99,7 +99,7 @@ import {
99
99
  fieldBase,
100
100
  fieldText,
101
101
  popupSurface
102
- } from "./chunk-6GAO75IU.js";
102
+ } from "./chunk-NCUBAVGK.js";
103
103
  import {
104
104
  DOM_EDIT_LAYER_OBSERVER_INIT,
105
105
  buildDefaultDomEditTextField,
@@ -532,6 +532,12 @@ if (typeof window !== "undefined") {
532
532
  // src/player/components/ShortcutsPanel.tsx
533
533
  import { useState, useCallback as useCallback2, useEffect as useEffect2, useId, useRef as useRef2, memo } from "react";
534
534
 
535
+ // src/components/timelineToolbarStyles.ts
536
+ var flatBtn = "flex h-7 w-7 items-center justify-center rounded-md transition-colors";
537
+ var flatIdle = `${flatBtn} text-text-2 hover:bg-hover hover:text-text-0 active:bg-press active:scale-[0.98]`;
538
+ var flatActive = `${flatBtn} bg-on text-text-0 hover:bg-on-hover active:scale-[0.98]`;
539
+ var flatDisabled = `${flatBtn} text-text-off cursor-not-allowed`;
540
+
535
541
  // src/hooks/useContextMenuDismiss.ts
536
542
  import { useCallback, useEffect, useRef } from "react";
537
543
  function useContextMenuDismiss(onClose) {
@@ -709,7 +715,7 @@ var ShortcutsPanel = memo(function ShortcutsPanel2({
709
715
  ref: triggerRef,
710
716
  type: "button",
711
717
  onClick: () => setShowShortcuts((v) => !v),
712
- className: `flex h-7 w-7 items-center justify-center rounded-md transition-colors ${showShortcuts ? "text-neutral-200" : "text-neutral-600 hover:text-neutral-300"}`,
718
+ className: showShortcuts ? flatActive : flatIdle,
713
719
  "aria-label": "Shortcuts and tools",
714
720
  "aria-expanded": showShortcuts,
715
721
  "aria-controls": shortcutsPanelId,
@@ -741,10 +747,8 @@ var ShortcutsPanel = memo(function ShortcutsPanel2({
741
747
  tabIndex: -1,
742
748
  role: "dialog",
743
749
  "aria-label": "Keyboard shortcuts and tools",
744
- className: "absolute bottom-full right-0 mb-2 z-50 rounded-lg shadow-xl min-w-[220px] overflow-y-auto outline-hidden",
750
+ className: "absolute bottom-full right-0 mb-2 z-50 rounded-lg border border-border bg-raised shadow-popover min-w-[220px] overflow-y-auto outline-hidden",
745
751
  style: {
746
- background: "#161618",
747
- border: "1px solid rgba(255,255,255,0.08)",
748
752
  maxHeight: "min(280px, calc(100vh - 80px))"
749
753
  },
750
754
  children: [
@@ -777,20 +781,13 @@ var ShortcutsPanel = memo(function ShortcutsPanel2({
777
781
  ) })
778
782
  ] })
779
783
  ] }),
780
- /* @__PURE__ */ jsx("div", { style: { borderTop: "1px solid rgba(255,255,255,0.06)" } }),
784
+ /* @__PURE__ */ jsx("div", { className: "border-t border-border" }),
781
785
  /* @__PURE__ */ jsxs("div", { className: "px-3 pt-2.5 pb-2", children: [
782
786
  /* @__PURE__ */ jsx("p", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider mb-1.5", children: "Work area" }),
783
787
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
784
788
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
785
789
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
786
- /* @__PURE__ */ jsx(
787
- "span",
788
- {
789
- className: "font-mono text-[10px] rounded-sm border border-neutral-700 px-1.5 py-0.5 text-neutral-300 min-w-[20px] text-center",
790
- style: { background: "rgba(255,255,255,0.05)" },
791
- children: "I"
792
- }
793
- ),
790
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[10px] rounded-sm border border-neutral-700 px-1.5 py-0.5 text-neutral-300 min-w-[20px] text-center bg-hover", children: "I" }),
794
791
  /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-400", children: "In-point" })
795
792
  ] }),
796
793
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: inPoint !== null ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -820,14 +817,7 @@ var ShortcutsPanel = memo(function ShortcutsPanel2({
820
817
  ] }),
821
818
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
822
819
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
823
- /* @__PURE__ */ jsx(
824
- "span",
825
- {
826
- className: "font-mono text-[10px] rounded-sm border border-neutral-700 px-1.5 py-0.5 text-neutral-300 min-w-[20px] text-center",
827
- style: { background: "rgba(255,255,255,0.05)" },
828
- children: "O"
829
- }
830
- ),
820
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[10px] rounded-sm border border-neutral-700 px-1.5 py-0.5 text-neutral-300 min-w-[20px] text-center bg-hover", children: "O" }),
831
821
  /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-400", children: "Out-point" })
832
822
  ] }),
833
823
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: outPoint !== null ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -857,18 +847,11 @@ var ShortcutsPanel = memo(function ShortcutsPanel2({
857
847
  ] })
858
848
  ] })
859
849
  ] }),
860
- /* @__PURE__ */ jsx("div", { style: { borderTop: "1px solid rgba(255,255,255,0.06)" } }),
850
+ /* @__PURE__ */ jsx("div", { className: "border-t border-border" }),
861
851
  /* @__PURE__ */ jsx("div", { className: "px-3 pt-2.5 pb-3 flex flex-col gap-3", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs("div", { children: [
862
852
  /* @__PURE__ */ jsx("p", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider mb-1.5", children: section.title }),
863
853
  /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: section.hints.map((hint, hintIndex) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
864
- /* @__PURE__ */ jsx(
865
- "span",
866
- {
867
- className: "font-mono text-[10px] rounded-sm border border-neutral-700 px-1.5 py-0.5 text-neutral-300 min-w-[36px] text-center",
868
- style: { background: "rgba(255,255,255,0.05)" },
869
- children: hint.key
870
- }
871
- ),
854
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[10px] rounded-sm border border-neutral-700 px-1.5 py-0.5 text-neutral-300 min-w-[36px] text-center bg-hover", children: hint.key }),
872
855
  /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-400", children: hint.label })
873
856
  ] }, hintIndex)) })
874
857
  ] }, sectionIndex)) })
@@ -1039,7 +1022,7 @@ var VolumeControl = memo3(function VolumeControl2({
1039
1022
  disabled,
1040
1023
  "aria-label": muteLabel,
1041
1024
  "aria-pressed": silent,
1042
- className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-md transition-colors disabled:pointer-events-none disabled:opacity-30 ${silent ? "text-studio-accent" : "text-neutral-500 hover:text-neutral-200"}`,
1025
+ className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-md transition-colors disabled:pointer-events-none disabled:opacity-30 ${silent ? "text-accent-ink" : "text-neutral-500 hover:text-neutral-200"}`,
1043
1026
  children: /* @__PURE__ */ jsx3(VolumeIcon, { muted: audioMuted, volume: audioVolume })
1044
1027
  }
1045
1028
  ) })
@@ -1085,7 +1068,7 @@ var LoopButton = memo4(function LoopButton2({
1085
1068
  setLoopEnabled(!loopEnabled);
1086
1069
  },
1087
1070
  disabled,
1088
- className: `flex h-7 w-7 items-center justify-center rounded-md transition-colors disabled:opacity-30 ${loopEnabled ? "text-studio-accent" : "text-neutral-500 hover:text-neutral-200"}`,
1071
+ className: `flex h-7 w-7 items-center justify-center rounded-md transition-colors disabled:opacity-30 ${loopEnabled ? "text-accent-ink" : "text-neutral-500 hover:text-neutral-200"}`,
1089
1072
  "aria-label": loopEnabled ? "Disable loop playback" : "Enable loop playback",
1090
1073
  "aria-pressed": loopEnabled,
1091
1074
  children: /* @__PURE__ */ jsxs4(
@@ -1123,7 +1106,7 @@ var FullscreenButton = memo4(function FullscreenButton2({
1123
1106
  trackStudioEvent("playback", { action: "fullscreen_toggle", active: !isFullscreen });
1124
1107
  onToggleFullscreen();
1125
1108
  },
1126
- className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-md transition-colors ${isFullscreen ? "text-studio-accent" : "text-neutral-500 hover:text-neutral-200"}`,
1109
+ className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-md transition-colors ${isFullscreen ? "text-accent-ink" : "text-neutral-500 hover:text-neutral-200"}`,
1127
1110
  "aria-label": isFullscreen ? "Exit fullscreen" : "Enter fullscreen",
1128
1111
  children: /* @__PURE__ */ jsx4(
1129
1112
  "svg",
@@ -1221,7 +1204,7 @@ var PlayerControls = memo4(function PlayerControls2({
1221
1204
  children: [
1222
1205
  /* @__PURE__ */ jsx4("span", { ref: timeDisplayRef, children: formatTime(0) }),
1223
1206
  timeDisplayMode === "time" ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
1224
- /* @__PURE__ */ jsx4("span", { className: "mx-0.5 text-neutral-700", children: "/" }),
1207
+ /* @__PURE__ */ jsx4("span", { className: "mx-0.5 text-text-off", children: "/" }),
1225
1208
  /* @__PURE__ */ jsx4("span", { className: "text-neutral-600", children: formatTime(duration) })
1226
1209
  ] }) : null
1227
1210
  ]
@@ -6590,7 +6573,7 @@ function MiniCurveSvg({
6590
6573
  {
6591
6574
  d,
6592
6575
  fill: "none",
6593
- stroke: active ? "#3CE6AC" : "#737373",
6576
+ className: active ? "stroke-accent-ink" : "stroke-text-muted",
6594
6577
  strokeWidth: "1.5",
6595
6578
  strokeLinecap: "round"
6596
6579
  }
@@ -6630,7 +6613,7 @@ var EasePresetGrid = function EasePresetGrid2({
6630
6613
  /* @__PURE__ */ jsx11(
6631
6614
  "span",
6632
6615
  {
6633
- className: `text-center text-[8px] leading-none ${isActive ? "text-panel-accent" : "text-neutral-500"}`,
6616
+ className: `text-center text-[8px] leading-none ${isActive ? "text-accent-ink" : "text-neutral-500"}`,
6634
6617
  children: preset.label
6635
6618
  }
6636
6619
  )
@@ -6647,7 +6630,7 @@ function EaseModeToggle({
6647
6630
  return /* @__PURE__ */ jsx11(
6648
6631
  "div",
6649
6632
  {
6650
- className: "mb-2 grid grid-cols-3 rounded-md bg-black/20 p-0.5",
6633
+ className: "mb-2 grid grid-cols-3 rounded-md bg-press p-0.5",
6651
6634
  role: "radiogroup",
6652
6635
  "aria-label": "Ease editor mode",
6653
6636
  children: EASE_MODES.map((candidateMode) => {
@@ -6753,7 +6736,7 @@ function EaseBezierField({
6753
6736
  }
6754
6737
  },
6755
6738
  onBlur: (event) => commit(event.currentTarget.value),
6756
- className: `w-full rounded border bg-black/20 px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden ${error ? "border-red-500/70 focus:border-red-400" : "border-white/10 focus:border-panel-accent/50"}`
6739
+ className: `w-full rounded border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden ${error ? "border-danger-ink/70 focus:border-danger-ink" : "border-border focus:border-panel-accent/50"}`
6757
6740
  }
6758
6741
  )
6759
6742
  ] }),
@@ -6762,7 +6745,7 @@ function EaseBezierField({
6762
6745
  {
6763
6746
  id: errorId,
6764
6747
  "aria-live": "polite",
6765
- className: `mt-1 text-[9px] text-red-400 ${error ? "" : "sr-only"}`,
6748
+ className: `mt-1 text-[9px] text-danger-ink ${error ? "" : "sr-only"}`,
6766
6749
  children: error ?? "Valid bezier values"
6767
6750
  }
6768
6751
  )
@@ -6830,7 +6813,7 @@ function SpringBounceField({
6830
6813
  const bounce = parseSpringBounce2(`spring(${value})`);
6831
6814
  if (bounce !== null) onCommit(`spring(${round2(bounce)})`);
6832
6815
  },
6833
- className: "w-16 rounded-sm border border-white/10 bg-black/20 px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
6816
+ className: "w-16 rounded-sm border border-border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
6834
6817
  }
6835
6818
  )
6836
6819
  ] });
@@ -6851,7 +6834,7 @@ function WiggleField({
6851
6834
  min: 1,
6852
6835
  step: 1,
6853
6836
  onCommit: (value) => commitWiggle(onCommit, value, config.type, amplitude),
6854
- className: "w-14 rounded-sm border border-white/10 bg-black/20 px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
6837
+ className: "w-14 rounded-sm border border-border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
6855
6838
  }
6856
6839
  )
6857
6840
  ] }),
@@ -6867,7 +6850,7 @@ function WiggleField({
6867
6850
  commitWiggle(onCommit, config.wiggles, event.currentTarget.value, amplitude);
6868
6851
  }
6869
6852
  },
6870
- className: "rounded-sm border border-white/10 bg-black/20 px-1.5 py-1 text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50",
6853
+ className: "rounded-sm border border-border bg-input px-1.5 py-1 text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50",
6871
6854
  children: WIGGLE_TYPES.map((type) => /* @__PURE__ */ jsx12("option", { value: type, children: type }, type))
6872
6855
  }
6873
6856
  )
@@ -6883,7 +6866,7 @@ function WiggleField({
6883
6866
  max: 1,
6884
6867
  step: 0.01,
6885
6868
  onCommit: (value) => commitWiggle(onCommit, config.wiggles, config.type, value),
6886
- className: "w-16 rounded-sm border border-white/10 bg-black/20 px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
6869
+ className: "w-16 rounded-sm border border-border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
6887
6870
  }
6888
6871
  )
6889
6872
  ] })
@@ -6902,7 +6885,6 @@ var VMAX = 1 + HR / S;
6902
6885
  var VMIN = -HR / S;
6903
6886
  var DRAG_VMAX = 2;
6904
6887
  var DRAG_VMIN = -1;
6905
- var ACCENT = "#3CE6AC";
6906
6888
  function EaseTypeDropdown({
6907
6889
  kind,
6908
6890
  ease,
@@ -6971,7 +6953,7 @@ function EaseTypeDropdown({
6971
6953
  "aria-expanded": open,
6972
6954
  "aria-controls": open ? menuId : void 0,
6973
6955
  onClick: () => setOpen((prev) => !prev),
6974
- className: "flex w-full items-center gap-2 rounded-md border border-white/10 bg-black/20 px-2 py-1.5 text-left transition-colors hover:border-white/20",
6956
+ className: "flex w-full items-center gap-2 rounded-md border border-border bg-input px-2 py-1.5 text-left transition-colors hover:border-border-strong",
6975
6957
  children: [
6976
6958
  /* @__PURE__ */ jsx13(MiniCurveSvg, { ease, active: true, size: 16 }),
6977
6959
  /* @__PURE__ */ jsx13("span", { className: "text-[11px] text-neutral-200", children: label }),
@@ -6997,7 +6979,7 @@ function EaseTypeDropdown({
6997
6979
  role: "menu",
6998
6980
  "aria-label": `${MODE_LABELS[kind]} ease presets`,
6999
6981
  onKeyDown: handleMenuKeyDown,
7000
- className: "absolute inset-x-0 top-full z-20 mt-1 rounded-md border border-white/10 bg-neutral-900 p-2 shadow-xl",
6982
+ className: "absolute inset-x-0 top-full z-20 mt-1 rounded-md border border-border bg-raised p-2 shadow-xl",
7001
6983
  children: /* @__PURE__ */ jsx13(
7002
6984
  EasePresetGrid,
7003
6985
  {
@@ -7184,7 +7166,7 @@ function EaseCurveSection({
7184
7166
  /* @__PURE__ */ jsx13(
7185
7167
  "div",
7186
7168
  {
7187
- className: "mx-auto overflow-hidden rounded-md border border-white/5 bg-black/20",
7169
+ className: "mx-auto overflow-hidden rounded-md border border-border bg-input",
7188
7170
  style: { aspectRatio: `${SVGW} / ${SVGH}`, width: "100%", maxWidth: 230 },
7189
7171
  children: /* @__PURE__ */ jsxs9(
7190
7172
  "svg",
@@ -7206,7 +7188,7 @@ function EaseCurveSection({
7206
7188
  y1: top,
7207
7189
  x2: xToSvg(q),
7208
7190
  y2: bottom,
7209
- stroke: "white",
7191
+ className: "stroke-text-0",
7210
7192
  strokeOpacity: "0.05",
7211
7193
  strokeWidth: "1"
7212
7194
  },
@@ -7219,7 +7201,7 @@ function EaseCurveSection({
7219
7201
  y1: yToSvg(q),
7220
7202
  x2: right,
7221
7203
  y2: yToSvg(q),
7222
- stroke: "white",
7204
+ className: "stroke-text-0",
7223
7205
  strokeOpacity: "0.05",
7224
7206
  strokeWidth: "1"
7225
7207
  },
@@ -7233,7 +7215,7 @@ function EaseCurveSection({
7233
7215
  width: S,
7234
7216
  height: bottom - top,
7235
7217
  fill: "none",
7236
- stroke: "white",
7218
+ className: "stroke-text-0",
7237
7219
  strokeOpacity: "0.1",
7238
7220
  strokeWidth: "1"
7239
7221
  }
@@ -7245,7 +7227,7 @@ function EaseCurveSection({
7245
7227
  y1: a0.y,
7246
7228
  x2: a1.x,
7247
7229
  y2: a1.y,
7248
- stroke: "white",
7230
+ className: "stroke-text-0",
7249
7231
  strokeOpacity: "0.08",
7250
7232
  strokeWidth: "1",
7251
7233
  strokeDasharray: "3 4"
@@ -7259,8 +7241,7 @@ function EaseCurveSection({
7259
7241
  y1: a0.y,
7260
7242
  x2: p1.x,
7261
7243
  y2: p1.y,
7262
- stroke: ACCENT,
7263
- strokeOpacity: "0.5",
7244
+ className: "stroke-accent-ink",
7264
7245
  strokeWidth: "1.5"
7265
7246
  }
7266
7247
  ),
@@ -7271,8 +7252,7 @@ function EaseCurveSection({
7271
7252
  y1: a1.y,
7272
7253
  x2: p2.x,
7273
7254
  y2: p2.y,
7274
- stroke: ACCENT,
7275
- strokeOpacity: "0.5",
7255
+ className: "stroke-accent-ink",
7276
7256
  strokeWidth: "1.5"
7277
7257
  }
7278
7258
  )
@@ -7282,13 +7262,13 @@ function EaseCurveSection({
7282
7262
  {
7283
7263
  d: curvePath2,
7284
7264
  fill: "none",
7285
- stroke: ACCENT,
7265
+ className: "stroke-accent-ink",
7286
7266
  strokeWidth: "2.5",
7287
7267
  strokeLinecap: "round"
7288
7268
  }
7289
7269
  ),
7290
- /* @__PURE__ */ jsx13("circle", { cx: a0.x, cy: a0.y, r: "3", fill: ACCENT }),
7291
- /* @__PURE__ */ jsx13("circle", { cx: a1.x, cy: a1.y, r: "3", fill: ACCENT }),
7270
+ /* @__PURE__ */ jsx13("circle", { cx: a0.x, cy: a0.y, r: "3", className: "fill-accent-ink" }),
7271
+ /* @__PURE__ */ jsx13("circle", { cx: a1.x, cy: a1.y, r: "3", className: "fill-accent-ink" }),
7292
7272
  showHandles && [["p1", p1], ["p2", p2]].map(([key2, pt]) => /* @__PURE__ */ jsxs9("g", { children: [
7293
7273
  /* @__PURE__ */ jsx13(
7294
7274
  "circle",
@@ -7304,7 +7284,7 @@ function EaseCurveSection({
7304
7284
  "aria-valuemax": 1,
7305
7285
  "aria-valuenow": key2 === "p1" ? x1 : x2,
7306
7286
  "aria-valuetext": `x ${key2 === "p1" ? x1 : x2}, y ${key2 === "p1" ? y1 : y2}`,
7307
- className: "cursor-grab stroke-transparent outline-hidden active:cursor-grabbing focus-visible:stroke-white focus-visible:stroke-[2px]",
7287
+ className: "cursor-grab stroke-transparent outline-hidden active:cursor-grabbing focus-visible:stroke-text-0 focus-visible:stroke-[2px]",
7308
7288
  onPointerDown: (e) => handlePointerDown(key2, e),
7309
7289
  onKeyDown: (event) => handleKeyDown(key2, event),
7310
7290
  onPointerEnter: () => setHover(key2),
@@ -7317,10 +7297,8 @@ function EaseCurveSection({
7317
7297
  cx: pt.x,
7318
7298
  cy: pt.y,
7319
7299
  r: hover === key2 || draggingRef.current === key2 ? 7 : 5.5,
7320
- fill: "#0a0a1a",
7321
- stroke: ACCENT,
7322
7300
  strokeWidth: "2.5",
7323
- className: "pointer-events-none transition-[r]"
7301
+ className: "pointer-events-none fill-input stroke-accent-ink transition-[r]"
7324
7302
  }
7325
7303
  )
7326
7304
  ] }, key2))
@@ -7591,8 +7569,11 @@ var KeyframeDiamond = memo6(function KeyframeDiamond2({
7591
7569
  isHold = false
7592
7570
  }) {
7593
7571
  const isFilled = state === "active";
7594
- const opacity = state === "ghost" ? 0.25 : state === "inactive" ? 0.6 : 1;
7595
- const color = state === "active" ? "#3CE6AC" : "#a3a3a3";
7572
+ const color = {
7573
+ active: "text-accent",
7574
+ inactive: "text-text-2 hover:text-text-0",
7575
+ ghost: "text-text-off hover:text-text-0"
7576
+ }[state];
7596
7577
  return /* @__PURE__ */ jsx15(
7597
7578
  "button",
7598
7579
  {
@@ -7601,8 +7582,7 @@ var KeyframeDiamond = memo6(function KeyframeDiamond2({
7601
7582
  e.stopPropagation();
7602
7583
  onClick();
7603
7584
  },
7604
- className: "relative shrink-0 p-0.5 transition-opacity hover:opacity-100 before:absolute before:-inset-1.5 before:content-['']",
7605
- style: { color, opacity },
7585
+ className: `relative shrink-0 p-0.5 transition-colors before:absolute before:-inset-1.5 before:content-[''] ${color}`,
7606
7586
  title,
7607
7587
  "aria-label": title,
7608
7588
  "aria-pressed": state === "active",
@@ -7667,12 +7647,12 @@ function ArrowLeft({ disabled }) {
7667
7647
  height: "10",
7668
7648
  viewBox: "0 0 6 10",
7669
7649
  fill: "none",
7670
- style: { opacity: disabled ? 0.25 : 1 },
7650
+ className: disabled ? "text-text-off" : "text-text-2",
7671
7651
  children: /* @__PURE__ */ jsx16(
7672
7652
  "path",
7673
7653
  {
7674
7654
  d: "M5 1L1 5L5 9",
7675
- stroke: "#a3a3a3",
7655
+ stroke: "currentColor",
7676
7656
  strokeWidth: "1.4",
7677
7657
  strokeLinecap: "round",
7678
7658
  strokeLinejoin: "round"
@@ -7689,12 +7669,12 @@ function ArrowRight({ disabled }) {
7689
7669
  height: "10",
7690
7670
  viewBox: "0 0 6 10",
7691
7671
  fill: "none",
7692
- style: { opacity: disabled ? 0.25 : 1 },
7672
+ className: disabled ? "text-text-off" : "text-text-2",
7693
7673
  children: /* @__PURE__ */ jsx16(
7694
7674
  "path",
7695
7675
  {
7696
7676
  d: "M1 1L5 5L1 9",
7697
- stroke: "#a3a3a3",
7677
+ stroke: "currentColor",
7698
7678
  strokeWidth: "1.4",
7699
7679
  strokeLinecap: "round",
7700
7680
  strokeLinejoin: "round"
@@ -10970,7 +10950,7 @@ function ClipLintDot({ element }) {
10970
10950
  return /* @__PURE__ */ jsx21(
10971
10951
  "span",
10972
10952
  {
10973
- className: "absolute w-1.5 h-1.5 rounded-full bg-amber-400",
10953
+ className: "absolute w-1.5 h-1.5 rounded-full bg-warning-ink",
10974
10954
  style: { top: 7, right: 7 },
10975
10955
  title: lint.messages.join("\n")
10976
10956
  }
@@ -11888,7 +11868,7 @@ var TIMELINE_VIEWPORT_BUDGETS = Object.freeze({
11888
11868
  richPreviewP95Ms: 750,
11889
11869
  constrainedRichPreviewP95Ms: 1200,
11890
11870
  supportedFixtureFallbackRatio: 0.02,
11891
- scrollSamplesPerRun: 21,
11871
+ scrollSamplesPerRun: 63,
11892
11872
  warmupRuns: 3,
11893
11873
  measuredRuns: 5,
11894
11874
  requiredPassingRuns: 4
@@ -14184,7 +14164,7 @@ var TimelineClip = memo10(function TimelineClip2({
14184
14164
  width: 2,
14185
14165
  borderRadius: 1,
14186
14166
  background: "var(--clip-handle)",
14187
- opacity: handleOpacity * 0.6
14167
+ opacity: handleOpacity
14188
14168
  }
14189
14169
  }
14190
14170
  )
@@ -14216,7 +14196,7 @@ var TimelineClip = memo10(function TimelineClip2({
14216
14196
  width: 2,
14217
14197
  borderRadius: 1,
14218
14198
  background: "var(--clip-handle)",
14219
- opacity: handleOpacity * 0.6
14199
+ opacity: handleOpacity
14220
14200
  }
14221
14201
  }
14222
14202
  )
@@ -16614,7 +16594,7 @@ function TrackClipCount({ clipCount }) {
16614
16594
  {
16615
16595
  "aria-label": `${clipCount} clips`,
16616
16596
  title: `${clipCount} clips`,
16617
- className: "shrink-0 rounded-full bg-white/10 px-1 text-[9px] leading-[14px] tabular-nums text-white/55",
16597
+ className: "shrink-0 rounded-full bg-hover px-1 text-[9px] leading-[14px] tabular-nums text-text-muted",
16618
16598
  children: clipCount
16619
16599
  }
16620
16600
  );
@@ -17123,7 +17103,7 @@ function TimelineFxPopover({
17123
17103
  ref: rootRef,
17124
17104
  role: "dialog",
17125
17105
  "aria-label": "Effects",
17126
- className: "z-200 flex flex-col overflow-hidden rounded-md border border-white/10 bg-[#1b1b1f] p-2 shadow-xl",
17106
+ className: "z-200 flex flex-col overflow-hidden rounded-md border border-border bg-raised p-2 shadow-xl",
17127
17107
  style: clampedStyle(anchorRect),
17128
17108
  onKeyDown,
17129
17109
  onPointerDown: (event) => event.stopPropagation(),
@@ -17137,12 +17117,12 @@ function TimelineFxPopover({
17137
17117
  onAuditionTracked: (id) => trackPresetAuditioned(id, { trackKind })
17138
17118
  }
17139
17119
  ) }),
17140
- /* @__PURE__ */ jsxs23("div", { className: "mt-2 flex shrink-0 items-center justify-between border-t border-white/10 pt-2 text-[10px] text-white/55", children: [
17120
+ /* @__PURE__ */ jsxs23("div", { className: "mt-2 flex shrink-0 items-center justify-between border-t border-border pt-2 text-[10px] text-text-muted", children: [
17141
17121
  /* @__PURE__ */ jsx41(
17142
17122
  "button",
17143
17123
  {
17144
17124
  type: "button",
17145
- className: "hover:text-white",
17125
+ className: "hover:text-text-0",
17146
17126
  onClick: () => {
17147
17127
  onClose();
17148
17128
  onOpenRack();
@@ -17154,7 +17134,7 @@ function TimelineFxPopover({
17154
17134
  "button",
17155
17135
  {
17156
17136
  type: "button",
17157
- className: "hover:text-white",
17137
+ className: "hover:text-text-0",
17158
17138
  onClick: () => {
17159
17139
  onClose();
17160
17140
  onOpenRack();
@@ -17644,7 +17624,7 @@ function PropertyGroupNavigation({
17644
17624
  onSeek,
17645
17625
  children
17646
17626
  }) {
17647
- const CHEVRON_BUTTON_CLASS = "relative h-5 w-3 border-0 bg-transparent p-0 text-white/55 hover:text-white disabled:text-white/15 focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-[#3CE6AC] before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']";
17627
+ const CHEVRON_BUTTON_CLASS = "relative h-5 w-3 border-0 bg-transparent p-0 text-text-2 hover:text-text-0 disabled:text-text-off focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-ring before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']";
17648
17628
  const seekTo = (keyframe) => {
17649
17629
  if (keyframe) {
17650
17630
  onSeek?.(expandedElement.start + keyframe.percentage / 100 * expandedElement.duration);
@@ -17711,7 +17691,7 @@ function PropertyGroupHeaderRow({
17711
17691
  tabIndex: rovingTargetId === timelinePropertyRowId(elementId2, lane.group) ? 0 : -1,
17712
17692
  "data-property-group": lane.group,
17713
17693
  "data-timeline-lane-top": getTimelineLaneTop(laneIndex),
17714
- className: "absolute left-0 flex items-center gap-1 overflow-hidden px-1.5 text-[10px] text-white/65",
17694
+ className: "absolute left-0 flex items-center gap-1 overflow-hidden px-1.5 text-[10px] text-text-2",
17715
17695
  style: {
17716
17696
  top: getTimelineLaneTop(laneIndex),
17717
17697
  // The header column narrows to contentOrigin whenever that is under
@@ -17726,13 +17706,13 @@ function PropertyGroupHeaderRow({
17726
17706
  /* @__PURE__ */ jsx44(
17727
17707
  "span",
17728
17708
  {
17729
- className: "absolute left-1.5 top-0 w-px bg-white/15",
17709
+ className: "absolute left-1.5 top-0 w-px bg-text-0/15",
17730
17710
  style: { height: isLastLane ? "50%" : "100%" }
17731
17711
  }
17732
17712
  ),
17733
- /* @__PURE__ */ jsx44("span", { className: "absolute left-1.5 top-1/2 h-px w-1.5 bg-white/15" })
17713
+ /* @__PURE__ */ jsx44("span", { className: "absolute left-1.5 top-1/2 h-px w-1.5 bg-text-0/15" })
17734
17714
  ] }),
17735
- /* @__PURE__ */ jsx44("span", { className: "w-[46px] shrink-0 truncate text-white", title: label, children: label }),
17715
+ /* @__PURE__ */ jsx44("span", { className: "w-[46px] shrink-0 truncate text-text-0", title: label, children: label }),
17736
17716
  /* @__PURE__ */ jsx44(
17737
17717
  PropertyGroupNavigation,
17738
17718
  {
@@ -17747,7 +17727,7 @@ function PropertyGroupHeaderRow({
17747
17727
  "aria-pressed": !!navigation.currentKeyframe,
17748
17728
  "aria-label": `${navigation.currentKeyframe ? "Remove" : "Add"} ${label} keyframe`,
17749
17729
  title: `${navigation.currentKeyframe ? "Remove" : "Add"} ${label} keyframe`,
17750
- className: "flex h-6 w-6 shrink-0 items-center justify-center border-0 bg-transparent p-0 text-[11px] text-[#3CE6AC] focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-[#3CE6AC]",
17730
+ className: "flex h-6 w-6 shrink-0 items-center justify-center border-0 bg-transparent p-0 text-[11px] text-accent-ink focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-ring",
17751
17731
  onClick: (event) => {
17752
17732
  event.stopPropagation();
17753
17733
  if (toggleTarget) {
@@ -17762,7 +17742,7 @@ function PropertyGroupHeaderRow({
17762
17742
  /* @__PURE__ */ jsx44(
17763
17743
  "span",
17764
17744
  {
17765
- className: "min-w-0 flex-1 truncate text-right tabular-nums text-white/45",
17745
+ className: "min-w-0 flex-1 truncate text-right tabular-nums text-text-muted",
17766
17746
  title: valueReadout(lane.group, values),
17767
17747
  children: valueReadout(lane.group, values)
17768
17748
  }
@@ -17790,7 +17770,7 @@ function AutomationLaneHeaderRow({
17790
17770
  {
17791
17771
  "data-automation-lane-label": label,
17792
17772
  "data-timeline-lane-top": top,
17793
- className: "absolute left-0 flex items-center gap-1 overflow-hidden px-1.5 text-[10px] text-white/65",
17773
+ className: "absolute left-0 flex items-center gap-1 overflow-hidden px-1.5 text-[10px] text-text-2",
17794
17774
  style: {
17795
17775
  top,
17796
17776
  width: columnWidth,
@@ -17802,11 +17782,11 @@ function AutomationLaneHeaderRow({
17802
17782
  /* @__PURE__ */ jsx44(
17803
17783
  "span",
17804
17784
  {
17805
- className: "absolute left-1.5 top-0 w-px bg-white/15",
17785
+ className: "absolute left-1.5 top-0 w-px bg-text-0/15",
17806
17786
  style: { height: isLastLane ? "50%" : "100%" }
17807
17787
  }
17808
17788
  ),
17809
- /* @__PURE__ */ jsx44("span", { className: "absolute left-1.5 top-1/2 h-px w-1.5 bg-white/15" })
17789
+ /* @__PURE__ */ jsx44("span", { className: "absolute left-1.5 top-1/2 h-px w-1.5 bg-text-0/15" })
17810
17790
  ] }),
17811
17791
  /* @__PURE__ */ jsxs26(
17812
17792
  "button",
@@ -17816,19 +17796,19 @@ function AutomationLaneHeaderRow({
17816
17796
  "aria-label": onReveal ? `Show ${label} in the effect rack` : void 0,
17817
17797
  title: onReveal ? `Show ${label} in the effect rack` : label,
17818
17798
  disabled: !onReveal,
17819
- className: "flex min-w-0 flex-1 flex-col justify-center rounded-sm border-0 bg-transparent p-0 text-left leading-tight enabled:hover:text-white focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-[#3CE6AC]",
17799
+ className: "flex min-w-0 flex-1 flex-col justify-center rounded-sm border-0 bg-transparent p-0 text-left leading-tight enabled:hover:text-text-0 focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-ring",
17820
17800
  onPointerDown: (event) => event.stopPropagation(),
17821
17801
  onClick: (event) => {
17822
17802
  event.stopPropagation();
17823
17803
  onReveal?.();
17824
17804
  },
17825
17805
  children: [
17826
- /* @__PURE__ */ jsx44("span", { "data-automation-lane-name": "", className: "truncate font-mono text-[9px] text-white/70", children: name }),
17806
+ /* @__PURE__ */ jsx44("span", { "data-automation-lane-name": "", className: "truncate font-mono text-[9px] text-text-2", children: name }),
17827
17807
  param ? /* @__PURE__ */ jsx44(
17828
17808
  "span",
17829
17809
  {
17830
17810
  "data-automation-lane-param": "",
17831
- className: "truncate font-mono text-[9px] text-white/40",
17811
+ className: "truncate font-mono text-[9px] text-text-muted",
17832
17812
  children: param
17833
17813
  }
17834
17814
  ) : null,
@@ -17836,7 +17816,7 @@ function AutomationLaneHeaderRow({
17836
17816
  "span",
17837
17817
  {
17838
17818
  "data-automation-lane-also": "",
17839
- className: "truncate text-[9px] text-[#F5C542]/80",
17819
+ className: "truncate text-[9px] text-warning-ink",
17840
17820
  title: `${alsoAutomatedBy} is also fading this \u2014 the two multiply.`,
17841
17821
  children: [
17842
17822
  alsoAutomatedBy,
@@ -17853,7 +17833,7 @@ function AutomationLaneHeaderRow({
17853
17833
  type: "button",
17854
17834
  "aria-label": `Remove ${label} automation`,
17855
17835
  title: `Remove ${label} automation`,
17856
- className: "flex h-6 w-6 shrink-0 items-center justify-center border-0 bg-transparent p-0 text-[11px] text-white/35 hover:text-white focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-[#3CE6AC]",
17836
+ className: "flex h-6 w-6 shrink-0 items-center justify-center border-0 bg-transparent p-0 text-[11px] text-text-muted hover:text-text-0 focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-ring",
17857
17837
  onPointerDown: (event) => event.stopPropagation(),
17858
17838
  onClick: (event) => {
17859
17839
  event.stopPropagation();
@@ -21121,8 +21101,7 @@ function TimelineLanes({
21121
21101
  color: ts.label,
21122
21102
  fontSize: 11,
21123
21103
  letterSpacing: "0.06em",
21124
- textTransform: "uppercase",
21125
- opacity: 0.5
21104
+ textTransform: "uppercase"
21126
21105
  },
21127
21106
  children: "New track"
21128
21107
  }
@@ -21457,7 +21436,7 @@ var TimelineCanvas = memo13(function TimelineCanvas2() {
21457
21436
  "aria-hidden": "true",
21458
21437
  "data-testid": "timeline-ghost-lane",
21459
21438
  "data-active": ghostLaneActive || void 0,
21460
- className: `pointer-events-none absolute flex items-center justify-center rounded-lg border border-dashed text-[11px] transition-colors duration-150 ${ghostLaneActive ? "border-studio-accent/60 bg-studio-accent/6 text-studio-accent" : "border-neutral-700/50 text-neutral-500"}`,
21439
+ className: `pointer-events-none absolute flex items-center justify-center rounded-lg border border-dashed text-[11px] transition-colors duration-150 ${ghostLaneActive ? "border-studio-accent/60 bg-studio-accent/6 text-accent-ink" : "border-neutral-700/50 text-neutral-500"}`,
21461
21440
  style: {
21462
21441
  top: props.rowGeometry.getRowTop(ghostLaneRow) + CLIP_Y,
21463
21442
  left: props.contentOrigin,
@@ -21798,7 +21777,7 @@ function EditPopover({ rangeStart, rangeEnd, anchorX, anchorY, onClose }) {
21798
21777
  ] })
21799
21778
  ] }),
21800
21779
  elementsInRange.length > 0 && /* @__PURE__ */ jsx56("div", { className: "px-4 py-2 border-b border-neutral-800/40 max-h-24 overflow-y-auto", children: elementsInRange.map((el) => /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between py-0.5", children: [
21801
- /* @__PURE__ */ jsxs36("span", { className: "text-[10px] font-mono text-studio-accent/80", children: [
21780
+ /* @__PURE__ */ jsxs36("span", { className: "text-[10px] font-mono text-accent-ink/80", children: [
21802
21781
  "#",
21803
21782
  el.id
21804
21783
  ] }),
@@ -21821,14 +21800,14 @@ function EditPopover({ rangeStart, rangeEnd, anchorX, anchorY, onClose }) {
21821
21800
  className: "w-full px-3 py-2 text-xs bg-neutral-800/60 border border-neutral-700/40 rounded-lg text-neutral-200 placeholder:text-neutral-600 resize-none focus:outline-hidden focus:border-studio-accent/40 transition-colors"
21822
21801
  }
21823
21802
  ) }),
21824
- copyError && /* @__PURE__ */ jsx56("p", { className: "px-3 pb-2 text-[10px] text-red-400", role: "alert", children: "Copy failed \u2014 check clipboard permissions and try again." }),
21803
+ copyError && /* @__PURE__ */ jsx56("p", { className: "px-3 pb-2 text-[10px] text-danger-ink", role: "alert", children: "Copy failed \u2014 check clipboard permissions and try again." }),
21825
21804
  /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-2 gap-2 px-3 pb-3", children: [
21826
21805
  /* @__PURE__ */ jsx56(
21827
21806
  "button",
21828
21807
  {
21829
21808
  onClick: handleCopyPrompt,
21830
21809
  disabled: !buildPromptCopyText(prompt),
21831
- className: `py-1.5 text-[11px] font-medium rounded-lg transition-all border ${copiedPromptOnly ? "bg-green-500/20 text-green-400 border-green-500/30" : "bg-neutral-800/70 text-neutral-200 border-neutral-700/50 hover:bg-neutral-800"} disabled:opacity-50 disabled:cursor-not-allowed`,
21810
+ className: `py-1.5 text-[11px] font-medium rounded-lg transition-all border ${copiedPromptOnly ? "bg-accent/15 text-accent-ink border-accent/30" : "bg-neutral-800/70 text-neutral-200 border-neutral-700/50 hover:bg-neutral-800"} disabled:opacity-50 disabled:cursor-not-allowed`,
21832
21811
  children: copiedPromptOnly ? "Prompt Copied!" : "Copy Prompt"
21833
21812
  }
21834
21813
  ),
@@ -21836,10 +21815,10 @@ function EditPopover({ rangeStart, rangeEnd, anchorX, anchorY, onClose }) {
21836
21815
  "button",
21837
21816
  {
21838
21817
  onClick: handleCopy2,
21839
- className: `py-1.5 text-[11px] font-medium rounded-lg transition-all ${copiedAgentPrompt ? "bg-green-500/20 text-green-400 border border-green-500/30" : "bg-studio-accent/15 text-studio-accent border border-studio-accent/25 hover:bg-studio-accent/25"}`,
21818
+ className: `py-1.5 text-[11px] font-medium rounded-lg transition-all ${copiedAgentPrompt ? "bg-accent/15 text-accent-ink border border-accent/30" : "bg-studio-accent/15 text-accent-ink border border-studio-accent/25 hover:bg-studio-accent/25"}`,
21840
21819
  children: [
21841
21820
  copiedAgentPrompt ? "Copied!" : "Copy to Agent",
21842
- !copiedAgentPrompt && /* @__PURE__ */ jsx56("span", { className: "text-[9px] text-studio-accent/50 ml-1.5", children: "Cmd+Enter" })
21821
+ !copiedAgentPrompt && /* @__PURE__ */ jsx56("span", { className: "text-[9px] text-text-muted ml-1.5", children: "Cmd+Enter" })
21843
21822
  ]
21844
21823
  }
21845
21824
  )
@@ -21893,7 +21872,7 @@ function useMenuKeyboardNav(menuRef) {
21893
21872
  // src/player/components/KeyframeDiamondContextMenu.tsx
21894
21873
  import { jsx as jsx57, jsxs as jsxs37 } from "react/jsx-runtime";
21895
21874
  var ITEM_CLS = "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-neutral-200 hover:bg-neutral-800 focus-visible:bg-neutral-800 outline-hidden cursor-pointer text-left";
21896
- var DESTRUCTIVE_ITEM_CLS = "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-red-400 hover:bg-neutral-800 focus-visible:bg-neutral-800 outline-hidden cursor-pointer text-left";
21875
+ var DESTRUCTIVE_ITEM_CLS = "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-danger-ink hover:bg-neutral-800 focus-visible:bg-neutral-800 outline-hidden cursor-pointer text-left";
21897
21876
  function KeyframeDiamondContextMenu({
21898
21877
  state,
21899
21878
  onClose,
@@ -22000,7 +21979,7 @@ function KeyframeDiamondContextMenu({
22000
21979
  {
22001
21980
  type: "button",
22002
21981
  role: "menuitem",
22003
- className: "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-red-400 hover:bg-red-950/40 focus-visible:bg-red-950/40 outline-hidden cursor-pointer text-left",
21982
+ className: "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-danger-ink hover:bg-danger/25 focus-visible:bg-danger/25 outline-hidden cursor-pointer text-left",
22004
21983
  onClick: () => {
22005
21984
  onDeleteAll(state.element, state.animationId);
22006
21985
  onClose();
@@ -22172,7 +22151,7 @@ var ClipContextMenu = memo14(function ClipContextMenu2({
22172
22151
  {
22173
22152
  type: "button",
22174
22153
  role: "menuitem",
22175
- className: "w-full flex items-center justify-between px-3 py-1.5 text-xs text-red-400 hover:bg-neutral-800 focus-visible:bg-neutral-800 outline-hidden cursor-pointer text-left",
22154
+ className: "w-full flex items-center justify-between px-3 py-1.5 text-xs text-danger-ink hover:bg-neutral-800 focus-visible:bg-neutral-800 outline-hidden cursor-pointer text-left",
22176
22155
  onClick: () => {
22177
22156
  onDelete(element);
22178
22157
  onClose();
@@ -22537,7 +22516,7 @@ function TimelineEmptyState({
22537
22516
  strokeWidth: "1.5",
22538
22517
  strokeLinecap: "round",
22539
22518
  strokeLinejoin: "round",
22540
- className: "text-studio-accent shrink-0",
22519
+ className: "text-accent-ink shrink-0",
22541
22520
  children: [
22542
22521
  /* @__PURE__ */ jsx62("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
22543
22522
  /* @__PURE__ */ jsx62("polyline", { points: "7 10 12 15 17 10" }),
@@ -22545,7 +22524,7 @@ function TimelineEmptyState({
22545
22524
  ]
22546
22525
  }
22547
22526
  ),
22548
- /* @__PURE__ */ jsx62("span", { className: "text-[13px] text-studio-accent", children: "Drop media files to import" })
22527
+ /* @__PURE__ */ jsx62("span", { className: "text-[13px] text-accent-ink", children: "Drop media files to import" })
22549
22528
  ] }) : /* @__PURE__ */ jsxs42(Fragment20, { children: [
22550
22529
  /* @__PURE__ */ jsxs42(
22551
22530
  "svg",
@@ -22782,10 +22761,7 @@ var ThumbnailScheduler = class {
22782
22761
  this.scrolling = scrolling;
22783
22762
  if (!scrolling) this.pump();
22784
22763
  }
22785
- /**
22786
- * Hold server-rendered composition thumbnails while the preview loads a new document: both
22787
- * are served by the same Studio server, and the preview is what the person is waiting for.
22788
- */
22764
+ /** Holds composition renders while the preview loads: same server, and the preview is what the person awaits. */
22789
22765
  setPreviewReloading(reloading) {
22790
22766
  if (this.previewReloading === reloading) return;
22791
22767
  this.previewReloading = reloading;
@@ -22909,7 +22885,7 @@ var ThumbnailScheduler = class {
22909
22885
  cacheResult(entry2) {
22910
22886
  const isWaveform = entry2.request.kind === "waveform";
22911
22887
  const byteBudget = isWaveform ? this.budgets.waveformCacheBytes : this.budgets.thumbnailCacheBytes;
22912
- entry2.cached = entry2.weight <= byteBudget;
22888
+ entry2.cached = !entry2.request.discardWhenReleased && entry2.weight <= byteBudget;
22913
22889
  if (!entry2.cached) return;
22914
22890
  if (isWaveform) this.waveformCacheBytes += entry2.weight;
22915
22891
  else this.cacheBytes += entry2.weight;
@@ -23468,6 +23444,17 @@ function compositionPathOfPreviewUrl(previewUrl) {
23468
23444
  const match = /\/preview\/comp\/([^?#]+)/.exec(previewUrl);
23469
23445
  return match?.[1] ? decodeURIComponent(match[1]) : "index.html";
23470
23446
  }
23447
+ function compositionThumbnailRequest(url, projectId, { sessionEpoch = 0, priority = "visible", rich = false } = {}) {
23448
+ return {
23449
+ key: createThumbnailKey({ kind: "composition", url }),
23450
+ projectId,
23451
+ sessionEpoch,
23452
+ kind: "composition",
23453
+ priority,
23454
+ rich,
23455
+ load: (signal) => loadCompositionImage(url, signal)
23456
+ };
23457
+ }
23471
23458
  async function loadCompositionImage(url, signal) {
23472
23459
  const response = await fetch(url, { signal });
23473
23460
  if (!response.ok) throw new Error(`Composition thumbnail failed (${response.status})`);
@@ -23510,15 +23497,7 @@ var CompositionThumbnail = memo18(function CompositionThumbnail2({
23510
23497
  contentRevision
23511
23498
  });
23512
23499
  const request = useMemo34(
23513
- () => ({
23514
- key: createThumbnailKey({ kind: "composition", url }),
23515
- projectId,
23516
- sessionEpoch,
23517
- kind: "composition",
23518
- priority,
23519
- rich: true,
23520
- load: (signal) => loadCompositionImage(url, signal)
23521
- }),
23500
+ () => compositionThumbnailRequest(url, projectId, { sessionEpoch, priority, rich: true }),
23522
23501
  [priority, projectId, sessionEpoch, url]
23523
23502
  );
23524
23503
  const snapshot3 = useThumbnailLease(request);
@@ -23558,7 +23537,7 @@ var CompositionThumbnail = memo18(function CompositionThumbnail2({
23558
23537
  ))
23559
23538
  }
23560
23539
  ),
23561
- snapshot3.status === "loading" && /* @__PURE__ */ jsx66("div", { className: "absolute inset-0 animate-pulse bg-white/[0.035]" }),
23540
+ snapshot3.status === "loading" && /* @__PURE__ */ jsx66("div", { className: "absolute inset-0 animate-pulse bg-text-0/[0.035]" }),
23562
23541
  label && /* @__PURE__ */ jsx66("div", { className: "absolute inset-y-0 left-3 z-10 flex items-center", children: /* @__PURE__ */ jsx66(
23563
23542
  "span",
23564
23543
  {
@@ -27115,7 +27094,7 @@ function PreviewZoomOverlay({
27115
27094
  "button",
27116
27095
  {
27117
27096
  type: "button",
27118
- className: "rounded px-1.5 py-0.5 font-medium text-studio-accent hover:bg-white/10 transition-colors",
27097
+ className: "rounded px-1.5 py-0.5 font-medium text-accent-ink hover:bg-white/10 transition-colors",
27119
27098
  onClick: onFit,
27120
27099
  "aria-label": "Fit the whole frame in view",
27121
27100
  "data-testid": "preview-zoom-fit",
@@ -27233,8 +27212,7 @@ function usePreviewPoster(projectId, activeKey, directUrl) {
27233
27212
  const renderMissingPoster = useCallback46(() => {
27234
27213
  if (missingForRef.current !== visit || liveReadyForRef.current !== visit) return;
27235
27214
  missingForRef.current = null;
27236
- void fetch(previewPosterUrl(projectId, false)).catch(() => {
27237
- });
27215
+ renderPosterForNextOpen(projectId);
27238
27216
  }, [visit, projectId]);
27239
27217
  const onLiveReadyToShowChange = useCallback46(
27240
27218
  (ready) => {
@@ -27259,6 +27237,27 @@ function usePreviewPoster(projectId, activeKey, directUrl) {
27259
27237
  }
27260
27238
  };
27261
27239
  }
27240
+ function renderPosterForNextOpen(projectId) {
27241
+ const url = previewPosterUrl(projectId, false);
27242
+ const request = {
27243
+ key: createThumbnailKey({ kind: "poster-render", url }),
27244
+ projectId,
27245
+ sessionEpoch: 0,
27246
+ kind: "composition",
27247
+ priority: "overscan",
27248
+ discardWhenReleased: true,
27249
+ load: async (signal) => {
27250
+ await (await fetch(url, { signal })).arrayBuffer();
27251
+ return { value: { kind: "image", url, aspect: 16 / 9 }, weight: 0 };
27252
+ }
27253
+ };
27254
+ const settled = () => ["ready", "error"].includes(thumbnailScheduler.getSnapshot(request).status);
27255
+ let lease = null;
27256
+ lease = thumbnailScheduler.acquire(request, () => {
27257
+ if (settled()) lease?.release();
27258
+ });
27259
+ if (settled()) lease.release();
27260
+ }
27262
27261
  function useVisitNumber(key2) {
27263
27262
  const [seen, setSeen] = useState30({ key: key2, visit: 0 });
27264
27263
  if (seen.key === key2) return seen.visit;
@@ -28019,7 +28018,7 @@ function AssetPreviewOverlay() {
28019
28018
  /* @__PURE__ */ jsx73(
28020
28019
  "button",
28021
28020
  {
28022
- className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-neutral-800 hover:bg-neutral-700 text-neutral-300 hover:text-white flex items-center justify-center transition-colors z-10",
28021
+ className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-raised hover:bg-press text-text-2 hover:text-text-0 flex items-center justify-center transition-colors z-10",
28023
28022
  onClick: (e) => {
28024
28023
  e.stopPropagation();
28025
28024
  clearPreviewAsset();
@@ -28480,7 +28479,7 @@ function PreviewPane({
28480
28479
  "div",
28481
28480
  {
28482
28481
  ref: containerRef,
28483
- className: `flex-1 min-h-0 flex flex-col overflow-hidden bg-[var(--studio-preview-bg,var(--color-neutral-950))] ${isFullscreen ? "" : "m-3 rounded-md border border-neutral-800/50"}`,
28482
+ className: `scheme-dark flex-1 min-h-0 flex flex-col overflow-hidden bg-[var(--studio-preview-bg,var(--color-neutral-950))] ${isFullscreen ? "" : "m-3 rounded-md border border-border"}`,
28484
28483
  "data-studio-fullscreen-target": "",
28485
28484
  children: [
28486
28485
  /* @__PURE__ */ jsxs51(
@@ -28736,7 +28735,7 @@ function useMeterLoop(strips, bars, iframeRef) {
28736
28735
  }, [previewIframeRef, bars]);
28737
28736
  }
28738
28737
  function Bar({ maskRef, peakRef }) {
28739
- return /* @__PURE__ */ jsxs52("div", { className: "relative h-full w-[18px] overflow-hidden rounded-[2px] bg-neutral-900", children: [
28738
+ return /* @__PURE__ */ jsxs52("div", { className: "scheme-dark relative h-full w-[18px] overflow-hidden rounded-[2px] bg-neutral-900", children: [
28740
28739
  /* @__PURE__ */ jsx77(
28741
28740
  "div",
28742
28741
  {
@@ -28772,7 +28771,7 @@ function Bar({ maskRef, peakRef }) {
28772
28771
  {
28773
28772
  ref: peakRef,
28774
28773
  "data-testid": "meter-peak",
28775
- className: "absolute inset-x-0 bottom-0 h-px bg-white"
28774
+ className: "absolute inset-x-0 bottom-0 h-px bg-text-0"
28776
28775
  }
28777
28776
  )
28778
28777
  ] });
@@ -31840,15 +31839,6 @@ function applyStudioRotation(element, rotation) {
31840
31839
  composeStudioRotationValue(element, `var(${STUDIO_ROTATION_PROP}, 0deg)`)
31841
31840
  );
31842
31841
  }
31843
- function applyStudioRotationDraft(element, rotation) {
31844
- promoteInlineForTransform(element);
31845
- writeStudioRotationVars(element, rotation, { updateBase: false });
31846
- element.setAttribute(STUDIO_ROTATION_DRAFT_ATTR, "true");
31847
- element.style.setProperty(
31848
- "rotate",
31849
- composeStudioRotationValue(element, `${roundTo3(rotation.angle)}deg`)
31850
- );
31851
- }
31852
31842
 
31853
31843
  // src/components/editor/manualEditsSeekReapply.ts
31854
31844
  function queryStudioElements(doc, attr) {
@@ -31986,6 +31976,8 @@ function captureStudioBoxSize(element) {
31986
31976
  function captureStudioRotation(element) {
31987
31977
  return {
31988
31978
  rotate: element.style.getPropertyValue("rotate"),
31979
+ transform: element.style.getPropertyValue("transform"),
31980
+ display: element.style.getPropertyValue("display"),
31989
31981
  transformOrigin: element.style.getPropertyValue("transform-origin"),
31990
31982
  studioRotation: element.style.getPropertyValue(STUDIO_ROTATION_PROP),
31991
31983
  marker: element.getAttribute(STUDIO_ROTATION_ATTR),
@@ -32121,7 +32113,7 @@ function restoreOriginalTranslateProperty(element) {
32121
32113
  element.removeAttribute(STUDIO_ORIGINAL_TRANSLATE_ATTR);
32122
32114
  }
32123
32115
  function clearStudioPathOffset(element) {
32124
- if (element.hasAttribute(STUDIO_PATH_OFFSET_ATTR) || styleUsesStudioOffset(element.style.getPropertyValue("translate"))) {
32116
+ if (element.hasAttribute(STUDIO_PATH_OFFSET_ATTR) || element.hasAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR) || styleUsesStudioOffset(element.style.getPropertyValue("translate"))) {
32125
32117
  restoreOriginalTranslateProperty(element);
32126
32118
  }
32127
32119
  restoreInlineDisplay(element);
@@ -32381,6 +32373,29 @@ function installStudioManualEditSeekReapply(win, apply) {
32381
32373
  }
32382
32374
 
32383
32375
  // src/hooks/draggedGsapPosition.ts
32376
+ var cssValue = (style, prop) => {
32377
+ const value = style.getPropertyValue(prop).trim();
32378
+ return value === "none" ? "" : value;
32379
+ };
32380
+ function readCssRotation(element, withRotate = true) {
32381
+ const view = element.ownerDocument.defaultView;
32382
+ if (!view) return 0;
32383
+ const style = view.getComputedStyle(element);
32384
+ const rotate2 = withRotate ? cssValue(style, "rotate") : "";
32385
+ const scale = cssValue(style, "scale");
32386
+ const transform = cssValue(style, "transform");
32387
+ const angle = (list) => {
32388
+ if (!list) return 0;
32389
+ const m = new view.DOMMatrix(list);
32390
+ return Math.atan2(m.b, m.a) * 180 / Math.PI;
32391
+ };
32392
+ const folded = [rotate2 && `rotate(${rotate2})`, scale && `scale(${scale.split(/\s+/).join(",")})`];
32393
+ try {
32394
+ return angle([...folded, transform].join(" ").trim());
32395
+ } catch {
32396
+ return angle(transform);
32397
+ }
32398
+ }
32384
32399
  function computeDraggedGsapPosition(element, studioOffset, fallbackBase) {
32385
32400
  const rotStyle = element.style.getPropertyValue("--hf-studio-rotation");
32386
32401
  const rotDeg = Number.parseFloat(rotStyle) || 0;
@@ -32407,6 +32422,125 @@ function computeDraggedGsapPosition(element, studioOffset, fallbackBase) {
32407
32422
 
32408
32423
  // src/hooks/gsapRuntimeKeyframes.ts
32409
32424
  import { buildArcPath } from "@hyperframes/core/gsap-parser-acorn";
32425
+
32426
+ // src/components/editor/manualEditsDomPatches.ts
32427
+ function collectInlineStyleOps(element, properties, ops) {
32428
+ for (const prop of properties) {
32429
+ const val = element.style.getPropertyValue(prop);
32430
+ if (val) ops.push({ type: "inline-style", property: prop, value: val });
32431
+ }
32432
+ }
32433
+ function collectAttributeOps(element, attrNames, ops) {
32434
+ for (const attr of attrNames) {
32435
+ const val = element.getAttribute(attr);
32436
+ if (val !== null) ops.push({ type: "attribute", property: attr, value: val });
32437
+ }
32438
+ }
32439
+ function appendTransformDisplayOps(element, ops) {
32440
+ const val = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
32441
+ if (val !== null) {
32442
+ ops.push({ type: "inline-style", property: "display", value: val || null });
32443
+ ops.push({ type: "attribute", property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, value: null });
32444
+ }
32445
+ }
32446
+ function buildClearPathOffsetPatches(element) {
32447
+ const originalInlineTranslate = element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR);
32448
+ const ops = [
32449
+ { type: "inline-style", property: STUDIO_OFFSET_X_PROP, value: null },
32450
+ { type: "inline-style", property: STUDIO_OFFSET_Y_PROP, value: null },
32451
+ { type: "inline-style", property: "translate", value: originalInlineTranslate || null },
32452
+ { type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: null },
32453
+ { type: "attribute", property: STUDIO_ORIGINAL_TRANSLATE_ATTR, value: null },
32454
+ { type: "attribute", property: STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, value: null }
32455
+ ];
32456
+ appendTransformDisplayOps(element, ops);
32457
+ return ops;
32458
+ }
32459
+ var BOX_SIZE_STYLE_PROPS = [
32460
+ "width",
32461
+ "height",
32462
+ "min-width",
32463
+ "min-height",
32464
+ "max-width",
32465
+ "max-height",
32466
+ "flex-basis",
32467
+ "flex-grow",
32468
+ "flex-shrink",
32469
+ "box-sizing",
32470
+ "scale",
32471
+ "transform-origin",
32472
+ "display"
32473
+ ];
32474
+ var BOX_SIZE_ORIG_ATTRS = [
32475
+ [STUDIO_ORIGINAL_WIDTH_ATTR, "width"],
32476
+ [STUDIO_ORIGINAL_HEIGHT_ATTR, "height"],
32477
+ // Records a measurement rather than a style, so it restores nothing.
32478
+ [STUDIO_ORIGINAL_BOX_WIDTH_ATTR, ""],
32479
+ [STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, ""],
32480
+ [STUDIO_ORIGINAL_MIN_WIDTH_ATTR, "min-width"],
32481
+ [STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, "min-height"],
32482
+ [STUDIO_ORIGINAL_MAX_WIDTH_ATTR, "max-width"],
32483
+ [STUDIO_ORIGINAL_MAX_HEIGHT_ATTR, "max-height"],
32484
+ [STUDIO_ORIGINAL_FLEX_BASIS_ATTR, "flex-basis"],
32485
+ [STUDIO_ORIGINAL_FLEX_GROW_ATTR, "flex-grow"],
32486
+ [STUDIO_ORIGINAL_FLEX_SHRINK_ATTR, "flex-shrink"],
32487
+ [STUDIO_ORIGINAL_BOX_SIZING_ATTR, "box-sizing"],
32488
+ [STUDIO_ORIGINAL_SCALE_ATTR, "scale"],
32489
+ [STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, "transform-origin"],
32490
+ [STUDIO_ORIGINAL_DISPLAY_ATTR, "display"],
32491
+ [STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, ""]
32492
+ ];
32493
+ function buildBoxSizePatches(element) {
32494
+ const ops = [];
32495
+ collectInlineStyleOps(element, [STUDIO_WIDTH_PROP, STUDIO_HEIGHT_PROP], ops);
32496
+ collectInlineStyleOps(element, BOX_SIZE_STYLE_PROPS, ops);
32497
+ ops.push({ type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: "true" });
32498
+ collectAttributeOps(
32499
+ element,
32500
+ BOX_SIZE_ORIG_ATTRS.map(([attr]) => attr),
32501
+ ops
32502
+ );
32503
+ return ops;
32504
+ }
32505
+ function buildClearBoxSizePatches(element) {
32506
+ const ops = [
32507
+ { type: "inline-style", property: STUDIO_WIDTH_PROP, value: null },
32508
+ { type: "inline-style", property: STUDIO_HEIGHT_PROP, value: null },
32509
+ { type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: null }
32510
+ ];
32511
+ for (const [attrName, styleProp] of BOX_SIZE_ORIG_ATTRS) {
32512
+ const origVal = element.getAttribute(attrName);
32513
+ if (origVal !== null && styleProp) {
32514
+ ops.push({ type: "inline-style", property: styleProp, value: origVal || null });
32515
+ }
32516
+ ops.push({ type: "attribute", property: attrName, value: null });
32517
+ }
32518
+ return ops;
32519
+ }
32520
+ function buildClearRotationPatches(element) {
32521
+ const origInlineRotate = element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR);
32522
+ const origRotationTransformOrigin = element.getAttribute(
32523
+ STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR
32524
+ );
32525
+ const ops = [
32526
+ { type: "inline-style", property: STUDIO_ROTATION_PROP, value: null },
32527
+ { type: "inline-style", property: "rotate", value: origInlineRotate || null },
32528
+ {
32529
+ type: "inline-style",
32530
+ property: "transform-origin",
32531
+ value: origRotationTransformOrigin !== null ? origRotationTransformOrigin || null : null
32532
+ },
32533
+ { type: "attribute", property: STUDIO_ROTATION_ATTR, value: null },
32534
+ { type: "attribute", property: STUDIO_ROTATION_DRAFT_ATTR, value: null },
32535
+ { type: "attribute", property: STUDIO_ORIGINAL_ROTATE_ATTR, value: null },
32536
+ { type: "attribute", property: STUDIO_ORIGINAL_INLINE_ROTATE_ATTR, value: null },
32537
+ { type: "attribute", property: STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, value: null }
32538
+ ];
32539
+ appendTransformDisplayOps(element, ops);
32540
+ return ops;
32541
+ }
32542
+
32543
+ // src/hooks/gsapRuntimeKeyframes.ts
32410
32544
  var FLAT_SKIP_KEYS = /* @__PURE__ */ new Set([
32411
32545
  "ease",
32412
32546
  "duration",
@@ -32621,9 +32755,32 @@ function gsapWritesChannels(el, channels) {
32621
32755
  )
32622
32756
  );
32623
32757
  }
32758
+ var ROTATION_CHANNELS = [
32759
+ ...["rotation", "rotationX", "rotationY", "rotationZ"],
32760
+ ...["rotate", "rotateX", "rotateY", "rotateZ"]
32761
+ ];
32762
+ var gsapRendersTransform = (el) => !!el._gsap?.renderTransform;
32624
32763
  function gsapWritesPosition(el) {
32764
+ return gsapRendersTransform(el) || gsapWritesChannels(el, MOVE_CHANNELS);
32765
+ }
32766
+ function gsapWritesRotation(el) {
32767
+ return gsapRendersTransform(el) || gsapWritesChannels(el, ROTATION_CHANNELS);
32768
+ }
32769
+ function gsapHoldsTranslate(el) {
32625
32770
  const cache2 = el._gsap;
32626
- return !!cache2?.renderTransform || gsapWritesChannels(el, MOVE_CHANNELS);
32771
+ return ["x", "y", "xPercent", "yPercent"].some(
32772
+ (key2) => !!Number.parseFloat(String(cache2?.[key2]))
32773
+ );
32774
+ }
32775
+ var BOX_CHANNELS = [
32776
+ ...BOX_SIZE_STYLE_PROPS.map(
32777
+ (prop) => prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
32778
+ ),
32779
+ "scaleX",
32780
+ "scaleY"
32781
+ ];
32782
+ function gsapWritesBox(el) {
32783
+ return gsapWritesPosition(el) || gsapWritesChannels(el, BOX_CHANNELS);
32627
32784
  }
32628
32785
  function elementHasNonHoldTween(el, channels) {
32629
32786
  const win = el.ownerDocument.defaultView;
@@ -32754,14 +32911,39 @@ var UNREADABLE_TRANSLATE = "Studio can't read this layer's translate. Move it in
32754
32911
  function formatTranslatePx(p) {
32755
32912
  return `${roundTo3(p.x)}px ${roundTo3(p.y)}px`;
32756
32913
  }
32757
- function translatePatch(p) {
32758
- return { type: "inline-style", property: "translate", value: formatTranslatePx(p) };
32914
+ var LEGACY_OFFSET_VARS = [STUDIO_OFFSET_X_PROP, STUDIO_OFFSET_Y_PROP];
32915
+ function writePlainMove(el, p) {
32916
+ writeTranslatePx(el, p);
32917
+ const patches = [
32918
+ { type: "inline-style", property: "translate", value: formatTranslatePx(p) },
32919
+ {
32920
+ type: "attribute",
32921
+ property: STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
32922
+ value: el.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR)
32923
+ }
32924
+ ];
32925
+ for (const prop of LEGACY_OFFSET_VARS.filter((v) => el.style.getPropertyValue(v))) {
32926
+ el.style.removeProperty(prop);
32927
+ patches.push({ type: "inline-style", property: prop, value: null });
32928
+ }
32929
+ if (el.hasAttribute(STUDIO_PATH_OFFSET_ATTR)) {
32930
+ el.removeAttribute(STUDIO_PATH_OFFSET_ATTR);
32931
+ patches.push({ type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: null });
32932
+ }
32933
+ return patches;
32759
32934
  }
32760
32935
  function writeTranslatePx(el, p) {
32936
+ if (!el.hasAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR)) {
32937
+ const own = el.style.getPropertyValue("translate");
32938
+ el.setAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, styleUsesStudioOffset(own) ? "" : own);
32939
+ }
32761
32940
  el.style.setProperty("translate", formatTranslatePx(p));
32762
32941
  }
32763
- function readMoveOffset(el) {
32764
- return gsapWritesPosition(el) ? readStudioPathOffset(el) : readTranslatePx(el);
32942
+ function readMoveOffset(el, plainTranslate = !gsapWritesPosition(el)) {
32943
+ return plainTranslate ? readTranslatePx(el) : readStudioPathOffset(el);
32944
+ }
32945
+ function readShownRotation(el) {
32946
+ return gsapWritesRotation(el) ? readStudioRotation(el) : { angle: roundTo3(readCssRotation(el)) };
32765
32947
  }
32766
32948
 
32767
32949
  // src/components/editor/manualOffsetDrag.ts
@@ -32778,17 +32960,6 @@ function applyOffsetDragDraftViaGsap(element, offset, baseGsap) {
32778
32960
  gsap3.set(element, { x: newX, y: newY });
32779
32961
  return true;
32780
32962
  }
32781
- function applyRotationDraftViaGsap(element, angle) {
32782
- const gsap3 = getOffsetDragGsap(element);
32783
- if (!gsap3) return false;
32784
- element.style.setProperty("rotate", "none");
32785
- gsap3.set(element, { rotation: angle });
32786
- return true;
32787
- }
32788
- function readGsapRotation(element) {
32789
- const gsap3 = getOffsetDragGsap(element);
32790
- return gsap3 ? Number(gsap3.getProperty(element, "rotation")) || 0 : 0;
32791
- }
32792
32963
  var DEFAULT_OFFSET_PROBE_PX = 100;
32793
32964
  var MIN_PROBE_VECTOR_LENGTH_PX = 0.01;
32794
32965
  var MIN_MATRIX_DETERMINANT = 1e-6;
@@ -32936,7 +33107,8 @@ function resolveManualOffsetForPointerDelta(input) {
32936
33107
  };
32937
33108
  }
32938
33109
  function createManualOffsetDragMember(input) {
32939
- const plainTranslate = !!input.gesture && !gsapWritesPosition(input.element);
33110
+ const gsapOwns = input.gesture === "resize" ? gsapWritesBox : gsapWritesPosition;
33111
+ const plainTranslate = !!input.gesture && !gsapOwns(input.element);
32940
33112
  const initialOffset = plainTranslate ? readTranslatePx(input.element) : readAppliedStudioPathOffset(input.element);
32941
33113
  if (!finitePoint(initialOffset))
32942
33114
  return { ok: false, reason: UNREADABLE_TRANSLATE, selection: input.selection };
@@ -33102,6 +33274,94 @@ function resumeGsapTimelines(element) {
33102
33274
  win.__player?.seek?.(t);
33103
33275
  }
33104
33276
 
33277
+ // src/components/editor/rotationDraft.ts
33278
+ function lastRuleTransform(element) {
33279
+ let value = "";
33280
+ for (const sheet of Array.from(element.ownerDocument.styleSheets)) {
33281
+ let rules = [];
33282
+ try {
33283
+ rules = Array.from(sheet.cssRules);
33284
+ } catch {
33285
+ }
33286
+ for (const rule of rules) {
33287
+ const declared = rule.style?.getPropertyValue("transform");
33288
+ if (declared && element.matches(rule.selectorText)) value = declared;
33289
+ }
33290
+ }
33291
+ return value;
33292
+ }
33293
+ function translatingTransform(element) {
33294
+ const view = element.ownerDocument.defaultView;
33295
+ const computed = view?.getComputedStyle(element).transform ?? "none";
33296
+ const m = computed === "none" ? null : new view.DOMMatrix(computed);
33297
+ if (!m || m.m41 === 0 && m.m42 === 0) return "";
33298
+ const value = element.style.getPropertyValue("transform") || lastRuleTransform(element);
33299
+ return value === "none" ? "" : value;
33300
+ }
33301
+ var TRANSLATE = /^translate(?:3d|X|Y|Z)?\(/i;
33302
+ var OWN_TURN = /^rotate\(\s*-?[\d.]+(?:e[+-]?\d+)?deg\s*\)$/i;
33303
+ function readCssRotationTarget(element) {
33304
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
33305
+ const inline = style?.display === "inline";
33306
+ const transform = translatingTransform(element);
33307
+ if (!transform) {
33308
+ const share2 = readCssRotation(element, false);
33309
+ return { property: "rotate", before: "", after: "", share: share2, sign: 1, inline };
33310
+ }
33311
+ const parts = splitTopLevelWhitespace(transform);
33312
+ const lead = parts.findIndex((part) => !TRANSLATE.test(part));
33313
+ const split = lead < 0 ? parts.length : lead;
33314
+ const rest = parts.slice(split);
33315
+ if (OWN_TURN.test(rest[0] ?? "")) rest.shift();
33316
+ const [before, after] = [parts.slice(0, split).join(" "), rest.join(" ")];
33317
+ const [sx = 1, sy = sx] = splitTopLevelWhitespace(style?.getPropertyValue("scale") ?? "").map(
33318
+ Number.parseFloat
33319
+ );
33320
+ const inlineStyle = element.style;
33321
+ const saved2 = [
33322
+ inlineStyle.getPropertyValue("transform"),
33323
+ inlineStyle.getPropertyPriority("transform")
33324
+ ];
33325
+ inlineStyle.setProperty("transform", `${before} ${after}`.trim() || "none");
33326
+ const share = readCssRotation(element);
33327
+ inlineStyle.setProperty("transform", saved2[0] ?? "", saved2[1] ?? "");
33328
+ return { property: "transform", before, after, share, sign: sx * sy < 0 ? -1 : 1, inline };
33329
+ }
33330
+ function applyCssRotation(element, angle, target = readCssRotationTarget(element)) {
33331
+ const turn = `${roundTo3(target.sign * (angle - target.share))}deg`;
33332
+ const value = target.property === "rotate" ? turn : [target.before, `rotate(${turn})`, target.after].filter(Boolean).join(" ");
33333
+ const patches = [
33334
+ { type: "inline-style", property: target.property, value }
33335
+ ];
33336
+ if (target.inline) {
33337
+ patches.unshift({ type: "inline-style", property: "display", value: "inline-block" });
33338
+ }
33339
+ for (const patch of patches) element.style.setProperty(patch.property, patch.value);
33340
+ return patches;
33341
+ }
33342
+ function restorePlainRotation(element, snapshot3) {
33343
+ restoreStudioRotation(element, snapshot3);
33344
+ element.style.setProperty("transform", snapshot3.transform);
33345
+ element.style.setProperty("display", snapshot3.display);
33346
+ }
33347
+ function applyRotationDraft(element, angle, plain) {
33348
+ if (plain) return void applyCssRotation(element, angle, plain);
33349
+ element.style.setProperty("rotate", "none");
33350
+ getOffsetDragGsap(element)?.set(element, { rotation: angle });
33351
+ }
33352
+ function restoreRotationDraft(element, angle, snapshot3, plain) {
33353
+ if (plain) return restorePlainRotation(element, snapshot3);
33354
+ getOffsetDragGsap(element)?.set(element, {
33355
+ rotation: angle - (Number.parseFloat(snapshot3.studioRotation) || 0)
33356
+ });
33357
+ restoreStudioRotation(element, snapshot3);
33358
+ }
33359
+ function readRotationBase(element, plain) {
33360
+ if (plain) return readCssRotation(element);
33361
+ const gsapRotation = Number(getOffsetDragGsap(element)?.getProperty(element, "rotation") ?? 0);
33362
+ return gsapRotation + readStudioRotation(element).angle;
33363
+ }
33364
+
33105
33365
  // src/components/editor/domEditResizeLocal.ts
33106
33366
  var MIN_RESIZE_LOCAL_PX = 1;
33107
33367
  var DEGENERATE_START_DIST_PX = 3;
@@ -33215,27 +33475,6 @@ function resolveResizeDraftRect(g, element, overlayEl, iframe, measureOrientedRe
33215
33475
  };
33216
33476
  }
33217
33477
 
33218
- // src/utils/elementGsap.ts
33219
- function gsapOf(element) {
33220
- return element.ownerDocument.defaultView?.gsap;
33221
- }
33222
- function setElementGsapPosition(element, x, y) {
33223
- const gsap3 = gsapOf(element);
33224
- if (!gsap3?.set) return false;
33225
- gsap3.set(element, { x, y });
33226
- return true;
33227
- }
33228
- function setElementGsapScale(element, x, y) {
33229
- const gsap3 = gsapOf(element);
33230
- if (!gsap3?.set) return false;
33231
- gsap3.set(element, { scaleX: x, scaleY: y });
33232
- return true;
33233
- }
33234
- function readElementGsapNumber(element, prop) {
33235
- const value = Number(gsapOf(element)?.getProperty?.(element, prop));
33236
- return Number.isFinite(value) ? value : null;
33237
- }
33238
-
33239
33478
  // src/components/editor/snapEngine.ts
33240
33479
  var SNAP_THRESHOLD_PX = 6;
33241
33480
  var SNAP_ENGAGE_TRAVEL_PX = 4;
@@ -33806,18 +34045,6 @@ function startGesture(kind, e, opts, options) {
33806
34045
  const rawContentScaleY = rect.height / (rect.editScaleY * actualHeight);
33807
34046
  const contentScaleX = Number.isFinite(rawContentScaleX) && rawContentScaleX > 0 ? rawContentScaleX : 1;
33808
34047
  const contentScaleY = Number.isFinite(rawContentScaleY) && rawContentScaleY > 0 ? rawContentScaleY : 1;
33809
- let resizeAnchor;
33810
- if (kind === "resize") {
33811
- const startBcr = sel.element.getBoundingClientRect();
33812
- resizeAnchor = {
33813
- anchorX: startBcr.x,
33814
- anchorY: startBcr.y,
33815
- baseGsapX: readElementGsapNumber(sel.element, "x") ?? 0,
33816
- baseGsapY: readElementGsapNumber(sel.element, "y") ?? 0,
33817
- pinX: 0,
33818
- pinY: 0
33819
- };
33820
- }
33821
34048
  let initialPathOffset = captureStudioPathOffset(sel.element);
33822
34049
  let manualEditDragToken;
33823
34050
  let pathOffsetMember;
@@ -33845,12 +34072,14 @@ function startGesture(kind, e, opts, options) {
33845
34072
  key: selectionCacheKey(sel),
33846
34073
  selection: sel,
33847
34074
  element: sel.element,
33848
- rect
34075
+ rect,
34076
+ gesture: "resize"
33849
34077
  });
33850
34078
  if (result.ok) {
33851
34079
  pathOffsetMember = result.member;
33852
34080
  initialPathOffset = result.member.initialPathOffset;
33853
34081
  manualEditDragToken = result.member.gestureToken;
34082
+ if (result.member.plainTranslate) applyManualOffsetDragDraft(result.member, 0, 0);
33854
34083
  } else {
33855
34084
  manualEditDragToken = beginStudioManualEditGesture(sel.element);
33856
34085
  }
@@ -33858,8 +34087,9 @@ function startGesture(kind, e, opts, options) {
33858
34087
  manualEditDragToken = beginStudioManualEditGesture(sel.element);
33859
34088
  }
33860
34089
  }
33861
- const gsapRotation = pathOffsetMember?.plainTranslate ? 0 : readGsapRotation(sel.element);
33862
- const rotation = { angle: gsapRotation + readStudioRotation(sel.element).angle };
34090
+ const plain = !!pathOffsetMember?.plainTranslate || !gsapWritesRotation(sel.element);
34091
+ const plainRotation = plain && kind === "rotate" ? readCssRotationTarget(sel.element) : null;
34092
+ const rotation = { angle: readRotationBase(sel.element, plain) };
33863
34093
  const overlayBounds = overlayEl?.getBoundingClientRect();
33864
34094
  const centerX = (overlayBounds?.left ?? 0) + rect.left + rect.width / 2;
33865
34095
  const centerY = (overlayBounds?.top ?? 0) + rect.top + rect.height / 2;
@@ -33897,11 +34127,11 @@ function startGesture(kind, e, opts, options) {
33897
34127
  actualWidth,
33898
34128
  actualHeight,
33899
34129
  actualRotation: rotation.angle,
34130
+ plainRotation,
33900
34131
  editScaleX: rect.editScaleX,
33901
34132
  editScaleY: rect.editScaleY,
33902
34133
  contentScaleX,
33903
34134
  contentScaleY,
33904
- resizeAnchor,
33905
34135
  manualEditDragToken,
33906
34136
  snapContext,
33907
34137
  resizeHandle: kind === "resize" ? options?.resizeHandle ?? "se" : void 0,
@@ -34156,9 +34386,7 @@ function createDomEditOverlayGestureHandlers(opts) {
34156
34386
  actualAngle: g.actualRotation,
34157
34387
  snap: e.shiftKey
34158
34388
  });
34159
- if (!applyRotationDraftViaGsap(sel.element, rotated.angle)) {
34160
- applyStudioRotationDraft(sel.element, rotated);
34161
- }
34389
+ applyRotationDraft(sel.element, rotated.angle, g.plainRotation);
34162
34390
  return;
34163
34391
  }
34164
34392
  if (g.kind === "drag") {
@@ -34293,7 +34521,8 @@ function createDomEditOverlayGestureHandlers(opts) {
34293
34521
  );
34294
34522
  const updates = groupG.members.map((member) => ({
34295
34523
  selection: member.selection,
34296
- next: applyManualOffsetDragCommit(member, dx, dy)
34524
+ next: applyManualOffsetDragCommit(member, dx, dy),
34525
+ plainTranslate: member.plainTranslate
34297
34526
  }));
34298
34527
  logDrag("drop", {
34299
34528
  pointer: `${Math.round(rawDx)},${Math.round(rawDy)}`,
@@ -34366,20 +34595,20 @@ function createDomEditOverlayGestureHandlers(opts) {
34366
34595
  actualAngle: g.actualRotation,
34367
34596
  snap: e.shiftKey
34368
34597
  });
34369
- const restoreRotation = () => {
34370
- if (!applyRotationDraftViaGsap(sel.element, g.actualRotation)) {
34371
- restoreStudioRotation(sel.element, g.initialRotation);
34372
- }
34373
- };
34598
+ const restoreRotation = () => restoreRotationDraft(
34599
+ sel.element,
34600
+ g.actualRotation,
34601
+ g.initialRotation,
34602
+ g.plainRotation !== null
34603
+ );
34374
34604
  if (!hasDomEditRotationChanged(g.actualRotation, finalRotation.angle)) {
34375
34605
  restoreRotation();
34376
34606
  endStudioManualEditGesture(sel.element, g.manualEditDragToken);
34377
34607
  return;
34378
34608
  }
34379
- if (!applyRotationDraftViaGsap(sel.element, finalRotation.angle)) {
34380
- applyStudioRotation(sel.element, finalRotation);
34381
- }
34382
- void Promise.resolve(opts.onRotationCommitRef.current(sel, finalRotation)).catch((error) => {
34609
+ applyRotationDraft(sel.element, finalRotation.angle, g.plainRotation);
34610
+ const commit = g.plainRotation ? { ...finalRotation, plain: g.plainRotation } : finalRotation;
34611
+ void Promise.resolve(opts.onRotationCommitRef.current(sel, commit)).catch((error) => {
34383
34612
  logGestureCommitFailure("rotate commit failed", error);
34384
34613
  if (g.manualEditDragToken && isStudioManualEditGestureCurrent(sel.element, g.manualEditDragToken))
34385
34614
  restoreRotation();
@@ -34408,7 +34637,10 @@ function createDomEditOverlayGestureHandlers(opts) {
34408
34637
  box.style.top = `${nextBoxTop}px`;
34409
34638
  }
34410
34639
  void Promise.resolve(
34411
- opts.onPathOffsetCommitRef.current(sel, finalOffset, { altKey: e.altKey })
34640
+ opts.onPathOffsetCommitRef.current(sel, finalOffset, {
34641
+ altKey: e.altKey,
34642
+ plainTranslate: g.pathOffsetMember.plainTranslate
34643
+ })
34412
34644
  ).catch(() => {
34413
34645
  if (g.pathOffsetMember?.gestureToken && isStudioManualEditGestureCurrent(sel.element, g.pathOffsetMember.gestureToken))
34414
34646
  restoreStudioPathOffset(sel.element, g.initialPathOffset);
@@ -34466,11 +34698,12 @@ function createDomEditOverlayGestureHandlers(opts) {
34466
34698
  restoreGestureOverlayRect(g);
34467
34699
  }
34468
34700
  if (g?.mode === "rotation" && sel) {
34469
- applyRotationDraftViaGsap(
34701
+ restoreRotationDraft(
34470
34702
  sel.element,
34471
- g.actualRotation - (Number.parseFloat(g.initialRotation.studioRotation) || 0)
34703
+ g.actualRotation,
34704
+ g.initialRotation,
34705
+ g.plainRotation !== null
34472
34706
  );
34473
- restoreStudioRotation(sel.element, g.initialRotation);
34474
34707
  endStudioManualEditGesture(sel.element, g.manualEditDragToken);
34475
34708
  }
34476
34709
  opts.blockedMoveRef.current = null;
@@ -34549,10 +34782,13 @@ function useDomEditNudge(params) {
34549
34782
  if (session.timer) clearTimeout(session.timer);
34550
34783
  const updates = session.members.map((member) => ({
34551
34784
  selection: member.selection,
34552
- next: applyManualOffsetNudgeCommit(member, session.accum)
34785
+ next: applyManualOffsetNudgeCommit(member, session.accum),
34786
+ plainTranslate: member.plainTranslate
34553
34787
  }));
34554
34788
  const p = paramsRef.current;
34555
- const commit = session.isGroup ? p.onGroupPathOffsetCommitRef.current(updates) : p.onPathOffsetCommitRef.current(updates[0].selection, updates[0].next);
34789
+ const commit = session.isGroup ? p.onGroupPathOffsetCommitRef.current(updates) : p.onPathOffsetCommitRef.current(updates[0].selection, updates[0].next, {
34790
+ plainTranslate: updates[0].plainTranslate
34791
+ });
34556
34792
  void Promise.resolve(commit).catch(() => {
34557
34793
  for (const member of session.members) {
34558
34794
  if (isStudioManualEditGestureCurrent(member.element, member.gestureToken)) {
@@ -35137,7 +35373,7 @@ function DomEditRotateHandle({
35137
35373
  title: "Rotate",
35138
35374
  "aria-label": "Rotate selection",
35139
35375
  onPointerDown: onStartRotate,
35140
- children: /* @__PURE__ */ jsx85("span", { className: "pointer-events-none flex h-[18px] w-[18px] items-center justify-center rounded-full border border-studio-accent/70 bg-studio-surface text-studio-accent shadow-[0_0_3px_rgba(0,0,0,0.45)]", children: /* @__PURE__ */ jsxs58(
35376
+ children: /* @__PURE__ */ jsx85("span", { className: "pointer-events-none flex h-[18px] w-[18px] items-center justify-center rounded-full border border-studio-accent/70 bg-studio-surface text-accent-ink shadow-[0_0_3px_rgba(0,0,0,0.45)]", children: /* @__PURE__ */ jsxs58(
35141
35377
  "svg",
35142
35378
  {
35143
35379
  width: "11",
@@ -35533,7 +35769,7 @@ var CanvasContextMenu = memo24(function CanvasContextMenu2({
35533
35769
  "button",
35534
35770
  {
35535
35771
  type: "button",
35536
- className: "w-full flex items-center justify-between px-3 py-1.5 text-xs text-red-400 hover:bg-neutral-800 cursor-pointer text-left",
35772
+ className: "w-full flex items-center justify-between px-3 py-1.5 text-xs text-danger-ink hover:bg-neutral-800 cursor-pointer text-left",
35537
35773
  onPointerDown: (e) => {
35538
35774
  if (e.button !== 0) return;
35539
35775
  e.preventDefault();
@@ -36090,7 +36326,7 @@ function InlineTextToolbar({
36090
36326
  "data-inline-text-toolbar": "true",
36091
36327
  role: "toolbar",
36092
36328
  "aria-label": "Text formatting",
36093
- className: "pointer-events-auto fixed z-200 flex items-center gap-1 rounded-lg border border-white/10 bg-[#15171c] p-1 shadow-[0_8px_24px_rgba(0,0,0,0.55)]",
36329
+ className: "pointer-events-auto fixed z-200 flex items-center gap-1 rounded-lg border border-border bg-raised p-1 shadow-[0_8px_24px_rgba(0,0,0,0.55)]",
36094
36330
  style: {
36095
36331
  left: placement.left,
36096
36332
  top: placement.top,
@@ -36103,14 +36339,14 @@ function InlineTextToolbar({
36103
36339
  /* @__PURE__ */ jsxs61(
36104
36340
  "label",
36105
36341
  {
36106
- className: "group relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-white/10",
36342
+ className: "group relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-hover",
36107
36343
  title: "Text colour",
36108
36344
  children: [
36109
36345
  /* @__PURE__ */ jsx88(
36110
36346
  "span",
36111
36347
  {
36112
36348
  "aria-hidden": "true",
36113
- className: "h-4 w-4 rounded-full border-2 border-white/25 transition-transform duration-150 group-hover:scale-110 group-active:scale-95",
36349
+ className: "h-4 w-4 rounded-full border-2 border-border-strong transition-transform duration-150 group-hover:scale-110 group-active:scale-95",
36114
36350
  style: {
36115
36351
  background: swatchBackground(placement.colours, styles.color),
36116
36352
  backgroundOrigin: "border-box"
@@ -36192,7 +36428,7 @@ function ToolbarToggle({
36192
36428
  title: label,
36193
36429
  "aria-label": label,
36194
36430
  "aria-pressed": on,
36195
- className: `flex h-6 w-6 items-center justify-center rounded-md text-xs ${on ? "bg-studio-accent/20 text-studio-accent" : "text-white/70 hover:bg-white/10"}`,
36431
+ className: `flex h-6 w-6 items-center justify-center rounded-md text-xs ${on ? "bg-studio-accent/20 text-accent-ink" : "text-text-2 hover:bg-hover"}`,
36196
36432
  style: {
36197
36433
  fontWeight: bold ? 700 : 400,
36198
36434
  fontStyle: italic ? "italic" : "normal",
@@ -36340,7 +36576,7 @@ function useInlineTextEdit({
36340
36576
  }
36341
36577
  if (event.key === "Escape") {
36342
36578
  event.preventDefault();
36343
- cancel();
36579
+ commit();
36344
36580
  }
36345
36581
  };
36346
36582
  const onBlur = () => commit();
@@ -36368,7 +36604,7 @@ function useInlineTextEdit({
36368
36604
  element.removeEventListener("dragover", onDragOver);
36369
36605
  element.removeEventListener("drop", onDrop);
36370
36606
  };
36371
- }, [session, commit, cancel]);
36607
+ }, [session, commit]);
36372
36608
  const commitRef = useRef66(commit);
36373
36609
  commitRef.current = commit;
36374
36610
  useEffect46(() => () => commitRef.current(), []);
@@ -40869,7 +41105,7 @@ function editableAnimationId(animations, kind, sel) {
40869
41105
 
40870
41106
  // src/components/editor/MotionPathNode.tsx
40871
41107
  import { jsx as jsx93, jsxs as jsxs64 } from "react/jsx-runtime";
40872
- var ACCENT2 = "var(--hf-accent, #3CE6AC)";
41108
+ var ACCENT = "var(--hf-accent, #3CE6AC)";
40873
41109
  function MotionPathNode(props) {
40874
41110
  const { cx, cy, r, interactive, removable, grabbing, selected } = props;
40875
41111
  const bx = cx + r * 1.8;
@@ -40889,7 +41125,7 @@ function MotionPathNode(props) {
40889
41125
  stroke: "#0b0f1a",
40890
41126
  strokeWidth: 1.5,
40891
41127
  vectorEffect: "non-scaling-stroke",
40892
- style: { fill: ACCENT2 }
41128
+ style: { fill: ACCENT }
40893
41129
  }
40894
41130
  ),
40895
41131
  interactive && /* @__PURE__ */ jsx93(
@@ -40924,7 +41160,7 @@ function MotionPathNode(props) {
40924
41160
  stroke: "#0b0f1a",
40925
41161
  strokeWidth: 1,
40926
41162
  vectorEffect: "non-scaling-stroke",
40927
- style: { fill: ACCENT2 }
41163
+ style: { fill: ACCENT }
40928
41164
  }
40929
41165
  ),
40930
41166
  /* @__PURE__ */ jsx93(
@@ -41250,7 +41486,7 @@ var MotionPathOverlay = memo26(function MotionPathOverlay2({
41250
41486
  strokeWidth: 1.5,
41251
41487
  strokeDasharray: "3 3",
41252
41488
  vectorEffect: "non-scaling-stroke",
41253
- style: { stroke: ACCENT2 },
41489
+ style: { stroke: ACCENT },
41254
41490
  opacity: 0.85
41255
41491
  }
41256
41492
  )
@@ -41446,7 +41682,7 @@ var MotionPathOverlay = memo26(function MotionPathOverlay2({
41446
41682
  {
41447
41683
  points,
41448
41684
  fill: "none",
41449
- style: { stroke: ACCENT2 },
41685
+ style: { stroke: ACCENT },
41450
41686
  strokeWidth: 1.5,
41451
41687
  strokeDasharray: "5 5",
41452
41688
  strokeLinejoin: "round",
@@ -41469,7 +41705,7 @@ var MotionPathOverlay = memo26(function MotionPathOverlay2({
41469
41705
  strokeDasharray: "2 2",
41470
41706
  vectorEffect: "non-scaling-stroke",
41471
41707
  className: "pointer-events-none",
41472
- style: { stroke: ACCENT2 }
41708
+ style: { stroke: ACCENT }
41473
41709
  }
41474
41710
  ),
41475
41711
  abs.map((p, i) => /* @__PURE__ */ jsx94(
@@ -41572,7 +41808,7 @@ var SnapToolbar = memo27(function SnapToolbar2() {
41572
41808
  "button",
41573
41809
  {
41574
41810
  type: "button",
41575
- className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${motionPathArmed ? "bg-studio-accent/20 text-studio-accent" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41811
+ className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${motionPathArmed ? "bg-studio-accent/20 text-accent-ink" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41576
41812
  onClick: () => setMotionPathArmed(!motionPathArmed),
41577
41813
  title: motionPathArmed ? "Click the canvas to set the destination" : "Set motion destination",
41578
41814
  "aria-label": "Set motion destination",
@@ -41589,7 +41825,7 @@ var SnapToolbar = memo27(function SnapToolbar2() {
41589
41825
  "button",
41590
41826
  {
41591
41827
  type: "button",
41592
- className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${visible ? "bg-studio-accent/20 text-studio-accent" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41828
+ className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${visible ? "bg-studio-accent/20 text-accent-ink" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41593
41829
  onClick: toggle,
41594
41830
  title: `${label} ${visible ? "on" : "off"}`,
41595
41831
  "aria-label": `Toggle ${label.toLowerCase()}`,
@@ -41603,7 +41839,7 @@ var SnapToolbar = memo27(function SnapToolbar2() {
41603
41839
  "button",
41604
41840
  {
41605
41841
  type: "button",
41606
- className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${prefs.snapEnabled ? "bg-studio-accent/20 text-studio-accent" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41842
+ className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${prefs.snapEnabled ? "bg-studio-accent/20 text-accent-ink" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41607
41843
  onClick: toggleSnap,
41608
41844
  title: prefs.snapEnabled ? "Snap enabled (S)" : "Snap disabled (S)",
41609
41845
  "aria-label": "Toggle snap",
@@ -41616,7 +41852,7 @@ var SnapToolbar = memo27(function SnapToolbar2() {
41616
41852
  {
41617
41853
  ref: gridButtonRef,
41618
41854
  type: "button",
41619
- className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${prefs.gridVisible ? "bg-studio-accent/20 text-studio-accent" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41855
+ className: `rounded-md p-1.5 transition-colors active:scale-[0.95] ${prefs.gridVisible ? "bg-studio-accent/20 text-accent-ink" : "bg-black/40 text-white/60 hover:bg-black/60 hover:text-white/80"}`,
41620
41856
  onClick: toggleGrid,
41621
41857
  onContextMenu: (e) => {
41622
41858
  e.preventDefault();
@@ -41643,7 +41879,7 @@ var SnapToolbar = memo27(function SnapToolbar2() {
41643
41879
  "div",
41644
41880
  {
41645
41881
  ref: popoverRef,
41646
- className: "absolute right-0 top-full mt-1 rounded-lg bg-neutral-800 border border-neutral-700 p-3 shadow-xl min-w-[180px]",
41882
+ className: "absolute right-0 top-full mt-1 rounded-lg bg-raised border border-border p-3 shadow-xl min-w-[180px]",
41647
41883
  children: [
41648
41884
  /* @__PURE__ */ jsxs66("label", { className: "flex items-center justify-between text-xs text-white/80 mb-2", children: [
41649
41885
  /* @__PURE__ */ jsx95("span", { children: "Grid spacing" }),
@@ -41903,7 +42139,7 @@ function PreviewOverlays({
41903
42139
  {
41904
42140
  type: "button",
41905
42141
  onClick: enterCaptionMode,
41906
- className: "pointer-events-auto absolute top-2 left-1/2 -translate-x-1/2 z-60 rounded-full border border-neutral-700 bg-black/60 px-2.5 py-1 text-2xs text-neutral-300 transition-colors hover:border-studio-accent/50 hover:text-studio-accent focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-studio-accent",
42142
+ className: "pointer-events-auto absolute top-2 left-1/2 -translate-x-1/2 z-60 rounded-full border border-neutral-700 bg-black/60 px-2.5 py-1 text-2xs text-neutral-300 transition-colors hover:border-studio-accent/50 hover:text-accent-ink focus-visible:outline-solid focus-visible:outline-1 focus-visible:outline-studio-accent",
41907
42143
  children: "Edit captions"
41908
42144
  }
41909
42145
  )
@@ -42566,7 +42802,6 @@ function getAnimationsForElement(animations, target, element) {
42566
42802
 
42567
42803
  // src/hooks/gsapRuntimeBridge.ts
42568
42804
  var POSITION_CHANNEL_SET = new Set(POSITION_CHANNELS);
42569
- var ROTATION_CHANNELS = ["rotation", "rotationX", "rotationY", "rotationZ"];
42570
42805
  var ROTATION_CHANNEL_SET = new Set(ROTATION_CHANNELS);
42571
42806
  async function resolveGroupTween(group, animations, selection, commitMutation, fetchFallbackAnimations) {
42572
42807
  const groupAnims = animations.filter((a) => a.propertyGroup === group);
@@ -43538,7 +43773,7 @@ var CaptionTimeline = memo29(function CaptionTimeline2({
43538
43773
  tabIndex: 0,
43539
43774
  "aria-label": `Caption word "${seg.text}"`,
43540
43775
  "aria-pressed": isSelected,
43541
- className: `absolute top-1 bottom-1 rounded flex items-center overflow-hidden cursor-pointer focus-visible:ring-1 focus-visible:ring-white outline-hidden${isSelected ? " ring-1 ring-white/50 z-10" : ""}`,
43776
+ className: `absolute top-1 bottom-1 rounded flex items-center overflow-hidden cursor-pointer focus-visible:ring-1 focus-visible:ring-text-0 outline-hidden${isSelected ? " ring-1 ring-text-0/50 z-10" : ""}`,
43542
43777
  style: {
43543
43778
  left,
43544
43779
  width,
@@ -43563,7 +43798,7 @@ var CaptionTimeline = memo29(function CaptionTimeline2({
43563
43798
  /* @__PURE__ */ jsx98(
43564
43799
  "div",
43565
43800
  {
43566
- className: "absolute top-0 bottom-0 w-px bg-white/70 pointer-events-none z-20",
43801
+ className: "absolute top-0 bottom-0 w-px bg-text-0/70 pointer-events-none z-20",
43567
43802
  style: { left: playheadLeft },
43568
43803
  "aria-hidden": "true"
43569
43804
  }
@@ -45802,7 +46037,7 @@ function WindowMenu() {
45802
46037
  onClick: () => togglePanel(id),
45803
46038
  className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-[11px] text-neutral-300 hover:bg-neutral-800",
45804
46039
  children: [
45805
- /* @__PURE__ */ jsx101("span", { className: "w-3 text-panel-accent", children: openPanels.has(id) ? "\u2713" : "" }),
46040
+ /* @__PURE__ */ jsx101("span", { className: "w-3 text-accent-ink", children: openPanels.has(id) ? "\u2713" : "" }),
45806
46041
  PANEL_DEFINITIONS[id].title
45807
46042
  ]
45808
46043
  },
@@ -46870,7 +47105,7 @@ function InspectorHeaderActions({
46870
47105
  track2("button", "Copy element info");
46871
47106
  onCopy();
46872
47107
  },
46873
- className: `flex h-6 w-6 items-center justify-center rounded transition-colors ${copied ? "text-studio-accent" : "text-neutral-500 hover:bg-neutral-800 hover:text-neutral-300"}`,
47108
+ className: `flex h-6 w-6 items-center justify-center rounded transition-colors ${copied ? "text-accent-ink" : "text-neutral-500 hover:bg-neutral-800 hover:text-neutral-300"}`,
46874
47109
  title: copied ? "Copied!" : "Copy element info to clipboard",
46875
47110
  children: /* @__PURE__ */ jsxs75(
46876
47111
  "svg",
@@ -47905,7 +48140,7 @@ function SegmentedControl({
47905
48140
  onChange(option.value);
47906
48141
  },
47907
48142
  "aria-pressed": option.value === value,
47908
- className: `min-w-0 truncate rounded px-2 py-[5px] text-[11px] font-medium transition-colors disabled:cursor-not-allowed ${option.value === value ? "bg-panel-hover text-white" : "text-panel-text-4 hover:text-panel-text-2"}`,
48143
+ className: `min-w-0 truncate rounded px-2 py-[5px] text-[11px] font-medium transition-colors disabled:cursor-not-allowed ${option.value === value ? "bg-panel-hover text-text-0" : "text-panel-text-4 hover:text-panel-text-2"}`,
47909
48144
  children: option.label
47910
48145
  },
47911
48146
  option.value
@@ -48023,14 +48258,16 @@ function createTransformCommitHandlers({
48023
48258
  "This element's position can't be edited here yet \u2014 it is driven by its animation"
48024
48259
  ))
48025
48260
  return;
48026
- const current = readMoveOffset(element.element);
48261
+ const plainTranslate = !gsapWritesPosition(element.element);
48262
+ const current = readMoveOffset(element.element, plainTranslate);
48027
48263
  if (!Number.isFinite(current.x) || !Number.isFinite(current.y))
48028
48264
  return void showToast?.(UNREADABLE_TRANSLATE);
48029
48265
  await Promise.resolve(
48030
- onSetManualOffset(element, {
48031
- x: axis === "x" ? parsed : current.x,
48032
- y: axis === "y" ? parsed : current.y
48033
- })
48266
+ onSetManualOffset(
48267
+ element,
48268
+ { x: axis === "x" ? parsed : current.x, y: axis === "y" ? parsed : current.y },
48269
+ { plainTranslate }
48270
+ )
48034
48271
  );
48035
48272
  };
48036
48273
  const commitManualSize = async (axis, nextValue) => {
@@ -48254,7 +48491,7 @@ function MediaSection({
48254
48491
  /* @__PURE__ */ jsx110("div", { className: "h-1 overflow-hidden rounded-full bg-panel-border", children: /* @__PURE__ */ jsx110(
48255
48492
  "div",
48256
48493
  {
48257
- className: `h-full rounded-full ${removeProgress.status === "failed" ? "bg-red-400" : "bg-studio-accent"}`,
48494
+ className: `h-full rounded-full ${removeProgress.status === "failed" ? "bg-danger-ink" : "bg-studio-accent"}`,
48258
48495
  style: { width: `${Math.max(0, Math.min(100, removeProgress.progress))}%` }
48259
48496
  }
48260
48497
  ) })
@@ -48556,7 +48793,7 @@ function ColorGradingSliderControl({
48556
48793
  event.stopPropagation();
48557
48794
  settings.onClick();
48558
48795
  },
48559
- className: `relative flex h-5 w-5 shrink-0 items-center justify-center rounded transition-colors hover:bg-panel-hover hover:text-panel-text-1 disabled:cursor-not-allowed disabled:opacity-40 ${settings.active ? "text-studio-accent" : "text-panel-text-5"}`,
48796
+ className: `relative flex h-5 w-5 shrink-0 items-center justify-center rounded transition-colors hover:bg-panel-hover hover:text-panel-text-1 disabled:cursor-not-allowed disabled:opacity-40 ${settings.active ? "text-accent-ink" : "text-panel-text-5"}`,
48560
48797
  title: settings.label,
48561
48798
  children: [
48562
48799
  /* @__PURE__ */ jsx111(Settings, { size: 11 }),
@@ -49021,7 +49258,7 @@ function ColorGradingControls({
49021
49258
  }
49022
49259
  )
49023
49260
  ] }),
49024
- lutImportError && /* @__PURE__ */ jsx112("div", { className: "text-[10px] text-red-400", role: "alert", children: lutImportError }),
49261
+ lutImportError && /* @__PURE__ */ jsx112("div", { className: "text-[10px] text-danger-ink", role: "alert", children: lutImportError }),
49025
49262
  grading.lut && /* @__PURE__ */ jsxs79("div", { className: "grid gap-2", children: [
49026
49263
  selectedProjectLut && /* @__PURE__ */ jsxs79("div", { className: "flex min-w-0 items-start gap-2 text-[10px] leading-4 text-panel-text-3", children: [
49027
49264
  /* @__PURE__ */ jsx112("span", { className: "mt-[5px] h-1.5 w-1.5 shrink-0 rounded-full bg-studio-accent" }),
@@ -49892,7 +50129,7 @@ function useColorGradingController({
49892
50129
  // src/components/editor/propertyPanelColorGradingSection.tsx
49893
50130
  import { jsx as jsx113, jsxs as jsxs80 } from "react/jsx-runtime";
49894
50131
  function StatusPill({ status }) {
49895
- const dotClass = status.state === "active" ? "bg-emerald-400" : status.state === "pending" ? "bg-amber-300" : status.state === "unavailable" ? "bg-red-400" : "bg-panel-text-5";
50132
+ const dotClass = status.state === "active" ? "bg-accent" : status.state === "pending" ? "bg-warning-ink" : status.state === "unavailable" ? "bg-danger-ink" : "bg-panel-text-5";
49896
50133
  return /* @__PURE__ */ jsxs80(
49897
50134
  "div",
49898
50135
  {
@@ -49914,16 +50151,16 @@ function HdrMediaWarning({ metadata }) {
49914
50151
  metadata.color.colorPrimaries,
49915
50152
  metadata.color.colorTransfer
49916
50153
  ].filter(Boolean).join(" \xB7 ");
49917
- return /* @__PURE__ */ jsxs80("div", { className: "mb-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-[11px] leading-4 text-amber-100", children: [
50154
+ return /* @__PURE__ */ jsxs80("div", { className: "mb-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-[11px] leading-4 text-warning-ink", children: [
49918
50155
  /* @__PURE__ */ jsxs80("div", { className: "mb-1 flex min-w-0 items-center justify-between gap-2", children: [
49919
50156
  /* @__PURE__ */ jsxs80("span", { className: "font-semibold", children: [
49920
50157
  metadata.color.label,
49921
50158
  " source"
49922
50159
  ] }),
49923
- /* @__PURE__ */ jsx113("span", { className: "rounded-sm bg-amber-400/20 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-amber-100", children: "SDR preview" })
50160
+ /* @__PURE__ */ jsx113("span", { className: "rounded-sm bg-amber-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-warning-ink", children: "SDR preview" })
49924
50161
  ] }),
49925
- /* @__PURE__ */ jsx113("p", { className: "text-amber-100/80", children: "These controls use the current SDR shader preview path. Render may stay HDR-tagged, but this is not true HDR color grading yet." }),
49926
- details && /* @__PURE__ */ jsx113("p", { className: "mt-1 truncate text-[10px] text-amber-100/55", children: details })
50162
+ /* @__PURE__ */ jsx113("p", { className: "text-text-2", children: "These controls use the current SDR shader preview path. Render may stay HDR-tagged, but this is not true HDR color grading yet." }),
50163
+ details && /* @__PURE__ */ jsx113("p", { className: "mt-1 truncate text-[10px] text-text-muted", children: details })
49927
50164
  ] });
49928
50165
  }
49929
50166
  function HoldBeforeButton({
@@ -49980,7 +50217,7 @@ function HoldBeforeButton({
49980
50217
  event.preventDefault();
49981
50218
  onHoldChange(false);
49982
50219
  },
49983
- className: `flex h-6 w-6 shrink-0 items-center justify-center rounded transition-colors ${active ? "bg-studio-accent text-black" : "text-panel-text-4 hover:bg-panel-hover hover:text-panel-text-1"} disabled:cursor-not-allowed disabled:opacity-40`,
50220
+ className: `flex h-6 w-6 shrink-0 items-center justify-center rounded transition-colors ${active ? "bg-studio-accent text-on-accent" : "text-panel-text-4 hover:bg-panel-hover hover:text-panel-text-1"} disabled:cursor-not-allowed disabled:opacity-40`,
49984
50221
  title: "Hold to show original",
49985
50222
  children: /* @__PURE__ */ jsx113(Compare, { size: 13 })
49986
50223
  }
@@ -50973,7 +51210,7 @@ function FontFamilyField({
50973
51210
  type: "button",
50974
51211
  disabled: disabled || loadingLocalFonts,
50975
51212
  onClick: loadBrowserLocalFonts,
50976
- className: "rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 text-[10px] font-medium text-neutral-400 transition-colors hover:border-neutral-600 hover:text-neutral-100 disabled:cursor-not-allowed disabled:text-neutral-700",
51213
+ className: "rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 text-[10px] font-medium text-neutral-400 transition-colors hover:border-neutral-600 hover:text-neutral-100 disabled:cursor-not-allowed disabled:text-text-off",
50977
51214
  children: loadingLocalFonts ? "..." : "Local"
50978
51215
  }
50979
51216
  ),
@@ -50983,7 +51220,7 @@ function FontFamilyField({
50983
51220
  type: "button",
50984
51221
  disabled: disabled || importingFonts || !onImportFonts,
50985
51222
  onClick: () => fontInputRef.current?.click(),
50986
- className: "rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 text-[10px] font-medium text-neutral-400 transition-colors hover:border-neutral-600 hover:text-neutral-100 disabled:cursor-not-allowed disabled:text-neutral-700",
51223
+ className: "rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 text-[10px] font-medium text-neutral-400 transition-colors hover:border-neutral-600 hover:text-neutral-100 disabled:cursor-not-allowed disabled:text-text-off",
50987
51224
  children: importingFonts ? "..." : "Import"
50988
51225
  }
50989
51226
  ),
@@ -51401,7 +51638,7 @@ function VariablesBindElement({
51401
51638
  className: `${VARIABLES_INPUT_CLASS} font-mono`
51402
51639
  }
51403
51640
  ),
51404
- existingDecl && /* @__PURE__ */ jsxs84("p", { className: "text-[9px] leading-snug text-amber-400/90", children: [
51641
+ existingDecl && /* @__PURE__ */ jsxs84("p", { className: "text-[9px] leading-snug text-warning-ink", children: [
51405
51642
  '"',
51406
51643
  trimmedId,
51407
51644
  '" already exists. This element will use its current value',
@@ -51592,7 +51829,7 @@ function PromotableControl({
51592
51829
  bound && /* @__PURE__ */ jsxs85(
51593
51830
  "span",
51594
51831
  {
51595
- className: "pointer-events-none absolute -top-2 right-1.5 z-10 inline-flex max-w-[60%] items-center gap-1 truncate rounded-sm bg-studio-accent/20 px-1 py-px font-mono text-[8px] font-medium text-studio-accent",
51832
+ className: "pointer-events-none absolute -top-2 right-1.5 z-10 inline-flex max-w-[60%] items-center gap-1 truncate rounded-sm bg-studio-accent/20 px-1 py-px font-mono text-[8px] font-medium text-accent-ink",
51596
51833
  title: `Bound to variable "${promote.boundId}"`,
51597
51834
  children: [
51598
51835
  "\u25C6 ",
@@ -51609,7 +51846,7 @@ function PromotableControl({
51609
51846
  e.stopPropagation();
51610
51847
  promote.promote();
51611
51848
  },
51612
- className: "absolute -top-2 right-1.5 z-10 inline-flex items-center gap-1 rounded-sm bg-neutral-800/80 px-1 py-px font-mono text-[8px] font-medium text-neutral-400 opacity-70 transition-colors hover:bg-studio-accent/20 hover:text-studio-accent hover:opacity-100",
51849
+ className: "absolute -top-2 right-1.5 z-10 inline-flex items-center gap-1 rounded-sm bg-raised/80 px-1 py-px font-mono text-[8px] font-medium text-neutral-400 opacity-70 transition-colors hover:bg-studio-accent/20 hover:text-accent-ink hover:opacity-100",
51613
51850
  children: "\u25C7 var"
51614
51851
  }
51615
51852
  )
@@ -52069,7 +52306,7 @@ function ImageFillField({
52069
52306
  type: "button",
52070
52307
  disabled: disabled || uploading,
52071
52308
  onClick: () => fileInputRef.current?.click(),
52072
- className: `inline-flex h-7 max-w-full items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors ${disabled || uploading ? "cursor-not-allowed text-neutral-600" : "cursor-pointer hover:border-neutral-600 hover:text-white"}`,
52309
+ className: `inline-flex h-7 max-w-full items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors ${disabled || uploading ? "cursor-not-allowed text-neutral-600" : "cursor-pointer hover:border-neutral-600 hover:text-text-0"}`,
52073
52310
  children: [
52074
52311
  /* @__PURE__ */ jsx121(Plus, { size: 12, className: "shrink-0" }),
52075
52312
  /* @__PURE__ */ jsx121("span", { className: "truncate", children: uploading ? "Uploading\u2026" : "Upload image" })
@@ -52092,7 +52329,7 @@ function ImageFillField({
52092
52329
  }
52093
52330
  )
52094
52331
  ] }),
52095
- uploadError && /* @__PURE__ */ jsx121("div", { className: "text-[10px] text-red-400", role: "alert", children: uploadError }),
52332
+ uploadError && /* @__PURE__ */ jsx121("div", { className: "text-[10px] text-danger-ink", role: "alert", children: uploadError }),
52096
52333
  imageAssets.length > 0 ? /* @__PURE__ */ jsxs87("div", { className: "space-y-3", children: [
52097
52334
  selectedAsset && /* @__PURE__ */ jsx121("div", { className: "overflow-hidden rounded-xl border border-neutral-800 bg-neutral-900/80", children: /* @__PURE__ */ jsx121(
52098
52335
  "img",
@@ -52256,7 +52493,7 @@ function GradientField({
52256
52493
  track2("toggle", "Repeat gradient");
52257
52494
  patch({ repeating: e.target.checked });
52258
52495
  },
52259
- className: "h-4 w-4 rounded-sm border-neutral-700 bg-neutral-950 text-panel-accent focus:ring-panel-accent"
52496
+ className: "h-4 w-4 rounded-sm border-neutral-700 bg-neutral-950 text-accent-ink focus:ring-panel-accent"
52260
52497
  }
52261
52498
  ),
52262
52499
  "Repeat"
@@ -52276,7 +52513,7 @@ function GradientField({
52276
52513
  }))
52277
52514
  });
52278
52515
  },
52279
- className: "inline-flex h-7 items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-white disabled:cursor-not-allowed disabled:text-neutral-600",
52516
+ className: "inline-flex h-7 items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-text-0 disabled:cursor-not-allowed disabled:text-neutral-600",
52280
52517
  children: [
52281
52518
  /* @__PURE__ */ jsx121(ReverseGradientIcon, { size: 16 }),
52282
52519
  "Reverse"
@@ -52370,7 +52607,7 @@ function GradientField({
52370
52607
  disabled: disabled || parsed.stops.length >= 6,
52371
52608
  onClick: () => addStop(),
52372
52609
  title: parsed.stops.length >= 6 ? "Maximum 6 stops" : "Add a gradient stop",
52373
- className: "inline-flex h-7 items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-white active:scale-[0.98] disabled:cursor-not-allowed disabled:text-neutral-600",
52610
+ className: "inline-flex h-7 items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-text-0 active:scale-[0.98] disabled:cursor-not-allowed disabled:text-neutral-600",
52374
52611
  children: [
52375
52612
  /* @__PURE__ */ jsx121(Plus, { size: 12 }),
52376
52613
  "Add stop"
@@ -52409,7 +52646,7 @@ function GradientField({
52409
52646
  type: "button",
52410
52647
  disabled: disabled || parsed.stops.length <= 2,
52411
52648
  onClick: () => removeStop(index),
52412
- className: "mt-[22px] flex h-10 items-center justify-center rounded-lg border border-neutral-700 bg-neutral-950 text-neutral-400 transition-colors hover:border-neutral-600 hover:text-white disabled:cursor-not-allowed disabled:text-neutral-700",
52649
+ className: "mt-[22px] flex h-10 items-center justify-center rounded-lg border border-neutral-700 bg-neutral-950 text-neutral-400 transition-colors hover:border-neutral-600 hover:text-text-0 disabled:cursor-not-allowed disabled:text-text-off",
52413
52650
  "aria-label": `Remove stop ${index + 1}`,
52414
52651
  children: /* @__PURE__ */ jsx121(X, { size: 12 })
52415
52652
  }
@@ -52468,6 +52705,7 @@ function BorderRadiusEditor({
52468
52705
  setLinked((l) => !l);
52469
52706
  }, [linked, uniform, tl, onCommit]);
52470
52707
  const path = buildRoundedRectPath(PREVIEW_W, PREVIEW_H, sTL, sTR, sBR, sBL);
52708
+ const dotFill = linked ? "fill-[light-dark(oklch(0.5_0.2_260),#3b82f6)]" : "fill-[light-dark(oklch(0.55_0.2_294),#a78bfa)]";
52471
52709
  return /* @__PURE__ */ jsxs88("div", { className: "space-y-3", children: [
52472
52710
  /* @__PURE__ */ jsxs88("div", { className: "flex items-center gap-3", children: [
52473
52711
  /* @__PURE__ */ jsxs88(
@@ -52478,27 +52716,11 @@ function BorderRadiusEditor({
52478
52716
  viewBox: `0 0 ${PREVIEW_W} ${PREVIEW_H}`,
52479
52717
  className: "shrink-0",
52480
52718
  children: [
52481
- /* @__PURE__ */ jsx122(
52482
- "path",
52483
- {
52484
- d: path,
52485
- fill: "rgba(255,255,255,0.06)",
52486
- stroke: "rgba(255,255,255,0.24)",
52487
- strokeWidth: 1.5
52488
- }
52489
- ),
52490
- /* @__PURE__ */ jsx122("circle", { cx: sTL, cy: sTL, r: 3, fill: linked ? "#3b82f6" : "#a78bfa" }),
52491
- /* @__PURE__ */ jsx122("circle", { cx: PREVIEW_W - sTR, cy: sTR, r: 3, fill: linked ? "#3b82f6" : "#a78bfa" }),
52492
- /* @__PURE__ */ jsx122(
52493
- "circle",
52494
- {
52495
- cx: PREVIEW_W - sBR,
52496
- cy: PREVIEW_H - sBR,
52497
- r: 3,
52498
- fill: linked ? "#3b82f6" : "#a78bfa"
52499
- }
52500
- ),
52501
- /* @__PURE__ */ jsx122("circle", { cx: sBL, cy: PREVIEW_H - sBL, r: 3, fill: linked ? "#3b82f6" : "#a78bfa" })
52719
+ /* @__PURE__ */ jsx122("path", { d: path, className: "fill-text-0/[0.06] stroke-text-0/25", strokeWidth: 1.5 }),
52720
+ /* @__PURE__ */ jsx122("circle", { cx: sTL, cy: sTL, r: 3, className: dotFill }),
52721
+ /* @__PURE__ */ jsx122("circle", { cx: PREVIEW_W - sTR, cy: sTR, r: 3, className: dotFill }),
52722
+ /* @__PURE__ */ jsx122("circle", { cx: PREVIEW_W - sBR, cy: PREVIEW_H - sBR, r: 3, className: dotFill }),
52723
+ /* @__PURE__ */ jsx122("circle", { cx: sBL, cy: PREVIEW_H - sBL, r: 3, className: dotFill })
52502
52724
  ]
52503
52725
  }
52504
52726
  ),
@@ -53320,7 +53542,7 @@ function TextFieldEditor({
53320
53542
  track2("button", "Remove text field");
53321
53543
  onRemoveTextField(field.key);
53322
53544
  },
53323
- className: "inline-flex h-7 shrink-0 items-center rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-white",
53545
+ className: "inline-flex h-7 shrink-0 items-center rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-text-0",
53324
53546
  children: "Remove"
53325
53547
  }
53326
53548
  )
@@ -53459,7 +53681,7 @@ function TextSection({
53459
53681
  if (nextKey) setActiveTextFieldKey(nextKey);
53460
53682
  });
53461
53683
  },
53462
- className: "inline-flex h-7 max-w-full items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-white",
53684
+ className: "inline-flex h-7 max-w-full items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-text-0",
53463
53685
  children: [
53464
53686
  /* @__PURE__ */ jsx124(Plus, { size: 12, className: "shrink-0" }),
53465
53687
  /* @__PURE__ */ jsx124("span", { className: "truncate", children: "Add text" })
@@ -53707,7 +53929,7 @@ function ComputedTweenNotice({
53707
53929
  {
53708
53930
  type: "button",
53709
53931
  onClick: onUnroll,
53710
- className: "shrink-0 rounded-sm px-1.5 py-0.5 text-[9px] font-medium text-panel-accent hover:bg-neutral-800",
53932
+ className: "shrink-0 rounded-sm px-1.5 py-0.5 text-[9px] font-medium text-accent-ink hover:bg-neutral-800",
53711
53933
  title: "Rewrite the helper/loop into explicit tweens so this keyframe edits directly",
53712
53934
  children: "Unroll to edit"
53713
53935
  }
@@ -53868,7 +54090,7 @@ function RemoveButton({ onClick, title }) {
53868
54090
  {
53869
54091
  type: "button",
53870
54092
  onClick,
53871
- className: "relative shrink-0 rounded-sm p-1.5 text-neutral-600 transition-colors hover:bg-neutral-800 hover:text-red-400 active:scale-[0.95]",
54093
+ className: "relative shrink-0 rounded-sm p-1.5 text-neutral-600 transition-colors hover:bg-neutral-800 hover:text-danger-ink active:scale-[0.95]",
53872
54094
  title,
53873
54095
  "aria-label": title,
53874
54096
  children: /* @__PURE__ */ jsx128(
@@ -54155,7 +54377,7 @@ var AnimationCard = memo34(function AnimationCard2({
54155
54377
  /* @__PURE__ */ jsx129(
54156
54378
  "span",
54157
54379
  {
54158
- className: "rounded-sm bg-panel-accent/10 px-1.5 py-0.5 text-[10px] font-semibold text-panel-accent",
54380
+ className: "rounded-sm bg-panel-accent/10 px-1.5 py-0.5 text-[10px] font-semibold text-accent-ink",
54159
54381
  title: METHOD_TOOLTIPS[animation.method],
54160
54382
  children: methodLabel
54161
54383
  }
@@ -54311,7 +54533,7 @@ var AnimationCard = memo34(function AnimationCard2({
54311
54533
  )
54312
54534
  ] }) }),
54313
54535
  animation.method === "fromTo" && /* @__PURE__ */ jsxs95("div", { className: "space-y-1", children: [
54314
- /* @__PURE__ */ jsx129("p", { className: "text-[9px] font-semibold uppercase tracking-wider text-orange-400/70", children: "From" }),
54536
+ /* @__PURE__ */ jsx129("p", { className: "text-[9px] font-semibold uppercase tracking-wider text-warning-ink", children: "From" }),
54315
54537
  /* @__PURE__ */ jsx129("div", { className: "space-y-1.5", children: Object.entries(animation.fromProperties ?? {}).map(([prop, val]) => /* @__PURE__ */ jsx129(
54316
54538
  PropertyRow,
54317
54539
  {
@@ -54333,11 +54555,11 @@ var AnimationCard = memo34(function AnimationCard2({
54333
54555
  onAdd: (prop) => onAddFromProperty?.(animation.id, prop),
54334
54556
  onOpen: () => setAddingFromProp(true),
54335
54557
  onClose: () => setAddingFromProp(false),
54336
- buttonClassName: "text-[11px] font-medium text-orange-400/70 transition-colors hover:text-orange-300"
54558
+ buttonClassName: "text-[11px] font-medium text-warning-ink transition-colors hover:text-text-0"
54337
54559
  }
54338
54560
  ) })
54339
54561
  ] }),
54340
- animation.method === "fromTo" && Object.keys(animation.properties).length > 0 && /* @__PURE__ */ jsx129("p", { className: "text-[9px] font-semibold uppercase tracking-wider text-panel-accent/70", children: "To" }),
54562
+ animation.method === "fromTo" && Object.keys(animation.properties).length > 0 && /* @__PURE__ */ jsx129("p", { className: "text-[9px] font-semibold uppercase tracking-wider text-accent-ink", children: "To" }),
54341
54563
  Object.keys(animation.properties).length > 0 && /* @__PURE__ */ jsx129("div", { className: "space-y-1.5", children: Object.entries(animation.properties).map(([prop, val]) => /* @__PURE__ */ jsx129(
54342
54564
  PropertyRow,
54343
54565
  {
@@ -54391,7 +54613,7 @@ var AnimationCard = memo34(function AnimationCard2({
54391
54613
  {
54392
54614
  type: "button",
54393
54615
  onClick: () => onDeleteAnimation(animation.id),
54394
- className: "ml-auto text-[11px] font-medium text-red-400 transition-colors hover:text-red-300",
54616
+ className: "ml-auto text-[11px] font-medium rounded-sm text-danger-ink transition-colors hover:bg-danger/15",
54395
54617
  title: "Remove this animation",
54396
54618
  children: "Remove"
54397
54619
  }
@@ -54407,7 +54629,7 @@ var AnimationCard = memo34(function AnimationCard2({
54407
54629
  import { jsx as jsx130, jsxs as jsxs96 } from "react/jsx-runtime";
54408
54630
  var STYLES = {
54409
54631
  classic: {
54410
- method: "rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 py-1.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-white",
54632
+ method: "rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 py-1.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-text-0",
54411
54633
  cancel: "px-1.5 text-[11px] text-neutral-500 hover:text-neutral-300",
54412
54634
  trigger: "text-[11px] font-medium text-neutral-400 transition-colors hover:text-neutral-200"
54413
54635
  },
@@ -54606,8 +54828,8 @@ var GsapAnimationSection = memo35(function GsapAnimationSection2({
54606
54828
  ...callbacks
54607
54829
  }) {
54608
54830
  return /* @__PURE__ */ jsxs98(Section, { title: "Animation", icon: /* @__PURE__ */ jsx132(Film, { size: 15 }), children: [
54609
- multipleTimelines && /* @__PURE__ */ jsx132("p", { className: "mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400", children: "This file has multiple GSAP timelines. Animation editing is disabled to prevent data loss \u2014 consolidate into a single timeline to enable editing." }),
54610
- unsupportedTimelinePattern && /* @__PURE__ */ jsx132("p", { className: "mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400", children: `This timeline uses a computed key (window.__timelines[variable]) the editor can't resolve statically. Use a string-literal key (window.__timelines["id"]) or a variable declaration (const tl = gsap.timeline()) to enable editing.` }),
54831
+ multipleTimelines && /* @__PURE__ */ jsx132("p", { className: "mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-warning-ink", children: "This file has multiple GSAP timelines. Animation editing is disabled to prevent data loss \u2014 consolidate into a single timeline to enable editing." }),
54832
+ unsupportedTimelinePattern && /* @__PURE__ */ jsx132("p", { className: "mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-warning-ink", children: `This timeline uses a computed key (window.__timelines[variable]) the editor can't resolve statically. Use a string-literal key (window.__timelines["id"]) or a variable declaration (const tl = gsap.timeline()) to enable editing.` }),
54611
54833
  multipleTimelines || unsupportedTimelinePattern ? null : /* @__PURE__ */ jsx132(
54612
54834
  GsapAnimationList,
54613
54835
  {
@@ -54949,7 +55171,7 @@ function Transform3DCube({
54949
55171
  title: keyframed ? "3D transform is keyframed \u2014 click a field diamond to add keyframes" : "Keyframe the 3D transform (animate it over time)",
54950
55172
  "aria-label": "Keyframe 3D transform",
54951
55173
  "aria-pressed": keyframed,
54952
- className: `absolute left-1.5 top-1.5 rounded p-0.5 hover:bg-neutral-800 ${keyframed ? "text-[#5ff0bf]" : "text-neutral-500 hover:text-neutral-200"}`,
55174
+ className: `absolute left-1.5 top-1.5 rounded p-0.5 hover:bg-neutral-800 ${keyframed ? "text-accent-ink" : "text-neutral-500 hover:text-neutral-200"}`,
54953
55175
  children: /* @__PURE__ */ jsx133(
54954
55176
  "svg",
54955
55177
  {
@@ -55309,7 +55531,7 @@ import { Eye as Eye4, EyeSlash as EyeSlash3 } from "@phosphor-icons/react";
55309
55531
  import { jsx as jsx135, jsxs as jsxs101 } from "react/jsx-runtime";
55310
55532
  var ICON_BY_KIND = { text: Type, media: Film, other: Square };
55311
55533
  var ICON_COLOR_BY_KIND = {
55312
- text: "text-panel-accent",
55534
+ text: "text-accent-ink",
55313
55535
  media: "text-panel-media",
55314
55536
  other: "text-panel-container"
55315
55537
  };
@@ -55392,7 +55614,7 @@ function PropertyPanelFlatHeader({
55392
55614
  track2("button", "Copy element info");
55393
55615
  onCopy();
55394
55616
  },
55395
- className: copied ? "text-panel-accent" : void 0,
55617
+ className: copied ? "text-accent-ink" : void 0,
55396
55618
  children: /* @__PURE__ */ jsx135(ClipboardList, { size: 13 })
55397
55619
  }
55398
55620
  ),
@@ -55450,7 +55672,7 @@ function PropertyPanelFlatFooter({
55450
55672
  height: "13",
55451
55673
  viewBox: "0 0 16 16",
55452
55674
  fill: "currentColor",
55453
- className: "text-panel-accent",
55675
+ className: "text-accent-ink",
55454
55676
  children: /* @__PURE__ */ jsx136("path", { d: "M8 1l1.4 4.6L14 7l-4.6 1.4L8 13l-1.4-4.6L2 7l4.6-1.4z" })
55455
55677
  }
55456
55678
  ),
@@ -55470,7 +55692,7 @@ function PropertyPanelFlatFooter({
55470
55692
  track2("button", "Gesture recording");
55471
55693
  onToggleRecording();
55472
55694
  },
55473
- className: recording ? "text-panel-danger animate-pulse" : "text-panel-danger",
55695
+ className: recording ? "text-danger-ink animate-pulse" : "text-danger-ink",
55474
55696
  children: /* @__PURE__ */ jsx136("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "currentColor", children: recording ? /* @__PURE__ */ jsx136("rect", { x: "2", y: "2", width: "10", height: "10", rx: "1.5" }) : /* @__PURE__ */ jsx136("circle", { cx: "7", cy: "7", r: "6" }) })
55475
55697
  }
55476
55698
  )
@@ -55543,7 +55765,7 @@ function FlatSliderReadout({
55543
55765
  e.stopPropagation();
55544
55766
  },
55545
55767
  onBlur: () => commit(false),
55546
- className: `w-11 shrink-0 rounded-[3px] border bg-panel-surface px-1 text-right font-mono text-[10px] text-panel-text-0 outline-none ${invalid ? "border-red-400" : "border-panel-accent"}`
55768
+ className: `w-11 shrink-0 rounded-[3px] border bg-panel-surface px-1 text-right font-mono text-[10px] text-panel-text-0 outline-none ${invalid ? "border-dashed border-danger-ink" : "border-panel-accent"}`
55547
55769
  }
55548
55770
  );
55549
55771
  }
@@ -55581,7 +55803,7 @@ var VALUE_TIER_LABEL_CLASS = {
55581
55803
  var VALUE_TIER_VALUE_CLASS = {
55582
55804
  default: "text-panel-text-3",
55583
55805
  explicitDefault: "text-panel-text-0",
55584
- explicitCustom: "text-panel-accent"
55806
+ explicitCustom: "text-accent-ink"
55585
55807
  };
55586
55808
 
55587
55809
  // src/components/editor/propertyPanelFlatSelectRow.tsx
@@ -56008,7 +56230,7 @@ function FlatSlider({
56008
56230
  "div",
56009
56231
  {
56010
56232
  "data-flat-slider-knob": "true",
56011
- className: `absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full ${tier === "explicitCustom" ? "h-2 w-2 bg-white" : "h-[7px] w-[7px] bg-panel-text-4"}`,
56233
+ className: `absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full ${tier === "explicitCustom" ? "h-2 w-2 bg-text-0" : "h-[7px] w-[7px] bg-panel-text-4"}`,
56012
56234
  style: { left: `${clampedPct}%` }
56013
56235
  }
56014
56236
  )
@@ -57410,8 +57632,8 @@ function FlatMotionSection({
57410
57632
  }
57411
57633
  ),
57412
57634
  showEffects && /* @__PURE__ */ jsxs110(Fragment41, { children: [
57413
- multipleTimelines && /* @__PURE__ */ jsx146("p", { className: "rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400", children: "This file has multiple GSAP timelines. Animation editing is disabled to prevent data loss \u2014 consolidate into a single timeline to enable editing." }),
57414
- unsupportedTimelinePattern && /* @__PURE__ */ jsx146("p", { className: "rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400", children: "This timeline uses a computed key the editor can't resolve statically." }),
57635
+ multipleTimelines && /* @__PURE__ */ jsx146("p", { className: "rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-warning-ink", children: "This file has multiple GSAP timelines. Animation editing is disabled to prevent data loss \u2014 consolidate into a single timeline to enable editing." }),
57636
+ unsupportedTimelinePattern && /* @__PURE__ */ jsx146("p", { className: "rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-warning-ink", children: "This timeline uses a computed key the editor can't resolve statically." }),
57415
57637
  !multipleTimelines && !unsupportedTimelinePattern && /* @__PURE__ */ jsx146(
57416
57638
  GsapAnimationList,
57417
57639
  {
@@ -57567,7 +57789,7 @@ function AutomationToggle({
57567
57789
  "button",
57568
57790
  {
57569
57791
  type: "button",
57570
- className: `hf-fx-automate w-[16px] shrink-0 rounded-[3px] border font-mono text-[9px] leading-none ${automated ? "border-panel-accent text-panel-accent" : "border-panel-border-input text-panel-text-2 hover:text-panel-text-0"}`,
57792
+ className: `hf-fx-automate w-[16px] shrink-0 rounded-[3px] border font-mono text-[9px] leading-none ${automated ? "border-panel-accent text-accent-ink" : "border-panel-border-input text-panel-text-2 hover:text-panel-text-0"}`,
57571
57793
  "aria-pressed": automated,
57572
57794
  "aria-label": automated ? `Remove ${label} automation` : `Automate ${label}`,
57573
57795
  onClick: () => automated ? onRemoveAutomation?.(paramKey) : onAutomate?.(paramKey),
@@ -57648,7 +57870,7 @@ function FxParamRow({
57648
57870
  /* @__PURE__ */ jsx147(
57649
57871
  "span",
57650
57872
  {
57651
- className: `hf-fx-label w-[86px] shrink-0 wrap-break-word text-[10px] leading-tight ${automated ? "text-panel-accent" : "text-panel-text-2"}`,
57873
+ className: `hf-fx-label w-[86px] shrink-0 wrap-break-word text-[10px] leading-tight ${automated ? "text-accent-ink" : "text-panel-text-2"}`,
57652
57874
  children: param.label
57653
57875
  }
57654
57876
  ),
@@ -58008,7 +58230,7 @@ function FxCarveMember({
58008
58230
  children: value
58009
58231
  }
58010
58232
  ),
58011
- automated ? /* @__PURE__ */ jsx148("span", { className: "text-[#3CE6AC]", children: "A" }) : null
58233
+ automated ? /* @__PURE__ */ jsx148("span", { className: "text-accent-ink", children: "A" }) : null
58012
58234
  ]
58013
58235
  },
58014
58236
  param.key
@@ -58323,7 +58545,7 @@ function Fader2({
58323
58545
  /* @__PURE__ */ jsx149(
58324
58546
  "span",
58325
58547
  {
58326
- className: `hf-fx-eq-value font-mono text-[9px] tabular-nums ${moved ? "text-panel-accent" : "text-panel-text-2"}`,
58548
+ className: `hf-fx-eq-value font-mono text-[9px] tabular-nums ${moved ? "text-accent-ink" : "text-panel-text-2"}`,
58327
58549
  children: moved ? shown(value) : "0"
58328
58550
  }
58329
58551
  )
@@ -58369,7 +58591,7 @@ function FxEqModule({
58369
58591
  "button",
58370
58592
  {
58371
58593
  type: "button",
58372
- className: "hf-fx-remove px-1 text-[11px] text-panel-text-2 hover:text-panel-danger",
58594
+ className: "hf-fx-remove px-1 text-[11px] text-panel-text-2 hover:text-danger-ink",
58373
58595
  "aria-label": "Remove Tone",
58374
58596
  disabled,
58375
58597
  onClick: onRemove,
@@ -58804,7 +59026,7 @@ function FxNodeHeader({
58804
59026
  "button",
58805
59027
  {
58806
59028
  type: "button",
58807
- className: "hf-fx-remove px-1 font-mono text-[11px] text-panel-text-2 hover:text-red-400 disabled:opacity-40",
59029
+ className: "hf-fx-remove px-1 font-mono text-[11px] text-panel-text-2 hover:text-danger-ink disabled:opacity-40",
58808
59030
  title: "Remove",
58809
59031
  disabled,
58810
59032
  onClick: onRemove,
@@ -59028,7 +59250,7 @@ function FxPresetRun({
59028
59250
  "button",
59029
59251
  {
59030
59252
  type: "button",
59031
- className: "hf-fx-preset-run-remove px-1 font-mono text-[11px] text-panel-text-2 hover:text-red-400 disabled:opacity-40",
59253
+ className: "hf-fx-preset-run-remove px-1 font-mono text-[11px] text-panel-text-2 hover:text-danger-ink disabled:opacity-40",
59032
59254
  title: `Remove ${preset.label}`,
59033
59255
  disabled,
59034
59256
  onClick: onRemoveRun,
@@ -60687,7 +60909,7 @@ function FlatMediaSection({
60687
60909
  "data-flat-media-remove-bg": "true",
60688
60910
  disabled: !canRemoveBackground || removeBusy,
60689
60911
  onClick: () => void runBackgroundRemoval(),
60690
- className: "flex items-center gap-1 text-[10px] font-medium text-panel-accent disabled:cursor-not-allowed disabled:opacity-50",
60912
+ className: "flex items-center gap-1 text-[10px] font-medium text-accent-ink disabled:cursor-not-allowed disabled:opacity-50",
60691
60913
  title: canRemoveBackground ? "Remove background and save a transparent asset" : "Select a project-local image or video asset",
60692
60914
  children: removeBusy ? "Working" : "Remove BG"
60693
60915
  }
@@ -60715,7 +60937,7 @@ function FlatMediaSection({
60715
60937
  /* @__PURE__ */ jsx160("div", { className: "h-1 overflow-hidden rounded-full bg-panel-hover", children: /* @__PURE__ */ jsx160(
60716
60938
  "div",
60717
60939
  {
60718
- className: `h-full rounded-full ${removeProgress.status === "failed" ? "bg-red-400" : "bg-panel-accent"}`,
60940
+ className: `h-full rounded-full ${removeProgress.status === "failed" ? "bg-danger-ink" : "bg-panel-accent"}`,
60719
60941
  style: { width: `${Math.max(0, Math.min(100, removeProgress.progress))}%` }
60720
60942
  }
60721
60943
  ) })
@@ -61339,7 +61561,7 @@ function CurveGraph({
61339
61561
  onSettle();
61340
61562
  }
61341
61563
  },
61342
- className: "mx-auto aspect-square w-full max-w-[200px] touch-none rounded-sm border border-panel-border-input bg-black/20 outline-hidden focus:ring-1 focus:ring-panel-accent",
61564
+ className: "mx-auto aspect-square w-full max-w-[200px] touch-none rounded-sm scheme-dark border border-panel-border-input bg-bg-0 outline-hidden focus:ring-1 focus:ring-inset focus:ring-panel-accent",
61343
61565
  children: [
61344
61566
  /* @__PURE__ */ jsx161("defs", { children: /* @__PURE__ */ jsxs123("linearGradient", { id: `hf-hue-axis-${tab.key}`, children: [
61345
61567
  /* @__PURE__ */ jsx161("stop", { offset: "0%", stopColor: "#f33" }),
@@ -61350,7 +61572,7 @@ function CurveGraph({
61350
61572
  /* @__PURE__ */ jsx161("stop", { offset: "83.3%", stopColor: "#f3f" }),
61351
61573
  /* @__PURE__ */ jsx161("stop", { offset: "100%", stopColor: "#f33" })
61352
61574
  ] }) }),
61353
- [0.25, 0.5, 0.75].map((ratio) => /* @__PURE__ */ jsxs123("g", { stroke: "rgba(255,255,255,0.08)", strokeWidth: "0.5", children: [
61575
+ [0.25, 0.5, 0.75].map((ratio) => /* @__PURE__ */ jsxs123("g", { className: "stroke-text-0/10", strokeWidth: "0.5", children: [
61354
61576
  /* @__PURE__ */ jsx161(
61355
61577
  "line",
61356
61578
  {
@@ -62255,14 +62477,14 @@ function PropertyPanelColorSecondary({
62255
62477
  setSampling(false);
62256
62478
  }
62257
62479
  },
62258
- className: "flex min-h-7 items-center gap-1.5 text-[10px] font-medium text-panel-accent hover:text-panel-accent/80 disabled:opacity-50",
62480
+ className: "flex min-h-7 items-center gap-1.5 text-[10px] font-medium text-accent-ink hover:text-accent-ink/80 disabled:opacity-50",
62259
62481
  children: [
62260
62482
  /* @__PURE__ */ jsx165(Eyedropper, { size: 12 }),
62261
62483
  sampling ? "Capturing frame" : "Sample color from frame"
62262
62484
  ]
62263
62485
  }
62264
62486
  ),
62265
- captureError && /* @__PURE__ */ jsx165("p", { role: "alert", className: "text-[9px] leading-4 text-red-300", children: captureError }),
62487
+ captureError && /* @__PURE__ */ jsx165("p", { role: "alert", className: "text-[9px] leading-4 text-danger-ink", children: captureError }),
62266
62488
  sampleFrame && samplePixels && /* @__PURE__ */ jsxs127("div", { className: "space-y-1", children: [
62267
62489
  /* @__PURE__ */ jsxs127("div", { className: "flex gap-2 text-[9px]", children: [
62268
62490
  /* @__PURE__ */ jsx165(
@@ -62271,7 +62493,7 @@ function PropertyPanelColorSecondary({
62271
62493
  type: "button",
62272
62494
  "aria-pressed": !showMatte,
62273
62495
  onClick: () => setShowMatte(false),
62274
- className: !showMatte ? "text-panel-accent" : "text-panel-text-4",
62496
+ className: !showMatte ? "text-accent-ink" : "text-panel-text-4",
62275
62497
  children: "Source"
62276
62498
  }
62277
62499
  ),
@@ -62281,7 +62503,7 @@ function PropertyPanelColorSecondary({
62281
62503
  type: "button",
62282
62504
  "aria-pressed": showMatte,
62283
62505
  onClick: () => setShowMatte(true),
62284
- className: showMatte ? "text-panel-accent" : "text-panel-text-4",
62506
+ className: showMatte ? "text-accent-ink" : "text-panel-text-4",
62285
62507
  children: "Selection matte"
62286
62508
  }
62287
62509
  )
@@ -62804,9 +63026,9 @@ import { useEffect as useEffect93, useRef as useRef109 } from "react";
62804
63026
  import { isHfColorGradingActive as isHfColorGradingActive3 } from "@hyperframes/core/color-grading";
62805
63027
  import { jsx as jsx167, jsxs as jsxs129 } from "react/jsx-runtime";
62806
63028
  var STATUS_DOT_CLASS = {
62807
- active: "bg-emerald-400",
62808
- pending: "bg-amber-300",
62809
- unavailable: "bg-red-400",
63029
+ active: "bg-accent",
63030
+ pending: "bg-warning-ink",
63031
+ unavailable: "bg-danger-ink",
62810
63032
  missing: "bg-panel-text-5",
62811
63033
  inactive: "bg-panel-text-5"
62812
63034
  };
@@ -62939,24 +63161,17 @@ function HdrBanner({ metadata }) {
62939
63161
  "div",
62940
63162
  {
62941
63163
  "data-flat-grade-hdr-banner": "true",
62942
- className: "rounded-md border border-amber-500/30 bg-amber-500/10 px-2.5 py-1.5 text-[10px] leading-4 text-amber-100",
63164
+ className: "rounded-md border border-amber-500/30 bg-amber-500/10 px-2.5 py-1.5 text-[10px] leading-4 text-warning-ink",
62943
63165
  children: [
62944
63166
  /* @__PURE__ */ jsxs130("div", { className: "mb-0.5 flex items-center justify-between gap-2", children: [
62945
63167
  /* @__PURE__ */ jsxs130("span", { className: "font-semibold", children: [
62946
63168
  metadata.color.label,
62947
63169
  " source"
62948
63170
  ] }),
62949
- /* @__PURE__ */ jsx168("span", { className: "rounded-sm bg-amber-400/20 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-amber-100", children: "SDR preview" })
63171
+ /* @__PURE__ */ jsx168("span", { className: "rounded-sm bg-amber-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-warning-ink", children: "SDR preview" })
62950
63172
  ] }),
62951
- /* @__PURE__ */ jsx168("p", { className: "text-amber-100/80", children: "These controls use the current SDR shader preview path. Render may stay HDR-tagged, but this is not true HDR color grading yet." }),
62952
- details && /* @__PURE__ */ jsx168(
62953
- "p",
62954
- {
62955
- "data-flat-grade-hdr-detail": "true",
62956
- className: "mt-0.5 truncate text-[9px] text-amber-100/55",
62957
- children: details
62958
- }
62959
- )
63173
+ /* @__PURE__ */ jsx168("p", { className: "text-text-2", children: "These controls use the current SDR shader preview path. Render may stay HDR-tagged, but this is not true HDR color grading yet." }),
63174
+ details && /* @__PURE__ */ jsx168("p", { "data-flat-grade-hdr-detail": "true", className: "mt-0.5 truncate text-[9px] text-text-muted", children: details })
62960
63175
  ]
62961
63176
  }
62962
63177
  );
@@ -63056,7 +63271,7 @@ function FlatColorGradingSection({
63056
63271
  {
63057
63272
  type: "button",
63058
63273
  onClick: onRequestPresetPreviews,
63059
- className: "text-[10px] font-medium text-panel-accent hover:text-panel-accent/80",
63274
+ className: "text-[10px] font-medium text-accent-ink hover:text-accent-ink/80",
63060
63275
  children: "Retry look previews"
63061
63276
  }
63062
63277
  ),
@@ -63357,7 +63572,7 @@ function FlatColorGradingSection({
63357
63572
  track2("button", "Apply grade to scope");
63358
63573
  onApplyToScope();
63359
63574
  },
63360
- className: "text-[11px] font-medium text-panel-accent hover:text-panel-accent/80 disabled:cursor-not-allowed disabled:opacity-50",
63575
+ className: "text-[11px] font-medium text-accent-ink hover:text-accent-ink/80 disabled:cursor-not-allowed disabled:opacity-50",
63361
63576
  children: applyBusy ? "Applying" : "Apply"
63362
63577
  }
63363
63578
  )
@@ -63833,7 +64048,7 @@ function FlatEffectsSection({
63833
64048
  track2("button", "Customize effect palette");
63834
64049
  onCommitColorGrading({ ...grading, palette: fallback });
63835
64050
  },
63836
- className: "flex min-h-[28px] items-center gap-1 text-[10px] font-medium text-panel-accent hover:text-panel-accent/80",
64051
+ className: "flex min-h-[28px] items-center gap-1 text-[10px] font-medium text-accent-ink hover:text-accent-ink/80",
63837
64052
  children: [
63838
64053
  /* @__PURE__ */ jsx170(Plus, { size: 11 }),
63839
64054
  " Custom palette"
@@ -63944,7 +64159,7 @@ function FlatEffectsSection({
63944
64159
  type: "button",
63945
64160
  title: `Remove ${selectedEffect.label}`,
63946
64161
  onClick: () => removeEffect(selectedEffect),
63947
- className: "text-panel-text-4 hover:text-red-300",
64162
+ className: "text-panel-text-4 hover:text-danger-ink",
63948
64163
  children: /* @__PURE__ */ jsx170(X, { size: 11 })
63949
64164
  }
63950
64165
  )
@@ -63987,7 +64202,7 @@ function FlatEffectsSection({
63987
64202
  "data-flat-effects-add-toggle": "true",
63988
64203
  "aria-expanded": catalogOpen,
63989
64204
  onClick: () => setCatalogOpen((open) => !open),
63990
- className: "flex min-h-[30px] items-center gap-1 text-[10px] font-medium text-panel-accent hover:text-panel-accent/80",
64205
+ className: "flex min-h-[30px] items-center gap-1 text-[10px] font-medium text-accent-ink hover:text-accent-ink/80",
63991
64206
  children: [
63992
64207
  /* @__PURE__ */ jsx170(Plus, { size: 11 }),
63993
64208
  " Add effect"
@@ -64009,7 +64224,7 @@ function FlatEffectsSection({
64009
64224
  "aria-selected": catalogGroup === group.label,
64010
64225
  "data-flat-effect-group": group.label,
64011
64226
  onClick: () => setCatalogGroup(group.label),
64012
- className: `min-h-[25px] min-w-0 truncate bg-panel-bg px-2 text-[9px] ${catalogGroup === group.label ? "font-medium text-panel-accent" : "text-panel-text-4 hover:text-panel-text-1"}`,
64227
+ className: `min-h-[25px] min-w-0 truncate bg-panel-bg px-2 text-[9px] ${catalogGroup === group.label ? "font-medium text-accent-ink" : "text-panel-text-4 hover:text-panel-text-1"}`,
64013
64228
  children: group.label
64014
64229
  },
64015
64230
  group.label
@@ -64144,15 +64359,47 @@ import {
64144
64359
  resolveBlockCategory
64145
64360
  } from "@hyperframes/core/registry";
64146
64361
  var COLOR_MAP = {
64147
- transitions: { bg: "bg-blue-500/15", text: "text-blue-400", dot: "bg-blue-400" },
64148
- vfx: { bg: "bg-purple-500/15", text: "text-purple-400", dot: "bg-purple-400" },
64149
- social: { bg: "bg-pink-500/15", text: "text-pink-400", dot: "bg-pink-400" },
64150
- data: { bg: "bg-green-500/15", text: "text-green-400", dot: "bg-green-400" },
64151
- scenes: { bg: "bg-amber-500/15", text: "text-amber-400", dot: "bg-amber-400" },
64152
- captions: { bg: "bg-cyan-500/15", text: "text-cyan-400", dot: "bg-cyan-400" },
64153
- effects: { bg: "bg-rose-500/15", text: "text-rose-400", dot: "bg-rose-400" },
64154
- "text-effects": { bg: "bg-violet-500/15", text: "text-violet-400", dot: "bg-violet-400" },
64155
- "code-animation": { bg: "bg-emerald-500/15", text: "text-emerald-400", dot: "bg-emerald-400" }
64362
+ transitions: {
64363
+ bg: "bg-blue-500/15",
64364
+ text: "text-[light-dark(oklch(0.48_0.12_255),var(--color-blue-400))]",
64365
+ dot: "bg-[light-dark(oklch(0.48_0.12_255),var(--color-blue-400))]"
64366
+ },
64367
+ vfx: {
64368
+ bg: "bg-purple-500/15",
64369
+ text: "text-[light-dark(oklch(0.48_0.12_305),var(--color-purple-400))]",
64370
+ dot: "bg-[light-dark(oklch(0.48_0.12_305),var(--color-purple-400))]"
64371
+ },
64372
+ social: {
64373
+ bg: "bg-pink-500/15",
64374
+ text: "text-[light-dark(oklch(0.48_0.12_350),var(--color-pink-400))]",
64375
+ dot: "bg-[light-dark(oklch(0.48_0.12_350),var(--color-pink-400))]"
64376
+ },
64377
+ data: {
64378
+ bg: "bg-green-500/15",
64379
+ text: "text-[light-dark(oklch(0.48_0.12_152),var(--color-green-400))]",
64380
+ dot: "bg-[light-dark(oklch(0.48_0.12_152),var(--color-green-400))]"
64381
+ },
64382
+ scenes: { bg: "bg-amber-500/15", text: "text-warning-ink", dot: "bg-warning-ink" },
64383
+ captions: {
64384
+ bg: "bg-cyan-500/15",
64385
+ text: "text-[light-dark(oklch(0.48_0.12_212),var(--color-cyan-400))]",
64386
+ dot: "bg-[light-dark(oklch(0.48_0.12_212),var(--color-cyan-400))]"
64387
+ },
64388
+ effects: {
64389
+ bg: "bg-rose-500/15",
64390
+ text: "text-[light-dark(oklch(0.48_0.12_13),var(--color-rose-400))]",
64391
+ dot: "bg-[light-dark(oklch(0.48_0.12_13),var(--color-rose-400))]"
64392
+ },
64393
+ "text-effects": {
64394
+ bg: "bg-violet-500/15",
64395
+ text: "text-[light-dark(oklch(0.48_0.12_294),var(--color-violet-400))]",
64396
+ dot: "bg-[light-dark(oklch(0.48_0.12_294),var(--color-violet-400))]"
64397
+ },
64398
+ "code-animation": {
64399
+ bg: "bg-emerald-500/15",
64400
+ text: "text-[light-dark(oklch(0.48_0.12_163),var(--color-emerald-400))]",
64401
+ dot: "bg-[light-dark(oklch(0.48_0.12_163),var(--color-emerald-400))]"
64402
+ }
64156
64403
  };
64157
64404
  function getCategoryColors(category) {
64158
64405
  return COLOR_MAP[category];
@@ -64257,7 +64504,7 @@ function FlatOverlaysSection({
64257
64504
  return /* @__PURE__ */ jsx171("div", { className: "py-4 text-center text-[10px] text-panel-text-4", children: "Loading overlays\u2026" });
64258
64505
  }
64259
64506
  if (error) {
64260
- return /* @__PURE__ */ jsx171("div", { className: "py-4 text-center text-[10px] text-red-300", children: error });
64507
+ return /* @__PURE__ */ jsx171("div", { className: "py-4 text-center text-[10px] text-danger-ink", children: error });
64261
64508
  }
64262
64509
  const busy = adding !== null;
64263
64510
  return /* @__PURE__ */ jsx171("div", { "data-flat-overlays": "true", className: FLAT_PREVIEW_GRID, children: overlays.map((overlay) => /* @__PURE__ */ jsxs132(
@@ -64306,7 +64553,7 @@ function FlatOverlaysSection({
64306
64553
  Plus,
64307
64554
  {
64308
64555
  size: 12,
64309
- className: "absolute right-1.5 top-1.5 text-white opacity-70 drop-shadow-sm group-hover:text-panel-accent group-hover:opacity-100"
64556
+ className: "absolute right-1.5 top-1.5 text-white opacity-70 drop-shadow-sm group-hover:text-accent-ink group-hover:opacity-100"
64310
64557
  }
64311
64558
  )
64312
64559
  ] }),
@@ -64823,7 +65070,7 @@ function GestureRecordPanelButton({
64823
65070
  track2("button", "Gesture recording");
64824
65071
  onToggleRecording();
64825
65072
  },
64826
- className: `w-full flex items-center justify-center gap-2 rounded-lg py-2 text-[11px] font-medium transition-colors ${recording ? "bg-red-500/15 text-red-400 border border-red-500/30 animate-pulse" : "bg-panel-input text-panel-text-2 hover:bg-panel-hover border border-panel-border"}`,
65073
+ className: `w-full flex items-center justify-center gap-2 rounded-lg py-2 text-[11px] font-medium transition-colors ${recording ? "bg-red-500/15 text-danger-ink border border-red-500/30 animate-pulse" : "bg-panel-input text-panel-text-2 hover:bg-panel-hover border border-panel-border"}`,
64827
65074
  children: [
64828
65075
  /* @__PURE__ */ jsx173(GestureRecordIcon, { recording }),
64829
65076
  recording ? `Stop recording ${(recordingDuration ?? 0).toFixed(1)}s -- press R` : "Record gesture (R) -- move pointer to capture motion"
@@ -64853,14 +65100,14 @@ function FlatEmptyState() {
64853
65100
  /* @__PURE__ */ jsxs135("div", { className: "mt-2 flex w-full flex-col gap-1.5", children: [
64854
65101
  /* @__PURE__ */ jsxs135("span", { className: "flex items-center justify-between rounded-lg border border-panel-border bg-panel-bg px-3 py-2", children: [
64855
65102
  /* @__PURE__ */ jsxs135("span", { className: "flex items-center gap-2 text-[11px] text-panel-text-2", children: [
64856
- /* @__PURE__ */ jsx174("span", { className: "text-panel-danger", children: "\u25CF" }),
65103
+ /* @__PURE__ */ jsx174("span", { className: "text-danger-ink", children: "\u25CF" }),
64857
65104
  "Record a gesture"
64858
65105
  ] }),
64859
65106
  /* @__PURE__ */ jsx174("span", { className: "rounded-sm border border-panel-border-input px-[5px] py-px font-mono text-[9px] text-panel-text-5", children: "R" })
64860
65107
  ] }),
64861
65108
  /* @__PURE__ */ jsxs135("span", { className: "flex items-center justify-between rounded-lg border border-panel-border bg-panel-bg px-3 py-2", children: [
64862
65109
  /* @__PURE__ */ jsxs135("span", { className: "flex items-center gap-2 text-[11px] text-panel-text-2", children: [
64863
- /* @__PURE__ */ jsx174("span", { className: "text-panel-accent", children: "\u2726" }),
65110
+ /* @__PURE__ */ jsx174("span", { className: "text-accent-ink", children: "\u2726" }),
64864
65111
  "Describe a change to the agent"
64865
65112
  ] }),
64866
65113
  /* @__PURE__ */ jsx174("span", { className: "rounded-sm border border-panel-border-input px-[5px] py-px font-mono text-[9px] text-panel-text-5", children: "\u2318K" })
@@ -64873,7 +65120,7 @@ function elementKindGlyph(element) {
64873
65120
  return { glyph: "\u25C6", className: "bg-panel-media/10 text-panel-media" };
64874
65121
  }
64875
65122
  if (element.textFields?.length > 0) {
64876
- return { glyph: "T", className: "bg-panel-accent/10 text-panel-accent" };
65123
+ return { glyph: "T", className: "bg-panel-accent/10 text-accent-ink" };
64877
65124
  }
64878
65125
  return { glyph: "\u25A6", className: "bg-panel-container/10 text-panel-container" };
64879
65126
  }
@@ -64887,7 +65134,7 @@ function FlatMultiSelectState({
64887
65134
  const hasAudio = !canHideSelections(multiSelectedElements);
64888
65135
  return /* @__PURE__ */ jsxs135("div", { className: "flex flex-col gap-3 px-4 py-3", children: [
64889
65136
  /* @__PURE__ */ jsxs135("div", { className: "flex items-center gap-3 rounded-xl border border-panel-border bg-panel-surface p-3", children: [
64890
- /* @__PURE__ */ jsx174("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-panel-accent/10 text-panel-accent", children: /* @__PURE__ */ jsx174(Layers, { size: 16 }) }),
65137
+ /* @__PURE__ */ jsx174("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-panel-accent/10 text-accent-ink", children: /* @__PURE__ */ jsx174(Layers, { size: 16 }) }),
64891
65138
  /* @__PURE__ */ jsxs135("div", { className: "min-w-0 flex-1", children: [
64892
65139
  /* @__PURE__ */ jsxs135("div", { className: "text-[13px] font-semibold text-panel-text-0", children: [
64893
65140
  multiSelectCount,
@@ -65119,7 +65366,7 @@ var PropertyPanel = memo36(function PropertyPanel2(props) {
65119
65366
  const manualSize = readStudioBoxSize(element.element);
65120
65367
  const resolvedWidth = manualSize.width > 0 ? manualSize.width : parsePxMetricValue(styles.width ?? "") ?? element.boundingBox.width;
65121
65368
  const resolvedHeight = manualSize.height > 0 ? manualSize.height : parsePxMetricValue(styles.height ?? "") ?? element.boundingBox.height;
65122
- const manualRotation = readStudioRotation(element.element);
65369
+ const manualRotation = readShownRotation(element.element);
65123
65370
  const elStart = Number.parseFloat(element?.dataAttributes?.start ?? "0") || 0;
65124
65371
  const elDuration = Number.parseFloat(element?.dataAttributes?.duration ?? "1") || 0;
65125
65372
  const currentPct = elDuration > 0 ? (currentTime - elStart) / elDuration * 100 : 0;
@@ -65510,34 +65757,52 @@ import {
65510
65757
  import { jsx as jsx176 } from "react/jsx-runtime";
65511
65758
  var SZ = 14;
65512
65759
  var W = "duotone";
65760
+ var RED = "text-[light-dark(oklch(0.59_0.194_35),oklch(0.71_0.194_35))]";
65761
+ var BLUE = "text-[light-dark(oklch(0.56_0.14_253),oklch(0.69_0.14_253))]";
65762
+ var GREEN = "text-[light-dark(oklch(0.53_0.192_150),#22C55E)]";
65763
+ var GRAY = "text-[light-dark(oklch(0.56_0.019_261),#9CA3AF)]";
65764
+ var DIM = "text-[light-dark(oklch(0.55_0.023_264),oklch(0.69_0.023_264))]";
65765
+ var ICONS = /* @__PURE__ */ new Map([
65766
+ ["html", [FileHtml, RED]],
65767
+ ["css", [FileCss, "text-[light-dark(oklch(0.5_0.2_266),oklch(0.71_0.2_266))]"]],
65768
+ ["js", [FileJs, "text-[light-dark(oklch(0.56_0.156_101),#F0DB4F)]"]],
65769
+ ["jsx", [FileJsx, "text-[light-dark(oklch(0.55_0.117_219),#61DAFB)]"]],
65770
+ ["ts", [FileTs, BLUE]],
65771
+ ["tsx", [FileTsx, BLUE]],
65772
+ ["json", [FileCode, "text-[light-dark(oklch(0.54_0.182_152),#4ADE80)]"]],
65773
+ ["svg", [FileSvg, "text-[light-dark(oklch(0.58_0.187_48),#F97316)]"]],
65774
+ ["md", [FileMd, GRAY]],
65775
+ ["txt", [FileTxt, GRAY]],
65776
+ ["png", [FilePng, GREEN]],
65777
+ ["jpg", [FileJpg, GREEN]],
65778
+ ["webp", [PhImage, GREEN]],
65779
+ ["mp4", [FileVideo, "text-[light-dark(oklch(0.59_0.2_304),oklch(0.71_0.2_304))]"]],
65780
+ ["mp3", [Waveform, "text-[light-dark(oklch(0.53_0.159_165),#3CE6AC)]"]],
65781
+ ["woff", [TextAa, DIM]]
65782
+ ]);
65783
+ var ALIAS = new Map(
65784
+ Object.entries({
65785
+ mjs: "js",
65786
+ cjs: "js",
65787
+ mts: "ts",
65788
+ mdx: "md",
65789
+ jpeg: "jpg",
65790
+ gif: "webp",
65791
+ ico: "webp",
65792
+ webm: "mp4",
65793
+ mov: "mp4",
65794
+ wav: "mp3",
65795
+ ogg: "mp3",
65796
+ m4a: "mp3",
65797
+ woff2: "woff",
65798
+ ttf: "woff",
65799
+ otf: "woff"
65800
+ })
65801
+ );
65513
65802
  function FileIcon({ path }) {
65514
65803
  const ext2 = path.split(".").pop()?.toLowerCase() ?? "";
65515
- const c = "shrink-0";
65516
- if (ext2 === "html") return /* @__PURE__ */ jsx176(FileHtml, { size: SZ, weight: W, color: "#E44D26", className: c });
65517
- if (ext2 === "css") return /* @__PURE__ */ jsx176(FileCss, { size: SZ, weight: W, color: "#264DE4", className: c });
65518
- if (ext2 === "js" || ext2 === "mjs" || ext2 === "cjs")
65519
- return /* @__PURE__ */ jsx176(FileJs, { size: SZ, weight: W, color: "#F0DB4F", className: c });
65520
- if (ext2 === "jsx") return /* @__PURE__ */ jsx176(FileJsx, { size: SZ, weight: W, color: "#61DAFB", className: c });
65521
- if (ext2 === "ts" || ext2 === "mts")
65522
- return /* @__PURE__ */ jsx176(FileTs, { size: SZ, weight: W, color: "#3178C6", className: c });
65523
- if (ext2 === "tsx") return /* @__PURE__ */ jsx176(FileTsx, { size: SZ, weight: W, color: "#3178C6", className: c });
65524
- if (ext2 === "json") return /* @__PURE__ */ jsx176(FileCode, { size: SZ, weight: W, color: "#4ADE80", className: c });
65525
- if (ext2 === "svg") return /* @__PURE__ */ jsx176(FileSvg, { size: SZ, weight: W, color: "#F97316", className: c });
65526
- if (ext2 === "md" || ext2 === "mdx")
65527
- return /* @__PURE__ */ jsx176(FileMd, { size: SZ, weight: W, color: "#9CA3AF", className: c });
65528
- if (ext2 === "txt") return /* @__PURE__ */ jsx176(FileTxt, { size: SZ, weight: W, color: "#9CA3AF", className: c });
65529
- if (ext2 === "png") return /* @__PURE__ */ jsx176(FilePng, { size: SZ, weight: W, color: "#22C55E", className: c });
65530
- if (ext2 === "jpg" || ext2 === "jpeg")
65531
- return /* @__PURE__ */ jsx176(FileJpg, { size: SZ, weight: W, color: "#22C55E", className: c });
65532
- if (ext2 === "webp" || ext2 === "gif" || ext2 === "ico")
65533
- return /* @__PURE__ */ jsx176(PhImage, { size: SZ, weight: W, color: "#22C55E", className: c });
65534
- if (ext2 === "mp4" || ext2 === "webm" || ext2 === "mov")
65535
- return /* @__PURE__ */ jsx176(FileVideo, { size: SZ, weight: W, color: "#A855F7", className: c });
65536
- if (ext2 === "mp3" || ext2 === "wav" || ext2 === "ogg" || ext2 === "m4a")
65537
- return /* @__PURE__ */ jsx176(Waveform, { size: SZ, weight: W, color: "#3CE6AC", className: c });
65538
- if (ext2 === "woff" || ext2 === "woff2" || ext2 === "ttf" || ext2 === "otf")
65539
- return /* @__PURE__ */ jsx176(TextAa, { size: SZ, weight: W, color: "#6B7280", className: c });
65540
- return /* @__PURE__ */ jsx176(File2, { size: SZ, weight: W, color: "#6B7280", className: c });
65804
+ const [Glyph, color] = ICONS.get(ALIAS.get(ext2) ?? ext2) ?? [File2, DIM];
65805
+ return /* @__PURE__ */ jsx176(Glyph, { size: SZ, weight: W, className: `shrink-0 ${color}` });
65541
65806
  }
65542
65807
  function buildTree(files) {
65543
65808
  const root = { name: "", fullPath: "", children: /* @__PURE__ */ new Map(), isFile: false };
@@ -65729,7 +65994,7 @@ function ContextMenu2({
65729
65994
  "button",
65730
65995
  {
65731
65996
  role: "menuitem",
65732
- className: "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-red-400 hover:bg-red-900/30 focus-visible:bg-red-900/30 active:bg-red-900/50 outline-hidden cursor-pointer text-left",
65997
+ className: "w-full flex items-center gap-2 px-3 py-1.5 text-xs text-danger-ink hover:bg-danger/25 focus-visible:bg-danger/25 active:bg-danger/25 outline-hidden cursor-pointer text-left",
65733
65998
  onClick: () => {
65734
65999
  onDelete(state.targetPath);
65735
66000
  onClose();
@@ -65806,7 +66071,7 @@ function InlineInput({
65806
66071
  className: "flex items-center gap-2 py-0.5 min-h-7",
65807
66072
  style: { paddingLeft: `${8 + depth * 12 + (isFolder ? 0 : 14)}px` },
65808
66073
  children: [
65809
- isFolder ? /* @__PURE__ */ jsx177(FolderSimple, { size: SZ_ICON, weight: "duotone", color: "#6B7280", className: "shrink-0" }) : /* @__PURE__ */ jsx177(FileIcon, { path: value }),
66074
+ isFolder ? /* @__PURE__ */ jsx177(FolderSimple, { size: SZ_ICON, weight: "duotone", className: `shrink-0 ${DIM}` }) : /* @__PURE__ */ jsx177(FileIcon, { path: value }),
65810
66075
  /* @__PURE__ */ jsxs137("div", { className: "flex-1 min-w-0", children: [
65811
66076
  /* @__PURE__ */ jsx177(
65812
66077
  "input",
@@ -65820,11 +66085,11 @@ function InlineInput({
65820
66085
  onKeyDown: handleKeyDown,
65821
66086
  onBlur: handleBlur,
65822
66087
  "aria-invalid": error ? true : void 0,
65823
- className: `w-full min-w-0 bg-neutral-800 text-neutral-200 text-xs px-1.5 py-0.5 rounded border outline-hidden ${error ? "border-red-500/70" : "border-neutral-600 focus:border-[#3CE6AC]"}`,
66088
+ className: `w-full min-w-0 bg-neutral-800 text-neutral-200 text-xs px-1.5 py-0.5 rounded border outline-hidden ${error ? "border-danger-ink" : "border-neutral-600 focus:border-accent-ink"}`,
65824
66089
  spellCheck: false
65825
66090
  }
65826
66091
  ),
65827
- error && /* @__PURE__ */ jsx177("div", { className: "mt-0.5 text-[10px] text-red-400", role: "alert", children: error })
66092
+ error && /* @__PURE__ */ jsx177("div", { className: "mt-0.5 text-[10px] text-danger-ink", role: "alert", children: error })
65828
66093
  ] })
65829
66094
  ]
65830
66095
  }
@@ -65871,7 +66136,7 @@ function DeleteConfirm({
65871
66136
  "button",
65872
66137
  {
65873
66138
  onClick: onCancel,
65874
- className: "flex-1 px-2 py-1 rounded-sm bg-neutral-700 text-neutral-300 hover:bg-neutral-600 transition-colors",
66139
+ className: "flex-1 px-2 py-1 rounded-sm bg-hover text-neutral-300 hover:bg-press transition-colors",
65875
66140
  children: "Cancel"
65876
66141
  }
65877
66142
  ),
@@ -65879,7 +66144,7 @@ function DeleteConfirm({
65879
66144
  "button",
65880
66145
  {
65881
66146
  onClick: onConfirm,
65882
- className: "flex-1 px-2 py-1 rounded-sm bg-red-900/60 text-red-300 hover:bg-red-800/60 transition-colors",
66147
+ className: "flex-1 px-2 py-1 rounded-sm bg-danger/15 text-danger-ink hover:bg-danger/25 transition-colors",
65883
66148
  children: "Delete"
65884
66149
  }
65885
66150
  )
@@ -65934,7 +66199,7 @@ var TreeFile = memo37(function TreeFile2({
65934
66199
  lintInfo && lintInfo.count > 0 && /* @__PURE__ */ jsx177(
65935
66200
  "span",
65936
66201
  {
65937
- className: "shrink-0 min-w-[16px] rounded-full bg-amber-500/20 px-1 text-[8px] font-bold text-amber-400 text-center mr-1",
66202
+ className: "shrink-0 min-w-[16px] rounded-full bg-amber-500/20 px-1 text-[8px] font-bold text-warning-ink text-center mr-1",
65938
66203
  title: lintInfo.messages.join("\n"),
65939
66204
  children: lintInfo.count
65940
66205
  }
@@ -66002,7 +66267,7 @@ var TreeFolder = memo37(function TreeFolder2({
66002
66267
  onDrop(e, node.fullPath);
66003
66268
  },
66004
66269
  onDragLeave,
66005
- className: `w-full flex items-center gap-1.5 px-2.5 py-1 min-h-7 text-left text-xs text-neutral-400 hover:bg-neutral-800/30 hover:text-neutral-300 transition-colors ${isDragOver ? "bg-[#3CE6AC]/10 outline-solid outline-1 outline-[#3CE6AC]/40" : ""}`,
66270
+ className: `w-full flex items-center gap-1.5 px-2.5 py-1 min-h-7 text-left text-xs text-neutral-400 hover:bg-neutral-800/30 hover:text-neutral-300 transition-colors ${isDragOver ? "bg-accent/10 outline-solid outline-1 outline-accent-ink -outline-offset-1" : ""}`,
66006
66271
  style: { paddingLeft: `${8 + depth * 12}px` },
66007
66272
  children: [
66008
66273
  /* @__PURE__ */ jsx177(Chevron, { size: 10, className: "shrink-0 text-neutral-600" }),
@@ -66258,7 +66523,7 @@ var FileTree = memo38(function FileTree2({
66258
66523
  /* @__PURE__ */ jsxs138(
66259
66524
  "div",
66260
66525
  {
66261
- className: `flex-1 overflow-y-auto py-1 transition-colors ${dragOverFolder === "" ? "bg-[#3CE6AC]/5 outline-solid outline-1 outline-[#3CE6AC]/30 -outline-offset-1" : ""}`,
66526
+ className: `flex-1 overflow-y-auto py-1 transition-colors ${dragOverFolder === "" ? "bg-accent/5 outline-solid outline-1 outline-accent-ink -outline-offset-1" : ""}`,
66262
66527
  onContextMenu: handleRootContextMenu,
66263
66528
  onDragOver: (e) => {
66264
66529
  e.preventDefault();
@@ -66359,7 +66624,7 @@ var FileTree = memo38(function FileTree2({
66359
66624
  });
66360
66625
 
66361
66626
  // src/App.tsx
66362
- import { useState as useState149, useCallback as useCallback186, useRef as useRef181, useMemo as useMemo82, useLayoutEffect as useLayoutEffect13 } from "react";
66627
+ import { useState as useState149, useCallback as useCallback186, useRef as useRef181, useMemo as useMemo83, useLayoutEffect as useLayoutEffect14 } from "react";
66363
66628
 
66364
66629
  // src/hooks/useRightPanelIntents.ts
66365
66630
  import { useCallback as useCallback92, useEffect as useEffect99, useRef as useRef115 } from "react";
@@ -67093,7 +67358,7 @@ ${pathLine}${lines.join("\n\n")}`;
67093
67358
  children: [
67094
67359
  /* @__PURE__ */ jsxs139("div", { className: "flex items-center justify-between px-5 py-4 border-b border-neutral-800", children: [
67095
67360
  /* @__PURE__ */ jsxs139("div", { className: "flex items-center gap-3", children: [
67096
- hasIssues ? /* @__PURE__ */ jsx179("div", { className: "w-8 h-8 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ jsx179(WarningIcon, { size: 18, className: "text-red-400", weight: "fill" }) }) : /* @__PURE__ */ jsx179("div", { className: "w-8 h-8 rounded-full bg-studio-accent/10 flex items-center justify-center", children: /* @__PURE__ */ jsx179(CheckCircleIcon, { size: 18, className: "text-studio-accent", weight: "fill" }) }),
67361
+ hasIssues ? /* @__PURE__ */ jsx179("div", { className: "w-8 h-8 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ jsx179(WarningIcon, { size: 18, className: "text-danger-ink", weight: "fill" }) }) : /* @__PURE__ */ jsx179("div", { className: "w-8 h-8 rounded-full bg-studio-accent/10 flex items-center justify-center", children: /* @__PURE__ */ jsx179(CheckCircleIcon, { size: 18, className: "text-accent-ink", weight: "fill" }) }),
67097
67362
  /* @__PURE__ */ jsxs139("div", { children: [
67098
67363
  /* @__PURE__ */ jsx179("h2", { className: "text-sm font-semibold text-neutral-200", children: hasIssues ? `${errors.length} error${errors.length !== 1 ? "s" : ""}, ${warnings.length} warning${warnings.length !== 1 ? "s" : ""}` : "All checks passed" }),
67099
67364
  /* @__PURE__ */ jsx179("p", { className: "text-xs text-neutral-500", children: title })
@@ -67113,34 +67378,14 @@ ${pathLine}${lines.join("\n\n")}`;
67113
67378
  "button",
67114
67379
  {
67115
67380
  onClick: handleCopyToAgent,
67116
- className: `px-3 py-1 text-xs font-medium rounded-lg transition-colors active:scale-[0.98] ${copied ? "bg-green-600 text-white" : copyFailed ? "bg-red-600 text-white" : "bg-studio-accent hover:bg-studio-accent/80 text-white"}`,
67381
+ className: `px-3 py-1 text-xs font-medium rounded-lg transition-colors active:scale-[0.98] ${copied ? "bg-accent text-on-accent" : copyFailed ? "bg-danger text-on-danger" : "bg-accent hover:bg-accent-hover text-on-accent"}`,
67117
67382
  children: copied ? "Copied!" : copyFailed ? "Copy failed \u2014 check permissions" : "Copy to Agent"
67118
67383
  }
67119
67384
  ) }),
67120
67385
  /* @__PURE__ */ jsxs139("div", { className: "flex-1 overflow-y-auto px-5 py-3", children: [
67121
67386
  !hasIssues && /* @__PURE__ */ jsx179("div", { className: "py-8 text-center text-neutral-500 text-sm", children: "No errors or warnings found. Your composition looks good!" }),
67122
- errors.map((f, i) => /* @__PURE__ */ jsx179("div", { className: "py-3 border-b border-neutral-800/50 last:border-0", children: /* @__PURE__ */ jsxs139("div", { className: "flex items-start gap-2", children: [
67123
- /* @__PURE__ */ jsx179(WarningIcon, { size: 14, className: "text-red-400 shrink-0 mt-0.5", weight: "fill" }),
67124
- /* @__PURE__ */ jsxs139("div", { className: "min-w-0", children: [
67125
- /* @__PURE__ */ jsx179("p", { className: "text-sm text-neutral-200", children: f.message }),
67126
- f.file && /* @__PURE__ */ jsx179("p", { className: "text-xs text-neutral-600 font-mono mt-0.5", children: f.file }),
67127
- f.fixHint && /* @__PURE__ */ jsxs139("div", { className: "flex items-start gap-1 mt-1.5", children: [
67128
- /* @__PURE__ */ jsx179(CaretRightIcon, { size: 10, className: "text-studio-accent shrink-0 mt-0.5" }),
67129
- /* @__PURE__ */ jsx179("p", { className: "text-xs text-studio-accent", children: f.fixHint })
67130
- ] })
67131
- ] })
67132
- ] }) }, `e-${i}`)),
67133
- warnings.map((f, i) => /* @__PURE__ */ jsx179("div", { className: "py-3 border-b border-neutral-800/50 last:border-0", children: /* @__PURE__ */ jsxs139("div", { className: "flex items-start gap-2", children: [
67134
- /* @__PURE__ */ jsx179(WarningIcon, { size: 14, className: "text-amber-400 shrink-0 mt-0.5" }),
67135
- /* @__PURE__ */ jsxs139("div", { className: "min-w-0", children: [
67136
- /* @__PURE__ */ jsx179("p", { className: "text-sm text-neutral-300", children: f.message }),
67137
- f.file && /* @__PURE__ */ jsx179("p", { className: "text-xs text-neutral-600 font-mono mt-0.5", children: f.file }),
67138
- f.fixHint && /* @__PURE__ */ jsxs139("div", { className: "flex items-start gap-1 mt-1.5", children: [
67139
- /* @__PURE__ */ jsx179(CaretRightIcon, { size: 10, className: "text-studio-accent shrink-0 mt-0.5" }),
67140
- /* @__PURE__ */ jsx179("p", { className: "text-xs text-studio-accent", children: f.fixHint })
67141
- ] })
67142
- ] })
67143
- ] }) }, `w-${i}`))
67387
+ errors.map((f, i) => /* @__PURE__ */ jsx179(LintFindingRow, { finding: f, tone: "error" }, `e-${i}`)),
67388
+ warnings.map((f, i) => /* @__PURE__ */ jsx179(LintFindingRow, { finding: f, tone: "warning" }, `w-${i}`))
67144
67389
  ] })
67145
67390
  ]
67146
67391
  }
@@ -67148,6 +67393,26 @@ ${pathLine}${lines.join("\n\n")}`;
67148
67393
  }
67149
67394
  );
67150
67395
  }
67396
+ function LintFindingRow({ finding, tone }) {
67397
+ return /* @__PURE__ */ jsx179("div", { className: "py-3 border-b border-border last:border-0", children: /* @__PURE__ */ jsxs139("div", { className: "flex items-start gap-2", children: [
67398
+ /* @__PURE__ */ jsx179(
67399
+ WarningIcon,
67400
+ {
67401
+ size: 14,
67402
+ className: `${tone === "error" ? "text-danger-ink" : "text-warning-ink"} shrink-0 mt-0.5`,
67403
+ weight: tone === "error" ? "fill" : void 0
67404
+ }
67405
+ ),
67406
+ /* @__PURE__ */ jsxs139("div", { className: "min-w-0", children: [
67407
+ /* @__PURE__ */ jsx179("p", { className: `text-sm ${tone === "error" ? "text-text-0" : "text-text-2"}`, children: finding.message }),
67408
+ finding.file && /* @__PURE__ */ jsx179("p", { className: "text-xs text-text-muted font-mono mt-0.5", children: finding.file }),
67409
+ finding.fixHint && /* @__PURE__ */ jsxs139("div", { className: "flex items-start gap-1 mt-1.5", children: [
67410
+ /* @__PURE__ */ jsx179(CaretRightIcon, { size: 10, className: "text-accent-ink shrink-0 mt-0.5" }),
67411
+ /* @__PURE__ */ jsx179("p", { className: "text-xs text-accent-ink", children: finding.fixHint })
67412
+ ] })
67413
+ ] })
67414
+ ] }) });
67415
+ }
67151
67416
 
67152
67417
  // src/components/AskAgentModal.tsx
67153
67418
  import { useState as useState100, useRef as useRef120 } from "react";
@@ -67267,7 +67532,7 @@ function AskAgentModal({
67267
67532
  /* @__PURE__ */ jsx180(
67268
67533
  "button",
67269
67534
  {
67270
- className: "px-4 py-1.5 rounded-lg bg-studio-accent/90 text-xs font-medium text-neutral-950 hover:bg-studio-accent disabled:opacity-40 disabled:cursor-not-allowed",
67535
+ className: "px-4 py-1.5 rounded-lg bg-accent text-xs font-medium text-on-accent hover:bg-accent-hover disabled:opacity-40 disabled:cursor-not-allowed",
67271
67536
  disabled: !value.trim(),
67272
67537
  onClick: handleSubmit,
67273
67538
  children: "Copy prompt"
@@ -67293,23 +67558,12 @@ function StudioToast({ message, tone, leaving, onDismiss }) {
67293
67558
  children: /* @__PURE__ */ jsxs141(
67294
67559
  "div",
67295
67560
  {
67296
- className: "relative flex max-w-[min(420px,calc(100vw-48px))] items-center gap-3 overflow-hidden rounded-2xl py-3 pl-4 pr-2 text-[12px]",
67297
- style: {
67298
- background: isError ? "linear-gradient(135deg, rgba(127,29,29,0.55), rgba(80,10,10,0.45))" : "linear-gradient(135deg, rgba(38,38,38,0.55), rgba(23,23,23,0.45))",
67299
- backdropFilter: "blur(16px) saturate(1.6)",
67300
- WebkitBackdropFilter: "blur(16px) saturate(1.6)",
67301
- border: `1px solid ${isError ? "rgba(239,68,68,0.18)" : "rgba(255,255,255,0.08)"}`,
67302
- boxShadow: [
67303
- "0 8px 32px rgba(0,0,0,0.35)",
67304
- `inset 0 1px 0 ${isError ? "rgba(239,68,68,0.12)" : "rgba(255,255,255,0.06)"}`,
67305
- `inset 0 -1px 0 rgba(0,0,0,0.15)`
67306
- ].join(", ")
67307
- },
67561
+ className: `relative flex max-w-[min(420px,calc(100vw-48px))] items-center gap-3 overflow-hidden rounded-2xl py-3 pl-4 pr-2 text-[12px] ${toastSurface(isError)}`,
67308
67562
  children: [
67309
67563
  /* @__PURE__ */ jsx181(
67310
67564
  "span",
67311
67565
  {
67312
- className: `min-w-0 wrap-break-word leading-5 ${isError ? "text-red-200" : "text-neutral-200"}`,
67566
+ className: `min-w-0 wrap-break-word leading-5 ${isError ? "text-danger-ink" : "text-text-0"}`,
67313
67567
  children: message
67314
67568
  }
67315
67569
  ),
@@ -67318,7 +67572,7 @@ function StudioToast({ message, tone, leaving, onDismiss }) {
67318
67572
  {
67319
67573
  type: "button",
67320
67574
  onClick: onDismiss,
67321
- className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-neutral-500 transition-colors hover:bg-white/10 hover:text-neutral-300",
67575
+ className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-neutral-500 transition-colors hover:bg-hover hover:text-neutral-300",
67322
67576
  "aria-label": "Dismiss",
67323
67577
  children: /* @__PURE__ */ jsx181(
67324
67578
  "svg",
@@ -67340,6 +67594,9 @@ function StudioToast({ message, tone, leaving, onDismiss }) {
67340
67594
  }
67341
67595
  );
67342
67596
  }
67597
+ function toastSurface(isError) {
67598
+ return `border shadow-popover backdrop-blur-md ${isError ? "border-danger/40 bg-raised" : "border-border bg-raised/95"}`;
67599
+ }
67343
67600
 
67344
67601
  // src/components/feedback/StudioFeedbackCard.tsx
67345
67602
  import { memo as memo39, useState as useState101, useCallback as useCallback96, useRef as useRef121, useEffect as useEffect103 } from "react";
@@ -67529,24 +67786,13 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67529
67786
  children: /* @__PURE__ */ jsxs142(
67530
67787
  "div",
67531
67788
  {
67532
- className: "flex w-[min(340px,calc(100vw-48px))] flex-col gap-2.5 overflow-hidden rounded-2xl px-3.5 py-3",
67533
- style: {
67534
- background: failed2 ? "linear-gradient(135deg, rgba(127,29,29,0.55), rgba(80,10,10,0.45))" : "linear-gradient(135deg, rgba(38,38,38,0.55), rgba(23,23,23,0.45))",
67535
- backdropFilter: "blur(16px) saturate(1.6)",
67536
- WebkitBackdropFilter: "blur(16px) saturate(1.6)",
67537
- border: `1px solid ${failed2 ? "rgba(239,68,68,0.18)" : "rgba(255,255,255,0.08)"}`,
67538
- boxShadow: [
67539
- "0 8px 32px rgba(0,0,0,0.35)",
67540
- `inset 0 1px 0 ${failed2 ? "rgba(239,68,68,0.12)" : "rgba(255,255,255,0.06)"}`,
67541
- "inset 0 -1px 0 rgba(0,0,0,0.15)"
67542
- ].join(", ")
67543
- },
67789
+ className: `flex w-[min(340px,calc(100vw-48px))] flex-col gap-2.5 overflow-hidden rounded-2xl px-3.5 py-3 ${toastSurface(failed2)}`,
67544
67790
  children: [
67545
67791
  /* @__PURE__ */ jsxs142("div", { className: "flex items-start gap-3", children: [
67546
67792
  /* @__PURE__ */ jsx182(
67547
67793
  "p",
67548
67794
  {
67549
- className: `min-w-0 flex-1 text-[12px] leading-5 ${failed2 ? "text-red-100" : "text-neutral-100"}`,
67795
+ className: `min-w-0 flex-1 text-[12px] leading-5 ${failed2 ? "text-danger-ink" : "text-text-0"}`,
67550
67796
  children: step === "thanks" ? "Thanks, that helps." : title
67551
67797
  }
67552
67798
  ),
@@ -67561,7 +67807,7 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67561
67807
  if (req) trackStudioFeedbackInterviewClick({ reason: req.reason });
67562
67808
  close("sent");
67563
67809
  },
67564
- className: "h-6 shrink-0 whitespace-nowrap rounded-full border border-white/20 bg-white/8 px-2.5 text-[11px] leading-6 text-neutral-100 transition-[background-color,border-color,transform] duration-150 ease-out hover:border-white/35 hover:bg-white/16 active:scale-[0.97] motion-reduce:transition-none",
67810
+ className: "h-6 shrink-0 whitespace-nowrap rounded-full border border-border-strong bg-hover px-2.5 text-[11px] leading-6 text-neutral-100 transition-[background-color,border-color,transform] duration-150 ease-out hover:border-text-muted hover:bg-press active:scale-[0.97] motion-reduce:transition-none",
67565
67811
  children: "Talk to us, 30 min"
67566
67812
  }
67567
67813
  ),
@@ -67570,7 +67816,7 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67570
67816
  {
67571
67817
  type: "button",
67572
67818
  onClick: () => close("close"),
67573
- className: "-mr-1 -mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-neutral-500 transition-colors duration-150 hover:bg-white/10 hover:text-neutral-200",
67819
+ className: "-mr-1 -mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-neutral-500 transition-colors duration-150 hover:bg-press hover:text-neutral-200",
67574
67820
  "aria-label": "Dismiss",
67575
67821
  children: /* @__PURE__ */ jsx182(
67576
67822
  "svg",
@@ -67587,14 +67833,14 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67587
67833
  }
67588
67834
  )
67589
67835
  ] }),
67590
- failed2 && request.detail && step !== "thanks" && /* @__PURE__ */ jsx182("p", { className: "line-clamp-2 text-[11px] leading-4 text-red-200/70", children: request.detail }),
67836
+ failed2 && request.detail && step !== "thanks" && /* @__PURE__ */ jsx182("p", { className: "line-clamp-2 text-[11px] leading-4 text-danger-ink", children: request.detail }),
67591
67837
  step === "rating" && /* @__PURE__ */ jsxs142(Fragment49, { children: [
67592
67838
  /* @__PURE__ */ jsxs142("fieldset", { className: "grid grid-cols-11 gap-[3px]", children: [
67593
67839
  /* @__PURE__ */ jsx182("legend", { className: "sr-only", children: "Rate this export from 0 to 10" }),
67594
67840
  RATINGS.map((n) => /* @__PURE__ */ jsxs142(
67595
67841
  "label",
67596
67842
  {
67597
- className: "flex h-7 cursor-pointer items-center justify-center rounded-md bg-white/4 text-[11px] tabular-nums text-neutral-400 transition-[background-color,color,transform] duration-150 ease-out hover:bg-white/[0.14] hover:text-neutral-100 active:scale-[0.97] has-checked:bg-white/90 has-checked:text-neutral-900 has-focus-visible:ring-1 has-focus-visible:ring-white/50 motion-reduce:transition-none",
67843
+ className: "flex h-7 cursor-pointer items-center justify-center rounded-md bg-hover text-[11px] tabular-nums text-neutral-400 transition-[background-color,color,transform] duration-150 ease-out hover:bg-press hover:text-neutral-100 active:scale-[0.97] has-checked:bg-text-0 has-checked:text-bg-0 has-focus-visible:ring-1 has-focus-visible:ring-ring motion-reduce:transition-none",
67598
67844
  children: [
67599
67845
  /* @__PURE__ */ jsx182(
67600
67846
  "input",
@@ -67629,7 +67875,7 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67629
67875
  onFocus: () => setHint(preset.hint),
67630
67876
  onBlur: () => setHint(null),
67631
67877
  "aria-label": `${preset.label}. ${preset.hint}`,
67632
- className: `h-6 rounded-full border px-2.5 text-[11px] transition-[background-color,border-color,color,transform] duration-150 ease-out active:scale-[0.97] motion-reduce:transition-none ${failed2 ? "border-red-300/20 bg-red-100/6 text-red-100/80 hover:border-red-200/70 hover:bg-red-100/25 hover:text-white" : "border-white/10 bg-white/4 text-neutral-300 hover:border-white/60 hover:bg-white/25 hover:text-white"}`,
67878
+ className: `h-6 rounded-full border px-2.5 text-[11px] transition-[background-color,border-color,color,transform] duration-150 ease-out active:scale-[0.97] motion-reduce:transition-none ${failed2 ? "border-danger/30 bg-danger/10 text-danger-ink hover:border-danger/60 hover:bg-danger/20" : "border-border bg-hover text-neutral-300 hover:border-text-muted hover:bg-press hover:text-text-0"}`,
67633
67879
  children: preset.label
67634
67880
  },
67635
67881
  preset.label
@@ -67649,7 +67895,7 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67649
67895
  placeholder: followUp.placeholder,
67650
67896
  "aria-label": followUp.prompt,
67651
67897
  maxLength: 500,
67652
- className: "h-7 min-w-0 flex-1 rounded-md border border-white/10 bg-black/20 px-2 text-[11px] text-neutral-100 outline-hidden transition-colors duration-150 placeholder:text-neutral-500 focus:border-white/25"
67898
+ className: "h-7 min-w-0 flex-1 rounded-md border border-border bg-input px-2 text-[11px] text-neutral-100 outline-hidden transition-colors duration-150 placeholder:text-neutral-500 focus:border-ring"
67653
67899
  }
67654
67900
  ),
67655
67901
  /* @__PURE__ */ jsx182(
@@ -67657,7 +67903,7 @@ var StudioFeedbackCard = memo39(function StudioFeedbackCard2() {
67657
67903
  {
67658
67904
  type: "button",
67659
67905
  onClick: () => submit(),
67660
- className: "h-7 shrink-0 rounded-md bg-white/10 px-2.5 text-[11px] text-neutral-100 transition-[background-color,transform] duration-150 ease-out hover:bg-white/16 active:scale-[0.97] motion-reduce:transition-none",
67906
+ className: "h-7 shrink-0 rounded-md bg-press px-2.5 text-[11px] text-neutral-100 transition-[background-color,transform] duration-150 ease-out hover:bg-on active:scale-[0.97] motion-reduce:transition-none",
67661
67907
  children: "Send"
67662
67908
  }
67663
67909
  )
@@ -74448,37 +74694,48 @@ function applyElementPositionOffset(el, gestureOffset) {
74448
74694
  }
74449
74695
 
74450
74696
  // src/hooks/elementOffsetStager.ts
74697
+ var GSAP_TOOK_OVER = "The animation took over this layer's position during the move, so it was not saved.";
74451
74698
  var ELEMENT_OFFSET_REFUSED = {
74452
74699
  anchored: "This layer is anchored from its right or bottom edge. Move it in the Code tab.",
74453
74700
  percent: "This layer's position is set in percent. Move it in the Code tab."
74454
74701
  };
74702
+ function gsapOf(el) {
74703
+ return el.ownerDocument.defaultView?.gsap;
74704
+ }
74455
74705
  function settleGsapDraftAtGestureStart(el) {
74456
- const gsap3 = el.ownerDocument.defaultView?.gsap;
74706
+ const gsap3 = gsapOf(el);
74457
74707
  const x = Number.parseFloat(el.getAttribute("data-hf-drag-gsap-base-x") ?? "");
74458
74708
  const y = Number.parseFloat(el.getAttribute("data-hf-drag-gsap-base-y") ?? "");
74459
74709
  if (gsap3 && Number.isFinite(x) && Number.isFinite(y)) gsap3.set(el, { x, y });
74460
74710
  }
74711
+ function refuseGsapTakeover(el, showToast) {
74712
+ if (!gsapHoldsTranslate(el)) return;
74713
+ gsapOf(el)?.set(el, { x: 0, y: 0, xPercent: 0, yPercent: 0 });
74714
+ showToast(GSAP_TOOK_OVER, "error");
74715
+ throw markStudioSaveErrorAlreadyToasted(new Error(GSAP_TOOK_OVER));
74716
+ }
74461
74717
  var plainMoveCounter = 0;
74462
74718
  function stagePlainTranslate(commitPositionPatchToHtml, selection, next, coalesceKey) {
74463
- const style = selection.element.style;
74464
- const before = style.getPropertyValue("translate");
74465
- const patch = translatePatch(next);
74466
- style.setProperty("translate", patch.value);
74719
+ const el = selection.element;
74720
+ const before = captureStudioPathOffset(el);
74721
+ const patches = writePlainMove(el, next);
74722
+ const written = el.style.getPropertyValue("translate");
74467
74723
  const rollback = () => {
74468
- if (style.getPropertyValue("translate") === patch.value) style.setProperty("translate", before);
74724
+ if (el.style.getPropertyValue("translate") === written) restoreStudioPathOffset(el, before);
74469
74725
  };
74470
74726
  const key2 = coalesceKey ?? `move:${++plainMoveCounter}`;
74471
74727
  const options = { label: "Move layer", coalesceKey: key2, coalesceMs: Number.POSITIVE_INFINITY };
74472
- const save = () => commitPositionPatchToHtml(selection, [patch], options).catch((error) => {
74728
+ const save = () => commitPositionPatchToHtml(selection, patches, options).catch((error) => {
74473
74729
  rollback();
74474
74730
  throw error;
74475
74731
  });
74476
74732
  return { save, rollback };
74477
74733
  }
74478
- function stageElementOffset({ commitPositionPatchToHtml, showToast, readOnlyPreview }, selection, next, coalesceKey) {
74734
+ function stageElementOffset({ commitPositionPatchToHtml, showToast, readOnlyPreview }, selection, next, plainTranslate, coalesceKey) {
74479
74735
  const el = selection.element;
74480
74736
  if (readOnlyPreview) return { save: () => Promise.resolve(), rollback: () => void 0 };
74481
- if (!gsapWritesPosition(el)) {
74737
+ if (plainTranslate) {
74738
+ refuseGsapTakeover(el, showToast);
74482
74739
  return stagePlainTranslate(commitPositionPatchToHtml, selection, next, coalesceKey);
74483
74740
  }
74484
74741
  const previous = { position: el.style.position, left: el.style.left, top: el.style.top };
@@ -74504,293 +74761,73 @@ function stageElementOffset({ commitPositionPatchToHtml, showToast, readOnlyPrev
74504
74761
  return { save, rollback };
74505
74762
  }
74506
74763
 
74507
- // src/components/editor/manualEditsDomPatches.ts
74508
- function collectInlineStyleOps(element, properties, ops) {
74509
- for (const prop of properties) {
74510
- const val = element.style.getPropertyValue(prop);
74511
- if (val) ops.push({ type: "inline-style", property: prop, value: val });
74512
- }
74513
- }
74514
- function collectAttributeOps(element, attrNames, ops) {
74515
- for (const attr of attrNames) {
74516
- const val = element.getAttribute(attr);
74517
- if (val !== null) ops.push({ type: "attribute", property: attr, value: val });
74518
- }
74519
- }
74520
- function appendTransformDisplayOps(element, ops) {
74521
- const val = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
74522
- if (val !== null) {
74523
- ops.push({ type: "inline-style", property: "display", value: val || null });
74524
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, value: null });
74525
- }
74526
- }
74527
- function buildPathOffsetPatches(element) {
74528
- const ops = [];
74529
- collectInlineStyleOps(element, [STUDIO_OFFSET_X_PROP, STUDIO_OFFSET_Y_PROP], ops);
74530
- const inlineTranslate = element.style.getPropertyValue("translate");
74531
- const hasOffsetVars = element.style.getPropertyValue(STUDIO_OFFSET_X_PROP) || element.style.getPropertyValue(STUDIO_OFFSET_Y_PROP);
74532
- const translateValue = inlineTranslate && inlineTranslate !== "none" ? inlineTranslate : hasOffsetVars ? `var(${STUDIO_OFFSET_X_PROP}, 0px) var(${STUDIO_OFFSET_Y_PROP}, 0px)` : null;
74533
- if (translateValue) {
74534
- ops.push({ type: "inline-style", property: "translate", value: translateValue });
74535
- }
74536
- ops.push({ type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: "true" });
74537
- collectAttributeOps(
74538
- element,
74539
- [STUDIO_ORIGINAL_TRANSLATE_ATTR, STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR],
74540
- ops
74541
- );
74542
- collectInlineStyleOps(element, ["display"], ops);
74543
- collectAttributeOps(element, [STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR], ops);
74544
- return ops;
74545
- }
74546
- function buildClearPathOffsetPatches(element) {
74547
- const originalInlineTranslate = element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR);
74548
- const ops = [
74549
- { type: "inline-style", property: STUDIO_OFFSET_X_PROP, value: null },
74550
- { type: "inline-style", property: STUDIO_OFFSET_Y_PROP, value: null },
74551
- { type: "inline-style", property: "translate", value: originalInlineTranslate || null },
74552
- { type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: null },
74553
- { type: "attribute", property: STUDIO_ORIGINAL_TRANSLATE_ATTR, value: null },
74554
- { type: "attribute", property: STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, value: null }
74555
- ];
74556
- appendTransformDisplayOps(element, ops);
74557
- return ops;
74558
- }
74559
- var BOX_SIZE_STYLE_PROPS = [
74560
- "width",
74561
- "height",
74562
- "min-width",
74563
- "min-height",
74564
- "max-width",
74565
- "max-height",
74566
- "flex-basis",
74567
- "flex-grow",
74568
- "flex-shrink",
74569
- "box-sizing",
74570
- "scale",
74571
- "transform-origin",
74572
- "display"
74573
- ];
74574
- var BOX_SIZE_ORIG_ATTRS = [
74575
- [STUDIO_ORIGINAL_WIDTH_ATTR, "width"],
74576
- [STUDIO_ORIGINAL_HEIGHT_ATTR, "height"],
74577
- // Records a measurement rather than a style, so it restores nothing.
74578
- [STUDIO_ORIGINAL_BOX_WIDTH_ATTR, ""],
74579
- [STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, ""],
74580
- [STUDIO_ORIGINAL_MIN_WIDTH_ATTR, "min-width"],
74581
- [STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, "min-height"],
74582
- [STUDIO_ORIGINAL_MAX_WIDTH_ATTR, "max-width"],
74583
- [STUDIO_ORIGINAL_MAX_HEIGHT_ATTR, "max-height"],
74584
- [STUDIO_ORIGINAL_FLEX_BASIS_ATTR, "flex-basis"],
74585
- [STUDIO_ORIGINAL_FLEX_GROW_ATTR, "flex-grow"],
74586
- [STUDIO_ORIGINAL_FLEX_SHRINK_ATTR, "flex-shrink"],
74587
- [STUDIO_ORIGINAL_BOX_SIZING_ATTR, "box-sizing"],
74588
- [STUDIO_ORIGINAL_SCALE_ATTR, "scale"],
74589
- [STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, "transform-origin"],
74590
- [STUDIO_ORIGINAL_DISPLAY_ATTR, "display"],
74591
- [STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, ""]
74592
- ];
74593
- function buildBoxSizePatches(element) {
74594
- const ops = [];
74595
- collectInlineStyleOps(element, [STUDIO_WIDTH_PROP, STUDIO_HEIGHT_PROP], ops);
74596
- collectInlineStyleOps(element, BOX_SIZE_STYLE_PROPS, ops);
74597
- ops.push({ type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: "true" });
74598
- collectAttributeOps(
74599
- element,
74600
- BOX_SIZE_ORIG_ATTRS.map(([attr]) => attr),
74601
- ops
74602
- );
74603
- return ops;
74604
- }
74605
- function buildClearBoxSizePatches(element) {
74606
- const ops = [
74607
- { type: "inline-style", property: STUDIO_WIDTH_PROP, value: null },
74608
- { type: "inline-style", property: STUDIO_HEIGHT_PROP, value: null },
74609
- { type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: null }
74610
- ];
74611
- for (const [attrName, styleProp] of BOX_SIZE_ORIG_ATTRS) {
74612
- const origVal = element.getAttribute(attrName);
74613
- if (origVal !== null && styleProp) {
74614
- ops.push({ type: "inline-style", property: styleProp, value: origVal || null });
74615
- }
74616
- ops.push({ type: "attribute", property: attrName, value: null });
74617
- }
74618
- return ops;
74619
- }
74620
- var ROTATION_STYLE_PROPS = [
74621
- STUDIO_ROTATION_PROP,
74622
- "rotate",
74623
- "transform-origin",
74624
- "display"
74625
- ];
74626
- var ROTATION_ORIG_ATTRS = [
74627
- STUDIO_ORIGINAL_ROTATE_ATTR,
74628
- STUDIO_ORIGINAL_INLINE_ROTATE_ATTR,
74629
- STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
74630
- STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR
74631
- ];
74632
- function buildRotationPatches(element) {
74633
- const ops = [];
74634
- collectInlineStyleOps(element, ROTATION_STYLE_PROPS, ops);
74635
- ops.push({ type: "attribute", property: STUDIO_ROTATION_ATTR, value: "true" });
74636
- collectAttributeOps(element, ROTATION_ORIG_ATTRS, ops);
74637
- return ops;
74638
- }
74639
- function buildClearRotationPatches(element) {
74640
- const origInlineRotate = element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR);
74641
- const origRotationTransformOrigin = element.getAttribute(
74642
- STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR
74643
- );
74644
- const ops = [
74645
- { type: "inline-style", property: STUDIO_ROTATION_PROP, value: null },
74646
- { type: "inline-style", property: "rotate", value: origInlineRotate || null },
74647
- {
74648
- type: "inline-style",
74649
- property: "transform-origin",
74650
- value: origRotationTransformOrigin !== null ? origRotationTransformOrigin || null : null
74651
- },
74652
- { type: "attribute", property: STUDIO_ROTATION_ATTR, value: null },
74653
- { type: "attribute", property: STUDIO_ROTATION_DRAFT_ATTR, value: null },
74654
- { type: "attribute", property: STUDIO_ORIGINAL_ROTATE_ATTR, value: null },
74655
- { type: "attribute", property: STUDIO_ORIGINAL_INLINE_ROTATE_ATTR, value: null },
74656
- { type: "attribute", property: STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, value: null }
74657
- ];
74658
- appendTransformDisplayOps(element, ops);
74659
- return ops;
74660
- }
74661
-
74662
- // src/hooks/gsapTargetCache.ts
74663
- var _gsapCachedTimelines;
74664
- var _gsapTargetIds;
74665
- var _gsapTargetNodes;
74666
- function addTargetsFromTimeline(tl, ids, nodes) {
74667
- const children = tl.getChildren?.(true);
74668
- if (!children) return;
74669
- for (const child of children) {
74670
- const targets = child.targets?.();
74671
- if (!targets) continue;
74672
- for (const t of targets) {
74673
- nodes.add(t);
74674
- if (t.id) ids.add(t.id);
74675
- }
74676
- }
74677
- }
74678
- function collectGsapTargets(timelines) {
74679
- const ids = /* @__PURE__ */ new Set();
74680
- const nodes = /* @__PURE__ */ new WeakSet();
74681
- for (const tl of Object.values(timelines)) {
74682
- if (!tl) continue;
74683
- try {
74684
- addTargetsFromTimeline(tl, ids, nodes);
74685
- } catch {
74764
+ // src/hooks/plainRotation.ts
74765
+ var plainRotateCounter = 0;
74766
+ function savePlainRotation({ commitPositionPatchToHtml, readOnlyPreview }, selection, next) {
74767
+ if (readOnlyPreview) return Promise.resolve();
74768
+ const { element } = selection;
74769
+ const before = captureStudioRotation(element);
74770
+ const patches = element.hasAttribute(STUDIO_ROTATION_ATTR) ? buildClearRotationPatches(element) : [];
74771
+ if (patches.length) clearStudioRotation(element);
74772
+ const drawn = applyCssRotation(element, next.angle, patches.length ? void 0 : next.plain);
74773
+ patches.push(...drawn);
74774
+ const turn = drawn.at(-1);
74775
+ return commitPositionPatchToHtml(selection, patches, {
74776
+ label: "Rotate layer",
74777
+ coalesceKey: `rotate:${++plainRotateCounter}`,
74778
+ coalesceMs: Number.POSITIVE_INFINITY
74779
+ }).catch((error) => {
74780
+ if (element.style.getPropertyValue(turn.property) === turn.value) {
74781
+ restorePlainRotation(element, before);
74686
74782
  }
74687
- }
74688
- return { ids, nodes };
74689
- }
74690
- function readTimelines(iframe) {
74691
- if (!iframe?.contentWindow) return void 0;
74692
- try {
74693
- return iframe.contentWindow.__timelines;
74694
- } catch {
74695
- return void 0;
74696
- }
74697
- }
74698
- function isElementGsapTargeted(iframe, element) {
74699
- const timelines = readTimelines(iframe);
74700
- if (!timelines) return false;
74701
- if (timelines !== _gsapCachedTimelines) {
74702
- const cache2 = collectGsapTargets(timelines);
74703
- _gsapTargetIds = cache2.ids;
74704
- _gsapTargetNodes = cache2.nodes;
74705
- _gsapCachedTimelines = timelines;
74706
- }
74707
- return _gsapTargetNodes.has(element) || !!(element.id && _gsapTargetIds.has(element.id));
74783
+ throw error;
74784
+ });
74708
74785
  }
74709
74786
 
74710
74787
  // src/hooks/useDomGeometryCommits.ts
74711
- var GSAP_CSS_FALLBACK_BLOCKED_MESSAGE = "This element is GSAP-animated \u2014 dragging via CSS would corrupt keyframes";
74712
- function rejectGsapCssFallback(selection, previewIframeRef, showToast) {
74713
- if (!isElementGsapTargeted(previewIframeRef.current, selection.element)) return null;
74714
- const error = new Error(GSAP_CSS_FALLBACK_BLOCKED_MESSAGE);
74715
- showToast(error.message, "error");
74716
- return Promise.reject(error);
74717
- }
74718
74788
  function useDomGeometryCommits({
74719
- previewIframeRef,
74720
74789
  showToast,
74721
74790
  commitPositionPatchToHtml,
74722
74791
  readOnlyPreview
74723
74792
  }) {
74724
74793
  const stageElementPositionOffset = useCallback125(
74725
- (selection, next, coalesceKey) => stageElementOffset(
74794
+ (selection, next, plainTranslate, coalesceKey) => stageElementOffset(
74726
74795
  { commitPositionPatchToHtml, showToast, readOnlyPreview },
74727
74796
  selection,
74728
74797
  next,
74798
+ plainTranslate,
74729
74799
  coalesceKey
74730
74800
  ),
74731
74801
  [commitPositionPatchToHtml, readOnlyPreview, showToast]
74732
74802
  );
74733
- const handleDomPathOffsetCommit = useCallback125(
74734
- (selection, next) => {
74735
- if (readOnlyPreview) return Promise.resolve();
74736
- const gsapFallback = rejectGsapCssFallback(selection, previewIframeRef, showToast);
74737
- if (gsapFallback) return gsapFallback;
74738
- const before = captureStudioPathOffset(selection.element);
74739
- applyStudioPathOffset(selection.element, next);
74740
- return commitPositionPatchToHtml(selection, buildPathOffsetPatches(selection.element), {
74741
- label: "Move layer",
74742
- coalesceKey: `path-offset:${getDomEditTargetKey(selection)}`
74743
- }).catch((error) => {
74744
- restoreStudioPathOffset(selection.element, before);
74745
- throw error;
74746
- });
74747
- },
74748
- [commitPositionPatchToHtml, previewIframeRef, showToast, readOnlyPreview]
74749
- );
74750
74803
  const handleDomBoxSizeCommit = useCallback125(
74751
- (selection, next, offset) => {
74804
+ (selection, next, offset, restore) => {
74752
74805
  if (readOnlyPreview) return Promise.resolve();
74753
- const gsapFallback = rejectGsapCssFallback(selection, previewIframeRef, showToast);
74754
- if (gsapFallback) return gsapFallback;
74755
- const beforeSize = captureStudioBoxSize(selection.element);
74756
- const beforeOffset = offset ? captureStudioPathOffset(selection.element) : null;
74757
- const stageCrop = prepareCropResize(selection.element);
74758
- applyStudioBoxSize(selection.element, next);
74806
+ const element = selection.element;
74807
+ const beforeSize = captureStudioBoxSize(element);
74808
+ const beforeOffset = captureStudioPathOffset(element);
74809
+ const stageCrop = prepareCropResize(element);
74810
+ applyStudioBoxSize(element, next);
74759
74811
  const crop = stageCrop();
74760
- const patches = buildBoxSizePatches(selection.element);
74812
+ const patches = buildBoxSizePatches(element);
74761
74813
  if (crop) patches.push(crop.patch);
74762
- if (offset) {
74763
- applyStudioPathOffset(selection.element, offset);
74764
- patches.push(...buildPathOffsetPatches(selection.element));
74765
- }
74814
+ if (offset) patches.push(...writePlainMove(element, offset));
74766
74815
  return commitPositionPatchToHtml(selection, patches, {
74767
74816
  label: "Resize layer box",
74768
74817
  coalesceKey: `box-size:${getDomEditTargetKey(selection)}`
74769
74818
  }).catch((error) => {
74770
- restoreStudioBoxSize(selection.element, beforeSize);
74771
- if (beforeOffset) restoreStudioPathOffset(selection.element, beforeOffset);
74819
+ restoreStudioBoxSize(element, beforeSize);
74820
+ if (offset) restoreStudioPathOffset(element, beforeOffset);
74772
74821
  crop?.revert();
74822
+ restore?.();
74773
74823
  throw error;
74774
74824
  });
74775
74825
  },
74776
- [commitPositionPatchToHtml, previewIframeRef, showToast, readOnlyPreview]
74826
+ [commitPositionPatchToHtml, readOnlyPreview]
74777
74827
  );
74778
74828
  const handleDomRotationCommit = useCallback125(
74779
- (selection, next) => {
74780
- if (readOnlyPreview) return Promise.resolve();
74781
- const gsapFallback = rejectGsapCssFallback(selection, previewIframeRef, showToast);
74782
- if (gsapFallback) return gsapFallback;
74783
- const before = captureStudioRotation(selection.element);
74784
- applyStudioRotation(selection.element, next);
74785
- return commitPositionPatchToHtml(selection, buildRotationPatches(selection.element), {
74786
- label: "Rotate layer",
74787
- coalesceKey: `rotation:${getDomEditTargetKey(selection)}`
74788
- }).catch((error) => {
74789
- restoreStudioRotation(selection.element, before);
74790
- throw error;
74791
- });
74792
- },
74793
- [commitPositionPatchToHtml, previewIframeRef, showToast, readOnlyPreview]
74829
+ (selection, next) => savePlainRotation({ commitPositionPatchToHtml, readOnlyPreview }, selection, next),
74830
+ [commitPositionPatchToHtml, readOnlyPreview]
74794
74831
  );
74795
74832
  const handleDomManualEditsReset = useCallback125(
74796
74833
  (selection) => {
@@ -74821,7 +74858,6 @@ function useDomGeometryCommits({
74821
74858
  );
74822
74859
  return {
74823
74860
  stageElementPositionOffset,
74824
- handleDomPathOffsetCommit,
74825
74861
  handleDomBoxSizeCommit,
74826
74862
  handleDomRotationCommit,
74827
74863
  handleDomManualEditsReset
@@ -75000,12 +75036,10 @@ function useDomEditCommits({
75000
75036
  });
75001
75037
  const {
75002
75038
  stageElementPositionOffset,
75003
- handleDomPathOffsetCommit,
75004
75039
  handleDomBoxSizeCommit,
75005
75040
  handleDomRotationCommit,
75006
75041
  handleDomManualEditsReset
75007
75042
  } = useDomGeometryCommits({
75008
- previewIframeRef,
75009
75043
  showToast,
75010
75044
  commitPositionPatchToHtml,
75011
75045
  readOnlyPreview
@@ -75041,7 +75075,6 @@ function useDomEditCommits({
75041
75075
  handleDomRemoveTextField,
75042
75076
  stageElementPositionOffset,
75043
75077
  commitPositionPatchToHtml,
75044
- handleDomPathOffsetCommit,
75045
75078
  handleDomBoxSizeCommit,
75046
75079
  handleDomRotationCommit,
75047
75080
  handleDomManualEditsReset,
@@ -77239,6 +77272,23 @@ function useDomEditWiring(params) {
77239
77272
  // src/hooks/useGsapAwareEditing.ts
77240
77273
  import { useCallback as useCallback139 } from "react";
77241
77274
 
77275
+ // src/utils/elementGsap.ts
77276
+ function gsapOf2(element) {
77277
+ return element.ownerDocument.defaultView?.gsap;
77278
+ }
77279
+ function setElementGsapPosition(element, x, y) {
77280
+ const gsap3 = gsapOf2(element);
77281
+ if (!gsap3?.set) return false;
77282
+ gsap3.set(element, { x, y });
77283
+ return true;
77284
+ }
77285
+ function setElementGsapScale(element, x, y) {
77286
+ const gsap3 = gsapOf2(element);
77287
+ if (!gsap3?.set) return false;
77288
+ gsap3.set(element, { scaleX: x, scaleY: y });
77289
+ return true;
77290
+ }
77291
+
77242
77292
  // src/hooks/gsapResizePreflight.ts
77243
77293
  function resizeRoute(animations, fetchedAnimations) {
77244
77294
  const allKnownAnimations = [...animations, ...fetchedAnimations];
@@ -77943,6 +77993,7 @@ function useGsapAwareEditing({
77943
77993
  trackGsapInteractionFailure,
77944
77994
  stageElementPositionOffset,
77945
77995
  handleDomBoxSizeCommit,
77996
+ handleDomRotationCommit,
77946
77997
  commitPositionPatchToHtml,
77947
77998
  addGsapAnimation,
77948
77999
  convertToKeyframes,
@@ -77958,8 +78009,8 @@ function useGsapAwareEditing({
77958
78009
  );
77959
78010
  const handleGsapAwarePathOffsetCommit = useCallback139(
77960
78011
  async (selection, next, modifiers) => {
77961
- if (!gsapWritesPosition(selection.element))
77962
- return stageElementPositionOffset(selection, next).save();
78012
+ if (modifiers?.plainTranslate ?? !gsapWritesPosition(selection.element))
78013
+ return stageElementPositionOffset(selection, next, true).save();
77963
78014
  if (gsapCommitMutation) {
77964
78015
  try {
77965
78016
  const ownedAnimations = getGsapAnimationsForSelection(selection);
@@ -77973,7 +78024,7 @@ function useGsapAwareEditing({
77973
78024
  makeFetchFallback(selection),
77974
78025
  modifiers
77975
78026
  );
77976
- await saveMove(outcome, () => stageElementPositionOffset(selection, next).save());
78027
+ await saveMove(outcome, () => stageElementPositionOffset(selection, next, false).save());
77977
78028
  } catch (error) {
77978
78029
  trackGsapInteractionFailure(error, selection, "drag", "Move animated layer");
77979
78030
  throw error;
@@ -78022,10 +78073,13 @@ function useGsapAwareEditing({
78022
78073
  return Promise.resolve();
78023
78074
  };
78024
78075
  const preflightAnimations = /* @__PURE__ */ new Map();
78025
- const offsetMembers = /* @__PURE__ */ new Set();
78076
+ const offsetMembers = /* @__PURE__ */ new Map();
78026
78077
  const preflightResults = await Promise.allSettled(
78027
- updates.map(async ({ selection }) => {
78028
- if (!gsapWritesPosition(selection.element)) return void offsetMembers.add(selection);
78078
+ updates.map(async ({ selection, plainTranslate }) => {
78079
+ if (plainTranslate ?? !gsapWritesPosition(selection.element)) {
78080
+ refuseGsapTakeover(selection.element, showToast);
78081
+ return void offsetMembers.set(selection, true);
78082
+ }
78029
78083
  const animations = await makeFetchFallback(selection, { failOnFetchError: true })();
78030
78084
  preflightAnimations.set(selection, animations);
78031
78085
  const outcome = await tryGsapDragIntercept(
@@ -78037,7 +78091,7 @@ function useGsapAwareEditing({
78037
78091
  void 0,
78038
78092
  { preflightOnly: true, group: true }
78039
78093
  );
78040
- if (outcome.status === "element-offset") offsetMembers.add(selection);
78094
+ if (outcome.status === "element-offset") offsetMembers.set(selection, false);
78041
78095
  assertGsapEditPersisted(outcome);
78042
78096
  })
78043
78097
  );
@@ -78056,8 +78110,9 @@ function useGsapAwareEditing({
78056
78110
  );
78057
78111
  for (const [index, { selection, next }] of updates.entries()) {
78058
78112
  renderOnCommit = index === lastScriptWrite;
78059
- if (offsetMembers.has(selection)) {
78060
- await stageElementPositionOffset(selection, next, coalesceKey).save();
78113
+ const plain = offsetMembers.get(selection);
78114
+ if (plain !== void 0) {
78115
+ await stageElementPositionOffset(selection, next, plain, coalesceKey).save();
78061
78116
  continue;
78062
78117
  }
78063
78118
  try {
@@ -78094,11 +78149,14 @@ function useGsapAwareEditing({
78094
78149
  previewIframeRef,
78095
78150
  makeFetchFallback,
78096
78151
  trackGsapInteractionFailure,
78097
- stageElementPositionOffset
78152
+ stageElementPositionOffset,
78153
+ showToast
78098
78154
  ]
78099
78155
  );
78100
78156
  const handleGsapAwareBoxSizeCommit = useCallback139(
78101
78157
  async (selection, next, offset, restore = () => void 0) => {
78158
+ if (!gsapWritesBox(selection.element))
78159
+ return handleDomBoxSizeCommit(selection, next, offset, restore);
78102
78160
  let targetAnimations;
78103
78161
  try {
78104
78162
  const ownedAnimations = getGsapAnimationsForSelection(selection);
@@ -78169,7 +78227,8 @@ function useGsapAwareEditing({
78169
78227
  makeFetchFallback(selection)
78170
78228
  );
78171
78229
  await saveMove(dragOutcome, async () => {
78172
- anchorMove = stageElementPositionOffset(selection, offset, coalesceKey);
78230
+ const plain = !gsapWritesPosition(selection.element);
78231
+ anchorMove = stageElementPositionOffset(selection, offset, plain, coalesceKey);
78173
78232
  });
78174
78233
  }
78175
78234
  logResizeSettle(selection.element, ownsDragOffset ? "gsap-scale" : "gsap-size");
@@ -78179,13 +78238,7 @@ function useGsapAwareEditing({
78179
78238
  throw error;
78180
78239
  }
78181
78240
  }
78182
- logResize("dom-route", {
78183
- next,
78184
- offset: offset ?? null,
78185
- hadGsapMutation: !!gsapCommitMutation
78186
- });
78187
- logResizeSettle(selection.element, "dom-route");
78188
- await handleDomBoxSizeCommit(selection, next, offset);
78241
+ throw new Error("Resize of a GSAP-owned box has no GSAP writer");
78189
78242
  },
78190
78243
  afterBufferedCommitsSaved: async () => {
78191
78244
  await anchorMove?.save();
@@ -78213,10 +78266,11 @@ function useGsapAwareEditing({
78213
78266
  );
78214
78267
  const handleGsapAwareRotationCommit = useCallback139(
78215
78268
  async (selection, next) => {
78269
+ if (next.plain || !gsapWritesRotation(selection.element))
78270
+ return handleDomRotationCommit(selection, next);
78216
78271
  if (gsapCommitMutation) {
78217
78272
  try {
78218
- const ownedAnimations = getGsapAnimationsForSelection(selection);
78219
- const targetAnimations = Array.isArray(ownedAnimations) ? ownedAnimations : await ownedAnimations;
78273
+ const targetAnimations = await getGsapAnimationsForSelection(selection);
78220
78274
  const outcome = await tryGsapRotationIntercept(
78221
78275
  selection,
78222
78276
  next.angle,
@@ -78237,7 +78291,8 @@ function useGsapAwareEditing({
78237
78291
  previewIframeRef,
78238
78292
  makeFetchFallback,
78239
78293
  trackGsapInteractionFailure,
78240
- getGsapAnimationsForSelection
78294
+ getGsapAnimationsForSelection,
78295
+ handleDomRotationCommit
78241
78296
  ]
78242
78297
  );
78243
78298
  const { commitAnimatedProperties: commitAnimatedPropertiesRaw } = useAnimatedPropertyCommit({
@@ -78779,6 +78834,7 @@ function useDomEditSession({
78779
78834
  stageElementPositionOffset,
78780
78835
  commitPositionPatchToHtml,
78781
78836
  handleDomBoxSizeCommit,
78837
+ handleDomRotationCommit: handleDomCssRotationCommit,
78782
78838
  handleDomManualEditsReset,
78783
78839
  handleDomEditElementsDelete,
78784
78840
  handleDomZIndexReorderCommit
@@ -79008,6 +79064,7 @@ function useDomEditSession({
79008
79064
  trackGsapInteractionFailure,
79009
79065
  stageElementPositionOffset,
79010
79066
  handleDomBoxSizeCommit,
79067
+ handleDomRotationCommit: handleDomCssRotationCommit,
79011
79068
  commitPositionPatchToHtml,
79012
79069
  addGsapAnimation,
79013
79070
  convertToKeyframes,
@@ -80896,10 +80953,16 @@ function remintHfIds(html2, parser, taken) {
80896
80953
  }
80897
80954
  var HF_ID_ATTR_RE = /\bdata-hf-id\s*=\s*["']?([^"'\s>]+)/gi;
80898
80955
  var hfIdsInFile = (content) => new Set(Array.from(content.matchAll(HF_ID_ATTR_RE), (match) => match[1]));
80899
- function pasteElementHtml(content, payload) {
80956
+ function pasteElementHtml(content, payload, fromThisFile = false) {
80900
80957
  const reminted = remintHfIds(payload.html, new DOMParser(), hfIdsInFile(content));
80901
80958
  const deduped = deduplicateIds(reminted, collectHtmlIds(content));
80902
- return insertAsSibling(content, deduped, payload.originSelector, payload.originSelectorIndex);
80959
+ const result = insertAsSibling(
80960
+ content,
80961
+ deduped,
80962
+ payload.originSelector,
80963
+ payload.originSelectorIndex
80964
+ );
80965
+ return fromThisFile ? carryLook(result, renamedIds(reminted, deduped), 0) : result;
80903
80966
  }
80904
80967
  function pasteTimelineClips(content, clips, anchorTime, liveElements, fromThisFile = false) {
80905
80968
  const groupMinStart = Math.min(...clips.map((c) => c.start));
@@ -81028,6 +81091,7 @@ function useClipboard({
81028
81091
  kind: "dom-element",
81029
81092
  html: savedMarkupElseLive(parseSavedSource(content), live, sourceFile),
81030
81093
  sourceFile,
81094
+ projectId: projectIdRef.current ?? void 0,
81031
81095
  originSelector: domSelection.selector,
81032
81096
  originSelectorIndex: domSelection.selectorIndex
81033
81097
  };
@@ -81069,15 +81133,17 @@ function useClipboard({
81069
81133
  const targetPath = activeCompPath || "index.html";
81070
81134
  try {
81071
81135
  let pastedIds = [];
81136
+ const fromThisFile = payload.sourceFile === targetPath && payload.projectId === pid;
81072
81137
  const paste = (originalContent) => {
81073
- if (payload.kind !== "timeline-clip") return pasteElementHtml(originalContent, payload);
81138
+ if (payload.kind !== "timeline-clip")
81139
+ return pasteElementHtml(originalContent, payload, fromThisFile);
81074
81140
  const { currentTime, elements } = usePlayerStore.getState();
81075
81141
  const pasted = pasteTimelineClips(
81076
81142
  originalContent,
81077
81143
  payload.clips,
81078
81144
  currentTime,
81079
81145
  elements,
81080
- payload.sourceFile === targetPath && payload.projectId === pid
81146
+ fromThisFile
81081
81147
  );
81082
81148
  pastedIds = pasted.ids;
81083
81149
  return extendRootDurationInSource(pasted.content, pasted.requiredEnd);
@@ -82462,7 +82528,7 @@ function StudioHeader({
82462
82528
  "aria-pressed": inspectorButtonActive,
82463
82529
  className: cn(
82464
82530
  "h-full rounded-none",
82465
- inspectorButtonActive && "bg-hover text-accent enabled:hover:text-accent"
82531
+ inspectorButtonActive && "bg-on text-accent-ink enabled:hover:bg-on-hover enabled:hover:text-accent-ink"
82466
82532
  ),
82467
82533
  icon: /* @__PURE__ */ jsx190(InspectorIcon, { size: 16 }),
82468
82534
  onClick: () => {
@@ -83752,7 +83818,7 @@ function ContextMenu3({
83752
83818
  {
83753
83819
  role: "menuitem",
83754
83820
  onClick: () => setMode("confirm-delete"),
83755
- className: `${itemCls} text-red-400`,
83821
+ className: `${itemCls} text-danger-ink`,
83756
83822
  children: "Delete"
83757
83823
  }
83758
83824
  )
@@ -83786,10 +83852,10 @@ function ContextMenu3({
83786
83852
  }
83787
83853
  },
83788
83854
  "aria-label": `Rename ${filename(asset)}`,
83789
- 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"
83855
+ className: "w-full bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-1 text-[11px] text-text-0 focus:border-studio-accent/60 focus:outline-hidden"
83790
83856
  }
83791
83857
  ),
83792
- renameError && /* @__PURE__ */ jsx194("span", { className: "text-[10px] text-red-400", children: renameError }),
83858
+ renameError && /* @__PURE__ */ jsx194("span", { className: "text-[10px] text-danger-ink", children: renameError }),
83793
83859
  /* @__PURE__ */ jsxs153("div", { className: "flex items-center justify-end gap-1", children: [
83794
83860
  /* @__PURE__ */ jsx194(
83795
83861
  "button",
@@ -83803,7 +83869,7 @@ function ContextMenu3({
83803
83869
  "button",
83804
83870
  {
83805
83871
  onClick: commitRename,
83806
- className: "px-2 py-0.5 text-[10px] rounded-sm bg-studio-accent/80 hover:bg-studio-accent text-white transition-colors",
83872
+ className: "px-2 py-0.5 text-[10px] rounded-sm bg-accent hover:bg-accent-hover text-on-accent transition-colors",
83807
83873
  children: "Rename"
83808
83874
  }
83809
83875
  )
@@ -83820,8 +83886,8 @@ function DeleteConfirm2({
83820
83886
  onConfirm,
83821
83887
  onCancel
83822
83888
  }) {
83823
- return /* @__PURE__ */ jsxs153("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: [
83824
- /* @__PURE__ */ jsxs153("span", { className: "text-[10px] text-red-400 truncate", children: [
83889
+ return /* @__PURE__ */ jsxs153("div", { className: "px-2 py-1.5 bg-danger/15 border-l-2 border-red-500 flex items-center justify-between gap-2", children: [
83890
+ /* @__PURE__ */ jsxs153("span", { className: "text-[10px] text-danger-ink truncate", children: [
83825
83891
  "Delete ",
83826
83892
  name,
83827
83893
  "?"
@@ -83831,7 +83897,7 @@ function DeleteConfirm2({
83831
83897
  "button",
83832
83898
  {
83833
83899
  onClick: onConfirm,
83834
- className: "px-2 py-0.5 text-[10px] rounded-sm bg-red-600 text-white hover:bg-red-500 active:bg-red-700 transition-colors",
83900
+ className: "px-2 py-0.5 text-[10px] rounded-sm bg-danger text-on-danger hover:brightness-95 active:brightness-90 transition-colors",
83835
83901
  children: "Delete"
83836
83902
  }
83837
83903
  ),
@@ -84057,7 +84123,7 @@ function AudioRow({
84057
84123
  {
84058
84124
  "aria-label": playing ? `Pause preview of ${name}` : `Play preview of ${name}`,
84059
84125
  "aria-pressed": playing,
84060
- className: `w-7 h-7 rounded-md shrink-0 flex items-center justify-center transition-colors active:scale-[0.95] ${playing ? "bg-panel-accent/15 text-panel-accent" : "text-panel-text-5 group-hover:text-panel-text-3"}`,
84126
+ className: `w-7 h-7 rounded-md shrink-0 flex items-center justify-center transition-colors active:scale-[0.95] ${playing ? "bg-panel-accent/15 text-accent-ink" : "text-panel-text-5 group-hover:text-panel-text-3"}`,
84061
84127
  onClick: (e) => {
84062
84128
  e.stopPropagation();
84063
84129
  togglePlay();
@@ -84081,12 +84147,12 @@ function AudioRow({
84081
84147
  meta?.duration ? `${meta.duration}s \xB7 ` : "",
84082
84148
  subtype
84083
84149
  ] }),
84084
- used && /* @__PURE__ */ jsx195("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" }),
84150
+ used && /* @__PURE__ */ jsx195("span", { className: "text-[9px] font-medium text-accent-ink bg-panel-accent/10 px-1.5 py-px rounded-sm shrink-0", children: "in use" }),
84085
84151
  (isCopied || copyFailed) && /* @__PURE__ */ jsx195(
84086
84152
  "span",
84087
84153
  {
84088
84154
  role: "status",
84089
- className: `shrink-0 text-[9px] font-medium px-1.5 py-px rounded ${copyFailed ? "text-red-400 bg-red-500/10" : "text-panel-accent bg-panel-accent/10"}`,
84155
+ className: `shrink-0 text-[9px] font-medium px-1.5 py-px rounded ${copyFailed ? "text-danger-ink bg-red-500/10" : "text-accent-ink bg-panel-accent/10"}`,
84090
84156
  children: copyFailed ? "Copy failed" : "Copied"
84091
84157
  }
84092
84158
  )
@@ -84250,7 +84316,7 @@ function CopyChip({ feedback, asset }) {
84250
84316
  "span",
84251
84317
  {
84252
84318
  role: "status",
84253
- className: `shrink-0 text-[9px] font-medium px-1.5 py-px rounded ${feedback.ok ? "text-panel-accent bg-panel-accent/10" : "text-red-400 bg-red-500/10"}`,
84319
+ className: `shrink-0 text-[9px] font-medium px-1.5 py-px rounded ${feedback.ok ? "text-accent-ink bg-panel-accent/10" : "text-danger-ink bg-red-500/10"}`,
84254
84320
  children: feedback.ok ? "Copied" : "Copy failed"
84255
84321
  }
84256
84322
  );
@@ -84479,7 +84545,7 @@ function FontRow({
84479
84545
  onContextMenu: (e) => openAssetContextMenu(e, setContextMenu),
84480
84546
  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"}`,
84481
84547
  children: [
84482
- /* @__PURE__ */ jsx198("div", { className: "w-[50px] h-[32px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx198("span", { className: "text-[9px] font-medium text-neutral-700", children: extension }) }),
84548
+ /* @__PURE__ */ jsx198("div", { className: "w-[50px] h-[32px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx198("span", { className: "text-[9px] font-medium text-text-muted", children: extension }) }),
84483
84549
  /* @__PURE__ */ jsxs156("div", { className: "min-w-0 flex-1", children: [
84484
84550
  /* @__PURE__ */ jsx198(
84485
84551
  "span",
@@ -84490,7 +84556,7 @@ function FontRow({
84490
84556
  ),
84491
84557
  /* @__PURE__ */ jsxs156("div", { className: "flex items-center gap-1.5", children: [
84492
84558
  /* @__PURE__ */ jsx198("span", { className: "text-[10px] text-neutral-600 truncate", children: extension }),
84493
- used && /* @__PURE__ */ jsx198("span", { className: "text-[9px] font-medium text-panel-accent bg-panel-accent/10 px-1.5 py-px rounded-sm", children: "in use" }),
84559
+ used && /* @__PURE__ */ jsx198("span", { className: "text-[9px] font-medium text-accent-ink bg-panel-accent/10 px-1.5 py-px rounded-sm", children: "in use" }),
84494
84560
  /* @__PURE__ */ jsx198(CopyChip, { feedback: copyFeedback, asset })
84495
84561
  ] })
84496
84562
  ] })
@@ -84623,7 +84689,7 @@ function EmptyState({
84623
84689
  fill: "none",
84624
84690
  stroke: "currentColor",
84625
84691
  strokeWidth: "1.5",
84626
- className: "text-neutral-700",
84692
+ className: "text-text-off",
84627
84693
  children: [
84628
84694
  /* @__PURE__ */ jsx199(
84629
84695
  "path",
@@ -84772,7 +84838,7 @@ var AssetsTab = memo41(function AssetsTab2({
84772
84838
  "button",
84773
84839
  {
84774
84840
  onClick: () => setViewMode(m),
84775
- className: `flex-1 px-2 py-1 text-[11px] font-medium rounded transition-colors ${viewMode === m ? "bg-panel-accent/15 text-panel-accent" : "text-panel-text-3 hover:text-panel-text-1"}`,
84841
+ className: `flex-1 px-2 py-1 text-[11px] font-medium rounded transition-colors ${viewMode === m ? "bg-panel-accent/15 text-accent-ink" : "text-panel-text-3 hover:text-panel-text-1"}`,
84776
84842
  children: m === "local" ? "This project" : "All projects"
84777
84843
  },
84778
84844
  m
@@ -84812,7 +84878,7 @@ var AssetsTab = memo41(function AssetsTab2({
84812
84878
  {
84813
84879
  onClick: () => setActiveFilter("all"),
84814
84880
  "aria-pressed": activeFilter === "all",
84815
- className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors active:scale-[0.98] ${activeFilter === "all" ? "bg-panel-accent/15 text-panel-accent" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84881
+ className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors active:scale-[0.98] ${activeFilter === "all" ? "bg-panel-accent/15 text-accent-ink" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84816
84882
  children: [
84817
84883
  "All ",
84818
84884
  counts.all
@@ -84825,7 +84891,7 @@ var AssetsTab = memo41(function AssetsTab2({
84825
84891
  {
84826
84892
  onClick: () => setActiveFilter(activeFilter === cat ? "all" : cat),
84827
84893
  "aria-pressed": activeFilter === cat,
84828
- className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors active:scale-[0.98] ${activeFilter === cat ? "bg-panel-accent/15 text-panel-accent" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84894
+ className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors active:scale-[0.98] ${activeFilter === cat ? "bg-panel-accent/15 text-accent-ink" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84829
84895
  children: [
84830
84896
  CATEGORY_LABELS[cat],
84831
84897
  " ",
@@ -84841,7 +84907,7 @@ var AssetsTab = memo41(function AssetsTab2({
84841
84907
  "button",
84842
84908
  {
84843
84909
  onClick: () => setUsageFilter(usageFilter === "used" ? "all" : "used"),
84844
- className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors ${usageFilter === "used" ? "bg-panel-accent/15 text-panel-accent" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84910
+ className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors ${usageFilter === "used" ? "bg-panel-accent/15 text-accent-ink" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84845
84911
  children: [
84846
84912
  "In use ",
84847
84913
  usageCounts.used
@@ -84852,7 +84918,7 @@ var AssetsTab = memo41(function AssetsTab2({
84852
84918
  "button",
84853
84919
  {
84854
84920
  onClick: () => setUsageFilter(usageFilter === "unused" ? "all" : "unused"),
84855
- className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors ${usageFilter === "unused" ? "bg-panel-accent/15 text-panel-accent" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84921
+ className: `px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors ${usageFilter === "unused" ? "bg-panel-accent/15 text-accent-ink" : "bg-panel-input text-panel-text-3 hover:text-panel-text-1"}`,
84856
84922
  children: [
84857
84923
  "Unused ",
84858
84924
  usageCounts.unused
@@ -85026,7 +85092,7 @@ function PromptPreviewModal({
85026
85092
  /* @__PURE__ */ jsx200(
85027
85093
  "button",
85028
85094
  {
85029
- 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"}`,
85095
+ className: `px-4 py-1.5 rounded-lg text-xs font-medium transition-colors active:scale-[0.97] ${copyState === "copied" ? "bg-accent text-on-accent" : copyState === "failed" ? "bg-danger text-on-danger" : "bg-accent text-on-accent hover:bg-accent-hover"}`,
85030
85096
  onClick: handleCopy2,
85031
85097
  children: copyState === "copied" ? "Copied!" : copyState === "failed" ? "Copy failed" : "Copy prompt"
85032
85098
  }
@@ -85048,7 +85114,7 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85048
85114
  return /* @__PURE__ */ jsx201("div", { className: "flex flex-1 items-center justify-center text-neutral-600 text-xs", children: "Loading blocks\u2026" });
85049
85115
  }
85050
85116
  if (error) {
85051
- return /* @__PURE__ */ jsx201("div", { className: "flex flex-1 items-center justify-center text-red-400 text-xs px-4 text-center", children: error });
85117
+ return /* @__PURE__ */ jsx201("div", { className: "flex flex-1 items-center justify-center text-danger-ink text-xs px-4 text-center", children: error });
85052
85118
  }
85053
85119
  return /* @__PURE__ */ jsxs159("div", { className: "flex flex-col flex-1 min-h-0", children: [
85054
85120
  /* @__PURE__ */ jsx201("div", { className: "px-3 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx201(
@@ -85074,10 +85140,10 @@ var BlocksTab = memo42(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
85074
85140
  ))
85075
85141
  ] }) }),
85076
85142
  /* @__PURE__ */ jsxs159("div", { className: "flex-1 overflow-y-auto min-h-0 px-2 pb-2", children: [
85077
- category === "vfx" && /* @__PURE__ */ jsxs159("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: [
85143
+ category === "vfx" && /* @__PURE__ */ jsxs159("div", { className: "mb-2 px-2 py-1.5 rounded-md bg-purple-500/10 border border-purple-500/20 text-[9px] text-text-2 leading-relaxed", children: [
85078
85144
  "VFX blocks use WebGL via HTML-in-Canvas. Enable",
85079
85145
  " ",
85080
- /* @__PURE__ */ jsx201("span", { className: "font-mono text-purple-200", children: "chrome://flags/#html-in-canvas" }),
85146
+ /* @__PURE__ */ jsx201("span", { className: "font-mono text-text-0", children: "chrome://flags/#html-in-canvas" }),
85081
85147
  " for preview."
85082
85148
  ] }),
85083
85149
  filteredBlocks.length === 0 ? /* @__PURE__ */ jsx201("div", { className: "flex items-center justify-center h-32 text-neutral-600 text-xs", children: "No blocks match your search" }) : /* @__PURE__ */ jsx201(
@@ -85341,7 +85407,7 @@ function BlockCard({
85341
85407
  type: "button",
85342
85408
  onClick: handleAdd,
85343
85409
  title: "Add to composition at current time",
85344
- 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"}`,
85410
+ 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-danger text-on-danger" : "bg-white text-black hover:bg-white/85"}`,
85345
85411
  children: [
85346
85412
  /* @__PURE__ */ jsx201(
85347
85413
  "svg",
@@ -85365,7 +85431,7 @@ function BlockCard({
85365
85431
  type: "button",
85366
85432
  onClick: handleShowPrompt,
85367
85433
  title: "Generate a prompt to paste into your AI agent",
85368
- 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"}`,
85434
+ 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-text-0 text-bg-0 hover:bg-text-2 text-[10px] font-semibold"}`,
85369
85435
  children: [
85370
85436
  /* @__PURE__ */ jsxs159(
85371
85437
  "svg",
@@ -85408,7 +85474,7 @@ function BlockCard({
85408
85474
  }
85409
85475
 
85410
85476
  // src/components/sidebar/CompositionsTab.tsx
85411
- import { memo as memo43, useCallback as useCallback163, useEffect as useEffect136, useRef as useRef169, useState as useState132 } from "react";
85477
+ import { memo as memo43, useCallback as useCallback163, useEffect as useEffect136, useLayoutEffect as useLayoutEffect12, useMemo as useMemo80, useRef as useRef169, useState as useState132 } from "react";
85412
85478
  import { jsx as jsx202, jsxs as jsxs160 } from "react/jsx-runtime";
85413
85479
  var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
85414
85480
  var CARD_W = 80;
@@ -85471,6 +85537,34 @@ function syncIframePlayback(iframe, shouldPlay) {
85471
85537
  return false;
85472
85538
  }
85473
85539
  }
85540
+ var imageUrlOf = (snapshot3) => snapshot3.status === "ready" && snapshot3.value.kind === "image" ? snapshot3.value.url : null;
85541
+ function useLastFrame(request, snapshot3) {
85542
+ const current = imageUrlOf(snapshot3);
85543
+ const [kept, setKept] = useState132(null);
85544
+ if (request && current && kept?.request !== request) setKept({ request, url: current });
85545
+ useLayoutEffect12(() => {
85546
+ if (!kept || kept.request === request) return;
85547
+ const lease = thumbnailScheduler.acquire(kept.request, () => {
85548
+ });
85549
+ return () => lease.release();
85550
+ }, [kept, request]);
85551
+ return current ?? kept?.url ?? null;
85552
+ }
85553
+ function useNearViewport() {
85554
+ const [element, setElement] = useState132(null);
85555
+ const [near2, setNear] = useState132(false);
85556
+ useEffect136(() => {
85557
+ if (!element || near2) return;
85558
+ if (typeof IntersectionObserver === "undefined") return setNear(true);
85559
+ const observer = new IntersectionObserver(
85560
+ (entries) => entries.some((entry2) => entry2.isIntersecting) && setNear(true),
85561
+ { root: element.closest("[data-composition-list]"), rootMargin: "200px" }
85562
+ );
85563
+ observer.observe(element);
85564
+ return () => observer.disconnect();
85565
+ }, [element, near2]);
85566
+ return [setElement, near2];
85567
+ }
85474
85568
  function CompCard({
85475
85569
  projectId,
85476
85570
  comp,
@@ -85487,7 +85581,6 @@ function CompCard({
85487
85581
  const [hovered, setHovered] = useState132(false);
85488
85582
  const [stageSize, setStageSize] = useState132(DEFAULT_PREVIEW_STAGE);
85489
85583
  const [livePreviewLoaded, setLivePreviewLoaded] = useState132(false);
85490
- const [failedThumbnailUrl, setFailedThumbnailUrl] = useState132(null);
85491
85584
  const iframeRef = useRef169(null);
85492
85585
  const hoverTimer = useRef169(null);
85493
85586
  const syncTimer = useRef169(null);
@@ -85521,7 +85614,18 @@ function CompCard({
85521
85614
  const name = comp.replace(/^compositions\//, "").replace(/\.html$/, "");
85522
85615
  const previewUrl = compositionPreviewUrl(projectId, comp);
85523
85616
  const thumbnailUrl2 = compositionCardThumbnailUrl(projectId, comp, contentRevision);
85524
- const thumbnailFailed = failedThumbnailUrl === thumbnailUrl2;
85617
+ const [thumbnailBox, nearViewport] = useNearViewport();
85618
+ const timelineSessionEpoch = usePlayerStore((state) => state.timelineSessionEpoch);
85619
+ const thumbnailRequest = useMemo80(
85620
+ () => previewBooted && nearViewport ? compositionThumbnailRequest(thumbnailUrl2, projectId, {
85621
+ sessionEpoch: timelineSessionEpoch,
85622
+ rich: true
85623
+ }) : null,
85624
+ [previewBooted, nearViewport, thumbnailUrl2, projectId, timelineSessionEpoch]
85625
+ );
85626
+ const thumbnail = useThumbnailLease(thumbnailRequest);
85627
+ const frameUrl = useLastFrame(thumbnailRequest, thumbnail);
85628
+ const thumbnailFailed = thumbnail.status === "error";
85525
85629
  const previewScale = resolveCompositionPreviewScale({
85526
85630
  cardWidth: CARD_W,
85527
85631
  cardHeight: CARD_H,
@@ -85571,52 +85675,57 @@ function CompCard({
85571
85675
  onPointerLeave: handleLeave,
85572
85676
  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"}`,
85573
85677
  children: [
85574
- /* @__PURE__ */ jsxs160("div", { className: "w-20 h-[45px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 relative", children: [
85575
- thumbnailFailed ? /* @__PURE__ */ jsx202("div", { className: "absolute inset-0 flex items-center justify-center px-1 text-center text-[8px] leading-tight text-neutral-600", children: "Preview unavailable" }) : !previewBooted ? null : /* @__PURE__ */ jsx202(
85576
- "img",
85577
- {
85578
- src: thumbnailUrl2,
85579
- alt: "",
85580
- draggable: false,
85581
- loading: "lazy",
85582
- decoding: "async",
85583
- onError: () => setFailedThumbnailUrl(thumbnailUrl2),
85584
- className: `absolute inset-0 h-full w-full object-contain transition-opacity ${livePreviewLoaded ? "opacity-0" : "opacity-100"}`
85585
- }
85586
- ),
85587
- hovered && /* @__PURE__ */ jsx202(
85588
- "iframe",
85589
- {
85590
- ref: iframeRef,
85591
- src: previewUrl,
85592
- sandbox: "allow-scripts allow-same-origin",
85593
- className: "absolute border-none pointer-events-none",
85594
- style: {
85595
- transformOrigin: "0 0",
85596
- width: stageSize.width,
85597
- height: stageSize.height,
85598
- left: thumbnailOffsetX,
85599
- top: thumbnailOffsetY,
85600
- transform: `scale(${previewScale})`
85601
- },
85602
- onLoad: (e) => {
85603
- try {
85604
- const iframe = e.currentTarget;
85605
- const root = iframe.contentDocument?.querySelector("[data-composition-id]");
85606
- const width = Number(root?.getAttribute("data-width")) || DEFAULT_PREVIEW_STAGE.width;
85607
- const height = Number(root?.getAttribute("data-height")) || DEFAULT_PREVIEW_STAGE.height;
85608
- setStageSize({ width, height });
85609
- setLivePreviewLoaded(true);
85610
- requestIframePlaybackSync(true);
85611
- } catch {
85612
- setStageSize(DEFAULT_PREVIEW_STAGE);
85678
+ /* @__PURE__ */ jsxs160(
85679
+ "div",
85680
+ {
85681
+ ref: thumbnailBox,
85682
+ className: "w-20 h-[45px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 relative",
85683
+ children: [
85684
+ thumbnailFailed ? /* @__PURE__ */ jsx202("div", { className: "absolute inset-0 flex items-center justify-center px-1 text-center text-[8px] leading-tight text-neutral-600", children: "Preview unavailable" }) : !frameUrl ? null : /* @__PURE__ */ jsx202(
85685
+ "img",
85686
+ {
85687
+ src: frameUrl,
85688
+ alt: "",
85689
+ draggable: false,
85690
+ decoding: "async",
85691
+ className: `absolute inset-0 h-full w-full object-contain transition-opacity ${livePreviewLoaded ? "opacity-0" : "opacity-100"}`
85613
85692
  }
85614
- },
85615
- title: `${name} preview`,
85616
- tabIndex: -1
85617
- }
85618
- )
85619
- ] }),
85693
+ ),
85694
+ hovered && /* @__PURE__ */ jsx202(
85695
+ "iframe",
85696
+ {
85697
+ ref: iframeRef,
85698
+ src: previewUrl,
85699
+ sandbox: "allow-scripts allow-same-origin",
85700
+ className: "absolute border-none pointer-events-none",
85701
+ style: {
85702
+ transformOrigin: "0 0",
85703
+ width: stageSize.width,
85704
+ height: stageSize.height,
85705
+ left: thumbnailOffsetX,
85706
+ top: thumbnailOffsetY,
85707
+ transform: `scale(${previewScale})`
85708
+ },
85709
+ onLoad: (e) => {
85710
+ try {
85711
+ const iframe = e.currentTarget;
85712
+ const root = iframe.contentDocument?.querySelector("[data-composition-id]");
85713
+ const width = Number(root?.getAttribute("data-width")) || DEFAULT_PREVIEW_STAGE.width;
85714
+ const height = Number(root?.getAttribute("data-height")) || DEFAULT_PREVIEW_STAGE.height;
85715
+ setStageSize({ width, height });
85716
+ setLivePreviewLoaded(true);
85717
+ requestIframePlaybackSync(true);
85718
+ } catch {
85719
+ setStageSize(DEFAULT_PREVIEW_STAGE);
85720
+ }
85721
+ },
85722
+ title: `${name} preview`,
85723
+ tabIndex: -1
85724
+ }
85725
+ )
85726
+ ]
85727
+ }
85728
+ ),
85620
85729
  /* @__PURE__ */ jsxs160(
85621
85730
  "div",
85622
85731
  {
@@ -85638,7 +85747,7 @@ function CompCard({
85638
85747
  "span",
85639
85748
  {
85640
85749
  "aria-label": `${lintInfo.count} lint finding${lintInfo.count === 1 ? "" : "s"}`,
85641
- className: "shrink-0 min-w-[16px] text-center rounded-full bg-amber-500/20 px-1 text-[8px] font-bold text-amber-400",
85750
+ className: "shrink-0 min-w-[16px] text-center rounded-full bg-amber-500/20 px-1 text-[8px] font-bold text-warning-ink",
85642
85751
  children: lintInfo.count
85643
85752
  }
85644
85753
  )
@@ -85657,7 +85766,7 @@ function CompCard({
85657
85766
  event.stopPropagation();
85658
85767
  onAddToTimeline();
85659
85768
  },
85660
- 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",
85769
+ 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-accent-ink group-hover/card:opacity-100 group-focus-within/card:opacity-100 focus:opacity-100",
85661
85770
  children: /* @__PURE__ */ jsx202("span", { "aria-hidden": "true", children: "+" })
85662
85771
  }
85663
85772
  ),
@@ -85671,7 +85780,7 @@ function CompCard({
85671
85780
  e.stopPropagation();
85672
85781
  onRender();
85673
85782
  },
85674
- 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"}`,
85783
+ 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-accent-ink hover:bg-neutral-800"}`,
85675
85784
  children: /* @__PURE__ */ jsxs160(
85676
85785
  "svg",
85677
85786
  {
@@ -85713,7 +85822,7 @@ var CompositionsTab = memo43(function CompositionsTab2({
85713
85822
  if (compositions.length === 0) {
85714
85823
  return /* @__PURE__ */ jsx202("div", { className: "flex-1 flex items-center justify-center px-4", children: /* @__PURE__ */ jsx202("p", { className: "text-xs text-neutral-600 text-center", children: "No compositions found" }) });
85715
85824
  }
85716
- return /* @__PURE__ */ jsx202("div", { className: "flex-1 overflow-y-auto", children: compositions.map((comp) => /* @__PURE__ */ jsx202(
85825
+ return /* @__PURE__ */ jsx202("div", { className: "flex-1 overflow-y-auto", "data-composition-list": true, children: compositions.map((comp) => /* @__PURE__ */ jsx202(
85717
85826
  CompCard,
85718
85827
  {
85719
85828
  projectId,
@@ -85759,7 +85868,7 @@ function SidebarLintButton({
85759
85868
  type: "button",
85760
85869
  onClick: onLint,
85761
85870
  disabled: linting,
85762
- 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",
85871
+ 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-warning-ink enabled:hover:bg-neutral-800 enabled:active:scale-[0.98] transition-colors disabled:opacity-40",
85763
85872
  children: [
85764
85873
  /* @__PURE__ */ jsxs161(
85765
85874
  "svg",
@@ -85782,7 +85891,7 @@ function SidebarLintButton({
85782
85891
  {
85783
85892
  "data-lint-badge": hasError ? "error" : "warning",
85784
85893
  style: hasError ? { animationIterationCount: ERROR_PULSES_BEFORE_IDLE } : void 0,
85785
- 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",
85894
+ className: hasError ? "ml-1 min-w-[16px] rounded-full bg-danger px-1 text-[9px] font-bold text-on-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-warning-ink",
85786
85895
  children: [
85787
85896
  findingCount,
85788
85897
  /* @__PURE__ */ jsx204("span", { className: "sr-only", children: hasError ? " lint findings, including errors" : " lint findings, warnings only" })
@@ -86520,7 +86629,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86520
86629
  handleSelectLayer(layer);
86521
86630
  }
86522
86631
  },
86523
- className: `group flex w-full items-center gap-1.5 px-2 py-1 text-left transition-colors ${isDragged ? "opacity-40" : selected ? "bg-panel-accent/14 text-panel-accent" : "text-panel-text-2 hover:bg-panel-hover/40 hover:text-panel-text-1"} ${dragKey ? "cursor-grabbing" : "cursor-pointer"}`,
86632
+ className: `group flex w-full items-center gap-1.5 px-2 py-1 text-left transition-colors ${isDragged ? "opacity-40" : selected ? "bg-panel-accent/14 text-accent-ink" : "text-panel-text-2 hover:bg-panel-hover/40 hover:text-panel-text-1"} ${dragKey ? "cursor-grabbing" : "cursor-pointer"}`,
86524
86633
  style: { paddingLeft: 8 + layer.depth * 16 },
86525
86634
  title: draggable ? layer.element.hasAttribute("data-hf-group") ? "Double-click to enter group" : void 0 : "This layer can't be reordered",
86526
86635
  children: [
@@ -86548,7 +86657,7 @@ var LayersPanel = memo44(function LayersPanel2() {
86548
86657
  /* @__PURE__ */ jsx206(
86549
86658
  "span",
86550
86659
  {
86551
- 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"}`,
86660
+ className: `flex h-5 w-5 shrink-0 items-center justify-center rounded text-[8px] font-bold uppercase ${selected ? "bg-panel-accent/18 text-accent-ink" : isCompHost ? "bg-on text-accent-ink" : "bg-panel-hover text-panel-text-4"}`,
86552
86661
  children: getTagBadge(layer.tagName)
86553
86662
  }
86554
86663
  ),
@@ -86829,7 +86938,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
86829
86938
  }
86830
86939
  const gated = !ANIMATION_PIPELINE_WIRED;
86831
86940
  return /* @__PURE__ */ jsxs165("div", { className: "flex flex-col h-full min-h-0", children: [
86832
- gated && /* @__PURE__ */ jsx208("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__ */ jsx208("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." }) }),
86941
+ gated && /* @__PURE__ */ jsx208("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__ */ jsx208("p", { className: "text-2xs text-warning-ink leading-snug", children: "Animation editing isn't applied to playback or saved yet, so these controls are disabled." }) }),
86833
86942
  /* @__PURE__ */ jsxs165("div", { className: "flex-1 overflow-y-auto px-3 py-2", children: [
86834
86943
  /* @__PURE__ */ jsx208(
86835
86944
  AnimationPhase,
@@ -86870,7 +86979,7 @@ var CaptionAnimationPanel = memo45(function CaptionAnimationPanel2() {
86870
86979
  onClick: handleApplyToAll,
86871
86980
  disabled: gated,
86872
86981
  title: gated ? "Disabled until animation editing is applied to playback" : void 0,
86873
- className: "w-full py-1.5 rounded-sm border border-neutral-700 text-2xs text-neutral-300 hover:border-studio-accent/50 hover:text-studio-accent transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:border-neutral-700 disabled:hover:text-neutral-300",
86982
+ className: "w-full py-1.5 rounded-sm border border-neutral-700 text-2xs text-neutral-300 hover:border-studio-accent/50 hover:text-accent-ink transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:border-neutral-700 disabled:hover:text-neutral-300",
86874
86983
  children: "Apply to all groups"
86875
86984
  }
86876
86985
  ) })
@@ -87031,7 +87140,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87031
87140
  onClick: () => setActiveTab("style"),
87032
87141
  className: [
87033
87142
  "flex-1 py-0.5 rounded-sm text-2xs font-medium transition-colors",
87034
- activeTab === "style" ? "bg-studio-accent/20 text-studio-accent border border-studio-accent/50" : "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600"
87143
+ activeTab === "style" ? "bg-studio-accent/20 text-accent-ink border border-studio-accent/50" : "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600"
87035
87144
  ].join(" "),
87036
87145
  children: "Style"
87037
87146
  }
@@ -87045,7 +87154,7 @@ var CaptionPropertyPanel = memo46(function CaptionPropertyPanel2({
87045
87154
  onClick: () => setActiveTab("animation"),
87046
87155
  className: [
87047
87156
  "flex-1 py-0.5 rounded-sm text-2xs font-medium transition-colors",
87048
- activeTab === "animation" ? "bg-studio-accent/20 text-studio-accent border border-studio-accent/50" : "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600"
87157
+ activeTab === "animation" ? "bg-studio-accent/20 text-accent-ink border border-studio-accent/50" : "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600"
87049
87158
  ].join(" "),
87050
87159
  children: "Animation"
87051
87160
  }
@@ -87236,7 +87345,7 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87236
87345
  /* @__PURE__ */ jsxs167("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
87237
87346
  /* @__PURE__ */ jsx210("div", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider", children: "Parameters" }),
87238
87347
  params.length === 0 && /* @__PURE__ */ jsx210("div", { className: "text-[10px] text-neutral-500", children: "This block has no editable parameters." }),
87239
- !fileManager && params.length > 0 && /* @__PURE__ */ jsx210("div", { className: "text-[10px] text-amber-400/90", children: "Block params can't be edited here \u2014 no project file access." }),
87348
+ !fileManager && params.length > 0 && /* @__PURE__ */ jsx210("div", { className: "text-[10px] text-warning-ink", children: "Block params can't be edited here \u2014 no project file access." }),
87240
87349
  params.map((param) => /* @__PURE__ */ jsx210(
87241
87350
  ParamControl,
87242
87351
  {
@@ -87248,11 +87357,11 @@ var BlockParamsPanel = memo47(function BlockParamsPanel2({
87248
87357
  param.key
87249
87358
  )),
87250
87359
  commitState.tone === "saving" && /* @__PURE__ */ jsx210("div", { className: "text-[10px] text-neutral-500", role: "status", children: "Saving\u2026" }),
87251
- commitState.tone === "saved" && /* @__PURE__ */ jsxs167("div", { className: "text-[10px] text-emerald-500/90", role: "status", children: [
87360
+ commitState.tone === "saved" && /* @__PURE__ */ jsxs167("div", { className: "text-[10px] text-accent-ink", role: "status", children: [
87252
87361
  "Saved to ",
87253
87362
  compositionPath
87254
87363
  ] }),
87255
- commitState.tone === "error" && /* @__PURE__ */ jsx210("div", { className: "text-[10px] text-red-400", role: "alert", children: commitState.message })
87364
+ commitState.tone === "error" && /* @__PURE__ */ jsx210("div", { className: "text-[10px] text-danger-ink", role: "alert", children: commitState.message })
87256
87365
  ] })
87257
87366
  ] });
87258
87367
  });
@@ -87334,7 +87443,7 @@ function ParamControl({
87334
87443
  import { memo as memo51 } from "react";
87335
87444
 
87336
87445
  // src/components/renders/RenderQueue.tsx
87337
- import { memo as memo50, useState as useState140, useRef as useRef175, useEffect as useEffect141, useLayoutEffect as useLayoutEffect12, useId as useId5 } from "react";
87446
+ import { memo as memo50, useState as useState140, useRef as useRef175, useEffect as useEffect141, useLayoutEffect as useLayoutEffect13, useId as useId5 } from "react";
87338
87447
  import { createPortal as createPortal10 } from "react-dom";
87339
87448
  import { CANVAS_DIMENSIONS } from "@hyperframes/parsers";
87340
87449
 
@@ -87426,7 +87535,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87426
87535
  )
87427
87536
  ] }),
87428
87537
  isRendering && /* @__PURE__ */ jsx211("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx211("div", { className: "w-2 h-2 rounded-full bg-accent animate-pulse motion-reduce:animate-none" }) }),
87429
- job.status === "failed" && /* @__PURE__ */ jsx211("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx211("div", { className: "w-2 h-2 rounded-full bg-danger" }) }),
87538
+ job.status === "failed" && /* @__PURE__ */ jsx211("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx211("div", { className: "w-2 h-2 rounded-full bg-danger-ink" }) }),
87430
87539
  job.status === "cancelled" && /* @__PURE__ */ jsx211("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx211("div", { className: "w-2 h-2 rounded-full bg-text-5" }) })
87431
87540
  ]
87432
87541
  }
@@ -87439,7 +87548,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87439
87548
  isRendering && /* @__PURE__ */ jsxs168("div", { className: "mt-1", children: [
87440
87549
  /* @__PURE__ */ jsxs168("div", { className: "flex items-center justify-between mb-0.5", children: [
87441
87550
  /* @__PURE__ */ jsx211("span", { className: "text-step-9 text-text-4", children: job.stage || "Rendering" }),
87442
- /* @__PURE__ */ jsxs168("span", { className: "text-step-9 font-mono text-accent", children: [
87551
+ /* @__PURE__ */ jsxs168("span", { className: "text-step-9 font-mono text-accent-ink", children: [
87443
87552
  job.progress,
87444
87553
  "%"
87445
87554
  ] })
@@ -87463,7 +87572,7 @@ var RenderQueueItem = memo48(function RenderQueueItem2({
87463
87572
  }
87464
87573
  )
87465
87574
  ] }),
87466
- job.status === "failed" && job.error && /* @__PURE__ */ jsx211("span", { className: "text-step-9 text-danger mt-0.5 block", children: job.error }),
87575
+ job.status === "failed" && job.error && /* @__PURE__ */ jsx211("span", { className: "text-step-9 text-danger-ink mt-0.5 block", children: job.error }),
87467
87576
  job.status === "cancelled" && /* @__PURE__ */ jsx211("span", { className: "text-step-9 text-text-4 mt-0.5 block", children: "Cancelled" }),
87468
87577
  !isRendering && /* @__PURE__ */ jsx211("span", { className: "text-step-9 text-text-5", children: formatTimeAgo(job.createdAt) })
87469
87578
  ] }),
@@ -87602,17 +87711,17 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87602
87711
  className: "flex flex-col gap-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-2.5",
87603
87712
  children: [
87604
87713
  /* @__PURE__ */ jsxs169("div", { className: "flex flex-col gap-0.5", children: [
87605
- /* @__PURE__ */ jsx212("span", { className: "text-[11px] font-semibold text-amber-300", children: status.title ?? "FFmpeg not found" }),
87714
+ /* @__PURE__ */ jsx212("span", { className: "text-[11px] font-semibold text-warning-ink", children: status.title ?? "FFmpeg not found" }),
87606
87715
  /* @__PURE__ */ jsx212("span", { className: "text-[10px] leading-snug text-pretty text-panel-text-2", children: status.detail ?? "FFmpeg is required to encode video." })
87607
87716
  ] }),
87608
87717
  status.command ? /* @__PURE__ */ jsxs169("div", { className: "flex items-center gap-1.5", children: [
87609
- /* @__PURE__ */ jsx212("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 }),
87718
+ /* @__PURE__ */ jsx212("code", { className: "flex-1 overflow-x-auto whitespace-nowrap rounded-xs bg-input px-2 py-1 text-[10px] text-panel-text-2", children: status.command }),
87610
87719
  /* @__PURE__ */ jsx212(
87611
87720
  "button",
87612
87721
  {
87613
87722
  type: "button",
87614
87723
  onClick: () => void copy(status.command ?? ""),
87615
- className: `h-6 w-14 shrink-0 rounded-xs border border-amber-500/30 text-[10px] font-medium text-amber-200 transition-colors hover:bg-amber-500/20 active:scale-[0.98] ${FOCUS_RING}`,
87724
+ className: `h-6 w-14 shrink-0 rounded-xs border border-amber-500/30 text-[10px] font-medium text-warning-ink transition-colors hover:bg-amber-500/20 active:scale-[0.98] ${FOCUS_RING}`,
87616
87725
  children: copied ? "Copied" : "Copy"
87617
87726
  }
87618
87727
  )
@@ -87624,7 +87733,7 @@ var FfmpegRequiredNotice = memo49(function FfmpegRequiredNotice2({
87624
87733
  type: "button",
87625
87734
  onClick: onRecheck,
87626
87735
  disabled: checking,
87627
- className: `rounded-xs py-0.5 text-[10px] font-medium text-amber-200 underline-offset-2 transition-colors hover:underline disabled:opacity-50 ${FOCUS_RING}`,
87736
+ className: `rounded-xs py-0.5 text-[10px] font-medium text-warning-ink underline-offset-2 transition-colors hover:underline disabled:opacity-50 ${FOCUS_RING}`,
87628
87737
  children: checking ? "Checking\u2026" : "Recheck"
87629
87738
  }
87630
87739
  ),
@@ -87719,7 +87828,7 @@ function FormatInfoTooltip({ format }) {
87719
87828
  timeoutRef.current = setTimeout(() => setOpen(false), 120);
87720
87829
  };
87721
87830
  useEffect141(() => () => clearTimeout(timeoutRef.current), []);
87722
- useLayoutEffect12(() => {
87831
+ useLayoutEffect13(() => {
87723
87832
  if (!open) return;
87724
87833
  const el = triggerRef.current;
87725
87834
  if (!el) return;
@@ -87985,7 +88094,7 @@ var RenderQueue = memo50(function RenderQueue2({
87985
88094
  role: "alert",
87986
88095
  className: "flex items-start justify-between gap-2 px-3 py-2 border-b border-border bg-danger/10",
87987
88096
  children: [
87988
- /* @__PURE__ */ jsx213("span", { className: "text-step-10 text-danger", children: actionError }),
88097
+ /* @__PURE__ */ jsx213("span", { className: "text-step-10 text-danger-ink", children: actionError }),
87989
88098
  onDismissActionError && /* @__PURE__ */ jsx213(
87990
88099
  IconButton,
87991
88100
  {
@@ -88013,7 +88122,7 @@ var RenderQueue = memo50(function RenderQueue2({
88013
88122
  }
88014
88123
  ),
88015
88124
  /* @__PURE__ */ jsx213("div", { ref: listRef, className: "flex-1 overflow-y-auto", children: loadError && jobs.length === 0 ? /* @__PURE__ */ jsxs170("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", role: "alert", children: [
88016
- /* @__PURE__ */ jsx213("p", { className: "text-step-10 text-danger text-center", children: loadError }),
88125
+ /* @__PURE__ */ jsx213("p", { className: "text-step-10 text-danger-ink text-center", children: loadError }),
88017
88126
  onRetryLoad && /* @__PURE__ */ jsx213(Button, { size: "sm", variant: "secondary", onClick: onRetryLoad, children: "Retry" })
88018
88127
  ] }) : jobs.length === 0 ? /* @__PURE__ */ jsxs170("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-2", children: [
88019
88128
  /* @__PURE__ */ jsxs170(
@@ -88162,7 +88271,7 @@ function SlideList({
88162
88271
  role: "button",
88163
88272
  tabIndex: 0,
88164
88273
  "aria-pressed": isSelected,
88165
- className: `flex items-center gap-2 px-3 py-1.5 rounded cursor-pointer text-[11px] transition-colors ${isSelected ? "bg-studio-accent/20 text-white" : "hover:bg-neutral-800/60 text-neutral-300"}`,
88274
+ className: `flex items-center gap-2 px-3 py-1.5 rounded cursor-pointer text-[11px] transition-colors ${isSelected ? "bg-on text-text-0" : "hover:bg-neutral-800/60 text-neutral-300"}`,
88166
88275
  onClick: () => onSelect(scene.id),
88167
88276
  onKeyDown: (e) => {
88168
88277
  if (e.key === "Enter" || e.key === " ") {
@@ -88191,7 +88300,7 @@ function SlideList({
88191
88300
  "aria-label": "Move slide up",
88192
88301
  title: "Move up",
88193
88302
  disabled: slideIndex <= 0,
88194
- className: "px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-white enabled:active:scale-[0.95] disabled:opacity-30 disabled:cursor-not-allowed",
88303
+ className: "px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-text-0 enabled:active:scale-[0.95] disabled:opacity-30 disabled:cursor-not-allowed",
88195
88304
  onClick: (e) => {
88196
88305
  e.stopPropagation();
88197
88306
  onReorder(scene.id, "up");
@@ -88206,7 +88315,7 @@ function SlideList({
88206
88315
  "aria-label": "Move slide down",
88207
88316
  title: "Move down",
88208
88317
  disabled: slideIndex === slides.length - 1,
88209
- className: "px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-white enabled:active:scale-[0.95] disabled:opacity-30 disabled:cursor-not-allowed",
88318
+ className: "px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-text-0 enabled:active:scale-[0.95] disabled:opacity-30 disabled:cursor-not-allowed",
88210
88319
  onClick: (e) => {
88211
88320
  e.stopPropagation();
88212
88321
  onReorder(scene.id, "down");
@@ -88242,7 +88351,7 @@ function SlideInspector({
88242
88351
  /* @__PURE__ */ jsx215(
88243
88352
  "textarea",
88244
88353
  {
88245
- 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",
88354
+ className: "bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1.5 text-[11px] text-text-0 resize-none placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden",
88246
88355
  rows: 3,
88247
88356
  placeholder: "Speaker notes or script...",
88248
88357
  value: slide?.notes ?? "",
@@ -88257,7 +88366,7 @@ function SlideInspector({
88257
88366
  "button",
88258
88367
  {
88259
88368
  type: "button",
88260
- className: "text-[10px] px-2 py-0.5 rounded-sm bg-neutral-700 hover:bg-neutral-600 text-neutral-200 transition-colors",
88369
+ className: "text-[10px] px-2 py-0.5 rounded-sm bg-hover hover:bg-press text-neutral-200 transition-colors",
88261
88370
  onClick: onMarkFragment,
88262
88371
  title: `Mark ${currentTime.toFixed(2)}s as hold-point`,
88263
88372
  children: [
@@ -88280,7 +88389,7 @@ function SlideInspector({
88280
88389
  {
88281
88390
  type: "button",
88282
88391
  "aria-label": `Remove fragment at ${t.toFixed(2)}s`,
88283
- className: "text-neutral-400 hover:text-red-400 transition-colors",
88392
+ className: "text-neutral-400 hover:text-danger-ink transition-colors",
88284
88393
  onClick: () => onRemoveFragment(t),
88285
88394
  children: "\xD7"
88286
88395
  }
@@ -88318,7 +88427,7 @@ function BranchTree({
88318
88427
  {
88319
88428
  id: inputId,
88320
88429
  type: "text",
88321
- className: "flex-1 bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-white placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden",
88430
+ className: "flex-1 bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-text-0 placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden",
88322
88431
  placeholder: "New branch name...",
88323
88432
  value: newLabel,
88324
88433
  onChange: (e) => setNewLabel(e.target.value),
@@ -88332,7 +88441,7 @@ function BranchTree({
88332
88441
  "button",
88333
88442
  {
88334
88443
  type: "button",
88335
- className: "px-2 py-1 rounded-sm bg-neutral-700 hover:bg-neutral-600 text-[11px] text-neutral-200 transition-colors shrink-0",
88444
+ className: "px-2 py-1 rounded-sm bg-hover hover:bg-press text-[11px] text-neutral-200 transition-colors shrink-0",
88336
88445
  onClick: handleCreate,
88337
88446
  children: "Add"
88338
88447
  }
@@ -88377,7 +88486,7 @@ function BranchItem({
88377
88486
  editing ? /* @__PURE__ */ jsx215(
88378
88487
  "input",
88379
88488
  {
88380
- 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",
88489
+ className: "flex-1 bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-0.5 text-[11px] text-text-0 focus:border-studio-accent/60 focus:outline-hidden",
88381
88490
  value: draft,
88382
88491
  autoFocus: true,
88383
88492
  onChange: (e) => setDraft(e.target.value),
@@ -88393,7 +88502,7 @@ function BranchItem({
88393
88502
  {
88394
88503
  role: "button",
88395
88504
  tabIndex: 0,
88396
- className: "flex-1 text-[11px] text-white font-medium truncate cursor-pointer hover:text-neutral-300",
88505
+ className: "flex-1 text-[11px] text-text-0 font-medium truncate cursor-pointer hover:text-neutral-300",
88397
88506
  title: "Click to rename",
88398
88507
  onClick: () => setEditing(true),
88399
88508
  onKeyDown: (e) => {
@@ -88410,14 +88519,14 @@ function BranchItem({
88410
88519
  {
88411
88520
  type: "button",
88412
88521
  "aria-label": `Delete branch ${seq.label}`,
88413
- className: "text-[10px] text-neutral-500 hover:text-red-400 active:scale-[0.95] transition-colors px-1",
88522
+ className: "text-[10px] text-neutral-500 hover:text-danger-ink active:scale-[0.95] transition-colors px-1",
88414
88523
  onClick: () => setConfirmingDelete(true),
88415
88524
  children: "\u2715"
88416
88525
  }
88417
88526
  )
88418
88527
  ] }),
88419
- confirmingDelete && /* @__PURE__ */ jsxs171("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: [
88420
- /* @__PURE__ */ jsxs171("span", { className: "text-[10px] text-red-400", children: [
88528
+ confirmingDelete && /* @__PURE__ */ jsxs171("div", { className: "px-2 py-1.5 bg-danger/15 border-l-2 border-red-500 flex flex-col gap-1 rounded-xs", children: [
88529
+ /* @__PURE__ */ jsxs171("span", { className: "text-[10px] text-danger-ink", children: [
88421
88530
  "Delete branch \u201C",
88422
88531
  seq.label,
88423
88532
  "\u201D",
@@ -88433,7 +88542,7 @@ function BranchItem({
88433
88542
  setConfirmingDelete(false);
88434
88543
  onDelete(seq.id);
88435
88544
  },
88436
- className: "px-2 py-0.5 text-[10px] rounded-sm bg-red-600 text-white hover:bg-red-500 active:bg-red-700 transition-colors",
88545
+ className: "px-2 py-0.5 text-[10px] rounded-sm bg-danger text-on-danger hover:brightness-95 active:brightness-90 transition-colors",
88437
88546
  children: "Delete"
88438
88547
  }
88439
88548
  ),
@@ -88472,7 +88581,7 @@ function BranchItem({
88472
88581
  {
88473
88582
  type: "button",
88474
88583
  "aria-pressed": isSelected,
88475
- className: `flex-1 text-left truncate transition-colors hover:text-neutral-200 ${isSelected ? "text-white" : "text-neutral-400"}`,
88584
+ className: `flex-1 text-left truncate transition-colors hover:text-neutral-200 ${isSelected ? "text-text-0" : "text-neutral-400"}`,
88476
88585
  onClick: () => onSelectBranchSlide(seq.id, scene.id),
88477
88586
  children: scene.label || scene.id
88478
88587
  }
@@ -88524,7 +88633,7 @@ function HotspotTool({
88524
88633
  "input",
88525
88634
  {
88526
88635
  type: "text",
88527
- className: "bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-white placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden",
88636
+ className: "bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-text-0 placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden",
88528
88637
  placeholder: "Button label...",
88529
88638
  value: hotspotLabel,
88530
88639
  onChange: (e) => setHotspotLabel(e.target.value),
@@ -88535,7 +88644,7 @@ function HotspotTool({
88535
88644
  /* @__PURE__ */ jsxs171(
88536
88645
  "select",
88537
88646
  {
88538
- 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",
88647
+ className: "bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-text-0 focus:border-studio-accent/60 focus:outline-hidden",
88539
88648
  value: targetSequenceId,
88540
88649
  onChange: (e) => setTargetSequenceId(e.target.value),
88541
88650
  "aria-label": "Target branch sequence",
@@ -88551,7 +88660,7 @@ function HotspotTool({
88551
88660
  type: "button",
88552
88661
  disabled: !elementKey3 || !targetSequenceId,
88553
88662
  title: !elementKey3 ? "Select an element on the canvas first" : !targetSequenceId ? "Choose a target branch first" : void 0,
88554
- className: "px-3 py-1.5 rounded-sm bg-studio-accent/80 enabled:hover:bg-studio-accent enabled:active:scale-[0.98] text-white text-[11px] font-medium transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
88663
+ className: "px-3 py-1.5 rounded-sm bg-accent enabled:hover:bg-accent-hover enabled:active:scale-[0.98] text-on-accent text-[11px] font-medium transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
88555
88664
  onClick: handleMakeHotspot,
88556
88665
  children: "Make hotspot"
88557
88666
  }
@@ -88576,7 +88685,7 @@ function HotspotTool({
88576
88685
  {
88577
88686
  type: "button",
88578
88687
  "aria-label": `Remove hotspot ${h.label}`,
88579
- className: "text-[10px] text-neutral-500 hover:text-red-400 transition-colors",
88688
+ className: "text-[10px] text-neutral-500 hover:text-danger-ink transition-colors",
88580
88689
  onClick: () => onRemoveHotspot(selectedSceneId, h.id),
88581
88690
  children: "\u2715"
88582
88691
  }
@@ -88988,7 +89097,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
88988
89097
  return /* @__PURE__ */ jsxs172(
88989
89098
  "div",
88990
89099
  {
88991
- className: "flex flex-col h-full overflow-y-auto text-white",
89100
+ className: "flex flex-col h-full overflow-y-auto text-text-0",
88992
89101
  onKeyDown: (e) => {
88993
89102
  if ((e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "z") {
88994
89103
  const target = e.target instanceof HTMLElement ? e.target.tagName : "";
@@ -89003,16 +89112,16 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89003
89112
  "div",
89004
89113
  {
89005
89114
  role: "alert",
89006
- className: "flex items-center justify-between gap-2 px-3 py-2 bg-red-950/40 border-b border-red-500/40",
89115
+ className: "flex items-center justify-between gap-2 px-3 py-2 bg-danger/15 border-b border-red-500/40",
89007
89116
  children: [
89008
- /* @__PURE__ */ jsx216("span", { className: "text-[11px] text-red-300", children: "Changes not saved" }),
89117
+ /* @__PURE__ */ jsx216("span", { className: "text-[11px] text-danger-ink", children: "Changes not saved" }),
89009
89118
  /* @__PURE__ */ jsx216(
89010
89119
  "button",
89011
89120
  {
89012
89121
  type: "button",
89013
89122
  disabled: retrying,
89014
89123
  onClick: handleRetryPersist,
89015
- className: "px-2 py-0.5 text-[10px] rounded-sm bg-red-600 text-white enabled:hover:bg-red-500 enabled:active:scale-[0.97] disabled:opacity-50 transition-colors",
89124
+ className: "px-2 py-0.5 text-[10px] rounded-sm bg-danger text-on-danger enabled:hover:brightness-95 enabled:active:scale-[0.97] disabled:opacity-50 transition-colors",
89016
89125
  children: retrying ? "Retrying\u2026" : "Retry"
89017
89126
  }
89018
89127
  )
@@ -89129,7 +89238,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
89129
89238
  }
89130
89239
 
89131
89240
  // src/components/panels/VariablesPanel.tsx
89132
- import { memo as memo52, useCallback as useCallback176, useEffect as useEffect144, useMemo as useMemo80, useState as useState146 } from "react";
89241
+ import { memo as memo52, useCallback as useCallback176, useEffect as useEffect144, useMemo as useMemo81, useState as useState146 } from "react";
89133
89242
 
89134
89243
  // src/hooks/useVariablesPersist.ts
89135
89244
  import { useCallback as useCallback173 } from "react";
@@ -89474,7 +89583,7 @@ function DeclarationForm({
89474
89583
  className: VARIABLES_INPUT_CLASS
89475
89584
  }
89476
89585
  ) }),
89477
- error && /* @__PURE__ */ jsx217("p", { className: "text-[10px] text-red-400", children: error }),
89586
+ error && /* @__PURE__ */ jsx217("p", { className: "text-[10px] text-danger-ink", children: error }),
89478
89587
  /* @__PURE__ */ jsxs173("div", { className: "flex items-center justify-end gap-2 pt-1", children: [
89479
89588
  /* @__PURE__ */ jsx217(
89480
89589
  "button",
@@ -89512,7 +89621,7 @@ function RowAction({
89512
89621
  type: "button",
89513
89622
  onClick,
89514
89623
  title,
89515
- className: `h-5 rounded px-1.5 text-[9px] text-neutral-500 hover:bg-neutral-800 ${danger ? "hover:text-red-400" : "hover:text-neutral-200"}`,
89624
+ className: `h-5 rounded px-1.5 text-[9px] text-neutral-500 hover:bg-neutral-800 ${danger ? "hover:text-danger-ink" : "hover:text-neutral-200"}`,
89516
89625
  children: label
89517
89626
  }
89518
89627
  );
@@ -89656,7 +89765,7 @@ function formatIssue(issue) {
89656
89765
  }
89657
89766
  function ValidationStrip({ issues }) {
89658
89767
  if (issues.length === 0) return null;
89659
- return /* @__PURE__ */ jsx220("div", { className: "space-y-1 rounded-lg border border-red-900/60 bg-red-950/30 p-2", children: issues.map((issue) => /* @__PURE__ */ jsx220("p", { className: "text-[10px] text-red-300", children: formatIssue(issue) }, `${issue.kind}:${issue.variableId}`)) });
89768
+ return /* @__PURE__ */ jsx220("div", { className: "space-y-1 rounded-lg border border-danger/40 bg-danger/15 p-2", children: issues.map((issue) => /* @__PURE__ */ jsx220("p", { className: "text-[10px] text-danger-ink", children: formatIssue(issue) }, `${issue.kind}:${issue.variableId}`)) });
89660
89769
  }
89661
89770
  function VariableRow({
89662
89771
  decl,
@@ -89677,7 +89786,7 @@ function VariableRow({
89677
89786
  unused && /* @__PURE__ */ jsx220(
89678
89787
  "span",
89679
89788
  {
89680
- className: "rounded-sm bg-amber-900/40 px-1 py-px text-[8px] text-amber-400",
89789
+ className: "rounded-sm bg-amber-500/15 px-1 py-px text-[8px] text-warning-ink",
89681
89790
  title: "No script reads this variable",
89682
89791
  children: "unused"
89683
89792
  }
@@ -89739,7 +89848,7 @@ function PreviewModeHeader({
89739
89848
  /* @__PURE__ */ jsx220(
89740
89849
  "span",
89741
89850
  {
89742
- 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"}`,
89851
+ className: `rounded-full px-2 py-0.5 text-[9px] font-medium ${hasOverrides ? "bg-studio-accent/20 text-accent-ink" : "bg-neutral-800 text-neutral-500"}`,
89743
89852
  children: hasOverrides ? `Previewing ${overrideCount} custom` : "Previewing defaults"
89744
89853
  }
89745
89854
  )
@@ -89825,22 +89934,22 @@ var VariablesPanel = memo52(function VariablesPanel2({
89825
89934
  reloadPreview,
89826
89935
  publishSdkSession
89827
89936
  });
89828
- const declarations = useMemo80(
89937
+ const declarations = useMemo81(
89829
89938
  () => sdkSession?.getVariableDeclarations() ?? [],
89830
89939
  // eslint-disable-next-line react-hooks/exhaustive-deps
89831
89940
  [sdkSession, refreshKey, revision]
89832
89941
  );
89833
- const usage = useMemo80(
89942
+ const usage = useMemo81(
89834
89943
  () => sdkSession?.getVariableUsage() ?? null,
89835
89944
  // eslint-disable-next-line react-hooks/exhaustive-deps
89836
89945
  [sdkSession, refreshKey, revision]
89837
89946
  );
89838
- const issues = useMemo80(
89947
+ const issues = useMemo81(
89839
89948
  () => previewValues && sdkSession ? sdkSession.validateVariableValues(previewValues) : [],
89840
89949
  // eslint-disable-next-line react-hooks/exhaustive-deps
89841
89950
  [sdkSession, previewValues, refreshKey, revision]
89842
89951
  );
89843
- const effectiveValues = useMemo80(
89952
+ const effectiveValues = useMemo81(
89844
89953
  () => sdkSession?.getVariableValues(previewValues ?? void 0) ?? {},
89845
89954
  // eslint-disable-next-line react-hooks/exhaustive-deps
89846
89955
  [sdkSession, previewValues, refreshKey, revision]
@@ -90155,15 +90264,15 @@ function useSlideshowPersist({
90155
90264
  }
90156
90265
 
90157
90266
  // src/hooks/useSlideshowTabState.ts
90158
- import { useMemo as useMemo81 } from "react";
90267
+ import { useMemo as useMemo82 } from "react";
90159
90268
  import { SLIDESHOW_ISLAND_TYPE as SLIDESHOW_ISLAND_TYPE2, slideshowIslandRegex as slideshowIslandRegex2 } from "@hyperframes/core/slideshow";
90160
90269
  function useSlideshowTabState(params) {
90161
90270
  const { editingFileContent, previewIframeRef, refreshKey, slideshowVisible } = params;
90162
- const isSlideshowComposition = useMemo81(() => {
90271
+ const isSlideshowComposition = useMemo82(() => {
90163
90272
  if (!editingFileContent || !editingFileContent.includes(SLIDESHOW_ISLAND_TYPE2)) return false;
90164
90273
  return slideshowIslandRegex2("i").test(editingFileContent);
90165
90274
  }, [editingFileContent]);
90166
- const slideshowScenes = useMemo81(() => {
90275
+ const slideshowScenes = useMemo82(() => {
90167
90276
  try {
90168
90277
  const win = previewIframeRef.current?.contentWindow;
90169
90278
  return (win?.__clipManifest?.scenes ?? []).map((s) => ({
@@ -91182,12 +91291,6 @@ function RippleEditIcon({ size = 16 }) {
91182
91291
  );
91183
91292
  }
91184
91293
 
91185
- // src/components/timelineToolbarStyles.ts
91186
- var flatBtn = "flex h-7 w-7 items-center justify-center rounded-md transition-colors";
91187
- var flatIdle = `${flatBtn} text-neutral-400 hover:bg-white/6 hover:text-neutral-200 active:scale-[0.98]`;
91188
- var flatActive = `${flatBtn} bg-white/8 text-neutral-100 active:scale-[0.98]`;
91189
- var flatDisabled = `${flatBtn} text-neutral-700 cursor-not-allowed`;
91190
-
91191
91294
  // src/components/TimelineHistoryButtons.tsx
91192
91295
  import { Fragment as Fragment62, jsx as jsx225, jsxs as jsxs178 } from "react/jsx-runtime";
91193
91296
  function HistoryButton({ action, can, label, onClick }) {
@@ -91300,7 +91403,7 @@ function TimelineToolPicker({ showSelectAroundPlayhead = true }) {
91300
91403
  shortcut: row.shortcut,
91301
91404
  onClick: row.run,
91302
91405
  "data-active": row.active || void 0,
91303
- className: row.active ? "bg-neutral-800 text-white" : void 0,
91406
+ className: row.active ? "bg-press text-text-0" : void 0,
91304
91407
  children: /* @__PURE__ */ jsxs179("span", { className: "flex items-center gap-2", children: [
91305
91408
  row.icon,
91306
91409
  row.label
@@ -91487,7 +91590,7 @@ function TimelineToolbar({
91487
91590
  disabled: !onToggleKeyframe,
91488
91591
  onClick: onToggleKeyframe,
91489
91592
  "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",
91490
- 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"}`,
91593
+ className: !onToggleKeyframe ? flatDisabled : `${flatBtn} active:scale-[0.98] hover:bg-hover ${keyframeState === "active" ? "text-accent-ink" : keyframeState === "inactive" ? "text-neutral-400 hover:text-accent-ink" : "text-neutral-600 hover:text-neutral-400"}`,
91491
91594
  children: /* @__PURE__ */ jsx227("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "currentColor", children: keyframeState === "active" ? /* @__PURE__ */ jsx227("path", { d: "M5 0.5L9.5 5L5 9.5L0.5 5Z" }) : /* @__PURE__ */ jsx227(
91492
91595
  "path",
91493
91596
  {
@@ -91512,7 +91615,7 @@ function TimelineToolbar({
91512
91615
  onClick: () => setAutoKeyframeEnabled(!autoKeyframeEnabled),
91513
91616
  "aria-label": "Auto-record manual edits as keyframes",
91514
91617
  "aria-pressed": autoKeyframeEnabled,
91515
- 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"}`,
91618
+ className: `${flatBtn} active:scale-[0.98] hover:bg-hover ${autoKeyframeEnabled ? "text-danger-ink" : "text-neutral-600 hover:text-neutral-400"}`,
91516
91619
  children: /* @__PURE__ */ jsxs180("svg", { width: "16", height: "16", viewBox: "0 0 10 10", fill: "none", children: [
91517
91620
  /* @__PURE__ */ jsx227("path", { d: "M5 0.7L9.3 5L5 9.3L0.7 5Z", stroke: "currentColor", strokeWidth: "1" }),
91518
91621
  /* @__PURE__ */ jsx227(
@@ -91589,7 +91692,7 @@ function TimelineToolbar({
91589
91692
  onClick: () => {
91590
91693
  if (canAdd) addBeatAtCompositionTime(currentTime);
91591
91694
  },
91592
- className: canAdd ? `${flatBtn} text-neutral-400 hover:bg-white/6 hover:text-[#22c55e] active:scale-[0.98]` : flatDisabled,
91695
+ className: canAdd ? `${flatBtn} text-text-2 hover:bg-hover hover:text-accent-ink active:scale-[0.98]` : flatDisabled,
91593
91696
  children: /* @__PURE__ */ jsx227("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx227(
91594
91697
  "path",
91595
91698
  {
@@ -91618,7 +91721,7 @@ function TimelineToolbar({
91618
91721
  "aria-label": thumbnailsVisible ? "Hide thumbnails \u2014 labels only" : "Show thumbnails \u2014 posters stay visible; richer previews appear on interaction",
91619
91722
  "aria-pressed": thumbnailsVisible,
91620
91723
  onClick: () => setThumbnailMode(thumbnailsVisible ? "hidden" : "adaptive"),
91621
- 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"}`,
91724
+ className: `h-7 px-2 rounded-md text-[11px] font-medium transition-colors ${thumbnailsVisible ? "bg-studio-accent/10 text-accent-ink" : "text-neutral-400 hover:bg-hover hover:text-neutral-200"}`,
91622
91725
  children: /* @__PURE__ */ jsx227(Image3, { size: 16, "aria-hidden": "true" })
91623
91726
  }
91624
91727
  )
@@ -91631,7 +91734,7 @@ function TimelineToolbar({
91631
91734
  onClick: () => setZoomMode("fit"),
91632
91735
  "aria-label": "Fit timeline to width",
91633
91736
  "aria-pressed": zoomMode === "fit",
91634
- className: `h-7 px-2 rounded-md text-[11px] font-medium transition-colors ${zoomMode === "fit" ? "bg-studio-accent/10 text-studio-accent" : "text-neutral-400 hover:bg-white/6 hover:text-neutral-200"}`,
91737
+ className: `h-7 px-2 rounded-md text-[11px] font-medium transition-colors ${zoomMode === "fit" ? "bg-studio-accent/10 text-accent-ink" : "text-neutral-400 hover:bg-hover hover:text-neutral-200"}`,
91635
91738
  children: /* @__PURE__ */ jsx227(ArrowsOutLineHorizontal, { size: 16, "aria-hidden": "true" })
91636
91739
  }
91637
91740
  ) }),
@@ -91665,7 +91768,7 @@ function TimelineToolbar({
91665
91768
  timelineSliderToZoomPercent(Number(e.target.value), timelineFitPps)
91666
91769
  );
91667
91770
  },
91668
- 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"
91771
+ 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-text-0 [&::-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"
91669
91772
  }
91670
91773
  ),
91671
91774
  /* @__PURE__ */ jsx227(Tooltip, { label: "Zoom in", children: /* @__PURE__ */ jsx227(
@@ -92016,7 +92119,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92016
92119
  recordEdit: editHistory.recordEdit,
92017
92120
  setRefreshKey
92018
92121
  });
92019
- const masterCompPath = useMemo82(
92122
+ const masterCompPath = useMemo83(
92020
92123
  () => resolveMasterCompositionPath(fileManager.compositions),
92021
92124
  [fileManager.compositions]
92022
92125
  );
@@ -92121,7 +92224,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92121
92224
  });
92122
92225
  const dismissBlockParams = useCallback186(() => setActiveBlockParams(null), [setActiveBlockParams]);
92123
92226
  const setRightPanelTab = useDismissingTabSetter(panelLayout.setRightPanelTab, dismissBlockParams);
92124
- const layout = useMemo82(
92227
+ const layout = useMemo83(
92125
92228
  () => ({ ...panelLayout, setRightPanelTab }),
92126
92229
  [panelLayout, setRightPanelTab]
92127
92230
  );
@@ -92273,7 +92376,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92273
92376
  });
92274
92377
  handleToggleRecordingRef.current = handleToggleRecording;
92275
92378
  const canvasRectRef = useRef181(null);
92276
- useLayoutEffect13(() => {
92379
+ useLayoutEffect14(() => {
92277
92380
  if (gestureState !== "recording" || !previewIframe) {
92278
92381
  canvasRectRef.current = null;
92279
92382
  return;
@@ -92340,7 +92443,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
92340
92443
  handlePreviewIframeRef,
92341
92444
  refreshPreviewDocumentVersion
92342
92445
  });
92343
- const timelineToolbar = useMemo82(
92446
+ const timelineToolbar = useMemo83(
92344
92447
  () => /* @__PURE__ */ jsx229(
92345
92448
  TimelineToolbar,
92346
92449
  {
@@ -92857,7 +92960,7 @@ function findElementBlock(html2, elementId2) {
92857
92960
  }
92858
92961
 
92859
92962
  // src/hooks/useDomStyleCommit.ts
92860
- import { useCallback as useCallback188, useMemo as useMemo83, useRef as useRef183, useState as useState151 } from "react";
92963
+ import { useCallback as useCallback188, useMemo as useMemo84, useRef as useRef183, useState as useState151 } from "react";
92861
92964
  var noop = () => {
92862
92965
  };
92863
92966
  function useDomStyleCommit({
@@ -92873,7 +92976,7 @@ function useDomStyleCommit({
92873
92976
  const [queue2] = useState151(createDomEditSaveQueue);
92874
92977
  useMountEffect(() => () => queue2.destroy());
92875
92978
  const versions = useRef183(/* @__PURE__ */ new Map()).current;
92876
- const editHistory = useMemo83(() => ({ recordEdit }), [recordEdit]);
92979
+ const editHistory = useMemo84(() => ({ recordEdit }), [recordEdit]);
92877
92980
  const persistDomEditOperations = useDomEditPersist({
92878
92981
  activeCompPath,
92879
92982
  previewIframeRef: iframeRef,
@@ -92905,11 +93008,10 @@ function useDomStyleCommit({
92905
93008
  }
92906
93009
 
92907
93010
  // src/hooks/useDomGeometryCommit.ts
92908
- import { useCallback as useCallback189, useMemo as useMemo84, useRef as useRef184, useState as useState152 } from "react";
93011
+ import { useCallback as useCallback189, useMemo as useMemo85, useRef as useRef184, useState as useState152 } from "react";
92909
93012
  var noop2 = () => {
92910
93013
  };
92911
93014
  var NO_SELECTED_ANIMATIONS = [];
92912
- var noDomBoxSizeRoute = () => Promise.reject(new Error("Resize has no DOM route here"));
92913
93015
  function useDomGeometryCommit({
92914
93016
  projectId,
92915
93017
  iframeRef,
@@ -92922,7 +93024,7 @@ function useDomGeometryCommit({
92922
93024
  const projectIdRef = useRef184(projectId);
92923
93025
  projectIdRef.current = projectId;
92924
93026
  const pending2 = useRef184(/* @__PURE__ */ new Set()).current;
92925
- const editHistory = useMemo84(() => ({ recordEdit }), [recordEdit]);
93027
+ const editHistory = useMemo85(() => ({ recordEdit }), [recordEdit]);
92926
93028
  const reload = useCallback189(
92927
93029
  () => reloadPreview ? reloadPreview() : iframeRef.current?.contentWindow?.location.reload(),
92928
93030
  [reloadPreview, iframeRef]
@@ -92962,15 +93064,11 @@ function useDomGeometryCommit({
92962
93064
  },
92963
93065
  [commitPositionPatchToHtml, queue2]
92964
93066
  );
92965
- const stageElementPositionOffset = useCallback189(
92966
- (selection, next, coalesceKey) => stageElementOffset(
92967
- { commitPositionPatchToHtml: commitWithFreshQueue, showToast },
92968
- selection,
92969
- next,
92970
- coalesceKey
92971
- ),
92972
- [commitWithFreshQueue, showToast]
92973
- );
93067
+ const { stageElementPositionOffset, handleDomBoxSizeCommit, handleDomRotationCommit } = useDomGeometryCommits({
93068
+ showToast,
93069
+ commitPositionPatchToHtml: commitWithFreshQueue,
93070
+ readOnlyPreview: false
93071
+ });
92974
93072
  const makeFetchFallback = useGsapAnimationFetchFallback(projectId);
92975
93073
  const trackGsapInteractionFailure = useGsapInteractionFailureTelemetry(activeCompPath, showToast);
92976
93074
  const {
@@ -92989,7 +93087,8 @@ function useDomGeometryCommit({
92989
93087
  makeFetchFallback,
92990
93088
  trackGsapInteractionFailure,
92991
93089
  stageElementPositionOffset,
92992
- handleDomBoxSizeCommit: noDomBoxSizeRoute,
93090
+ handleDomBoxSizeCommit,
93091
+ handleDomRotationCommit,
92993
93092
  commitPositionPatchToHtml: commitWithFreshQueue,
92994
93093
  addGsapAnimation: gsap3.addGsapAnimation,
92995
93094
  convertToKeyframes: gsap3.convertToKeyframes,
@@ -93015,7 +93114,7 @@ function useDomGeometryCommit({
93015
93114
  },
93016
93115
  [pending2, showToast]
93017
93116
  );
93018
- return useMemo84(
93117
+ return useMemo85(
93019
93118
  () => ({
93020
93119
  commitPathOffset: (selection, next, modifiers) => saved2(() => handleGsapAwarePathOffsetCommit(selection, next, modifiers)),
93021
93120
  commitGroupPathOffset: (updates) => saved2(() => handleGsapAwareGroupPathOffsetCommit(updates)),