@oalacea/chaosui 0.1.0 → 0.5.0

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 (139) hide show
  1. package/bin/cli.js +105 -13
  2. package/components/backgrounds/glow-orbs/index.tsx +1 -1
  3. package/components/buttons/chaos-button/chaos-button.module.css +3 -2
  4. package/components/buttons/cta-brutal/cta-brutal.module.css +81 -0
  5. package/components/buttons/cta-brutal/index.tsx +56 -0
  6. package/components/buttons/dead-button/dead-button.module.css +111 -0
  7. package/components/buttons/dead-button/index.tsx +47 -0
  8. package/components/buttons/deeper-button/deeper-button.module.css +76 -0
  9. package/components/buttons/deeper-button/index.tsx +51 -0
  10. package/components/buttons/dual-choice/dual-choice.module.css +90 -0
  11. package/components/buttons/dual-choice/index.tsx +54 -0
  12. package/components/buttons/glitch-button/glitch-button.module.css +7 -7
  13. package/components/buttons/tension-bar/index.tsx +79 -0
  14. package/components/buttons/tension-bar/tension-bar.module.css +105 -0
  15. package/components/chaos-vars.css +27 -0
  16. package/components/cyber/cyber-avatar/css/cyber-avatar.module.css +60 -0
  17. package/components/cyber/cyber-avatar/css/index.tsx +28 -0
  18. package/components/cyber/cyber-avatar/tailwind/index.tsx +46 -0
  19. package/components/cyber/cyber-input/css/cyber-input.module.css +87 -0
  20. package/components/cyber/cyber-input/css/index.tsx +49 -0
  21. package/components/cyber/cyber-input/tailwind/index.tsx +55 -0
  22. package/components/cyber/cyber-loader/css/cyber-loader.module.css +102 -0
  23. package/components/cyber/cyber-loader/css/index.tsx +58 -0
  24. package/components/cyber/cyber-loader/tailwind/index.tsx +63 -0
  25. package/components/cyber/cyber-modal/css/cyber-modal.module.css +124 -0
  26. package/components/cyber/cyber-modal/css/index.tsx +75 -0
  27. package/components/cyber/cyber-modal/tailwind/index.tsx +87 -0
  28. package/components/cyber/cyber-slider/css/cyber-slider.module.css +61 -0
  29. package/components/cyber/cyber-slider/css/index.tsx +41 -0
  30. package/components/cyber/cyber-slider/tailwind/index.tsx +51 -0
  31. package/components/cyber/cyber-tooltip/css/cyber-tooltip.module.css +67 -0
  32. package/components/cyber/cyber-tooltip/css/index.tsx +36 -0
  33. package/components/cyber/cyber-tooltip/tailwind/index.tsx +48 -0
  34. package/components/decorative/coffee-stain/coffee-stain.module.css +24 -0
  35. package/components/decorative/coffee-stain/index.tsx +55 -0
  36. package/components/decorative/ornaments/index.tsx +51 -0
  37. package/components/decorative/ornaments/ornaments.module.css +33 -0
  38. package/components/decorative/rune-symbols/index.tsx +55 -0
  39. package/components/decorative/rune-symbols/rune-symbols.module.css +22 -0
  40. package/components/effects/glitch-image/css/glitch-image.module.css +64 -0
  41. package/components/effects/glitch-image/css/index.tsx +25 -0
  42. package/components/effects/glitch-image/tailwind/index.tsx +49 -0
  43. package/components/effects/glowing-border/css/glowing-border.module.css +73 -0
  44. package/components/effects/glowing-border/css/index.tsx +45 -0
  45. package/components/effects/glowing-border/tailwind/index.tsx +40 -0
  46. package/components/effects/screen-distortion/screen-distortion.module.css +2 -2
  47. package/components/effects/warning-tape/index.tsx +4 -4
  48. package/components/effects/warning-tape/warning-tape.module.css +2 -0
  49. package/components/layout/data-grid/css/data-grid.module.css +52 -0
  50. package/components/layout/data-grid/css/index.tsx +76 -0
  51. package/components/layout/data-grid/tailwind/index.tsx +74 -0
  52. package/components/layout/hologram-card/css/hologram-card.module.css +102 -0
  53. package/components/layout/hologram-card/css/index.tsx +46 -0
  54. package/components/layout/hologram-card/tailwind/index.tsx +61 -0
  55. package/components/layout/horizontal-scroll/horizontal-scroll.module.css +30 -0
  56. package/components/layout/horizontal-scroll/index.tsx +78 -0
  57. package/components/layout/spec-grid/index.tsx +56 -0
  58. package/components/layout/spec-grid/spec-grid.module.css +21 -0
  59. package/components/layout/tower-pricing/index.tsx +56 -0
  60. package/components/layout/tower-pricing/tower-pricing.module.css +27 -0
  61. package/components/layout/tracklist/index.tsx +45 -0
  62. package/components/layout/tracklist/tracklist.module.css +24 -0
  63. package/components/layout/void-frame/index.tsx +32 -0
  64. package/components/layout/void-frame/void-frame.module.css +38 -0
  65. package/components/navigation/brutal-nav/brutal-nav.module.css +85 -0
  66. package/components/navigation/brutal-nav/index.tsx +71 -0
  67. package/components/navigation/hexagon-menu/css/hexagon-menu.module.css +55 -0
  68. package/components/navigation/hexagon-menu/css/index.tsx +35 -0
  69. package/components/navigation/hexagon-menu/tailwind/index.tsx +53 -0
  70. package/components/navigation/progress-dots/index.tsx +55 -0
  71. package/components/navigation/progress-dots/progress-dots.module.css +91 -0
  72. package/components/navigation/scattered-nav/index.tsx +59 -0
  73. package/components/navigation/scattered-nav/scattered-nav.module.css +113 -0
  74. package/components/navigation/scroll-indicator/index.tsx +58 -0
  75. package/components/navigation/scroll-indicator/scroll-indicator.module.css +82 -0
  76. package/components/navigation/vertical-nav/index.tsx +59 -0
  77. package/components/navigation/vertical-nav/vertical-nav.module.css +98 -0
  78. package/components/neon/neon-alert/css/index.tsx +53 -0
  79. package/components/neon/neon-alert/css/neon-alert.module.css +60 -0
  80. package/components/neon/neon-alert/tailwind/index.tsx +59 -0
  81. package/components/neon/neon-badge/css/index.tsx +49 -0
  82. package/components/neon/neon-badge/css/neon-badge.module.css +53 -0
  83. package/components/neon/neon-badge/tailwind/index.tsx +50 -0
  84. package/components/neon/neon-button/css/index.tsx +54 -0
  85. package/components/neon/neon-button/css/neon-button.module.css +114 -0
  86. package/components/neon/neon-button/tailwind/index.tsx +51 -0
  87. package/components/neon/neon-divider/css/index.tsx +26 -0
  88. package/components/neon/neon-divider/css/neon-divider.module.css +43 -0
  89. package/components/neon/neon-divider/tailwind/index.tsx +36 -0
  90. package/components/neon/neon-progress/css/index.tsx +65 -0
  91. package/components/neon/neon-progress/css/neon-progress.module.css +88 -0
  92. package/components/neon/neon-progress/tailwind/index.tsx +46 -0
  93. package/components/neon/neon-tabs/css/index.tsx +41 -0
  94. package/components/neon/neon-tabs/css/neon-tabs.module.css +45 -0
  95. package/components/neon/neon-tabs/tailwind/index.tsx +53 -0
  96. package/components/neon/neon-toggle/css/index.tsx +58 -0
  97. package/components/neon/neon-toggle/css/neon-toggle.module.css +79 -0
  98. package/components/neon/neon-toggle/tailwind/index.tsx +57 -0
  99. package/components/text/ascii-art/css/ascii-art.module.css +173 -0
  100. package/components/text/ascii-art/css/index.tsx +116 -0
  101. package/components/text/ascii-art/tailwind/index.tsx +124 -0
  102. package/components/text/blood-drip/css/blood-drip.module.css +142 -0
  103. package/components/text/blood-drip/css/index.tsx +113 -0
  104. package/components/text/blood-drip/tailwind/index.tsx +133 -0
  105. package/components/text/char-glitch/css/char-glitch.module.css +124 -0
  106. package/components/text/char-glitch/css/index.tsx +153 -0
  107. package/components/text/char-glitch/tailwind/index.tsx +126 -0
  108. package/components/text/countdown-display/css/countdown-display.module.css +179 -0
  109. package/components/text/countdown-display/css/index.tsx +190 -0
  110. package/components/text/countdown-display/tailwind/index.tsx +155 -0
  111. package/components/text/giant-layers/css/giant-layers.module.css +156 -0
  112. package/components/text/giant-layers/css/index.tsx +97 -0
  113. package/components/text/giant-layers/tailwind/index.tsx +111 -0
  114. package/components/text/glitch-text/glitch-text.module.css +2 -2
  115. package/components/text/reveal-text/css/index.tsx +180 -0
  116. package/components/text/reveal-text/css/reveal-text.module.css +129 -0
  117. package/components/text/reveal-text/tailwind/index.tsx +135 -0
  118. package/components/text/rotate-text/css/index.tsx +139 -0
  119. package/components/text/rotate-text/css/rotate-text.module.css +162 -0
  120. package/components/text/rotate-text/tailwind/index.tsx +127 -0
  121. package/components/text/strike-reveal/css/index.tsx +124 -0
  122. package/components/text/strike-reveal/css/strike-reveal.module.css +139 -0
  123. package/components/text/strike-reveal/tailwind/index.tsx +138 -0
  124. package/components/text/terminal-output/css/index.tsx +179 -0
  125. package/components/text/terminal-output/css/terminal-output.module.css +203 -0
  126. package/components/text/terminal-output/tailwind/index.tsx +174 -0
  127. package/components/text/typing-text/css/index.tsx +115 -0
  128. package/components/text/typing-text/css/typing-text.module.css +84 -0
  129. package/components/text/typing-text/tailwind/index.tsx +126 -0
  130. package/package.json +1 -1
  131. package/components/glow-orbs/glow-orbs.module.css +0 -31
  132. package/components/glow-orbs/index.tsx +0 -87
  133. package/components/light-beams/index.tsx +0 -80
  134. package/components/light-beams/light-beams.module.css +0 -27
  135. package/components/noise-canvas/index.tsx +0 -113
  136. package/components/noise-canvas/noise-canvas.module.css +0 -8
  137. package/components/package.json +0 -13
  138. package/components/particle-field/index.tsx +0 -81
  139. package/components/particle-field/particle-field.module.css +0 -31
