1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8" />
5<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6<title>Wavy Divider Animation</title>
7<style>
8 html, body {
9 margin: 0;
10 width: 100%;
11 height: 100%;
12 overflow: hidden;
13 background: #000;
14 }
15
16 body {
17 position: relative;
18 }
19
20 /* soft side glows visible in the reference frames */
21 body::before,
22 body::after {
23 content: "";
24 position: absolute;
25 top: 34%;
26 width: 72px;
27 height: 140px;
28 pointer-events: none;
29 filter: blur(10px);
30 opacity: .9;
31 z-index: 3;
32 }
33
34 body::before {
35 left: -18px;
36 background: radial-gradient(ellipse at left center,
37 rgba(255,255,255,.95) 0%,
38 rgba(255,255,255,.55) 22%,
39 rgba(255,255,255,.18) 45%,
40 rgba(255,255,255,0) 72%);
41 }
42
43 body::after {
44 right: -18px;
45 background: radial-gradient(ellipse at right center,
46 rgba(255,255,255,.95) 0%,
47 rgba(255,255,255,.55) 22%,
48 rgba(255,255,255,.18) 45%,
49 rgba(255,255,255,0) 72%);
50 }
51
52 svg {
53 position: absolute;
54 inset: 0;
55 width: 100%;
56 height: 100%;
57 display: block;
58 }
59
60 .fill {
61 fill: #fff;
62 }
63
64 .edge {
65 fill: none;
66 stroke: rgba(255,255,255,.55);
67 stroke-width: 2.2;
68 stroke-linecap: round;
69 filter: blur(.6px);
70 }
71</style>
72</head>
73<body>
74<svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
75 <path id="waveFill" class="fill"></path>
76 <path id="waveEdge" class="edge"></path>
77</svg>
78
79<script>
80(() => {
81 const fill = document.getElementById('waveFill');
82 const edge = document.getElementById('waveEdge');
83
84 // Baseline sits around the upper third, matching the frames.
85 const baseY = 39;
86 const points = 220;
87 const duration = 4200; // smooth looping drift
88 const speed = 0.00115;
89
90 // Layered sine waves tuned for a gentle liquid surface.
91 const waves = [
92 { amp: 1.55, freq: 1.55, phase: 0.0, vel: 1.00 },
93 { amp: 0.95, freq: 3.10, phase: 1.2, vel: -0.72 },
94 { amp: 0.45, freq: 5.40, phase: 2.4, vel: 0.48 }
95 ];
96
97 function yAt(x, t) {
98 let y = baseY;
99 for (const w of waves) {
100 y += w.amp * Math.sin((x / 100) * Math.PI * 2 * w.freq + w.phase + t * w.vel);
101 }
102 return y;
103 }
104
105 function render(ms) {
106 const t = ms * speed;
107 let d = `M 0 ${yAt(0, t).toFixed(3)}`;
108 let e = `M 0 ${yAt(0, t).toFixed(3)}`;
109
110 for (let i = 1; i <= points; i++) {
111 const x = (i / points) * 100;
112 const y = yAt(x, t);
113 d += ` L ${x.toFixed(3)} ${y.toFixed(3)}`;
114 e += ` L ${x.toFixed(3)} ${y.toFixed(3)}`;
115 }
116
117 d += ` L 100 100 L 0 100 Z`;
118
119 fill.setAttribute('d', d);
120 edge.setAttribute('d', e);
121
122 requestAnimationFrame(render);
123 }
124
125 requestAnimationFrame(render);
126})();
127</script>
128</body>
129</html>