@shohojdhara/atomix 0.6.4 → 0.6.6

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 (83) hide show
  1. package/dist/atomix.css +117 -38
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +1 -1
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/atomix.umd.js +1 -1
  6. package/dist/atomix.umd.js.map +1 -1
  7. package/dist/atomix.umd.min.js +1 -1
  8. package/dist/charts.d.ts +30 -1
  9. package/dist/charts.js +625 -846
  10. package/dist/charts.js.map +1 -1
  11. package/dist/core.d.ts +30 -1
  12. package/dist/core.js +659 -873
  13. package/dist/core.js.map +1 -1
  14. package/dist/forms.d.ts +30 -1
  15. package/dist/forms.js +1171 -1402
  16. package/dist/forms.js.map +1 -1
  17. package/dist/heavy.d.ts +31 -89
  18. package/dist/heavy.js +975 -1195
  19. package/dist/heavy.js.map +1 -1
  20. package/dist/index.d.ts +383 -140
  21. package/dist/index.esm.js +1567 -1679
  22. package/dist/index.esm.js.map +1 -1
  23. package/dist/index.js +1556 -1667
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.min.js +1 -1
  26. package/dist/index.min.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/components/Accordion/Accordion.tsx +2 -5
  29. package/src/components/AtomixGlass/AtomixGlass.test.tsx +14 -16
  30. package/src/components/AtomixGlass/AtomixGlass.tsx +137 -364
  31. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +32 -251
  32. package/src/components/AtomixGlass/GlassFilter.tsx +62 -68
  33. package/src/components/AtomixGlass/README.md +2 -1
  34. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +19 -18
  35. package/src/components/AtomixGlass/glass-border-styles.test.ts +58 -0
  36. package/src/components/AtomixGlass/glass-border-styles.ts +136 -0
  37. package/src/components/AtomixGlass/glass-utils.ts +456 -22
  38. package/src/components/AtomixGlass/shader-utils.ts +19 -77
  39. package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +158 -537
  40. package/src/components/AtomixGlass/stories/Border.stories.tsx +149 -0
  41. package/src/components/AtomixGlass/stories/Examples.stories.tsx +229 -89
  42. package/src/components/AtomixGlass/stories/Playground.stories.tsx +29 -340
  43. package/src/components/AtomixGlass/stories/argTypes.ts +30 -13
  44. package/src/components/AtomixGlass/stories/premium-presets.ts +206 -0
  45. package/src/components/AtomixGlass/stories/shared-components.tsx +52 -8
  46. package/src/components/Badge/Badge.tsx +4 -4
  47. package/src/components/Button/Button.tsx +2 -6
  48. package/src/components/Callout/Callout.test.tsx +4 -3
  49. package/src/components/Callout/Callout.tsx +2 -5
  50. package/src/components/Dropdown/Dropdown.tsx +3 -7
  51. package/src/components/Form/Checkbox.tsx +2 -8
  52. package/src/components/Form/Input.tsx +2 -9
  53. package/src/components/Form/Radio.tsx +2 -9
  54. package/src/components/Form/Select.test.tsx +6 -6
  55. package/src/components/Form/Select.tsx +2 -7
  56. package/src/components/Form/Textarea.stories.tsx +5 -5
  57. package/src/components/Form/Textarea.tsx +2 -9
  58. package/src/components/Messages/Messages.tsx +2 -8
  59. package/src/components/Modal/Modal.tsx +4 -5
  60. package/src/components/Navigation/Nav/Nav.tsx +2 -6
  61. package/src/components/Navigation/Navbar/Navbar.tsx +2 -9
  62. package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -6
  63. package/src/components/Pagination/Pagination.tsx +2 -10
  64. package/src/components/Popover/Popover.tsx +2 -9
  65. package/src/components/Progress/Progress.tsx +2 -7
  66. package/src/components/Rating/Rating.tsx +2 -10
  67. package/src/components/Spinner/Spinner.tsx +2 -7
  68. package/src/components/Steps/Steps.tsx +2 -10
  69. package/src/components/Tabs/Tabs.tsx +2 -9
  70. package/src/components/Toggle/Toggle.tsx +2 -10
  71. package/src/components/Tooltip/Tooltip.tsx +2 -5
  72. package/src/lib/composables/useAtomixGlass.ts +42 -143
  73. package/src/lib/composables/useAtomixGlassStyles.ts +61 -77
  74. package/src/lib/composables/usePerformanceMonitor.ts +5 -66
  75. package/src/lib/constants/components.ts +363 -46
  76. package/src/lib/types/components.ts +33 -1
  77. package/src/styles/01-settings/_settings.atomix-glass.scss +66 -28
  78. package/src/styles/02-tools/_tools.button.scss +51 -42
  79. package/src/styles/02-tools/_tools.glass.scss +45 -3
  80. package/src/styles/06-components/_components.atomix-glass.scss +116 -79
  81. package/src/components/AtomixGlass/PerformanceDashboard.tsx +0 -171
  82. package/src/components/AtomixGlass/animation-system.ts +0 -578
  83. package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +0 -390
package/dist/heavy.js CHANGED
@@ -25,7 +25,56 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
25
25
  ACTIVE: "c-btn--active",
26
26
  SELECTED: "c-btn--selected"
27
27
  }
28
- }, VIDEO_PLAYER_CLASSES_BASE = "c-video-player", VIDEO_PLAYER_CLASSES_VIDEO = "c-video-player__video", VIDEO_PLAYER_CLASSES_YOUTUBE = "c-video-player--youtube", VIDEO_PLAYER_CLASSES_LOADING = "c-video-player__loading", VIDEO_PLAYER_CLASSES_SPINNER = "c-video-player__spinner", VIDEO_PLAYER_CLASSES_CONTROLS = "c-video-player__controls", VIDEO_PLAYER_CLASSES_CONTROLS_VISIBLE = "c-video-player__controls--visible", VIDEO_PLAYER_CLASSES_PROGRESS_CONTAINER = "c-video-player__progress-container", VIDEO_PLAYER_CLASSES_PROGRESS_BAR = "c-video-player__progress-bar", VIDEO_PLAYER_CLASSES_PROGRESS_BUFFERED = "c-video-player__progress-buffered", VIDEO_PLAYER_CLASSES_PROGRESS_PLAYED = "c-video-player__progress-played", VIDEO_PLAYER_CLASSES_PROGRESS_THUMB = "c-video-player__progress-thumb", VIDEO_PLAYER_CLASSES_CONTROLS_ROW = "c-video-player__controls-row", VIDEO_PLAYER_CLASSES_CONTROLS_LEFT = "c-video-player__controls-left", VIDEO_PLAYER_CLASSES_CONTROLS_RIGHT = "c-video-player__controls-right", VIDEO_PLAYER_CLASSES_CONTROL_BUTTON = "c-video-player__control-button", VIDEO_PLAYER_CLASSES_VOLUME_CONTAINER = "c-video-player__volume-container", VIDEO_PLAYER_CLASSES_VOLUME_SLIDER = "c-video-player__volume-slider", VIDEO_PLAYER_CLASSES_VOLUME_BAR = "c-video-player__volume-bar", VIDEO_PLAYER_CLASSES_VOLUME_FILL = "c-video-player__volume-fill", VIDEO_PLAYER_CLASSES_TIME_DISPLAY = "c-video-player__time-display", VIDEO_PLAYER_CLASSES_SETTINGS_CONTAINER = "c-video-player__settings-container", VIDEO_PLAYER_CLASSES_SETTINGS_MENU = "c-video-player__settings-menu", VIDEO_PLAYER_CLASSES_SETTINGS_TABS = "c-video-player__settings-tabs", VIDEO_PLAYER_CLASSES_SETTINGS_TAB = "c-video-player__settings-tab", VIDEO_PLAYER_CLASSES_SETTINGS_TAB_ACTIVE = "c-video-player__settings-tab--active", VIDEO_PLAYER_CLASSES_SETTINGS_CONTENT = "c-video-player__settings-content", VIDEO_PLAYER_CLASSES_SETTINGS_OPTIONS = "c-video-player__settings-options", VIDEO_PLAYER_CLASSES_SETTINGS_OPTION = "c-video-player__settings-option", VIDEO_PLAYER_CLASSES_SETTINGS_OPTION_ACTIVE = "c-video-player__settings-option--active", VIDEO_PLAYER_CLASSES_AMBIENT = "c-video-player--ambient", VIDEO_PLAYER_CLASSES_AMBIENT_CANVAS = "c-video-player__ambient-canvas", VIDEO_PLAYER_CLASSES_GLASS = "c-video-player--glass", VIDEO_PLAYER_CLASSES_GLASS_OVERLAY = "c-video-player__glass-overlay", VIDEO_PLAYER_CLASSES_GLASS_CONTENT = "c-video-player__glass-content", ATOMIX_GLASS = {
28
+ }, VIDEO_PLAYER_CLASSES_BASE = "c-video-player", VIDEO_PLAYER_CLASSES_VIDEO = "c-video-player__video", VIDEO_PLAYER_CLASSES_YOUTUBE = "c-video-player--youtube", VIDEO_PLAYER_CLASSES_LOADING = "c-video-player__loading", VIDEO_PLAYER_CLASSES_SPINNER = "c-video-player__spinner", VIDEO_PLAYER_CLASSES_CONTROLS = "c-video-player__controls", VIDEO_PLAYER_CLASSES_CONTROLS_VISIBLE = "c-video-player__controls--visible", VIDEO_PLAYER_CLASSES_PROGRESS_CONTAINER = "c-video-player__progress-container", VIDEO_PLAYER_CLASSES_PROGRESS_BAR = "c-video-player__progress-bar", VIDEO_PLAYER_CLASSES_PROGRESS_BUFFERED = "c-video-player__progress-buffered", VIDEO_PLAYER_CLASSES_PROGRESS_PLAYED = "c-video-player__progress-played", VIDEO_PLAYER_CLASSES_PROGRESS_THUMB = "c-video-player__progress-thumb", VIDEO_PLAYER_CLASSES_CONTROLS_ROW = "c-video-player__controls-row", VIDEO_PLAYER_CLASSES_CONTROLS_LEFT = "c-video-player__controls-left", VIDEO_PLAYER_CLASSES_CONTROLS_RIGHT = "c-video-player__controls-right", VIDEO_PLAYER_CLASSES_CONTROL_BUTTON = "c-video-player__control-button", VIDEO_PLAYER_CLASSES_VOLUME_CONTAINER = "c-video-player__volume-container", VIDEO_PLAYER_CLASSES_VOLUME_SLIDER = "c-video-player__volume-slider", VIDEO_PLAYER_CLASSES_VOLUME_BAR = "c-video-player__volume-bar", VIDEO_PLAYER_CLASSES_VOLUME_FILL = "c-video-player__volume-fill", VIDEO_PLAYER_CLASSES_TIME_DISPLAY = "c-video-player__time-display", VIDEO_PLAYER_CLASSES_SETTINGS_CONTAINER = "c-video-player__settings-container", VIDEO_PLAYER_CLASSES_SETTINGS_MENU = "c-video-player__settings-menu", VIDEO_PLAYER_CLASSES_SETTINGS_TABS = "c-video-player__settings-tabs", VIDEO_PLAYER_CLASSES_SETTINGS_TAB = "c-video-player__settings-tab", VIDEO_PLAYER_CLASSES_SETTINGS_TAB_ACTIVE = "c-video-player__settings-tab--active", VIDEO_PLAYER_CLASSES_SETTINGS_CONTENT = "c-video-player__settings-content", VIDEO_PLAYER_CLASSES_SETTINGS_OPTIONS = "c-video-player__settings-options", VIDEO_PLAYER_CLASSES_SETTINGS_OPTION = "c-video-player__settings-option", VIDEO_PLAYER_CLASSES_SETTINGS_OPTION_ACTIVE = "c-video-player__settings-option--active", VIDEO_PLAYER_CLASSES_AMBIENT = "c-video-player--ambient", VIDEO_PLAYER_CLASSES_AMBIENT_CANVAS = "c-video-player__ambient-canvas", VIDEO_PLAYER_CLASSES_GLASS = "c-video-player--glass", VIDEO_PLAYER_CLASSES_GLASS_OVERLAY = "c-video-player__glass-overlay", VIDEO_PLAYER_CLASSES_GLASS_CONTENT = "c-video-player__glass-content", GLASS_DEFAULTS_BUTTON = {
29
+ displacementScale: 16,
30
+ saturation: 180,
31
+ elasticity: 0
32
+ }, GLASS_DEFAULTS_BADGE = {
33
+ displacementScale: 14,
34
+ borderRadius: 16,
35
+ elasticity: 0
36
+ }, GLASS_DEFAULTS_SPINNER = {
37
+ displacementScale: 12,
38
+ elasticity: 0
39
+ }, GLASS_BORDER_GRADIENT = {
40
+ BASE_ANGLE: 135,
41
+ ANGLE_MULTIPLIER: .5,
42
+ VELOCITY_ANGLE_MULTIPLIER: .5,
43
+ CHROMATIC_OFFSET: 1.5,
44
+ STOP_1: {
45
+ MIN: 10,
46
+ BASE: 33,
47
+ get MULTIPLIER() {
48
+ return .009 * this.BASE;
49
+ }
50
+ },
51
+ STOP_2: {
52
+ MAX: 90,
53
+ BASE: 66,
54
+ get MULTIPLIER() {
55
+ return .006 * this.BASE;
56
+ }
57
+ },
58
+ OPACITY: {
59
+ /** Matches $glass-border-1-opacity (0.08) */
60
+ BASE_1: .08,
61
+ get BASE_2() {
62
+ return 3.33 * this.BASE_1;
63
+ },
64
+ get BASE_3() {
65
+ return 2.66 * this.BASE_1;
66
+ },
67
+ get BASE_4() {
68
+ return 5 * this.BASE_1;
69
+ },
70
+ get MULTIPLIER_LOW() {
71
+ return .066 * this.BASE_1;
72
+ },
73
+ get MULTIPLIER_HIGH() {
74
+ return .1 * this.BASE_1;
75
+ }
76
+ }
77
+ }, ATOMIX_GLASS = {
29
78
  BASE_CLASS: "c-atomix-glass",
30
79
  CONTAINER_CLASS: "c-atomix-glass__container",
31
80
  INNER_CLASS: "c-atomix-glass__inner",
@@ -36,6 +85,22 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
36
85
  BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
37
86
  BORDER_1_CLASS: "c-atomix-glass__border-1",
38
87
  BORDER_2_CLASS: "c-atomix-glass__border-2",
88
+ /** Centralized liquid glass rim configuration */
89
+ BORDER: {
90
+ WIDTH_CSS_VAR: "--atomix-glass-border-width",
91
+ DEFAULT_WIDTH: "0.5px",
92
+ GRADIENT_CSS_VARS: {
93
+ GRADIENT_1: "--atomix-glass-border-gradient-1",
94
+ GRADIENT_2: "--atomix-glass-border-gradient-2"
95
+ },
96
+ GRADIENT: GLASS_BORDER_GRADIENT,
97
+ OVER_LIGHT: {
98
+ opacity: .7
99
+ },
100
+ DARK: {
101
+ opacity: .35
102
+ }
103
+ },
39
104
  HOVER_1_CLASS: "c-atomix-glass__hover-1",
40
105
  HOVER_2_CLASS: "c-atomix-glass__hover-2",
41
106
  HOVER_3_CLASS: "c-atomix-glass__hover-3",
@@ -64,25 +129,22 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
64
129
  SHADER: "c-atomix-glass--shader"
65
130
  },
66
131
  DEFAULTS: {
67
- DISPLACEMENT_SCALE: 70,
132
+ /** Subtle refraction — Apple UI chrome avoids heavy liquid distortion */
133
+ DISPLACEMENT_SCALE: 28,
68
134
  get BLUR_AMOUNT() {
69
- return .15 * this.DISPLACEMENT_SCALE;
70
- // Dynamically computed based on displacement
71
- },
72
- get SATURATION() {
73
- return 100 + .5 * this.DISPLACEMENT_SCALE;
74
- // Saturate relative to intensity
75
- },
135
+ // Apple Music sidebar / player bar: ~20–40px frost (see $glass-backdrop-filter)
136
+ return Math.max(20, .72 * this.DISPLACEMENT_SCALE);
137
+ },
138
+ /** Fixed 180% matches Apple's saturate(180%) backdrop recipe */
139
+ SATURATION: 180,
76
140
  get ABERRATION_INTENSITY() {
77
- return .03 * this.DISPLACEMENT_SCALE;
78
- // Scale aberration with displacement
79
- },
80
- ELASTICITY: .15,
141
+ return .02 * this.DISPLACEMENT_SCALE;
142
+ },
143
+ ELASTICITY: .05,
81
144
  get CORNER_RADIUS() {
82
145
  return 16;
83
146
  // Use 16 to match SCSS design system (was 20)
84
147
  },
85
- PADDING: "0",
86
148
  MODE: "standard",
87
149
  OVER_LIGHT: !1,
88
150
  ENABLE_OVER_LIGHT_LAYERS: !0,
@@ -98,19 +160,29 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
98
160
  },
99
161
  CONSTANTS: {
100
162
  ACTIVATION_ZONE: 200,
101
- LERP_FACTOR: .08,
163
+ LERP_FACTOR: .05,
164
+ // Lower = more viscous, liquid-smooth tracking (Apple feel)
102
165
  SMOOTHSTEP_POWER: 2.5,
103
166
  MIN_BLUR: .1,
104
167
  MOUSE_INFLUENCE_DIVISOR: 100,
105
168
  EDGE_FADE_PIXELS: 2,
106
- // Elasticity physics constants
107
- ELASTICITY_TRANSLATION_FACTOR: .1,
169
+ // Interaction intensity multipliers shared by the hook and the imperative style updater
170
+ INTERACTION: {
171
+ HOVER_INTENSITY: 1.4,
172
+ ACTIVE_INTENSITY: 1.6
173
+ },
174
+ // Elasticity physics constants — Apple-tuned: soft springs, fast settling, minimal stretch
175
+ ELASTICITY_TRANSLATION_FACTOR: .06,
176
+ // Subtler elastic shift (was 0.1)
108
177
  ELASTICITY_DISTANCE_THRESHOLD: 200,
109
178
  ELASTICITY_COMPRESSION_FACTOR: .3,
110
- ELASTICITY_STIFFNESS: .1,
111
- ELASTICITY_DAMPING: .76,
179
+ ELASTICITY_STIFFNESS: .06,
180
+ // Softer springs = gentler motion (was 0.1)
181
+ ELASTICITY_DAMPING: .88,
182
+ // Fast settling, no wobble (was 0.76)
112
183
  ELASTICITY_VELOCITY_FACTOR: .65,
113
- ELASTICITY_STRETCH_RATIO: .45,
184
+ ELASTICITY_STRETCH_RATIO: .25,
185
+ // Less visible surface tension stretch (was 0.45)
114
186
  ELASTICITY_MAGNIFICATION_BASE: 1.02,
115
187
  // Note: This default must match the SCSS variable --atomix-radius-md
116
188
  // @see src/styles/01-settings/_settings.global.scss
@@ -124,55 +196,16 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
124
196
  },
