appvoid commited on
Commit
730f342
·
verified ·
1 Parent(s): 7e56327

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +24 -385
index.html CHANGED
@@ -1,387 +1,26 @@
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" />
6
- <title>Dot Labs</title>
7
- <style>
8
- * { box-sizing: border-box; }
9
- body {
10
- margin: 0;
11
- min-height: 100vh;
12
- display: grid;
13
- place-items: center;
14
- padding: 24px;
15
- background: #000;
16
- color: #f5f5f7;
17
- font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
18
- -webkit-font-smoothing: antialiased;
19
- }
20
- .card {
21
- position: relative;
22
- isolation: isolate;
23
- overflow: hidden;
24
- width: min(100%, 720px);
25
- min-height: 480px;
26
- padding: clamp(32px, 7vw, 64px);
27
- display: flex;
28
- flex-direction: column;
29
- justify-content: space-between;
30
- background: #000; /* PURE BLACK — no gradients, overlays or colored fog */
31
- border: 1px solid #1c1c1e;
32
- border-radius: 28px;
33
- }
34
- canvas.grain {
35
- position: absolute;
36
- inset: 0;
37
- width: 100%;
38
- height: 100%;
39
- z-index: 0;
40
- pointer-events: none;
41
- display: block;
42
- }
43
- .card > :not(canvas) { position: relative; z-index: 1; }
44
- .logo { font-size: 15px; font-weight: 600; letter-spacing: -0.02em; }
45
- main { max-width: 580px; }
46
- h1 {
47
- margin: 0;
48
- font-size: clamp(14px, 5vw, 28px);
49
- line-height: 0.98;
50
- font-weight: 550;
51
- letter-spacing: -0.06em;
52
- }
53
- p, a {
54
- margin: 28px 0 0;
55
- max-width: 520px;
56
- color: #8e8e93;
57
- font-size: clamp(16px, 2vw, 18px);
58
- line-height: 1.5;
59
- letter-spacing: -0.02em;
60
- }
61
- footer { color: #555; font-size: 11px; letter-spacing: 0.04em; }
62
- /* Partners: each identity is a single, non-wrapping icon + name row. */
63
- .partners {
64
- display: flex;
65
- flex-direction: column;
66
- align-items: flex-start;
67
- gap: 12px;
68
- margin: 0 0 17px;
69
- padding-top: 17px;
70
- border-top: 1px solid rgba(255,255,255,.105);
71
- }
72
- .partners-label {
73
- margin: 0;
74
- color: #68686b;
75
- font-size: 10px;
76
- font-weight: 600;
77
- letter-spacing: .16em;
78
- text-transform: uppercase;
79
- line-height: 1;
80
- }
81
- .partner-list {
82
- display: flex;
83
- flex-wrap: wrap;
84
- gap: 8px;
85
- width: 100%;
86
- }
87
- .partner-link {
88
- display: inline-flex;
89
- flex-direction: row;
90
- align-items: center;
91
- justify-content: flex-start;
92
- flex-wrap: nowrap;
93
- gap: 10px;
94
- min-width: 153px;
95
- min-height: 43px;
96
- padding: 6px 10px 6px 7px;
97
- margin: 0;
98
- background: rgba(255,255,255,.026);
99
- border: 1px solid rgba(255,255,255,.105);
100
- border-radius: 9px;
101
- color: #d7d7d9;
102
- text-decoration: none;
103
- font-size: 12px;
104
- font-weight: 550;
105
- letter-spacing: -.015em;
106
- line-height: 1;
107
- transition: border-color .2s ease, background .2s ease, color .2s ease;
108
- }
109
- .partner-link:hover,
110
- .partner-link:focus-visible {
111
- background: rgba(255,255,255,.055);
112
- border-color: rgba(255,255,255,.26);
113
- color: #fff;
114
- outline-offset: 3px;
115
- }
116
- .partner-icon {
117
- position: relative;
118
- display: grid;
119
- place-items: center;
120
- width: 29px;
121
- height: 29px;
122
- min-width: 29px;
123
- flex: 0 0 29px;
124
- overflow: hidden;
125
- background: #1a1a1c;
126
- border: 1px solid #29292d;
127
- border-radius: 6px;
128
- color: #c9c9cc;
129
- font-size: 13px;
130
- font-weight: 700;
131
- line-height: 1;
132
- letter-spacing: 0;
133
- }
134
- .partner-icon img {
135
- position: absolute;
136
- width: 100%;
137
- height: 100%;
138
- inset: 0;
139
- border-radius: inherit;
140
- object-fit: cover;
141
- }
142
- .partner-name { white-space: nowrap; }
143
- .partner-arrow {
144
- display: inline-block;
145
- margin-left: auto;
146
- color: #77777b;
147
- font-size: 14px;
148
- line-height: 1;
149
- transition: transform .2s ease, color .2s ease;
150
- }
151
- .partner-link:hover .partner-arrow { color: #cfcfd2; transform: translate(1px,-1px); }
152
- .disclaimer { color: #555; font-size: 10px; line-height: 1.6; letter-spacing: .018em; }
153
- @media (max-width: 600px) {
154
- body { padding: 14px; }
155
- .card {
156
- min-height: calc(100vh - 28px);
157
- padding: 28px 24px;
158
- border-radius: 22px;
159
- }
160
- }
161
- </style>
162
- </head>
163
- <body>
164
- <section class="card">
165
- <canvas class="grain" aria-hidden="true"></canvas>
166
- <div class="logo">D●t Labs</div>
167
- <main>
168
- <h1>Intelligence<br>from the byte up.</h1>
169
- <p>
170
- Independent AI research exploring multimodal,
171
- byte-level intelligence and simpler foundations
172
- for increasingly general models.
173
- </p>
174
- <br/>
175
- <a style="font-size: 14px" href="https://huggingface.co/spaces/dotlabs/README/discussions/1">Click here to learn on how to join!</a>
176
- </main>
177
- <footer>
178
- <div class="partners" aria-label="Partners">
179
- <div class="partners-label">Partners</div>
180
- <div class="partner-list">
181
- <a class="partner-link" href="https://huggingface.co/SurjoLabs" target="_blank" rel="noopener noreferrer" aria-label="Visit SurjoLabs on Hugging Face">
182
- <span class="partner-icon" aria-hidden="true">
183
- <span>S</span>
184
- <img src="https://huggingface.co/api/organizations/SurjoLabs/avatar?redirect=true" alt="" loading="lazy" referrerpolicy="no-referrer" onerror="this.style.display='none'">
185
- </span>
186
- <span class="partner-name">SurjoLabs</span>
187
- <span class="partner-arrow" aria-hidden="true">↗</span>
188
- </a>
189
- <a class="partner-link" href="https://huggingface.co/AxiomicLabs" target="_blank" rel="noopener noreferrer" aria-label="Visit AxiomicLabs on Hugging Face">
190
- <span class="partner-icon" aria-hidden="true">
191
- <span>B</span>
192
- <img src="https://huggingface.co/api/organizations/AxiomicLabs/avatar?redirect=true" alt="" loading="lazy" referrerpolicy="no-referrer" onerror="this.style.display='none'">
193
- </span>
194
- <span class="partner-name">AxiomicLabs</span>
195
- <span class="partner-arrow" aria-hidden="true">↗</span>
196
- </a>
197
- </div>
198
- </div>
199
- <div class="disclaimer">Dot Labs™ is not related in any way to OpenAI's Dot product nor SpaceXAI web domain.</div>
200
- </footer>
201
- </section>
202
- <script>
203
- (() => {
204
- // Feel free to tune these; everything is native Canvas, no dependencies.
205
- const SETTINGS = {
206
- style: 'drift',
207
- seed: 137,
208
- opacity: 1.0, // Grain visibility
209
- size: 1.0, // Overall dot size
210
- speed: 1.0 // Animation speed; 0 = frozen
211
- };
212
- const card = document.querySelector('.card');
213
- const canvas = document.querySelector('canvas.grain');
214
- const ctx = canvas.getContext('2d', { alpha: true });
215
- if (!ctx) return;
216
- const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
217
- const PI2 = Math.PI * 2;
218
- const gaussian = (x) => Math.exp(-x*x * .5);
219
- const clamp = (x, a=0, b=1) => Math.max(a, Math.min(b, x));
220
- const fract = x => x - Math.floor(x);
221
- let particles = [], width=0, height=0, dpr=1, frame=0, then=0, elapsed=0, active=true;
222
 
223
- function rng(seed) {
224
- return () => {
225
- let t = seed += 0x6D2B79F5;
226
- t = Math.imul(t ^ t >>> 15, t | 1);
227
- t ^= t + Math.imul(t ^ t >>> 7, t | 61);
228
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
229
- };
230
- }
 
 
231
 
232
- function concentration(x, y) {
233
- if (SETTINGS.style === 'drift') {
234
- return clamp(.28 + .34*x + .22*gaussian((x-.78)/.28)*gaussian((y-.43)/.47));
235
- }
236
- if (SETTINGS.style === 'nebula') {
237
- const cloud = gaussian((x-.72)/.23)*gaussian((y-.41-.09*Math.sin(x*7))/.21);
238
- const plume = gaussian((x-.53)/.29)*gaussian((y-.72)/.16);
239
- return clamp(.055 + .88*cloud + .34*plume);
240
- }
241
- if (SETTINGS.style === 'eclipse') {
242
- const r = Math.hypot((x-.72)/.43, (y-.48)/.60);
243
- return clamp(.045 + .88*gaussian((r-.77)/.19));
244
- }
245
- const path = .80 - .53*x + .046*Math.sin(9*x);
246
- return clamp(.07 + .89*gaussian((y-path)/.125) * (.35+.65*x));
247
- }
248
-
249
- // Larger dots progressively emerge across each pattern, without any
250
- // solid gray gradient. Only individual particles carry color.
251
- function sizeProgress(x, y) {
252
- if (SETTINGS.style === 'eclipse') {
253
- return clamp(.07 + .93*x);
254
- }
255
- if (SETTINGS.style === 'nebula') {
256
- return clamp(.06 + .78*x + .17*y);
257
- }
258
- return clamp(.04 + .96*x);
259
- }
260
-
261
- function rebuild() {
262
- const rect = card.getBoundingClientRect();
263
- width = rect.width;
264
- height = rect.height;
265
- if (!width || !height) return;
266
- dpr = Math.min(window.devicePixelRatio || 1, 2);
267
- canvas.width = Math.round(width*dpr);
268
- canvas.height = Math.round(height*dpr);
269
- ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
270
- const random = rng(SETTINGS.seed);
271
- const area = width*height;
272
- particles = [];
273
- const count = Math.floor(area / (SETTINGS.style === 'nebula' ? 13 : 15));
274
- for (let i=0; i<count; i++) {
275
- const x=random(), y=random();
276
- const c = concentration(x,y);
277
- if (random()>c) continue;
278
- const growth = sizeProgress(x,y);
279
- const isFine = random() < .76;
280
- let radius;
281
- let alpha;
282
- if (isFine) {
283
- radius=(.13 + .15*random() + .12*growth)*SETTINGS.size;
284
- alpha=(.17 + .34*random()) * (.71+.29*c);
285
- } else {
286
- // A few larger grains emerge gently, but all remain subpixel-to-1px dust.
287
- radius=(.19 + .66*Math.pow(growth,1.9)) * (.47+.53*random())*SETTINGS.size;
288
- alpha=(.18 + .42*random())*(.70+.30*c);
289
- }
290
- // Occasional slightly larger isolated grains in the denser region.
291
- if (random()<.008 && growth>.60) radius*=1.18;
292
- const shade = Math.floor(139 + random()*75);
293
- particles.push({x,y,radius,alpha,shade,phase:random()*PI2,
294
- velocity:.42+random()*1.25,depth:random(),offset:0});
295
- }
296
- // The quiet microdust layer fills dark negative space at tiny sizes.
297
- const fineCount = Math.floor(area / 21);
298
- for (let i=0; i<fineCount; i++) {
299
- const x=random(), y=random();
300
- const density = concentration(x,y);
301
- if (random() > .42+.36*density) continue;
302
- const shade=Math.floor(140+random()*73);
303
- particles.push({x,y,radius:(.12+.16*random())*SETTINGS.size,
304
- alpha:(.16+.19*random())* (.67+.33*density),
305
- shade,phase:random()*PI2,velocity:.24+random()*.75,
306
- depth:random(),offset:0});
307
- }
308
- draw(0);
309
- }
310
-
311
- function position(p, t) {
312
- const x=p.x, y=p.y;
313
- if (SETTINGS.style === 'drift') {
314
- // Low, steady breeze; different velocity at every dust depth.
315
- return [fract(x+t*(3.5+4.2*p.velocity)/width),
316
- y + 1.6*Math.sin(t*.49+p.phase)/height];
317
- }
318
- if (SETTINGS.style === 'nebula') {
319
- // A barely rotating, breathing cloud of gray points.
320
- const dx=(x-.68)*width, dy=(y-.48)*height;
321
- const theta=t*(.003+.006*p.velocity);
322
- const cos=Math.cos(theta), sin=Math.sin(theta);
323
- return [.68 + (dx*cos-dy*sin+2.1*Math.sin(t*.31+p.phase))/width,
324
- .48 + (dx*sin+dy*cos+2.0*Math.cos(t*.33+p.phase))/height];
325
- }
326
- if (SETTINGS.style === 'eclipse') {
327
- // Subtle orbital travel around the ring; no fog or glow.
328
- const dx=(x-.72)*width, dy=(y-.48)*height;
329
- const angle=t*(.009+.006*p.velocity);
330
- const rx=Math.cos(angle)*dx-Math.sin(angle)*dy*.78;
331
- const ry=Math.sin(angle)*dx/ .78+Math.cos(angle)*dy;
332
- return [.72+rx/width,.48+ry/height];
333
- }
334
- // Stream moves diagonally upward along a curved path.
335
- const nx=fract(x+t*(4.0+5.5*p.velocity)/width);
336
- const oldPath=.80-.53*x+.046*Math.sin(9*x);
337
- const newPath=.80-.53*nx+.046*Math.sin(9*nx);
338
- return [nx, newPath + (y-oldPath) + 1.8*Math.sin(t*.50+p.phase)/height];
339
- }
340
-
341
- function draw(t) {
342
- ctx.clearRect(0,0,width,height);
343
- for (const p of particles) {
344
- const [nx,ny]=position(p,t);
345
- if (nx<0 || nx>1 || ny<0 || ny>1) continue;
346
- const shimmer=.91+.09*Math.sin(t*.67+p.phase);
347
- const a=clamp(p.alpha*shimmer*SETTINGS.opacity);
348
- ctx.fillStyle=`rgba(${p.shade},${p.shade},${p.shade},${a})`;
349
- ctx.beginPath();
350
- ctx.arc(nx*width,ny*height,p.radius,0,PI2);
351
- ctx.fill();
352
- }
353
- }
354
-
355
- function stop() {
356
- cancelAnimationFrame(frame);
357
- frame=0;
358
- then=0;
359
- }
360
- function tick(now) {
361
- if (!active || reducedMotion.matches) { stop(); return; }
362
- if (then) elapsed+=Math.min((now-then)/1000,.05)*SETTINGS.speed;
363
- then=now;
364
- // Max ~25fps to keep the denser microdust field lightweight.
365
- if (!tick.drawn || now-tick.drawn>=40) {
366
- draw(elapsed);
367
- tick.drawn=now;
368
- }
369
- frame=requestAnimationFrame(tick);
370
- }
371
- function updateRunning() {
372
- stop();
373
- if (active && !reducedMotion.matches) frame=requestAnimationFrame(tick);
374
- else draw(elapsed);
375
- }
376
- document.addEventListener('visibilitychange',()=> {
377
- active=!document.hidden;
378
- updateRunning();
379
- });
380
- reducedMotion.addEventListener('change', updateRunning);
381
- new ResizeObserver(rebuild).observe(card);
382
- rebuild();
383
- updateRunning();
384
- })();
385
- </script>
386
- </body>
387
- </html>
 
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#090909"><title>Dot Labs — Split Signal Dark</title>
2
+ <style>
3
+ :root{--bg:#090909;--panel:#111214;--soft:#18191b;--ink:#f1f1ee;--muted:#949490;--line:#2b2d31}*{box-sizing:border-box}html,body{margin:0}body{background:var(--bg);color:var(--ink);font-family:Arial,Helvetica,sans-serif}a{color:inherit}
4
+ .page{min-height:100svh;padding:24px;display:flex}.frame{width:min(100%,calc(100vw - 48px));min-height:calc(100svh - 48px);margin:0 auto;border:1px solid var(--line);display:grid;grid-template-columns:minmax(320px,.92fr) minmax(0,1.08fr);background:var(--panel)}
5
+ .left{padding:22px;display:flex;flex-direction:column;border-right:1px solid var(--line)}.right{display:grid;grid-template-rows:1fr auto;min-width:0}.brand{text-decoration:none;font-size:20px;font-weight:800;letter-spacing:-.07em}.brand span{display:inline-block;width:.68em;height:.68em;border-radius:50%;background:#fff;margin:0 1px}.micro{font:10px 'Courier New',monospace;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
6
+ .title{margin:auto 0}.title h1{font-size:clamp(78px,8vw,148px);line-height:.9;letter-spacing:-.1em;margin:16px 0}.title p{font-size:24px;max-width:360px;line-height:1.2;color:#cbcbc7;margin:0 0 24px}.stack{display:grid;gap:12px}.stack a{text-decoration:none;border:1px solid #35383e;padding:12px 14px;font:11px 'Courier New',monospace;letter-spacing:.08em;text-transform:uppercase}
7
+ .field{position:relative;overflow:hidden;min-height:420px;background:var(--soft)}.field canvas{position:absolute;inset:0;width:100%;height:100%}.tag{position:absolute;z-index:2;top:18px;left:18px}.count{position:absolute;z-index:2;bottom:18px;right:18px}
8
+ .info{padding:20px 22px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:20px;align-items:flex-end;flex-wrap:wrap}.partners{display:flex;gap:18px;flex-wrap:wrap}.partners a{text-decoration:none;border-bottom:1px solid #3a3d42;padding-bottom:3px}
9
+ @media(max-width:950px){.frame{grid-template-columns:1fr}.left{border-right:0;border-bottom:1px solid var(--line)}.field{min-height:320px}}
10
+ @media(max-width:560px){.page{padding:14px}.frame{width:min(100%,calc(100vw - 28px));min-height:calc(100svh - 28px)}.left,.info{padding:18px}.title h1{font-size:clamp(72px,16vw,116px)}.title p{font-size:21px}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ /* Partner identities: real HF avatars when available; visible marks even offline. */
13
+ .partner-link{display:inline-flex!important;align-items:center;justify-content:flex-start;gap:9px;min-height:36px;text-decoration:none;white-space:nowrap;padding:2px 0 4px}
14
+ .partner-avatar{position:relative;display:grid;place-items:center;flex:0 0 32px;width:32px;height:32px;overflow:hidden;background:#25272b;border:1px solid #555960;border-radius:7px;color:#f3f3f0;font:800 16px/1 Arial,Helvetica,sans-serif;letter-spacing:0;text-transform:none}
15
+ .partner-avatar img{position:absolute;inset:0;width:100%;height:100%;display:block;object-fit:cover;background:#25272b;border-radius:6px}
16
+ .partner-fallback{position:relative;z-index:0;display:grid;place-items:center;width:100%;height:100%;text-transform:uppercase;font:800 15px/1 Arial,Helvetica,sans-serif;letter-spacing:0}
17
+ .partner-name{color:#dededb;font:600 11px/1.3 Arial,Helvetica,sans-serif;letter-spacing:-.01em;text-transform:none}
18
+ .partner-arrow{color:#a4a5a1;font:14px/1 Arial,Helvetica,sans-serif;letter-spacing:0;margin-left:1px}
19
+ .partner-link:hover .partner-avatar{border-color:#b2b4b6}
20
+ .partner-link:hover .partner-name,.partner-link:focus-visible .partner-name{color:#fff}
21
+ .partner-link:focus-visible{outline:2px solid #bbb;outline-offset:4px}
22
 
23
+ </style></head><body><div class="page"><div class="frame"><section class="left"><div style="display:flex;justify-content:space-between;gap:12px;align-items:center"><a class="brand" href="#top">D<span></span>t Labs</a><div class="micro">Study / 001</div></div><div class="title" id="top"><div class="micro">A narrower language, a wider ambition</div><h1>void.1</h1><p>Bytes dots become signal. The interface remains simple.</p><div class="stack"><a href="https://huggingface.co/dotlabs/void.1">Explore the model ↗</a><a href="https://huggingface.co/spaces/dotlabs/README/discussions/1">Join the research ↗</a></div></div><div class="micro">Dark gray and black only. No white surfaces.</div></section><section class="right"><div class="field"><canvas id="signal"></canvas><div class="micro tag">Dot wave / intentional rhythm</div><div class="micro count">BYTE FIELD / 01</div></div><div class="info"><div><div class="micro" style="margin-bottom:8px">Partners</div><div class="partners micro"><a class="partner-link" href="https://huggingface.co/SurjoLabs" target="_blank" rel="noopener noreferrer" aria-label="SurjoLabs on Hugging Face"><span class="partner-avatar" aria-hidden="true"><span class="partner-fallback">S</span><img src="https://huggingface.co/api/organizations/SurjoLabs/avatar?redirect=true" alt="" loading="lazy" referrerpolicy="no-referrer" onerror="this.hidden=true;this.style.display='none'"></span><span class="partner-name">SurjoLabs</span><span class="partner-arrow" aria-hidden="true">↗</span></a><a class="partner-link" href="https://huggingface.co/AxiomicLabs" target="_blank" rel="noopener noreferrer" aria-label="AxiomicLabs on Hugging Face"><span class="partner-avatar" aria-hidden="true"><span class="partner-fallback">A</span><img src="https://huggingface.co/api/organizations/AxiomicLabs/avatar?redirect=true" alt="" loading="lazy" referrerpolicy="no-referrer" onerror="this.hidden=true;this.style.display='none'"></span><span class="partner-name">AxiomicLabs</span><span class="partner-arrow" aria-hidden="true">↗</span></a></div></div><div class="micro">Dot Labs is unaffiliated with OpenAI's Dot product or SpaceXAI.</div></div></section></div></div>
24
+ <script>
25
+ (()=>{const c=document.getElementById('signal'),x=c.getContext('2d');if(!x)return;const reduce=matchMedia('(prefers-reduced-motion: reduce)');let W=0,H=0,dpr=1,raf=0,t0=0;function size(){const r=c.parentElement.getBoundingClientRect();W=r.width;H=r.height;dpr=Math.min(devicePixelRatio||1,2);c.width=Math.round(W*dpr);c.height=Math.round(H*dpr);x.setTransform(dpr,0,0,dpr,0,0);draw(0)}function draw(t){x.clearRect(0,0,W,H);const space=W<500?20:24;for(let yy=space/2;yy<H;yy+=space)for(let xx=space/2;xx<W;xx+=space){const nx=xx/W,ny=yy/H;const center=.68-.36*nx+.055*Math.sin(nx*8+t*.9);const dist=Math.abs(ny-center);const band=Math.exp(-Math.pow(dist/.18,2));const r=.7+band*(space*.27);x.beginPath();x.fillStyle=`rgba(240,240,236,${.08+.7*band})`;x.arc(xx,yy,r,0,Math.PI*2);x.fill();}}function tick(now){draw((now-t0)/1000);raf=requestAnimationFrame(tick)}function update(){cancelAnimationFrame(raf);if(!reduce.matches&&!document.hidden){t0=performance.now();raf=requestAnimationFrame(tick)}else draw(0)}new ResizeObserver(size).observe(c.parentElement);document.addEventListener('visibilitychange',update);reduce.addEventListener('change',update);size();update();})();
26
+ </script></body></html>