@buoy-gg/shared-ui 7.0.25 → 7.0.27

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 (209) hide show
  1. package/lib/commonjs/JsModal.js +156 -20
  2. package/lib/commonjs/JsModal.web.js +85 -39
  3. package/lib/commonjs/dataViewer/VirtualizedDataExplorer.js +14 -4
  4. package/lib/commonjs/dataViewer/diffThemes.js +20 -18
  5. package/lib/commonjs/dataViewer/tree/TreeDiffViewer.js +8 -8
  6. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  7. package/lib/commonjs/icons/lucide-icons.js +74 -15
  8. package/lib/commonjs/index.js +86 -0
  9. package/lib/commonjs/ui/backgrounds/BackgroundSwitcher.js +248 -74
  10. package/lib/commonjs/ui/backgrounds/README.md +102 -20
  11. package/lib/commonjs/ui/backgrounds/backgroundStore.js +20 -6
  12. package/lib/commonjs/ui/backgrounds/index.js +91 -1
  13. package/lib/commonjs/ui/backgrounds/primitives.js +50 -14
  14. package/lib/commonjs/ui/backgrounds/registry.js +41 -64
  15. package/lib/commonjs/ui/backgrounds/rng.js +21 -0
  16. package/lib/commonjs/ui/backgrounds/skyClock.js +45 -0
  17. package/lib/commonjs/ui/backgrounds/variants/daylight.js +453 -0
  18. package/lib/commonjs/ui/backgrounds/variants/deepField.js +60 -30
  19. package/lib/commonjs/ui/backgrounds/variants/hyperspace.js +218 -0
  20. package/lib/commonjs/ui/backgrounds/variants/liveSky.js +898 -0
  21. package/lib/commonjs/ui/backgrounds/variants/meteors.js +257 -0
  22. package/lib/commonjs/ui/backgrounds/variants/moonlight.js +472 -0
  23. package/lib/commonjs/ui/backgrounds/variants/underwater.js +757 -0
  24. package/lib/commonjs/ui/components/Badge.js +11 -10
  25. package/lib/commonjs/ui/components/CompactRow.js +30 -17
  26. package/lib/commonjs/ui/components/DevToolsCard.js +12 -8
  27. package/lib/commonjs/ui/components/DynamicFilterView.js +43 -41
  28. package/lib/commonjs/ui/components/EventStepperFooter.js +38 -10
  29. package/lib/commonjs/ui/components/FilterComponents.js +11 -11
  30. package/lib/commonjs/ui/components/ModalHeader.js +13 -13
  31. package/lib/commonjs/ui/components/SectionHeader.js +3 -1
  32. package/lib/commonjs/ui/components/StorageTypeBadge.js +3 -2
  33. package/lib/commonjs/ui/components/TabSelector.js +56 -38
  34. package/lib/commonjs/ui/components/ValueTypeBadge.js +7 -6
  35. package/lib/commonjs/ui/components/WindowControls.js +37 -10
  36. package/lib/commonjs/ui/gameUI/constants/gameUIColors.js +8 -0
  37. package/lib/commonjs/ui/night/nightTheme.js +120 -0
  38. package/lib/commonjs/ui/night/primitives.js +498 -0
  39. package/lib/module/JsModal.js +156 -20
  40. package/lib/module/JsModal.web.js +83 -39
  41. package/lib/module/dataViewer/VirtualizedDataExplorer.js +14 -4
  42. package/lib/module/dataViewer/diffThemes.js +20 -18
  43. package/lib/module/dataViewer/tree/TreeDiffViewer.js +9 -9
  44. package/lib/module/hooks/safe-area-impl.js +1 -1
  45. package/lib/module/icons/lucide-icons.js +74 -15
  46. package/lib/module/index.js +4 -0
  47. package/lib/module/ui/backgrounds/BackgroundSwitcher.js +250 -76
  48. package/lib/module/ui/backgrounds/README.md +102 -20
  49. package/lib/module/ui/backgrounds/backgroundStore.js +19 -5
  50. package/lib/module/ui/backgrounds/index.js +11 -2
  51. package/lib/module/ui/backgrounds/primitives.js +53 -16
  52. package/lib/module/ui/backgrounds/registry.js +41 -64
  53. package/lib/module/ui/backgrounds/rng.js +20 -0
  54. package/lib/module/ui/backgrounds/skyClock.js +39 -0
  55. package/lib/module/ui/backgrounds/variants/daylight.js +449 -0
  56. package/lib/module/ui/backgrounds/variants/deepField.js +62 -31
  57. package/lib/module/ui/backgrounds/variants/hyperspace.js +214 -0
  58. package/lib/module/ui/backgrounds/variants/liveSky.js +893 -0
  59. package/lib/module/ui/backgrounds/variants/meteors.js +253 -0
  60. package/lib/module/ui/backgrounds/variants/moonlight.js +468 -0
  61. package/lib/module/ui/backgrounds/variants/underwater.js +753 -0
  62. package/lib/module/ui/components/Badge.js +11 -10
  63. package/lib/module/ui/components/CompactRow.js +30 -17
  64. package/lib/module/ui/components/DevToolsCard.js +12 -8
  65. package/lib/module/ui/components/DynamicFilterView.js +43 -41
  66. package/lib/module/ui/components/EventStepperFooter.js +38 -10
  67. package/lib/module/ui/components/FilterComponents.js +11 -11
  68. package/lib/module/ui/components/ModalHeader.js +13 -13
  69. package/lib/module/ui/components/SectionHeader.js +3 -1
  70. package/lib/module/ui/components/StorageTypeBadge.js +3 -2
  71. package/lib/module/ui/components/TabSelector.js +57 -39
  72. package/lib/module/ui/components/ValueTypeBadge.js +7 -6
  73. package/lib/module/ui/components/WindowControls.js +37 -10
  74. package/lib/module/ui/gameUI/constants/gameUIColors.js +8 -0
  75. package/lib/module/ui/night/nightTheme.js +116 -0
  76. package/lib/module/ui/night/primitives.js +485 -0
  77. package/lib/typescript/commonjs/JsModal.d.ts +18 -0
  78. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/JsModal.web.d.ts +13 -0
  80. package/lib/typescript/commonjs/JsModal.web.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/dataViewer/diffThemes.d.ts +3 -1
  83. package/lib/typescript/commonjs/dataViewer/diffThemes.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/dataViewer/tree/TreeDiffViewer.d.ts.map +1 -1
  85. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  86. package/lib/typescript/commonjs/icons/lucide-icons.d.ts +12 -1
  87. package/lib/typescript/commonjs/icons/lucide-icons.d.ts.map +1 -1
  88. package/lib/typescript/commonjs/index.d.ts +3 -0
  89. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  90. package/lib/typescript/commonjs/ui/backgrounds/BackgroundSwitcher.d.ts +26 -6
  91. package/lib/typescript/commonjs/ui/backgrounds/BackgroundSwitcher.d.ts.map +1 -1
  92. package/lib/typescript/commonjs/ui/backgrounds/backgroundStore.d.ts +3 -0
  93. package/lib/typescript/commonjs/ui/backgrounds/backgroundStore.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/ui/backgrounds/index.d.ts +7 -1
  95. package/lib/typescript/commonjs/ui/backgrounds/index.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/ui/backgrounds/primitives.d.ts +18 -3
  97. package/lib/typescript/commonjs/ui/backgrounds/primitives.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/ui/backgrounds/registry.d.ts +8 -0
  99. package/lib/typescript/commonjs/ui/backgrounds/registry.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/ui/backgrounds/rng.d.ts +6 -0
  101. package/lib/typescript/commonjs/ui/backgrounds/rng.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/ui/backgrounds/skyClock.d.ts +17 -0
  103. package/lib/typescript/commonjs/ui/backgrounds/skyClock.d.ts.map +1 -0
  104. package/lib/typescript/commonjs/ui/backgrounds/types.d.ts +1 -1
  105. package/lib/typescript/commonjs/ui/backgrounds/types.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/ui/backgrounds/variants/daylight.d.ts +30 -0
  107. package/lib/typescript/commonjs/ui/backgrounds/variants/daylight.d.ts.map +1 -0
  108. package/lib/typescript/commonjs/ui/backgrounds/variants/deepField.d.ts +19 -4
  109. package/lib/typescript/commonjs/ui/backgrounds/variants/deepField.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/ui/backgrounds/variants/hyperspace.d.ts +39 -0
  111. package/lib/typescript/commonjs/ui/backgrounds/variants/hyperspace.d.ts.map +1 -0
  112. package/lib/typescript/commonjs/ui/backgrounds/variants/liveSky.d.ts +41 -0
  113. package/lib/typescript/commonjs/ui/backgrounds/variants/liveSky.d.ts.map +1 -0
  114. package/lib/typescript/commonjs/ui/backgrounds/variants/meteors.d.ts +26 -0
  115. package/lib/typescript/commonjs/ui/backgrounds/variants/meteors.d.ts.map +1 -0
  116. package/lib/typescript/commonjs/ui/backgrounds/variants/moonlight.d.ts +35 -0
  117. package/lib/typescript/commonjs/ui/backgrounds/variants/moonlight.d.ts.map +1 -0
  118. package/lib/typescript/commonjs/ui/backgrounds/variants/underwater.d.ts +51 -0
  119. package/lib/typescript/commonjs/ui/backgrounds/variants/underwater.d.ts.map +1 -0
  120. package/lib/typescript/commonjs/ui/components/Badge.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/ui/components/CompactRow.d.ts.map +1 -1
  122. package/lib/typescript/commonjs/ui/components/DynamicFilterView.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/ui/components/EventStepperFooter.d.ts +2 -0
  124. package/lib/typescript/commonjs/ui/components/EventStepperFooter.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/ui/components/StorageTypeBadge.d.ts.map +1 -1
  126. package/lib/typescript/commonjs/ui/components/TabSelector.d.ts +9 -0
  127. package/lib/typescript/commonjs/ui/components/TabSelector.d.ts.map +1 -1
  128. package/lib/typescript/commonjs/ui/components/ValueTypeBadge.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts +4 -2
  130. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
  131. package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts +8 -0
  132. package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
  133. package/lib/typescript/commonjs/ui/night/nightTheme.d.ts +113 -0
  134. package/lib/typescript/commonjs/ui/night/nightTheme.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/ui/night/primitives.d.ts +111 -0
  136. package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -0
  137. package/lib/typescript/module/JsModal.d.ts +18 -0
  138. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  139. package/lib/typescript/module/JsModal.web.d.ts +13 -0
  140. package/lib/typescript/module/JsModal.web.d.ts.map +1 -1
  141. package/lib/typescript/module/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
  142. package/lib/typescript/module/dataViewer/diffThemes.d.ts +3 -1
  143. package/lib/typescript/module/dataViewer/diffThemes.d.ts.map +1 -1
  144. package/lib/typescript/module/dataViewer/tree/TreeDiffViewer.d.ts.map +1 -1
  145. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  146. package/lib/typescript/module/icons/lucide-icons.d.ts +12 -1
  147. package/lib/typescript/module/icons/lucide-icons.d.ts.map +1 -1
  148. package/lib/typescript/module/index.d.ts +3 -0
  149. package/lib/typescript/module/index.d.ts.map +1 -1
  150. package/lib/typescript/module/ui/backgrounds/BackgroundSwitcher.d.ts +26 -6
  151. package/lib/typescript/module/ui/backgrounds/BackgroundSwitcher.d.ts.map +1 -1
  152. package/lib/typescript/module/ui/backgrounds/backgroundStore.d.ts +3 -0
  153. package/lib/typescript/module/ui/backgrounds/backgroundStore.d.ts.map +1 -1
  154. package/lib/typescript/module/ui/backgrounds/index.d.ts +7 -1
  155. package/lib/typescript/module/ui/backgrounds/index.d.ts.map +1 -1
  156. package/lib/typescript/module/ui/backgrounds/primitives.d.ts +18 -3
  157. package/lib/typescript/module/ui/backgrounds/primitives.d.ts.map +1 -1
  158. package/lib/typescript/module/ui/backgrounds/registry.d.ts +8 -0
  159. package/lib/typescript/module/ui/backgrounds/registry.d.ts.map +1 -1
  160. package/lib/typescript/module/ui/backgrounds/rng.d.ts +6 -0
  161. package/lib/typescript/module/ui/backgrounds/rng.d.ts.map +1 -1
  162. package/lib/typescript/module/ui/backgrounds/skyClock.d.ts +17 -0
  163. package/lib/typescript/module/ui/backgrounds/skyClock.d.ts.map +1 -0
  164. package/lib/typescript/module/ui/backgrounds/types.d.ts +1 -1
  165. package/lib/typescript/module/ui/backgrounds/types.d.ts.map +1 -1
  166. package/lib/typescript/module/ui/backgrounds/variants/daylight.d.ts +30 -0
  167. package/lib/typescript/module/ui/backgrounds/variants/daylight.d.ts.map +1 -0
  168. package/lib/typescript/module/ui/backgrounds/variants/deepField.d.ts +19 -4
  169. package/lib/typescript/module/ui/backgrounds/variants/deepField.d.ts.map +1 -1
  170. package/lib/typescript/module/ui/backgrounds/variants/hyperspace.d.ts +39 -0
  171. package/lib/typescript/module/ui/backgrounds/variants/hyperspace.d.ts.map +1 -0
  172. package/lib/typescript/module/ui/backgrounds/variants/liveSky.d.ts +41 -0
  173. package/lib/typescript/module/ui/backgrounds/variants/liveSky.d.ts.map +1 -0
  174. package/lib/typescript/module/ui/backgrounds/variants/meteors.d.ts +26 -0
  175. package/lib/typescript/module/ui/backgrounds/variants/meteors.d.ts.map +1 -0
  176. package/lib/typescript/module/ui/backgrounds/variants/moonlight.d.ts +35 -0
  177. package/lib/typescript/module/ui/backgrounds/variants/moonlight.d.ts.map +1 -0
  178. package/lib/typescript/module/ui/backgrounds/variants/underwater.d.ts +51 -0
  179. package/lib/typescript/module/ui/backgrounds/variants/underwater.d.ts.map +1 -0
  180. package/lib/typescript/module/ui/components/Badge.d.ts.map +1 -1
  181. package/lib/typescript/module/ui/components/CompactRow.d.ts.map +1 -1
  182. package/lib/typescript/module/ui/components/DynamicFilterView.d.ts.map +1 -1
  183. package/lib/typescript/module/ui/components/EventStepperFooter.d.ts +2 -0
  184. package/lib/typescript/module/ui/components/EventStepperFooter.d.ts.map +1 -1
  185. package/lib/typescript/module/ui/components/StorageTypeBadge.d.ts.map +1 -1
  186. package/lib/typescript/module/ui/components/TabSelector.d.ts +9 -0
  187. package/lib/typescript/module/ui/components/TabSelector.d.ts.map +1 -1
  188. package/lib/typescript/module/ui/components/ValueTypeBadge.d.ts.map +1 -1
  189. package/lib/typescript/module/ui/components/WindowControls.d.ts +4 -2
  190. package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
  191. package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts +8 -0
  192. package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
  193. package/lib/typescript/module/ui/night/nightTheme.d.ts +113 -0
  194. package/lib/typescript/module/ui/night/nightTheme.d.ts.map +1 -0
  195. package/lib/typescript/module/ui/night/primitives.d.ts +111 -0
  196. package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -0
  197. package/package.json +4 -4
  198. package/lib/commonjs/ui/backgrounds/variants/lattice.js +0 -579
  199. package/lib/commonjs/ui/backgrounds/variants/starfield.js +0 -210
  200. package/lib/module/ui/backgrounds/variants/lattice.js +0 -575
  201. package/lib/module/ui/backgrounds/variants/starfield.js +0 -206
  202. package/lib/typescript/commonjs/ui/backgrounds/variants/lattice.d.ts +0 -33
  203. package/lib/typescript/commonjs/ui/backgrounds/variants/lattice.d.ts.map +0 -1
  204. package/lib/typescript/commonjs/ui/backgrounds/variants/starfield.d.ts +0 -12
  205. package/lib/typescript/commonjs/ui/backgrounds/variants/starfield.d.ts.map +0 -1
  206. package/lib/typescript/module/ui/backgrounds/variants/lattice.d.ts +0 -33
  207. package/lib/typescript/module/ui/backgrounds/variants/lattice.d.ts.map +0 -1
  208. package/lib/typescript/module/ui/backgrounds/variants/starfield.d.ts +0 -12
  209. package/lib/typescript/module/ui/backgrounds/variants/starfield.d.ts.map +0 -1