125
197
  // Gradient calculation constants
126
198
  GRADIENT: {
127
- BASE_ANGLE: 135,
128
- // Base angle for border gradients (degrees)
129
- ANGLE_MULTIPLIER: 1.2,
130
- // Multiplier for mouse influence on angle
131
- VELOCITY_ANGLE_MULTIPLIER: 2.5,
132
- // How much velocity affects gradient rotation
133
- CHROMATIC_OFFSET: 1.5,
134
- // Degree offset for chromatic rim layers
135
- BORDER_STOP_1: {
136
- MIN: 10,
137
- // Minimum percentage for border stop 1
138
- BASE: 33,
139
- // Base percentage for border stop 1
140
- get MULTIPLIER() {
141
- return .009 * this.BASE;
142
- }
143
- },
144
- BORDER_STOP_2: {
145
- MAX: 90,
146
- // Maximum percentage for border stop 2
147
- BASE: 66,
148
- // Base percentage for border stop 2
149
- get MULTIPLIER() {
150
- return .006 * this.BASE;
151
- }
152
- },
153
- BORDER_OPACITY: {
154
- BASE_1: .12,
155
- // Base opacity for border gradient 1
156
- get BASE_2() {
157
- return 3.33 * this.BASE_1;
158
- },
159
- // Base opacity for border gradient 2
160
- get BASE_3() {
161
- return 2.66 * this.BASE_1;
162
- },
163
- // Base opacity for border gradient 3
164
- get BASE_4() {
165
- return 5 * this.BASE_1;
166
- },
167
- // Base opacity for border gradient 4
168
- get MULTIPLIER_LOW() {
169
- return .066 * this.BASE_1;
170
- },
171
- // Low multiplier for mouse influence on opacity
172
- get MULTIPLIER_HIGH() {
173
- return .1 * this.BASE_1;
174
- }
175
- },
199
+ BASE_ANGLE: GLASS_BORDER_GRADIENT.BASE_ANGLE,
200
+ ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.ANGLE_MULTIPLIER,
201
+ VELOCITY_ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER,
202
+ CHROMATIC_OFFSET: GLASS_BORDER_GRADIENT.CHROMATIC_OFFSET,
203
+ /** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_1 */
204
+ BORDER_STOP_1: GLASS_BORDER_GRADIENT.STOP_1,
205
+ /** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_2 */
206
+ BORDER_STOP_2: GLASS_BORDER_GRADIENT.STOP_2,
207
+ /** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.OPACITY */
208
+ BORDER_OPACITY: GLASS_BORDER_GRADIENT.OPACITY,
176
209
  CENTER_POSITION: 50,
177
210
  // Center position percentage (50%)
178
211
  HOVER_POSITION: {
@@ -205,8 +238,8 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
205
238
  return 2 * this.BLACK_STOP;
206
239
  },
207
240
  // End percentage for black hover 1
208
- WHITE_START: .5,
209
- // Start opacity for white hover 1
241
+ WHITE_START: .35,
242
+ // Gentler hover flash Apple hover is barely visible
210
243
  get WHITE_STOP() {
211
244
  return this.BLACK_END - 10;
212
245
  }
@@ -224,8 +257,8 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
224
257
  return 2 * this.BLACK_STOP;
225
258
  },
226
259
  // End percentage for black hover 2
227
- WHITE_START: 1,
228
- // Start opacity for white hover 2
260
+ WHITE_START: .7,
261
+ // Gentler hover flash
229
262
  get WHITE_STOP() {
230
263
  return this.BLACK_END;
231
264
  }
@@ -243,8 +276,8 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
243
276
  return 2 * this.BLACK_STOP;
244
277
  },
245
278
  // End percentage for black hover 3
246
- WHITE_START: 1,
247
- // Start opacity for white hover 3
279
+ WHITE_START: .7,
280
+ // Gentler hover flash
248
281
  get WHITE_STOP() {
249
282
  return this.BLACK_END;
250
283
  }
@@ -254,13 +287,13 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
254
287
  BASE_GRADIENT: {
255
288
  ANGLE: 135,
256
289
  // Gradient angle in degrees
257
- BLACK_START_BASE: .15,
290
+ BLACK_START_BASE: .1,
258
291
  // Base start opacity for black
259
292
  get BLACK_START_MULTIPLIER() {
260
293
  return .02 * this.BLACK_START_BASE;
261
294
  },
262
295
  // Multiplier for mouse X influence on start
263
- BLACK_MID_BASE: .1,
296
+ BLACK_MID_BASE: .07,
264
297
  // Base mid opacity for black
265
298
  get BLACK_MID_MULTIPLIER() {
266
299
  return .02 * this.BLACK_MID_BASE;
@@ -281,7 +314,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
281
314
  }
282
315
  },
283
316
  OVERLAY_GRADIENT: {
284
- BLACK_START_BASE: .12,
317
+ BLACK_START_BASE: .08,
285
318
  // Base start opacity for black overlay
286
319
  get BLACK_START_MULTIPLIER() {
287
320
  return .025 * this.BLACK_START_BASE;
@@ -305,14 +338,14 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
305
338
  return .416 * this.BLACK_START_BASE;
306
339
  }
307
340
  },
308
- // Overlay highlight constants
341
+ // Overlay highlight constants — Apple places specular at the top-center
309
342
  OVERLAY_HIGHLIGHT: {
310
- POSITION_X: 20,
311
- // X position percentage
312
- POSITION_Y: 20,
313
- // Y position percentage
314
- WHITE_OPACITY: .4,
315
- // White opacity in gradient
343
+ POSITION_X: 50,
344
+ // Centered horizontal — Apple's top-center specular
345
+ POSITION_Y: 5,
346
+ // Very top — catches light like a curved glass surface
347
+ WHITE_OPACITY: .28,
348
+ // Softer specular visible but not glaring
316
349
  get STOP() {
317
350
  return 150 * this.WHITE_OPACITY;
318
351
  },
@@ -333,6 +366,10 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
333
366
  SATURATION: {
334
367
  HIGH_CONTRAST: 200
335
368
  },
369
+ // Container shadows — hairline inner catch + soft floating lift (Apple player bar)
370
+ CONTAINER_SHADOW: {
371
+ LIGHT: "inset 0 0.5px 0 rgba(255, 255, 255, 0.32), inset 0 1px 2px rgba(255, 255, 255, 0.06), 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08)"
372
+ },
336
373
  // Phase 1: Animation System Constants
337
374
  ANIMATION: {
338
375
  // Breathing effect timing (in milliseconds)
@@ -372,7 +409,331 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
372
409
  }
373
410
  }
374
411
  }
375
- }, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
412
+ };
413
+
414
+ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
415
+
416
+ function getDefaultExportFromCjs(x) {
417
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
418
+ }
419
+
420
+ var fails$8 = function(exec) {
421
+ try {
422
+ return !!exec();
423
+ } catch (error) {
424
+ return !0;
425
+ }
426
+ }, functionBindNative = !fails$8((function() {
427
+ // eslint-disable-next-line es/no-function-prototype-bind -- safe
428
+ var test = function() {/* empty */}.bind();
429
+ // eslint-disable-next-line no-prototype-builtins -- safe
430
+ return "function" != typeof test || test.hasOwnProperty("prototype");
431
+ })), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
432
+ return function() {
433
+ return call$5.apply(fn, arguments);
434
+ };
435
+ }, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
436
+ return it && it.Math === Math && it;
437
+ }, globalThis_1 =
438
+ // eslint-disable-next-line es/no-global-this -- safe
439
+ check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
440
+ // eslint-disable-next-line no-restricted-globals -- safe
441
+ check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
442
+ // eslint-disable-next-line no-new-func -- fallback
443
+ function() {
444
+ return this;
445
+ }() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
446
+ return call$4.apply(apply$1, arguments);
447
+ }), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
448
+ return stringSlice(toString$3(it), 8, -1);
449
+ }, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
450
+ // Nashorn bug:
451
+ // https://github.com/zloirock/core-js/issues/1128
452
+ // https://github.com/zloirock/core-js/issues/1130
453
+ if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
454
+ }, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
455
+ return "function" == typeof argument || argument === documentAll;
456
+ } : function(argument) {
457
+ return "function" == typeof argument;
458
+ }, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
459
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
460
+ return 7 !== Object.defineProperty({}, 1, {
461
+ get: function() {
462
+ return 7;
463
+ }
464
+ })[1];
465
+ })), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
466
+ return call$3.apply(call$3, arguments);
467
+ }, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
468
+ 1: 2
469
+ }, 1);
470
+
471
+ // `Object.prototype.propertyIsEnumerable` method implementation
472
+ // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
473
+ objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
474
+ var descriptor = getOwnPropertyDescriptor$1(this, V);
475
+ return !!descriptor && descriptor.enumerable;
476
+ } : $propertyIsEnumerable;
477
+
478
+ var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
479
+ return {
480
+ enumerable: !(1 & bitmap),
481
+ configurable: !(2 & bitmap),
482
+ writable: !(4 & bitmap),
483
+ value: value
484
+ };
485
+ }, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
486
+ // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
487
+ // eslint-disable-next-line no-prototype-builtins -- safe
488
+ return !$Object$3("z").propertyIsEnumerable(0);
489
+ })) ? function(it) {
490
+ return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
491
+ } : $Object$3, isNullOrUndefined$2 = function(it) {
492
+ return null == it;
493
+ }, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
494
+ if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
495
+ return it;
496
+ }, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
497
+ return IndexedObject(requireObjectCoercible$2(it));
498
+ }, isCallable$7 = isCallable$8, isObject$5 = function(it) {
499
+ return "object" == typeof it ? null !== it : isCallable$7(it);
500
+ }, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
501
+ return isCallable$6(variable) ? variable : void 0;
502
+ }, navigator$1 = globalThis_1.navigator, userAgent$1 = navigator$1 && navigator$1.userAgent, globalThis$8 = globalThis_1, userAgent = userAgent$1 ? String(userAgent$1) : "", process$1 = globalThis$8.process, Deno = globalThis$8.Deno, versions = process$1 && process$1.versions || Deno && Deno.version, v8 = versions && versions.v8;
503
+
504
+ v8 && (
505
+ // in old Chrome, versions of V8 isn't V8 = Chrome / 10
506
+ // but their correct versions are not interesting for us
507
+ version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
508
+ // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
509
+ // so check `userAgent` even if `.v8` exists, but 0
510
+ !version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
511
+
512
+ var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
513
+ var symbol = Symbol("symbol detection");
514
+ // Chrome 38 Symbol has incorrect toString conversion
515
+ // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
516
+ // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
517
+ // of course, fail.
518
+ return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
519
+ // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
520
+ !Symbol.sham && V8_VERSION && V8_VERSION < 41;
521
+ })), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
522
+ return "symbol" == typeof it;
523
+ } : function(it) {
524
+ var $Symbol = function(namespace, method) {
525
+ return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$a[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$a[namespace] && globalThis$a[namespace][method];
526
+ }("Symbol");
527
+ return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
528
+ }, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
529
+ if (isCallable$4(argument)) return argument;
530
+ throw new $TypeError$5(function(argument) {
531
+ try {
532
+ return $String$2(argument);
533
+ } catch (error) {
534
+ return "Object";
535
+ }
536
+ }(argument) + " is not a function");
537
+ }, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
538
+ exports: {}
539
+ }, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
540
+ try {
541
+ defineProperty(globalThis$6, key, {
542
+ value: value,
543
+ configurable: !0,
544
+ writable: !0
545
+ });
546
+ } catch (error) {
547
+ globalThis$6[key] = value;
548
+ }
549
+ return value;
550
+ }("__core-js_shared__", {});
551
+
552
+ /* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
553
+ version: "3.43.0",
554
+ mode: "pure",
555
+ copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
556
+ license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
557
+ source: "https://github.com/zloirock/core-js"
558
+ });
559
+
560
+ var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
561
+ return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
562
+ }, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
563
+ return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
564
+ }, wellKnownSymbol$5 = function(name) {
565
+ return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
566
+ WellKnownSymbolsStore[name];
567
+ }, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
568
+ if (!isObject$3(input) || isSymbol$1(input)) return input;
569
+ var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
570
+ if (exoticToPrim) {
571
+ if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
572
+ !isObject$3(result) || isSymbol$1(result)) return result;
573
+ throw new $TypeError$3("Can't convert object to primitive value");
574
+ }
575
+ return void 0 === pref && (pref = "number"), function(input, pref) {
576
+ var fn, val;
577
+ if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
578
+ if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
579
+ if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
580
+ throw new $TypeError$4("Can't convert object to primitive value");
581
+ }(input, pref);
582
+ }, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
583
+ var key = toPrimitive(argument, "string");
584
+ return isSymbol(key) ? key : key + "";
585
+ }, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
586
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
587
+ return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
588
+ get: function() {
589
+ return 7;
590
+ }
591
+ }).a;
592
+ var it;
593
+ })), DESCRIPTORS$3 = descriptors, call = functionCall, propertyIsEnumerableModule = objectPropertyIsEnumerable, createPropertyDescriptor$1 = createPropertyDescriptor$2, toIndexedObject$1 = toIndexedObject$2, toPropertyKey$1 = toPropertyKey$2, hasOwn$1 = hasOwnProperty_1, IE8_DOM_DEFINE$1 = ie8DomDefine, $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
594
+
595
+ // `Object.getOwnPropertyDescriptor` method
596
+ // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
597
+ objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
598
+ if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
599
+ return $getOwnPropertyDescriptor$1(O, P);
600
+ } catch (error) {/* empty */}
601
+ if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
602
+ };
603
+
604
+ var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
605
+ var value = data[normalize(feature)];
606
+ return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
607
+ }, normalize = isForced$1.normalize = function(string) {
608
+ return String(string).replace(replacement, ".").toLowerCase();
609
+ }, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable = aCallable$2, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$8((function() {
610
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
611
+ return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
612
+ value: 42,
613
+ writable: !1
614
+ }).prototype;
615
+ })), isObject$1 = isObject$5, $String$1 = String, $TypeError$2 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
616
+ if (isObject$1(argument)) return argument;
617
+ throw new $TypeError$2($String$1(argument) + " is not an object");
618
+ }, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
619
+
620
+ // `Object.defineProperty` method
621
+ // https://tc39.es/ecma262/#sec-object.defineproperty
622
+ objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
623
+ if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
624
+ var current = $getOwnPropertyDescriptor(O, P);
625
+ current && current.writable && (O[P] = Attributes.value, Attributes = {
626
+ configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
627
+ enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
628
+ writable: !1
629
+ });
630
+ }
631
+ return $defineProperty(O, P, Attributes);
632
+ } : $defineProperty : function(O, P, Attributes) {
633
+ if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
634
+ return $defineProperty(O, P, Attributes);
635
+ } catch (error) {/* empty */}
636
+ if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
637
+ return "value" in Attributes && (O[P] = Attributes.value), O;
638
+ };
639
+
640
+ var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
641
+ return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
642
+ } : function(object, key, value) {
643
+ return object[key] = value, object;
644
+ }, globalThis$2 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
645
+ return aCallable(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
646
+ return fn.apply(that, arguments);
647
+ };
648
+ }, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
649
+ var Wrapper = function(a, b, c) {
650
+ if (this instanceof Wrapper) {
651
+ switch (arguments.length) {
652
+ case 0:
653
+ return new NativeConstructor;
654
+
655
+ case 1:
656
+ return new NativeConstructor(a);
657
+
658
+ case 2:
659
+ return new NativeConstructor(a, b);
660
+ }
661
+ return new NativeConstructor(a, b, c);
662
+ }
663
+ return apply(NativeConstructor, this, arguments);
664
+ };
665
+ return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
666
+ }, _export = function(options, source) {
667
+ var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$2 : STATIC ? globalThis$2[TARGET] : globalThis$2[TARGET] && globalThis$2[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
668
+ for (key in source)
669
+ // contains in native
670
+ USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
671
+ targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
672
+ // export native or implementation
673
+ sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
674
+ // bind methods to global for calling from export context
675
+ resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
676
+ // add a flag to not completely full polyfills
677
+ (options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
678
+ createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
679
+ // export virtual prototype methods
680
+ createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
681
+ // export real prototype methods
682
+ options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
683
+ }, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
684
+ var n = +x;
685
+ return (n > 0 ? floor : ceil)(n);
686
+ }, toIntegerOrInfinity$2 = function(argument) {
687
+ var number = +argument;
688
+ // eslint-disable-next-line no-self-compare -- NaN check
689
+ return number != number || 0 === number ? 0 : trunc(number);
690
+ }, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, min$1 = Math.min, globalThis$1 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$2 = function(CONSTRUCTOR, METHOD) {
691
+ var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
692
+ if (pureMethod) return pureMethod;
693
+ var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
694
+ return NativePrototype && NativePrototype[METHOD];
695
+ };
696
+
697
+ /**
698
+ * Component Utilities
699
+ *
700
+ * Helper functions for component development with the new customization system
701
+ */
702
+ /**
703
+ * Merge multiple class names
704
+ */
705
+ function mergeClassNames(...classes) {
706
+ return classes.filter(Boolean).join(" ");
707
+ }
708
+
709
+ /**
710
+ * Check if a URL is a YouTube URL
711
+ */ function isYouTubeUrl(url) {
712
+ return /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/.test(url);
713
+ }
714
+
715
+ /**
716
+ * Extract YouTube video ID from URL
717
+ */
718
+ /**
719
+ * Utility to merge multiple React refs into one
720
+ */
721
+ function setRef(ref, value) {
722
+ "function" == typeof ref ? ref(value) : ref && (
723
+ // This is safe because we're checking that ref exists first
724
+ ref.current = value);
725
+ }
726
+
727
+ /**
728
+ * Combines two React refs into a single ref function
729
+ * This is used when you need to use and forward a ref at the same time
730
+ */ function useForkRef(refA, refB) {
731
+ return React.useMemo((() => null == refA && null == refB ? null : refValue => {
732
+ setRef(refA, refValue), setRef(refB, refValue);
733
+ }), [ refA, refB ]);
734
+ }
735
+
736
+ const {CONSTANTS: CONSTANTS$3} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
376
737
  x: rect.left + rect.width / 2,
377
738
  y: rect.top + rect.height / 2
378
739
  } : {
@@ -380,37 +741,37 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
380
741
  y: 0
381
742
  }, calculateMouseInfluence = mouseOffset => {
382
743
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
383
- // Bounded calculation keeps the glass effect subtle and stable
384
- const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
744
+ // Clamp influence to keep mouse response subtle and stable.
745
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$3.MOUSE_INFLUENCE_DIVISOR;
385
746
  return Math.min(.8, influence);
386
747
  // Tighter cap to prevent blur/filter blow-out
387
- }, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$2.MIN_BLUR : Math.max(CONSTANTS$2.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$2.MAX_SIZE && size.height <= CONSTANTS$2.MAX_SIZE, parseBorderRadiusValue = value => {
748
+ }, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$3.MIN_BLUR : Math.max(CONSTANTS$3.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$3.MAX_SIZE && size.height <= CONSTANTS$3.MAX_SIZE, parseBorderRadiusValue = value => {
388
749
  if ("number" == typeof value) return Math.max(0, value);
389
- if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
750
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
390
751
  const trimmedValue = value.trim();
391
752
  // Handle px values
392
753
  if (trimmedValue.endsWith("px")) {
393
754
  const parsed = parseFloat(trimmedValue);
394
- return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
755
+ return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
395
756
  }
396
757
  // Handle rem values (assume 16px = 1rem)
397
758
  if (trimmedValue.endsWith("rem")) {
398
759
  const parsed = parseFloat(trimmedValue);
399
- return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
760
+ return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
400
761
  }
401
762
  // Handle em values (assume 16px = 1em for simplicity)
402
763
  if (trimmedValue.endsWith("em")) {
403
764
  const parsed = parseFloat(trimmedValue);
404
- return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
765
+ return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
405
766
  }
406
767
  // Handle percentage (convert to approximate px value, assuming 200px container)
407
768
  if (trimmedValue.endsWith("%")) {
408
769
  const parsed = parseFloat(trimmedValue);
409
- return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
770
+ return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
410
771
  }
411
772
  // Handle unitless numbers
412
773
  const numValue = parseFloat(trimmedValue);
413
- return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
774
+ return isNaN(numValue) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
414
775
  }, extractBorderRadiusFromElement = element => {
415
776
  if (!element || !element.props) return null;
416
777
  // Check inline styles first (highest priority)
@@ -426,11 +787,11 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
426
787
  // If element has children, recursively check them
427
788
  if (element.props.children) {
428
789
  const childRadius = extractBorderRadiusFromChildren(element.props.children);
429
- if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
790
+ if (childRadius > 0 && childRadius !== CONSTANTS$3.DEFAULT_CORNER_RADIUS) return childRadius;
430
791
  }
431
792
  return null;
432
793
  }, extractBorderRadiusFromChildren = children => {
433
- if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
794
+ if (!children) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
434
795
  try {
435
796
  const childArray = React.Children.toArray(children);
436
797
  for (let i = 0; i < childArray.length; i++) {
@@ -443,17 +804,78 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
443
804
  } catch (error) {
444
805
  // Silently handle errors
445
806
  }
446
- return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
807
+ return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
447
808
  }, smoothstep = t => {
448
809
  const clamped = Math.max(0, Math.min(1, t));
449
810
  return clamped * clamped * (3 - 2 * clamped);
450
- }, lerp$1 = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
811
+ }, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), clamp = (value, min, max) => "number" != typeof value || isNaN(value) ? min : Math.max(min, Math.min(max, value)), smoothstepEdge = (edge0, edge1, x) => "number" != typeof edge0 || "number" != typeof edge1 || "number" != typeof x ? 0 : smoothstep((x - edge0) / (edge1 - edge0)), easeInOutCubic = t => {
812
+ if ("number" != typeof t || isNaN(t)) return 0;
813
+ const clamped = Math.max(0, Math.min(1, t));
814
+ return clamped < .5 ? 4 * clamped * clamped * clamped : 1 - Math.pow(-2 * clamped + 2, 3) / 2;
815
+ }, easeOutQuart = t => {
816
+ if ("number" != typeof t || isNaN(t)) return 0;
817
+ const clamped = Math.max(0, Math.min(1, t));
818
+ return 1 - Math.pow(1 - clamped, 4);
819
+ }, vec2Length = (x, y) => {
820
+ if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
821
+ const maxComponent = Math.max(Math.abs(x), Math.abs(y));
822
+ if (0 === maxComponent) return 0;
823
+ const scaledX = x / maxComponent, scaledY = y / maxComponent;
824
+ return maxComponent * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
825
+ }, getInteractionIntensity = (isHovered, isActive) => ({
826
+ hoverIntensity: isHovered ? CONSTANTS$3.INTERACTION.HOVER_INTENSITY : 1,
827
+ activeIntensity: isActive ? CONSTANTS$3.INTERACTION.ACTIVE_INTENSITY : 1
828
+ })
829
+ /**
830
+ * Spring-damper integration helper
831
+ * Calculates the next value based on velocity, stiffness, and damping.
832
+ */ , calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
451
833
  const newVelocity = (velocity + (target - current) * stiffness) * damping;
452
834
  return {
453
835
  value: current + newVelocity,
454
836
  velocity: newVelocity
455
837
  };
456
- }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
838
+ };
839
+
840
+ /**
841
+ * Calculate element center from bounding rect
842
+ */
843
+ /**
844
+ * Normalizes a layout inset for use in CSS custom properties.
845
+ *
846
+ * @param value - Raw inset from `style` (number, px string, or `auto`).
847
+ * @param fallback - Value used when `value` is undefined.
848
+ */
849
+ function formatGlassInsetValue(value, fallback = "auto") {
850
+ return void 0 === value ? "number" == typeof fallback ? `${fallback}px` : String(fallback) : "auto" === value ? "auto" : "number" == typeof value ? `${value}px` : value;
851
+ }
852
+
853
+ /**
854
+ * Determines whether the glass should use fixed/sticky layout semantics.
855
+ *
856
+ * @param explicit - Value of the `isFixedOrSticky` prop.
857
+ * @param position - `position` from the consumer `style` object.
858
+ */
859
+ /** Coerces a value to a finite number, returning `fallback` when invalid. */
860
+ function toSafeNumber(value, fallback = 0) {
861
+ return "number" != typeof value || isNaN(value) ? fallback : value;
862
+ }
863
+
864
+ /**
865
+ * Calculates the target frame rate for shader time-animation loops.
866
+ *
867
+ * Balances visual quality against distortion complexity and `animationSpeed`.
868
+ */
869
+ /**
870
+ * Computes per-channel displacement scale for the SVG chromatic-aberration filter.
871
+ */
872
+ function getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channelFactor) {
873
+ return displacementScale * (("shader" === mode ? 1 : -1) - aberrationIntensity * channelFactor);
874
+ }
875
+
876
+ /**
877
+ * Get displacement map URL based on mode
878
+ */ const getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
457
879
  switch (mode) {
458
880
  case "standard":
459
881
  return displacementMap;
@@ -470,13 +892,28 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
470
892
  default:
471
893
  return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
472
894
  }
