@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
@@ -5,72 +5,110 @@
5
5
  @theme static {
6
6
  /* ---------------------------------------------------------------- colour */
7
7
 
8
- /* Background levels, darkest (app shell) to lightest (inset panel body). */
9
- --color-bg-0: #0a0a0a;
10
- --color-bg-1: #0c0c0e;
11
- --color-bg-2: #121214;
12
-
13
- /* Raised surfaces. */
14
- --color-surface: #18181b;
15
- --color-surface-alt: #141414;
16
- --color-input: #161618;
17
- --color-hover: #27272a;
18
-
19
- /* Separators, weakest to strongest. */
20
- --color-hairline: #1a1a1c;
21
- --color-border: #1e1e1e;
22
- --color-border-input: #27272a;
23
- --color-border-strong: #262626;
24
-
25
- /* Text, brightest (0) to dimmest (5). */
26
- --color-text-0: #fafafa;
27
- --color-text-1: #e4e4e7;
28
- --color-text-2: #a1a1aa;
29
- --color-text-3: #71717a;
30
- --color-text-4: #52525b;
31
- --color-text-5: #3f3f46;
32
- --color-text-body: #e5e5e5;
33
- --color-text-muted: #737373;
8
+ /* Graphite. Each colour is `light-dark(light, dark)`, resolved where it is painted, so the
9
+ * colour-scheme decides: Studio is dark, `data-theme="paper"` makes it light, and the player
10
+ * keeps a dark scheme in both. Text clears 4.5:1 and icons 3:1 on every surface below. */
11
+
12
+ /* Surfaces: the app shell first, menus and popovers last. */
13
+ --color-bg-0: light-dark(oklch(0.955 0.005 70), oklch(0.235 0.007 70));
14
+ --color-bg-1: var(--color-bg-0);
15
+ --color-bg-2: var(--color-surface);
16
+ --color-input: light-dark(oklch(1 0 70), oklch(0.25 0.007 70));
17
+ --color-surface: light-dark(oklch(0.987 0.005 70), oklch(0.265 0.007 70));
18
+ --color-surface-alt: var(--color-surface);
19
+ /* Menus, popovers and tooltips. */
20
+ --color-raised: light-dark(oklch(1 0 70), oklch(0.295 0.007 70));
21
+
22
+ /* States, washes of the brightest text so they work on any surface. `on` is a toggle that is on. */
23
+ --color-hover: light-dark(
24
+ color-mix(in oklab, var(--color-text-0) 5.5%, transparent),
25
+ color-mix(in oklab, var(--color-text-0) 7.5%, transparent)
26
+ );
27
+ --color-press: light-dark(
28
+ color-mix(in oklab, var(--color-text-0) 9.5%, transparent),
29
+ color-mix(in oklab, var(--color-text-0) 13%, transparent)
30
+ );
31
+ --color-on: light-dark(
32
+ color-mix(in oklab, var(--color-accent) 13%, transparent),
33
+ color-mix(in oklab, var(--color-accent) 16%, transparent)
34
+ );
35
+ --color-on-hover: light-dark(
36
+ color-mix(in oklab, var(--color-accent) 22%, transparent),
37
+ color-mix(in oklab, var(--color-accent) 27%, transparent)
38
+ );
39
+
40
+ /* Separators. */
41
+ --color-border: light-dark(
42
+ color-mix(in oklab, var(--color-text-0) 8%, transparent),
43
+ color-mix(in oklab, var(--color-text-0) 7.5%, transparent)
44
+ );
45
+ --color-hairline: var(--color-border);
46
+ --color-border-strong: light-dark(
47
+ color-mix(in oklab, var(--color-text-0) 15%, transparent),
48
+ color-mix(in oklab, var(--color-text-0) 14%, transparent)
49
+ );
50
+ --color-border-input: var(--color-border-strong);
51
+
52
+ /* Text: primary, secondary, muted (4.5:1), and off (3:1, disabled controls only). */
53
+ --color-text-0: light-dark(oklch(0.205 0.003 70), oklch(0.965 0.004 70));
54
+ --color-text-1: var(--color-text-0);
55
+ --color-text-body: var(--color-text-0);
56
+ --color-text-2: light-dark(oklch(0.403 0.003 70), oklch(0.908 0.004 70));
57
+ --color-text-3: var(--color-text-2);
58
+ --color-text-muted: light-dark(oklch(0.503 0.003 70), oklch(0.777 0.004 70));
59
+ --color-text-4: var(--color-text-muted);
60
+ --color-text-5: var(--color-text-muted);
61
+ --color-text-off: light-dark(oklch(0.597 0.003 70), oklch(0.67 0.004 70));
34
62
 
35
63
  /* Roles. Selection and playhead are reserved and differ from the accent so a
36
- * selected clip, the playhead and an accented control stay tellable apart. */
37
- --color-accent: #3ce6ac;
38
- --color-selection: #4ba3d2;
39
- --color-playhead: #ffffff;
40
- --color-danger: #ef4444;
41
- --color-media: #00e3ff;
42
- --color-container: #f5a623;
64
+ * selected clip, the playhead and an accented control stay tellable apart.
65
+ * `accent-ink` is accent text on a surface; `on-accent` is text on an accent fill. */
66
+ --color-accent: light-dark(oklch(0.536 0.114 164), oklch(0.82 0.159 164));
67
+ --color-accent-hover: light-dark(oklch(0.486 0.103 164), oklch(0.87 0.159 164));
68
+ --color-on-accent: light-dark(oklch(1 0 0), oklch(0.2 0.043 164));
69
+ --color-accent-ink: light-dark(oklch(0.45 0.096 164), oklch(0.827 0.159 164));
70
+ --color-ring: var(--color-accent-ink);
71
+ --color-selection: light-dark(oklch(0.5 0.13 240), #4ba3d2);
72
+ --color-playhead: var(--color-text-0);
73
+ --color-danger: oklch(0.56 0.19 25);
74
+ --color-danger-ink: light-dark(oklch(0.45 0.17 25), oklch(0.791 0.12 25));
75
+ --color-warning-ink: light-dark(oklch(0.5 0.12 70), oklch(82.8% 0.189 84.429));
76
+ --color-on-danger: oklch(1 0 0);
77
+ --color-media: light-dark(oklch(0.5 0.1 215), #00e3ff);
78
+ --color-container: light-dark(oklch(0.55 0.13 70), #f5a623);
43
79
 
44
80
  /* The two stops of the HeyGen brand gradient, worn by the header logo. Fixed brand values
45
81
  * rather than roles, so they are not reachable as a background or text colour by mistake. */
46
82
  --color-brand-gradient-from: #06e3fa;
47
83
  --color-brand-gradient-to: #4fdb5e;
48
84
 
49
- /* The timeline's own surfaces: darker and bluer than the shared scale, so they
50
- * get their own names instead of snapping to the nearest --color-bg/-surface
51
- * step (a host themes the timeline by overriding these). */
52
- --timeline-shell-bg: #0a0a0b;
53
- --timeline-shell-border: rgba(255, 255, 255, 0.05);
54
- --timeline-ruler-border: rgba(255, 255, 255, 0.16);
55
- --timeline-row-bg: #101014;
56
- --timeline-row-border: rgba(255, 255, 255, 0.06);
57
- --timeline-gutter-bg: #0e0f12;
58
- --timeline-gutter-border: rgba(255, 255, 255, 0.1);
59
- --timeline-text-primary: rgba(255, 255, 255, 0.92);
60
- --timeline-text-secondary: rgba(255, 255, 255, 0.62);
61
- --timeline-tick-text: rgba(255, 255, 255, 0.34);
62
- --timeline-tick-major: rgba(255, 255, 255, 0.1);
63
- --timeline-tick-minor: rgba(255, 255, 255, 0.06);
64
- --timeline-clip-bg: rgba(255, 255, 255, 0.12);
65
- --timeline-clip-label-active: rgba(232, 255, 247, 0.95);
85
+ /* The timeline's own surfaces and inks, named so a host can theme the timeline alone. */
86
+ --timeline-shell-bg: var(--color-surface);
87
+ --timeline-shell-border: var(--color-border);
88
+ --timeline-ruler-border: color-mix(in oklab, var(--color-text-0) 16%, transparent);
89
+ --timeline-row-bg: light-dark(oklch(0.997 0.002 70), oklch(0.275 0.007 70));
90
+ --timeline-row-border: color-mix(in oklab, var(--color-text-0) 6%, transparent);
91
+ --timeline-gutter-bg: light-dark(oklch(0.967 0.005 70), oklch(0.253 0.007 70));
92
+ --timeline-gutter-border: color-mix(in oklab, var(--color-text-0) 10%, transparent);
93
+ --timeline-text-primary: var(--color-text-0);
94
+ --timeline-text-secondary: var(--color-text-2);
95
+ --timeline-tick-text: var(--color-text-2);
96
+ --timeline-tick-major: color-mix(in oklab, var(--color-text-0) 10%, transparent);
97
+ --timeline-tick-minor: color-mix(in oklab, var(--color-text-0) 6%, transparent);
98
+ --timeline-clip-bg: light-dark(
99
+ color-mix(in oklab, var(--color-text-0) 12%, transparent),
100
+ color-mix(in oklab, var(--color-text-0) 13%, transparent)
101
+ );
102
+ --timeline-clip-label-active: light-dark(#0b3d2c, rgba(232, 255, 247, 0.95));
66
103
  --timeline-clip-label-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
67
- --timeline-clip-audio-bg: rgba(167, 139, 250, 0.16);
68
- --timeline-clip-audio-border: rgba(167, 139, 250, 0.4);
69
- --timeline-clip-audio-bg-hover: rgba(167, 139, 250, 0.24);
70
- --timeline-clip-audio-bg-dragging: rgba(60, 52, 84, 0.96);
104
+ /* Audio clips are a solid fill that carries white ink in both themes. */
105
+ --timeline-clip-audio-bg: oklch(0.45 0.12 300);
106
+ --timeline-clip-audio-border: oklch(0.37 0.12 300);
107
+ --timeline-clip-audio-bg-hover: oklch(0.49 0.12 300);
108
+ --timeline-clip-audio-bg-dragging: oklch(0.42 0.12 300 / 0.96);
71
109
  --timeline-clip-audio-muted-bg: rgb(72, 74, 78);
72
- --timeline-audio-link: #a0aaa4;
73
- --timeline-clip-selection: rgba(255, 255, 255, 0.85);
110
+ --timeline-audio-link: light-dark(#626d66, #a0aaa4);
111
+ --timeline-clip-selection: light-dark(#0f766e, rgba(255, 255, 255, 0.85));
74
112
  --timeline-clip-selection-highlight: rgb(255 255 255 / 0.55);
75
113
  --timeline-clip-radius: 8px;
76
114
  --timeline-clip-audio-radius: 21px;
@@ -79,7 +117,7 @@
79
117
  --timeline-clip-chip-bg: rgba(15, 22, 18, 0.73);
80
118
  --timeline-clip-chip-audio-bg: rgba(25, 16, 38, 0.7);
81
119
  --timeline-clip-chip-text: #ffffff;
82
- --timeline-shortcut-bg: rgba(17, 23, 35, 0.84);
120
+ --timeline-shortcut-bg: color-mix(in oklab, var(--color-raised) 94%, transparent);
83
121
  /* Composition and text clips draw their frame as it is, like video filmstrips; a host may dim them. */
84
122
  --timeline-composition-thumbnail-opacity: 1;
85
123
  --timeline-composition-thumbnail-blend: normal;
@@ -105,58 +143,82 @@
105
143
  transparent 2px 5px
106
144
  );
107
145
  --timeline-waveform-label-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
108
- --timeline-clip-bg-active: rgba(60, 230, 172, 0.2);
109
- --timeline-clip-bg-hover: rgba(255, 255, 255, 0.16);
110
- --timeline-clip-bg-dragging: rgba(38, 42, 52, 0.96);
111
- --timeline-clip-border: rgba(255, 255, 255, 0.22);
112
- --timeline-clip-border-hover: rgba(60, 230, 172, 0.75);
113
- --timeline-clip-border-active: rgba(60, 230, 172, 0.55);
114
- --timeline-handle: rgba(255, 255, 255, 0.55);
146
+ --timeline-clip-bg-active: color-mix(in oklab, var(--color-accent) 20%, transparent);
147
+ --timeline-clip-bg-hover: light-dark(
148
+ color-mix(in oklab, var(--color-text-0) 26%, transparent),
149
+ color-mix(in oklab, var(--color-text-0) 16%, transparent)
150
+ );
151
+ --timeline-clip-bg-dragging: color-mix(in oklab, var(--color-raised) 96%, transparent);
152
+ --timeline-clip-border: light-dark(
153
+ color-mix(in oklab, var(--color-text-0) 40%, transparent),
154
+ color-mix(in oklab, var(--color-text-0) 30%, transparent)
155
+ );
156
+ --timeline-clip-border-hover: color-mix(in oklab, var(--color-accent) 75%, transparent);
157
+ --timeline-clip-border-active: light-dark(
158
+ color-mix(in oklab, var(--color-accent) 90%, transparent),
159
+ color-mix(in oklab, var(--color-accent) 55%, transparent)
160
+ );
161
+ --timeline-handle: var(--color-text-0);
115
162
  /* Audio clip fades: the shaded wedge over the faded gain, and the corner dots. */
116
163
  --timeline-fade-shade: rgba(0, 0, 0, 0.38);
117
164
  --timeline-fade-dot: #fff;
118
165
  --timeline-fade-dot-ring: rgba(0, 0, 0, 0.55);
119
- --timeline-resize-seam: rgba(255, 255, 255, 0.12);
120
- --timeline-resize-active: rgba(255, 255, 255, 0.24);
121
- --timeline-track-clip-fill: rgba(255, 255, 255, 0.055);
122
- --timeline-track-clip-active: rgba(60, 230, 172, 0.16);
123
- --timeline-track-label: rgba(255, 255, 255, 0.5);
124
- --timeline-border-strong: rgba(255, 255, 255, 0.2);
125
- --timeline-group-member-tint: rgba(255, 255, 255, 0.035);
126
- --timeline-overlay-text: rgba(255, 255, 255, 0.8);
127
- --timeline-accent: #3ce6ac;
128
- --timeline-accent-soft: rgba(60, 230, 172, 0.18);
129
- --timeline-accent-faint: rgba(60, 230, 172, 0.055);
130
- --timeline-accent-fill: rgba(60, 230, 172, 0.1);
131
- --timeline-accent-glow: rgba(60, 230, 172, 0.5);
132
- --timeline-accent-border: rgba(60, 230, 172, 0.7);
133
- --timeline-accent-rail: rgba(60, 230, 172, 0.35);
134
- --timeline-accent-hover: rgba(60, 230, 172, 0.25);
135
- --timeline-accent-button-bg: rgba(60, 230, 172, 0.15);
136
- --timeline-danger: rgba(239, 68, 68, 0.7);
166
+ --timeline-resize-seam: color-mix(in oklab, var(--color-text-0) 12%, transparent);
167
+ --timeline-resize-active: color-mix(in oklab, var(--color-text-0) 24%, transparent);
168
+ --timeline-track-clip-fill: color-mix(in oklab, var(--color-text-0) 8%, transparent);
169
+ --timeline-track-clip-active: color-mix(in oklab, var(--color-accent) 20%, transparent);
170
+ --timeline-track-label: var(--color-text-muted);
171
+ --timeline-border-strong: color-mix(in oklab, var(--color-text-0) 20%, transparent);
172
+ --timeline-group-member-tint: color-mix(in oklab, var(--color-text-0) 3.5%, transparent);
173
+ --timeline-overlay-text: var(--color-text-2);
174
+ --timeline-accent: var(--color-accent);
175
+ --timeline-accent-soft: color-mix(in oklab, var(--color-accent) 18%, transparent);
176
+ --timeline-accent-faint: color-mix(in oklab, var(--color-accent) 5.5%, transparent);
177
+ --timeline-accent-fill: color-mix(in oklab, var(--color-accent) 10%, transparent);
178
+ --timeline-accent-glow: color-mix(in oklab, var(--color-accent) 50%, transparent);
179
+ --timeline-accent-border: color-mix(in oklab, var(--color-accent) 70%, transparent);
180
+ --timeline-accent-rail: color-mix(in oklab, var(--color-accent) 35%, transparent);
181
+ --timeline-accent-hover: var(--color-on-hover);
182
+ --timeline-accent-button-bg: var(--color-on);
183
+ --timeline-danger: color-mix(in oklab, var(--color-danger) 70%, transparent);
137
184
  --timeline-info-bg: rgba(59, 130, 246, 0.12);
138
185
  --timeline-info-border: rgba(59, 130, 246, 0.4);
139
- --timeline-dialog-bg: #1b1b1f;
140
- --timeline-diamond-bg: #171717;
141
- --timeline-diamond-border: rgba(255, 255, 255, 0.14);
142
- --timeline-text-solid: #ffffff;
143
- --timeline-text-faint: rgba(255, 255, 255, 0.35);
144
- --timeline-text-dim: rgba(255, 255, 255, 0.4);
145
- --timeline-text-soft: rgba(255, 255, 255, 0.75);
146
- --timeline-text-bright: rgba(255, 255, 255, 0.7);
147
- --timeline-snap-guide: rgba(255, 255, 255, 0.6);
148
- --timeline-overlay-bg: rgba(0, 0, 0, 0.8);
149
- --timeline-overlay-bg-strong: rgba(0, 0, 0, 0.85);
150
- --timeline-input-bg: rgba(0, 0, 0, 0.3);
151
- --timeline-automation-rail: rgba(255, 255, 255, 0.08);
152
- --timeline-automation-point-muted: rgba(0, 0, 0, 0.5);
153
- --timeline-diamond-muted: #a3a3a3;
186
+ --timeline-dialog-bg: var(--color-raised);
187
+ --timeline-diamond-bg: var(--color-raised);
188
+ --timeline-diamond-border: color-mix(in oklab, var(--color-text-0) 14%, transparent);
189
+ --timeline-text-solid: var(--color-text-0);
190
+ --timeline-text-faint: var(--color-text-off);
191
+ --timeline-text-dim: var(--color-text-muted);
192
+ --timeline-text-soft: var(--color-text-2);
193
+ --timeline-text-bright: var(--color-text-2);
194
+ --timeline-snap-guide: color-mix(in oklab, var(--color-text-0) 60%, transparent);
195
+ --timeline-overlay-bg: light-dark(oklch(1 0 70 / 0.9), rgba(0, 0, 0, 0.8));
196
+ --timeline-overlay-bg-strong: light-dark(oklch(1 0 70 / 0.95), rgba(0, 0, 0, 0.85));
197
+ --timeline-input-bg: light-dark(
198
+ color-mix(in oklab, var(--color-text-0) 5%, transparent),
199
+ rgba(0, 0, 0, 0.3)
200
+ );
201
+ --timeline-automation-rail: color-mix(in oklab, var(--color-text-0) 8%, transparent);
202
+ --timeline-automation-point-muted: light-dark(
203
+ color-mix(in oklab, var(--color-text-0) 30%, transparent),
204
+ rgba(0, 0, 0, 0.5)
205
+ );
206
+ --timeline-diamond-muted: var(--color-text-muted);
154
207
  --timeline-beat: rgb(34, 197, 94);
155
- --timeline-clip-shadow-dragging: rgba(0, 0, 0, 0.4);
156
- --timeline-playhead-glow: rgba(60, 230, 172, 0.14);
157
- --timeline-playhead-shadow: rgba(0, 0, 0, 0.55);
158
- --timeline-transition-zone: rgba(255, 255, 255, 0.2);
159
- --timeline-transition-badge: rgba(237, 244, 239, 0.98);
208
+ --timeline-clip-shadow-dragging: light-dark(
209
+ color-mix(in oklab, var(--color-text-0) 16%, transparent),
210
+ rgba(0, 0, 0, 0.4)
211
+ );
212
+ --timeline-playhead-glow: color-mix(in oklab, var(--color-accent) 14%, transparent);
213
+ --timeline-playhead-shadow: light-dark(
214
+ color-mix(in oklab, var(--color-text-0) 20%, transparent),
215
+ rgba(0, 0, 0, 0.55)
216
+ );
217
+ --timeline-transition-zone: light-dark(
218
+ color-mix(in oklab, var(--color-text-0) 12%, transparent),
219
+ color-mix(in oklab, var(--color-text-0) 20%, transparent)
220
+ );
221
+ --timeline-transition-badge: light-dark(#ffffff, rgba(237, 244, 239, 0.98));
160
222
  --timeline-transition-badge-ink: rgba(36, 56, 45, 0.96);
161
223
 
162
224
  /* -------------------------------------------------------------- geometry */
@@ -197,14 +259,16 @@
197
259
 
198
260
  /* ---------------------------------------------------------------- shadow */
199
261
 
200
- /* Floating chrome over a near-black canvas: the hairline ring does the edge
201
- * definition that a light-mode drop shadow cannot. */
202
- --shadow-menu: 0 8px 24px rgb(0 0 0 / 0.45), 0 0 0 1px rgb(0 0 0 / 0.4);
203
- --shadow-popover: 0 16px 40px rgb(0 0 0 / 0.55), 0 0 0 1px rgb(0 0 0 / 0.45);
262
+ /* Floating chrome: a drop shadow plus a hairline ring that defines the edge. */
263
+ --shadow-menu:
264
+ 0 8px 24px light-dark(rgb(0 0 0 / 0.12), rgb(0 0 0 / 0.45)),
265
+ 0 0 0 1px light-dark(rgb(0 0 0 / 0.07), rgb(0 0 0 / 0.4));
266
+ --shadow-popover:
267
+ 0 16px 40px light-dark(rgb(0 0 0 / 0.14), rgb(0 0 0 / 0.55)),
268
+ 0 0 0 1px light-dark(rgb(0 0 0 / 0.07), rgb(0 0 0 / 0.45));
204
269
 
205
- /* The primary button is the one light surface in a dark UI, so it reads as a
206
- * raised key rather than a floating panel: a tight contact shadow, a soft
207
- * ambient one, and an inner top highlight. */
270
+ /* The primary button reads as a raised key rather than a floating panel: a tight
271
+ * contact shadow, a soft ambient one, and an inner top highlight. */
208
272
  --shadow-btn-primary:
209
273
  0 1px 2px rgb(0 0 0 / 0.6), 0 2px 6px rgb(0 0 0 / 0.35), inset 0 1px 0 rgb(255 255 255 / 0.65);
210
274
 
@@ -277,9 +341,9 @@
277
341
  * strip sits below the card body and the shown tab is a fill in the body colour. */
278
342
  --panel-shell-bg: var(--color-bg-1);
279
343
  --panel-card-bg: var(--color-surface);
280
- --panel-card-border: #303034;
344
+ --panel-card-border: var(--color-border-strong);
281
345
  --panel-strip-bg: var(--color-bg-0);
282
- --panel-tab-bg-hover: #202023;
346
+ --panel-tab-bg-hover: var(--color-hover);
283
347
 
284
348
  /* Names Studio's markup invented that no config ever defined, so the classes
285
349
  * compiled to nothing. Aliased to the token that was meant, rather than
@@ -291,9 +355,9 @@
291
355
 
292
356
  /* ------------------------------------------- deprecated: Tailwind palette */
293
357
 
294
- /* Verbatim Tailwind 4.3.3 defaults for stock colours markup still names, so
295
- * `--color-*: initial` does not blank them. U12 deletes this block;
296
- * `theme.test.ts` fails if a value drifts from upstream. */
358
+ /* Stock colours markup still names, so `--color-*: initial` does not blank them. U12 deletes
359
+ * this block. The neutral scale is Graphite's roles by the job each step does in markup (light
360
+ * steps text, dark steps surfaces and lines); the rest are verbatim Tailwind 4.3.3 defaults. */
297
361
  --color-amber-50: oklch(98.7% 0.022 95.277);
298
362
  --color-amber-100: oklch(96.2% 0.059 95.617);
299
363
  --color-amber-200: oklch(92.4% 0.12 95.746);
@@ -315,17 +379,17 @@
315
379
  --color-green-400: oklch(79.2% 0.209 151.711);
316
380
  --color-green-500: oklch(72.3% 0.219 149.579);
317
381
  --color-green-600: oklch(62.7% 0.194 149.214);
318
- --color-neutral-50: oklch(98.5% 0 none);
319
- --color-neutral-100: oklch(97% 0 none);
320
- --color-neutral-200: oklch(92.2% 0 none);
321
- --color-neutral-300: oklch(87% 0 none);
322
- --color-neutral-400: oklch(70.8% 0 none);
323
- --color-neutral-500: oklch(55.6% 0 none);
324
- --color-neutral-600: oklch(43.9% 0 none);
325
- --color-neutral-700: oklch(37.1% 0 none);
326
- --color-neutral-800: oklch(26.9% 0 none);
327
- --color-neutral-900: oklch(20.5% 0 none);
328
- --color-neutral-950: oklch(14.5% 0 none);
382
+ --color-neutral-50: var(--color-text-0);
383
+ --color-neutral-100: var(--color-text-0);
384
+ --color-neutral-200: var(--color-text-0);
385
+ --color-neutral-300: var(--color-text-2);
386
+ --color-neutral-400: var(--color-text-2);
387
+ --color-neutral-500: var(--color-text-muted);
388
+ --color-neutral-600: var(--color-text-muted);
389
+ --color-neutral-700: var(--color-border-strong);
390
+ --color-neutral-800: var(--color-border);
391
+ --color-neutral-900: var(--color-surface);
392
+ --color-neutral-950: var(--color-bg-0);
329
393
  --color-orange-300: oklch(83.7% 0.128 66.29);
330
394
  --color-orange-400: oklch(75% 0.183 55.934);
331
395
  --color-pink-400: oklch(71.8% 0.202 349.761);
@@ -359,31 +423,24 @@
359
423
  --color-white: #fff;
360
424
  }
361
425
 
362
- /* One paper block. A host sets data-theme="paper" on the document element. */
426
+ /* The colour-scheme picks each token's light or dark half: dark unless the document element
427
+ * has data-theme="paper". Base layer, so a host's own colour-scheme wins. */
428
+ @layer base {
429
+ :root {
430
+ color-scheme: dark;
431
+ }
432
+ :root:where([data-theme="paper"]) {
433
+ color-scheme: light;
434
+ }
435
+ }
363
436
  :root[data-theme="paper"] {
364
- --timeline-shell-bg: #f4f6f3;
365
- --timeline-row-bg: #edf0ed;
366
- --timeline-clip-bg: #c9d1cb;
437
+ --timeline-clip-label-shadow: none;
367
438
  --timeline-clip-shadow: 0 2px 6px rgb(0 0 0 / 0.12);
368
- --timeline-clip-highlight: rgb(255 255 255 / 0.08);
369
- --timeline-clip-selection: #0f766e;
370
- --timeline-clip-selection-highlight: rgb(255 255 255 / 0.55);
371
- --timeline-clip-chip-bg: rgba(15, 22, 18, 0.73);
372
- --timeline-clip-chip-audio-bg: rgba(25, 16, 38, 0.7);
373
- --timeline-clip-chip-text: #ffffff;
374
- --timeline-clip-audio-bg: rgb(150, 128, 180);
375
- --timeline-clip-audio-bg-hover: rgb(135, 109, 170);
376
- --timeline-clip-audio-bg-dragging: rgb(232, 224, 242);
377
- --timeline-clip-audio-border: rgba(113, 80, 155, 0.45);
378
- --timeline-clip-audio-muted-bg: rgb(156, 161, 157);
379
- --timeline-audio-link: #626d66;
380
- --timeline-waveform-bar-rgb: 20, 12, 32;
381
- --timeline-waveform-muted-rgb: 24, 28, 26;
382
- --timeline-waveform-baseline-rgb: 76, 62, 88;
383
- --timeline-waveform-error: repeating-linear-gradient(
439
+ --timeline-thumbnail-shimmer: linear-gradient(
384
440
  90deg,
385
- rgba(20, 12, 32, 0.35) 0 2px,
386
- transparent 2px 5px
441
+ rgba(24, 24, 27, 0.02) 0%,
442
+ rgba(24, 24, 27, 0.05) 50%,
443
+ rgba(24, 24, 27, 0.02) 100%
387
444
  );
388
445
  }
389
446
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  /** Guards the ways `theme.css` can silently break: a dropped CSS custom
4
4
  * property, a utility that stops compiling, the stock Tailwind palette
5
- * leaking back in, or the JS preset / legacy colours drifting from it. */
5
+ * leaking back in, or the legacy colours drifting from it. */
6
6
 
7
7
  import { readFileSync } from "node:fs";
8
8
  import path from "node:path";
@@ -11,7 +11,6 @@ import { createRoot } from "react-dom/client";
11
11
  import { Gear, IconContext } from "@phosphor-icons/react";
12
12
  import { compile } from "tailwindcss";
13
13
  import { afterEach, describe, expect, it } from "vitest";
14
- import studioPreset from "./tailwind-preset.shared.js";
15
14
  import { readIconTokens } from "./iconTokens";
16
15
  import { loadStylesheet, STYLES_DIR, TAILWIND_DIR } from "./styleSources";
17
16
 
@@ -52,7 +51,9 @@ describe("studio theme", () => {
52
51
  it("emits the semantic palette as custom properties and as utilities", async () => {
53
52
  const css = await build("studio.css", ["bg-accent", "text-text-2", "border-border"]);
54
53
 
55
- expect(rootVariables(css).get("--color-accent")).toBe("#3ce6ac");
54
+ expect(rootVariables(css).get("--color-accent")).toBe(
55
+ "light-dark(oklch(0.536 0.114 164), oklch(0.82 0.159 164))",
56
+ );
56
57
  expect(css).toContain(".bg-accent {");
57
58
  expect(css).toContain("background-color: var(--color-accent)");
58
59
  });
@@ -127,7 +128,7 @@ describe("studio theme", () => {
127
128
  expect(css).toContain(".duration-open {");
128
129
  });
129
130
 
130
- it("keeps every legacy Tailwind palette entry at its upstream default value", async () => {
131
+ it("keeps every legacy Tailwind palette entry that is not a role at its upstream value", async () => {
131
132
  // These are copies of Tailwind's own values, kept only so existing markup
132
133
  // renders unchanged. A Tailwind upgrade that moves one of them would
133
134
  // otherwise silently change Studio's colors.
@@ -138,7 +139,9 @@ describe("studio theme", () => {
138
139
  ),
139
140
  ].map(([, name, value]) => [name, value.trim()]),
140
141
  );
141
- const legacy = [...themeSource.matchAll(/\n\s*(--color-[a-z]+-(?:50|\d00|950)):\s*([^;]+);/g)];
142
+ const legacy = [
143
+ ...themeSource.matchAll(/\n\s*(--color-[a-z]+-(?:50|\d00|950)):\s*([^;]+);/g),
144
+ ].filter(([, , value]) => !value.trim().startsWith("var("));
142
145
 
143
146
  expect(legacy.length).toBeGreaterThan(0);
144
147
  for (const [, name, value] of legacy) {
@@ -147,11 +150,12 @@ describe("studio theme", () => {
147
150
  }
148
151
  });
149
152
 
150
- it("keeps the deprecated JS preset in step with the CSS it shadows", () => {
151
- const colors = studioPreset.theme.extend.colors;
153
+ it("maps every neutral step onto a Graphite role, so the stock scale follows the theme", () => {
154
+ const steps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
152
155
 
153
- expect(colors.studio.accent.toLowerCase()).toBe(declaredValue("--color-accent"));
154
- expect(colors.panel.surface.toLowerCase()).toBe(declaredValue("--color-surface"));
156
+ for (const step of steps) {
157
+ expect(declaredValue(`--color-neutral-${step}`)).toMatch(/^var\(--color-[a-z0-9-]+\)$/);
158
+ }
155
159
  });
156
160
 
157
161
  it("reads the icon defaults off the theme rather than hard-coding them", () => {
@@ -8,15 +8,47 @@ export type { BlockCategory };
8
8
  export { BLOCK_CATEGORIES, resolveBlockCategory };
9
9
 
10
10
  const COLOR_MAP: Record<BlockCategory, { bg: string; text: string; dot: string }> = {
11
- transitions: { bg: "bg-blue-500/15", text: "text-blue-400", dot: "bg-blue-400" },
12
- vfx: { bg: "bg-purple-500/15", text: "text-purple-400", dot: "bg-purple-400" },
13
- social: { bg: "bg-pink-500/15", text: "text-pink-400", dot: "bg-pink-400" },
14
- data: { bg: "bg-green-500/15", text: "text-green-400", dot: "bg-green-400" },
15
- scenes: { bg: "bg-amber-500/15", text: "text-amber-400", dot: "bg-amber-400" },
16
- captions: { bg: "bg-cyan-500/15", text: "text-cyan-400", dot: "bg-cyan-400" },
17
- effects: { bg: "bg-rose-500/15", text: "text-rose-400", dot: "bg-rose-400" },
18
- "text-effects": { bg: "bg-violet-500/15", text: "text-violet-400", dot: "bg-violet-400" },
19
- "code-animation": { bg: "bg-emerald-500/15", text: "text-emerald-400", dot: "bg-emerald-400" },
11
+ transitions: {
12
+ bg: "bg-blue-500/15",
13
+ text: "text-[light-dark(oklch(0.48_0.12_255),var(--color-blue-400))]",
14
+ dot: "bg-[light-dark(oklch(0.48_0.12_255),var(--color-blue-400))]",
15
+ },
16
+ vfx: {
17
+ bg: "bg-purple-500/15",
18
+ text: "text-[light-dark(oklch(0.48_0.12_305),var(--color-purple-400))]",
19
+ dot: "bg-[light-dark(oklch(0.48_0.12_305),var(--color-purple-400))]",
20
+ },
21
+ social: {
22
+ bg: "bg-pink-500/15",
23
+ text: "text-[light-dark(oklch(0.48_0.12_350),var(--color-pink-400))]",
24
+ dot: "bg-[light-dark(oklch(0.48_0.12_350),var(--color-pink-400))]",
25
+ },
26
+ data: {
27
+ bg: "bg-green-500/15",
28
+ text: "text-[light-dark(oklch(0.48_0.12_152),var(--color-green-400))]",
29
+ dot: "bg-[light-dark(oklch(0.48_0.12_152),var(--color-green-400))]",
30
+ },
31
+ scenes: { bg: "bg-amber-500/15", text: "text-warning-ink", dot: "bg-warning-ink" },
32
+ captions: {
33
+ bg: "bg-cyan-500/15",
34
+ text: "text-[light-dark(oklch(0.48_0.12_212),var(--color-cyan-400))]",
35
+ dot: "bg-[light-dark(oklch(0.48_0.12_212),var(--color-cyan-400))]",
36
+ },
37
+ effects: {
38
+ bg: "bg-rose-500/15",
39
+ text: "text-[light-dark(oklch(0.48_0.12_13),var(--color-rose-400))]",
40
+ dot: "bg-[light-dark(oklch(0.48_0.12_13),var(--color-rose-400))]",
41
+ },
42
+ "text-effects": {
43
+ bg: "bg-violet-500/15",
44
+ text: "text-[light-dark(oklch(0.48_0.12_294),var(--color-violet-400))]",
45
+ dot: "bg-[light-dark(oklch(0.48_0.12_294),var(--color-violet-400))]",
46
+ },
47
+ "code-animation": {
48
+ bg: "bg-emerald-500/15",
49
+ text: "text-[light-dark(oklch(0.48_0.12_163),var(--color-emerald-400))]",
50
+ dot: "bg-[light-dark(oklch(0.48_0.12_163),var(--color-emerald-400))]",
51
+ },
20
52
  };
21
53
 
22
54
  export function getCategoryColors(category: BlockCategory) {
@@ -22,6 +22,7 @@ export type ClipboardPayload =
22
22
  kind: "dom-element";
23
23
  html: string;
24
24
  sourceFile: string;
25
+ projectId?: string;
25
26
  originSelector?: string;
26
27
  originSelectorIndex?: number;
27
28
  };
@@ -70,6 +71,7 @@ export function deserializeClipboardPayload(json: string): ClipboardPayload | nu
70
71
  kind: "dom-element",
71
72
  html: obj.html,
72
73
  sourceFile: obj.sourceFile,
74
+ projectId: typeof obj.projectId === "string" ? obj.projectId : undefined,
73
75
  originSelector: typeof obj.originSelector === "string" ? obj.originSelector : undefined,
74
76
  originSelectorIndex:
75
77
  typeof obj.originSelectorIndex === "number" ? obj.originSelectorIndex : undefined,