@konitif/theme 0.284.2

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 (48) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +56 -0
  3. package/package.json +56 -0
  4. package/reference/README.md +10 -0
  5. package/reference/catalog.json +129 -0
  6. package/reference/diagrams.json +60 -0
  7. package/src/ambient/SpatialAmbientCanvas.svelte +148 -0
  8. package/src/ambient/SpatialAmbientParticles.svelte +89 -0
  9. package/src/ambient/SpatialAmbientRuntime.svelte +306 -0
  10. package/src/ambient/SpatialProjectionGrid.svelte +252 -0
  11. package/src/ambient/shaders/noise.glsl +1 -0
  12. package/src/ambient/shaders/particleField.glsl +1 -0
  13. package/src/ambient/shaders/spatialAmbient.frag.glsl +1 -0
  14. package/src/ambient/shaders/spatialAmbient.vert.glsl +1 -0
  15. package/src/ambient/shaders/volumetricFog.glsl +1 -0
  16. package/src/ambient/spatialAmbientStore.ts +3 -0
  17. package/src/ambient/spatialAmbientTypes.ts +11 -0
  18. package/src/ambient/spatialProjectionGridModel.ts +276 -0
  19. package/src/ambient/spatialProjectionGridPresets.ts +152 -0
  20. package/src/ambient/spatialProjectionGridTypes.ts +72 -0
  21. package/src/ambient/themeToAmbientUniforms.ts +3 -0
  22. package/src/components/KonitifBadge.svelte +2 -0
  23. package/src/components/KonitifButton.svelte +2 -0
  24. package/src/components/KonitifCard.svelte +2 -0
  25. package/src/components/KonitifGlassSurface.svelte +3 -0
  26. package/src/components/KonitifIconFrame.svelte +2 -0
  27. package/src/components/KonitifPanel.svelte +2 -0
  28. package/src/depth/SpatialDepthLayer.svelte +49 -0
  29. package/src/depth/SpatialDepthStack.svelte +25 -0
  30. package/src/depth/spatialDepthTokens.css +82 -0
  31. package/src/depth/spatialDepthTypes.ts +79 -0
  32. package/src/focus/FocusPlaneProvider.svelte +43 -0
  33. package/src/focus/PerceptualSurface.svelte +146 -0
  34. package/src/focus/focusDepthMap.ts +33 -0
  35. package/src/focus/perceptualFocusStore.ts +98 -0
  36. package/src/focus/perceptualFocusTypes.ts +38 -0
  37. package/src/focus/usePerceptualFocus.ts +18 -0
  38. package/src/index.ts +22 -0
  39. package/src/konitifRuntimePhaseTokens.ts +15 -0
  40. package/src/konitifTheme.ts +2 -0
  41. package/src/konitifThemeAdapter.ts +13 -0
  42. package/src/konitifTokens.css +201 -0
  43. package/src/konitifWorkbenchThemeRuntime.ts +35 -0
  44. package/src/runtime/RuntimePhaseTintProvider.svelte +28 -0
  45. package/src/runtime/runtimePhaseIconMap.ts +1 -0
  46. package/src/runtime/runtimePhaseVisualMap.ts +37 -0
  47. package/src/runtime/runtimeSpatialReactivity.ts +307 -0
  48. package/src/runtime/runtimeSpatialStateStore.ts +53 -0