473
- }, sharedShaderCache = new Map, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
474
- style: {
475
- position: "absolute",
476
- width: "100%",
477
- height: "100%",
478
- inset: 0
479
- },
895
+ }, sharedShaderCache = new Map, CHROMATIC_CHANNELS = [ {
896
+ result: "RED_DISPLACED",
897
+ channelResult: "RED_CHANNEL",
898
+ aberrationFactor: 0,
899
+ colorMatrix: "1 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
900
+ }, {
901
+ result: "GREEN_DISPLACED",
902
+ channelResult: "GREEN_CHANNEL",
903
+ aberrationFactor: .02,
904
+ colorMatrix: "0 0 0 0 0\n0 1 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
905
+ }, {
906
+ result: "BLUE_DISPLACED",
907
+ channelResult: "BLUE_CHANNEL",
908
+ aberrationFactor: .03,
909
+ colorMatrix: "0 0 0 0 0\n0 0 0 0 0\n0 0 1 0 0\n0 0 0 1 0"
910
+ } ], FILTER_SVG_STYLE = {
911
+ position: "absolute",
912
+ width: "100%",
913
+ height: "100%",
914
+ inset: 0
915
+ }, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
916
+ style: FILTER_SVG_STYLE,
480
917
  "aria-hidden": "true",
481
918
  children: jsxs("defs", {
482
919
  children: [ jsxs("radialGradient", {
@@ -530,43 +967,21 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
530
967
  dx: "0",
531
968
  dy: "0",
532
969
  result: "CENTER_ORIGINAL"
533
- }), jsx("feDisplacementMap", {
534
- in: "SourceGraphic",
535
- in2: "DISPLACEMENT_MAP",
536
- scale: displacementScale * ("shader" === mode ? 1 : -1),
537
- xChannelSelector: "R",
538
- yChannelSelector: "B",
539
- result: "RED_DISPLACED"
540
- }), jsx("feColorMatrix", {
541
- in: "RED_DISPLACED",
542
- type: "matrix",
543
- values: "1 0 0 0 0\n 0 0 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
544
- result: "RED_CHANNEL"
545
- }), jsx("feDisplacementMap", {
546
- in: "SourceGraphic",
547
- in2: "DISPLACEMENT_MAP",
548
- scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
549
- xChannelSelector: "R",
550
- yChannelSelector: "B",
551
- result: "GREEN_DISPLACED"
552
- }), jsx("feColorMatrix", {
553
- in: "GREEN_DISPLACED",
554
- type: "matrix",
555
- values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
556
- result: "GREEN_CHANNEL"
557
- }), jsx("feDisplacementMap", {
558
- in: "SourceGraphic",
559
- in2: "DISPLACEMENT_MAP",
560
- scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
561
- xChannelSelector: "R",
562
- yChannelSelector: "B",
563
- result: "BLUE_DISPLACED"
564
- }), jsx("feColorMatrix", {
565
- in: "BLUE_DISPLACED",
566
- type: "matrix",
567
- values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
568
- result: "BLUE_CHANNEL"
569
- }), jsx("feBlend", {
970
+ }), CHROMATIC_CHANNELS.map((channel => jsxs(React.Fragment, {
971
+ children: [ jsx("feDisplacementMap", {
972
+ in: "SourceGraphic",
973
+ in2: "DISPLACEMENT_MAP",
974
+ scale: getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channel.aberrationFactor),
975
+ xChannelSelector: "R",
976
+ yChannelSelector: "B",
977
+ result: channel.result
978
+ }), jsx("feColorMatrix", {
979
+ in: channel.result,
980
+ type: "matrix",
981
+ values: channel.colorMatrix,
982
+ result: channel.channelResult
983
+ }) ]
984
+ }, channel.channelResult))), jsx("feBlend", {
570
985
  in: "GREEN_CHANNEL",
571
986
  in2: "BLUE_CHANNEL",
572
987
  mode: "screen",
@@ -606,20 +1021,23 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
606
1021
  })
607
1022
  });
608
1023
 
609
- GlassFilterComponent.displayName = "GlassFilter";
1024
+ /**
1025
+ * Module-level LRU cache for shader displacement maps.
1026
+ *
1027
+ * Shared across all `AtomixGlassContainer` instances so identical size and
1028
+ * variant combinations are generated once.
1029
+ */ GlassFilterComponent.displayName = "GlassFilter";
610
1030
 
611
- // Memoize component to prevent unnecessary re-renders
1031
+ /** Shallow prop comparison to avoid redundant SVG filter regeneration. */
612
1032
  const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
613
1033
  x: 0,
614
1034
  y: 0
615
- }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
1035
+ }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, glassSize: glassSize = {
616
1036
  width: 0,
617
1037
  height: 0
618
- }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
619
- // Phase 1: Animation System props
620
- shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
1038
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
621
1039
  // React 18 useId — stable, unique, and SSR-safe (no module-level counter)
622
- const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
1040
+ const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), containerRef = useForkRef(ref, null), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
623
1041
  // Lazy load shader utilities only when shader mode is needed
624
1042
  useEffect((() => {
625
1043
  "shader" === mode ?
@@ -697,15 +1115,23 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
697
1115
  shaderGeneratorRef.current = null;
698
1116
  }
699
1117
  };
700
- }), [ mode, glassSize, shaderVariant ]),
701
- // Phase 1: Time-Based Animation Loop - Continuous shader regeneration
702
- useEffect((() => {
1118
+ }), [ mode, glassSize, shaderVariant ]), useEffect((() => {
703
1119
  // Only run animations in shader mode with time animation enabled
704
1120
  if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
705
1121
  // Cancel any existing animation frame
706
1122
  return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
707
1123
  animationFrameRef.current = null));
708
- const baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed || 1)), complexity = withMultiLayerDistortion ? Math.max(1, (distortionOctaves || 3) / 3 + .25 * Math.max(0, (distortionLacunarity || 2) - 2) + Math.max(0, (distortionGain || .5) - .5)) : 1, frameInterval = 1e3 / Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
1124
+ const targetFps = function(options) {
1125
+ const {distortionQuality: distortionQuality, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5} = options, baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed)), complexity = withMultiLayerDistortion ? Math.max(1, distortionOctaves / 3 + .25 * Math.max(0, distortionLacunarity - 2) + Math.max(0, distortionGain - .5)) : 1;
1126
+ return Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
1127
+ }({
1128
+ distortionQuality: distortionQuality,
1129
+ animationSpeed: animationSpeed,
1130
+ withMultiLayerDistortion: withMultiLayerDistortion,
1131
+ distortionOctaves: distortionOctaves,
1132
+ distortionLacunarity: distortionLacunarity,
1133
+ distortionGain: distortionGain
1134
+ }), frameInterval = 1e3 / targetFps;
709
1135
  let lastUpdate = 0, isCancelled = !1;
710
1136
  const animate = currentTime => {
711
1137
  if (!isCancelled) {
@@ -729,88 +1155,21 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
729
1155
  };
730
1156
  }), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
731
1157
  // Removed forced reflow to avoid layout thrash and potential feedback sizing loops
732
- const [rectCache, setRectCache] = useState(null);
733
- useEffect((() => {
734
- if (!ref || "function" == typeof ref) return;
735
- const element = ref.current;
736
- if (element) try {
737
- setRectCache(element.getBoundingClientRect());
738
- } catch (error) {
739
- console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
740
- }
741
- }), [ ref, glassSize ]);
742
- const liquidBlur = useMemo((() => {
743
- const defaultBlur = {
744
- baseBlur: blurAmount,
745
- edgeBlur: 1.25 * blurAmount,
746
- centerBlur: 1.1 * blurAmount,
747
- flowBlur: 1.2 * blurAmount
748
- };
749
- // Enhanced validation for liquid blur
750
- if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
751
- try {
752
- const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
753
- // NOTE: hover/active multipliers intentionally omitted here —
754
- // they belong on opacity layers, not the blur filter itself.
755
- return {
756
- baseBlur: clampBlur(baseBlur),
757
- edgeBlur: clampBlur(edgeBlur),
758
- centerBlur: clampBlur(centerBlur),
759
- flowBlur: clampBlur(flowBlur)
760
- };
761
- } catch (error) {
762
- return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
763
- defaultBlur;
764
- }
765
- }), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
766
- try {
767
- const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
768
- // Validate blur values before using them
769
- return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
770
- backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
771
- } : {
772
- backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1}) brightness(${overLightConfig?.brightness || 1})`
773
- };
774
- // Single-pass fallback: stronger radius to match perceived blur of multi-pass
775
- } catch (error) {
776
- return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
777
- {
778
- backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
779
- };
780
- }
781
- }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = useMemo((() => {
1158
+ const containerVars = useMemo((() => {
782
1159
  try {
783
- // Safe extraction of mouse offset values
784
- const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
785
1160
  return {
786
- "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
787
- "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
788
- "--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
789
- "--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
790
- // Background and shadow values use design token-aligned RGB values
791
- "--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
792
- "--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
793
- "--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
1161
+ "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`
794
1162
  };
795
1163
  } catch (error) {
796
1164
  return console.warn("AtomixGlassContainer: Error generating container variables", error),
797
1165
  {
798
- "--atomix-glass-container-padding": "0 0",
799
- "--atomix-glass-container-radius": "0px",
800
- "--atomix-glass-container-backdrop": "none",
801
- "--atomix-glass-container-shadow": "none",
802
- "--atomix-glass-container-shadow-opacity": 1,
803
- "--atomix-glass-container-bg": "none",
804
- "--atomix-glass-container-text-shadow": "none"
1166
+ "--atomix-glass-container-radius": "0px"
805
1167
  };
806
1168
  }
807
- }), [ borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects, overLightConfig ]);
1169
+ }), [ borderRadius ]);
808
1170
  return jsx("div", {
809
- ref: el => {
810
- // Handle forwarded ref
811
- "function" == typeof ref ? ref(el) : ref && (ref.current = el);
812
- },
813
- className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
1171
+ ref: containerRef,
1172
+ className: mergeClassNames(ATOMIX_GLASS.CONTAINER_CLASS, className, isActive && ATOMIX_GLASS.CLASSES.ACTIVE, overLight && ATOMIX_GLASS.CLASSES.OVER_LIGHT),
814
1173
  style: {
815
1174
  ...style,
816
1175
  ...containerVars
@@ -828,8 +1187,8 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
828
1187
  blurAmount: blurAmount,
829
1188
  mode: mode,
830
1189
  id: filterId,
831
- displacementScale: "number" != typeof displacementScale || isNaN(displacementScale) ? 0 : displacementScale,
832
- aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
1190
+ displacementScale: toSafeNumber(displacementScale),
1191
+ aberrationIntensity: toSafeNumber(aberrationIntensity),
833
1192
  shaderMapUrl: shaderMapUrl
834
1193
  }), jsx("div", {
835
1194
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
@@ -851,8 +1210,12 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
851
1210
  });
852
1211
  }));
853
1212
 
