diff --git a/crates/snowbound/assets/icon/Snowbound-Sequoia.icns b/crates/snowbound/assets/icon/Snowbound-Sequoia.icns
new file mode 100644
index 0000000000000000000000000000000000000000..b0c6a23c678b25cd60ae9f87c8e02982d9747953
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-Sequoia.icns differ
diff --git a/crates/snowbound/assets/icon/Snowbound-Sequoia.png b/crates/snowbound/assets/icon/Snowbound-Sequoia.png
new file mode 100644
index 0000000000000000000000000000000000000000..26b874f31bbc9792cf3e60ecb96dc4d8fc602778
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-Sequoia.png differ
diff --git a/crates/snowbound/assets/icon/Snowbound-SnowLeopard.icns b/crates/snowbound/assets/icon/Snowbound-SnowLeopard.icns
new file mode 100644
index 0000000000000000000000000000000000000000..3be15b3d51337b1ef0701d07c73c1521e78a3c6a
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-SnowLeopard.icns differ
diff --git a/crates/snowbound/assets/icon/Snowbound-SnowLeopard.png b/crates/snowbound/assets/icon/Snowbound-SnowLeopard.png
new file mode 100644
index 0000000000000000000000000000000000000000..8d1229a52814ab39bf024eb4a0518bdb49aa0973
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-SnowLeopard.png differ
diff --git a/crates/snowbound/assets/icon/Snowbound-Tahoe-Dark.png b/crates/snowbound/assets/icon/Snowbound-Tahoe-Dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..0604b1dbf609de476d2a2a2e1b43e1e201b077c6
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-Tahoe-Dark.png differ
diff --git a/crates/snowbound/assets/icon/Snowbound-Tahoe-Mono.png b/crates/snowbound/assets/icon/Snowbound-Tahoe-Mono.png
new file mode 100644
index 0000000000000000000000000000000000000000..58cb7a26b7d89b2238b3805fe604a3b6d54579de
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-Tahoe-Mono.png differ
diff --git a/crates/snowbound/assets/icon/Snowbound-Tahoe.icns b/crates/snowbound/assets/icon/Snowbound-Tahoe.icns
new file mode 100644
index 0000000000000000000000000000000000000000..8e5fbb8b3e3b23359fb4cc7e89fcdfac258babd2
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-Tahoe.icns differ
diff --git a/crates/snowbound/assets/icon/Snowbound-Tahoe.png b/crates/snowbound/assets/icon/Snowbound-Tahoe.png
new file mode 100644
index 0000000000000000000000000000000000000000..4d6a2e7b7a686a040a218320dd9a14c076d1577e
Binary files /dev/null and b/crates/snowbound/assets/icon/Snowbound-Tahoe.png differ
diff --git a/crates/snowbound/assets/icon/renders/Sequoia.exr b/crates/snowbound/assets/icon/renders/Sequoia.exr
new file mode 100644
index 0000000000000000000000000000000000000000..dd56fcd0105fa0efb0a93fbbae51ebd034aaba14
Binary files /dev/null and b/crates/snowbound/assets/icon/renders/Sequoia.exr differ
diff --git a/crates/snowbound/assets/icon/renders/Sequoia.png b/crates/snowbound/assets/icon/renders/Sequoia.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9242ce66a9c4d27606c72feaf620fae79386844
Binary files /dev/null and b/crates/snowbound/assets/icon/renders/Sequoia.png differ
diff --git a/crates/snowbound/assets/icon/renders/SnowLeopard.exr b/crates/snowbound/assets/icon/renders/SnowLeopard.exr
new file mode 100644
index 0000000000000000000000000000000000000000..b4fa056cd0c21c3d2c09d7cd3d0dda043c9d0aba
Binary files /dev/null and b/crates/snowbound/assets/icon/renders/SnowLeopard.exr differ
diff --git a/crates/snowbound/assets/icon/renders/SnowLeopard.png b/crates/snowbound/assets/icon/renders/SnowLeopard.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce47b950549da546efa1d175c5f9b0b410d620f3
Binary files /dev/null and b/crates/snowbound/assets/icon/renders/SnowLeopard.png differ
diff --git a/crates/snowbound/assets/icon/showcase.png b/crates/snowbound/assets/icon/showcase.png
new file mode 100644
index 0000000000000000000000000000000000000000..8743c26a682f1606c8e399c96f82626f55c96889
Binary files /dev/null and b/crates/snowbound/assets/icon/showcase.png differ
diff --git a/crates/snowbound/assets/icon/sources/Snowbound-Finishing.comp b/crates/snowbound/assets/icon/sources/Snowbound-Finishing.comp
new file mode 100755
index 0000000000000000000000000000000000000000..548d7941b32f40e7cd8ee5f5755ba34e96b3b1a6
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/Snowbound-Finishing.comp
@@ -0,0 +1,614 @@
+Composition {
+ CurrentTime = 0,
+ RenderRange = { 0, 0 },
+ GlobalRange = { 0, 1 },
+ CurrentID = 72,
+ HiQ = true,
+ PlaybackUpdateMode = 0,
+ StereoMode = false,
+ Version = "Fusion Studio 20.3.1 build 5",
+ SavedOutputs = 0,
+ HeldTools = 0,
+ DisabledTools = 0,
+ LockedTools = 0,
+ AudioOffset = 0,
+ Resumable = true,
+ OutputClips = {
+ "Comp:/../Snowbound-Sequoia0000.png",
+ "Comp:/../Snowbound-SnowLeopard0000.png"
+ },
+ Tools = {
+ Notebook_2010 = Loader {
+ Clips = {
+ Clip {
+ ID = "Clip1",
+ Filename = "Comp:/../renders/SnowLeopard.png",
+ FormatID = "PNGFormat",
+ StartFrame = -1,
+ LengthSetManually = true,
+ TrimIn = 0,
+ TrimOut = 0,
+ ExtendFirst = 0,
+ ExtendLast = 0,
+ Loop = 0,
+ AspectMode = 0,
+ Depth = 0,
+ TimeCode = 0,
+ GlobalStart = 0,
+ GlobalEnd = 0
+ }
+ },
+ CtrlWZoom = false,
+ Inputs = {
+ ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
+ ["Clip1.PNGFormat.PostMultiply"] = Input { Value = 1, }
+ },
+ ViewInfo = OperatorInfo { Pos = { 55, 82.197 } },
+ },
+ Notebook_15 = Loader {
+ Clips = {
+ Clip {
+ ID = "Clip1",
+ Filename = "Comp:/../renders/Sequoia.png",
+ FormatID = "PNGFormat",
+ StartFrame = -1,
+ LengthSetManually = true,
+ TrimIn = 0,
+ TrimOut = 0,
+ ExtendFirst = 0,
+ ExtendLast = 0,
+ Loop = 0,
+ AspectMode = 0,
+ Depth = 0,
+ TimeCode = 0,
+ GlobalStart = 0,
+ GlobalEnd = 0
+ }
+ },
+ Inputs = {
+ ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
+ ["Clip1.PNGFormat.PostMultiply"] = Input { Value = 1, }
+ },
+ ViewInfo = OperatorInfo { Pos = { 55, 148.197 } },
+ },
+ Dock_shadow_2010 = Shadow {
+ Inputs = {
+ ShadowOffset = Input { Value = { 0.503, 0.494 }, },
+ Softness = Input { Value = 0.012, },
+ Alpha = Input { Value = 0.25, },
+ Input = Input {
+ SourceOp = "Finish_2010",
+ Source = "Output",
+ }
+ },
+ ViewInfo = OperatorInfo { Pos = { 495, 82.197 } },
+ },
+ Export_15 = Saver {
+ CtrlWZoom = false,
+ Inputs = {
+ ["OpenEXRFormat.ZipCompressionLevel"] = Input {
+ Value = Number {
+ Value = 4
+ },
+ },
+ ProcessWhenBlendIs00 = Input { Value = 0, },
+ Clip = Input {
+ Value = Clip {
+ Filename = "Comp:/../Snowbound-Sequoia0000.png",
+ FormatID = "PNGFormat",
+ Saving = true,
+ LengthSetManually = true,
+ TrimIn = 0,
+ TrimOut = 0,
+ ExtendFirst = 0,
+ ExtendLast = 0,
+ Loop = 1,
+ AspectMode = 0,
+ Depth = 0,
+ TimeCode = 0,
+ GlobalStart = 0,
+ GlobalEnd = 0
+ },
+ },
+ OutputFormat = Input { Value = FuID { "PNGFormat" }, },
+ ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
+ Input = Input {
+ SourceOp = "Dock_shadow_15",
+ Source = "Output",
+ },
+ ["PNGFormat.PreDivide"] = Input { Value = 1, }
+ },
+ ViewInfo = OperatorInfo { Pos = { 715, 148.197 } },
+ },
+ Finish_2010 = ColorCorrector {
+ CtrlWZoom = false,
+ Inputs = {
+ ColorRanges = Input {
+ Value = ColorCurves {
+ Curves = {
+ {
+ Points = {
+ { 0, 1 },
+ { 0.4, 0.2 },
+ { 0.6, 0 },
+ { 1, 0 }
+ }
+ },
+ {
+ Points = {
+ { 0, 0 },
+ { 0.4, 0 },
+ { 0.6, 0.2 },
+ { 1, 1 }
+ }
+ }
+ }
+ },
+ },
+ PreDividePostMultiply = Input { Value = 1, },
+ HistogramIgnoreTransparent = Input { Value = 1, },
+ Input = Input {
+ SourceOp = "Notebook_2010",
+ Source = "Output",
+ }
+ },
+ ViewInfo = OperatorInfo { Pos = { 275, 82.197 } },
+ },
+ Finish_15 = ColorCorrector {
+ CtrlWZoom = false,
+ Inputs = {
+ ColorRanges = Input {
+ Value = ColorCurves {
+ Curves = {
+ {
+ Points = {
+ { 0, 1 },
+ { 0.4, 0.2 },
+ { 0.6, 0 },
+ { 1, 0 }
+ }
+ },
+ {
+ Points = {
+ { 0, 0 },
+ { 0.4, 0 },
+ { 0.6, 0.2 },
+ { 1, 1 }
+ }
+ }
+ }
+ },
+ },
+ PreDividePostMultiply = Input { Value = 1, },
+ HistogramIgnoreTransparent = Input { Value = 1, },
+ Input = Input {
+ SourceOp = "Notebook_15",
+ Source = "Output",
+ }
+ },
+ ViewInfo = OperatorInfo { Pos = { 275, 148.197 } },
+ },
+ Export_2010 = Saver {
+ Inputs = {
+ ["OpenEXRFormat.ZipCompressionLevel"] = Input {
+ Value = Number {
+ Value = 4
+ },
+ },
+ ProcessWhenBlendIs00 = Input { Value = 0, },
+ Clip = Input {
+ Value = Clip {
+ Filename = "Comp:/../Snowbound-SnowLeopard0000.png",
+ FormatID = "PNGFormat",
+ Saving = true,
+ LengthSetManually = true,
+ TrimIn = 0,
+ TrimOut = 0,
+ ExtendFirst = 0,
+ ExtendLast = 0,
+ Loop = 1,
+ AspectMode = 0,
+ Depth = 0,
+ TimeCode = 0,
+ GlobalStart = 0,
+ GlobalEnd = 0
+ },
+ },
+ OutputFormat = Input { Value = FuID { "PNGFormat" }, },
+ ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
+ Input = Input {
+ SourceOp = "Dock_shadow_2010",
+ Source = "Output",
+ },
+ ["PNGFormat.PreDivide"] = Input { Value = 1, }
+ },
+ ViewInfo = OperatorInfo { Pos = { 715, 82.197 } },
+ },
+ Dock_shadow_15 = Shadow {
+ Inputs = {
+ ShadowOffset = Input { Value = { 0.503, 0.494 }, },
+ Softness = Input { Value = 0.012, },
+ Alpha = Input { Value = 0.25, },
+ Input = Input {
+ SourceOp = "Finish_15",
+ Source = "Output",
+ }
+ },
+ ViewInfo = OperatorInfo { Pos = { 495, 148.197 } },
+ }
+ },
+ Frames = {
+ {
+ FrameTypeID = "ChildFrame",
+ Mode = 3,
+ LayoutPreset = 0,
+ PresetName = "Default",
+ Left = 0,
+ Top = 27,
+ Width = 1280,
+ Height = 644,
+ ZoneInfo = {
+ AuxRight = { Expanded = true },
+ ["!Left"] = {
+ },
+ AuxLeft = { Expanded = true },
+ Right = { Expanded = true, },
+ Left = { Expanded = false, },
+ ["!Right"] = {
+ }
+ },
+ ViewInfo = {
+ Viewer1 = { Show = true, RatioY = 0.01, RatioX = 1, },
+ InnerLeft = {
+ },
+ MainSplit = {
+ RatioX = 100,
+ RatioY = 0.998344370860927,
+ },
+ CenterSplit = {
+ RatioX = 1,
+ RatioY = 100,
+ },
+ Viewer2 = { Show = true, RatioY = 0.01, RatioX = 1, },
+ Comments = { Show = false },
+ Time = { Show = true, RatioX = 100, },
+ InnerColumns = {
+ RatioX = 100,
+ RatioY = 2.00165562913907,
+ },
+ Keyframes = { Show = true, Adjust = false, RatioY = 100, MRU = 2, RatioX = 0.999999999999999, },
+ LayoutStrip = { Show = true, RatioX = 100, },
+ Inspector = { Show = true, RatioY = 1, RatioX = 100, },
+ InnerRight = {
+ },
+ MediaPool = { Show = false, },
+ OuterColumns = {
+ RatioX = 100,
+ RatioY = 1,
+ },
+ Effects = { Show = false, },
+ ActionStrip = { Show = false, Adjust = true, MRU = 0, RatioX = 100, },
+ Metadata = { Show = false, },
+ OuterLeft = {
+ },
+ ViewerSplit = {
+ RatioX = 100,
+ RatioY = 1,
+ },
+ Nodes = { Show = true, RatioY = 100, RatioX = 0.999999999999999, },
+ OuterRight = {
+ PixelX = 420,
+ RatioY = 100,
+ },
+ Clips = { Show = false, },
+ Spline = { Show = true, Adjust = false, RatioY = 100, MRU = 1, RatioX = 0.999999999999999, }
+ },
+ Views = ordered() {
+ Effects = MultiView {
+ Active = "EffectView",
+ ViewList = ordered() {
+ EffectView = "EffectView"
+ },
+ },
+ Nodes = MultiView {
+ Active = "FlowView",
+ ViewList = ordered() {
+ FlowView = "FlowView"
+ },
+ FlowView = FlowView {
+ Flags = {
+ Navigator = true,
+ AutoHideNavigator = true,
+ AutoSnap = true,
+ RemoveRouters = true
+ },
+ NavigatorSize = { 200, 140 },
+ Direction = "Horizontal",
+ PipeStyle = "Direct",
+ RootScale = 1,
+ RootOffset = { 130, 29 }
+ }
+ },
+ Keyframes = MultiView {
+ Active = "TimelineView",
+ ViewList = ordered() {
+ TimelineView = "TimelineView"
+ },
+ TimelineView = TimelineView {
+ TreeControlState = {
+ },
+ DisplayMode = "All Tools",
+ ShowCurrentTimeTools = false,
+ Filter = "Show All",
+ ShowSelectedTools = false,
+ ShowAnimatedToolsOnly = false,
+ ShowEditBoxes = false,
+ KeyFrameView = {
+ Position = { Left = 232, Bottom = 139 },
+ ScaleX = 2.28215767634855,
+ OffsetX = -11.4107883817427,
+ OffsetY = 0,
+ AutoScaling = "scroll",
+ AutoSnapTo = "frame",
+ AutoSnapToGuidelines = true,
+ GuidelinesGrabEnabled = true,
+ GuidelinesSnapTo = "none"
+ },
+ Spreadsheet = { LeftPos = 232, Visible = false }
+ }
+ },
+ Spline = MultiView {
+ Active = "SplineView",
+ ViewList = ordered() {
+ SplineView = "SplineEditorView"
+ },
+ SplineView = SplineEditorView {
+ LeftPos = 264,
+ ScaleX = 0.2,
+ ScaleY = 0.00338983050847458,
+ OffsetX = -0.2,
+ OffsetY = 0,
+ AutoScaling = "scroll",
+ AutoSnapTo = "frame",
+ AutoSnapToGuidelines = true,
+ GuidelinesSnapTo = "frame",
+ ShowKeyMarkers = false,
+ IndependentHandles = false,
+ ShowNonSplineModifiers = false,
+ GuidelinesGrabEnabled = true,
+ ShowOneToolOnly = false,
+ ShowSelectedTools = false,
+ ShowAllInputs = false,
+ Filter = "Show All"
+ }
+ },
+ Inspector = MultiView {
+ Active = "Tools",
+ ViewList = ordered() {
+ Tools = "ControlView",
+ Modifiers = "ModifierView"
+ },
+ },
+ Viewer1 = MultiView {
+ Active = "LeftView",
+ ViewList = ordered() {
+ LeftView = "PreviewContainer"
+ },
+ },
+ Viewer2 = MultiView {
+ Active = "RightView",
+ ViewList = ordered() {
+ RightView = "PreviewContainer"
+ },
+ },
+ Time = "TimeView",
+ ActionStrip = "ActionStripView",
+ LayoutStrip = "LayoutStripView"
+ },
+ Layout = {
+ { ID = "LayoutStrip", FixedY = 36, Resolve = false, Flat = true },
+ {
+ {
+ { ID = "MediaPool", Fusion = false, RatioX = 1 },
+ { ID = "Effects", RatioX = 1 },
+ Zone = "Left",
+ Rows = 2,
+ PaneID = "OuterLeft",
+ PixelX = 420
+ },
+ {
+ {
+ {
+ { ID = "MediaPool", Fusion = false, RatioX = 1 },
+ { ID = "Effects", RatioX = 1 },
+ PaneID = "InnerLeft",
+ MaxViews = 1,
+ PixelX = 420,
+ Rows = 2,
+ Zone = "!Left"
+ },
+ {
+ {
+ { ID = "Viewer1", RatioY = 0.01, RatioX = 1 },
+ { ID = "Viewer2", RatioX = 1 },
+ RatioY = 1,
+ Columns = 2,
+ PaneID = "ViewerSplit"
+ },
+ { ID = "Time", FixedY = 83, Flat = true },
+ RatioX = 1,
+ Rows = 2
+ },
+ {
+ { ID = "Inspector", RatioY = 1 },
+ { ID = "Metadata", RatioY = 1, Fusion = false },
+ PaneID = "InnerRight",
+ MaxViews = 1,
+ PixelX = 420,
+ Rows = 2,
+ Zone = "!Right"
+ },
+ RatioY = 2,
+ Columns = 3,
+ PaneID = "InnerColumns"
+ },
+ { ID = "ActionStrip", FixedY = 50, Flat = true },
+ {
+ { ID = "Nodes", RatioX = 1 },
+ { ID = "Spline", RatioX = 1 },
+ { ID = "Keyframes", RatioX = 1 },
+ RatioY = 1,
+ Columns = 3,
+ PaneID = "MainSplit"
+ },
+ { Fusion = false, ID = "Clips", LARGE_FixedY = 160, MEDIUM_FixedY = 138, SMALL_FixedY = 110 },
+ RatioX = 1,
+ Rows = 4,
+ PaneID = "CenterSplit"
+ },
+ {
+ { ID = "Inspector", RatioY = 1 },
+ { ID = "Metadata", RatioY = 1, Fusion = false },
+ Zone = "Right",
+ Rows = 2,
+ PaneID = "OuterRight",
+ PixelX = 420
+ },
+ RatioY = 1,
+ Columns = 3,
+ PaneID = "OuterColumns"
+ },
+ RatioX = 1,
+ Rows = 2,
+ RatioY = 1
+ },
+ TopBar = {
+ Left = { "Left", "MediaPool", "Effects", "Clips", "Nodes", "Console" },
+ Right = { "Spline", "Keyframes", "Metadata", "Inspector", "Right" }
+ }
+ }
+ },
+ Prefs = {
+ Comp = {
+ AutoSave = {
+ Delay = 60,
+ },
+ Memory = {
+ FramesAtOnce = 4,
+ Interactive = {
+ SimultaneousBranching = true,
+ }
+ },
+ Views = {
+ RightView = {
+ Viewer = {
+ Layer = ":Default"
+ },
+ },
+ LeftView = {
+ Viewer = {
+ Layer = ":Default"
+ },
+ },
+ View1 = {
+ PickH = 1,
+ PickW = 1,
+ AlwaysOnTop = true,
+ FullScreen = false,
+ },
+ Defaults = {
+ View3D = {
+ Options = {
+ ShowUVTangentVectors = false
+ },
+ TextureDepth = "int8"
+ },
+ Guides = {
+ SafeTitle = true,
+ SafeImage = true,
+ Center = true,
+ },
+ MaterialViewer = {
+ Options = {
+ TextureDepth = "int8"
+ },
+ },
+ },
+ ["Image View"] = {
+ Viewer = {
+ ScaleMode = 1
+ }
+ }
+ },
+ Preview = {
+ SkipFrames = true,
+ ActiveLoaders = false,
+ ActiveSavers = false,
+ },
+ Paths = {
+ Map = {
+ ["ResolveCaches:"] = "Temp:DiskCache",
+ },
+ },
+ FrameFormat = {
+ Width = 1024,
+ Height = 1024,
+ GuideRatio = 1.77777777777778,
+ },
+ Unsorted = {
+ GlobalEnd = 1,
+ RenderSettings = {
+ Configs = {
+ Preview = {
+ StepRender = false,
+ PriorityClasses = "all",
+ ShowRenderNodes = false,
+ SizeType = 1,
+ CustomAspect = true,
+ CustomHeight = 160,
+ StepSize = 5,
+ CustomWidth = 200,
+ MotionBlur = true,
+ UpdateMode = "Some",
+ UseNetwork = false,
+ Quality = true
+ },
+ Final = {
+ StepRender = false,
+ PriorityClasses = "all",
+ ShowRenderNodes = false,
+ SizeType = 1,
+ CustomAspect = true,
+ CustomHeight = 160,
+ StepSize = 5,
+ CustomWidth = 200,
+ MotionBlur = true,
+ UpdateMode = "Some",
+ UseNetwork = false,
+ Quality = true
+ }
+ },
+ PreviewConfig = "Preview",
+ CurrentConfig = "Final"
+ }
+ },
+ Tweaks = {
+ OpenCL = {
+ Enable = 2,
+ Caching = 2
+ }
+ },
+ LUTView = {
+ ShowTips = true,
+ },
+ Cluster = {
+ SlaveClasses = "all"
+ },
+ FlowView = {
+ FullToolIndicator = false
+ },
+ QuickTime = {
+ },
+ }
+ },
+}
diff --git a/crates/snowbound/assets/icon/sources/Snowbound-Physical.blend b/crates/snowbound/assets/icon/sources/Snowbound-Physical.blend
new file mode 100644
index 0000000000000000000000000000000000000000..91ae11ab409cd09546fdc5d740d9a6be85f26e38
Binary files /dev/null and b/crates/snowbound/assets/icon/sources/Snowbound-Physical.blend differ
diff --git a/crates/snowbound/assets/icon/sources/Snowbound-Sequoia.blend b/crates/snowbound/assets/icon/sources/Snowbound-Sequoia.blend
new file mode 100644
index 0000000000000000000000000000000000000000..2fcd6e9d76a979de73a26cb4c9a212de3736d80a
Binary files /dev/null and b/crates/snowbound/assets/icon/sources/Snowbound-Sequoia.blend differ
diff --git a/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/Assets/Snowflake.svg b/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/Assets/Snowflake.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d2e96ce05b5e89c66b7910925b66775dcb194a8e
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/Assets/Snowflake.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/Assets/Tabs.svg b/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/Assets/Tabs.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5d3dea5158cf962635fabe2db7ded63245129d82
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/Assets/Tabs.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/icon.json b/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/icon.json
new file mode 100644
index 0000000000000000000000000000000000000000..0674f509a14b0fc884b8bb91addf72cba3b59b6d
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/Snowbound-Tahoe.icon/icon.json
@@ -0,0 +1,78 @@
+{
+ "fill": {
+ "linear-gradient": [
+ "extended-srgb:0.86,0.87,0.88,1",
+ "extended-srgb:0.73,0.76,0.78,1"
+ ],
+ "orientation": {
+ "start": {
+ "x": 0.5,
+ "y": 0
+ },
+ "stop": {
+ "x": 0.5,
+ "y": 1
+ }
+ }
+ },
+ "groups": [
+ {
+ "layers": [
+ {
+ "fill-specializations": [
+ {
+ "appearance": "dark",
+ "value": {
+ "solid": "extended-srgb:0.38,0.75,1,1"
+ }
+ }
+ ],
+ "glass": true,
+ "hidden": false,
+ "image-name": "Snowflake.svg",
+ "name": "Snowflake",
+ "opacity": 0.49,
+ "position": {
+ "scale": 1.1,
+ "translation-in-points": [
+ -48,
+ 0
+ ]
+ }
+ }
+ ],
+ "name": "Snowflake",
+ "shadow": {
+ "kind": "neutral",
+ "opacity": 0.34
+ },
+ "translucency": {
+ "enabled": true,
+ "value": 0.06
+ }
+ },
+ {
+ "layers": [
+ {
+ "name": "Tabs",
+ "image-name": "Tabs.svg",
+ "glass": true,
+ "opacity": 0.72
+ }
+ ],
+ "name": "Index tabs",
+ "shadow": {
+ "kind": "neutral",
+ "opacity": 0.22
+ },
+ "specular": true,
+ "translucency": {
+ "enabled": true,
+ "value": 0.12
+ }
+ }
+ ],
+ "supported-platforms": {
+ "squares": "shared"
+ }
+}
diff --git a/crates/snowbound/assets/icon/sources/finish.lua b/crates/snowbound/assets/icon/sources/finish.lua
new file mode 100644
index 0000000000000000000000000000000000000000..47c0217086b24aee9b2596fb7c2a54bee20e38fb
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/finish.lua
@@ -0,0 +1,21 @@
+local fu = Fusion()
+local root = assert(arg[1], 'Pass the absolute design directory')
+local path = root .. '/sources/Snowbound-Finishing.comp'
+local comp
+for _, c in pairs(fu:GetCompList()) do
+ if c:GetAttrs().COMPS_FileName == path then comp = c end
+end
+comp = comp or fu:LoadComp(path)
+for name,file in pairs({Notebook_2010='SnowLeopard',Notebook_15='Sequoia'}) do
+ comp:FindTool(name).Clip = root .. '/renders/' .. file .. '.png'
+end
+print('Render',comp:Render({Start=0,End=0,Wait=true}))
+for name,file in pairs({Notebook_2010='SnowLeopard',Notebook_15='Sequoia'}) do
+ comp:FindTool(name).Clip = 'Comp:/../renders/' .. file .. '.png'
+end
+print('Save',comp:Save())
+
+for _,name in ipairs({'SnowLeopard','Sequoia'}) do
+ local base = root .. '/Snowbound-' .. name
+ assert(os.rename(base .. '0000.png', base .. '.png'))
+end
diff --git a/crates/snowbound/assets/icon/sources/package_icons.py b/crates/snowbound/assets/icon/sources/package_icons.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f83ddf30db8cd81631335f1beef55bb7157da28
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/package_icons.py
@@ -0,0 +1,43 @@
+from io import BytesIO
+from pathlib import Path
+import subprocess
+import tempfile
+from PIL import Image, ImageCms
+
+root = Path(__file__).resolve().parent.parent
+exports = root / 'exports'
+srgb = ImageCms.createProfile('sRGB')
+profile = ImageCms.ImageCmsProfile(srgb).tobytes()
+board = Image.new('RGBA', (1800, 1100), '#edf0f2')
+board.paste('#25343e', (0, 550, 1800, 1100))
+for col, name in enumerate(('SnowLeopard', 'Sequoia', 'Tahoe')):
+ for dark in (False, True):
+ suffix = '-Dark' if name == 'Tahoe' and dark else ''
+ im = Image.open(exports / f'Snowbound-{name}{suffix}.png')
+ art = im.convert('RGBA')
+ if im.info.get('icc_profile'):
+ art = ImageCms.profileToProfile(art, ImageCms.ImageCmsProfile(BytesIO(im.info['icc_profile'])), srgb, outputMode='RGBA')
+ if name == 'Tahoe':
+ tile = art.resize((824, 824), Image.Resampling.LANCZOS)
+ art = Image.new('RGBA', (1024, 1024))
+ art.alpha_composite(tile, (100, 100))
+ x, y = col * 600, 550 if dark else 0
+ board.alpha_composite(art.resize((480, 480), Image.Resampling.LANCZOS), (x + 60, y))
+ for size, center in ((64, 180), (32, 310), (16, 420)):
+ board.alpha_composite(art.resize((size, size), Image.Resampling.LANCZOS), (x + center - size // 2, y + 500 - size // 2))
+ if not dark:
+ with tempfile.TemporaryDirectory() as temp:
+ folder = Path(temp) / f'Snowbound-{name}.iconset'
+ folder.mkdir()
+ pixels = {}
+ for size in (16, 32, 128, 256, 512):
+ for scale in (1, 2):
+ n = size * scale
+ dest = folder / (f'icon_{size}x{size}' + ('@2x' if scale == 2 else '') + '.png')
+ if n in pixels:
+ dest.symlink_to(pixels[n].name)
+ else:
+ art.resize((n, n), Image.Resampling.LANCZOS).save(dest, icc_profile=profile)
+ pixels[n] = dest
+ subprocess.run(['iconutil', '-c', 'icns', str(folder), '-o', str(exports / f'Snowbound-{name}.icns')], check=True)
+board.convert('RGB').save(root / 'Snowbound-comparison.png', icc_profile=profile)
diff --git a/crates/snowbound/assets/icon/sources/render_blender.py b/crates/snowbound/assets/icon/sources/render_blender.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9accf997c8e474aeb0f484f1e762683d71a7974
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/render_blender.py
@@ -0,0 +1,16 @@
+import bpy
+from pathlib import Path
+
+root=Path(bpy.data.filepath).parent.parent
+s=bpy.context.scene
+stem='SnowLeopard' if s.name.startswith('2010') else 'Sequoia'
+s.render.image_settings.file_format='OPEN_EXR'
+s.render.image_settings.color_depth='16'
+s.render.image_settings.exr_codec='ZIP'
+(root/'renders').mkdir(exist_ok=True)
+s.render.filepath=str(root/'renders'/f'{stem}.exr')
+bpy.ops.render.render(write_still=True)
+s.render.image_settings.file_format='PNG'
+s.render.filepath=str(root/'renders'/f'{stem}.png')
+bpy.data.images['Render Result'].save_render(s.render.filepath,scene=s)
+
diff --git a/crates/snowbound/assets/icon/sources/render_glass.py b/crates/snowbound/assets/icon/sources/render_glass.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a287a4cb637a32ad9172f8ef8f3897ef6dcaa27
--- /dev/null
+++ b/crates/snowbound/assets/icon/sources/render_glass.py
@@ -0,0 +1,13 @@
+from pathlib import Path
+import subprocess
+
+root = Path(__file__).resolve().parent.parent
+(root / 'exports').mkdir(exist_ok=True)
+tool = '/Applications/Xcode.app/Contents/Applications/Icon Composer.app/Contents/Executables/ictool'
+for suffix, rendition in (('', 'Default'), ('-Dark', 'Dark'), ('-Mono', 'Mono')):
+ subprocess.run([
+ tool, str(root / 'sources/Snowbound-Tahoe.icon'), '--export-image',
+ '--output-file', str(root / 'exports' / f'Snowbound-Tahoe{suffix}.png'),
+ '--platform', 'macOS', '--rendition', rendition,
+ '--width', '1024', '--height', '1024', '--scale', '1', '--light-angle', '-53',
+ ], check=True)
diff --git a/tools/canvas/build_macos.py b/tools/canvas/build_macos.py
index 114af9fcf77709b9c2ca192a599b8de5f5776ce0..066e651aea9260c88de1bae85eddefef9e3bda5b 100644
--- a/tools/canvas/build_macos.py
+++ b/tools/canvas/build_macos.py
@@ -3,6 +3,7 @@
import argparse
import json
from pathlib import Path
+import platform
import plistlib
import shutil
import subprocess
@@ -28,6 +29,10 @@ binary.parent.mkdir(parents=True, exist_ok=True)
pending = binary.with_suffix('.next')
shutil.copy2(target / ('release' if args.release else 'debug') / 'one-canvas-app', pending)
pending.replace(binary)
+icon = 'Snowbound-Tahoe' if int(platform.mac_ver()[0].split('.')[0] or 0) >= 26 else 'Snowbound-Sequoia'
+resources = bundle / 'Contents/Resources'
+resources.mkdir(exist_ok=True)
+shutil.copy2(root / 'crates/snowbound/assets/icon' / f'{icon}.icns', resources / 'Snowbound.icns')
(bundle / 'Contents/Info.plist').write_bytes(plistlib.dumps({
'CFBundleExecutable': binary.name,
'CFBundleIdentifier': args.bundle_id or 'dev.onecanvas.app',
@@ -37,6 +42,7 @@ pending.replace(binary)
'CFBundleVersion': '1',
'NSHighResolutionCapable': True,
'NSPrincipalClass': 'NSApplication',
+ 'CFBundleIconFile': 'Snowbound',
}))
subprocess.run(['codesign', '--force', '--sign', '-', str(bundle)], check=True)
subprocess.run(['codesign', '--verify', '--strict', str(bundle)], check=True)