@@ -1,31 +0,0 @@
1
- .container {
2
- inset: 0;
3
- width: 100%;
4
- height: 100%;
5
- overflow: hidden;
6
- pointer-events: none;
7
- z-index: 1;
8
- }
9
-
10
- .orb {
11
- position: absolute;
12
- border-radius: 50%;
13
- opacity: 0.3;
14
- transform: translate(-50%, -50%);
15
- animation: float 20s ease-in-out infinite;
16
- }
17
-
18
- @keyframes float {
19
- 0%, 100% {
20
- transform: translate(-50%, -50%) translate(0, 0);
21
- }
22
- 25% {
23
- transform: translate(-50%, -50%) translate(30px, -40px);
24
- }
25
- 50% {
26
- transform: translate(-50%, -50%) translate(-20px, 20px);
27
- }
28
- 75% {
29
- transform: translate(-50%, -50%) translate(40px, 30px);
30
- }
31
- }
@@ -1,87 +0,0 @@
1
- 'use client';
2
-
3
- import { forwardRef, HTMLAttributes } from 'react';
4
- import styles from './glow-orbs.module.css';
5
-
6
- export interface GlowOrbsProps extends HTMLAttributes<HTMLDivElement> {
7
- /** Array of orb colors (will cycle through) */
8
- colors?: string[];
9
- /** Number of orbs */
10
- count?: number;
11
- /** Orb size range [min, max] in pixels */
12
- sizeRange?: [number, number];
13
- /** Blur amount in pixels */
14
- blur?: number;
15
- /** Animation duration range [min, max] in seconds */
16
- durationRange?: [number, number];
17
- /** Fixed or absolute positioning */
18
- position?: 'fixed' | 'absolute';
19
- }
20
-
21
- export const GlowOrbs = forwardRef<HTMLDivElement, GlowOrbsProps>(
22
- (
23
- {
24
- colors = ['#7c3aed', '#06b6d4', '#ec4899', '#10b981'],
25
- count = 5,
26
- sizeRange = [100, 300],
27
- blur = 80,
28
- durationRange = [15, 25],
29
- position = 'fixed',
30
- className,
31
- style,
32
- ...props
33
- },
34
- ref
35
- ) => {
36
- // Generate random orbs
37
- const orbs = Array.from({ length: count }, (_, i) => {
38
- const size = sizeRange[0] + Math.random() * (sizeRange[1] - sizeRange[0]);
39
- const duration = durationRange[0] + Math.random() * (durationRange[1] - durationRange[0]);
40
- const delay = Math.random() * -duration;
41
- const color = colors[i % colors.length];
42
- const startX = Math.random() * 100;
43
- const startY = Math.random() * 100;
44
-
45
- return {
46
- id: i,
47
- size,
48
- duration,
49
- delay,
50
- color,
51
- startX,
52
- startY,
53
- };
54
- });
55
-
56
- return (
57
- <div
58
- ref={ref}
59
- className={`${styles.container} ${className || ''}`}
60
- style={{ position, ...style }}
61
- aria-hidden="true"
62
- {...props}
63
- >
64
- {orbs.map((orb) => (
65
- <div
66
- key={orb.id}
67
- className={styles.orb}
68
- style={{
69
- width: orb.size,
70
- height: orb.size,
71
- background: orb.color,
72
- filter: `blur(${blur}px)`,
73
- left: `${orb.startX}%`,
74
- top: `${orb.startY}%`,
75
- animationDuration: `${orb.duration}s`,
76
- animationDelay: `${orb.delay}s`,
77
- }}
78
- />
79
- ))}
80
- </div>
81
- );
82
- }
83
- );
84
-
85
- GlowOrbs.displayName = 'GlowOrbs';
86
-
87
- export default GlowOrbs;
@@ -1,80 +0,0 @@
1
- 'use client';
2
-
3
- import { forwardRef, HTMLAttributes } from 'react';
4
- import styles from './light-beams.module.css';
5
-
6
- export interface LightBeamsProps extends HTMLAttributes<HTMLDivElement> {
7
- /** Array of beam colors */
8
- colors?: string[];
9
- /** Number of beams */
10
- count?: number;
11
- /** Beam width in pixels */
12
- beamWidth?: number;
13
- /** Beam opacity (0-1) */
14
- opacity?: number;
15
- /** Animation duration range [min, max] in seconds */
16
- durationRange?: [number, number];
17
- /** Fixed or absolute positioning */
18
- position?: 'fixed' | 'absolute';
19
- }
20
-
21
- export const LightBeams = forwardRef<HTMLDivElement, LightBeamsProps>(
22
- (
23
- {
24
- colors = ['#7c3aed', '#06b6d4', '#ec4899', '#10b981', '#f59e0b'],
25
- count = 5,
26
- beamWidth = 2,
27
- opacity = 0.15,
28
- durationRange = [15, 25],
29
- position = 'fixed',
30
- className,
31
- style,
32
- ...props
33
- },
34
- ref
35
- ) => {
36
- const beams = Array.from({ length: count }, (_, i) => {
37
- const duration = durationRange[0] + Math.random() * (durationRange[1] - durationRange[0]);
38
- const delay = Math.random() * -duration;
39
- const color = colors[i % colors.length];
40
- const positionX = ((i + 1) / (count + 1)) * 100;
41
-
42
- return {
43
- id: i,
44
- duration,
45
- delay,
46
- color,
47
- positionX,
48
- };
49
- });
50
-
51
- return (
52
- <div
53
- ref={ref}
54
- className={`${styles.container} ${className || ''}`}
55
- style={{ position, ...style }}
56
- aria-hidden="true"
57
- {...props}
58
- >
59
- {beams.map((beam) => (
60
- <div
61
- key={beam.id}
62
- className={styles.beam}
63
- style={{
64
- left: `${beam.positionX}%`,
65
- width: beamWidth,
66
- background: `linear-gradient(180deg, transparent, ${beam.color}, transparent)`,
67
- opacity,
68
- animationDuration: `${beam.duration}s`,
69
- animationDelay: `${beam.delay}s`,
70
- }}
71
- />
72
- ))}
73
- </div>
74
- );
75
- }
76
- );
77
-
78
- LightBeams.displayName = 'LightBeams';
79
-
80
- export default LightBeams;
@@ -1,27 +0,0 @@
1
- .container {
2
- inset: 0;
3
- width: 100%;
4
- height: 100%;
5
- overflow: hidden;
6
- pointer-events: none;
7
- z-index: 1;
8
- }
9
-
10
- .beam {
11
- position: absolute;
12
- top: 0;
13
- height: 100%;
14
- filter: blur(1px);
15
- animation: beam-move 20s ease-in-out infinite;
16
- }
17
-
18
- @keyframes beam-move {
19
- 0%, 100% {
20
- transform: translateX(-50px) skewX(-5deg);
21
- opacity: 0.1;
22
- }
23
- 50% {
24
- transform: translateX(50px) skewX(5deg);
25
- opacity: 0.2;
26
- }
27
- }
@@ -1,113 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect, useRef, forwardRef, HTMLAttributes } from 'react';
4
- import styles from './noise-canvas.module.css';
5
-
6
- export interface NoiseCanvasProps extends HTMLAttributes<HTMLCanvasElement> {
7
- /** Noise opacity (0-1) */
8
- opacity?: number;
9
- /** Animation speed (fps) */
10
- fps?: number;
11
- /** Noise intensity (0-255) */
12
- intensity?: number;
13
- /** Monochrome or colored noise */
14
- monochrome?: boolean;
15
- /** Fixed or absolute positioning */
16
- position?: 'fixed' | 'absolute';
17
- }
18
-
19
- export const NoiseCanvas = forwardRef<HTMLCanvasElement, NoiseCanvasProps>(
20
- (
21
- {
22
- opacity = 0.05,
23
- fps = 24,
24
- intensity = 50,
25
- monochrome = true,
26
- position = 'fixed',
27
- className,
28
- style,
29
- ...props
30
- },
31
- ref
32
- ) => {
33
- const canvasRef = useRef<HTMLCanvasElement>(null);
34
- const animationRef = useRef<number>();
35
-
36
- useEffect(() => {
37
- const canvas = canvasRef.current;
38
- if (!canvas) return;
39
-
40
- const ctx = canvas.getContext('2d');
41
- if (!ctx) return;
42
-
43
- const resize = () => {
44
- canvas.width = window.innerWidth;
45
- canvas.height = window.innerHeight;
46
- };
47
-
48
- resize();
49
- window.addEventListener('resize', resize);
50
-
51
- let lastFrame = 0;
52
- const frameInterval = 1000 / fps;
53
-
54
- const render = (timestamp: number) => {
55
- if (timestamp - lastFrame >= frameInterval) {
56
- const imageData = ctx.createImageData(canvas.width, canvas.height);
57
- const data = imageData.data;
58
-
59
- for (let i = 0; i < data.length; i += 4) {
60
- const value = Math.random() * intensity;
61
-
62
- if (monochrome) {
63
- data[i] = value;
64
- data[i + 1] = value;
65
- data[i + 2] = value;
66
- } else {
67
- data[i] = Math.random() * intensity;
68
- data[i + 1] = Math.random() * intensity;
69
- data[i + 2] = Math.random() * intensity;
70
- }
71
- data[i + 3] = 255;
72
- }
73
-
74
- ctx.putImageData(imageData, 0, 0);
75
- lastFrame = timestamp;
76
- }
77
-
78
- animationRef.current = requestAnimationFrame(render);
79
- };
80
-
81
- animationRef.current = requestAnimationFrame(render);
82
-
83
- return () => {
84
- window.removeEventListener('resize', resize);
85
- if (animationRef.current) {
86
- cancelAnimationFrame(animationRef.current);
87
- }
88
- };
89
- }, [fps, intensity, monochrome]);
90
-
91
- return (
92
- <canvas
93
- ref={(node) => {
94
- (canvasRef as React.MutableRefObject<HTMLCanvasElement | null>).current = node;
95
- if (typeof ref === 'function') ref(node);
96
- else if (ref) ref.current = node;
97
- }}
98
- className={`${styles.canvas} ${className || ''}`}
99
- style={{
100
- position,
101
- opacity,
102
- ...style,
103
- }}
104
- aria-hidden="true"
105
- {...props}
106
- />
107
- );
108
- }
109
- );
110
-
111
- NoiseCanvas.displayName = 'NoiseCanvas';
112
-
113
- export default NoiseCanvas;
@@ -1,8 +0,0 @@
1
- .canvas {
2
- inset: 0;
3
- width: 100%;
4
- height: 100%;
5
- pointer-events: none;
6
- z-index: 9999;
7
- mix-blend-mode: overlay;
8
- }
@@ -1,13 +0,0 @@
1
- {
2
- "name": "@chaos/components",
3
- "version": "0.1.0",
4
- "description": "Glitch, noise, and distortion UI components",
5
- "type": "module",
6
- "exports": {
7
- "./text/*": "./text/*/index.tsx",
8
- "./overlays/*": "./overlays/*/index.tsx",
9
- "./buttons/*": "./buttons/*/index.tsx",
10
- "./effects/*": "./effects/*/index.tsx",
11
- "./backgrounds/*": "./backgrounds/*/index.tsx"
12
- }
13
- }
@@ -1,81 +0,0 @@
1
- 'use client';
2
-
3
- import { forwardRef, HTMLAttributes, useMemo } from 'react';
4
- import styles from './particle-field.module.css';
5
-
6
- export interface ParticleFieldProps extends HTMLAttributes<HTMLDivElement> {
7
- /** Number of particles */
8
- count?: number;
9
- /** Particle color */
10
- color?: string;
11
- /** Particle size range [min, max] in pixels */
12
- sizeRange?: [number, number];
13
- /** Animation duration range [min, max] in seconds */
14
- durationRange?: [number, number];
15
- /** Particle opacity */
16
- opacity?: number;
17
- /** Fixed or absolute positioning */
18
- position?: 'fixed' | 'absolute';
19
- }
20
-
21
- export const ParticleField = forwardRef<HTMLDivElement, ParticleFieldProps>(
22
- (
23
- {
24
- count = 50,
25
- color = '#ffffff',
26
- sizeRange = [1, 3],
27
- durationRange = [10, 20],
28
- opacity = 0.5,
29
- position = 'fixed',
30
- className,
31
- style,
32
- ...props
33
- },
34
- ref
35
- ) => {
36
- const particles = useMemo(() => {
37
- return Array.from({ length: count }, (_, i) => {
38
- const size = sizeRange[0] + Math.random() * (sizeRange[1] - sizeRange[0]);
39
- const duration = durationRange[0] + Math.random() * (durationRange[1] - durationRange[0]);
40
- const delay = Math.random() * -duration;
41
- const startX = Math.random() * 100;
42
- const startY = Math.random() * 100;
43
- const drift = (Math.random() - 0.5) * 100;
44
-
45
- return { id: i, size, duration, delay, startX, startY, drift };
46
- });
47
- }, [count, sizeRange, durationRange]);
48
-
49
- return (
50
- <div
51
- ref={ref}
52
- className={`${styles.container} ${className || ''}`}
53
- style={{ position, ...style }}
54
- aria-hidden="true"
55
- {...props}
56
- >
57
- {particles.map((p) => (
58
- <div
59
- key={p.id}
60
- className={styles.particle}
61
- style={{
62
- width: p.size,
63
- height: p.size,
64
- backgroundColor: color,
65
- opacity,
66
- left: `${p.startX}%`,
67
- top: `${p.startY}%`,
68
- animationDuration: `${p.duration}s`,
69
- animationDelay: `${p.delay}s`,
70
- '--drift': `${p.drift}px`,
71
- } as React.CSSProperties}
72
- />
73
- ))}
74
- </div>
75
- );
76
- }
77
- );
78
-
79
- ParticleField.displayName = 'ParticleField';
80
-
81
- export default ParticleField;
@@ -1,31 +0,0 @@
1
- .container {
2
- inset: 0;
3
- width: 100%;
4
- height: 100%;
5
- overflow: hidden;
6
- pointer-events: none;
7
- z-index: 1;
8
- }
9
-
10
- .particle {
11
- position: absolute;
12
- border-radius: 50%;
13
- animation: drift linear infinite;
14
- }
15
-
16
- @keyframes drift {
17
- 0% {
18
- transform: translate(0, 0);
19
- opacity: 0;
20
- }
21
- 10% {
22
- opacity: var(--opacity, 0.5);
23
- }
24
- 90% {
25
- opacity: var(--opacity, 0.5);
26
- }
27
- 100% {
28
- transform: translate(var(--drift, 50px), -100vh);
29
- opacity: 0;
30
- }
31
- }