854
- // ─── Blur multiplier constants (module-level, never change at runtime) ────────
855
- AtomixGlassContainer.displayName = "AtomixGlassContainer";
1213
+ /**
1214
+ * Internal glass surface that owns backdrop-filter, SVG distortion, and content.
1215
+ *
1216
+ * Layout and stacking styles are applied via the `style` prop from the parent.
1217
+ * The root wrapper supplies CSS custom properties only.
1218
+ */ AtomixGlassContainer.displayName = "AtomixGlassContainer";
856
1219
 
857
1220
  // Singleton instance
858
1221
  const globalMouseTracker = new
@@ -967,28 +1330,32 @@ class {
967
1330
  */ getSubscriberCount() {
968
1331
  return this.listeners.size;
969
1332
  }
970
- }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
1333
+ }, {BORDER: BORDER, CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, BORDER_GRADIENT = BORDER.GRADIENT, WHITE = CONSTANTS$2.PALETTE.WHITE, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
971
1334
  if (!wrapperElement && !containerElement) return;
972
1335
  if (!validateGlassSize(params.glassSize)) return;
973
- const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, isFixedOrSticky: isFixedOrSticky = !1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
1336
+ const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, isFixedOrSticky: isFixedOrSticky = !1, borderAnimated: borderAnimated = !0, borderOpacityMultiplier: borderOpacityMultiplier = 1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), overLightConfig = {
974
1337
  opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
975
1338
  contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
976
1339
  brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
977
1340
  shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
978
1341
  borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
979
1342
  saturationBoost: baseOverLightConfig.saturationBoost
980
- }, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, stretchMagnitude = ((pos1, pos2) => {
981
- if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
982
- const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
983
- return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
984
- })({
985
- x: 0,
986
- y: 0
987
- }, elasticTranslation), tensionFactor = smoothstep(stretchMagnitude / 80), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
1343
+ }, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, tensionFactor =
1344
+ /**
1345
+ * Computes tension factor from elastic translation magnitude (0–1).
1346
+ */
1347
+ function(elasticTranslation) {
1348
+ const magnitude = Math.hypot(elasticTranslation.x, elasticTranslation.y);
1349
+ return smoothstep(magnitude / 80);
1350
+ }
1351
+ /**
1352
+ * Updates the styles of the AtomixGlass wrapper and container elements imperatively
1353
+ * to avoid React re-renders on mouse movement.
1354
+ */ (elasticTranslation), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
988
1355
  // Calculate mouse influence
989
1356
  // Update Wrapper Styles (glassVars)
990
1357
  if (wrapperElement) {
991
- const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, velocityRotation = (mouseVelocity.x + elasticVelocity.x) * (GRADIENT.VELOCITY_ANGLE_MULTIPLIER || 2.5), borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = GRADIENT.CHROMATIC_OFFSET || 1.5, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), tensionGlow = 1 + .5 * tensionFactor, borderOpacities = [ (GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
1358
+ const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
992
1359
  hover1: {
993
1360
  x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
994
1361
  y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
@@ -1005,28 +1372,55 @@ class {
1005
1372
  x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
1006
1373
  y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
1007
1374
  }, opacityValues = {
1008
- hover1: isHovered || isActive ? .5 : 0,
1009
- hover2: isActive ? .5 : 0,
1010
- hover3: isHovered ? .4 : isActive ? .8 : 0,
1011
- base: isOverLight ? overLightConfig.opacity : 0,
1012
- over: isOverLight ? 1.1 * overLightConfig.opacity : 0
1375
+ // hover-1: ambient highlight glow present on hover and during press
1376
+ hover1: isHovered || isActive ? 1 : 0,
1377
+ // hover-2: press depth shadow only fires on active (mousedown)
1378
+ hover2: isActive ? 1 : 0,
1379
+ // hover-3: global soft-light surface shift half-strength on hover, full on press
1380
+ hover3: isActive ? 1 : isHovered ? .55 : 0,
1381
+ // Dark chrome: faint smoky tint; over-light keeps stronger fill
1382
+ base: isOverLight ? overLightConfig.opacity : .14,
1383
+ over: isOverLight ? 1.1 * overLightConfig.opacity : .1
1013
1384
  }, style = wrapperElement.style;
1014
1385
  style.setProperty("--atomix-glass-transform", transformStyle || "none");
1015
1386
  // Parallax for content (liquid refraction feel)
1016
1387
  const parallaxFactor = .38 + .12 * tensionFactor;
1017
1388
  style.setProperty("--atomix-glass-child-parallax", `translate(${elasticTranslation.x * -parallaxFactor}px, ${elasticTranslation.y * -parallaxFactor}px)`),
1018
- style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString()),
1389
+ style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString());
1019
1390
  // ── Chromatic Rim Lighting ──────────────────────────────────────
1020
- // Layer 1: Core White/Blue highlight
1021
- style.setProperty("--atomix-glass-border-gradient-1", `linear-gradient(${angleB}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
1022
- // Layer 2: Subtle Red/Warm highlight (offset angle)
1023
- style.setProperty("--atomix-glass-border-gradient-2", `linear-gradient(${angleR}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
1024
- // Hover gradients
1025
- style.setProperty("--atomix-glass-hover-1-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`),
1026
- style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`),
1027
- style.setProperty("--atomix-glass-hover-3-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`),
1028
- style.setProperty("--atomix-glass-base-gradient", isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`),
1029
- style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`),
1391
+ const borderVars = ATOMIX_GLASS.BORDER.GRADIENT_CSS_VARS;
1392
+ if (borderAnimated && !effectiveWithoutEffects) {
1393
+ const borderCssVars =
1394
+ /**
1395
+ * Builds animated chromatic rim CSS variables for border layers 1 and 2.
1396
+ * When empty, SCSS static conic/linear fallbacks apply.
1397
+ */
1398
+ function(params) {
1399
+ const {mouseOffset: mouseOffset, mouseVelocity: mouseVelocity, elasticVelocity: elasticVelocity, borderOpacity: borderOpacity, opacityMultiplier: opacityMultiplier = 1, tensionFactor: tensionFactor = 0} = params, mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), velocityRotation = (mouseVelocity.x + elasticVelocity.x) * BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER, borderGradientAngle = BORDER_GRADIENT.BASE_ANGLE + mx * BORDER_GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = BORDER_GRADIENT.CHROMATIC_OFFSET, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, borderStop1 = Math.max(BORDER_GRADIENT.STOP_1.MIN, BORDER_GRADIENT.STOP_1.BASE + my * BORDER_GRADIENT.STOP_1.MULTIPLIER), borderStop2 = Math.min(BORDER_GRADIENT.STOP_2.MAX, BORDER_GRADIENT.STOP_2.BASE + my * BORDER_GRADIENT.STOP_2.MULTIPLIER), tensionGlow = 1 + .5 * tensionFactor, opacities = BORDER_GRADIENT.OPACITY, borderOpacities = [ (opacities.BASE_1 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_2 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow, (opacities.BASE_3 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_4 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = borderOpacity * opacityMultiplier, gradient1 = `linear-gradient(${angleB}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`, gradient2 = `linear-gradient(${angleR}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`;
1400
+ return {
1401
+ [BORDER.GRADIENT_CSS_VARS.GRADIENT_1]: gradient1,
1402
+ [BORDER.GRADIENT_CSS_VARS.GRADIENT_2]: gradient2
1403
+ };
1404
+ }({
1405
+ mouseOffset: mouseOffset,
1406
+ mouseVelocity: mouseVelocity,
1407
+ elasticVelocity: elasticVelocity,
1408
+ borderOpacity: overLightConfig.borderOpacity,
1409
+ opacityMultiplier: borderOpacityMultiplier,
1410
+ tensionFactor: tensionFactor
1411
+ });
1412
+ style.setProperty(borderVars.GRADIENT_1, borderCssVars[borderVars.GRADIENT_1] ?? ""),
1413
+ style.setProperty(borderVars.GRADIENT_2, borderCssVars[borderVars.GRADIENT_2] ?? "");
1414
+ } else style.removeProperty(borderVars.GRADIENT_1), style.removeProperty(borderVars.GRADIENT_2);
1415
+ // Hover gradients — cursor-relative radial positions for realistic light tracking.
1416
+ // hover-1: white overlay highlight following cursor (works on both dark + light)
1417
+ style.setProperty("--atomix-glass-hover-1-gradient", `radial-gradient(65% 55% at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, 0.24) 0%, rgba(${whiteColor}, 0.06) 45%, rgba(${whiteColor}, 0) 72%)`),
1418
+ // hover-2: press depth — darkens at cursor with multiply blend, isOverLight uses stronger black
1419
+ style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.22) 0%, rgba(${blackColor}, 0.06) 50%, rgba(${blackColor}, 0) 72%)` : `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.18) 0%, rgba(${blackColor}, 0.04) 50%, rgba(${blackColor}, 0) 72%)`),
1420
+ // hover-3: full-surface soft-light tint; linear gradient angled with cursor X
1421
+ style.setProperty("--atomix-glass-hover-3-gradient", `linear-gradient(${150 + .3 * mx}deg, rgba(${whiteColor}, ${isOverLight ? .08 : .12}) 0%, rgba(${whiteColor}, 0.04) 55%, rgba(${whiteColor}, 0) 100%)`),
1422
+ style.setProperty("--atomix-glass-base-gradient", isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `linear-gradient(180deg, rgba(${blackColor}, 0.42) 0%, rgba(${blackColor}, 0.22) 55%, rgba(${blackColor}, 0.12) 100%)`),
1423
+ style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `radial-gradient(120% 80% at 50% 0%, rgba(${whiteColor}, 0.14) 0%, rgba(${whiteColor}, 0) 55%)`),
1030
1424
  // Opacities
1031
1425
  style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
1032
1426
  style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
@@ -1063,151 +1457,16 @@ class {
1063
1457
  backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})`;
1064
1458
  // Container variables
1065
1459
  const style = containerElement.style;
1066
- style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
1460
+ style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
1067
1461
  style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
1068
1462
  // Shadows
1069
- style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset"),
1463
+ style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.35 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.15 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.06 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.08 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : ATOMIX_GLASS.CONSTANTS.CONTAINER_SHADOW.LIGHT),
1070
1464
  style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
1071
1465
  style.setProperty("--atomix-glass-container-bg", isOverLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none"),
1072
1466
  style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
1073
- style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)");
1467
+ style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0 4px 16px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.10)");
1074
1468
  }
1075
- };
1076
-
1077
- /**
1078
- * Updates the styles of the AtomixGlass wrapper and container elements imperatively
1079
- * to avoid React re-renders on mouse movement.
1080
- */
1081
- /**
1082
- * Animation System for AtomixGlass Component
1083
- *
1084
- * Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
1085
- * - Feature 1.1: Time-Based Animation System
1086
- * - Feature 1.2: Multi-Layer Distortion System (FBM)
1087
- *
1088
- * @packageDocumentation
1089
- */
1090
- // ============================================================================
1091
- // Noise Functions for FBM (Feature 1.2)
1092
- // ============================================================================
1093
- /**
1094
- * Perlin noise implementation for smooth gradient noise
1095
- *
1096
- * @param x - X coordinate
1097
- * @param y - Y coordinate
1098
- * @returns Noise value in range [0, 1]
1099
- */
1100
- function perlinNoise(x, y) {
1101
- // Simplified Perlin noise using pseudo-random gradients
1102
- const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = fade(xf), v = fade(yf), A = p[X] + Y & 255, B = p[X + 1] + Y & 255, ga = grad(p[A], xf, yf), gb = grad(p[B], xf - 1, yf), gc = grad(p[A + 1 & 255], xf, yf - 1), gd = grad(p[B + 1 & 255], xf - 1, yf - 1), lerpX1 = lerp(ga, gb, u), lerpX2 = lerp(gc, gd, u);
1103
- // Scale to [0, 1] range
1104
- return (lerp(lerpX1, lerpX2, v) + 1) / 2;
1105
- }
1106
-
1107
- // ============================================================================
1108
- // Fractal Brownian Motion (FBM) Engine (Feature 1.2)
1109
- // ============================================================================
1110
- /**
1111
- * Creates an FBM engine with configurable parameters
1112
- *
1113
- * @param config - FBM configuration (octaves, lacunarity, gain)
1114
- * @returns Object with fbm function
1115
- *
1116
- * @example
1117
- * ```typescript
1118
- * const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
1119
- *
1120
- * // Generate noise at position (0.5, 0.5) with time animation
1121
- * const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
1122
- * ```
1123
- */ function createFBMEngine(config) {
1124
- /**
1125
- * Fractal Brownian Motion function
1126
- * Combines multiple octaves of noise for complex, natural patterns
1127
- *
1128
- * @param x - X coordinate
1129
- * @param y - Y coordinate
1130
- * @param time - Optional time value for animation
1131
- * @returns FBM noise value in range [0, 1]
1132
- */
1133
- const fbm = (x, y, time = 0) => {
1134
- let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
1135
- // Convert to seconds for reasonable animation speed
1136
- for (let i = 0; i < config.octaves; i++)
1137
- // Apply time-based phase shift to all octaves
1138
- value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
1139
- frequency *= config.lacunarity, // Increase frequency
1140
- amplitude *= config.gain;
1141
- return value;
1142
- };
1143
- /**
1144
- * Get FBM with simple time factor
1145
- */ return {
1146
- fbm: fbm,
1147
- fbmWithTime: (x, y, time) => fbm(x, y, time)
1148
- };
1149
- }
1150
-
1151
- /**
1152
- * Gets optimal FBM config based on quality preset
1153
- *
1154
- * @param quality - Quality preset level
1155
- * @returns FBM configuration for the quality level
1156
- */ const fbmEngineCache = new Map;
1157
-
1158
- // ============================================================================
1159
- // Shader Utility Functions for Time-Based Effects
1160
- // ============================================================================
1161
- /**
1162
- * Liquid glass distortion with time-based animation
1163
- * Uses FBM to create organic, flowing liquid effects
1164
- *
1165
- * @param uv - UV coordinates (normalized 0-1)
1166
- * @param time - Elapsed time in milliseconds
1167
- * @param config - FBM configuration
1168
- * @returns Distorted UV coordinates
1169
- */ function liquidGlassWithTime(uv, time, config) {
1170
- const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
1171
- let fbmEngine = fbmEngineCache.get(configKey);
1172
- fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
1173
- // Animate noise with time
1174
- const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
1175
- return {
1176
- x: uv.x + .04 * (animatedNoise - .5),
1177
- y: uv.y + .04 * (animatedNoise - .5)
1178
- };
1179
- }
1180
-
1181
- // ============================================================================
1182
- // Helper Functions
1183
- // ============================================================================
1184
- /**
1185
- * Fade curve for smooth interpolation (Perlin's fade function)
1186
- */ function fade(t) {
1187
- return t * t * t * (t * (6 * t - 15) + 10);
1188
- }
1189
-
1190
- /**
1191
- * Linear interpolation
1192
- */ function lerp(a, b, t) {
1193
- return a + t * (b - a);
1194
- }
1195
-
1196
- /**
1197
- * Gradient calculation for Perlin noise
1198
- */ function grad(hash, x, y) {
1199
- const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
1200
- return (1 & h ? -u : u) + (2 & h ? -v : v);
1201
- }
1202
-
1203
- /**
1204
- * Permutation table for Perlin noise
1205
- */ const p = (() => {
1206
- const permutation = [];
1207
- for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
1208
- // Duplicate for overflow handling
1209
- return [ ...permutation, ...permutation ];
1210
- })(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
1469
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
1211
1470
 
1212
1471
  const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
1213
1472
  parentElement && backgroundDetectionCache.set(parentElement, {
@@ -1222,12 +1481,35 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
1222
1481
  * Composable hook for AtomixGlass component logic
1223
1482
  * Manages all state, calculations, and event handlers
1224
1483
  */
1225
- function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1, withTimeAnimation:
1226
- // Default priority
1227
- // Phase 1: Animation System Props
1228
- withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
1229
- // State
1230
- const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
1484
+ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, border: border, withBorder: withBorder = !0, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1}) {
1485
+ // State
1486
+ const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), resolvedBorder = useMemo((() =>
1487
+ /**
1488
+ * Resolves `border` and legacy `withBorder` into a single configuration object.
1489
+ */
1490
+ function(border, withBorder) {
1491
+ const legacyDefault = withBorder ?? !0;
1492
+ return void 0 === border ? {
1493
+ enabled: legacyDefault,
1494
+ width: BORDER.DEFAULT_WIDTH,
1495
+ opacityMultiplier: 1,
1496
+ animated: !0
1497
+ } : "boolean" == typeof border ? {
1498
+ enabled: border,
1499
+ width: BORDER.DEFAULT_WIDTH,
1500
+ opacityMultiplier: 1,
1501
+ animated: !0
1502
+ } : {
1503
+ enabled: border.enabled ?? legacyDefault,
1504
+ width: (value = border.width, void 0 === value ? BORDER.DEFAULT_WIDTH : "number" == typeof value ? `${value}px` : value),
1505
+ opacityMultiplier: border.opacity ?? 1,
1506
+ animated: !1 !== border.animated
1507
+ };
1508
+ /**
1509
+ * Formats border width for CSS custom properties.
1510
+ */
1511
+ var value;
1512
+ }(border, withBorder)), [ border, withBorder ]), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
1231
1513
  x: 0,
1232
1514
  y: 0
1233
1515
  }), internalMouseOffsetRef = useRef({
@@ -1251,52 +1533,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1251
1533
  }), scaleVelocityRef = useRef({
1252
1534
  x: 0,
1253
1535
  y: 0
1254
- });
1255
- useRef(0);
1256
- const mouseVelocityRef = useRef({
1536
+ }), mouseVelocityRef = useRef({
1257
1537
  x: 0,
1258
1538
  y: 0
1259
- }), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), animationFrameIdRef = useRef(null), animationStartTimeRef = useRef(0), elapsedTimeRef = useRef(0), shaderTimeRef = useRef(0), fbmConfig = useMemo((() => {
1260
- // If quality preset is provided, use it as base
1261
- const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
1262
- // Override with custom values if provided
1263
- var quality;
1264
- return {
1265
- octaves: distortionOctaves ?? preset.octaves,
1266
- lacunarity: distortionLacunarity ?? preset.lacunarity,
1267
- gain: distortionGain ?? preset.gain
1268
- };
1269
- }), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
1270
- /**
1271
- * Animation loop for time-based effects
1272
- */
1273
- useEffect((() => {
1274
- if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
1275
- let lastFrameTime = performance.now();
1276
- /**
1277
- * Animation frame handler
1278
- */ const animate = currentTime => {
1279
- // Calculate delta time
1280
- const deltaTime = currentTime - lastFrameTime;
1281
- lastFrameTime = currentTime;
1282
- // Apply animation speed multiplier
1283
- const scaledDelta = deltaTime * animationSpeed;
1284
- elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
1285
- // Continue animation loop
1286
- animationFrameIdRef.current = requestAnimationFrame(animate);
1287
- };
1288
- // Start animation
1289
- // Cleanup
1290
- return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
1291
- () => {
1292
- null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
1293
- animationFrameIdRef.current = null);
1294
- };
1295
- }), [ effectiveWithTimeAnimation, animationSpeed ]);
1296
- /**
1297
- * Get current shader time for animations
1298
- */
1299
- const getShaderTime = useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
1539
+ }), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
1300
1540
  const [glassSize, setGlassSize] = useState({
1301
1541
  width: 270,
1302
1542
  height: 69
@@ -1356,9 +1596,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1356
1596
  effectiveBorderRadius: effectiveBorderRadius,
1357
1597
  cachedRectRef: cachedRectRef
1358
1598
  }), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
