react-swarm-rebuild 0.0.0-stage → 0.3.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nguyễn Quốc Cường
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE.md ADDED
@@ -0,0 +1,12 @@
1
+ # Attribution and implementation provenance
2
+
3
+ Author of this package: Nguyễn Quốc Cường.
4
+
5
+ The visual concept was inspired by Swarm by Joel Califa
6
+ (https://califa.github.io/swarm/) and the Swarm Cursors Chrome extension
7
+ by Dhvanil Patel (https://github.com/DhvanilPatel/swarm-cursors).
8
+
9
+ This package is an independent implementation. No upstream animation engine,
10
+ cursor artwork, audio, or extension source is distributed in this package.
11
+ The upstream projects are not covered by this package's MIT license.
12
+ This package is not affiliated with or endorsed by those authors.
package/README.md CHANGED
@@ -1,3 +1,293 @@
1
- # Temporary Holding Version
1
+ # react-swarm-rebuild
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A swarm of colorful cursors reconstructs your React UI. React 18 / 19, TypeScript, ESM and CommonJS. MIT, Nguyễn Quốc Cường.
4
+
5
+ ## Quick start
6
+
7
+ ```tsx
8
+ import { useRef } from 'react';
9
+ import { SwarmRebuild } from 'react-swarm-rebuild';
10
+
11
+ export function Dashboard({ loading, children }) {
12
+ const content = useRef<HTMLDivElement>(null);
13
+ return <>
14
+ <div ref={content}>{children}</div>
15
+ <SwarmRebuild target={content} ready={!loading} />
16
+ </>;
17
+ }
18
+ ```
19
+
20
+ By default, cursors fade into a buoyant orbit, wait for your content, then reconstruct it with colored typing carets and parallel workers. Workers waiting for another task move toward upcoming work areas and float there instead of gathering around the user's mouse. After the last task, they fan radially out of the covered area and the real UI is revealed. There is no default toolbar or visible skip button. Click/tap anywhere inside the effect, or press **Esc**, to skip immediately.
21
+
22
+ Rulers and red alignment/measurement guides are **off by default**. Component targets only cover their own visible area; the surrounding header, sidebar and controls remain available.
23
+
24
+ ## Loading and the transition into reconstruction
25
+
26
+ 1. The overlay covers the target immediately. Cursors fade in while your original React tree stays mounted and loads underneath.
27
+ 2. `ready={false}` keeps the cursors orbiting. Set it to `true` after your data and fonts have settled; this does not restart the orbit.
28
+ 3. Once ready and the minimum intro has elapsed, the library measures the DOM cooperatively across animation frames. The cursors keep floating during this work.
29
+ 4. A short handoff slows the orbit. Workers depart with staggered timing and retain their departure velocity instead of snapping to a new trajectory.
30
+ 5. Boxes/media are drawn and text is typed. Idle workers gently drift near their previous position while waiting for their next assignment.
31
+ 6. All cursors leave directly from their current positions in a radial burst. They do not regroup at the center. The cover fades back to the live UI and is removed.
32
+
33
+ `snapshotBudget` controls the approximate measurement budget per frame. Smaller budgets leave more time for cursor movement but take more frames to prepare the snapshot. A single DOM/media operation may exceed that budget. It is a scheduling budget, not a guaranteed frame-time limit.
34
+
35
+ For an application entrance with no initial content flash, start the imperative controller in `useLayoutEffect`, after the DOM has mounted and before the first browser paint:
36
+
37
+ ```tsx
38
+ import { useLayoutEffect, useRef } from 'react';
39
+ import { createSwarmRebuild } from 'react-swarm-rebuild';
40
+ import type { SwarmController } from 'react-swarm-rebuild';
41
+
42
+ export function Overview({ ready, children }) {
43
+ const target = useRef<HTMLDivElement>(null);
44
+ const controller = useRef<SwarmController | null>(null);
45
+
46
+ useLayoutEffect(() => {
47
+ const swarm = createSwarmRebuild({ target, ready: false });
48
+ controller.current = swarm;
49
+ swarm.start();
50
+ return () => {
51
+ swarm.destroy();
52
+ controller.current = null;
53
+ };
54
+ }, []);
55
+
56
+ useLayoutEffect(() => {
57
+ let cancelled = false;
58
+ controller.current?.setReady(false);
59
+ if (!ready) return;
60
+ Promise.resolve(document.fonts?.ready).then(() => {
61
+ if (!cancelled) controller.current?.setReady(true);
62
+ });
63
+ return () => { cancelled = true; };
64
+ }, [ready]);
65
+
66
+ return <div ref={target}>{children}</div>;
67
+ }
68
+ ```
69
+
70
+ The declarative `SwarmRebuild` component uses `useEffect` for server-rendering compatibility. The opaque cover is installed synchronously by `start()`. `fadeIn` fades the cursors/decorations over that cover, so the real page does not flash through while it loads.
71
+
72
+ ## Motion options
73
+
74
+ All of these work as React props or imperative/hook options. The visual enhancements default to **on**; the two measuring aids default to **off**.
75
+
76
+ | Option | Default | Behavior |
77
+ | --- | --- | --- |
78
+ | `showRulers` | `false` | Horizontal and vertical rulers along the covered area |
79
+ | `showGuides` | `false` | Red alignment guides and red duplicate-distance measurements |
80
+ | `clickToSkip` | `true` | Click/tap the covered area to reveal the UI immediately |
81
+ | `floatingIntro` | `true` | Slowly rotating orbit with independent bobbing and breathing motion |
82
+ | `floatingIdle` | `true` | Idle workers drift near their last position or next queued task; `false` restores mouse-following flock behavior |
83
+ | `floatAmplitude` | `1` | Intro/idle movement amplitude multiplier, 0.25–3; defaults to stronger, wider oscillations |
84
+ | `floatSpeed` | `1` | Intro/idle movement speed multiplier, 0.25–3; defaults to faster independent oscillations |
85
+ | `parallelDrawing` | `true` | Start child/duplicate tasks while their backing surfaces are underway; `false` waits for complete ancestors |
86
+ | `smoothTransition` | `true` | Soft orbit-to-work handoff and staggered departures |
87
+ | `transitionDuration` | `480` | Handoff duration, real milliseconds, 0–3,000 |
88
+ | `fadeIn` | `true` | Fade in cursors, the intro symbol and optional controls |
89
+ | `fadeInDuration` | `360` | Entrance duration, real milliseconds, 0–3,000 |
90
+ | `typing` | `true` | Reveal text by grapheme and use each worker's colored I-beam cursor |
91
+ | `typingSpeed` | `45` | Graphemes per animation second, 5–300, multiplied by `speed` |
92
+ | `burstOnComplete` | `true` | Radial cursor exit before automatically going live |
93
+ | `exitDuration` | `700` | Radial exit duration, real milliseconds, 0–3,000 |
94
+ | `snapshotBudget` | `4` | Approximate DOM measurement budget per frame, milliseconds, 1–12 |
95
+
96
+ Typing carets use measured glyph positions and move to the next line as text wraps. Where `Intl.Segmenter` is available, combining marks, Vietnamese accents and emoji sequences are typed as complete graphemes. Other browsers fall back to Unicode code points. Text keeps its original font size throughout; there are no stepped heading-size changes. Individual text-task durations are clamped to 0.35–8 animation seconds to keep unusually long nodes bounded. With `typing={false}`, text fades into place with an arrow cursor.
97
+
98
+ Colorful selection outlines around boxes/media are independent of rulers and red guides. They remain part of the reconstruction when `showRulers` and `showGuides` are off.
99
+
100
+ A full configuration, showing the defaults explicitly:
101
+
102
+ ```tsx
103
+ <SwarmRebuild
104
+ target={content}
105
+ ready={!loading}
106
+ showRulers={false}
107
+ showGuides={false}
108
+ clickToSkip
109
+ floatingIntro
110
+ floatingIdle
111
+ smoothTransition
112
+ transitionDuration={480}
113
+ fadeIn
114
+ fadeInDuration={360}
115
+ typing
116
+ typingSpeed={45}
117
+ burstOnComplete
118
+ exitDuration={700}
119
+ snapshotBudget={4}
120
+ />
121
+ ```
122
+
123
+ Disable enhancements independently, or turn the measuring aids back on:
124
+
125
+ ```ts
126
+ const swarm = createSwarmRebuild({
127
+ target: '#overview',
128
+ showRulers: true,
129
+ showGuides: true,
130
+ floatingIntro: false, // Uniform orbit.
131
+ floatingIdle: false, // Follow the user's mouse while idle.
132
+ smoothTransition: false, // Skip the handoff and staggered delays.
133
+ fadeIn: false, // Cursors appear immediately.
134
+ typing: false, // Fade complete text instead of typing.
135
+ burstOnComplete: false, // Remove the overlay immediately on completion.
136
+ clickToSkip: false, // Esc and imperative goLive() still work.
137
+ });
138
+ ```
139
+
140
+ A component-scoped burst is clipped at the component's boundary. Cursors never fly across its header/sidebar or block other components. Explicit `finishBehavior: 'flock'` keeps the workers floating after completion and bypasses the automatic burst/removal; click/tap or `goLive()` ends that mode.
141
+
142
+ ## Concurrent work and cursor count
143
+
144
+ `cursorCount` sets the worker-pool size, independently of playback `speed`. It is available on `SwarmRebuild`, `useSwarmRebuild`, and `createSwarmRebuild`. The default is 16; values are constrained to whole numbers from 2 to 48.
145
+
146
+ ```tsx
147
+ <SwarmRebuild
148
+ target={content}
149
+ ready={!loading}
150
+ cursorCount={24}
151
+ parallelDrawing
152
+ floatAmplitude={1.2}
153
+ floatSpeed={1.15}
154
+ />
155
+ ```
156
+
157
+ ```ts
158
+ const swarm = createSwarmRebuild({ target: '#overview', cursorCount: 24 });
159
+ swarm.start();
160
+ swarm.setCursorCount(32); // Add workers without restarting the overlay.
161
+ swarm.setCursorCount(8); // Free workers leave; busy excess workers finish first.
162
+ ```
163
+
164
+ Changing the React `cursorCount` prop also resizes the existing pool. Growing the pool fades in the new workers. Shrinking it preserves any drawings already in flight, so the actual `state.agents` count can temporarily exceed the requested count until those workers finish. Changes during the radial exit apply to the next run.
165
+
166
+ The scheduler preserves DOM stacking order while allowing more work to overlap. With `parallelDrawing: true`, a child becomes eligible after its backing surface reaches 15% draw progress; duplicate tasks become eligible after their source reaches 35%. Text and media still remain hidden until their own cursor reaches them and starts drawing. Set `parallelDrawing: false` to restore strict parent/source completion ordering.
167
+
168
+ The number actually drawing at once depends on available tasks and their dependencies. Workers with no eligible task stage near distinct upcoming tasks, with wider, faster, independently phased floating motion. They do not paint fake content while waiting. `floatAmplitude` and `floatSpeed` tune the waiting motion independently of reconstruction playback speed.
169
+
170
+ In the Lexor Admin integration, **Theme → Concurrent cursors** chooses 2–48 workers (default 24), saves the value in `localStorage`, and updates the running effect without restarting it. No account or server setting is changed.
171
+
172
+ ## Other options
173
+
174
+ | Option | Default | Purpose |
175
+ | --- | --- | --- |
176
+ | `target` | `document.body` | Selector, HTMLElement or React ref |
177
+ | `scope` | `target` for components, `viewport` for body | Component clipping or full-viewport effect |
178
+ | `ready` | `true` | Wait for application content before measuring |
179
+ | `finishBehavior` | `live` | Burst and remove automatically, or keep `flock` |
180
+ | `controls` | `false` | `true` for a full playback toolbar; `minimal` for status only, without a skip button |
181
+ | `cursorCount` | `16` | 2–48 concurrent workers; can change during a run |
182
+ | `speed` | `1` | Reconstruction/typing multiplier, 0.25–8 |
183
+ | `introDuration` | `1600` | Minimum orbit time in animation milliseconds; also waits for `ready` |
184
+ | `sound` | `false` | Optional synthesized audio, subject to browser audio policy |
185
+ | `tour` | `false` | Auto-scroll the document in viewport mode |
186
+ | `showNames` | `false` | Optional collaborator names |
187
+ | `names`, `colors` | Built-in palette | Custom nonempty arrays |
188
+ | `maxLayers` | `2500` | Snapshot limit, 1–10,000 |
189
+ | `background` | Nearest opaque ancestor | Cover background color |
190
+ | `zIndex` | `2147483000` | Overlay stacking order |
191
+ | `respectReducedMotion` | `true` | Skip all motion when the user requests reduced motion |
192
+ | `active` | `true` | React component only: start/stop when this changes |
193
+
194
+ Entrance, handoff, floating motion and radial exit use real time. `speed` affects reconstruction, typing and the minimum intro clock; it does not make the buoyant drift or radial exit abruptly faster.
195
+
196
+ `ready`, `cursorCount`, `speed`, `sound`, and `tour` update an existing React instance. Other options apply to the next start/replay. Use one active instance per target.
197
+
198
+ ## Scope, skipping and cleanup
199
+
200
+ A component target is intersected with its viewport and scrolling/clipping ancestors. The cover intercepts clicks only inside that area. Header/sidebar clicks outside it keep their normal behavior and do not skip the effect. Clicking the cover removes it on the click event, so the same click cannot activate a covered application link/button.
201
+
202
+ With `clickToSkip`, the covered area is also keyboard-focusable and supports **Enter**/**Space**. **Esc** always closes the effect. There is no focus trap for component-scoped effects. Full-toolbar buttons still perform their own actions rather than triggering click-to-skip.
203
+
204
+ Offscreen content is omitted from component snapshots, so an inner scrolling container cannot prevent completion. Scrolling, changing the viewport width, removing the target, or changing scoped geometry during reconstruction reveals the live UI or disposes the run. This avoids stale geometry. The next start captures the new layout.
205
+
206
+ `stop()`, `goLive()`, `destroy()`, React unmount and `active={false}` cancel measurement and animation, including an in-progress handoff or radial exit. Reduced motion skips directly to the live UI without creating an overlay.
207
+
208
+ ## Controller and callbacks
209
+
210
+ ```ts
211
+ const swarm = createSwarmRebuild({ target: '#overview', ready: false });
212
+ swarm.start();
213
+ // Render/load data in parallel, then:
214
+ swarm.setReady(true);
215
+ // On navigation:
216
+ swarm.destroy();
217
+ ```
218
+
219
+ `useSwarmRebuild(options)` exposes the same controller plus reactive `state`. Methods: `start`, `replay`, `stop`, `goLive`, `pause`, `resume`, `setReady`, `setCursorCount`, `setSpeed`, `setSound`, `setTour`, `getState`, `destroy`. A destroyed imperative instance cannot be restarted. The React hook handles Strict Mode and unmount cleanup.
220
+
221
+ Callbacks:
222
+
223
+ - `onStateChange(state)`: phase/progress updates, limited to roughly seven per second during animation, plus phase transitions.
224
+ - `onComplete()`: called once when all captured layers have been reconstructed, **before** the radial exit. Also called when reduced motion skips reconstruction.
225
+ - `onError(error)`: target or snapshot errors. The overlay is removed on snapshot failure.
226
+
227
+ State fields: `phase`, `progress`, `completed`, `total`, `agents`, `speed`, `sound`, `tour`. Phases: `idle`, `scanning`, `intro`, `transition`, `building`, `paused`, `complete`, `exiting`, `live`.
228
+
229
+ Watch `phase === 'live'` to know that the automatic exit has finished and the overlay is gone. A skipped run does not call `onComplete()`. `pause()` freezes the animation, including a handoff or exit; `resume()` continues it.
230
+
231
+ ## Install and develop
232
+
233
+ ```sh
234
+ npm install react-swarm-rebuild
235
+ # Or install the local release:
236
+ npm install /path/to/react-swarm-rebuild-0.3.0.tgz
237
+
238
+ npm install
239
+ npm run typecheck
240
+ npm run build
241
+ npm run test:browser # Chrome required; set CHROME_PATH if needed.
242
+ npm pack
243
+ ```
244
+
245
+ Use Node 20+ for development with current Playwright versions. The bundled library supports Node 18+ for server imports and needs no CSS import or runtime dependency beyond its React peers. It is safe to import/render on the server. Browsers need Shadow DOM, DOM Range, requestAnimationFrame and CSS clip-path.
246
+
247
+ Snapshots preserve measured text, common boxes, gradients, controls, images, SVGs and readable 2D canvases. They are visual reconstructions rather than screenshots: complex transforms, pseudo-elements, custom elements, protected canvases, cross-origin iframes and unavailable media may differ. Lazy content must already be loaded. Geometry is measured across frames while the real application continues running; settle dynamic data/fonts before releasing `ready`. Add `data-swarm-ignore` to exclude a subtree.
248
+
249
+ ## Publish to npm
250
+
251
+ Use the Node version selected by `.nvmrc` when publishing. Run these commands from this repository:
252
+
253
+ ```sh
254
+ nvm use
255
+ node --version
256
+ npm --version
257
+ npm login --auth-type=web --registry=https://registry.npmjs.org/
258
+ npm whoami --registry=https://registry.npmjs.org/
259
+ npm publish --access public --registry=https://registry.npmjs.org/
260
+ ```
261
+
262
+ Complete the browser login and any two-factor authentication prompts. Continue to publish only after `npm whoami` returns your npm username. If Node 24 is not installed, run `nvm install` first.
263
+
264
+ If publication reports `E404` even though packaging succeeded, check authentication with `npm whoami`. An `E401` response means the current credentials are not accepted; log in again with the current CLI. Update an outdated CLI and renew the login before retrying. A failed upload alone does not require a new package version or name.
265
+
266
+ Publishing requires account 2FA or a granular token with the appropriate publishing permissions and bypass-2FA setting. See the [npm publishing authentication requirements](https://docs.npmjs.com/requiring-2fa-for-package-publishing-and-settings-modification/). Never put tokens in this repository or paste them into chat.
267
+
268
+ ## 0.3.0
269
+
270
+ - Fix SVG/media descendants escaping hidden snapshot layers before their own drawing starts.
271
+ - Preserve CSS `rotate`, `scale` and 2D/3D `transform` groups during reconstruction so tilted/scaled elements and their text are drawn and typed in place without snapping at completion.
272
+ - Merge inline formatting flows (`<strong>`, `<em>`, `<a>`, `<br>`, adjacent JSX text nodes), gradient-clipped text (`background-clip: text`), ellipsis clipping and form field values into cohesive typing tasks.
273
+ - Curved cursor flight paths with velocity banking, diagonal 2D surface reveal, human typing cadence, and randomized scatter trajectories on completion.
274
+ - Resize the cursor pool during a run with `setCursorCount` or the React prop.
275
+ - Parallelize work across partially drawn surfaces and stage waiting cursors near upcoming tasks.
276
+ - Stronger, faster floating motion with `floatAmplitude` and `floatSpeed` controls.
277
+ - Lexor Admin adds a local-only concurrent cursor count in Theme.
278
+
279
+ ## 0.2.0
280
+
281
+ - Rulers/red guides are opt-in; toolbar is hidden by default.
282
+ - Click/tap the effect to skip, without a visible skip button or click-through.
283
+ - Buoyant intro and local idle drift; smooth, staggered handoff with cooperative snapshots.
284
+ - Grapheme-aware typewriter text and colored carets that follow actual line geometry.
285
+ - Fade-in entrance and radial cursor exit, with independent options and durations.
286
+
287
+ ## 0.1.1
288
+
289
+ - Component-scoped overlays preserve surrounding layout and interactions.
290
+ - Orbit before snapshot; readiness can change while data renders in parallel.
291
+ - Automatic cleanup on completion, including inner scrolling containers.
292
+
293
+ Inspired by Swarm by Joel Califa and Swarm Cursors by Dhvanil Patel. This is an independent implementation; no upstream code or artwork is bundled. See [NOTICE.md](./NOTICE.md).
@@ -0,0 +1,9 @@
1
+ /** Small, original Web Audio instrument. No audio files or network requests. */
2
+ export declare class SwarmAudio {
3
+ private context?;
4
+ private enabled;
5
+ private last;
6
+ setEnabled(enabled: boolean): void;
7
+ play(kind: 'type' | 'draw' | 'complete', x?: number): void;
8
+ destroy(): void;
9
+ }
@@ -0,0 +1,9 @@
1
+ /** Small, original Web Audio instrument. No audio files or network requests. */
2
+ export declare class SwarmAudio {
3
+ private context?;
4
+ private enabled;
5
+ private last;
6
+ setEnabled(enabled: boolean): void;
7
+ play(kind: 'type' | 'draw' | 'complete', x?: number): void;
8
+ destroy(): void;
9
+ }
@@ -0,0 +1,3 @@
1
+ /** Intersect a component with its viewport and any scrolling/clipping ancestors. */
2
+ export declare function visibleBounds(target: HTMLElement): DOMRect;
3
+ export declare function backgroundColor(target: HTMLElement): string;
@@ -0,0 +1,3 @@
1
+ /** Intersect a component with its viewport and any scrolling/clipping ancestors. */
2
+ export declare function visibleBounds(target: HTMLElement): DOMRect;
3
+ export declare function backgroundColor(target: HTMLElement): string;
@@ -0,0 +1,4 @@
1
+ import type { SwarmController, SwarmOptions, SwarmState } from './types.cjs';
2
+ export declare const initialState: (options?: SwarmOptions) => SwarmState;
3
+ /** Create an imperative instance. Safe to import during SSR; call in the browser. */
4
+ export declare function createSwarmRebuild(options?: SwarmOptions): SwarmController;
@@ -0,0 +1,4 @@
1
+ import type { SwarmController, SwarmOptions, SwarmState } from './types.js';
2
+ export declare const initialState: (options?: SwarmOptions) => SwarmState;
3
+ /** Create an imperative instance. Safe to import during SSR; call in the browser. */
4
+ export declare function createSwarmRebuild(options?: SwarmOptions): SwarmController;
package/dist/index.cjs ADDED
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ "use strict";var jt=Object.defineProperty;var Me=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Se=Object.prototype.hasOwnProperty;var we=(o,n)=>{for(var l in n)jt(o,l,{get:n[l],enumerable:!0})},Te=(o,n,l,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let c of Ee(n))!Se.call(o,c)&&c!==l&&jt(o,c,{get:()=>n[c],enumerable:!(a=Me(n,c))||a.enumerable});return o};var Ce=o=>Te(jt({},"__esModule",{value:!0}),o);var Ie={};we(Ie,{SwarmRebuild:()=>De,createSwarmRebuild:()=>Wt,useSwarmRebuild:()=>pe});module.exports=Ce(Ie);var U=require("react");var zt=class{constructor(){this.enabled=!1;this.last=0}setEnabled(n){if(this.enabled=n,n)try{this.context??(this.context=new AudioContext),this.context.resume().catch(()=>{})}catch{}}play(n,l=.5){let a=this.context;if(!this.enabled||!a||a.state!=="running"||a.currentTime-this.last<.035)return;this.last=a.currentTime;let c=a.createOscillator(),R=a.createGain(),b=a.createStereoPanner(),P=a.currentTime;c.type=n==="type"?"triangle":"sine";let E=[164.81,185,207.65,246.94,277.18,329.63,369.99],k=n==="type"?650+Math.random()*800:E[Math.floor(Math.max(0,Math.min(.999,l))*E.length)];c.frequency.setValueAtTime(k,P),c.frequency.exponentialRampToValueAtTime(n==="type"?180:k,P+.04);let st=n==="complete"?.8:n==="type"?.035:.18;R.gain.setValueAtTime(1e-4,P),R.gain.exponentialRampToValueAtTime(n==="type"?.018:.035,P+.004),R.gain.exponentialRampToValueAtTime(1e-4,P+st),b.pan.value=Math.max(-1,Math.min(1,l*2-1)),c.connect(R).connect(b).connect(a.destination),c.start(),c.stop(P+st+.01)}destroy(){this.context&&this.context.close().catch(()=>{}),this.context=void 0}};function Jt(o){let n=o.getBoundingClientRect(),l=Math.max(0,n.left),a=Math.max(0,n.top),c=Math.min(window.innerWidth,n.right),R=Math.min(window.innerHeight,n.bottom);for(let b=o.parentElement;b;b=b.parentElement){let P=getComputedStyle(b),E=b.getBoundingClientRect();/^(hidden|clip|auto|scroll)$/.test(P.overflowX)&&(l=Math.max(l,E.left+b.clientLeft),c=Math.min(c,E.left+b.clientLeft+b.clientWidth)),/^(hidden|clip|auto|scroll)$/.test(P.overflowY)&&(a=Math.max(a,E.top+b.clientTop),R=Math.min(R,E.top+b.clientTop+b.clientHeight))}return new DOMRect(l,a,Math.max(0,c-l),Math.max(0,R-a))}function te(o){for(let n=o;n;n=n.parentElement){let l=getComputedStyle(n).backgroundColor;if(l&&l!=="transparent"&&l!=="rgba(0, 0, 0, 0)")return l}return"#ffffff"}var j=(o,n,l)=>Math.max(n,Math.min(l,o));function Z(o,n,l,a){return Number.isFinite(o)?j(o,l,a):n}function _t(o,n,l,a){let c=(n+(l-o)*20*a)*Math.exp(-7*a);return{position:o+c*a,velocity:c}}var Qt=["#f56551","#8b5cf6","#25a9ed","#31bd8c","#e35b9d","#e9a52a","#526cf5","#19b8bc"],ee=["C\u01B0\u1EDDng","Linh","Alex","Maya","Kai","An","Sam","Minh","Jules","Quinn","Rin","Noah"];function ne(o){return`<svg class="pointer" width="26" height="29" viewBox="0 0 26 29" fill="none"><path d="M3 2.5L7.4 23.5L12.2 16.5L20.8 15.9L3 2.5Z" fill="${o.replace(/[^#\w(),.%\s-]/g,"")}" stroke="white" stroke-width="1.75" stroke-linejoin="round"/></svg><svg class="cross" width="22" height="22" viewBox="0 0 22 22"><path d="M11 1V21M1 11H21" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><circle cx="11" cy="11" r="2.2" fill="#fff" stroke="currentColor" stroke-width="1.4"/></svg><svg class="ibeam" width="12" height="24" viewBox="0 0 12 24" preserveAspectRatio="none" aria-hidden="true"><path d="M3 1H9M6 1V23M3 23H9" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg><span class="pen">\u2712</span>`}var oe=`
3
+ :host{all:initial;color-scheme:light;font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#fff}
4
+ .toolbar,.help,.worker{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
5
+ *,*::before,*::after{box-sizing:border-box}button{font:inherit;cursor:pointer}
6
+ .cover{position:fixed;inset:0;overflow:hidden;pointer-events:auto;isolation:isolate}
7
+ .stage{position:absolute;inset:0;pointer-events:none;transform-origin:0 0}
8
+ .workers{position:fixed;inset:0;pointer-events:none;overflow:hidden}
9
+ .worker{position:absolute;left:0;top:0;will-change:transform,opacity;color:var(--color);filter:drop-shadow(0 2px 4px #0000002e)}
10
+ .worker .pointer{display:block;transform-origin:4px 3.5px;transform:translate(-3px,-2.5px)}
11
+ .worker .cross,.worker .ibeam,.worker .pen{display:none;position:absolute;left:-11px;top:-11px}
12
+ .worker[data-tool=cross] .pointer,.worker[data-tool=type] .pointer,.worker[data-tool=pen] .pointer{display:none}
13
+ .worker[data-tool=cross] .cross,.worker[data-tool=type] .ibeam,.worker[data-tool=pen] .pen{display:block}
14
+ .worker .ibeam{left:-6px;top:0;width:12px;height:var(--caret-height,24px);color:var(--color);transform-origin:6px 0;transform:rotate(var(--caret-angle,0deg));filter:drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 4px var(--color))}
15
+ .pen{font:22px/1 serif;transform-origin:2px 20px}
16
+ .worker[data-tool=duplicate]::before{content:'\u2325';position:absolute;left:-11px;top:-15px;font:600 10px/1.2 ui-monospace,monospace;background:#fff;color:var(--color);border:1px solid var(--color);border-radius:3px;padding:0 3px;box-shadow:0 1px 3px #0002}
17
+ .name{display:block;position:absolute;left:13px;top:19px;background:var(--color);border:1px solid #fff6;border-radius:4px;padding:1.5px 6px;color:#fff;font-size:10px;font-weight:500;white-space:nowrap;opacity:.95;box-shadow:0 2px 6px #0002}
18
+ .selection{position:absolute;pointer-events:none;border:1.25px solid var(--color);min-width:1px;min-height:1px;box-shadow:0 0 0 1px #ffffff55;border-radius:1px}
19
+ .selection::before,.selection::after{content:'';position:absolute;width:6px;height:6px;background:#fff;border:1.5px solid var(--color);border-radius:1.5px;box-shadow:0 1px 2px #0002}
20
+ .selection::before{left:-3.5px;top:-3.5px}.selection::after{right:-3.5px;bottom:-3.5px}
21
+ .badge{position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);font:600 10px/1.35 ui-monospace,monospace;font-variant-numeric:tabular-nums;padding:2px 6px;background:var(--color);color:white;border-radius:4px;white-space:nowrap;box-shadow:0 2px 6px #00000029}
22
+ .guide{position:fixed;top:var(--swarm-top,20px);height:var(--swarm-height,100vh);border-left:1px solid #f16a56;opacity:.65;pointer-events:none}
23
+ .measure{position:absolute;top:-19px;left:0;right:0;border-bottom:1px solid #f16a56;color:#f16a56;text-align:center;font:10px/1.5 monospace}
24
+ .ruler-x{position:fixed;left:var(--swarm-left,20px);width:var(--swarm-width,100vw);top:var(--swarm-top,0px);height:20px;background:repeating-linear-gradient(90deg,#aaa5 0px,#aaa5 1px,transparent 1px,transparent 10px),#fafafae8;border-bottom:1px solid #ddd8;color:#999;font:9px/18px monospace;pointer-events:none}
25
+ .ruler-y{position:fixed;left:var(--swarm-left,0px);top:var(--swarm-top,20px);height:var(--swarm-height,100vh);width:20px;background:repeating-linear-gradient(0deg,#aaa5 0px,#aaa5 1px,transparent 1px,transparent 10px),#fafafae8;border-right:1px solid #ddd8;pointer-events:none}
26
+ .toolbar{pointer-events:auto;position:fixed;bottom:var(--swarm-bottom,24px);left:var(--swarm-center-x,50%);transform:translateX(-50%);display:flex;align-items:center;gap:7px;padding:8px 10px;background:#25292eef;color:#f8fafc;border:1px solid #ffffff28;border-radius:14px;box-shadow:0 12px 40px #0003,0 0 0 5px #ffffff80;backdrop-filter:blur(16px);white-space:nowrap;max-width:calc(var(--swarm-width,100vw) - 24px);z-index:5;font-size:11px}
27
+ .toolbar button{background:none;color:#dce1e9;border:0;border-radius:6px;padding:6px 8px;min-height:30px;white-space:nowrap}
28
+ .toolbar button:hover,.toolbar button[aria-pressed=true]{background:#ffffff18;color:#fff}
29
+ .toolbar button:focus-visible{outline:2px solid #7dcfff;outline-offset:2px}
30
+ .toolbar .live{background:#e4f5c8;color:#24351c;font-weight:650}
31
+ .status{min-width:115px;color:#c4cbd5;font-variant-numeric:tabular-nums}.track{width:54px;height:3px;background:#ffffff24;border-radius:9px;overflow:hidden}.fill{height:100%;background:#b8ee8a;width:0;transition:width .2s}
32
+ .avatars{display:flex;padding-left:5px}.avatar{width:16px;height:16px;border:2px solid #30343a;border-radius:50%;margin-left:-5px}
33
+ .divider{height:16px;width:1px;background:#ffffff20}.intro{position:fixed;left:var(--swarm-center-x,50%);top:var(--swarm-center-y,46%);transform:translate(-50%,-50%);width:48px;height:48px;display:grid;place-items:center;background:#25292e;color:#e4f5c8;border-radius:14px;font-size:26px;box-shadow:0 6px 24px #00000024,0 0 0 6px #25292e14;transition:opacity .3s,transform .3s}
34
+ .help{position:fixed;bottom:calc(var(--swarm-bottom,24px) + 64px);left:var(--swarm-center-x,50%);transform:translateX(-50%);color:#687078;font-size:11px;pointer-events:none;background:#ffffffc9;padding:5px 12px;border-radius:20px}
35
+ .toolbar.minimal{gap:12px;box-shadow:0 6px 24px #0002;max-width:calc(var(--swarm-width,100vw) - 24px)}
36
+ .toolbar.minimal .status{min-width:0}
37
+ @media(max-width:600px){.toolbar{gap:2px;bottom:var(--swarm-bottom,14px);padding:6px}.toolbar button{padding:6px}.avatars,.track,.divider{display:none}.status{min-width:90px;font-size:10px}.name{font-size:9px}.help{bottom:calc(var(--swarm-bottom,14px) + 60px)}}
38
+ `;var Le=["background","background-image","background-size","background-position","background-repeat","background-origin","background-clip","-webkit-background-clip","border-top","border-right","border-bottom","border-left","border-radius","box-shadow","opacity","filter","backdrop-filter","-webkit-backdrop-filter","mix-blend-mode","outline","outline-offset","clip-path"],Pe=["font-family","font-size","font-weight","font-style","font-stretch","font-variant","font-variant-ligatures","font-variant-caps","font-variant-numeric","font-variant-east-asian","font-variant-position","font-feature-settings","font-variation-settings","font-kerning","font-optical-sizing","font-synthesis","font-size-adjust","text-rendering","-webkit-font-smoothing","color","letter-spacing","word-spacing","text-transform","text-shadow","-webkit-text-fill-color","-webkit-text-stroke-width","-webkit-text-stroke-color","paint-order","direction","unicode-bidi"],$e=["text-decoration-line","text-decoration-color","text-decoration-style","text-decoration-thickness","text-underline-offset","text-underline-position"],Zt=o=>o==="transparent"||o==="rgba(0, 0, 0, 0)"||!o,He=new Set(["SCRIPT","STYLE","NOSCRIPT","TEMPLATE","HEAD","LINK","META","OPTION"]),re=new Set(["IMG","SVG","VIDEO","CANVAS","IFRAME","INPUT","TEXTAREA","SELECT","PICTURE","OBJECT","EMBED"]),Re=new Set(["","text","search","email","url","tel","number","password","button","submit","reset"]),ie=typeof Intl<"u"?Intl.Segmenter:void 0,ae;function se(o){return ie?(ae??(ae=new ie(void 0,{granularity:"grapheme"}))).segment(o):Ae(o)}function*Ae(o){let n=0;for(let l of o)yield{segment:l,index:n},n+=l.length}function de(o,n){if(!(n instanceof HTMLElement||n instanceof SVGElement))return;let l=getComputedStyle(o);for(let a of l)n.style.setProperty(a,l.getPropertyValue(a));n.style.animation="none",n.style.transition="none",n.removeAttribute("id");for(let a of Array.from(n.attributes))(/^on/i.test(a.name)||["autofocus","autoplay","srcdoc"].includes(a.name))&&n.removeAttribute(a.name);Array.from(o.children).forEach((a,c)=>{n.children[c]&&de(a,n.children[c])})}var at=(o,n)=>Math.abs(o-n)<1e-4;function le(o){let n=o.getPropertyValue("rotate"),l=o.getPropertyValue("scale");if(n&&n!=="none"&&!/^(0|0deg|0rad|0turn|0grad)$/.test(n.trim())||l&&l!=="none"&&l.trim().split(/\s+/).some(c=>parseFloat(c)!==1))return!0;let a=o.transform;if(!a||a==="none")return!1;try{let c=new DOMMatrixReadOnly(a);return!at(c.a,1)||!at(c.b,0)||!at(c.c,0)||!at(c.d,1)?!0:!c.is2D&&(!at(c.m13,0)||!at(c.m23,0)||!at(c.m31,0)||!at(c.m32,0)||!at(c.m33,1)||!at(c.m14,0)||!at(c.m24,0)||!at(c.m34,0))}catch{return!1}}function ce(o){let n=["top","right","bottom","left"].some(c=>parseFloat(o.getPropertyValue(`border-${c}-width`))>0&&o.getPropertyValue(`border-${c}-style`)!=="none");return!(o.getPropertyValue("-webkit-background-clip")==="text"||o.getPropertyValue("background-clip")==="text")&&(!Zt(o.backgroundColor)||o.backgroundImage!=="none")||n||o.boxShadow!=="none"}function Xe(o,n){let l=o.style,a=n?["transform","rotate","scale","translate","animation"]:["transform","rotate","scale","translate"],c={transform:"translate(0px)",rotate:"none",scale:"none",translate:"none",animation:"none"},R=[...a,"transition"].map(b=>[b,l.getPropertyValue(b),l.getPropertyPriority(b)]);l.setProperty("transition","none","important");for(let b of a)l.setProperty(b,c[b],"important");return()=>{let b=([E,k,st])=>{l.getPropertyPriority(E)==="important"&&(k?l.setProperty(E,k,st):l.removeProperty(E))};R.filter(([E])=>E!=="transition").forEach(E=>{l.getPropertyValue(E[0]).replace(/\s/g,"")===c[E[0]].replace(/\s/g,"")&&b(E)}),getComputedStyle(o).transform;let P=R.find(([E])=>E==="transition");l.getPropertyValue("transition")==="none"&&b(P)}}function*ue(o,n,l,a){let c=[],R=new Map,b=window.scrollX,P=window.scrollY,k=getComputedStyle(o).backgroundColor;Zt(k)&&(k=getComputedStyle(document.documentElement).backgroundColor),Zt(k)&&(k="#ffffff");let st=0,$=0,lt={id:st++,node:n,ox:0,oy:0,angle:0,frame:void 0};lt.frame=lt;let ht=new Map,yt=new Map,_,$t=(r,p)=>!p||r.bottom>p.top&&r.top<p.bottom&&r.right>p.left&&r.left<p.right,Ht=(r,p)=>`inset(${Math.max(0,p.top-r.top)}px ${Math.max(0,r.right-p.right)}px ${Math.max(0,r.bottom-p.bottom)}px ${Math.max(0,p.left-r.left)}px)`,ot=(r,p,h)=>{let d=r.matrix;if(!d)return{x:p,y:h};let x=p-r.ox,S=h-r.oy;return{x:d.a*x+d.c*S+d.e,y:d.b*x+d.d*S+d.f}},Rt=r=>{let p=n.getBoundingClientRect(),h=[[0,0],[100,0],[0,100]].map(([m,z])=>{let T=document.createElement("i");T.style.cssText=`position:absolute;left:${m}px;top:${z}px;width:0;height:0;`,r.node.append(T);let G=T.getBoundingClientRect();return T.remove(),{x:G.left-p.left,y:G.top-p.top}}),[d,x,S]=h;r.matrix={a:(x.x-d.x)/100,b:(x.y-d.y)/100,c:(S.x-d.x)/100,d:(S.y-d.y)/100,e:d.x,f:d.y},r.angle=Math.atan2(r.matrix.b,r.matrix.a)*180/Math.PI},At=(r,p,h,d,x)=>{r.node.append(p);let S={id:st++,node:p,ox:h,oy:d,angle:r.angle,frame:r.frame};return x&&(S.frame=S),(x||r.matrix)&&Rt(S),S},gt=(r,p,h,d,x,S="")=>{let m=document.createElement("div");m.dataset.swarmKind=r;let z=p.left+b,T=p.top+P;m.style.cssText=`position:absolute;left:${z-d.ox}px;top:${T-d.oy}px;width:${p.width}px;height:${p.height}px;visibility:hidden;opacity:0;pointer-events:none;box-sizing:border-box;`,m.append(h),d.node.append(m);let G=ot(d,z+p.width/2,T+p.height/2),A={id:c.length,kind:r,x:z,y:T,width:p.width,height:p.height,cx:G.x,cy:G.y,element:m,container:d,parent:x,signature:S,done:!1,started:!1,progress:0,opacity:h.style.opacity};if(r==="box"&&S){let F=`${d.id}|${S}`;A.master=R.get(F),A.master||R.set(F,A)}return c.push(A),A},Ft=r=>{if(ht.has(r))return ht.get(r);let p=null;for(let h=r,d=0;h&&d<12;h=h.parentElement,d++){let x=getComputedStyle(h);if(x.textDecorationLine&&x.textDecorationLine!=="none"){p=x;break}if(h===o||/^inline-|^table/.test(x.display)||x.float!=="none"||x.position==="absolute"||x.position==="fixed")break}return ht.set(r,p),p},St=r=>{if(yt.has(r))return yt.get(r);let p=null;for(let h=r,d=0;h&&d<6;h=h.parentElement,d++){let x=getComputedStyle(h);if(x.getPropertyValue("-webkit-background-clip")==="text"||x.getPropertyValue("background-clip")==="text"){p=h;break}if(h===o)break}return yt.set(r,p),p},wt=(r,p,h,d)=>{for(let S of Pe)r.style.setProperty(S,h.getPropertyValue(S));let x=Ft(p);if(x)for(let S of $e)r.style.setProperty(S,x.getPropertyValue(S));r.style.opacity=String(d)},ut=(r,p,h,d)=>{let x=St(p);if(!x)return;let S=getComputedStyle(x),m=x.getBoundingClientRect();r.style.backgroundImage=S.backgroundImage,r.style.backgroundColor=S.backgroundColor,r.style.backgroundRepeat=S.backgroundRepeat,r.style.backgroundSize=/px/.test(S.backgroundSize)&&!/auto|%|cover|contain/.test(S.backgroundSize)?S.backgroundSize:`${m.width}px ${m.height}px`,r.style.backgroundPosition=`${m.left-h}px ${m.top-d}px`,r.style.setProperty("-webkit-background-clip","text"),r.style.setProperty("background-clip","text"),r.style.setProperty("-webkit-text-fill-color",S.getPropertyValue("-webkit-text-fill-color")||"transparent")},tt=r=>{if(!r.runs.length||c.length>=l)return;let p={left:r.left,top:r.top,width:r.right-r.left,height:r.bottom-r.top};r.visual.style.cssText=`position:absolute;left:${r.originX-r.left}px;top:${r.originY-r.top}px;`;let h=gt("text",p,r.visual,r.container,r.owner);h.text=r.runs,r.clip&&(h.element.style.clipPath=Ht(r,r.clip))};function*Xt(r,p,h,d,x,S=!1){let m=document.createRange();m.selectNodeContents(r);let z=m.getBoundingClientRect();if(!z.width||!z.height||!$t(z,x.clip)||x.ellipsis?.done)return;let T=x.current;T||(T=x.current={visual:document.createElement("div"),runs:[],left:1/0,top:1/0,right:-1/0,bottom:-1/0,originX:z.left,originY:z.top,owner:x.owner,clip:x.clip,container:x.container,opacity:d});let G=h.direction==="rtl",A=h.textAlign==="justify",F=/^pre|break-spaces/.test(h.whiteSpace),g=(r.textContent??"").slice(0,12e3),C=S?T.runs[T.runs.length-1]:void 0,mt=-1/0,J=NaN,V=!1,y=0,M=x.ellipsis;for(let{segment:X,index:O}of se(g)){$===0&&y++%24===0&&(yield),m.setStart(r,O),m.setEnd(r,O+X.length);let w=m.getBoundingClientRect(),ct=/^\s+$/.test(X),Q=!F&&ct&&X.length===1&&X!==" "?" ":X;if(!w.width&&ct){if(S)continue;let W=C?.units[C.units.length-1];C&&W&&(C.value+=Q,C.units.push({...W,end:C.value.length}),V=!0);continue}if(!w.width&&!w.height)continue;if(M&&!G&&w.right>M.limit+.5){if(M.done=!0,C){let W=C.units[C.units.length-1];C.value+="\u2026",C.units.push({end:C.value.length,startX:W.x,x:W.x+M.width,y:W.y,height:W.height})}break}let bt=G?w.right:w.left,Dt=!S&&(Math.abs(w.top-mt)>2||(G?bt>J+2:bt<J-2));if(!C||Dt||A&&V&&!ct){let W=document.createElement("span");wt(W,p,h,d);let Tt=w.left-T.originX,It=w.top-T.originY;W.style.cssText+=G?`;position:absolute;right:${T.originX-w.right}px;top:${It}px;white-space:pre;line-height:${w.height}px;`:`;position:absolute;left:${Tt}px;top:${It}px;white-space:pre;line-height:${w.height}px;`,ut(W,p,w.left,w.top),T.visual.append(W),C={node:W,value:"",opacity:String(d),units:[]},T.runs.push(C),V=!1}C.value+=Q,C.units.push({end:C.value.length,startX:(G?w.right:w.left)+b,x:(G?w.left:w.right)+b,y:w.top+P,height:w.height}),ct&&(V=!0),T.left=Math.min(T.left,w.left),T.top=Math.min(T.top,w.top),T.right=Math.max(T.right,w.right),T.bottom=Math.max(T.bottom,w.bottom),mt=w.top,J=bt}}let v=(r,p,h,d,x)=>{if(c.length>=l)return;let S=r instanceof HTMLInputElement;if(S&&!Re.has(r.type))return;let m=S&&r.type==="password"&&r.value?"\u2022".repeat(Math.min(12,[...r.value].length)):r.value,z=m?"value":"placeholder",T=(m||r.placeholder||"").slice(0,2e3);if(!T.trim())return;p.value="",p.placeholder="",_??(_=document.createElement("canvas").getContext("2d"));let G=`${h.fontStyle} ${h.fontWeight} ${h.fontSize} ${h.fontFamily}`;_&&(_.font=G);let A=parseFloat(h.letterSpacing)||0,F=Q=>parseFloat(h.getPropertyValue(Q))||0,g=d.left+F("border-left-width")+F("padding-left"),C=d.right-F("border-right-width")-F("padding-right"),mt=F("font-size")||14,J=parseFloat(h.lineHeight)||mt*1.25,V=Q=>(_?_.measureText(Q).width:Q.length*mt*.55)+[...Q].length*A,y=S?[T]:T.split(`
39
+ `),M=h.textAlign,X=[],O=0;if(y.forEach((Q,bt)=>{let Dt=V(Q),W=C-g,Tt=M==="center"||S&&/button|submit|reset/.test(r.type)&&M!=="left"&&M!=="start"?g+Math.max(0,W-Dt)/2:M==="right"||M==="end"?g+Math.max(0,W-Dt):g,It=S?d.top+(d.height-J)/2:d.top+F("border-top-width")+F("padding-top")+bt*J,Ct="";for(let{segment:Gt}of se(Q)){let qt=Math.min(C,Tt+V(Ct));Ct+=Gt,X.push({end:O+Ct.length,startX:qt+b,x:Math.min(C,Tt+V(Ct))+b,y:Math.max(d.top,It)+P,height:Math.min(J,d.height)})}O+=Q.length+1,bt<y.length-1&&X.length&&(X[X.length-1]={...X[X.length-1],end:O})}),!X.length)return;let w=document.createElement("div"),ct=gt("text",d,w,x.container,x);ct.element.style.visibility="hidden",ct.text=[{node:w,value:T,opacity:"1",units:X,write:Q=>{p[z]=Q}}]};function*pt(r,p,h,d,x,S){if($===0&&(yield),c.length>=l||He.has(r.tagName.toUpperCase())||r.hasAttribute("data-swarm-ignore")||r.hasAttribute("data-swarm-overlay"))return;let m=getComputedStyle(r);if(m.display==="none"||m.visibility==="hidden"||m.getPropertyValue("content-visibility")==="hidden"||(h*=Number(m.opacity),h<.01))return;let z=r.tagName.toUpperCase(),T=r instanceof HTMLElement||r instanceof SVGElement,G=!S&&T&&le(m),A=G?{transform:m.transform,rotate:m.getPropertyValue("rotate"),scale:m.getPropertyValue("scale"),translate:m.getPropertyValue("translate"),origin:m.transformOrigin}:void 0,F=G?($++,Xe(r,!!(m.animationName&&m.animationName!=="none"))):void 0;try{let g=r.getBoundingClientRect();if(g.top+P>4e4||g.bottom+P<0)return;if(A&&g.width>0&&g.height>0){let y=x;if(d){let w=document.createElement("div");w.style.cssText=`position:absolute;left:${d.left+b-y.ox}px;top:${d.top+P-y.oy}px;width:${d.width}px;height:${d.height}px;overflow:hidden;pointer-events:none;`,y=At(y,w,d.left+b,d.top+P,!1),d=void 0}let M=document.createElement("div"),X=g.left+b,O=g.top+P;M.style.cssText=`position:absolute;left:${X-y.ox}px;top:${O-y.oy}px;width:${g.width}px;height:${g.height}px;pointer-events:none;transform-origin:${A.origin};`,M.style.transform=A.transform==="none"?"":A.transform,A.translate&&A.translate!=="none"&&M.style.setProperty("translate",A.translate),A.rotate&&A.rotate!=="none"&&M.style.setProperty("rotate",A.rotate),A.scale&&A.scale!=="none"&&M.style.setProperty("scale",A.scale),M.dataset.swarmGroup="",x=At(y,M,X,O,!0)}let C=p,mt=y=>{d&&(y.element.style.clipPath=Ht(g,d))};if(g.width>0&&g.height>0&&$t(g,d)){if(re.has(z)){let y=document.createElement("div");y.style.cssText="width:100%;height:100%;overflow:hidden;";let M;if(r instanceof HTMLCanvasElement){let O=document.createElement("canvas");O.width=r.width,O.height=r.height;try{O.getContext("2d")?.drawImage(r,0,0)}catch{}M=O}else if(r instanceof HTMLVideoElement){let O=document.createElement("canvas");O.width=Math.max(1,r.videoWidth),O.height=Math.max(1,r.videoHeight);try{O.getContext("2d")?.drawImage(r,0,0)}catch{}if(r.poster&&r.readyState<2){let w=document.createElement("img");w.src=r.poster,M=w}else M=O}else r instanceof HTMLIFrameElement||z==="OBJECT"||z==="EMBED"?(M=document.createElement("div"),M.textContent="Embedded content"):M=r.cloneNode(!0);de(r,M),(M instanceof HTMLElement||M instanceof SVGElement)&&(M.style.cssText+=";position:relative!important;inset:auto!important;margin:0!important;transform:none!important;rotate:none!important;scale:none!important;translate:none!important;width:100%!important;height:100%!important;box-sizing:border-box!important;",r instanceof HTMLInputElement&&M instanceof HTMLInputElement&&(M.value=r.type==="password"?"\u2022\u2022\u2022\u2022\u2022\u2022":r.value,M.name="",M.disabled=!0),r instanceof HTMLTextAreaElement&&M instanceof HTMLTextAreaElement&&(M.value=r.value),r instanceof HTMLSelectElement&&M instanceof HTMLSelectElement&&(M.selectedIndex=r.selectedIndex)),y.append(M);let X=gt("media",g,y,x,p);mt(X),(r instanceof HTMLInputElement&&M instanceof HTMLInputElement||r instanceof HTMLTextAreaElement&&M instanceof HTMLTextAreaElement)&&v(r,M,m,g,X);return}if(ce(m)){let y=document.createElement("div");y.style.cssText="width:100%;height:100%;box-sizing:border-box;";for(let X of Le)y.style.setProperty(X,m.getPropertyValue(X));y.style.opacity=String(h);let M=`${Math.round(g.width)}:${Math.round(g.height)}:${m.background}:${m.border}:${m.borderRadius}`;C=gt(g.height<=3||g.width<=3?"line":"box",g,y,x,p,M),mt(C)}}let J=S||!["hidden","clip","auto","scroll"].some(y=>m.overflowX===y||m.overflowY===y)||r===document.body||r===document.documentElement?d:d?new DOMRect(Math.max(d.left,g.left),Math.max(d.top,g.top),Math.max(0,Math.min(d.right,g.right)-Math.max(d.left,g.left)),Math.max(0,Math.min(d.bottom,g.bottom)-Math.max(d.top,g.top))):g,V=S;if(!V){let y={owner:C,clip:J,container:x,flush:()=>{y.current&&tt(y.current),y.current=void 0}};if(m.textOverflow==="ellipsis"&&m.overflowX!=="visible"&&r instanceof HTMLElement&&r.scrollWidth>r.clientWidth+1){_??(_=document.createElement("canvas").getContext("2d")),_&&(_.font=`${m.fontStyle} ${m.fontWeight} ${m.fontSize} ${m.fontFamily}`);let M=_?_.measureText("\u2026").width:parseFloat(m.fontSize)*.8;y.ellipsis={limit:g.right-(parseFloat(m.borderRightWidth)||0)-(parseFloat(m.paddingRight)||0)-M,width:M,done:!1}}V=y}for(let y of Array.from(r.childNodes)){if(c.length>=l)break;if(y.nodeType===Node.ELEMENT_NODE){let X=y,O=X.tagName.toUpperCase(),w=getComputedStyle(X);(w.display==="inline"||w.display==="contents")&&!re.has(O)&&!ce(w)&&!le(w)?yield*pt(X,C,h,J,x,V):(V.flush(),yield*pt(X,C,h,J,x));continue}if(y.nodeType!==Node.TEXT_NODE||!y.textContent)continue;if(!y.textContent.trim()){V.current?.runs.length&&(yield*Xt(y,r,m,h,V,!0));continue}yield*Xt(y,r,m,h,V,!1)}if(r.shadowRoot){V.flush();for(let y of Array.from(r.shadowRoot.children))yield*pt(y,C,h,J,x)}S||V.flush()}finally{F&&($--,F())}}return yield*pt(o,void 0,1,a,lt),{layers:c,background:k}}function Vt(o,n,l){let a=o.container.matrix;if(!a)return{x:n,y:l};let c=n-o.container.ox,R=l-o.container.oy;return{x:a.a*c+a.c*R+a.e,y:a.b*c+a.d*R+a.f}}var ft=o=>{let n=j(o,0,1);return n*n*(3-2*n)},Ot=(o={})=>({phase:"idle",completed:0,total:0,progress:0,agents:0,speed:Z(o.speed,1,.25,8),sound:o.sound??!1,tour:o.tour??!1});function Wt(o={}){let n=Ot(o),l,a,c,R,b,P,E,k,st,$=[],lt=[],ht=0,yt=0,_=0,$t=0,Ht=!1,ot=!1,Rt=null,At="building",gt={x:0,y:0},Ft=[],St=0,wt=0,ut,tt=!1,Xt=o.ready!==!1,v,pt,r=!1,p,h=0,d=0,x=0,S=0,m=Math.floor(Z(o.cursorCount,16,2,48)),z=0,T=new zt,G=()=>({...n}),A=()=>{l&&(l.dataset.swarmPhase=n.phase),mt(),o.onStateChange?.(G())},F=(t,i,e,s)=>{t.addEventListener(i,e,s),Ft.push(()=>t.removeEventListener(i,e,s))},g=(t,i,e)=>{let s=document.createElement(t);return s.className=i,e?.appendChild(s),s};function C(t){n.phase=t,A()}function mt(){if(!a)return;E&&(E.textContent=n.phase==="scanning"?"Scanning page\u2026":n.phase==="intro"?Xt?"Gathering the swarm\u2026":"Preparing content\u2026":n.phase==="transition"?"Preparing the canvas\u2026":n.phase==="exiting"?"Ready.":n.phase==="complete"?"Built.":`${n.completed} / ${n.total} layers`),k&&(k.style.width=`${n.progress*100}%`);let t=(i,e,s)=>{let D=a.querySelector(`[data-action="${i}"]`);D&&(D.textContent=e,s!==void 0&&D.setAttribute("aria-pressed",String(s)))};t("speed",`${n.speed}\xD7`),t("sound",n.sound?"\u266A On":"\u266A Off",n.sound),t("tour","Tour",n.tour),t("pause",n.phase==="paused"?"Resume":"Pause",n.phase==="paused"),st&&(st.textContent=n.phase==="complete"?"Move your mouse \xB7 Go live to use the page":"Scroll to build more \xB7 Esc to exit")}function J(){let t=!!a?.activeElement;ot=!1,p?.return(void 0),p=void 0,ht&&window.cancelAnimationFrame(ht),ht=0,Ft.splice(0).forEach(i=>i()),l?.remove(),l=void 0,a=void 0,$=[],lt=[],T.setEnabled(!1),t&&Rt?.isConnected&&Rt.focus({preventScroll:!0}),Rt=null}function V(){J(),n.agents=0,C("idle")}function y(){J(),n.agents=0,C("live")}function M(){!ot||n.phase==="paused"||n.phase==="scanning"||(At=n.phase,C("paused"))}function X(){n.phase==="paused"&&(yt=performance.now(),C(At))}function O(t){n.speed=Z(t,n.speed,.25,8),A()}function w(t){n.sound=t,T.setEnabled(t&&ot),A()}function ct(t){n.tour=t,A()}function Q(t){if(Xt=t,!t&&p){p.return(void 0),p=void 0,pt=void 0;for(let i of Array.from(R.children))i.classList.contains("selection")||i.remove()}}function bt(){if(!o.controls)return;let t=o.controls==="minimal",i=g("div",t?"toolbar minimal":"toolbar",a);if(i.setAttribute("role","toolbar"),i.setAttribute("aria-label","Swarm rebuild controls"),t){i.style.pointerEvents="none",E=g("span","status",i),E.setAttribute("role","status");return}let e=g("div","avatars",i);Qt.slice(0,5).forEach(u=>{let f=g("span","avatar",e);f.style.background=u}),E=g("span","status",i),E.setAttribute("role","status"),E.setAttribute("aria-live","polite");let s=g("div","track",i);k=g("div","fill",s),g("div","divider",i),[["pause","Pause / resume animation",()=>n.phase==="paused"?X():M()],["tour","Toggle automatic scrolling",()=>ct(!n.tour)],["speed","Change playback speed",()=>O(n.speed>=3?1:Math.floor(n.speed)+1)],["sound","Toggle sound",()=>w(!n.sound)],["replay","Replay animation",W],["live","Go live",y],["close","Close animation",V]].forEach(([u,f,Y])=>{let L=g("button",u==="live"?"live":"",i);L.type="button",L.dataset.action=u,L.setAttribute("aria-label",f),L.title=f,L.textContent={replay:"Replay",live:"Go live",close:"\xD7"}[u]??u,F(L,"click",Y)}),st=g("div","help",a)}function Dt(){let t=o.target,i=typeof t=="string"?document.querySelector(t):t&&"current"in t?t.current:t??document.body;if(!(i instanceof HTMLElement)||!i.isConnected)throw new Error("Swarm target must be a connected HTMLElement. Check your selector or ref.");return i}function W(){if(Ht)return;if(typeof window>"u"||typeof document>"u")throw new Error("Start Swarm Rebuild in a browser effect or event handler.");J();try{ut=Dt()}catch(i){if(C("idle"),o.onError?.(i),!o.onError)throw i;return}if(n={...n,phase:"scanning",completed:0,total:0,progress:0,agents:0},o.respectReducedMotion!==!1&&window.matchMedia("(prefers-reduced-motion: reduce)").matches){n.progress=1,C("live"),o.onComplete?.();return}tt=o.scope==="target"||o.scope!=="viewport"&&ut!==document.body&&ut!==document.documentElement,St=window.innerWidth,wt=window.innerHeight,v=tt?Jt(ut):new DOMRect(0,0,St,wt),pt=void 0,r=!1,p=void 0,h=0,d=0,x=0,S=0,gt={x:v.left+v.width/2,y:v.top+v.height*.46},Rt=document.activeElement instanceof HTMLElement?document.activeElement:null,l=document.createElement("div"),l.setAttribute("data-swarm-overlay",""),l.style.cssText=`all:initial;position:fixed;inset:0;display:block;z-index:${Z(o.zIndex,2147483e3,0,2147483647)};isolation:isolate;`,l.style.pointerEvents="none",l.dataset.swarmScope=tt?"target":"viewport",a=l.attachShadow({mode:"open"});let t=document.createElement("style");t.textContent=oe,a.append(t),c=g("div","cover",a),c.style.background=o.background??te(ut),R=g("div","stage",c),R.inert=!0,R.setAttribute("aria-hidden","true"),b=g("div","workers",a),b.setAttribute("aria-hidden","true"),P=g("div","intro",a),P.textContent="\u2197",P.setAttribute("aria-hidden","true"),bt(),document.documentElement.append(l),Tt(),ot=!0,_=0,yt=performance.now(),$t=0,F(window,"pointermove",(i=>{gt={x:i.clientX,y:i.clientY}}),{passive:!0}),F(window,"keydown",(i=>{if(i.key==="Escape"&&(i.preventDefault(),V()),(!tt||a?.activeElement)&&i.key.toLowerCase()==="m"&&!i.ctrlKey&&!i.metaKey&&!i.altKey&&w(!n.sound),i.key==="Tab"&&a&&!tt){let e=Array.from(a.querySelectorAll("button"));if(!e.length)return;let s=e.indexOf(a.activeElement);i.preventDefault(),e[(s+(i.shiftKey?-1:1)+e.length)%e.length].focus()}})),o.clickToSkip!==!1&&(c.style.cursor="pointer",c.tabIndex=0,c.setAttribute("role","button"),c.setAttribute("aria-label","Skip animation"),F(c,"click",i=>{i.preventDefault(),i.stopPropagation(),y()}),F(c,"keydown",(i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),i.stopPropagation(),y())}))),F(window,"resize",()=>{Math.abs(window.innerWidth-St)>2?tt?y():W():wt=window.innerHeight},{passive:!0}),T.setEnabled(n.sound),A(),tt&&F(document,"scroll",()=>{(r||p)&&y()},{capture:!0,passive:!0}),me(),C("intro"),ht=window.requestAnimationFrame(kt)}function Tt(){l&&(v=tt?Jt(ut):new DOMRect(0,0,window.innerWidth,window.innerHeight),tt&&(l.style.clipPath=`inset(${v.top}px ${Math.max(0,window.innerWidth-v.right)}px ${Math.max(0,window.innerHeight-v.bottom)}px ${v.left}px)`,l.style.setProperty("--swarm-left",`${v.left}px`),l.style.setProperty("--swarm-top",`${v.top}px`),l.style.setProperty("--swarm-width",`${v.width}px`),l.style.setProperty("--swarm-height",`${v.height}px`),l.style.setProperty("--swarm-center-x",`${v.left+v.width/2}px`),l.style.setProperty("--swarm-center-y",`${v.top+v.height*.46}px`),l.style.setProperty("--swarm-bottom",`${window.innerHeight-v.bottom+16}px`)))}function It(){p||(pt=v,p=ue(ut,R,Z(o.maxLayers,2500,1,1e4),tt?v:void 0));let t=performance.now()+Z(o.snapshotBudget,4,1,12);try{do{let i=p.next();if(i.done){lt=i.value.layers,n.total=lt.length,r=!0,p=void 0,$.forEach(e=>{R.append(e.selection),e.fromX=e.x,e.fromY=e.y,e.idleX=e.x,e.idleY=e.y,e.idleTime=0,e.delay=o.smoothTransition===!1?0:e.index*.022}),o.showGuides===!0&&[...new Set(lt.filter(s=>s.kind==="text").map(s=>Math.round(s.x)))].slice(0,5).forEach(s=>{let D=g("div","guide",a);D.style.left=`${s-window.scrollX}px`}),P.style.transition=o.smoothTransition===!1?"none":"",x=0,C(o.smoothTransition===!1?"building":"transition");return}}while(performance.now()<t)}catch(i){V(),o.onError?.(i),o.onError||console.error("[react-swarm-rebuild]",i)}}function Ct(t,i){let e=o.colors?.length?o.colors:Qt,s=o.names?.length?o.names:ee,D=e[t%e.length],u=g("div","worker",b);if(u.style.setProperty("--color",D),u.innerHTML=ne(D),o.showNames===!0){let rt=g("span","name",u);rt.textContent=s[t%s.length]}let f=g("div","selection",R);f.style.setProperty("--color",D),f.hidden=!0;let Y=g("span","badge",f),L=t/i*Math.PI*2,et=.72+t%3*.18,I=v.left+v.width/2+Math.cos(L)*Math.min(105,v.width*.26)*et,H=v.top+v.height*.46+Math.sin(L)*Math.min(74,v.height*.21)*et;return u.style.transform=`translate3d(${I}px,${H}px,0)`,u.dataset.motion="orbit",{node:u,selection:f,badge:Y,index:t,color:D,x:I,y:H,angle:0,scale:1,vx:0,vy:0,fromX:I,fromY:H,fromVx:0,fromVy:0,travel:.36,curve:0,idleX:I,idleY:H,idleTime:0,delay:0,exitX:I,exitY:H,exitCurveX:0,exitCurveY:0,exitAngle:0,elapsed:0,duration:1,retiring:!1,bornAt:-1/0}}function Gt(t){if(Ht||(m=Math.floor(Z(t,m,2,48)),!ot||n.phase==="exiting"||n.phase==="paused"&&At==="exiting"))return;for($.forEach(e=>{e.retiring=!1});$.length>m;){let e=[...$].reverse().find(s=>!s.task);if(!e)break;e.node.remove(),e.selection.remove(),$=$.filter(s=>s!==e)}let i=Math.max(0,$.length-m);for(i>0&&$.slice(-i).forEach(e=>{e.retiring=!0,e.pending=void 0});$.length<m;){let e=Ct(z++,m);e.bornAt=h,e.node.style.opacity="0",$.push(e)}n.agents=$.length,A()}function qt(){let t=$.length;$=$.filter(i=>!i.retiring||i.task?!0:(i.node.remove(),i.selection.remove(),!1)),t!==$.length&&(n.agents=$.length,A())}function me(){if(z=0,$=Array.from({length:m},()=>Ct(z++,m)),n.agents=$.length,o.showRulers===!0){let e=g("div","ruler-x",a);e.textContent="\u3000 0\u3000\u3000\u3000\u3000 100\u3000\u3000\u3000\u3000 200\u3000\u3000\u3000\u3000 300\u3000\u3000\u3000\u3000 400\u3000\u3000\u3000\u3000 500\u3000\u3000\u3000\u3000 600\u3000\u3000\u3000\u3000 700\u3000\u3000\u3000\u3000 800\u3000\u3000\u3000\u3000 900",g("div","ruler-y",a)}let t=o.fadeIn===!1?"1":"0";b.style.opacity=t,P.style.opacity=t;let i=a?.querySelector(".toolbar");i&&(i.style.opacity=t)}function fe(t){if(o.parallelDrawing===!1)return(!t.parent||t.parent.done)&&(!t.master||t.master.done);let i=t.parent?.master?.68:.15;return(!t.parent||t.parent.done||t.parent.progress>=i)&&(!t.master||t.master.done||t.master.progress>=.35)}function he(t){if(t.pending&&!t.pending.started&&!t.pending.done)return;let i=new Set($.filter(s=>s!==t).map(s=>s.pending)),e=lt.find(s=>!s.started&&!s.done&&!i.has(s));e!==t.pending&&(t.pending=e,t.idleTime=0)}function ge(t){let i=window.scrollY,e=i+wt,s,D=1/0;for(let H of lt){if(H.done||H.started||!fe(H)||H.cy-H.height*.5>e+80)continue;let rt=Math.max(0,H.cy-H.height*.5-i)*.78+Math.hypot(H.cx-window.scrollX-t.x,H.cy-i-t.y)*.22-(t.pending===H?150:0);rt<D&&(s=H,D=rt)}if(!s){he(t);return}t.pending=void 0,s.started=!0,t.task=s,t.elapsed=0,t.fromX=t.x,t.fromY=t.y,t.fromVx=t.vx,t.fromVy=t.vy;let u=s.text?.[0]?.units[0],f=Vt(s,u&&o.typing!==!1?u.startX:s.master?s.master.x:s.x,u&&o.typing!==!1?u.y:s.master?s.master.y:s.y),Y=Math.hypot(f.x-window.scrollX-t.x,f.y-window.scrollY-t.y);t.travel=j(.2+Math.sqrt(Y)*.013,.2,.52);let L=(t.index+s.id)%2===0?1:-1;t.curve=L*j(Y*(.11+(t.index+s.id)%4*.03),8,64);let I=(s.text?.reduce((H,rt)=>H+rt.units.length,0)??0)/Z(o.typingSpeed,45,5,300);if(t.duration=s.kind==="text"?j(I<1?.48+I*.52:I,.48,8):.45+Math.min(1,(s.width+s.height)/950),t.node.dataset.motion="working",t.node.dataset.tool="arrow",t.node.style.setProperty("--caret-angle",`${s.container.angle.toFixed(2)}deg`),t.selection.parentElement!==s.container.node&&s.container.node.append(t.selection),t.selection.style.borderStyle=s.master?"dashed":"solid",s.master&&o.showGuides===!0){let H=g("span","measure",t.selection);H.textContent=`\u2325 ${Math.round(Math.hypot(s.x-s.master.x,s.y-s.master.y))}`}}function xe(t,i){let e=t.task;t.elapsed+=i;let s=t.travel,D=e.text?.[0]?.units[0],u=D&&o.typing!==!1?D.startX:e.master?e.master.x:e.x,f=D&&o.typing!==!1?D.y:e.master?e.master.y:e.y,Y=Vt(e,u,f),L=Y.x-window.scrollX,et=Y.y-window.scrollY;if(t.elapsed<s){let B=j(t.elapsed/s,0,1),N=ft(B),xt=L-t.fromX,dt=et-t.fromY,vt=Math.hypot(xt,dt)||1,nt=-dt/vt,Mt=xt/vt,Lt=4*N*(1-N)*t.curve,Bt=B*(1-B)*(1-B)*s/n.speed,Kt=t.x,Nt=t.y;t.x=t.fromX+xt*N+nt*Lt+t.fromVx*Bt,t.y=t.fromY+dt*N+Mt*Lt+t.fromVy*Bt;let q=Math.max(.004,i/n.speed),Et=(t.x-Kt)/q,Pt=(t.y-Nt)/q,ve=j(Et*.026-Pt*.01,-26,26)*(1-N*.65);t.angle+=(ve-t.angle)*(1-Math.exp(-14*q));return}let I=j((t.elapsed-s)/t.duration,0,1),H=ft(I);e.progress=I,e.element.dataset.swarmProgress=String(I);let rt=e.width*H,Yt=e.height*H,K=e.master?(e.master.x-e.x)*(1-H):0,it=e.master?(e.master.y-e.y)*(1-H)-Math.sin(H*Math.PI)*10:0;if(e.element.style.opacity="1",e.element.style.visibility="visible",e.element.style.transform=e.master?`translate(${K}px,${it}px)`:"",e.text){t.selection.hidden=!0;let B=o.typing!==!1;t.node.dataset.tool=B?"type":"arrow";let N=e.text.reduce((q,Et)=>q+Et.units.length,0),xt=j(I+Math.sin(I*Math.PI*3+t.index)*(.12/Math.max(4,N))*(1-I),0,1),dt=B?I>=1?N:Math.min(N,Math.max(1,Math.floor(xt*(N+.7)))):N,vt=dt,nt=D,Mt=!1;for(let q of e.text){let Et=Math.min(q.units.length,Math.max(0,vt)),Pt=q.value.slice(0,Et?q.units[Et-1].end:0);q.write&&q.shown!==Pt&&(q.shown=Pt,q.write(Pt),Mt=!0),q.node.textContent!==Pt&&(q.node.textContent=Pt,Mt=!0),Et&&(nt=q.units[Et-1]),vt-=q.units.length,q.node.style.opacity=B?q.opacity:String(Number(q.opacity||1)*H)}let Lt=!B||dt>0,Bt=nt?Lt?nt.x:nt.startX:e.x,Kt=nt?nt.y:e.y,Nt=Vt(e,Bt,Kt);t.x=Nt.x-window.scrollX,t.y=Nt.y-window.scrollY,t.node.style.setProperty("--caret-height",`${j(nt?.height??e.height,12,80)}px`),t.node.style.setProperty("--caret-angle",`${e.container.angle.toFixed(2)}deg`),B&&Mt&&T.play("type",t.x/St)}else{t.node.dataset.tool=e.master?"duplicate":e.kind==="line"?"pen":"cross",t.selection.hidden=!1;let B=e.x-e.container.ox+K,N=e.y-e.container.oy+it;t.selection.style.left=`${B}px`,t.selection.style.top=`${N}px`,t.selection.style.width=`${Math.max(1,e.master?e.width:rt)}px`,t.selection.style.height=`${Math.max(1,e.master?e.height:Yt)}px`,t.selection.style.background=e.kind==="box"&&!e.master&&I<.65?"#a0a5ab18":"",t.badge.textContent=`${Math.round(rt)} \xD7 ${Math.round(Yt)}`;let xt=e.master?e.x+K:e.kind==="line"&&e.height>e.width?e.x+e.width*.5:e.x+rt,dt=e.master?e.y+it:e.kind==="line"&&e.width>=e.height?e.y+e.height*.5:e.y+Yt,vt=Vt(e,xt,dt);t.x=vt.x-window.scrollX,t.y=vt.y-window.scrollY;let nt=e.element.firstElementChild,Mt=(1-H)*100,Lt=(1-H)*100;nt.style.clipPath=e.master||H>.97?"":e.kind==="line"?e.height>e.width?`inset(0 0 ${Lt}% 0)`:`inset(0 ${Mt}% 0 0)`:`inset(0 ${Mt}% ${Lt}% 0)`,nt.style.transform=e.master||e.kind==="line"?"":`scale(${(.975+.025*H).toFixed(4)})`,nt.style.opacity=String(Number(e.opacity||1)*(.28+.72*H))}if(I>.02&&I<.08&&T.play("draw",t.x/St),I>=1){e.done=!0;let B=e.element.firstElementChild;B.style.clipPath="",B.style.opacity=e.opacity,B.style.transform="",e.element.style.transform="",t.selection.hidden=!0,t.selection.querySelector(".measure")?.remove(),t.node.dataset.tool="arrow",t.node.dataset.motion="idle",t.node.style.setProperty("--caret-angle","0deg"),t.task=void 0,t.vx=0,t.vy=0,t.idleX=t.x,t.idleY=t.y,t.idleTime=0,t.delay=o.smoothTransition===!1?0:.06+t.index%5*.022,n.completed++,n.progress=n.total?n.completed/n.total:1}}function Ut(t,i,e){let s=t.index*2.399963,D=Z(o.floatSpeed,1,.25,3),u=Z(o.floatAmplitude,1,.25,3),f=h*D,Y,L;if(e){let K=o.floatingIntro!==!1,it=K?.74+t.index%3*.17:1,B=K&&t.index%4===3?-.72:.85,N=t.index/$.length*Math.PI*2+f*B,xt=K?Math.sin(f*1.45+s)*26*u:0,dt=Math.min((108+xt)*it,v.width*.32,v.height*.32);Y=v.left+v.width/2+Math.cos(N)*dt+(K?Math.sin(f*1.65+s)*20*u:0),L=v.top+v.height*.46+Math.sin(N)*dt*.72+(K?Math.cos(f*2.05+s)*24*u:0)}else if(o.floatingIdle!==!1){t.idleTime+=i;let K=ft(t.idleTime/.32);if(t.pending&&!t.pending.started&&!t.pending.done){let it=j(t.pending.cx-window.scrollX,v.left+25,Math.max(v.left+25,v.right-35)),B=j(t.pending.cy-window.scrollY,v.top+35,Math.max(v.top+35,v.bottom-45)),N=1-Math.exp(-3.1*i);t.idleX+=(it-t.idleX)*N,t.idleY+=(B-t.idleY)*N}Y=t.idleX+(Math.sin(f*1.55+s)*52+Math.sin(f*2.4+s*.7)*16)*u*K,L=t.idleY+(Math.cos(f*1.85+s)*36+Math.sin(f*2.75+s*1.3)*12)*u*K}else{let K=t.index/$.length*Math.PI*2+f*.28,it=55+t.index%4*23;Y=gt.x+Math.cos(K)*it,L=gt.y+Math.sin(K)*it*.7}let et=(K,it,B)=>{let N=(it+(B-K)*38*i)*Math.exp(-8*i);return{position:K+N*i,velocity:N}},I=et(t.x,t.vx,j(Y,v.left+15,Math.max(v.left+15,v.right-25))),H=et(t.y,t.vy,j(L,v.top+25,Math.max(v.top+25,v.bottom-35)));t.x=I.position,t.vx=I.velocity,t.y=H.position,t.vy=H.velocity,t.node.dataset.motion=e?"orbit":t.pending&&!t.pending.started?"staging":"idle";let rt=j(t.vx*.045-t.vy*.015,-24,24),Yt=Math.sin(f*1.5+s)*16+rt;t.angle+=(Yt-t.angle)*(1-Math.exp(-8*i))}function ye(){if(o.burstOnComplete===!1||Z(o.exitDuration,700,0,3e3)===0){y();return}let t=Math.hypot(v.width,v.height)+120,i=$.map((e,s)=>s);for(let e=i.length-1;e>0;e--){let s=Math.floor(Math.random()*(e+1));[i[e],i[s]]=[i[s],i[e]]}$.forEach((e,s)=>{let D=i[s]/Math.max(1,$.length),u=(Math.random()-.5)*(Math.PI*1.35/Math.max(1,$.length)+.85),f=-Math.PI+D*Math.PI*2+u,Y=t*(.78+Math.random()*.62),L=Math.cos(f)*Y,et=Math.sin(f)*Y,I=(Math.random()-.5)*220;e.fromX=e.x,e.fromY=e.y,e.exitX=e.x+L,e.exitY=e.y+et,e.exitCurveX=-Math.sin(f)*I,e.exitCurveY=Math.cos(f)*I,e.exitAngle=j(Math.cos(f)*28-Math.sin(f)*14+(Math.random()-.5)*18,-42,42),e.node.dataset.tool="arrow",e.node.dataset.motion="exit",e.selection.hidden=!0}),S=0,C("exiting")}function be(t){n.phase!=="exiting"&&Number.isFinite(t.bornAt)&&(t.node.style.opacity=String(ft((h-t.bornAt)/.25))),t.node.style.transform=`translate3d(${t.x.toFixed(2)}px,${t.y.toFixed(2)}px,0)`;let i=t.node.querySelector(".pointer");i&&(i.style.transform=`translate(-3px,-2.5px) rotate(${t.angle.toFixed(2)}deg) scale(${t.scale.toFixed(3)})`)}function kt(t){if(!ot)return;if(!ut.isConnected){V();return}if(Tt(),tt&&pt&&["left","top","width","height"].some(e=>Math.abs(v[e]-pt[e])>2)){y();return}let i=Math.min(.05,Math.max(0,(t-yt)/1e3));if(yt=t,R.style.transform=`translate(${-window.scrollX}px,${-window.scrollY}px)`,n.phase!=="paused"){let e=i*n.speed;_+=e,h+=i,d+=i;let s=o.fadeIn===!1?1:ft(d*1e3/Math.max(1,Z(o.fadeInDuration,360,0,3e3)));b.style.opacity=String(s);let D=a?.querySelector(".toolbar");if(D&&(D.style.opacity=String(s)),n.phase==="intro"){P.style.opacity=String(s);let u=1+Math.sin(h*3.2)*.045;if(P.style.transform=`translate(-50%,-50%) scale(${u.toFixed(3)})`,$.forEach(f=>Ut(f,i,!0)),Xt&&_*1e3>=Z(o.introDuration,1600,0,15e3)&&It(),!ot)return}else if(n.phase==="transition"){x+=i;let u=ft(x*1e3/Math.max(1,Z(o.transitionDuration,480,0,3e3)));P.style.opacity=String(1-u),P.style.transform=`translate(-50%,-50%) scale(${(1-u*.18).toFixed(3)})`,$.forEach(f=>{let Y=f.index*2.399963,L=_t(f.x,f.vx,f.fromX+Math.sin(Y)*22*u,i),et=_t(f.y,f.vy,f.fromY+Math.cos(Y)*16*u,i);f.x=L.position,f.vx=L.velocity,f.y=et.position,f.vy=et.velocity,f.node.dataset.motion="handoff",f.idleX=f.x,f.idleY=f.y}),u>=1&&(P.style.opacity="0",C("building"))}else if(n.phase==="building"){if(P.style.opacity="0",$.forEach(u=>{u.delay=Math.max(0,u.delay-i),!(u.retiring&&!u.task)&&(!u.retiring&&!u.task&&u.delay<=0&&ge(u),u.task?(u.elapsed>=u.travel&&(u.angle*=Math.exp(-10*i)),xe(u,e)):Ut(u,i,!1))}),qt(),n.tour&&!tt){let u=lt.filter(f=>!f.done).reduce((f,Y)=>Math.min(f,Y.cy-Y.height*.5),1/0);if(Number.isFinite(u)){let f=Math.max(0,u-wt*.35);f>window.scrollY+1&&window.scrollBy(0,Math.min(f-window.scrollY,180*e))}}if(n.completed===n.total&&(n.progress=1,a?.querySelectorAll(".guide,.ruler-x,.ruler-y").forEach(u=>u.remove()),T.play("complete"),C("complete"),o.onComplete?.(),!ot||(o.finishBehavior!=="flock"&&ye(),!ot)))return}else if(n.phase==="exiting"){S+=i;let u=j(S*1e3/Math.max(1,Z(o.exitDuration,700,0,3e3)),0,1),f=u*(.36+.64*u),Y=4*u*(1-u);if($.forEach(L=>{L.x=L.fromX+(L.exitX-L.fromX)*f+L.exitCurveX*Y,L.y=L.fromY+(L.exitY-L.fromY)*f+L.exitCurveY*Y,L.angle+=(L.exitAngle-L.angle)*(1-Math.exp(-12*i)),L.scale=1-ft(u)*.12,L.node.style.opacity=String(1-ft((u-.42)/.58))}),c.style.opacity=String(1-ft((u-.42)/.58)),D&&(D.style.opacity=String(1-ft(u))),u>=1){y();return}}else n.phase==="complete"&&$.forEach(u=>Ut(u,i,!1));$.forEach(be),t-$t>150&&($t=t,A())}ot&&(ht=window.requestAnimationFrame(kt))}return{start:W,replay:W,pause:M,resume:X,goLive:y,stop:V,setSpeed:O,setSound:w,setTour:ct,setReady:Q,setCursorCount:Gt,getState:G,destroy(){J(),T.destroy(),Ht=!0,n={...n,phase:"idle",agents:0}}}}function pe(o={}){let n=(0,U.useRef)(o);n.current=o;let l=(0,U.useRef)({}),a=(0,U.useRef)(null),[c,R]=(0,U.useState)(()=>Ot(o)),b=(0,U.useRef)(null);if(!b.current){let P=()=>(a.current||(a.current=Wt({...n.current,...l.current,onStateChange:E=>{l.current={...l.current,speed:E.speed,sound:E.sound,tour:E.tour},R(E),n.current.onStateChange?.(E)},onComplete:()=>n.current.onComplete?.(),onError:E=>{n.current.onError?n.current.onError(E):console.error("[react-swarm-rebuild]",E)}})),a.current);b.current={start:()=>{a.current?.destroy(),a.current=null,P().start()},replay:()=>b.current.start(),pause:()=>a.current?.pause(),resume:()=>a.current?.resume(),goLive:()=>a.current?.goLive(),stop:()=>a.current?.stop(),setSpeed:E=>P().setSpeed(E),setSound:E=>P().setSound(E),setTour:E=>P().setTour(E),setReady:E=>{l.current.ready=E,a.current?.setReady(E)},setCursorCount:E=>{l.current.cursorCount=E,a.current?.setCursorCount(E)},getState:()=>a.current?.getState()??Ot(n.current),destroy:()=>{a.current?.destroy(),a.current=null,R(Ot(n.current))}}}return(0,U.useEffect)(()=>()=>{a.current?.destroy(),a.current=null},[]),(0,U.useEffect)(()=>{o.speed!==void 0&&a.current?.setSpeed(o.speed)},[o.speed]),(0,U.useEffect)(()=>{o.sound!==void 0&&a.current?.setSound(o.sound)},[o.sound]),(0,U.useEffect)(()=>{o.tour!==void 0&&a.current?.setTour(o.tour)},[o.tour]),(0,U.useEffect)(()=>{o.ready!==void 0&&b.current?.setReady(o.ready)},[o.ready]),(0,U.useEffect)(()=>{o.cursorCount!==void 0&&b.current?.setCursorCount(o.cursorCount)},[o.cursorCount]),{...b.current,state:c}}var De=(0,U.forwardRef)(function({active:n=!0,...l},a){let c=pe(l);(0,U.useImperativeHandle)(a,()=>c,[c]);let{start:R,stop:b}=c;return(0,U.useEffect)(()=>(n?R():b(),b),[n,R,b]),null});
40
+ //# sourceMappingURL=index.cjs.map