@@ -0,0 +1,893 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Live Sky — the cove on your clock.
5
+ *
6
+ * One scene that tracks the actual local time — through the WORKDAY REMAP
7
+ * (`workdaySceneMinutes` below): the real clock is compressed onto the scene's
8
+ * day so sunrise lands ~9:00, noon at lunch, sunset ~17:30 and night after
9
+ * ~20:00, and a normal working session sees the whole cycle. In scene time the
10
+ * sun runs 06:30→19:00 and the moon takes the night shift; dawn, golden hour,
11
+ * sunset and dusk are palette keyframes lerped in between. The night keyframe
12
+ * is Moonlight's palette and the noon keyframe is Daylight's, so the live
13
+ * scene passes through both fixed siblings exactly.
14
+ *
15
+ * THE CHEAP TRICK (see LIVE_SKY_PLAN.md): real time IS the cheap version. The
16
+ * sun moves ~0.4px per minute on this surface — invisible as motion — so the
17
+ * cycle itself animates NOTHING. The scene is laid out statically for the
18
+ * current minute and a once-a-minute tick re-renders it (~one small React
19
+ * commit). That also sidesteps the native driver's hard limit (transform and
20
+ * opacity only, never colour): colour "animation" here is just new style
21
+ * values in an ordinary render. Between ticks the preset costs exactly what
22
+ * Daylight costs — a handful of native loops that never touch JS.
23
+ *
24
+ * The scrub slider in `BackgroundSwitcher` writes `skyClock.ts`; a non-null
25
+ * scrub freezes this scene at that minute and stops the tick.
26
+ *
27
+ * Same contract as ../README.md otherwise: native-driven loops only, static
28
+ * geometry rasterized, scatter tables at module load, light geometry sized
29
+ * from the WINDOW (resizing crops, never stretches).
30
+ */
31
+
32
+ import { memo, useEffect, useState } from "react";
33
+ import { Animated, AppState, Dimensions, View } from "react-native";
34
+ import { absoluteFill } from "../../../utils/absoluteFill.js";
35
+ import { Base, LinearFade, RadialGlow, RasterLayer, Vignette, usePulse } from "../primitives.js";
36
+ import { lerpColor, scatter, withAlpha } from "../rng.js";
37
+ import { useSkyScrub } from "../skyClock.js";
38
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
39
+ const HORIZON = 0.46;
40
+ const SUN_RISE = 6.5 * 60;
41
+ const SUN_SET = 19 * 60;
42
+ const MOON_SPAN = 1440 - (SUN_SET - SUN_RISE);
43
+ const SUN_DIA = 50;
44
+ const MOON_DIA = 56;
45
+
46
+ /** Moon craters, fixed — the moon doesn't take the palette's disc colour. */
47
+ const CRATERS = [[0.24, -0.12, 0.2], [-0.16, 0.2, 0.13], [0.08, 0.06, 0.1]];
48
+
49
+ // ============================================================================
50
+ // The palette — keyframes lerped by time of day
51
+ // ============================================================================
52
+
53
+ const NIGHT = {
54
+ skyTop: "#070C15",
55
+ skyHorizon: "#040609",
56
+ skyHorizonAlpha: 1,
57
+ seaColor: "#04070C",
58
+ seaFade: "#010409",
59
+ seaFadeAlpha: 0.5,
60
+ hazeBand: "#17293F",
61
+ hazeAlpha: 0.28,
62
+ cloudRim: "#1D2A42",
63
+ cloudRimAlpha: 0.35,
64
+ cloudBody: "#070D18",
65
+ cloudBodyAlpha: 0.94,
66
+ peakNear: "#030609",
67
+ peakFar: "#020408",
68
+ glitter: "#CFE0F4",
69
+ glitterAlpha: 0.95,
70
+ bloom: "#A9C2DE",
71
+ bloomAlpha: 0.15,
72
+ glow: "#DCE8F6",
73
+ glowAlpha: 0.34,
74
+ disc: "#EDF3FB",
75
+ horizonLine: "#9FB8D4",
76
+ horizonLineAlpha: 0.12,
77
+ underLine: "#C6DAF0",
78
+ underLineAlpha: 0.32,
79
+ vignette: "#020305",
80
+ starAlpha: 1,
81
+ dayness: 0
82
+ };
83
+ const DAWN = {
84
+ skyTop: "#12263E",
85
+ skyHorizon: "#C4756B",
86
+ skyHorizonAlpha: 0.5,
87
+ seaColor: "#0C1E30",
88
+ seaFade: "#03080F",
89
+ seaFadeAlpha: 0.52,
90
+ hazeBand: "#D98F7E",
91
+ hazeAlpha: 0.34,
92
+ cloudRim: "#F2A98C",
93
+ cloudRimAlpha: 0.5,
94
+ cloudBody: "#2E2B41",
95
+ cloudBodyAlpha: 0.9,
96
+ peakNear: "#1A2536",
97
+ peakFar: "#131B29",
98
+ glitter: "#F2C4A0",
99
+ glitterAlpha: 0.8,
100
+ bloom: "#FFB37A",
101
+ bloomAlpha: 0.24,
102
+ glow: "#FFD9B0",
103
+ glowAlpha: 0.4,
104
+ disc: "#FFE9C4",
105
+ horizonLine: "#E8B49A",
106
+ horizonLineAlpha: 0.24,
107
+ underLine: "#FFD2A8",
108
+ underLineAlpha: 0.4,
109
+ vignette: "#080810",
110
+ starAlpha: 0.35,
111
+ dayness: 0.15
112
+ };
113
+ const SUNRISE = {
114
+ skyTop: "#27567D",
115
+ skyHorizon: "#F2B26A",
116
+ skyHorizonAlpha: 0.55,
117
+ seaColor: "#12324C",
118
+ seaFade: "#051220",
119
+ seaFadeAlpha: 0.54,
120
+ hazeBand: "#F2C08A",
121
+ hazeAlpha: 0.36,
122
+ cloudRim: "#FFDCB0",
123
+ cloudRimAlpha: 0.6,
124
+ cloudBody: "#7E88A6",
125
+ cloudBodyAlpha: 0.88,
126
+ peakNear: "#264A64",
127
+ peakFar: "#1E3D54",
128
+ glitter: "#FFD9A0",
129
+ glitterAlpha: 1.05,
130
+ bloom: "#FFCE8A",
131
+ bloomAlpha: 0.26,
132
+ glow: "#FFE6C0",
133
+ glowAlpha: 0.46,
134
+ disc: "#FFF2D4",
135
+ horizonLine: "#F5D2A4",
136
+ horizonLineAlpha: 0.28,
137
+ underLine: "#FFE0AE",
138
+ underLineAlpha: 0.46,
139
+ vignette: "#0A1420",
140
+ starAlpha: 0,
141
+ dayness: 0.6
142
+ };
143
+
144
+ /** Noon — Daylight's palette, verbatim. */
145
+ const DAY = {
146
+ skyTop: "#1C4E74",
147
+ skyHorizon: "#A9CDE6",
148
+ skyHorizonAlpha: 0.42,
149
+ seaColor: "#16405E",
150
+ seaFade: "#06192B",
151
+ seaFadeAlpha: 0.55,
152
+ hazeBand: "#CFE3F1",
153
+ hazeAlpha: 0.3,
154
+ cloudRim: "#FFFFFF",
155
+ cloudRimAlpha: 0.6,
156
+ cloudBody: "#C7DCEC",
157
+ cloudBodyAlpha: 0.88,
158
+ peakNear: "#2E5E80",
159
+ peakFar: "#27516F",
160
+ glitter: "#FFE9B0",
161
+ glitterAlpha: 1,
162
+ bloom: "#FFE9B0",
163
+ bloomAlpha: 0.18,
164
+ glow: "#FFF4D2",
165
+ glowAlpha: 0.42,
166
+ disc: "#FFF9E6",
167
+ horizonLine: "#E4F0F8",
168
+ horizonLineAlpha: 0.2,
169
+ underLine: "#FFEFC2",
170
+ underLineAlpha: 0.42,
171
+ vignette: "#0A2033",
172
+ starAlpha: 0,
173
+ dayness: 1
174
+ };
175
+ const GOLDEN = {
176
+ skyTop: "#31618B",
177
+ skyHorizon: "#F5C26B",
178
+ skyHorizonAlpha: 0.5,
179
+ seaColor: "#1A3C58",
180
+ seaFade: "#071626",
181
+ seaFadeAlpha: 0.55,
182
+ hazeBand: "#F2C888",
183
+ hazeAlpha: 0.36,
184
+ cloudRim: "#FFE0A8",
185
+ cloudRimAlpha: 0.62,
186
+ cloudBody: "#8FA3BC",
187
+ cloudBodyAlpha: 0.88,
188
+ peakNear: "#2A5070",
189
+ peakFar: "#223F5A",
190
+ glitter: "#FFCE7E",
191
+ glitterAlpha: 1.1,
192
+ bloom: "#FFC26E",
193
+ bloomAlpha: 0.24,
194
+ glow: "#FFDCA0",
195
+ glowAlpha: 0.48,
196
+ disc: "#FFEDC2",
197
+ horizonLine: "#F8D8A0",
198
+ horizonLineAlpha: 0.28,
199
+ underLine: "#FFD088",
200
+ underLineAlpha: 0.48,
201
+ vignette: "#0C1B2A",
202
+ starAlpha: 0,
203
+ dayness: 1
204
+ };
205
+ const SUNSET = {
206
+ skyTop: "#232F55",
207
+ skyHorizon: "#E86A3C",
208
+ skyHorizonAlpha: 0.6,
209
+ seaColor: "#1E3049",
210
+ seaFade: "#050A14",
211
+ seaFadeAlpha: 0.55,
212
+ hazeBand: "#F08A4A",
213
+ hazeAlpha: 0.4,
214
+ cloudRim: "#FFC48A",
215
+ cloudRimAlpha: 0.65,
216
+ cloudBody: "#3A2F45",
217
+ cloudBodyAlpha: 0.9,
218
+ peakNear: "#1C2438",
219
+ peakFar: "#151C2C",
220
+ glitter: "#FF9D5C",
221
+ glitterAlpha: 1.15,
222
+ bloom: "#FF8A50",
223
+ bloomAlpha: 0.3,
224
+ glow: "#FFB27A",
225
+ glowAlpha: 0.5,
226
+ disc: "#FFD9A0",
227
+ horizonLine: "#FFD2A0",
228
+ horizonLineAlpha: 0.3,
229
+ underLine: "#FFB070",
230
+ underLineAlpha: 0.5,
231
+ vignette: "#120A18",
232
+ starAlpha: 0,
233
+ dayness: 0.4
234
+ };
235
+ const DUSK = {
236
+ skyTop: "#131B33",
237
+ skyHorizon: "#7A4260",
238
+ skyHorizonAlpha: 0.45,
239
+ seaColor: "#0B1526",
240
+ seaFade: "#02060E",
241
+ seaFadeAlpha: 0.52,
242
+ hazeBand: "#3A2C4E",
243
+ hazeAlpha: 0.3,
244
+ cloudRim: "#5A4668",
245
+ cloudRimAlpha: 0.4,
246
+ cloudBody: "#12141F",
247
+ cloudBodyAlpha: 0.92,
248
+ peakNear: "#0A1220",
249
+ peakFar: "#070D18",
250
+ glitter: "#D8C4D8",
251
+ glitterAlpha: 0.8,
252
+ bloom: "#C0A8C4",
253
+ bloomAlpha: 0.18,
254
+ glow: "#E4D2E4",
255
+ glowAlpha: 0.36,
256
+ disc: "#F2E4E8",
257
+ horizonLine: "#B49CB4",
258
+ horizonLineAlpha: 0.18,
259
+ underLine: "#D0BCD0",
260
+ underLineAlpha: 0.34,
261
+ vignette: "#050408",
262
+ starAlpha: 0.5,
263
+ dayness: 0
264
+ };
265
+
266
+ /** [minutes since midnight, palette] — adjacent identical entries hold. */
267
+ const KEYFRAMES = [[0, NIGHT], [300, NIGHT],
268
+ // 05:00 — night holds
269
+ [360, DAWN],
270
+ // 06:00
271
+ [415, SUNRISE],
272
+ // 06:55
273
+ [510, DAY],
274
+ // 08:30
275
+ [1050, DAY],
276
+ // 17:30 — day holds
277
+ [1080, GOLDEN],
278
+ // 18:00
279
+ [1130, SUNSET],
280
+ // 18:50
281
+ [1180, DUSK],
282
+ // 19:40
283
+ [1245, NIGHT],
284
+ // 20:45
285
+ [1440, NIGHT]];
286
+ function lerpPalette(a, b, t) {
287
+ const out = {};
288
+ for (const k of Object.keys(a)) {
289
+ const av = a[k];
290
+ const bv = b[k];
291
+ out[k] = typeof av === "number" ? av + (bv - av) * t : lerpColor(av, bv, t);
292
+ }
293
+ return out;
294
+ }
295
+ function paletteAt(minutes) {
296
+ for (let i = 0; i < KEYFRAMES.length - 1; i++) {
297
+ const [t0, p0] = KEYFRAMES[i];
298
+ const [t1, p1] = KEYFRAMES[i + 1];
299
+ if (minutes >= t0 && minutes <= t1) {
300
+ if (p0 === p1 || t1 === t0) return p0;
301
+ return lerpPalette(p0, p1, (minutes - t0) / (t1 - t0));
302
+ }
303
+ }
304
+ return NIGHT;
305
+ }
306
+
307
+ // ============================================================================
308
+ // The workday remap — THE mapping LIVE mode runs on
309
+ // ============================================================================
310
+
311
+ /**
312
+ * Real minutes → scene minutes, compressing the planet's day onto a working
313
+ * human's: dawn as you sit down (~8:00), sunrise ~9:00, noon at lunch, golden
314
+ * hour ~16:30, sunset as the workday ends (~17:30), night after ~20:00. A 9–5
315
+ * session sees the whole cycle; the honest 1:1 mapping (auditioned against
316
+ * this via two play buttons, and cut) held featureless DAY for all of it —
317
+ * the pretty parts fired while nobody was at their desk.
318
+ *
319
+ * The scrub slider and the ▶ movie also run through this (the slider thumb is
320
+ * a WALL clock; the scene is always the remap of it).
321
+ *
322
+ * Anchors are [real, scene] minute pairs, strictly increasing, folded across
323
+ * midnight so the night segment (20:00 → 7:30 next day) is one linear piece.
324
+ */
325
+ const WORKDAY_ANCHORS = [[450, 330],
326
+ // 07:30 → 05:30 pre-dawn
327
+ [540, 420],
328
+ // 09:00 → 07:00 just after sunrise
329
+ [750, 720],
330
+ // 12:30 → noon
331
+ [990, 1080],
332
+ // 16:30 → 18:00 golden hour
333
+ [1050, 1130],
334
+ // 17:30 → 18:50 sunset
335
+ [1140, 1180],
336
+ // 19:00 → 19:40 dusk
337
+ [1200, 1260],
338
+ // 20:00 → 21:00 night
339
+ [1890, 1770] // 07:30 next day → 05:30 next day (the night piece, wrapped)
340
+ ];
341
+ export function workdaySceneMinutes(realMinutes) {
342
+ let m = realMinutes;
343
+ if (m < WORKDAY_ANCHORS[0][0]) m += 1440;
344
+ for (let i = 0; i < WORKDAY_ANCHORS.length - 1; i++) {
345
+ const [r0, s0] = WORKDAY_ANCHORS[i];
346
+ const [r1, s1] = WORKDAY_ANCHORS[i + 1];
347
+ if (m >= r0 && m <= r1) {
348
+ return (s0 + (m - r0) / (r1 - r0) * (s1 - s0)) % 1440;
349
+ }
350
+ }
351
+ return realMinutes;
352
+ }
353
+
354
+ // ============================================================================
355
+ // The clock — one small render per minute, AppState-gated like the loops
356
+ // ============================================================================
357
+
358
+ function nowMinutes() {
359
+ const d = new Date();
360
+ return d.getHours() * 60 + d.getMinutes();
361
+ }
362
+ function useMinuteClock(enabled) {
363
+ const [minutes, setMinutes] = useState(nowMinutes);
364
+ useEffect(() => {
365
+ if (!enabled) return;
366
+ let timeout = null;
367
+ let interval = null;
368
+ const stop = () => {
369
+ if (timeout) clearTimeout(timeout);
370
+ if (interval) clearInterval(interval);
371
+ timeout = interval = null;
372
+ };
373
+ // Snap to now, then align the tick to the minute boundary.
374
+ const start = () => {
375
+ setMinutes(nowMinutes());
376
+ const d = new Date();
377
+ const untilNext = 60_000 - (d.getSeconds() * 1000 + d.getMilliseconds()) + 50;
378
+ timeout = setTimeout(() => {
379
+ setMinutes(nowMinutes());
380
+ interval = setInterval(() => setMinutes(nowMinutes()), 60_000);
381
+ }, untilNext);
382
+ };
383
+ start();
384
+ const sub = AppState.addEventListener("change", state => {
385
+ stop();
386
+ // Re-snapping on foreground means an hour in the background comes back
387
+ // to the RIGHT sky, not a stale one.
388
+ if (state === "active") start();
389
+ });
390
+ return () => {
391
+ stop();
392
+ sub.remove();
393
+ };
394
+ }, [enabled]);
395
+ return minutes;
396
+ }
397
+
398
+ // ============================================================================
399
+ // Shared geometry (same specs as the fixed siblings)
400
+ // ============================================================================
401
+
402
+ /** Stride 3: x, y, size — Moonlight's star field. */
403
+ const SKY_STAR_COUNT = 22;
404
+ const SKY_STARS = scatter(0x52b7, SKY_STAR_COUNT * 3);
405
+ const CLOUDS = [{
406
+ at: [0.16, 0.3],
407
+ puffs: [[-62, 4, 150, 20], [-44, -8, 62, 24], [-4, -14, 74, 30], [38, -4, 54, 20]],
408
+ bodyAlpha: 1
409
+ }, {
410
+ at: [0.84, 0.37],
411
+ puffs: [[-55, 3, 130, 18], [-30, -8, 56, 22], [8, -13, 64, 27], [42, -3, 44, 17]],
412
+ bodyAlpha: 1
413
+ }, {
414
+ at: [0.46, 0.425],
415
+ puffs: [[-40, 2, 96, 13], [-12, -6, 48, 16], [22, -2, 38, 12]],
416
+ bodyAlpha: 0.95
417
+ }];
418
+
419
+ /** The lit rim tilts toward wherever the light currently is. */
420
+ function rimFor(cloudX, lightXFrac) {
421
+ if (lightXFrac === null) return [0, -3.5];
422
+ const dx = Math.max(-4, Math.min(4, (lightXFrac - cloudX) * 10));
423
+ return [dx, -3.5];
424
+ }
425
+ function cloudPuffs(cloud, cx, cy, rim, rimColor, bodyColor, key) {
426
+ const parts = [];
427
+ for (let i = 0; i < cloud.puffs.length; i++) {
428
+ const [dx, dy, w, h] = cloud.puffs[i];
429
+ parts.push(/*#__PURE__*/_jsx(View, {
430
+ style: {
431
+ position: "absolute",
432
+ left: cx + dx + rim[0] - w / 2,
433
+ top: cy + dy + rim[1] - h / 2,
434
+ width: w,
435
+ height: h,
436
+ borderRadius: h / 2,
437
+ backgroundColor: rimColor
438
+ }
439
+ }, `${key}-r${i}`));
440
+ }
441
+ for (let i = 0; i < cloud.puffs.length; i++) {
442
+ const [dx, dy, w, h] = cloud.puffs[i];
443
+ parts.push(/*#__PURE__*/_jsx(View, {
444
+ style: {
445
+ position: "absolute",
446
+ left: cx + dx - w / 2,
447
+ top: cy + dy - h / 2,
448
+ width: w,
449
+ height: h,
450
+ borderRadius: h / 2,
451
+ backgroundColor: bodyColor
452
+ }
453
+ }, `${key}-b${i}`));
454
+ }
455
+ return parts;
456
+ }
457
+
458
+ /** [xFrac, yFrac (of the horizon), wing length]. */
459
+ const GULLS = [[0.2, 0.42, 6], [0.3, 0.28, 5], [0.42, 0.52, 4]];
460
+
461
+ /** [xFrac, base width, height, near?] — near peaks take peakNear. */
462
+ const PEAKS = [[0.03, 120, 24, 1], [0.11, 96, 36, 0], [0.2, 140, 24, 1], [0.29, 76, 15, 0], [0.9, 96, 18, 1], [0.98, 130, 27, 0]];
463
+ const SAILS = [[0.07, 6], [0.14, 4.5], [0.23, 5.5]];
464
+ const SHORE_LIGHTS = [0.06, 0.13, 0.18, 0.26];
465
+
466
+ // ============================================================================
467
+ // The glade — glitter column under whichever body is up
468
+ // ============================================================================
469
+
470
+ /** Stride 4: depth, x jitter, width jitter, alpha jitter. */
471
+ const GLADE_LAYERS = [{
472
+ count: 44,
473
+ seed: 0x3aa1
474
+ }, {
475
+ count: 34,
476
+ seed: 0x77c2
477
+ }, {
478
+ count: 26,
479
+ seed: 0xb4e9
480
+ }];
481
+ const GLADE_TABLES = GLADE_LAYERS.map(l => scatter(l.seed, l.count * 4));
482
+ const ROW_STEP = 7;
483
+ const GlitterLayer = /*#__PURE__*/memo(function GlitterLayer({
484
+ layerIndex,
485
+ drive,
486
+ lightXFrac,
487
+ color,
488
+ alphaScale,
489
+ width,
490
+ height,
491
+ animated
492
+ }) {
493
+ const sway = usePulse(drive === "swayA" ? 9000 : 12500, animated && drive !== "breathe");
494
+ const breathe = usePulse(6200, animated && drive === "breathe");
495
+ const lightX = width * lightXFrac;
496
+ const horizonY = height * HORIZON;
497
+ const layer = GLADE_LAYERS[layerIndex];
498
+ const table = GLADE_TABLES[layerIndex];
499
+ const blocks = [];
500
+ for (let i = 0; i < layer.count; i++) {
501
+ const d = table[i * 4];
502
+ const jx = table[i * 4 + 1];
503
+ const jw = table[i * 4 + 2];
504
+ const ja = table[i * 4 + 3];
505
+ const y = horizonY + 4 + d * (height - horizonY) * 0.94;
506
+ const halfSpread = width * (0.03 + d * 0.16);
507
+ const x = lightX + (jx - 0.5) * 2 * halfSpread;
508
+ const blockW = 6 + d * 26 + jw * 10;
509
+ const blockH = d < 0.3 ? 1 : d < 0.62 ? 2 : 3;
510
+ const arc = Math.sin(Math.PI * (0.12 + d * 0.82));
511
+ const centered = Math.max(0.25, 1 - Math.abs(jx - 0.5) * 1.4);
512
+ const alpha = (0.16 + arc * 0.48) * centered * (0.75 + ja * 0.25) * alphaScale;
513
+ if (alpha < 0.02) continue;
514
+ blocks.push(/*#__PURE__*/_jsx(View, {
515
+ style: {
516
+ position: "absolute",
517
+ left: x - blockW / 2,
518
+ top: Math.round(y / ROW_STEP) * ROW_STEP,
519
+ width: blockW,
520
+ height: blockH,
521
+ borderRadius: 0.5,
522
+ backgroundColor: withAlpha(color, Math.min(1, alpha))
523
+ }
524
+ }, i));
525
+ }
526
+ const style = drive === "breathe" ? {
527
+ opacity: breathe.interpolate({
528
+ inputRange: [0, 1],
529
+ outputRange: [0.55, 1]
530
+ })
531
+ } : {
532
+ transform: [{
533
+ translateX: sway.interpolate({
534
+ inputRange: [0, 1],
535
+ outputRange: drive === "swayA" ? [-7, 7] : [6, -6]
536
+ })
537
+ }]
538
+ };
539
+ return /*#__PURE__*/_jsx(Animated.View, {
540
+ style: [absoluteFill, style],
541
+ pointerEvents: "none",
542
+ children: /*#__PURE__*/_jsx(RasterLayer, {
543
+ style: absoluteFill,
544
+ children: blocks
545
+ })
546
+ });
547
+ });
548
+
549
+ // ============================================================================
550
+ // The scene
551
+ // ============================================================================
552
+
553
+ /** Progress 0..1 → position on the east→west arc. */
554
+ function arcPos(progress, width, horizonY) {
555
+ return {
556
+ xFrac: 0.08 + 0.84 * progress,
557
+ x: width * (0.08 + 0.84 * progress),
558
+ y: horizonY - Math.sin(Math.PI * progress) * horizonY * 0.75,
559
+ altitude: Math.sin(Math.PI * progress)
560
+ };
561
+ }
562
+ export const LiveSkyTunable = /*#__PURE__*/memo(function LiveSkyTunable({
563
+ clockMinutes,
564
+ ...props
565
+ }) {
566
+ const {
567
+ width,
568
+ height,
569
+ animated
570
+ } = props;
571
+ const live = useMinuteClock(clockMinutes === undefined);
572
+ const minutes = workdaySceneMinutes(clockMinutes ?? live);
573
+ const p = paletteAt(minutes);
574
+ const horizonY = height * HORIZON;
575
+ // Light geometry is sized from the WINDOW so resizing the modal never
576
+ // swells or shrinks the blooms — only positions follow the modal.
577
+ const refW = Dimensions.get("window").width;
578
+
579
+ // Exactly one body is in its window at any minute (the windows adjoin at
580
+ // 06:30 and 19:00, where both sit half-set on opposite horizons).
581
+ const sunP = (minutes - SUN_RISE) / (SUN_SET - SUN_RISE);
582
+ const moonP = (minutes - SUN_SET + 1440) % 1440 / MOON_SPAN;
583
+ const sunUp = sunP >= 0 && sunP <= 1;
584
+ const moonUp = moonP >= 0 && moonP <= 1;
585
+ const sun = sunUp ? arcPos(sunP, width, horizonY) : null;
586
+ const moon = moonUp ? arcPos(moonP, width, horizonY) : null;
587
+ // The dominant body carries the bloom, the glade column and the cloud rims.
588
+ const dominant = sun && moon ? sun.altitude >= moon.altitude ? sun : moon : sun ?? moon;
589
+ const twinkle = usePulse(7400, animated && p.starAlpha > 0.01);
590
+ const cloudDrift = usePulse(26000, animated);
591
+ const twinkleOpacity = twinkle.interpolate({
592
+ inputRange: [0, 1],
593
+ outputRange: [0.7, 1]
594
+ });
595
+ const cloudX = cloudDrift.interpolate({
596
+ inputRange: [0, 1],
597
+ outputRange: [-8, 8]
598
+ });
599
+ const stars = [];
600
+ if (p.starAlpha > 0.01) {
601
+ for (let i = 0; i < SKY_STAR_COUNT; i++) {
602
+ const size = SKY_STARS[i * 3 + 2];
603
+ const dia = 1 + size * 1.3;
604
+ const x = SKY_STARS[i * 3] * width;
605
+ const y = SKY_STARS[i * 3 + 1] * horizonY * 0.92;
606
+ // Keep the sky clear around the current body so its bloom stays clean.
607
+ if (dominant && Math.hypot(x - dominant.x, y - dominant.y) < refW * 0.18) continue;
608
+ stars.push(/*#__PURE__*/_jsx(View, {
609
+ style: {
610
+ position: "absolute",
611
+ left: x - dia / 2,
612
+ top: y - dia / 2,
613
+ width: dia,
614
+ height: dia,
615
+ borderRadius: dia / 2,
616
+ backgroundColor: withAlpha("#C9DAF0", (0.3 + size * 0.4) * p.starAlpha)
617
+ }
618
+ }, i));
619
+ }
620
+ }
621
+ const rimColor = withAlpha(p.cloudRim, p.cloudRimAlpha);
622
+ const clouds = CLOUDS.flatMap((cloud, i) => cloudPuffs(cloud, width * cloud.at[0], height * cloud.at[1], rimFor(cloud.at[0], dominant ? dominant.xFrac : null), rimColor, withAlpha(p.cloudBody, cloud.bodyAlpha * p.cloudBodyAlpha), `c${i}`));
623
+ const gulls = p.dayness > 0.03 ? GULLS.flatMap(([xf, yf, len], i) => {
624
+ const wing = {
625
+ position: "absolute",
626
+ top: horizonY * yf,
627
+ width: len,
628
+ height: 1.4,
629
+ borderRadius: 0.7,
630
+ backgroundColor: withAlpha("#123049", 0.75 * p.dayness)
631
+ };
632
+ const x = width * xf;
633
+ return [/*#__PURE__*/_jsx(View, {
634
+ style: [wing, {
635
+ left: x - len,
636
+ transform: [{
637
+ rotate: "18deg"
638
+ }]
639
+ }]
640
+ }, `g${i}l`), /*#__PURE__*/_jsx(View, {
641
+ style: [wing, {
642
+ left: x,
643
+ transform: [{
644
+ rotate: "-18deg"
645
+ }]
646
+ }]
647
+ }, `g${i}r`)];
648
+ }) : [];
649
+ const mountains = PEAKS.map(([xf, wBase, h, near], i) => /*#__PURE__*/_jsx(View, {
650
+ style: {
651
+ position: "absolute",
652
+ left: width * xf - wBase / 2,
653
+ top: horizonY - h,
654
+ width: 0,
655
+ height: 0,
656
+ borderLeftWidth: wBase / 2,
657
+ borderRightWidth: wBase / 2,
658
+ borderBottomWidth: h,
659
+ borderLeftColor: "transparent",
660
+ borderRightColor: "transparent",
661
+ borderBottomColor: near ? p.peakNear : p.peakFar
662
+ }
663
+ }, `m${i}`));
664
+ const sails = p.dayness > 0.03 ? SAILS.map(([xf, h], i) => /*#__PURE__*/_jsx(View, {
665
+ style: {
666
+ position: "absolute",
667
+ left: width * xf,
668
+ top: horizonY - h,
669
+ width: 0,
670
+ height: 0,
671
+ borderLeftWidth: 2,
672
+ borderRightWidth: 2,
673
+ borderBottomWidth: h,
674
+ borderLeftColor: "transparent",
675
+ borderRightColor: "transparent",
676
+ borderBottomColor: withAlpha("#F2F8FC", 0.85 * p.dayness)
677
+ }
678
+ }, `s${i}`)) : [];
679
+ const nightness = 1 - p.dayness;
680
+ const lights = nightness > 0.03 ? SHORE_LIGHTS.map((xf, i) => /*#__PURE__*/_jsx(View, {
681
+ style: {
682
+ position: "absolute",
683
+ left: width * xf,
684
+ top: horizonY - 3,
685
+ width: 2,
686
+ height: 1.5,
687
+ backgroundColor: withAlpha("#E8D9A8", (0.55 + i % 2 * 0.2) * nightness)
688
+ }
689
+ }, `sl${i}`)) : [];
690
+
691
+ /** A body's disc (+ craters for the moon), drawn UNDER the sea rect so the
692
+ * horizon clips a rising or setting body for free. */
693
+ const disc = (pos, isMoon, key) => {
694
+ const dia = isMoon ? MOON_DIA : SUN_DIA;
695
+ return /*#__PURE__*/_jsx(View, {
696
+ style: {
697
+ position: "absolute",
698
+ left: pos.x - dia / 2,
699
+ top: pos.y - dia / 2,
700
+ width: dia,
701
+ height: dia,
702
+ borderRadius: dia / 2,
703
+ // Fully opaque: any translucency lets the app behind the modal
704
+ // bleed through the brightest surface in the scene.
705
+ backgroundColor: isMoon ? "#EDF3FB" : p.disc,
706
+ overflow: "hidden"
707
+ },
708
+ children: isMoon ? CRATERS.map(([dx, dy, frac], i) => {
709
+ const d = dia * frac;
710
+ return /*#__PURE__*/_jsx(View, {
711
+ style: {
712
+ position: "absolute",
713
+ left: dia / 2 + dx * dia - d / 2,
714
+ top: dia / 2 + dy * dia - d / 2,
715
+ width: d,
716
+ height: d,
717
+ borderRadius: d / 2,
718
+ backgroundColor: withAlpha("#9DB2C8", 0.32)
719
+ }
720
+ }, i);
721
+ }) : null
722
+ }, key);
723
+ };
724
+ return (
725
+ /*#__PURE__*/
726
+ // Clips: the blooms are window-sized, so a small modal crops the scene.
727
+ _jsxs(View, {
728
+ style: [absoluteFill, {
729
+ overflow: "hidden"
730
+ }],
731
+ pointerEvents: "none",
732
+ children: [/*#__PURE__*/_jsx(Base, {
733
+ color: p.skyTop
734
+ }), /*#__PURE__*/_jsx(View, {
735
+ style: {
736
+ position: "absolute",
737
+ left: 0,
738
+ right: 0,
739
+ top: 0,
740
+ height: horizonY
741
+ },
742
+ children: /*#__PURE__*/_jsx(LinearFade, {
743
+ color: p.skyHorizon,
744
+ from: 0,
745
+ to: p.skyHorizonAlpha,
746
+ direction: "down",
747
+ bands: 20,
748
+ flattenBase: p.skyTop
749
+ })
750
+ }), p.starAlpha > 0.01 ? /*#__PURE__*/_jsx(Animated.View, {
751
+ style: [absoluteFill, {
752
+ opacity: twinkleOpacity
753
+ }],
754
+ pointerEvents: "none",
755
+ children: /*#__PURE__*/_jsx(RasterLayer, {
756
+ style: absoluteFill,
757
+ children: stars
758
+ })
759
+ }) : null, /*#__PURE__*/_jsx(Animated.View, {
760
+ style: [absoluteFill, {
761
+ transform: [{
762
+ translateX: cloudX
763
+ }]
764
+ }],
765
+ pointerEvents: "none",
766
+ children: /*#__PURE__*/_jsxs(RasterLayer, {
767
+ style: absoluteFill,
768
+ children: [clouds, gulls]
769
+ })
770
+ }), dominant ? /*#__PURE__*/_jsxs(_Fragment, {
771
+ children: [/*#__PURE__*/_jsx(RadialGlow, {
772
+ size: refW * 0.46,
773
+ color: p.bloom,
774
+ alpha: p.bloomAlpha,
775
+ rings: 20,
776
+ falloff: 1.9,
777
+ style: {
778
+ position: "absolute",
779
+ left: dominant.x - refW * 0.23,
780
+ top: dominant.y - refW * 0.23
781
+ }
782
+ }), /*#__PURE__*/_jsx(RadialGlow, {
783
+ size: 118,
784
+ color: p.glow,
785
+ alpha: p.glowAlpha,
786
+ rings: 10,
787
+ falloff: 1.6,
788
+ style: {
789
+ position: "absolute",
790
+ left: dominant.x - 59,
791
+ top: dominant.y - 59
792
+ }
793
+ })]
794
+ }) : null, sun ? disc(sun, false, "sun") : null, moon ? disc(moon, true, "moon") : null, /*#__PURE__*/_jsx(View, {
795
+ style: {
796
+ position: "absolute",
797
+ left: 0,
798
+ right: 0,
799
+ top: horizonY,
800
+ bottom: 0,
801
+ backgroundColor: p.seaColor
802
+ }
803
+ }), /*#__PURE__*/_jsx(View, {
804
+ style: {
805
+ position: "absolute",
806
+ left: 0,
807
+ right: 0,
808
+ top: horizonY - 76,
809
+ height: 76
810
+ },
811
+ children: /*#__PURE__*/_jsx(LinearFade, {
812
+ color: p.hazeBand,
813
+ from: 0,
814
+ to: p.hazeAlpha,
815
+ direction: "down",
816
+ bands: 12
817
+ })
818
+ }), /*#__PURE__*/_jsxs(RasterLayer, {
819
+ style: absoluteFill,
820
+ children: [mountains, sails, lights]
821
+ }), /*#__PURE__*/_jsx(View, {
822
+ style: {
823
+ position: "absolute",
824
+ left: 0,
825
+ right: 0,
826
+ top: horizonY,
827
+ height: 1,
828
+ backgroundColor: withAlpha(p.horizonLine, p.horizonLineAlpha)
829
+ }
830
+ }), dominant ? /*#__PURE__*/_jsx(View, {
831
+ style: {
832
+ position: "absolute",
833
+ left: dominant.x - width * 0.16,
834
+ top: horizonY,
835
+ width: width * 0.32,
836
+ height: 1,
837
+ backgroundColor: withAlpha(p.underLine, p.underLineAlpha)
838
+ }
839
+ }) : null, /*#__PURE__*/_jsx(View, {
840
+ style: {
841
+ position: "absolute",
842
+ left: 0,
843
+ right: 0,
844
+ top: horizonY,
845
+ bottom: 0
846
+ },
847
+ children: /*#__PURE__*/_jsx(LinearFade, {
848
+ color: p.seaFade,
849
+ from: 0,
850
+ to: p.seaFadeAlpha,
851
+ direction: "down",
852
+ bands: 12
853
+ })
854
+ }), dominant ? /*#__PURE__*/_jsxs(_Fragment, {
855
+ children: [/*#__PURE__*/_jsx(GlitterLayer, {
856
+ layerIndex: 0,
857
+ drive: "swayA",
858
+ lightXFrac: dominant.xFrac,
859
+ color: p.glitter,
860
+ alphaScale: p.glitterAlpha,
861
+ ...props
862
+ }), /*#__PURE__*/_jsx(GlitterLayer, {
863
+ layerIndex: 1,
864
+ drive: "swayB",
865
+ lightXFrac: dominant.xFrac,
866
+ color: p.glitter,
867
+ alphaScale: p.glitterAlpha,
868
+ ...props
869
+ }), /*#__PURE__*/_jsx(GlitterLayer, {
870
+ layerIndex: 2,
871
+ drive: "breathe",
872
+ lightXFrac: dominant.xFrac,
873
+ color: p.glitter,
874
+ alphaScale: p.glitterAlpha,
875
+ ...props
876
+ })]
877
+ }) : null, /*#__PURE__*/_jsx(Vignette, {
878
+ color: p.vignette,
879
+ alpha: 0.4,
880
+ spread: 0.34
881
+ })]
882
+ })
883
+ );
884
+ });
885
+ export const LiveSky = /*#__PURE__*/memo(function LiveSky(props) {
886
+ // A non-null scrub (the switcher's slider) freezes the scene at that minute
887
+ // and stops the tick; LIVE clears it.
888
+ const scrub = useSkyScrub();
889
+ return /*#__PURE__*/_jsx(LiveSkyTunable, {
890
+ ...props,
891
+ clockMinutes: scrub ?? undefined
892
+ });
893
+ });