1359
- /**
1360
- * Apply time-based distortion to UV coordinates
1361
- */
1362
1599
  // Extract border-radius from children
1363
1600
  useEffect((() => {
1364
1601
  const extractRadius = () => {
@@ -1518,25 +1755,26 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1518
1755
  * Get effective overLight value based on configuration
1519
1756
  */
1520
1757
  const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
1521
- const isOverLight = getEffectiveOverLight(), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
1758
+ const isOverLight = getEffectiveOverLight(), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), baseConfig = {
1522
1759
  isOverLight: isOverLight,
1523
1760
  threshold: .7,
1524
1761
  opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
1525
- contrast: 1.4,
1526
- brightness: .9,
1527
- saturationBoost: 1.3,
1528
- // Fixed value dynamic saturation amplifies perceived displacement
1529
- shadowIntensity: .9,
1530
- borderOpacity: .7
1762
+ // Dark UI (Apple Music): neutral contrast + slight brightness lift
1763
+ contrast: isOverLight ? 1.4 : 1.02,
1764
+ brightness: isOverLight ? .9 : 1.02,
1765
+ saturationBoost: isOverLight ? 1.3 : 1,
1766
+ shadowIntensity: isOverLight ? .9 : 1,
1767
+ borderOpacity: isOverLight ? ATOMIX_GLASS.BORDER.OVER_LIGHT.opacity : ATOMIX_GLASS.BORDER.DARK.opacity
1531
1768
  };
1532
1769
  if ("object" == typeof overLight && null !== overLight) {
1533
- const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), finalConfig = {
1770
+ const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), validatedBorderOpacity = validateConfigValue(objConfig.borderOpacity, .1, 1, baseConfig.borderOpacity), finalConfig = {
1534
1771
  ...baseConfig,
1535
1772
  threshold: validatedThreshold,
1536
1773
  opacity: validatedOpacity * hoverIntensity * activeIntensity,
1537
1774
  contrast: validatedContrast,
1538
1775
  brightness: validatedBrightness,
1539
- saturationBoost: validatedSaturationBoost
1776
+ saturationBoost: validatedSaturationBoost,
1777
+ borderOpacity: validatedBorderOpacity
1540
1778
  };
1541
1779
  return "undefined" == typeof process || process.env, finalConfig;
1542
1780
  }
@@ -1561,8 +1799,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1561
1799
  };
1562
1800
  const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
1563
1801
  internalGlobalMousePositionRef.current = {
1564
- x: lerp$1(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
1565
- y: lerp$1(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
1802
+ x: lerp(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
1803
+ y: lerp(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
1566
1804
  };
1567
1805
  // ── Calculate Elastic Physics ─────────────────────────────────────
1568
1806
  let targetElasticTranslation = {
@@ -1634,12 +1872,13 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1634
1872
  withLiquidBlur: withLiquidBlur,
1635
1873
  blurAmount: blurAmount,
1636
1874
  saturation: saturation,
1637
- padding: padding,
1638
- isFixedOrSticky: isFixedOrSticky
1875
+ isFixedOrSticky: isFixedOrSticky,
1876
+ borderAnimated: resolvedBorder.animated,
1877
+ borderOpacityMultiplier: resolvedBorder.opacityMultiplier
1639
1878
  }), Math.abs(mouseVelocityRef.current.x) < .001 && Math.abs(mouseVelocityRef.current.y) < .001 && Math.abs(elasticVelocityRef.current.x) < .001 && Math.abs(elasticVelocityRef.current.y) < .001 && Math.abs(scaleVelocityRef.current.x) < .001 && Math.abs(scaleVelocityRef.current.y) < .001 && Math.abs(internalMouseOffsetRef.current.x - targetMouseOffsetRef.current.x) < .001 && Math.abs(internalMouseOffsetRef.current.y - targetMouseOffsetRef.current.y) < .001 ? stopLerpLoop() : lerpRafRef.current = requestAnimationFrame(tick);
1640
1879
  };
1641
1880
  lerpRafRef.current = requestAnimationFrame(tick);
1642
- }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
1881
+ }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, isFixedOrSticky, resolvedBorder.animated, resolvedBorder.opacityMultiplier, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
1643
1882
  if (externalGlobalMousePosition && externalMouseOffset) return;
1644
1883
  if (effectiveWithoutEffects) return;
1645
1884
  const container = mouseContainer?.current || glassRef.current;
@@ -1703,9 +1942,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1703
1942
  withLiquidBlur: withLiquidBlur,
1704
1943
  blurAmount: blurAmount,
1705
1944
  saturation: saturation,
1706
- padding: padding
1945
+ borderAnimated: resolvedBorder.animated,
1946
+ borderOpacityMultiplier: resolvedBorder.opacityMultiplier
1707
1947
  });
1708
- }), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
1948
+ }), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, resolvedBorder.animated, resolvedBorder.opacityMultiplier, onClick ]);
1709
1949
  // Event handlers
1710
1950
  const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
1711
1951
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
@@ -1725,9 +1965,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1725
1965
  mouseOffset: mouseOffset,
1726
1966
  // This is now static (refs or props) unless prop changes
1727
1967
  overLightConfig: overLightConfig,
1968
+ resolvedBorder: resolvedBorder,
1728
1969
  transformStyle: transformStyle,
1729
- getShaderTime: getShaderTime,
1730
- applyTimeBasedDistortion: applyTimeBasedDistortion,
1731
1970
  handleMouseEnter: handleMouseEnter,
1732
1971
  handleMouseLeave: handleMouseLeave,
1733
1972
  handleMouseDown: handleMouseDown,
@@ -1759,317 +1998,41 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1759
1998
  maxWidth: 1024,
1760
1999
  params: {
1761
2000
  distortionOctaves: 4,
1762
- displacementScale: .85,
1763
- blurAmount: .9,
1764
- animationSpeed: .9,
1765
- chromaticIntensity: .75
1766
- }
1767
- },
1768
- desktop: {
1769
- minWidth: 1025,
1770
- params: {
1771
- distortionOctaves: 5,
1772
- displacementScale: 1,
1773
- blurAmount: 1,
1774
- animationSpeed: 1,
1775
- chromaticIntensity: 1
1776
- }
1777
- }
1778
- };
1779
-
1780
- /**
1781
- * Device performance tier detection
1782
- *
1783
- * Uses Device Memory API and Hardware Concurrency API to classify devices
1784
- * into performance tiers for automatic quality adjustment.
1785
- *
1786
- * @returns Performance tier classification
1787
- */ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
1788
-
1789
- function getDefaultExportFromCjs(x) {
1790
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
1791
- }
1792
-
1793
- var fails$8 = function(exec) {
1794
- try {
1795
- return !!exec();
1796
- } catch (error) {
1797
- return !0;
1798
- }
1799
- }, functionBindNative = !fails$8((function() {
1800
- // eslint-disable-next-line es/no-function-prototype-bind -- safe
1801
- var test = function() {/* empty */}.bind();
1802
- // eslint-disable-next-line no-prototype-builtins -- safe
1803
- return "function" != typeof test || test.hasOwnProperty("prototype");
1804
- })), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
1805
- return function() {
1806
- return call$5.apply(fn, arguments);
1807
- };
1808
- }, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
1809
- return it && it.Math === Math && it;
1810
- }, globalThis_1 =
1811
- // eslint-disable-next-line es/no-global-this -- safe
1812
- check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
1813
- // eslint-disable-next-line no-restricted-globals -- safe
1814
- check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
1815
- // eslint-disable-next-line no-new-func -- fallback
1816
- function() {
1817
- return this;
1818
- }() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
1819
- return call$4.apply(apply$1, arguments);
1820
- }), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
1821
- return stringSlice(toString$3(it), 8, -1);
1822
- }, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
1823
- // Nashorn bug:
1824
- // https://github.com/zloirock/core-js/issues/1128
1825
- // https://github.com/zloirock/core-js/issues/1130
1826
- if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
1827
- }, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
1828
- return "function" == typeof argument || argument === documentAll;
1829
- } : function(argument) {
1830
- return "function" == typeof argument;
1831
- }, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
1832
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
1833
- return 7 !== Object.defineProperty({}, 1, {
1834
- get: function() {
1835
- return 7;
1836
- }
1837
- })[1];
1838
- })), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
1839
- return call$3.apply(call$3, arguments);
1840
- }, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
1841
- 1: 2
1842
- }, 1);
1843
-
1844
- // `Object.prototype.propertyIsEnumerable` method implementation
1845
- // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
1846
- objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
1847
- var descriptor = getOwnPropertyDescriptor$1(this, V);
1848
- return !!descriptor && descriptor.enumerable;
1849
- } : $propertyIsEnumerable;
1850
-
1851
- var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
1852
- return {
1853
- enumerable: !(1 & bitmap),
1854
- configurable: !(2 & bitmap),
1855
- writable: !(4 & bitmap),
1856
- value: value
1857
- };
1858
- }, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
1859
- // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
1860
- // eslint-disable-next-line no-prototype-builtins -- safe
1861
- return !$Object$3("z").propertyIsEnumerable(0);
1862
- })) ? function(it) {
1863
- return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
1864
- } : $Object$3, isNullOrUndefined$2 = function(it) {
1865
- return null == it;
1866
- }, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
1867
- if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
1868
- return it;
1869
- }, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
1870
- return IndexedObject(requireObjectCoercible$2(it));
1871
- }, isCallable$7 = isCallable$8, isObject$5 = function(it) {
1872
- return "object" == typeof it ? null !== it : isCallable$7(it);
1873
- }, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
1874
- return isCallable$6(variable) ? variable : void 0;
1875
- }, navigator$1 = globalThis_1.navigator, userAgent$1 = navigator$1 && navigator$1.userAgent, globalThis$8 = globalThis_1, userAgent = userAgent$1 ? String(userAgent$1) : "", process$1 = globalThis$8.process, Deno = globalThis$8.Deno, versions = process$1 && process$1.versions || Deno && Deno.version, v8 = versions && versions.v8;
1876
-
1877
- v8 && (
1878
- // in old Chrome, versions of V8 isn't V8 = Chrome / 10
1879
- // but their correct versions are not interesting for us
1880
- version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
1881
- // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
1882
- // so check `userAgent` even if `.v8` exists, but 0
1883
- !version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
1884
-
1885
- var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
1886
- var symbol = Symbol("symbol detection");
1887
- // Chrome 38 Symbol has incorrect toString conversion
1888
- // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
1889
- // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
1890
- // of course, fail.
1891
- return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
1892
- // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
1893
- !Symbol.sham && V8_VERSION && V8_VERSION < 41;
1894
- })), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
1895
- return "symbol" == typeof it;
1896
- } : function(it) {
1897
- var $Symbol = function(namespace, method) {
1898
- return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$a[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$a[namespace] && globalThis$a[namespace][method];
1899
- }("Symbol");
1900
- return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
1901
- }, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
1902
- if (isCallable$4(argument)) return argument;
1903
- throw new $TypeError$5(function(argument) {
1904
- try {
1905
- return $String$2(argument);
1906
- } catch (error) {
1907
- return "Object";
1908
- }
1909
- }(argument) + " is not a function");
1910
- }, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
1911
- exports: {}
1912
- }, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
1913
- try {
1914
- defineProperty(globalThis$6, key, {
1915
- value: value,
1916
- configurable: !0,
1917
- writable: !0
1918
- });
1919
- } catch (error) {
1920
- globalThis$6[key] = value;
1921
- }
1922
- return value;
1923
- }("__core-js_shared__", {});
1924
-
1925
- /* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
1926
- version: "3.43.0",
1927
- mode: "pure",
1928
- copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
1929
- license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
1930
- source: "https://github.com/zloirock/core-js"
1931
- });
1932
-
1933
- var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
1934
- return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
1935
- }, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
1936
- return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
1937
- }, wellKnownSymbol$5 = function(name) {
1938
- return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
1939
- WellKnownSymbolsStore[name];
1940
- }, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
1941
- if (!isObject$3(input) || isSymbol$1(input)) return input;
1942
- var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
1943
- if (exoticToPrim) {
1944
- if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
1945
- !isObject$3(result) || isSymbol$1(result)) return result;
1946
- throw new $TypeError$3("Can't convert object to primitive value");
1947
- }
1948
- return void 0 === pref && (pref = "number"), function(input, pref) {
1949
- var fn, val;
1950
- if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
1951
- if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
1952
- if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
1953
- throw new $TypeError$4("Can't convert object to primitive value");
1954
- }(input, pref);
1955
- }, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
1956
- var key = toPrimitive(argument, "string");
1957
- return isSymbol(key) ? key : key + "";
1958
- }, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
1959
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
1960
- return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
1961
- get: function() {
1962
- return 7;
1963
- }
1964
- }).a;
1965
- var it;
1966
- })), DESCRIPTORS$3 = descriptors, call = functionCall, propertyIsEnumerableModule = objectPropertyIsEnumerable, createPropertyDescriptor$1 = createPropertyDescriptor$2, toIndexedObject$1 = toIndexedObject$2, toPropertyKey$1 = toPropertyKey$2, hasOwn$1 = hasOwnProperty_1, IE8_DOM_DEFINE$1 = ie8DomDefine, $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
1967
-
1968
- // `Object.getOwnPropertyDescriptor` method
1969
- // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
1970
- objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
1971
- if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
1972
- return $getOwnPropertyDescriptor$1(O, P);
1973
- } catch (error) {/* empty */}
1974
- if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
1975
- };
1976
-
1977
- var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
1978
- var value = data[normalize(feature)];
1979
- return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
1980
- }, normalize = isForced$1.normalize = function(string) {
1981
- return String(string).replace(replacement, ".").toLowerCase();
1982
- }, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable = aCallable$2, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$8((function() {
1983
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
1984
- return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
1985
- value: 42,
1986
- writable: !1
1987
- }).prototype;
1988
- })), isObject$1 = isObject$5, $String$1 = String, $TypeError$2 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
1989
- if (isObject$1(argument)) return argument;
1990
- throw new $TypeError$2($String$1(argument) + " is not an object");
1991
- }, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
1992
-
1993
- // `Object.defineProperty` method
1994
- // https://tc39.es/ecma262/#sec-object.defineproperty
1995
- objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
1996
- if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
1997
- var current = $getOwnPropertyDescriptor(O, P);
1998
- current && current.writable && (O[P] = Attributes.value, Attributes = {
1999
- configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
2000
- enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
2001
- writable: !1
2002
- });
2001
+ displacementScale: .85,
2002
+ blurAmount: .9,
2003
+ animationSpeed: .9,
2004
+ chromaticIntensity: .75
2005
+ }
2006
+ },
2007
+ desktop: {
2008
+ minWidth: 1025,
2009
+ params: {
2010
+ distortionOctaves: 5,
2011
+ displacementScale: 1,
2012
+ blurAmount: 1,
2013
+ animationSpeed: 1,
2014
+ chromaticIntensity: 1
2015
+ }
2003
2016
  }
2004
- return $defineProperty(O, P, Attributes);
2005
- } : $defineProperty : function(O, P, Attributes) {
2006
- if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
2007
- return $defineProperty(O, P, Attributes);
2008
- } catch (error) {/* empty */}
2009
- if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
2010
- return "value" in Attributes && (O[P] = Attributes.value), O;
2011
2017
  };
2012
2018
 