@@ -0,0 +1,306 @@
1
+ <script lang="ts">
2
+ import { onDestroy, onMount } from 'svelte';
3
+ import type { StageAmbientProjection } from '@konitif/workbench';
4
+ import { globalPerceptualFocusStore } from '../focus/perceptualFocusStore';
5
+ import { normalizeKonitifRuntimePhase, type RuntimePhase } from '../konitifRuntimePhaseTokens';
6
+ import {
7
+ createRuntimeSpatialState,
8
+ interpolateRuntimeSpatialState,
9
+ type RuntimeSpatialState
10
+ } from '../runtime/runtimeSpatialReactivity';
11
+ import SpatialAmbientCanvas from './SpatialAmbientCanvas.svelte';
12
+ import SpatialAmbientParticles from './SpatialAmbientParticles.svelte';
13
+ import SpatialProjectionGrid from './SpatialProjectionGrid.svelte';
14
+ import type { AmbientQuality } from './spatialAmbientTypes';
15
+ import type { SpatialProjectionGridConfig } from './spatialProjectionGridTypes';
16
+
17
+ export let phase: RuntimePhase = 'LAUNCH_GATE';
18
+ export let quality: AmbientQuality = 'medium';
19
+ export let reducedMotion = false;
20
+ export let themeMode: 'dark' | 'light' = 'dark';
21
+ export let spatialOverrides: Partial<RuntimeSpatialState> | null = null;
22
+ export let gridConfig: Partial<SpatialProjectionGridConfig> | null = null;
23
+ export let stageAmbient: StageAmbientProjection | null = null;
24
+
25
+ let prefersReducedMotion = false;
26
+ let isDocumentHidden = false;
27
+ let reducedMotionQuery: MediaQueryList | null = null;
28
+ let focusState = globalPerceptualFocusStore.getState();
29
+ let renderedPhase: RuntimePhase | null = null;
30
+ let renderedSpatialState: RuntimeSpatialState | null = null;
31
+ let vectorTransitionTarget: RuntimePhase | null = null;
32
+ let vectorTransitionFrame: number | null = null;
33
+ let vectorTransitionStartedAt = 0;
34
+
35
+ const phaseVectorFadeDuration = 680;
36
+
37
+ $: resolvedPhase = normalizeKonitifRuntimePhase(phase);
38
+ $: effectiveReducedMotion = reducedMotion || prefersReducedMotion || isDocumentHidden;
39
+ $: targetSpatialState = {
40
+ ...createRuntimeSpatialState(resolvedPhase, {
41
+ quality,
42
+ reducedMotion: reducedMotion || prefersReducedMotion,
43
+ hidden: isDocumentHidden
44
+ }),
45
+ ...(spatialOverrides ?? {}),
46
+ phase: resolvedPhase
47
+ };
48
+ $: activeSpatialState = renderedSpatialState ?? targetSpatialState;
49
+ $: ambientStyle = createAmbientStyle(activeSpatialState);
50
+ $: if (quality !== 'off') {
51
+ syncRuntimeVector(resolvedPhase, targetSpatialState, effectiveReducedMotion);
52
+ } else {
53
+ clearVectorTransition();
54
+ renderedPhase = null;
55
+ renderedSpatialState = null;
56
+ vectorTransitionTarget = null;
57
+ }
58
+
59
+ onMount(() => {
60
+ const unsubscribeFocus = globalPerceptualFocusStore.subscribe((state) => {
61
+ focusState = state;
62
+ });
63
+
64
+ if (typeof document !== 'undefined') {
65
+ isDocumentHidden = document.hidden;
66
+ const handleVisibilityChange = (): void => {
67
+ isDocumentHidden = document.hidden;
68
+ };
69
+
70
+ document.addEventListener('visibilitychange', handleVisibilityChange);
71
+
72
+ if (typeof window === 'undefined' || !window.matchMedia) {
73
+ return () => {
74
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
75
+ unsubscribeFocus();
76
+ };
77
+ }
78
+
79
+ reducedMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
80
+ prefersReducedMotion = reducedMotionQuery.matches;
81
+
82
+ const handleChange = (event: MediaQueryListEvent): void => {
83
+ prefersReducedMotion = event.matches;
84
+ };
85
+
86
+ reducedMotionQuery.addEventListener('change', handleChange);
87
+
88
+ return () => {
89
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
90
+ reducedMotionQuery?.removeEventListener('change', handleChange);
91
+ unsubscribeFocus();
92
+ };
93
+ }
94
+
95
+ return unsubscribeFocus;
96
+ });
97
+
98
+ onDestroy(() => {
99
+ clearVectorTransition();
100
+ reducedMotionQuery = null;
101
+ });
102
+
103
+ function createAmbientStyle(state: RuntimeSpatialState): string {
104
+ const focusPoint = stageAmbient?.focusPoint ?? focusState.focusPoint;
105
+ const focusStrength = stageAmbient
106
+ ? Math.max(0.2, 1 - stageAmbient.focusDepth * 0.42)
107
+ : focusState.focusStrength;
108
+
109
+ return [
110
+ `--k-runtime-tint: ${state.tint}`,
111
+ `--k-runtime-tint-rgb: ${state.tintRgb}`,
112
+ `--k-runtime-intensity: ${state.lightIntensity}`,
113
+ `--k-runtime-fog-density: ${state.fogDensity}`,
114
+ `--k-runtime-particle-density: ${state.particleDensity}`,
115
+ `--k-runtime-particle-speed: ${state.particleSpeed}`,
116
+ `--k-runtime-motion-intensity: ${state.motionIntensity}`,
117
+ `--k-runtime-tilt-strength: ${state.tiltStrength}`,
118
+ `--k-runtime-focus-falloff: ${state.focusFalloff}`,
119
+ `--k-runtime-instability: ${state.instability}`,
120
+ `--k-focus-x: ${focusPoint.x}`,
121
+ `--k-focus-y: ${focusPoint.y}`,
122
+ `--k-focus-strength: ${focusStrength}`
123
+ ].join('; ');
124
+ }
125
+
126
+ function syncRuntimeVector(
127
+ phaseValue: RuntimePhase,
128
+ state: RuntimeSpatialState,
129
+ shouldReduceMotion: boolean
130
+ ): void {
131
+ if (typeof window === 'undefined' || shouldReduceMotion || renderedSpatialState === null || renderedPhase === null) {
132
+ clearVectorTransition();
133
+ renderedPhase = phaseValue;
134
+ renderedSpatialState = { ...state };
135
+ vectorTransitionTarget = null;
136
+ return;
137
+ }
138
+
139
+ if (phaseValue === renderedPhase) {
140
+ if (vectorTransitionTarget === null) {
141
+ renderedSpatialState = { ...state };
142
+ }
143
+ return;
144
+ }
145
+
146
+ if (phaseValue === vectorTransitionTarget) {
147
+ return;
148
+ }
149
+
150
+ startVectorTransition(renderedSpatialState, { ...state }, phaseValue);
151
+ }
152
+
153
+ function startVectorTransition(fromState: RuntimeSpatialState, toState: RuntimeSpatialState, targetPhase: RuntimePhase): void {
154
+ if (typeof window === 'undefined') {
155
+ renderedPhase = targetPhase;
156
+ renderedSpatialState = { ...toState };
157
+ vectorTransitionTarget = null;
158
+ return;
159
+ }
160
+
161
+ clearVectorTransition();
162
+ vectorTransitionTarget = targetPhase;
163
+ vectorTransitionStartedAt = window.performance.now();
164
+
165
+ const step = (now: number): void => {
166
+ const progress = (now - vectorTransitionStartedAt) / phaseVectorFadeDuration;
167
+ renderedSpatialState = interpolateRuntimeSpatialState(fromState, toState, progress);
168
+
169
+ if (progress < 1) {
170
+ vectorTransitionFrame = window.requestAnimationFrame(step);
171
+ return;
172
+ }
173
+
174
+ renderedPhase = targetPhase;
175
+ renderedSpatialState = { ...toState };
176
+ vectorTransitionTarget = null;
177
+ vectorTransitionFrame = null;
178
+ };
179
+
180
+ vectorTransitionFrame = window.requestAnimationFrame(step);
181
+ }
182
+
183
+ function clearVectorTransition(): void {
184
+ if (typeof window !== 'undefined' && vectorTransitionFrame !== null) {
185
+ window.cancelAnimationFrame(vectorTransitionFrame);
186
+ }
187
+ vectorTransitionFrame = null;
188
+ }
189
+ </script>
190
+
191
+ {#if quality !== 'off' && activeSpatialState}
192
+ <div
193
+ class="konitif-ambient workbench-theme-ambient"
194
+ data-workbench-theme-ambient
195
+ data-workbench-theme-family="konitif"
196
+ data-quality={quality}
197
+ data-theme-mode={themeMode}
198
+ aria-hidden="true"
199
+ >
200
+ <div
201
+ class="konitif-ambient__phase-layer"
202
+ style={ambientStyle}
203
+ data-phase={activeSpatialState.phase}
204
+ data-reduced-motion={effectiveReducedMotion}
205
+ >
206
+ <SpatialAmbientCanvas
207
+ phase={activeSpatialState.phase}
208
+ {quality}
209
+ reducedMotion={effectiveReducedMotion}
210
+ spatialState={activeSpatialState}
211
+ {themeMode}
212
+ />
213
+ <SpatialProjectionGrid
214
+ phase={activeSpatialState.phase}
215
+ {quality}
216
+ reducedMotion={effectiveReducedMotion}
217
+ config={gridConfig}
218
+ {themeMode}
219
+ />
220
+ <SpatialAmbientParticles
221
+ phase={activeSpatialState.phase}
222
+ {quality}
223
+ reducedMotion={effectiveReducedMotion}
224
+ spatialState={activeSpatialState}
225
+ {themeMode}
226
+ />
227
+ <div class="konitif-frustum-vignette"></div>
228
+ <div class="konitif-corner-tilt"></div>
229
+ </div>
230
+ </div>
231
+ {/if}
232
+
233
+ <style>
234
+ .konitif-ambient {
235
+ position: absolute;
236
+ inset: 0;
237
+ z-index: 0;
238
+ overflow: hidden;
239
+ pointer-events: none;
240
+ background: var(--k-bg-root);
241
+ }
242
+
243
+ .konitif-ambient__phase-layer {
244
+ position: absolute;
245
+ inset: 0;
246
+ overflow: hidden;
247
+ pointer-events: none;
248
+ background:
249
+ radial-gradient(circle at 50% 35%, rgba(var(--k-runtime-tint-rgb), calc(var(--k-runtime-intensity) * 0.34)), transparent 34%),
250
+ radial-gradient(circle at 12% 18%, var(--k-frustum-light), transparent 28%),
251
+ linear-gradient(180deg, var(--k-bg-space, var(--k-bg-root)), var(--k-bg-space-deep, var(--k-bg-root)));
252
+ }
253
+
254
+ .konitif-ambient[data-theme-mode='light'] .konitif-ambient__phase-layer {
255
+ background:
256
+ radial-gradient(circle at 68% 16%, var(--k-frustum-light-core), transparent 18%),
257
+ radial-gradient(circle at 50% 44%, rgba(var(--k-runtime-tint-rgb), calc(var(--k-runtime-intensity) * 0.085)), transparent 30%),
258
+ radial-gradient(ellipse at 50% 56%, var(--k-frustum-fog), transparent 44%),
259
+ linear-gradient(135deg, rgba(255, 246, 230, 0.26) 0%, transparent 32%),
260
+ linear-gradient(315deg, var(--k-frustum-shadow) 0%, transparent 30%),
261
+ linear-gradient(180deg, var(--k-bg-space), var(--k-bg-space-deep));
262
+ }
263
+
264
+ .konitif-frustum-vignette,
265
+ .konitif-corner-tilt {
266
+ position: absolute;
267
+ inset: 0;
268
+ }
269
+
270
+ .konitif-frustum-vignette {
271
+ background:
272
+ radial-gradient(circle at 50% 42%, transparent 0%, transparent 42%, rgba(0, 0, 0, calc(0.18 + var(--k-runtime-fog-density) * 0.18)) 100%),
273
+ linear-gradient(115deg, transparent 0%, rgba(var(--k-runtime-tint-rgb), 0.035) 48%, transparent 68%);
274
+ mix-blend-mode: multiply;
275
+ }
276
+
277
+ .konitif-ambient[data-theme-mode='light'] .konitif-frustum-vignette {
278
+ background:
279
+ radial-gradient(circle at 50% 42%, transparent 0%, transparent 54%, rgba(110, 135, 165, calc(0.08 + var(--k-runtime-fog-density) * 0.08)) 100%),
280
+ linear-gradient(35deg, rgba(110, 135, 165, 0.08) 0%, transparent 38%),
281
+ linear-gradient(120deg, transparent 0%, rgba(var(--k-runtime-tint-rgb), 0.026) 48%, transparent 72%);
282
+ mix-blend-mode: multiply;
283
+ }
284
+
285
+ .konitif-corner-tilt {
286
+ inset: -8%;
287
+ background:
288
+ linear-gradient(135deg, transparent 0%, rgba(255, 255, 255, 0.035) 48%, transparent 64%),
289
+ linear-gradient(315deg, transparent 0%, rgba(var(--k-runtime-tint-rgb), 0.045) 52%, transparent 72%);
290
+ opacity: 0.72;
291
+ }
292
+
293
+ .konitif-ambient[data-theme-mode='light'] .konitif-corner-tilt {
294
+ background:
295
+ linear-gradient(135deg, rgba(255, 238, 205, 0.14) 0%, transparent 38%),
296
+ linear-gradient(315deg, rgba(110, 135, 165, 0.1) 0%, transparent 34%);
297
+ opacity: 0.58;
298
+ }
299
+
300
+ @media (prefers-reduced-motion: reduce) {
301
+ .konitif-corner-tilt {
302
+ animation: none;
303
+ transform: none;
304
+ }
305
+ }
306
+ </style>
@@ -0,0 +1,252 @@
1
+ <script context="module" lang="ts">
2
+ let spatialProjectionGridInstanceSequence = 0;
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import type { RuntimePhase } from '../konitifRuntimePhaseTokens';
7
+ import type { AmbientQuality } from './spatialAmbientTypes';
8
+ import {
9
+ createSpatialProjectionGridGeometry,
10
+ resolveSpatialProjectionGridConfig
11
+ } from './spatialProjectionGridModel';
12
+ import type { SpatialProjectionGridConfig } from './spatialProjectionGridTypes';
13
+
14
+ export let config: Partial<SpatialProjectionGridConfig> | null = null;
15
+ export let phase: RuntimePhase | string = 'LAUNCH_GATE';
16
+ export let quality: AmbientQuality = 'medium';
17
+ export let reducedMotion = false;
18
+ export let animated = true;
19
+ export let themeMode: 'dark' | 'light' = 'dark';
20
+
21
+ const instanceId = `konitif-grid-${++spatialProjectionGridInstanceSequence}`;
22
+
23
+ $: resolvedConfig = resolveSpatialProjectionGridConfig({ phase, quality, reducedMotion, config });
24
+ $: renderConfig = resolveRenderConfig(resolvedConfig, themeMode);
25
+ $: geometry = createSpatialProjectionGridGeometry(renderConfig);
26
+ $: shouldRender = quality !== 'off' && renderConfig.enabled;
27
+ $: shouldAnimate = animated && !reducedMotion && renderConfig.animationSpeed > 0;
28
+ $: gridStyle = [
29
+ `--k-space-grid-major-opacity: ${renderConfig.majorLineOpacity}`,
30
+ `--k-space-grid-minor-opacity: ${renderConfig.minorLineOpacity}`,
31
+ `--k-space-grid-node-opacity: ${renderConfig.nodeOpacity}`,
32
+ `--k-space-grid-origin-opacity: ${renderConfig.originNodeOpacity}`,
33
+ `--k-space-grid-glow: ${renderConfig.glowIntensity}`,
34
+ `--k-space-grid-fog-opacity: ${renderConfig.fogIntensity}`,
35
+ `--k-space-grid-drift-duration: ${Math.max(18, 54 - renderConfig.animationSpeed * 34)}s`
36
+ ].join('; ');
37
+
38
+ function resolveRenderConfig(
39
+ currentConfig: SpatialProjectionGridConfig,
40
+ mode: 'dark' | 'light'
41
+ ): SpatialProjectionGridConfig {
42
+ if (mode !== 'light') {
43
+ return currentConfig;
44
+ }
45
+
46
+ return {
47
+ ...currentConfig,
48
+ majorLineOpacity: clamp01(currentConfig.majorLineOpacity * 1.14 + 0.025),
49
+ minorLineOpacity: clamp01(currentConfig.minorLineOpacity * 0.56),
50
+ nodeOpacity: clamp01(currentConfig.nodeOpacity * 1.08),
51
+ originNodeOpacity: clamp01(currentConfig.originNodeOpacity * 1.12),
52
+ glowIntensity: clamp01(currentConfig.glowIntensity * 0.58),
53
+ fogIntensity: clamp01(currentConfig.fogIntensity * 0.72),
54
+ animationSpeed: clamp01(currentConfig.animationSpeed * 0.72)
55
+ };
56
+ }
57
+
58
+ function clamp01(value: number): number {
59
+ return Math.min(1, Math.max(0, value));
60
+ }
61
+ </script>
62
+
63
+ {#if shouldRender}
64
+ <div
65
+ class:spatial-grid--animated={shouldAnimate}
66
+ class="spatial-grid"
67
+ data-quality={quality}
68
+ data-phase={phase}
69
+ data-theme-mode={themeMode}
70
+ style={gridStyle}
71
+ aria-hidden="true"
72
+ >
73
+ <div class="spatial-grid__fog"></div>
74
+ <svg
75
+ class="spatial-grid__svg"
76
+ viewBox={`0 0 ${geometry.width} ${geometry.height}`}
77
+ preserveAspectRatio="none"
78
+ focusable="false"
79
+ role="presentation"
80
+ >
81
+ <defs>
82
+ <filter id={`${instanceId}-node-glow`} x="-160%" y="-160%" width="420%" height="420%">
83
+ <feGaussianBlur stdDeviation="4" result="blur" />
84
+ <feMerge>
85
+ <feMergeNode in="blur" />
86
+ <feMergeNode in="SourceGraphic" />
87
+ </feMerge>
88
+ </filter>
89
+ <linearGradient id={`${instanceId}-depth-fade`} x1="0" x2="0" y1="1" y2="0">
90
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
91
+ <stop offset="54%" stop-color="white" stop-opacity="0.52" />
92
+ <stop offset="100%" stop-color="white" stop-opacity="0" />
93
+ </linearGradient>
94
+ <radialGradient id={`${instanceId}-lateral-fade`} cx="50%" cy="76%" r="72%">
95
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
96
+ <stop offset="58%" stop-color="white" stop-opacity="0.74" />
97
+ <stop offset="100%" stop-color="white" stop-opacity="0" />
98
+ </radialGradient>
99
+ <mask id={`${instanceId}-mask`}>
100
+ <rect width={geometry.width} height={geometry.height} fill={`url(#${instanceId}-depth-fade)`} />
101
+ <rect width={geometry.width} height={geometry.height} fill={`url(#${instanceId}-lateral-fade)`} opacity="0.82" />
102
+ </mask>
103
+ </defs>
104
+
105
+ <g class="spatial-grid__layer" mask={`url(#${instanceId}-mask)`}>
106
+ {#each geometry.lines as line (line.id)}
107
+ <line
108
+ class={`spatial-grid__line spatial-grid__line--${line.kind}`}
109
+ x1={line.x1}
110
+ y1={line.y1}
111
+ x2={line.x2}
112
+ y2={line.y2}
113
+ opacity={line.opacity}
114
+ />
115
+ {/each}
116
+
117
+ {#each geometry.nodes as node (node.id)}
118
+ <circle
119
+ class:spatial-grid__node--origin={node.origin}
120
+ class="spatial-grid__node"
121
+ cx={node.x}
122
+ cy={node.y}
123
+ r={node.radius}
124
+ opacity={node.opacity}
125
+ filter={`url(#${instanceId}-node-glow)`}
126
+ />
127
+ {/each}
128
+ </g>
129
+ </svg>
130
+ </div>
131
+ {/if}
132
+
133
+ <style>
134
+ .spatial-grid {
135
+ position: absolute;
136
+ inset: 0;
137
+ overflow: hidden;
138
+ pointer-events: none;
139
+ opacity: var(--k-space-grid-opacity, 0.92);
140
+ filter: blur(var(--k-space-grid-blur, 0px));
141
+ }
142
+
143
+ .spatial-grid::after {
144
+ position: absolute;
145
+ inset: 0;
146
+ content: '';
147
+ pointer-events: none;
148
+ opacity: 0;
149
+ }
150
+
151
+ .spatial-grid__fog,
152
+ .spatial-grid__svg {
153
+ position: absolute;
154
+ inset: 0;
155
+ width: 100%;
156
+ height: 100%;
157
+ }
158
+
159
+ .spatial-grid__fog {
160
+ background:
161
+ radial-gradient(ellipse at 50% 45%, var(--k-space-grid-horizon), transparent 28%),
162
+ radial-gradient(ellipse at 50% 72%, var(--k-space-grid-fog), transparent 44%);
163
+ opacity: var(--k-space-grid-fog-opacity, 0.32);
164
+ }
165
+
166
+ .spatial-grid[data-theme-mode='light'] .spatial-grid__fog {
167
+ background:
168
+ radial-gradient(ellipse at 72% 18%, rgba(255, 238, 205, 0.2), transparent 24%),
169
+ radial-gradient(ellipse at 50% 48%, var(--k-space-grid-horizon), transparent 28%),
170
+ radial-gradient(ellipse at 50% 72%, var(--k-space-grid-fog), transparent 48%);
171
+ }
172
+
173
+ .spatial-grid__svg {
174
+ overflow: visible;
175
+ }
176
+
177
+ .spatial-grid__layer {
178
+ transform-origin: 50% 82%;
179
+ }
180
+
181
+ .spatial-grid--animated .spatial-grid__layer {
182
+ animation: konitif-grid-drift var(--k-space-grid-drift-duration, 42s) ease-in-out infinite alternate;
183
+ }
184
+
185
+ .spatial-grid__line {
186
+ vector-effect: non-scaling-stroke;
187
+ stroke-linecap: round;
188
+ mix-blend-mode: screen;
189
+ }
190
+
191
+ .spatial-grid[data-theme-mode='light'] .spatial-grid__line {
192
+ mix-blend-mode: multiply;
193
+ }
194
+
195
+ .spatial-grid__line--axis {
196
+ stroke: var(--k-space-grid-axis);
197
+ stroke-width: 1.25;
198
+ }
199
+
200
+ .spatial-grid__line--major {
201
+ stroke: var(--k-space-grid-major);
202
+ stroke-width: 0.9;
203
+ }
204
+
205
+ .spatial-grid__line--minor {
206
+ stroke: var(--k-space-grid-minor);
207
+ stroke-width: 0.56;
208
+ }
209
+
210
+ .spatial-grid__line--tertiary {
211
+ stroke: var(--k-space-grid-tertiary);
212
+ stroke-width: 0.42;
213
+ }
214
+
215
+ .spatial-grid__node {
216
+ fill: var(--k-space-grid-node);
217
+ mix-blend-mode: screen;
218
+ }
219
+
220
+ .spatial-grid[data-theme-mode='light'] .spatial-grid__node {
221
+ mix-blend-mode: normal;
222
+ }
223
+
224
+ .spatial-grid__node--origin {
225
+ fill: var(--k-space-grid-origin);
226
+ }
227
+
228
+ .spatial-grid[data-theme-mode='light']::after {
229
+ background:
230
+ radial-gradient(circle at 50% 82%, rgba(75, 135, 190, 0.08), transparent 22%),
231
+ linear-gradient(35deg, rgba(110, 135, 165, 0.12) 0%, transparent 34%),
232
+ linear-gradient(160deg, rgba(255, 238, 205, 0.12) 0%, transparent 28%);
233
+ mix-blend-mode: multiply;
234
+ opacity: 1;
235
+ }
236
+
237
+ @keyframes konitif-grid-drift {
238
+ from {
239
+ transform: translate3d(0, 3px, 0);
240
+ }
241
+
242
+ to {
243
+ transform: translate3d(0, -5px, 0);
244
+ }
245
+ }
246
+
247
+ @media (prefers-reduced-motion: reduce) {
248
+ .spatial-grid--animated .spatial-grid__layer {
249
+ animation: none;
250
+ }
251
+ }
252
+ </style>
@@ -0,0 +1 @@
1
+ float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453123);}float noise(vec2 p){vec2 i=floor(p),f=fract(p);float a=hash(i),b=hash(i+vec2(1.,0.)),c=hash(i+vec2(0.,1.)),d=hash(i+vec2(1.,1.));vec2 u=f*f*(3.-2.*f);return mix(a,b,u.x)+(c-a)*u.y*(1.-u.x)+(d-b)*u.x*u.y;}
@@ -0,0 +1 @@
1
+ float particleField(vec2 uv,float time){float v=0.0;for(int i=0;i<8;i++){vec2 p=fract(uv*float(i+3)+time*.01*float(i+1));v+=smoothstep(.995,1.0,1.0-length(p-.5));}return v;}
@@ -0,0 +1 @@
1
+ precision mediump float;varying vec2 vUv;uniform float uTime;uniform vec3 uFogColor;uniform vec3 uLightColor;uniform float uIntensity;#include "noise.glsl" void main(){vec2 p=vUv-.5;float r=length(p);float beam=smoothstep(.42,0.,abs(p.x))*smoothstep(.55,.05,p.y+.15);float n=noise(vUv*8.+uTime*.03);vec3 col=mix(uFogColor,uLightColor,beam*.55+n*.08)*uIntensity*(1.-r*.8);gl_FragColor=vec4(col,max(0.,.42-r*.55));}
@@ -0,0 +1 @@
1
+ attribute vec2 position;varying vec2 vUv;void main(){vUv=position*.5+.5;gl_Position=vec4(position,0.,1.);}
@@ -0,0 +1 @@
1
+ float volumetricFog(vec2 uv,float depth){float center=1.0-length(uv-0.5);return smoothstep(0.0,1.0,center)*depth;}
@@ -0,0 +1,3 @@
1
+ import { writable } from 'svelte/store';
2
+ import type { SpatialAmbientConfig } from './spatialAmbientTypes';
3
+ export const spatialAmbientStore=writable<SpatialAmbientConfig>({phase:'LAUNCH_GATE',quality:'medium',reducedMotion:false,focusX:.5,focusY:.42});
@@ -0,0 +1,11 @@
1
+ import type { RuntimePhase } from '../konitifRuntimePhaseTokens';
2
+
3
+ export type AmbientQuality = 'off' | 'low' | 'medium' | 'high';
4
+
5
+ export type SpatialAmbientConfig = {
6
+ phase: RuntimePhase;
7
+ quality: AmbientQuality;
8
+ reducedMotion: boolean;
9
+ focusX: number;
10
+ focusY: number;
11
+ };