2013
- var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
2014
- return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
2015
- } : function(object, key, value) {
2016
- return object[key] = value, object;
2017
- }, globalThis$2 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
2018
- return aCallable(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
2019
- return fn.apply(that, arguments);
2020
- };
2021
- }, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
2022
- var Wrapper = function(a, b, c) {
2023
- if (this instanceof Wrapper) {
2024
- switch (arguments.length) {
2025
- case 0:
2026
- return new NativeConstructor;
2027
-
2028
- case 1:
2029
- return new NativeConstructor(a);
2030
-
2031
- case 2:
2032
- return new NativeConstructor(a, b);
2033
- }
2034
- return new NativeConstructor(a, b, c);
2035
- }
2036
- return apply(NativeConstructor, this, arguments);
2037
- };
2038
- return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
2039
- }, _export = function(options, source) {
2040
- var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$2 : STATIC ? globalThis$2[TARGET] : globalThis$2[TARGET] && globalThis$2[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
2041
- for (key in source)
2042
- // contains in native
2043
- USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
2044
- targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
2045
- // export native or implementation
2046
- sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
2047
- // bind methods to global for calling from export context
2048
- resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
2049
- // add a flag to not completely full polyfills
2050
- (options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
2051
- createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
2052
- // export virtual prototype methods
2053
- createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
2054
- // export real prototype methods
2055
- options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
2056
- }, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
2057
- var n = +x;
2058
- return (n > 0 ? floor : ceil)(n);
2059
- }, toIntegerOrInfinity$2 = function(argument) {
2060
- var number = +argument;
2061
- // eslint-disable-next-line no-self-compare -- NaN check
2062
- return number != number || 0 === number ? 0 : trunc(number);
2063
- }, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
2064
- return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
2019
+ /**
2020
+ * Device performance tier detection
2021
+ *
2022
+ * Uses Device Memory API and Hardware Concurrency API to classify devices
2023
+ * into performance tiers for automatic quality adjustment.
2024
+ *
2025
+ * @returns Performance tier classification
2026
+ */ var toIntegerOrInfinity = toIntegerOrInfinity$2, max = Math.max, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
2027
+ return argument = obj.length, (len = toIntegerOrInfinity$1(argument)) > 0 ? min$1(len, 9007199254740991) : 0;
2065
2028
  var argument, len;
2066
2029
  }, createMethod = function(IS_INCLUDES) {
2067
2030
  return function($this, el, fromIndex) {
2068
2031
  var O = toIndexedObject($this), length = lengthOfArrayLike(O);
2069
2032
  if (0 === length) return !IS_INCLUDES && -1;
2070
2033
  var value, index = function(index, length) {
2071
- var integer = toIntegerOrInfinity$1(index);
2072
- return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
2034
+ var integer = toIntegerOrInfinity(index);
2035
+ return integer < 0 ? max(integer + length, 0) : min(integer, length);
2073
2036
  }(fromIndex, length);
2074
2037
  // Array#includes uses SameValueZero equality algorithm
2075
2038
  // eslint-disable-next-line no-self-compare -- NaN check
@@ -2098,12 +2061,7 @@ _export({
2098
2061
  }
2099
2062
  });
2100
2063
 
2101
- var globalThis$1 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$2 = function(CONSTRUCTOR, METHOD) {
2102
- var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
2103
- if (pureMethod) return pureMethod;
2104
- var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
2105
- return NativePrototype && NativePrototype[METHOD];
2106
- }, includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
2064
+ var includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
2107
2065
 
2108
2066
  test[wellKnownSymbol$5("toStringTag")] = "z";
2109
2067
 
@@ -2159,148 +2117,6 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2159
2117
  /**
2160
2118
  * Get GPU memory info if available (Chrome DevTools only)
2161
2119
  */
2162
- /** Map an FPS value to a semantic color token string. */
2163
- const getQualityColor = quality => {
2164
- switch (quality) {
2165
- case "high":
2166
- return "var(--atomix-color-success, #4ade80)";
2167
-
2168
- case "medium":
2169
- return "var(--atomix-color-warning, #fbbf24)";
2170
-
2171
- case "low":
2172
- return "var(--atomix-color-danger, #ef4444)";
2173
-
2174
- default:
2175
- return "#9ca3af";
2176
- }
2177
- }, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
2178
-
2179
- /** Map a quality level string to a semantic color token string. */
2180
- // Inject keyframes once
2181
- if ("undefined" != typeof document) {
2182
- const styleId = "perf-dashboard-keyframes";
2183
- if (!document.getElementById(styleId)) {
2184
- const styleEl = document.createElement("style");
2185
- styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
2186
- document.head.appendChild(styleEl);
2187
- }
2188
- }
2189
-
2190
- /**
2191
- * PerformanceDashboard - Real-time performance monitoring overlay.
2192
- *
2193
- * Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
2194
- * Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
2195
- */ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
2196
- if (!isVisible) return null;
2197
- const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
2198
- var fps;
2199
- const isCritical = metrics.fps < 45;
2200
- return jsxs("div", {
2201
- className: "c-perf-dashboard u-position-fixed u-top-4 u-end-4 u-p-3 u-px-4 u-text-xs u-font-mono u-text-white u-rounded-md u-border u-border-white-alpha-10 u-shadow-lg",
2202
- style: {
2203
- zIndex: 9999,
2204
- minWidth: "12.5rem",
2205
- // 200px
2206
- backgroundColor: "rgba(17, 24, 39, 0.95)",
2207
- backdropFilter: "blur(8px)",
2208
- transition: "opacity 0.3s ease"
2209
- },
2210
- children: [ jsxs("div", {
2211
- className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
2212
- children: [ jsx("span", {
2213
- className: "u-text-sm u-font-bold u-text-white",
2214
- children: "Performance Monitor"
2215
- }), onClose && jsx("button", {
2216
- className: "u-bg-transparent u-border-none u-p-0 u-line-height-1 u-text-base u-text-gray-400 u-cursor-pointer hover:u-text-white",
2217
- onClick: onClose,
2218
- "aria-label": "Close performance dashboard",
2219
- style: {
2220
- transition: "color 0.2s ease"
2221
- },
2222
- children: "×"
2223
- }) ]
2224
- }), jsxs("div", {
2225
- className: "u-flex u-items-center u-justify-between u-mb-1-5",
2226
- children: [ jsx("span", {
2227
- className: "u-text-gray-400 u-me-3",
2228
- children: "FPS"
2229
- }), jsx("span", {
2230
- className: "u-font-bold",
2231
- style: {
2232
- color: fpsColor
2233
- },
2234
- children: Math.round(metrics.fps)
2235
- }) ]
2236
- }), jsxs("div", {
2237
- className: "u-flex u-items-center u-justify-between u-mb-1-5",
2238
- children: [ jsx("span", {
2239
- className: "u-text-gray-400 u-me-3",
2240
- children: "Frame Time"
2241
- }), jsxs("span", {
2242
- className: "u-font-bold",
2243
- children: [ metrics.frameTime.toFixed(2), "ms" ]
2244
- }) ]
2245
- }), jsxs("div", {
2246
- className: "u-flex u-items-center u-justify-between u-mb-1-5",
2247
- children: [ jsx("span", {
2248
- className: "u-text-gray-400 u-me-3",
2249
- children: "Quality"
2250
- }), jsx("span", {
2251
- className: "u-font-bold u-text-uppercase",
2252
- style: {
2253
- fontSize: "0.6875rem",
2254
- // 11px
2255
- color: getQualityColor(metrics.qualityLevel)
2256
- },
2257
- children: metrics.qualityLevel
2258
- }) ]
2259
- }), metrics.gpuMemory && jsxs("div", {
2260
- className: "u-flex u-items-center u-justify-between u-mb-1-5",
2261
- children: [ jsx("span", {
2262
- className: "u-text-gray-400 u-me-3",
2263
- children: "GPU Memory"
2264
- }), jsxs("span", {
2265
- className: "u-font-bold",
2266
- children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
2267
- }) ]
2268
- }), metrics.isAutoScaling && jsx("div", {
2269
- className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
2270
- style: {
2271
- fontSize: "0.625rem",
2272
- // 10px
2273
- color: "#6b7280"
2274
- },
2275
- children: "Auto-scaling active"
2276
- }), jsxs("div", {
2277
- className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
2278
- children: [ jsx("div", {
2279
- className: "u-rounded-full",
2280
- style: {
2281
- width: "0.5rem",
2282
- height: "0.5rem",
2283
- flexShrink: 0,
2284
- backgroundColor: fpsColor,
2285
- ...isCritical && {
2286
- animation: "perf-dashboard-pulse 1s infinite"
2287
- }
2288
- }
2289
- }), jsx("span", {
2290
- className: "u-text-xs",
2291
- style: {
2292
- fontSize: "0.625rem",
2293
- // 10px
2294
- color: fpsColor
2295
- },
2296
- children: getFpsLabel(metrics.fps)
2297
- }) ]
2298
- }) ]
2299
- });
2300
- }));
2301
-
2302
- PerformanceDashboard.displayName = "PerformanceDashboard";
2303
-
2304
2120
  /**
2305
2121
  * Mobile optimization presets
2306
2122
  *
@@ -2420,18 +2236,13 @@ const PERFORMANCE_PRESET = {
2420
2236
  saturation: 70
2421
2237
  }
2422
2238
  }
2423
- }, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, withBorder: withBorder = !0, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
2424
- const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useMemo((() =>
2425
- // Helper to merge refs
2426
- function(...refs) {
2427
- return node => {
2428
- refs.forEach((ref => {
2429
- "function" == typeof ref ? ref(node) : null != ref && (ref.current = node);
2430
- }));
2431
- };
2432
- }
2433
- // Internal implementation with forwardRef
2434
- (ref, internalWrapperRef)), [ ref ]), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = propsIsFixedOrSticky || "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
2239
+ }, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, border: border, withBorder: withBorder = !0, debugBorderRadius: debugBorderRadius = !1, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
2240
+ const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useForkRef(ref, internalWrapperRef), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = (explicit = propsIsFixedOrSticky,
2241
+ position = restStyle.position, Boolean(explicit || "fixed" === position || "sticky" === position));
2242
+ var explicit, position;
2243
+ /**
2244
+ * Extracts layout-related properties from a React `CSSProperties` object.
2245
+ */ const {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown, resolvedBorder: resolvedBorder} = useAtomixGlass({
2435
2246
  glassRef: glassRef,
2436
2247
  contentRef: contentRef,
2437
2248
  wrapperRef: internalWrapperRef,
@@ -2451,20 +2262,13 @@ const PERFORMANCE_PRESET = {
2451
2262
  blurAmount: blurAmount,
2452
2263
  saturation: saturation,
2453
2264
  withLiquidBlur: withLiquidBlur,
2454
- padding: padding,
2265
+ border: border,
2266
+ withBorder: withBorder,
2267
+ debugBorderRadius: debugBorderRadius,
2455
2268
  style: style,
2456
- isFixedOrSticky: isFixedOrSticky,
2457
- // Phase 1: Animation System props
2458
- withTimeAnimation: withTimeAnimation,
2459
- animationSpeed: animationSpeed,
2460
- withMultiLayerDistortion: withMultiLayerDistortion,
2461
- distortionOctaves: distortionOctaves,
2462
- distortionLacunarity: distortionLacunarity,
2463
- distortionGain: distortionGain,
2464
- distortionQuality: distortionQuality
2269
+ isFixedOrSticky: isFixedOrSticky
2465
2270
  });
2466
- // Responsive breakpoint system - automatically adjusts parameters based on viewport
2467
- !
2271
+ (
2468
2272
  /**
2469
2273
  * Responsive Glass Parameters Hook
2470
2274
  *
@@ -2619,7 +2423,7 @@ const PERFORMANCE_PRESET = {
2619
2423
  }), [ enabled ]), useCallback((() => {
2620
2424
  calculateParams();
2621
2425
  }), [ calculateParams ]);
2622
- }({
2426
+ })({
2623
2427
  baseParams: {
2624
2428
  ...useMemo((() =>
2625
2429
  /**
@@ -2653,9 +2457,7 @@ const PERFORMANCE_PRESET = {
2653
2457
  breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
2654
2458
  enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
2655
2459
  debug: !1
2656
- });
2657
- // Performance monitoring - tracks FPS, frame time, memory usage
2658
- const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} =
2460
+ }),
2659
2461
  /**
2660
2462
  * Performance Monitor Hook
2661
2463
  *
@@ -2690,7 +2492,13 @@ const PERFORMANCE_PRESET = {
2690
2492
  timestamp: 0,
2691
2493
  isAutoScaling: !0,
2692
2494
  lowFpsCount: 0
2693
- }), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled), frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
2495
+ }), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled);
2496
+ // Sync external `enabled` prop changes into internal state
2497
+ useEffect((() => {
2498
+ setIsEnabled(enabled ?? !0);
2499
+ }), [ enabled ]);
2500
+ // Refs for frame tracking
2501
+ const frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
2694
2502
  setMetrics((prev => ({
2695
2503
  ...prev,
2696
2504
  ...newMetrics,
@@ -2810,191 +2618,214 @@ const PERFORMANCE_PRESET = {
2810
2618
  /**
2811
2619
  * Reset to auto-scaling mode
2812
2620
  */ var fps, currentQuality;
2813
- return {
2814
- metrics: metrics,
2815
- recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
2816
- isUnderperforming: metrics.fps < minFps,
2817
- setQualityLevel: setQualityLevel,
2818
- resetAutoScaling: resetAutoScaling,
2819
- toggleMonitoring: toggleMonitoring
2820
- };
2621
+ fps = metrics.fps, currentQuality = metrics.qualityLevel, metrics.fps;
2821
2622
  }({
2822
2623
  enabled: debugPerformance,
2823
- // Enable when debugPerformance is true
2824
2624
  debug: !1,
2825
2625
  showOverlay: !1
2826
2626
  });
2827
- // Auto-start performance monitoring when debugPerformance is enabled
2828
- React.useEffect((() => {
2829
- debugPerformance && toggleMonitoring();
2830
- // eslint-disable-next-line react-hooks/exhaustive-deps
2831
- }), [ debugPerformance ]);
2832
- // Re-run when debugPerformance changes
2833
- const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
2834
- if (!isFixedOrSticky) return {};
2835
- const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
2836
- return {
2837
- ...p && {
2838
- position: p
2839
- },
2840
- ...void 0 !== t && {
2841
- top: t
2842
- },
2843
- ...void 0 !== l && {
2844
- left: l
2845
- },
2846
- ...void 0 !== r && {
2847
- right: r
2848
- },
2849
- ...void 0 !== b && {
2850
- bottom: b
2851
- }
2852
- };
2853
- }), [ isFixedOrSticky, restStyle ]);
2854
- // Calculate base style with transforms
2855
- // When layout is hoisted to the root, strip those props from the container
2856
- useMemo((() => {
2857
- if (isFixedOrSticky) {
2858
- const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
2859
- return {
2860
- ...visualStyle
2861
- };
2627
+ const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, containerStyle = useMemo((() => ({
2628
+ ...restStyle,
2629
+ ...void 0 !== customZIndex && {
2630
+ zIndex: customZIndex
2862
2631
  }
2632
+ })), [ restStyle, customZIndex ]), componentClassName = mergeClassNames(ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className), positionStyles = useMemo((() =>
2633
+ /**
2634
+ * Returns the internal positioning context for effect layers relative to the root.
2635
+ */
2636
+ function(isFixedOrSticky, restStyle) {
2863
2637
  return {
2864
- ...restStyle
2638
+ position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
2639
+ top: 0,
2640
+ left: 0,
2641
+ right: "auto",
2642
+ bottom: "auto"
2865
2643
  };
2866
- }), [ isFixedOrSticky, restStyle ]);
2867
- // Build className with state modifiers
2868
- const componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
2869
- position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
2870
- top: isFixedOrSticky ? restStyle.top ?? 0 : 0,
2871
- left: isFixedOrSticky ? restStyle.left ?? 0 : 0,
2872
- right: isFixedOrSticky ? restStyle.right ?? "auto" : "auto",
2873
- bottom: isFixedOrSticky ? restStyle.bottom ?? "auto" : "auto"
2874
- })), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
2875
- // Keep a reference to positionStyles to avoid unused-variable lint,
2876
- // but sizing is driven by explicit width/height or measured size.
2877
- positionStyles.position;
2878
- const resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
2644
+ }
2645
+ /**
2646
+ * Computes `--atomix-glass-width` and `--atomix-glass-height` values.
2647
+ *
2648
+ * Fixed/sticky elements prefer explicit dimensions or measured size; in-flow
2649
+ * elements default to `100%`.
2650
+ */ (isFixedOrSticky, restStyle)), [ isFixedOrSticky, restStyle ]), adjustedSize = useMemo((() => function(options) {
2651
+ const {width: width, height: height, restStyle: restStyle, glassSize: glassSize, isFixedOrSticky: isFixedOrSticky} = options, resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
2879
2652
  return {
2880
2653
  width: resolveLength(effectiveWidth, glassSize.width),
2881
2654
  height: resolveLength(effectiveHeight, glassSize.height)
2882
2655
  };
2883
- }), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height, isFixedOrSticky ]), gradientValues = useMemo((() => {
2884
- const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
2885
- return {
2886
- borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
2887
- borderStop1: Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER),
2888
- borderStop2: Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER),
2889
- borderOpacities: [ GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH ],
2890
- hoverPositions: {
2891
- hover1: {
2892
- x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
2893
- y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
2894
- },
2895
- hover2: {
2896
- x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
2897
- y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
2898
- },
2899
- hover3: {
2900
- x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
2901
- y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
2902
- }
2903
- },
2904
- basePosition: {
2905
- x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
2906
- y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
2907
- },
2908
- mx: mx,
2909
- my: my,
2910
- absMx: absMx,
2911
- absMy: absMy
2912
- };
2913
- }), [ mouseOffset.x, mouseOffset.y ]), clampedOverLightOpacity = Math.max(0, Math.min(1, overLightConfig?.opacity ?? .4)), clampedBorderOpacity = Math.max(0, Math.min(1, overLightConfig?.borderOpacity ?? 1)), opacityValues = useMemo((() => ({
2914
- hover1: isHovered || isActive ? .5 : 0,
2915
- hover2: isActive ? .5 : 0,
2916
- hover3: isHovered ? .4 : isActive ? .8 : 0,
2917
- base: isOverLight ? clampedOverLightOpacity || .4 : 0,
2918
- over: isOverLight ? 1.1 * (clampedOverLightOpacity || .4) : 0
2919
- })), [ isHovered, isActive, isOverLight, clampedOverLightOpacity ]), glassVars = useMemo((() => {
2920
- const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues;
2656
+ }
2657
+ /**
2658
+ * Builds the CSS custom properties applied to the root `.c-atomix-glass` element.
2659
+ *
2660
+ * These variables drive layer geometry, transforms, and stacking offsets. They
2661
+ * must not include layout properties that would interfere with backdrop-filter.
2662
+ */ ({
2663
+ width: width,
2664
+ height: height,
2665
+ restStyle: restStyle,
2666
+ glassSize: glassSize,
2667
+ isFixedOrSticky: isFixedOrSticky
2668
+ })), [ width, height, restStyle, glassSize, isFixedOrSticky ]), glassVars = useMemo((() => function(input) {
2669
+ const {effectiveBorderRadius: effectiveBorderRadius, transformStyle: transformStyle, adjustedSize: adjustedSize, isOverLight: isOverLight, customZIndex: customZIndex, isFixedOrSticky: isFixedOrSticky, positionStyles: positionStyles, restStyle: restStyle, borderWidth: borderWidth = ATOMIX_GLASS.BORDER.DEFAULT_WIDTH} = input, layerPosition =
2670
+ /**
2671
+ * Resolves the `--atomix-glass-position` value for decorative layers.
2672
+ *
2673
+ * Fixed/sticky layers use the same positioning mode as the container; in-flow
2674
+ * layers default to the internal absolute positioning context.
2675
+ */
2676
+ function(isFixedOrSticky, positionStyles, restStyle) {
2677
+ return isFixedOrSticky ? `${function(style) {
2678
+ const {position: position, top: top, left: left, right: right, bottom: bottom, inset: inset} = style;
2679
+ return {
2680
+ ...null != position && {
2681
+ position: position
2682
+ },
2683
+ ...void 0 !== top && {
2684
+ top: top
2685
+ },
2686
+ ...void 0 !== left && {
2687
+ left: left
2688
+ },
2689
+ ...void 0 !== right && {
2690
+ right: right
2691
+ },
2692
+ ...void 0 !== bottom && {
2693
+ bottom: bottom
2694
+ },
2695
+ ...void 0 !== inset && {
2696
+ inset: inset
2697
+ }
2698
+ };
2699
+ }
2700
+ /**
2701
+ * Resolves inset custom properties for decorative layers (hover, borders, backgrounds).
2702
+ *
2703
+ * For fixed and sticky modes, insets mirror the container so sibling layers remain
2704
+ * aligned. In-flow modes, insets follow the consumer `style` when a non-default
2705
+ * `position` is provided.
2706
+ */ (restStyle).position ?? restStyle.position ?? "fixed"}` : `${positionStyles.position}`;
2707
+ }(isFixedOrSticky, positionStyles, restStyle), layerInsets = function(isFixedOrSticky, restStyle) {
2708
+ if (isFixedOrSticky) return {
2709
+ top: formatGlassInsetValue(restStyle.top, 0),
2710
+ left: formatGlassInsetValue(restStyle.left, 0),
2711
+ right: formatGlassInsetValue(restStyle.right, "auto"),
2712
+ bottom: formatGlassInsetValue(restStyle.bottom, "auto")
2713
+ };
2714
+ const position = restStyle.position;
2715
+ return null != position && "static" !== position && "relative" !== position ? {
2716
+ top: formatGlassInsetValue(restStyle.top, 0),
2717
+ left: formatGlassInsetValue(restStyle.left, 0),
2718
+ right: formatGlassInsetValue(restStyle.right, "auto"),
2719
+ bottom: formatGlassInsetValue(restStyle.bottom, "auto")
2720
+ } : {
2721
+ top: "0px",
2722
+ left: "0px",
2723
+ right: "auto",
2724
+ bottom: "auto"
2725
+ };
2726
+ }(isFixedOrSticky, restStyle);
2921
2727
  return {
2922
2728
  ...void 0 !== customZIndex && {
2923
2729
  "--atomix-glass-base-z-index": customZIndex
2924
2730
  },
2925
2731
  "--atomix-glass-radius": `${effectiveBorderRadius}px`,
2926
2732
  "--atomix-glass-transform": transformStyle || "none",
2927
- "--atomix-glass-container-position": `${isFixedOrSticky ? rootLayoutStyle.position : positionStyles.position}`,
2928
- "--atomix-glass-position": `${isFixedOrSticky ? rootLayoutStyle.position : positionStyles.position}`,
2929
- "--atomix-glass-top": `${isFixedOrSticky ? restStyle.top ?? 0 : 0}px`,
2930
- "--atomix-glass-left": `${isFixedOrSticky ? restStyle.left ?? 0 : 0}px`,
2931
- "--atomix-glass-right": isFixedOrSticky ? restStyle.right ?? "auto" : "auto",
2932
- "--atomix-glass-bottom": isFixedOrSticky ? restStyle.bottom ?? "auto" : "auto",
2733
+ "--atomix-glass-container-position": layerPosition,
2734
+ "--atomix-glass-position": layerPosition,
2735
+ "--atomix-glass-top": layerInsets.top,
2736
+ "--atomix-glass-left": layerInsets.left,
2737
+ "--atomix-glass-right": layerInsets.right,
2738
+ "--atomix-glass-bottom": layerInsets.bottom,
2933
2739
  "--atomix-glass-width": adjustedSize.width,
2934
2740
  "--atomix-glass-height": adjustedSize.height,
2935
- "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.125rem)",
2936
- "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
2937
- "--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
2938
- "--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
2939
- "--atomix-glass-hover-1-opacity": opacityValues.hover1,
2940
- "--atomix-glass-hover-1-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
2941
- "--atomix-glass-hover-2-opacity": opacityValues.hover2,
2942
- "--atomix-glass-hover-2-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
2943
- "--atomix-glass-hover-3-opacity": opacityValues.hover3,
2944
- "--atomix-glass-hover-3-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
2945
- "--atomix-glass-base-opacity": opacityValues.base,
2946
- "--atomix-glass-base-gradient": isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
2947
- "--atomix-glass-overlay-opacity": opacityValues.over,
2948
- "--atomix-glass-overlay-gradient": isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
2949
- "--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
2950
- "--atomix-glass-overlay-highlight-bg": `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
2741
+ // Aliases maintained for backward compatibility and consumer overrides.
2742
+ "--atomix-glass-container-width": adjustedSize.width,
2743
+ "--atomix-glass-container-height": adjustedSize.height,
2744
+ [ATOMIX_GLASS.BORDER.WIDTH_CSS_VAR]: borderWidth,
2745
+ "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay"
2746
+ };
2747
+ }
2748
+ /**
2749
+ * Applies mode-specific multipliers and accessibility overrides to container effects.
2750
+ */ ({
2751
+ effectiveBorderRadius: effectiveBorderRadius,
2752
+ transformStyle: transformStyle,
2753
+ adjustedSize: adjustedSize,
2754
+ isOverLight: isOverLight,
2755
+ customZIndex: customZIndex,
2756
+ isFixedOrSticky: isFixedOrSticky,
2757
+ positionStyles: positionStyles,
2758
+ restStyle: restStyle,
2759
+ borderWidth: resolvedBorder.width
2760
+ })), [ effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, customZIndex, isFixedOrSticky, positionStyles, restStyle, resolvedBorder.width ]), containerEffects = useMemo((() => function(options) {
2761
+ const {MULTIPLIERS: MULTIPLIERS, SATURATION: SATURATION} = ATOMIX_GLASS.CONSTANTS, zeroMouse = {
2762
+ x: 0,
2763
+ y: 0
2764
+ }, resolveSaturation = () => options.effectiveHighContrast ? SATURATION.HIGH_CONTRAST : options.isOverLight ? options.saturation * options.saturationBoost : options.saturation;
2765
+ if (options.effectiveWithoutEffects) return {
2766
+ displacementScale: 0,
2767
+ blurAmount: 0,
2768
+ saturation: resolveSaturation(),
2769
+ aberrationIntensity: 0,
2770
+ mouseOffset: zeroMouse,
2771
+ globalMousePosition: zeroMouse
2951
2772
  };
2952
- }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, clampedBorderOpacity, customZIndex, isFixedOrSticky, positionStyles.position, rootLayoutStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), renderBackgroundLayer = layerType => jsx("div", {
2953
- className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" ")
2773
+ let resolvedDisplacement = options.displacementScale;
2774
+ "shader" === options.mode ? resolvedDisplacement *= MULTIPLIERS.SHADER_DISPLACEMENT : options.isOverLight && (resolvedDisplacement *= MULTIPLIERS.OVER_LIGHT_DISPLACEMENT);
2775
+ let resolvedAberration = options.aberrationIntensity;
2776
+ return "shader" === options.mode && (resolvedAberration *= MULTIPLIERS.SHADER_ABERRATION),
2777
+ {
2778
+ displacementScale: resolvedDisplacement,
2779
+ blurAmount: options.blurAmount,
2780
+ saturation: resolveSaturation(),
2781
+ aberrationIntensity: resolvedAberration,
2782
+ mouseOffset: options.mouseOffset,
2783
+ globalMousePosition: options.globalMousePosition
2784
+ };
2785
+ }({
2786
+ displacementScale: displacementScale,
2787
+ blurAmount: blurAmount,
2788
+ saturation: saturation,
2789
+ aberrationIntensity: aberrationIntensity,
2790
+ mode: mode,
2791
+ effectiveWithoutEffects: effectiveWithoutEffects,
2792
+ effectiveHighContrast: effectiveHighContrast,
2793
+ isOverLight: isOverLight,
2794
+ saturationBoost: overLightConfig.saturationBoost,
2795
+ mouseOffset: mouseOffset,
2796
+ globalMousePosition: globalMousePosition
2797
+ })), [ displacementScale, blurAmount, saturation, aberrationIntensity, mode, effectiveWithoutEffects, effectiveHighContrast, isOverLight, overLightConfig.saturationBoost, mouseOffset, globalMousePosition ]), renderBackgroundLayer = layerType => jsx("div", {
2798
+ "aria-hidden": "true",
2799
+ className: mergeClassNames(ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS)
2954
2800
  });
2955
- // Calculate position and size styles for internal layers
2956
- // When root is fixed/sticky, internal layers use absolute (relative to root)
2957
- return jsxs("div", {
2801
+ return jsxs("div", {
2958
2802
  ...rest,
2959
2803
  ref: mergedRef,
2960
2804
  className: componentClassName,
2961
- style: {
2962
- ...glassVars
2963
- },
2805
+ style: glassVars,
2964
2806
  role: role || (onClick ? "button" : void 0),
2965
2807
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
2966
2808
  "aria-label": ariaLabel,
2967
2809
  "aria-describedby": ariaDescribedBy,
2968
2810
  "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
2969
- "aria-pressed": onClick ? isActive : void 0,
2970
2811
  onKeyDown: onClick ? handleKeyDown : void 0,
2971
2812
  children: [ jsx(AtomixGlassContainer, {
2972
2813
  ref: glassRef,
2973
2814
  contentRef: contentRef,
2974
2815
  className: className,
2975
- style: {
2976
- ...restStyle
2977
- },
2816
+ style: containerStyle,
2978
2817
  borderRadius: effectiveBorderRadius,
2979
- displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
2980
- blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
2981
- saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
2982
- aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
2818
+ displacementScale: containerEffects.displacementScale,
2819
+ blurAmount: containerEffects.blurAmount,
2820
+ saturation: containerEffects.saturation,
2821
+ aberrationIntensity: containerEffects.aberrationIntensity,
2983
2822
  glassSize: glassSize,
2984
- padding: padding,
2985
- mouseOffset: effectiveWithoutEffects ? {
2986
- x: 0,
2987
- y: 0
2988
- } : mouseOffset,
2989
- globalMousePosition: effectiveWithoutEffects ? {
2990
- x: 0,
2991
- y: 0
2992
- } : globalMousePosition,
2823
+ mouseOffset: containerEffects.mouseOffset,
2824
+ globalMousePosition: containerEffects.globalMousePosition,
2993
2825
  onMouseEnter: handleMouseEnter,
2994
2826
  onMouseLeave: handleMouseLeave,
2995
2827
  onMouseDown: handleMouseDown,
2996
2828
  onMouseUp: handleMouseUp,
2997
- isHovered: isHovered,
2998
2829
  isActive: isActive,
2999
2830
  overLight: isOverLight,
3000
2831
  overLightConfig: {
@@ -3010,8 +2841,6 @@ const PERFORMANCE_PRESET = {
3010
2841
  shaderVariant: shaderVariant,
3011
2842
  withLiquidBlur: withLiquidBlur,
3012
2843
  isFixedOrSticky: isFixedOrSticky,
3013
- // Phase 1: Animation System props
3014
- shaderTime: getShaderTime(),
3015
2844
  withTimeAnimation: withTimeAnimation,
3016
2845
  animationSpeed: animationSpeed,
3017
2846
  withMultiLayerDistortion: withMultiLayerDistortion,
@@ -3022,32 +2851,39 @@ const PERFORMANCE_PRESET = {
3022
2851
  children: children
3023
2852
  }), Boolean(onClick) && jsxs(Fragment, {
3024
2853
  children: [ jsx("div", {
2854
+ "aria-hidden": "true",
3025
2855
  className: ATOMIX_GLASS.HOVER_1_CLASS
3026
2856
  }), jsx("div", {
2857
+ "aria-hidden": "true",
3027
2858
  className: ATOMIX_GLASS.HOVER_2_CLASS
3028
2859
  }), jsx("div", {
2860
+ "aria-hidden": "true",
3029
2861
  className: ATOMIX_GLASS.HOVER_3_CLASS
3030
2862
  }) ]
3031
- }), renderBackgroundLayer("dark"), renderBackgroundLayer("black"), shouldRenderOverLightLayers && jsxs(Fragment, {
2863
+ }), [ "dark", "black" ].map((layerType => jsx(React.Fragment, {
2864
+ children: renderBackgroundLayer(layerType)
2865
+ }, layerType))), shouldRenderOverLightLayers && jsxs(Fragment, {
3032
2866
  children: [ jsx("div", {
2867
+ "aria-hidden": "true",
3033
2868
  className: ATOMIX_GLASS.BASE_LAYER_CLASS
3034
2869
  }), jsx("div", {
2870
+ "aria-hidden": "true",
3035
2871
  className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
3036
2872
  }), jsx("div", {
2873
+ "aria-hidden": "true",
3037
2874
  className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
3038
2875
  }) ]
3039
- }), withBorder && jsxs(Fragment, {
2876
+ }), resolvedBorder.enabled && jsxs(Fragment, {
3040
2877
  children: [ jsx("span", {
2878
+ "aria-hidden": "true",
3041
2879
  className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
3042
2880
  }), jsx("span", {
2881
+ "aria-hidden": "true",
3043
2882
  className: ATOMIX_GLASS.BORDER_1_CLASS
3044
2883
  }), jsx("span", {
2884
+ "aria-hidden": "true",
3045
2885
  className: ATOMIX_GLASS.BORDER_2_CLASS
3046
2886
  }) ]
3047
- }), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
3048
- metrics: performanceMetrics,
3049
- isVisible: !0,
3050
- onClose: () => {}
3051
2887
  }) ]
3052
2888
  });
3053
2889
  }));
@@ -3057,44 +2893,16 @@ const PERFORMANCE_PRESET = {
3057
2893
  * Default preset for most mobile devices
3058
2894
  */ AtomixGlassInner.displayName = "AtomixGlass";
3059
2895
 
3060
- /**
3061
- * AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
3062
- * Ref is forwarded to the root `<div>` element.
3063
- */
3064
- const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3065
- // Add input validation
3066
- if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
3067
- const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
3068
- return clamped * clamped * (3 - 2 * clamped);
3069
- }, calculateLength = (x, y) => {
3070
- // Add input validation and error handling
3071
- if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
3072
- // Prevent potential overflow
3073
- const maxX = Math.max(Math.abs(x), Math.abs(y));
3074
- if (0 === maxX) return 0;
3075
- const scaledX = x / maxX, scaledY = y / maxX;
3076
- return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
3077
- }, roundedRectSDF = (x, y, width, height, radius) => {
2896
+ /** Memoized public export. Ref targets the root `.c-atomix-glass` wrapper. */
2897
+ const AtomixGlass = memo(AtomixGlassInner), roundedRectSDF = (x, y, width, height, radius) => {
3078
2898
  // Add input validation
3079
2899
  if ("number" != typeof x || "number" != typeof y || "number" != typeof width || "number" != typeof height || "number" != typeof radius) return 0;
3080
2900
  const qx = Math.abs(x) - width + radius, qy = Math.abs(y) - height + radius;
3081
- return Math.min(Math.max(qx, qy), 0) + calculateLength(Math.max(qx, 0), Math.max(qy, 0)) - radius;
2901
+ return Math.min(Math.max(qx, qy), 0) + vec2Length(Math.max(qx, 0), Math.max(qy, 0)) - radius;
3082
2902
  }, createTexture = (x, y) => ({
3083
2903
  x: "number" != typeof x || isNaN(x) ? .5 : Math.max(0, Math.min(1, x)),
3084
2904
  y: "number" != typeof y || isNaN(y) ? .5 : Math.max(0, Math.min(1, y))
3085
- }), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), clampValue = (value, min, max) =>
3086
- // Add input validation
3087
- "number" != typeof value || "number" != typeof min || "number" != typeof max || isNaN(value) ? min : isNaN(min) ? 0 : isNaN(max) ? 1 : Math.max(min, Math.min(max, value)), easeInOutCubic = t => {
3088
- // Add input validation
3089
- if ("number" != typeof t || isNaN(t)) return 0;
3090
- const clampedT = Math.max(0, Math.min(1, t));
3091
- return clampedT < .5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
3092
- }, easeOutQuart = t => {
3093
- // Add input validation
3094
- if ("number" != typeof t || isNaN(t)) return 0;
3095
- const clampedT = Math.max(0, Math.min(1, t));
3096
- return 1 - Math.pow(1 - clampedT, 4);
3097
- }, noise2D = (x, y) => {
2905
+ }), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), noise2D = (x, y) => {
3098
2906
  // Add input validation
3099
2907
  if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
3100
2908
  const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = easeInOutCubic(xf), v = easeInOutCubic(yf), hash = (i, j) => {
@@ -3133,13 +2941,13 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3133
2941
  x: .5,
3134
2942
  y: .5
3135
2943
  };
3136
- const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(2 * mouseDistance, 1)), organicFlow = fbm(12 * (ix + .5 * mouseX) + time, 12 * (iy + .5 * mouseY) + .7 * time, 3) - .5, distanceToEdge = roundedRectSDF(ix, iy, .4, .3, .35), baseDisplacement = smoothStep(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
2944
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(2 * mouseDistance, 1)), organicFlow = fbm(12 * (ix + .5 * mouseX) + time, 12 * (iy + .5 * mouseY) + .7 * time, 3) - .5, distanceToEdge = roundedRectSDF(ix, iy, .4, .3, .35), baseDisplacement = smoothstepEdge(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
3137
2945
  // Add input validation
3138
2946
  if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y) || isNaN(strength)) return {
3139
2947
  x: 0,
3140
2948
  y: 0
3141
2949
  };
3142
- const distance = calculateLength(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
2950
+ const distance = vec2Length(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
3143
2951
  // Limit distance to prevent extreme values
3144
2952
  return {
3145
2953
  x: x * (1 + distortion),
@@ -3151,7 +2959,7 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3151
2959
  x: 0,
3152
2960
  y: 0
3153
2961
  };
3154
- const distance = calculateLength(x, y);
2962
+ const distance = vec2Length(x, y);
3155
2963
  // Prevent division by zero and extreme values
3156
2964
  if (0 === distance) return {
3157
2965
  x: 0,
@@ -3162,8 +2970,8 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3162
2970
  x: Math.cos(angle) * distance * intensity,
3163
2971
  y: Math.sin(angle) * distance * intensity
3164
2972
  };
3165
- })(ix, iy, .015 * baseDisplacement), scaled = smoothStep(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
3166
- return createTexture(clampValue(finalX * scaled + .5, 0, 1), clampValue(finalY * scaled + .5, 0, 1));
2973
+ })(ix, iy, .015 * baseDisplacement), scaled = smoothstepEdge(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
2974
+ return createTexture(clamp(finalX * scaled + .5, 0, 1), clamp(finalY * scaled + .5, 0, 1));
3167
2975
  },
3168
2976
  // Premium Apple-style fluid glass with enhanced organic flow
3169
2977
  appleFluid: (uv, mousePosition) => {
@@ -3171,8 +2979,8 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3171
2979
  x: .5,
3172
2980
  y: .5
3173
2981
  };
3174
- const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.5 * mouseDistance, 1)), organicX = fbm(10 * (ix + .3 * mouseX) + time, 10 * (iy + .3 * mouseY), 5) - .5, organicY = fbm(10 * (ix - .3 * mouseX), 10 * (iy - .3 * mouseY) + .8 * time, 5) - .5, distanceToEdge = roundedRectSDF(ix, iy, .42, .32, .38), mask = smoothStep(.85, -.1, distanceToEdge), fluidVelocityX = Math.sin(6 * ix + 2 * time) * Math.cos(4 * iy - time) * .025, fluidVelocityY = Math.cos(4 * ix - time) * Math.sin(6 * iy + 2 * time) * .025, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexStrength = mouseFalloff * mouseDistance * .08, vortexX = Math.cos(vortexAngle + time) * vortexStrength, totalY = iy + (.035 * organicY + fluidVelocityY + Math.sin(vortexAngle + time) * vortexStrength) * mask;
3175
- return createTexture(clampValue(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clampValue(totalY + .5, 0, 1));
2982
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.5 * mouseDistance, 1)), organicX = fbm(10 * (ix + .3 * mouseX) + time, 10 * (iy + .3 * mouseY), 5) - .5, organicY = fbm(10 * (ix - .3 * mouseX), 10 * (iy - .3 * mouseY) + .8 * time, 5) - .5, distanceToEdge = roundedRectSDF(ix, iy, .42, .32, .38), mask = smoothstepEdge(.85, -.1, distanceToEdge), fluidVelocityX = Math.sin(6 * ix + 2 * time) * Math.cos(4 * iy - time) * .025, fluidVelocityY = Math.cos(4 * ix - time) * Math.sin(6 * iy + 2 * time) * .025, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexStrength = mouseFalloff * mouseDistance * .08, vortexX = Math.cos(vortexAngle + time) * vortexStrength, totalY = iy + (.035 * organicY + fluidVelocityY + Math.sin(vortexAngle + time) * vortexStrength) * mask;
2983
+ return createTexture(clamp(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clamp(totalY + .5, 0, 1));
3176
2984
  },
3177
2985
  // High-end glass with advanced refraction and depth
3178
2986
  premiumGlass: (uv, mousePosition) => {
@@ -3180,7 +2988,7 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3180
2988
  x: .5,
3181
2989
  y: .5
3182
2990
  };
3183
- const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), centerDistance = calculateLength(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
2991
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), centerDistance = vec2Length(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
3184
2992
  // Multi-layer depth effect
3185
2993
  let depthX = 0, depthY = 0;
3186
2994
  for (let layer = 0; layer < 3; layer++) {
@@ -3188,8 +2996,8 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3188
2996
  depthX += Math.sin(ix * layerScale + layerTime) * layerStrength, depthY += Math.cos(iy * layerScale - layerTime) * layerStrength;
3189
2997
  }
3190
2998
  // Glass refraction with mouse influence
3191
- const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask = smoothStep(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
3192
- return createTexture(clampValue(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clampValue(finalY + .5, 0, 1));
2999
+ const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask = smoothstepEdge(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
3000
+ return createTexture(clamp(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clamp(finalY + .5, 0, 1));
3193
3001
  },
3194
3002
  // Metallic liquid effect with shimmer
3195
3003
  liquidMetal: (uv, mousePosition) => {
@@ -3197,8 +3005,8 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3197
3005
  x: .5,
3198
3006
  y: .5
3199
3007
  };
3200
- const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance = calculateLength(ix - mouseX, iy - mouseY), flowEffect = .02 * Math.sin(15 * flowDistance - 6 * time) * easeOutQuart(1 - Math.min(2 * flowDistance, 1)), distanceToEdge = roundedRectSDF(ix, iy, .41, .31, .37), mask = smoothStep(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
3201
- return createTexture(clampValue(totalX + .5, 0, 1), clampValue(totalY + .5, 0, 1));
3008
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance = vec2Length(ix - mouseX, iy - mouseY), flowEffect = .02 * Math.sin(15 * flowDistance - 6 * time) * easeOutQuart(1 - Math.min(2 * flowDistance, 1)), distanceToEdge = roundedRectSDF(ix, iy, .41, .31, .37), mask = smoothstepEdge(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
3009
+ return createTexture(clamp(totalX + .5, 0, 1), clamp(totalY + .5, 0, 1));
3202
3010
  },
3203
3011
  // basiBasi - Expert Premium Glass Shader
3204
3012
  // The most advanced shader with caustics, spectral dispersion, parallax depth, and volumetric effects
@@ -3207,7 +3015,7 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3207
3015
  x: .5,
3208
3016
  y: .5
3209
3017
  };
3210
- const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
3018
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
3211
3019
  // Add input validation
3212
3020
  "number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(intensity) ? .5 : .5 * (Math.sin(8 * x + 2 * time) * Math.cos(8 * y - 2 * time) * .5 + Math.sin(8 * (x + .5) * 1.3 - 2 * time * .8) * Math.cos(8 * (y - .3) * 1.3 + 2 * time * .8) * .3 + Math.sin(8 * (x - .3) * .7 + 2 * time * 1.2) * Math.cos(8 * (y + .4) * .7 - 2 * time * 1.2) * .2 + 1) * intensity)(ix, iy, time, .8), causticDistortion = .02 * (causticIntensity - .5), refractionAngle = Math.atan2(iy, ix), spectralDispersion = ((x, y, angle) => {
3213
3021
  // Add input validation
@@ -3225,7 +3033,7 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3225
3033
  y: 0
3226
3034
  }
3227
3035
  };
3228
- const distance = calculateLength(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
3036
+ const distance = vec2Length(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
3229
3037
  return {
3230
3038
  r: {
3231
3039
  x: Math.cos(angle) * redOffset,
@@ -3265,8 +3073,8 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3265
3073
  return turbulence;
3266
3074
  })(6 * ix, 6 * iy, time, 6), turbulenceX = .012 * Math.cos(turbulence * Math.PI * 2), turbulenceY = .012 * Math.sin(turbulence * Math.PI * 2), microSurface = ((x, y, time) =>
3267
3075
  // Add input validation
3268
- "number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance = calculateLength(ix, iy), dynamicRefraction = .35 * Math.pow(Math.min(centerDistance, 1), 1.8) * (1 + mouseFalloff * mouseDistance * .8), refractionX = Math.cos(refractionAngle) * dynamicRefraction, refractionY = Math.sin(refractionAngle) * dynamicRefraction, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexDistance = calculateLength(ix - mouseX, iy - mouseY), vortexStrength = mouseFalloff * Math.sin(10 * vortexDistance - 3 * time) * .025, vortexX = Math.cos(vortexAngle + 2 * time) * vortexStrength, vortexY = Math.sin(vortexAngle + 2 * time) * vortexStrength, fluidX = Math.sin(10 * ix + 5 * mouseX + 2.5 * time) * Math.cos(8 * iy - 2 * time) * .018, fluidY = Math.cos(8 * ix - 2 * time) * Math.sin(10 * iy + 5 * mouseY + 2.5 * time) * .018, rippleEffect = (.012 * Math.sin(15 * Math.min(centerDistance, 10) - 4 * time) + .008 * Math.cos(20 * Math.min(centerDistance, 10) + 3 * time)) * mouseFalloff, rippleX = Math.cos(refractionAngle) * rippleEffect, rippleY = Math.sin(refractionAngle) * rippleEffect, distanceToEdge = roundedRectSDF(ix, iy, .44, .34, .39), edgeMask = smoothStep(.92, -.12, distanceToEdge), edgeSoftness = smoothStep(.85, .1, distanceToEdge), finalY = iy + (1.2 * refractionY + .8 * spectralY + 1.5 * parallaxY + .9 * scatteringY + 1 * turbulenceY + .6 * microDetailY + 1.3 * vortexY + 1.1 * fluidY + .7 * rippleY + .8 * causticDistortion) * edgeMask * edgeSoftness * .85;
3269
- return createTexture(clampValue(ix + (1.2 * refractionX + .8 * spectralX + 1.5 * parallaxX + .9 * scatteringX + 1 * turbulenceX + .6 * microDetailX + 1.3 * vortexX + 1.1 * fluidX + .7 * rippleX + causticDistortion) * edgeMask * edgeSoftness * .85 + .5, 0, 1), clampValue(finalY + .5, 0, 1));
3076
+ "number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance = vec2Length(ix, iy), dynamicRefraction = .35 * Math.pow(Math.min(centerDistance, 1), 1.8) * (1 + mouseFalloff * mouseDistance * .8), refractionX = Math.cos(refractionAngle) * dynamicRefraction, refractionY = Math.sin(refractionAngle) * dynamicRefraction, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexDistance = vec2Length(ix - mouseX, iy - mouseY), vortexStrength = mouseFalloff * Math.sin(10 * vortexDistance - 3 * time) * .025, vortexX = Math.cos(vortexAngle + 2 * time) * vortexStrength, vortexY = Math.sin(vortexAngle + 2 * time) * vortexStrength, fluidX = Math.sin(10 * ix + 5 * mouseX + 2.5 * time) * Math.cos(8 * iy - 2 * time) * .018, fluidY = Math.cos(8 * ix - 2 * time) * Math.sin(10 * iy + 5 * mouseY + 2.5 * time) * .018, rippleEffect = (.012 * Math.sin(15 * Math.min(centerDistance, 10) - 4 * time) + .008 * Math.cos(20 * Math.min(centerDistance, 10) + 3 * time)) * mouseFalloff, rippleX = Math.cos(refractionAngle) * rippleEffect, rippleY = Math.sin(refractionAngle) * rippleEffect, distanceToEdge = roundedRectSDF(ix, iy, .44, .34, .39), edgeMask = smoothstepEdge(.92, -.12, distanceToEdge), edgeSoftness = smoothstepEdge(.85, .1, distanceToEdge), finalY = iy + (1.2 * refractionY + .8 * spectralY + 1.5 * parallaxY + .9 * scatteringY + 1 * turbulenceY + .6 * microDetailY + 1.3 * vortexY + 1.1 * fluidY + .7 * rippleY + .8 * causticDistortion) * edgeMask * edgeSoftness * .85;
3077
+ return createTexture(clamp(ix + (1.2 * refractionX + .8 * spectralX + 1.5 * parallaxX + .9 * scatteringX + 1 * turbulenceX + .6 * microDetailX + 1.3 * vortexX + 1.1 * fluidX + .7 * rippleX + causticDistortion) * edgeMask * edgeSoftness * .85 + .5, 0, 1), clamp(finalY + .5, 0, 1));
3270
3078
  },
3271
3079
  // Aliases for compatibility
3272
3080
  plasma: (uv, mousePosition) => fragmentShaders.premiumGlass(uv, mousePosition),
@@ -3308,8 +3116,8 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3308
3116
  let dx = pos.x * w - x, dy = pos.y * h - y;
3309
3117
  // Apply edge smoothing for Apple-like effect
3310
3118
  const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
3311
- dx *= smoothStep(0, .2, edgeFactor), dy *= smoothStep(0, .2, edgeFactor), maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)),
3312
- rawValues.push(dx, dy);
3119
+ dx *= smoothstepEdge(0, .2, edgeFactor), dy *= smoothstepEdge(0, .2, edgeFactor),
3120
+ maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)), rawValues.push(dx, dy);
3313
3121
  }
3314
3122
  // Improved normalization to prevent artifacts while maintaining intensity
3315
3123
  maxScale = Math.max(maxScale, 1);
@@ -3319,9 +3127,9 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3319
3127
  let rawIndex = 0;
3320
3128
  for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
3321
3129
  const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
3322
- data[pixelIndex] = clampValue(255 * r, 0, 255), // Red channel (X displacement)
3323
- data[pixelIndex + 1] = clampValue(255 * g, 0, 255), // Green channel (Y displacement)
3324
- data[pixelIndex + 2] = clampValue(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
3130
+ data[pixelIndex] = clamp(255 * r, 0, 255), // Red channel (X displacement)
3131
+ data[pixelIndex + 1] = clamp(255 * g, 0, 255), // Green channel (Y displacement)
3132
+ data[pixelIndex + 2] = clamp(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
3325
3133
  data[pixelIndex + 3] = 255;
3326
3134
  }
3327
3135
  return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
@@ -3349,34 +3157,10 @@ const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
3349
3157
  return this.canvasDPI;
3350
3158
  }
3351
3159
  },
3352
- createFBMEngine: createFBMEngine,
3353
- fragmentShaders: fragmentShaders,
3354
- liquidGlassWithTime: liquidGlassWithTime
3160
+ fragmentShaders: fragmentShaders
3355
3161
  }, Symbol.toStringTag, {
3356
3162
  value: "Module"
3357
- }));
3358
-
3359
- // Adapted from https://github.com/shuding/liquid-glass
3360
- // Constants
3361
- /**
3362
- * Component Utilities
3363
- *
3364
- * Helper functions for component development with the new customization system
3365
- */
3366
- /**
3367
- * Check if a URL is a YouTube URL
3368
- */
3369
- function isYouTubeUrl(url) {
3370
- return /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/.test(url);
3371
- }
3372
-
3373
- /**
3374
- * Extract YouTube video ID from URL
3375
- */
3376
- /**
3377
- * Advanced Video Player Component
3378
- */
3379
- const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: youtubeId, poster: poster, autoplay: autoplay = !1, loop: loop = !1, muted: muted = !1, controls: controls = !0, preload: preload = "metadata", width: width, height: height, aspectRatio: aspectRatio = "16:9", className: className = "", onPlay: onPlay, onPause: onPause, onEnded: onEnded, onTimeUpdate: onTimeUpdate, onVolumeChange: onVolumeChange, onFullscreenChange: onFullscreenChange, onError: onError, showDownload: showDownload = !1, showShare: showShare = !1, showSettings: showSettings = !0, playbackRates: playbackRates = [ .5, .75, 1, 1.25, 1.5, 2 ], subtitles: subtitles, quality: quality, ambientMode: ambientMode = !1, glass: glass = !1, glassOpacity: glassOpacity = 1, glassContent: glassContent, style: style, ...props}, ref) => {
3163
+ })), VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: youtubeId, poster: poster, autoplay: autoplay = !1, loop: loop = !1, muted: muted = !1, controls: controls = !0, preload: preload = "metadata", width: width, height: height, aspectRatio: aspectRatio = "16:9", className: className = "", onPlay: onPlay, onPause: onPause, onEnded: onEnded, onTimeUpdate: onTimeUpdate, onVolumeChange: onVolumeChange, onFullscreenChange: onFullscreenChange, onError: onError, showDownload: showDownload = !1, showShare: showShare = !1, showSettings: showSettings = !0, playbackRates: playbackRates = [ .5, .75, 1, 1.25, 1.5, 2 ], subtitles: subtitles, quality: quality, ambientMode: ambientMode = !1, glass: glass = !1, glassOpacity: glassOpacity = 1, glassContent: glassContent, style: style, ...props}, ref) => {
3380
3164
  const videoRef = useRef(null), containerRef = useRef(null), canvasRef = useRef(null), iframeRef = useRef(null), [containerBorderRadius, setContainerBorderRadius] = useState(8), isYouTube = "youtube" === type || youtubeId || src && isYouTubeUrl(src), videoId = youtubeId || (isYouTube && src ? function(url) {
3381
3165
  if (!isYouTubeUrl(url)) return null;
3382
3166
  const patterns = [ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, /youtube\.com\/.*[?&]v=([^&\n?#]+)/ ];
@@ -3554,7 +3338,10 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
3554
3338
  getProgressPercentage: getProgressPercentage,
3555
3339
  getBufferedPercentage: getBufferedPercentage
3556
3340
  };
3557
- }({
3341
+ }
3342
+ /**
3343
+ * Advanced Video Player Component
3344
+ */ ({
3558
3345
  videoRef: videoRef,
3559
3346
  containerRef: containerRef,
3560
3347
  onPlay: onPlay,
@@ -4053,6 +3840,8 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
4053
3840
  });
4054
3841
  }));
4055
3842
 
3843
+ // Adapted from https://github.com/shuding/liquid-glass
3844
+ // Constants
4056
3845
  VideoPlayer.displayName = "VideoPlayer";
4057
3846
 
4058
3847
  /**
@@ -4307,10 +4096,10 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
4307
4096
  if (glass) {
4308
4097
  // Default glass settings for badges
4309
4098
  const defaultGlassProps = {
4310
- displacementScale: 20,
4311
- borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
4312
- className: "c-badge--glass",
4313
- elasticity: 0
4099
+ ...GLASS_DEFAULTS_BADGE,
4100
+ // Override borderRadius dynamically if the ref is available
4101
+ borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : GLASS_DEFAULTS_BADGE.borderRadius,
4102
+ className: "c-badge--glass"
4314
4103
  }, glassProps = !0 === glass ? defaultGlassProps : {
4315
4104
  ...defaultGlassProps,
4316
4105
  ...glass
@@ -4375,12 +4164,7 @@ const Spinner = memo( forwardRef((({size: size = "md", variant: variant = "prim
4375
4164
  })
4376
4165
  });
4377
4166
  if (glass) {
4378
- const defaultGlassProps = {
4379
- displacementScale: 20,
4380
- blurAmount: 1,
4381
- borderRadius: 999,
4382
- mode: "shader"
4383
- }, glassProps = !0 === glass ? defaultGlassProps : {
4167
+ const defaultGlassProps = GLASS_DEFAULTS_SPINNER, glassProps = !0 === glass ? defaultGlassProps : {
4384
4168
  ...defaultGlassProps,
4385
4169
  ...glass
4386
4170
  };
@@ -4660,11 +4444,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
4660
4444
  // This is a safe fallback for disabled links.
4661
4445
  if (glass) {
4662
4446
  // Default glass props
4663
- const defaultGlassProps = {
4664
- displacementScale: 20,
4665
- blurAmount: 0,
4666
- saturation: 200
4667
- }, glassProps = !0 === glass ? defaultGlassProps : {
4447
+ const defaultGlassProps = GLASS_DEFAULTS_BUTTON, glassProps = !0 === glass ? defaultGlassProps : {
4668
4448
  ...defaultGlassProps,
4669
4449
  ...glass
4670
4450
  };