UNPKG

@tsparticles/all

Version:

All-inclusive tsParticles bundle — all engine packages, plugins, interactions, presets, shapes, updaters, effects, paths, emitters, sounds, and palettes in one dependency. Ready to use components available for React, Vue.js (2.x and 3.x), Angular, Svelte,

28,656 lines 1.11 MB
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
/* tsParticles v4.4.0 */
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.bundles = global.__tsParticlesInternals.bundles || {}, global.__tsParticlesInternals.bundles.all = global.__tsParticlesInternals.bundles.all || {})));
})(this, (function (exports) { 'use strict';

    const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half$2 = 0.5, millisecondsToSeconds$1 = 1000, originPoint = {
        x: 0,
        y: 0,
        z: 0,
    }, defaultTransform$1 = {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
    }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha$1 = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio$1 = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty$1 = 0, quarter$2 = 0.25, threeQuarter = half$2 + quarter$2, minVelocity = 0, minDistance$7 = 0, minRadius$8 = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$3 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex$1 = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle$1 = 0, identity$3 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;

    exports.MoveDirection = void 0;
    (function (MoveDirection) {
        MoveDirection["bottom"] = "bottom";
        MoveDirection["bottomLeft"] = "bottom-left";
        MoveDirection["bottomRight"] = "bottom-right";
        MoveDirection["left"] = "left";
        MoveDirection["none"] = "none";
        MoveDirection["right"] = "right";
        MoveDirection["top"] = "top";
        MoveDirection["topLeft"] = "top-left";
        MoveDirection["topRight"] = "top-right";
        MoveDirection["outside"] = "outside";
        MoveDirection["inside"] = "inside";
    })(exports.MoveDirection || (exports.MoveDirection = {}));

    function getZ(source) {
        return "z" in source ? source.z : originPoint.z;
    }
    class Vector3d {
        x;
        y;
        z;
        constructor(x = originPoint.x, y = originPoint.y, z = originPoint.z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        static get origin() {
            return Vector3d.create(originPoint.x, originPoint.y, originPoint.z);
        }
        get angle() {
            return Math.atan2(this.y, this.x);
        }
        set angle(angle) {
            this.#updateFromAngle(angle, this.length);
        }
        get length() {
            return Math.sqrt(this.getLengthSq());
        }
        set length(length) {
            this.#updateFromAngle(this.angle, length);
        }
        static clone(source) {
            return Vector3d.create(source.x, source.y, getZ(source));
        }
        static create(x, y, z) {
            if (typeof x === "number") {
                return new Vector3d(x, y ?? originPoint.y, z ?? originPoint.z);
            }
            return new Vector3d(x.x, x.y, getZ(x));
        }
        add(v) {
            return Vector3d.create(this.x + v.x, this.y + v.y, this.z + getZ(v));
        }
        addTo(v) {
            this.x += v.x;
            this.y += v.y;
            this.z += getZ(v);
        }
        copy() {
            return Vector3d.clone(this);
        }
        div(n) {
            return Vector3d.create(this.x / n, this.y / n, this.z / n);
        }
        getLengthSq() {
            return this.x ** squareExp + this.y ** squareExp;
        }
        mult(n) {
            return Vector3d.create(this.x * n, this.y * n, this.z * n);
        }
        multTo(n) {
            this.x *= n;
            this.y *= n;
            this.z *= n;
        }
        normalize() {
            const length = this.length;
            if (length != none) {
                this.multTo(inverseFactorNumerator / length);
            }
        }
        rotate(angle) {
            return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), originPoint.z);
        }
        setTo(c) {
            this.x = c.x;
            this.y = c.y;
            this.z = getZ(c);
        }
        sub(v) {
            return Vector3d.create(this.x - v.x, this.y - v.y, this.z - getZ(v));
        }
        subFrom(v) {
            this.x -= v.x;
            this.y -= v.y;
            this.z -= getZ(v);
        }
        #updateFromAngle(angle, length) {
            this.x = Math.cos(angle) * length;
            this.y = Math.sin(angle) * length;
        }
    }
    class Vector extends Vector3d {
        constructor(x = originPoint.x, y = originPoint.y) {
            super(x, y, originPoint.z);
        }
        static get origin() {
            return Vector.create(originPoint.x, originPoint.y);
        }
        static clone(source) {
            return Vector.create(source.x, source.y);
        }
        static create(x, y) {
            if (typeof x === "number") {
                return new Vector(x, y ?? originPoint.y);
            }
            return new Vector(x.x, x.y);
        }
    }

    function isBoolean(arg) {
        return typeof arg === "boolean";
    }
    function isString(arg) {
        return typeof arg === "string";
    }
    function isNumber(arg) {
        return typeof arg === "number";
    }
    function isFunction(arg) {
        return typeof arg === "function";
    }
    function isObject(arg) {
        return typeof arg === "object" && arg !== null;
    }
    function isArray(arg) {
        return Array.isArray(arg);
    }
    function isNull(arg) {
        return arg === null || arg === undefined;
    }

    const piDeg$1 = 180, degToRadFactor = Math.PI / piDeg$1;
    let _random = Math.random;
    const _animationLoop = {
        nextFrame: (cb) => requestAnimationFrame(cb),
        cancel: (idx) => {
            cancelAnimationFrame(idx);
        },
    };
    function setRandom(rnd = Math.random) {
        _random = rnd;
    }
    function getRandomFn() {
        return _random;
    }
    function getRandom() {
        const min = 0, max = 1;
        return clamp(_random(), min, max - Number.EPSILON);
    }
    function getRandomInRange(min, max) {
        return getRandom() * (max - min) + min;
    }
    function setAnimationFunctions(nextFrame, cancel) {
        _animationLoop.nextFrame = nextFrame;
        _animationLoop.cancel = cancel;
    }
    function animate(fn) {
        return _animationLoop.nextFrame(fn);
    }
    function cancelAnimation(handle) {
        _animationLoop.cancel(handle);
    }
    function clamp(num, min, max) {
        return Math.min(Math.max(num, min), max);
    }
    function mix(comp1, comp2, weight1, weight2) {
        return Math.floor((comp1 * weight1 + comp2 * weight2) / (weight1 + weight2));
    }
    function randomInRangeValue(r) {
        const max = getRangeMax(r), minOffset = 0;
        let min = getRangeMin(r);
        if (max === min) {
            min = minOffset;
        }
        return getRandomInRange(min, max);
    }
    function getRangeValue(value) {
        return isNumber(value) ? value : randomInRangeValue(value);
    }
    function getRangeMin(value) {
        return isNumber(value) ? value : value.min;
    }
    function getRangeMax(value) {
        return isNumber(value) ? value : value.max;
    }
    function setRangeValue(source, value) {
        if (source === value || (value === undefined && isNumber(source))) {
            return source;
        }
        const min = getRangeMin(source), max = getRangeMax(source);
        return value !== undefined
            ? {
                min: Math.min(min, value),
                max: Math.max(max, value),
            }
            : setRangeValue(min, max);
    }
    function getDistances(pointA, pointB) {
        const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y;
        return { dx: dx, dy: dy, distance: Math.hypot(dx, dy) };
    }
    function getDistanceSq(pointA, pointB) {
        const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y;
        return dx * dx + dy * dy;
    }
    function getDistance(pointA, pointB) {
        return Math.sqrt(getDistanceSq(pointA, pointB));
    }
    function checkDistance(pointA, pointB, distance) {
        return getDistanceSq(pointA, pointB) <= distance * distance;
    }
    function degToRad(degrees) {
        return degrees * degToRadFactor;
    }
    function getParticleDirectionAngle(direction, position, center) {
        if (isNumber(direction)) {
            return degToRad(direction);
        }
        switch (direction) {
            case exports.MoveDirection.top:
                return -Math.PI * half$2;
            case exports.MoveDirection.topRight:
                return -Math.PI * quarter$2;
            case exports.MoveDirection.right:
                return empty$1;
            case exports.MoveDirection.bottomRight:
                return Math.PI * quarter$2;
            case exports.MoveDirection.bottom:
                return Math.PI * half$2;
            case exports.MoveDirection.bottomLeft:
                return Math.PI * threeQuarter;
            case exports.MoveDirection.left:
                return Math.PI;
            case exports.MoveDirection.topLeft:
                return -Math.PI * threeQuarter;
            case exports.MoveDirection.inside:
                return Math.atan2(center.y - position.y, center.x - position.x);
            case exports.MoveDirection.outside:
                return Math.atan2(position.y - center.y, position.x - center.x);
            default:
                return getRandom() * doublePI;
        }
    }
    function getParticleBaseVelocity(direction) {
        const baseVelocity = Vector.origin;
        baseVelocity.length = 1;
        baseVelocity.angle = direction;
        return baseVelocity;
    }
    function collisionVelocity(v1, v2, m1, m2) {
        return Vector.create((v1.x * (m1 - m2)) / (m1 + m2) + (v2.x * double * m2) / (m1 + m2), v1.y);
    }
    function calcPositionFromSize(data) {
        return data.position?.x !== undefined && data.position.y !== undefined
            ? {
                x: (data.position.x * data.size.width) / percentDenominator,
                y: (data.position.y * data.size.height) / percentDenominator,
            }
            : undefined;
    }
    function calcPositionOrRandomFromSize(data) {
        return {
            x: ((data.position?.x ?? getRandom() * percentDenominator) * data.size.width) / percentDenominator,
            y: ((data.position?.y ?? getRandom() * percentDenominator) * data.size.height) / percentDenominator,
        };
    }
    function calcPositionOrRandomFromSizeRanged(data) {
        const position = {
            x: data.position?.x !== undefined ? getRangeValue(data.position.x) : undefined,
            y: data.position?.y !== undefined ? getRangeValue(data.position.y) : undefined,
        };
        return calcPositionOrRandomFromSize({ size: data.size, position });
    }
    function calcExactPositionOrRandomFromSize(data) {
        const { position, size } = data;
        return {
            x: position?.x ?? getRandom() * size.width,
            y: position?.y ?? getRandom() * size.height,
        };
    }
    function parseAlpha(input) {
        const defaultAlpha = 1;
        if (!input) {
            return defaultAlpha;
        }
        return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
    }

    exports.OutModeDirection = void 0;
    (function (OutModeDirection) {
        OutModeDirection["bottom"] = "bottom";
        OutModeDirection["left"] = "left";
        OutModeDirection["right"] = "right";
        OutModeDirection["top"] = "top";
    })(exports.OutModeDirection || (exports.OutModeDirection = {}));

    exports.PixelMode = void 0;
    (function (PixelMode) {
        PixelMode["precise"] = "precise";
        PixelMode["percent"] = "percent";
    })(exports.PixelMode || (exports.PixelMode = {}));

    const minRadius$7 = 0;
    function isForbiddenKey(key) {
        return key === "__proto__" || key === "constructor" || key === "prototype";
    }
    function hasMatchMedia() {
        return typeof matchMedia !== "undefined";
    }
    function safeDocument() {
        return globalThis.document;
    }
    function safeMatchMedia(query) {
        if (!hasMatchMedia()) {
            return;
        }
        return matchMedia(query);
    }
    function safeMutationObserver(callback) {
        if (typeof MutationObserver === "undefined") {
            return;
        }
        return new MutationObserver(callback);
    }
    function isInArray(value, array) {
        return value === array || (isArray(array) && array.includes(value));
    }
    function itemFromArray(array, index, useIndex = true) {
        return array[index !== undefined && useIndex ? index % array.length : Math.floor(getRandom() * array.length)];
    }
    function isPointInside(point, size, offset, radius, direction) {
        return areBoundsInside(calculateBounds(point, radius ?? minRadius$7), size, offset, direction);
    }
    function areBoundsInside(bounds, size, offset, direction) {
        let inside = true;
        if (!direction || direction === exports.OutModeDirection.bottom) {
            inside = bounds.top < size.height + offset.x;
        }
        if (inside && (!direction || direction === exports.OutModeDirection.left)) {
            inside = bounds.right > offset.x;
        }
        if (inside && (!direction || direction === exports.OutModeDirection.right)) {
            inside = bounds.left < size.width + offset.y;
        }
        if (inside && (!direction || direction === exports.OutModeDirection.top)) {
            inside = bounds.bottom > offset.y;
        }
        return inside;
    }
    function calculateBounds(point, radius) {
        return {
            bottom: point.y + radius,
            left: point.x - radius,
            right: point.x + radius,
            top: point.y - radius,
        };
    }
    function deepExtend(destination, ...sources) {
        for (const source of sources) {
            if (isNull(source)) {
                continue;
            }
            if (!isObject(source)) {
                destination = source;
                continue;
            }
            if (Array.isArray(source)) {
                if (!Array.isArray(destination)) {
                    destination = [];
                }
            }
            else if (!isObject(destination) || Array.isArray(destination)) {
                destination = Object.create(null);
            }
            const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
                const v = source[k];
                return isObject(v) || Array.isArray(v);
            });
            if (!hasNested) {
                const sourceDict = source, destDict = destination;
                for (const key of sourceKeys) {
                    if (isForbiddenKey(key)) {
                        continue;
                    }
                    const v = sourceDict[key];
                    if (v !== undefined) {
                        destDict[key] = v;
                    }
                }
                continue;
            }
            for (const key of sourceKeys) {
                if (isForbiddenKey(key)) {
                    continue;
                }
                const sourceDict = source, destDict = destination, value = sourceDict[key];
                destDict[key] = Array.isArray(value)
                    ? value.map(v => deepExtend(undefined, v))
                    : deepExtend(destDict[key], value);
            }
        }
        return destination;
    }
    function circleBounceDataFromParticle(p) {
        return {
            position: p.getPosition(),
            radius: p.getRadius(),
            mass: p.getMass(),
            velocity: p.velocity,
            factor: Vector.create(getRangeValue(p.options.bounce.horizontal.value), getRangeValue(p.options.bounce.vertical.value)),
        };
    }
    function circleBounce(p1, p2) {
        const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity), [pos1, pos2] = [p1.position, p2.position], { dx: xDist, dy: yDist } = getDistances(pos2, pos1), minimumDistance = 0;
        if (xVelocityDiff * xDist + yVelocityDiff * yDist < minimumDistance) {
            return;
        }
        const angle = -Math.atan2(yDist, xDist), m1 = p1.mass, m2 = p2.mass, u1 = p1.velocity.rotate(angle), u2 = p2.velocity.rotate(angle), v1 = collisionVelocity(u1, u2, m1, m2), v2 = collisionVelocity(u2, u1, m1, m2), vFinal1 = v1.rotate(-angle), vFinal2 = v2.rotate(-angle);
        p1.velocity.x = vFinal1.x * p1.factor.x;
        p1.velocity.y = vFinal1.y * p1.factor.y;
        p2.velocity.x = vFinal2.x * p2.factor.x;
        p2.velocity.y = vFinal2.y * p2.factor.y;
    }
    function executeOnSingleOrMultiple(obj, callback) {
        const defaultIndex = 0;
        return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, defaultIndex);
    }
    function itemFromSingleOrMultiple(obj, index, useIndex) {
        return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj;
    }
    function getPositionOrSize(positionOrSize, canvasSize) {
        const isPercent = positionOrSize.mode === exports.PixelMode.percent;
        if (!isPercent) {
            const { mode: _, ...rest } = positionOrSize;
            return rest;
        }
        const isPosition = "x" in positionOrSize;
        if (isPosition) {
            return {
                x: (positionOrSize.x / percentDenominator) * canvasSize.width,
                y: (positionOrSize.y / percentDenominator) * canvasSize.height,
            };
        }
        else {
            return {
                width: (positionOrSize.width / percentDenominator) * canvasSize.width,
                height: (positionOrSize.height / percentDenominator) * canvasSize.height,
            };
        }
    }
    function getPosition(position, canvasSize) {
        return getPositionOrSize(position, canvasSize);
    }
    function cloneStyle(style) {
        const clonedStyle = safeDocument().createElement("div").style;
        for (const key in style) {
            const styleKey = style[key];
            if (!(key in style) || isNull(styleKey)) {
                continue;
            }
            const styleValue = style.getPropertyValue?.(styleKey);
            if (!styleValue) {
                continue;
            }
            const stylePriority = style.getPropertyPriority?.(styleKey);
            if (stylePriority) {
                clonedStyle.setProperty(styleKey, styleValue, stylePriority);
            }
            else {
                clonedStyle.setProperty(styleKey, styleValue);
            }
        }
        return clonedStyle;
    }
    let _cachedZIndex, _cachedStyle;
    function getFullScreenStyle(zIndex) {
        if (_cachedZIndex !== zIndex || !_cachedStyle) {
            _cachedZIndex = zIndex;
            const fullScreenStyle = safeDocument().createElement("div").style, radix = 10, style = {
                width: "100%",
                height: "100%",
                margin: "0",
                padding: "0",
                borderWidth: "0",
                position: "fixed",
                zIndex: zIndex.toString(radix),
                "z-index": zIndex.toString(radix),
                top: "0",
                left: "0",
                "pointer-events": "none",
            };
            for (const key in style) {
                const value = style[key];
                if (value === undefined) {
                    continue;
                }
                fullScreenStyle.setProperty(key, value);
            }
            _cachedStyle = fullScreenStyle;
        }
        return _cachedStyle;
    }
    function manageListener(element, event, handler, add, options) {
        if (add) {
            let addOptions = { passive: true };
            if (isBoolean(options)) {
                addOptions.capture = options;
            }
            else if (options !== undefined) {
                addOptions = options;
            }
            element.addEventListener(event, handler, addOptions);
        }
        else {
            const removeOptions = options;
            element.removeEventListener(event, handler, removeOptions);
        }
    }
    async function getItemsFromInitializer(container, map, initializers, force = false) {
        let res = map.get(container);
        if (!res || force) {
            res = await Promise.all([...initializers.values()].map(t => t(container)));
            map.set(container, res);
        }
        return res;
    }
    async function getItemMapFromInitializer(container, map, initializers, force = false) {
        let res = map.get(container);
        if (!res || force) {
            const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
            res = new Map(entries);
            map.set(container, res);
        }
        return res;
    }

    class EventDispatcher {
        #listeners;
        constructor() {
            this.#listeners = new Map();
        }
        addEventListener(type, listener) {
            this.removeEventListener(type, listener);
            let arr = this.#listeners.get(type);
            if (!arr) {
                arr = [];
                this.#listeners.set(type, arr);
            }
            arr.push(listener);
        }
        dispatchEvent(type, args) {
            const listeners = this.#listeners.get(type);
            listeners?.forEach(handler => {
                handler(args);
            });
        }
        hasEventListener(type) {
            return !!this.#listeners.get(type);
        }
        removeAllEventListeners(type) {
            if (!type) {
                this.#listeners = new Map();
            }
            else {
                this.#listeners.delete(type);
            }
        }
        removeEventListener(type, listener) {
            const arr = this.#listeners.get(type);
            if (!arr) {
                return;
            }
            const length = arr.length, idx = arr.indexOf(listener);
            if (idx < minIndex$1) {
                return;
            }
            if (length === deleteCount) {
                this.#listeners.delete(type);
            }
            else {
                arr.splice(idx, deleteCount);
            }
        }
    }

    exports.EventType = void 0;
    (function (EventType) {
        EventType["configAdded"] = "configAdded";
        EventType["containerInit"] = "containerInit";
        EventType["particlesSetup"] = "particlesSetup";
        EventType["containerStarted"] = "containerStarted";
        EventType["containerStopped"] = "containerStopped";
        EventType["containerDestroyed"] = "containerDestroyed";
        EventType["containerPaused"] = "containerPaused";
        EventType["containerPlay"] = "containerPlay";
        EventType["containerBuilt"] = "containerBuilt";
        EventType["particleAdded"] = "particleAdded";
        EventType["particleDestroyed"] = "particleDestroyed";
        EventType["particleRemoved"] = "particleRemoved";
    })(exports.EventType || (exports.EventType = {}));

    class PluginManager {
        colorManagers = new Map();
        easingFunctions = new Map();
        effectDrawers = new Map();
        initializers = {
            effects: new Map(),
            shapes: new Map(),
            updaters: new Map(),
        };
        palettes = new Map();
        plugins = [];
        presets = new Map();
        shapeDrawers = new Map();
        updaters = new Map();
        #allLoadersSet = new Set();
        #configs = new Map();
        #engine;
        #executedSet = new Set();
        #initialized = false;
        #isRunningLoaders = false;
        #loadPromises = new Set();
        constructor(engine) {
            this.#engine = engine;
        }
        get configs() {
            const res = {};
            for (const [name, config] of this.#configs) {
                res[name] = config;
            }
            return res;
        }
        addColorManager(name, manager) {
            this.colorManagers.set(name, manager);
        }
        addConfig(config) {
            const key = config.key ?? config.name ?? "default";
            this.#configs.set(key, config);
            this.#engine.dispatchEvent(exports.EventType.configAdded, { data: { name: key, config } });
        }
        addEasing(name, easing) {
            if (this.easingFunctions.get(name)) {
                return;
            }
            this.easingFunctions.set(name, easing);
        }
        addEffect(effect, drawer) {
            this.initializers.effects.set(effect, drawer);
        }
        addPalette(name, palette) {
            this.palettes.set(name, palette);
        }
        addParticleUpdater(name, updaterInitializer) {
            this.initializers.updaters.set(name, updaterInitializer);
        }
        addPlugin(plugin) {
            if (this.getPlugin(plugin.id)) {
                return;
            }
            this.plugins.push(plugin);
        }
        addPreset(preset, options, override = false) {
            if (!(override || !this.getPreset(preset))) {
                return;
            }
            this.presets.set(preset, options);
        }
        addShape(shapes, drawer) {
            for (const shape of shapes) {
                this.initializers.shapes.set(shape, drawer);
            }
        }
        clearPlugins(container) {
            this.effectDrawers.delete(container);
            this.shapeDrawers.delete(container);
            this.updaters.delete(container);
        }
        getEasing(name) {
            return this.easingFunctions.get(name) ?? ((value) => value);
        }
        getEffectDrawers(container, force = false) {
            return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
        }
        getPalette(name) {
            return this.palettes.get(name);
        }
        getPlugin(plugin) {
            return this.plugins.find(t => t.id === plugin);
        }
        getPreset(preset) {
            return this.presets.get(preset);
        }
        async getShapeDrawers(container, force = false) {
            return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
        }
        async getUpdaters(container, force = false) {
            return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
        }
        async init() {
            if (this.#initialized || this.#isRunningLoaders) {
                return;
            }
            this.#isRunningLoaders = true;
            this.#executedSet = new Set();
            this.#allLoadersSet = new Set(this.#loadPromises);
            try {
                for (const loader of this.#allLoadersSet) {
                    await this.#runLoader(loader, this.#executedSet, this.#allLoadersSet);
                }
            }
            finally {
                this.#loadPromises.clear();
                this.#isRunningLoaders = false;
                this.#initialized = true;
            }
        }
        loadParticlesOptions(container, options, ...sourceOptions) {
            const updaters = this.updaters.get(container);
            if (!updaters) {
                return;
            }
            updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
        }
        async register(...loaders) {
            if (this.#initialized) {
                throw new Error("Register plugins can only be done before calling tsParticles.load()");
            }
            for (const loader of loaders) {
                if (this.#isRunningLoaders) {
                    await this.#runLoader(loader, this.#executedSet, this.#allLoadersSet);
                }
                else {
                    this.#loadPromises.add(loader);
                }
            }
        }
        async #runLoader(loader, executed, allLoaders) {
            if (executed.has(loader))
                return;
            executed.add(loader);
            allLoaders.add(loader);
            await loader(this.#engine);
        }
    }

    const errorPrefix = "tsParticles - Error";
    const wrap = (fn) => (...args) => {
        fn(...args);
    }, _logger = {
        debug: wrap(console.debug),
        error: (message, ...optionalParams) => {
            console.error(`${errorPrefix} - ${message}`, ...optionalParams);
        },
        info: wrap(console.info),
        log: wrap(console.log),
        trace: wrap(console.trace),
        verbose: wrap(console.log),
        warning: wrap(console.warn),
    };
    function setLogger(logger) {
        if (logger.debug) {
            _logger.debug = wrap(logger.debug);
        }
        if (logger.error) {
            _logger.error = wrap(logger.error);
        }
        if (logger.info) {
            _logger.info = wrap(logger.info);
        }
        if (logger.log) {
            _logger.log = wrap(logger.log);
        }
        if (logger.trace) {
            _logger.trace = wrap(logger.trace);
        }
        if (logger.verbose) {
            _logger.verbose = wrap(logger.verbose);
        }
        if (logger.warning) {
            _logger.warning = wrap(logger.warning);
        }
    }
    function getLogger() {
        return _logger;
    }

    const fullPercent = "100%";
    async function getDataFromUrl(data) {
        const url = itemFromSingleOrMultiple(data.url, data.index);
        if (!url) {
            return data.fallback;
        }
        const response = await fetch(url);
        if (response.ok) {
            return (await response.json());
        }
        getLogger().error(`${response.status.toString()} while retrieving config file`);
        return data.fallback;
    }
    const getCanvasFromContainer = (domContainer) => {
        const documentSafe = safeDocument();
        let canvasEl;
        const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
        if (isCanvas) {
            canvasEl = domContainer;
            canvasEl.dataset[generatedAttribute] ??= generatedFalse;
            if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
                canvasEl.style.width ||= fullPercent;
                canvasEl.style.height ||= fullPercent;
                canvasEl.style.pointerEvents = "none";
                canvasEl.style.setProperty("pointer-events", "none");
            }
        }
        else {
            const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
            if (foundCanvas) {
                canvasEl = foundCanvas;
                canvasEl.dataset[generatedAttribute] = generatedFalse;
            }
            else {
                canvasEl = documentSafe.createElement(canvasTag);
                canvasEl.dataset[generatedAttribute] = generatedTrue;
                domContainer.appendChild(canvasEl);
            }
            canvasEl.style.width ||= fullPercent;
            canvasEl.style.height ||= fullPercent;
            canvasEl.style.pointerEvents = "none";
            canvasEl.style.setProperty("pointer-events", "none");
        }
        return canvasEl;
    }, getDomContainer = (id, source) => {
        const documentSafe = safeDocument();
        let domContainer = source ?? documentSafe.getElementById(id);
        if (domContainer) {
            return domContainer;
        }
        domContainer = documentSafe.createElement("canvas");
        domContainer.id = id;
        domContainer.dataset[generatedAttribute] = generatedTrue;
        documentSafe.body.append(domContainer);
        return domContainer;
    };
    class Engine {
        pluginManager = new PluginManager(this);
        #domArray = [];
        #eventDispatcher = new EventDispatcher();
        #initialized = false;
        get items() {
            return this.#domArray;
        }
        get version() {
            return "4.4.0";
        }
        addEventListener(type, listener) {
            this.#eventDispatcher.addEventListener(type, listener);
        }
        checkVersion(pluginVersion) {
            if (this.version === pluginVersion) {
                return;
            }
            throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
        }
        dispatchEvent(type, args) {
            this.#eventDispatcher.dispatchEvent(type, args);
        }
        async init() {
            if (this.#initialized) {
                return;
            }
            await this.pluginManager.init();
            this.#initialized = true;
        }
        item(index) {
            const items = this.items, item = items[index];
            if (item?.destroyed) {
                items.splice(index, removeDeleteCount);
                return;
            }
            return item;
        }
        async load(params) {
            await this.init();
            let domSourceElement;
            if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
                domSourceElement = params.element;
            }
            const { Container } = await Promise.resolve().then(function () { return Container$1; }), id = params.id ?? domSourceElement?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor).toString()}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container({
                dispatchCallback: (eventType, args) => {
                    this.dispatchEvent(eventType, args);
                },
                id,
                onDestroy: (remove) => {
                    if (!remove) {
                        return;
                    }
                    const mainArr = this.items, idx = mainArr.indexOf(newItem);
                    if (idx >= removeMinIndex) {
                        mainArr.splice(idx, removeDeleteCount);
                    }
                },
                pluginManager: this.pluginManager,
                sourceOptions: currentOptions,
            });
            if (oldIndex >= loadMinIndex) {
                const old = this.item(oldIndex), deleteCount = old ? one : none;
                if (old && !old.destroyed) {
                    old.destroy(false);
                }
                items.splice(oldIndex, deleteCount, newItem);
            }
            else {
                items.push(newItem);
            }
            const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
                ? params.element
                : getCanvasFromContainer(getDomContainer(id, domSourceElement));
            newItem.canvas.loadCanvas(sourceCanvas);
            await newItem.start();
            return newItem;
        }
        async refresh(refresh = true) {
            if (!refresh) {
                return;
            }
            await Promise.all(this.items.map(t => t.refresh()));
        }
        removeEventListener(type, listener) {
            this.#eventDispatcher.removeEventListener(type, listener);
        }
    }

    function initEngine() {
        const existing = globalThis.tsParticles;
        if (existing?.pluginManager) {
            return existing;
        }
        return new Engine();
    }

    var RangeType;
    (function (RangeType) {
        RangeType["circle"] = "circle";
        RangeType["rectangle"] = "rectangle";
    })(RangeType || (RangeType = {}));

    class BaseRange {
        position;
        type;
        constructor(x, y, type) {
            this.position = {
                x: x,
                y: y,
            };
            this.type = type;
        }
        _resetPosition(x, y) {
            this.position.x = x;
            this.position.y = y;
        }
    }
    class Circle extends BaseRange {
        radius;
        constructor(x, y, radius) {
            super(x, y, RangeType.circle);
            this.radius = radius;
        }
        contains(point) {
            return checkDistance(point, this.position, this.radius);
        }
        intersects(range) {
            const pos1 = this.position, pos2 = range.position, r = this.radius, dx = Math.abs(pos2.x - pos1.x), dy = Math.abs(pos2.y - pos1.y);
            if (range instanceof Circle || range.type === RangeType.circle) {
                const circleRange = range, rSum = r + circleRange.radius, dist = Math.hypot(dx, dy);
                return rSum > dist;
            }
            else if (range instanceof Rectangle || range.type === RangeType.rectangle) {
                const rectRange = range, { width, height } = rectRange.size, edges = Math.pow(dx - width, squareExp) + Math.pow(dy - height, squareExp);
                return edges <= r ** squareExp || (dx <= r + width && dy <= r + height) || dx <= width || dy <= height;
            }
            return false;
        }
        reset(x, y, radius) {
            this._resetPosition(x, y);
            this.radius = radius;
            return this;
        }
    }
    class Rectangle extends BaseRange {
        size;
        constructor(x, y, width, height) {
            super(x, y, RangeType.rectangle);
            this.size = {
                height: height,
                width: width,
            };
        }
        contains(point) {
            const w = this.size.width, h = this.size.height, pos = this.position;
            return point.x >= pos.x && point.x <= pos.x + w && point.y >= pos.y && point.y <= pos.y + h;
        }
        intersects(range) {
            if (range instanceof Circle) {
                return range.intersects(this);
            }
            if (!(range instanceof Rectangle)) {
                return false;
            }
            const w = this.size.width, h = this.size.height, pos1 = this.position, pos2 = range.position, size2 = range.size, w2 = size2.width, h2 = size2.height;
            return pos2.x < pos1.x + w && pos2.x + w2 > pos1.x && pos2.y < pos1.y + h && pos2.y + h2 > pos1.y;
        }
        reset(x, y, width, height) {
            this._resetPosition(x, y);
            this.size.width = width;
            this.size.height = height;
            return this;
        }
    }

    exports.RotateDirection = void 0;
    (function (RotateDirection) {
        RotateDirection["clockwise"] = "clockwise";
        RotateDirection["counterClockwise"] = "counter-clockwise";
        RotateDirection["random"] = "random";
    })(exports.RotateDirection || (exports.RotateDirection = {}));

    exports.AnimationMode = void 0;
    (function (AnimationMode) {
        AnimationMode["auto"] = "auto";
        AnimationMode["increase"] = "increase";
        AnimationMode["decrease"] = "decrease";
        AnimationMode["random"] = "random";
    })(exports.AnimationMode || (exports.AnimationMode = {}));

    exports.HdrMode = void 0;
    (function (HdrMode) {
        HdrMode["standard"] = "standard";
        HdrMode["natural"] = "natural";
        HdrMode["vivid"] = "vivid";
        HdrMode["cinematic"] = "cinematic";
        HdrMode["dynamic"] = "dynamic";
    })(exports.HdrMode || (exports.HdrMode = {}));

    exports.LimitMode = void 0;
    (function (LimitMode) {
        LimitMode["delete"] = "delete";
        LimitMode["wait"] = "wait";
    })(exports.LimitMode || (exports.LimitMode = {}));

    exports.OutMode = void 0;
    (function (OutMode) {
        OutMode["bounce"] = "bounce";
        OutMode["none"] = "none";
        OutMode["out"] = "out";
        OutMode["destroy"] = "destroy";
        OutMode["split"] = "split";
    })(exports.OutMode || (exports.OutMode = {}));

    exports.AlterType = void 0;
    (function (AlterType) {
        AlterType["darken"] = "darken";
        AlterType["enlighten"] = "enlighten";
    })(exports.AlterType || (exports.AlterType = {}));

    exports.DestroyType = void 0;
    (function (DestroyType) {
        DestroyType["none"] = "none";
        DestroyType["max"] = "max";
        DestroyType["min"] = "min";
    })(exports.DestroyType || (exports.DestroyType = {}));

    exports.GradientType = void 0;
    (function (GradientType) {
        GradientType["linear"] = "linear";
        GradientType["radial"] = "radial";
        GradientType["random"] = "random";
    })(exports.GradientType || (exports.GradientType = {}));

    exports.ParticleOutType = void 0;
    (function (ParticleOutType) {
        ParticleOutType["normal"] = "normal";
        ParticleOutType["inside"] = "inside";
        ParticleOutType["outside"] = "outside";
    })(exports.ParticleOutType || (exports.ParticleOutType = {}));

    exports.StartValueType = void 0;
    (function (StartValueType) {
        StartValueType["max"] = "max";
        StartValueType["min"] = "min";
        StartValueType["random"] = "random";
    })(exports.StartValueType || (exports.StartValueType = {}));

    exports.AnimationStatus = void 0;
    (function (AnimationStatus) {
        AnimationStatus["increasing"] = "increasing";
        AnimationStatus["decreasing"] = "decreasing";
    })(exports.AnimationStatus || (exports.AnimationStatus = {}));

    exports.DrawLayer = void 0;
    (function (DrawLayer) {
        DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
        DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
        DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
        DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
        DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
        DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
        DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
        DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
    })(exports.DrawLayer || (exports.DrawLayer = {}));

    class OptionLoader {
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.doLoad(data);
        }
    }
    function loadOptions(options, ...sourceOptionsArr) {
        for (const sourceOptions of sourceOptionsArr) {
            options.load(sourceOptions);
        }
    }

    function loadProperty(obj, key, value) {
        if (value !== undefined) {
            obj[key] = value;
        }
    }
    function loadRangeProperty(obj, key, value) {
        if (value !== undefined) {
            obj[key] = setRangeValue(value);
        }
    }
    function loadNestedProperty(obj, key, value) {
        if (value !== undefined) {
            obj[key].load(value);
        }
    }
    function loadLazyProperty(obj, key, value, factory) {
        if (value !== undefined) {
            const objRecord = obj;
            objRecord[key] ??= factory();
            objRecord[key].load(value);
        }
    }
    function loadExtendProperty(obj, key, value) {
        if (value !== undefined) {
            const keyStr = key;
            if (keyStr === "__proto__" || keyStr === "constructor" || keyStr === "prototype") {
                return;
            }
            const objRecord = obj, currentValue = Object.prototype.hasOwnProperty.call(objRecord, keyStr) ? objRecord[keyStr] : {};
            objRecord[keyStr] = deepExtend(currentValue, value);
        }
    }
    function loadOptionProperty(obj, key, optionClass, ...sources) {
        const objRecord = obj;
        objRecord[key] ??= new optionClass();
        const target = objRecord[key];
        for (const source of sources) {
            target.load(source?.[key]);
        }
    }

    class AnimationOptions extends OptionLoader {
        count = 0;
        decay = 0;
        delay = 0;
        enable = false;
        speed = 1;
        sync = false;
        doLoad(data) {
            loadRangeProperty(this, "count", data.count);
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "decay", data.decay);
            loadRangeProperty(this, "delay", data.delay);
            loadProperty(this, "sync", data.sync);
        }
    }
    class RangedAnimationOptions extends AnimationOptions {
        mode = exports.AnimationMode.auto;
        startValue = exports.StartValueType.random;
        doLoad(data) {
            super.doLoad(data);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "startValue", data.startValue);
        }
    }

    class ColorAnimation extends AnimationOptions {
        max;
        min;
        offset = 0;
        sync = true;
        constructor(min, max) {
            super();
            this.min = min;
            this.max = max;
        }
        doLoad(data) {
            super.doLoad(data);
            loadProperty(this, "max", data.max);
            loadProperty(this, "min", data.min);
            loadRangeProperty(this, "offset", data.offset);
        }
    }

    class HslAnimation extends OptionLoader {
        h = new ColorAnimation(hMin, hMax);
        l = new ColorAnimation(lMin, lMax);
        s = new ColorAnimation(sMin, sMax);
        doLoad(data) {
            this.h.load(data.h);
            this.s.load(data.s);
            this.l.load(data.l);
        }
    }

    class OptionsColor extends OptionLoader {
        value = "";
        static create(source, data) {
            const color = new OptionsColor();
            color.load(source);
            if (data !== undefined) {
                if (isString(data) || isArray(data)) {
                    color.load({ value: data });
                }
                else {
                    color.load(data);
                }
            }
            return color;
        }
        doLoad(data) {
            if (!isNull(data.value)) {
                this.value = data.value;
            }
        }
    }

    class AnimatableColor extends OptionsColor {
        animation = new HslAnimation();
        static create(source, data) {
            const color = new AnimatableColor();
            color.load(source);
            if (data !== undefined) {
                if (isString(data) || isArray(data)) {
                    color.load({ value: data });
                }
                else {
                    color.load(data);
                }
            }
            return color;
        }
        doLoad(data) {
            super.doLoad(data);
            const colorAnimation = data.animation;
            if (colorAnimation !== undefined) {
                if (colorAnimation.enable === undefined) {
                    this.animation.load(data.animation);
                }
                else {
                    this.animation.h.load(colorAnimation);
                }
            }
        }
    }

    class Background extends OptionLoader {
        color;
        draw;
        element;
        image = "";
        opacity = 1;
        position = "";
        repeat = "";
        size = "";
        constructor() {
            super();
            this.color = new OptionsColor();
            this.color.value = "";
        }
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "element", data.element);
            loadProperty(this, "draw", data.draw);
            loadProperty(this, "image", data.image);
            loadProperty(this, "position", data.position);
            loadProperty(this, "repeat", data.repeat);
            loadProperty(this, "size", data.size);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    class FullScreen extends OptionLoader {
        enable = true;
        zIndex = 0;
        doLoad(data) {
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "zIndex", data.zIndex);
        }
    }

    const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
    class HDROptions extends OptionLoader {
        enable = true;
        mode = exports.HdrMode.standard;
        peakNits = defaultPeakNits;
        doLoad(data) {
            if (data.enable !== undefined && !isBoolean(data.enable)) {
                throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
            }
            if (data.mode !== undefined &&
                (typeof data.mode !== "string" || !Object.values(exports.HdrMode).includes(data.mode))) {
                throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(exports.HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
            }
            if (data.peakNits !== undefined &&
                (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
                throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "peakNits", data.peakNits);
        }
    }

    class ResizeEvent extends OptionLoader {
        delay = 0.5;
        enable = true;
        doLoad(data) {
            loadProperty(this, "delay", data.delay);
            loadProperty(this, "enable", data.enable);
        }
    }

    class Effect extends OptionLoader {
        close = true;
        options = {};
        type = [];
        doLoad(data) {
            const options = data.options;
            if (options !== undefined) {
                for (const effect in options) {
                    const item = options[effect];
                    if (item) {
                        this.options[effect] = deepExtend(this.options[effect] ?? {}, item);
                    }
                }
            }
            loadProperty(this, "close", data.close);
            loadProperty(this, "type", data.type);
        }
    }

    class Fill extends OptionLoader {
        color;
        enable = true;
        opacity = 1;
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = AnimatableColor.create(this.color, data.color);
            }
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class MoveAngle extends OptionLoader {
        offset = 0;
        value = 90;
        doLoad(data) {
            loadRangeProperty(this, "offset", data.offset);
            loadRangeProperty(this, "value", data.value);
        }
    }

    class MoveCenter extends OptionLoader {
        mode = exports.PixelMode.percent;
        radius = 0;
        x = 50;
        y = 50;
        doLoad(data) {
            loadProperty(this, "x", data.x);
            loadProperty(this, "y", data.y);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "radius", data.radius);
        }
    }

    class MoveGravity extends OptionLoader {
        acceleration = 9.81;
        enable = false;
        inverse = false;
        maxSpeed = 50;
        doLoad(data) {
            loadRangeProperty(this, "acceleration", data.acceleration);
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "inverse", data.inverse);
            loadRangeProperty(this, "maxSpeed", data.maxSpeed);
        }
    }

    class ValueWithRandom extends OptionLoader {
        value = 0;
        doLoad(data) {
            if (!isNull(data.value)) {
                this.value = setRangeValue(data.value);
            }
        }
    }
    class AnimationValueWithRandom extends ValueWithRandom {
        animation = new AnimationOptions();
        doLoad(data) {
            super.doLoad(data);
            loadNestedProperty(this, "animation", data.animation);
        }
    }
    class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
        animation = new RangedAnimationOptions();
    }

    class MovePath extends OptionLoader {
        clamp = true;
        delay = new ValueWithRandom();
        enable = false;
        generator;
        options = {};
        doLoad(data) {
            loadProperty(this, "clamp", data.clamp);
            this.delay.load(data.delay);
            loadProperty(this, "enable", data.enable);
            this.generator = data.generator;
            if (data.options) {
                this.options = deepExtend(this.options, data.options);
            }
        }
    }

    class OutModes extends OptionLoader {
        bottom;
        default = exports.OutMode.out;
        left;
        right;
        top;
        doLoad(data) {
            if (data.default !== undefined) {
                this.default = data.default;
            }
            this.bottom = data.bottom ?? data.default;
            this.left = data.left ?? data.default;
            this.right = data.right ?? data.default;
            this.top = data.top ?? data.default;
        }
    }

    class Spin extends OptionLoader {
        acceleration = 0;
        enable = false;
        position;
        doLoad(data) {
            loadRangeProperty(this, "acceleration", data.acceleration);
            loadProperty(this, "enable", data.enable);
            if (data.position) {
                this.position = deepExtend({}, data.position);
            }
        }
    }

    class Move extends OptionLoader {
        angle = new MoveAngle();
        center = new MoveCenter();
        decay = 0;
        direction = exports.MoveDirection.none;
        distance = {};
        drift = 0;
        enable = false;
        gravity = new MoveGravity();
        outModes = new OutModes();
        path = new MovePath();
        random = false;
        size = false;
        speed = 2;
        spin = new Spin();
        straight = false;
        vibrate = false;
        warp = false;
        doLoad(data) {
            this.angle.load(isNumber(data.angle) ? { value: data.angle } : data.angle);
            this.center.load(data.center);
            loadRangeProperty(this, "decay", data.decay);
            loadProperty(this, "direction", data.direction);
            if (data.distance !== undefined) {
                this.distance = isNumber(data.distance)
                    ? {
                        horizontal: data.distance,
                        vertical: data.distance,
                    }
                    : { ...data.distance };
            }
            loadRangeProperty(this, "drift", data.drift);
            loadProperty(this, "enable", data.enable);
            this.gravity.load(data.gravity);
            const outModes = data.outModes;
            if (outModes !== undefined) {
                if (isObject(outModes)) {
                    this.outModes.load(outModes);
                }
                else {
                    this.outModes.load({
                        default: outModes,
                    });
                }
            }
            this.path.load(data.path);
            loadProperty(this, "random", data.random);
            loadProperty(this, "size", data.size);
            loadRangeProperty(this, "speed", data.speed);
            this.spin.load(data.spin);
            loadProperty(this, "straight", data.straight);
            loadProperty(this, "vibrate", data.vibrate);
            loadProperty(this, "warp", data.warp);
        }
    }

    class Stroke extends OptionLoader {
        color;
        opacity;
        width = 0;
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = AnimatableColor.create(this.color, data.color);
            }
            loadRangeProperty(this, "width", data.width);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class Paint extends OptionLoader {
        color;
        fill;
        stroke;
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = AnimatableColor.create(this.color, data.color);
            }
            loadLazyProperty(this, "fill", data.fill, () => new Fill());
            loadLazyProperty(this, "stroke", data.stroke, () => new Stroke());
        }
    }

    class ParticlesBounceFactor extends ValueWithRandom {
        value = 1;
    }

    class ParticlesBounce extends OptionLoader {
        horizontal = new ParticlesBounceFactor();
        vertical = new ParticlesBounceFactor();
        doLoad(data) {
            this.horizontal.load(data.horizontal);
            this.vertical.load(data.vertical);
        }
    }

    class ParticlesDensity extends OptionLoader {
        enable = false;
        height = 1080;
        width = 1920;
        doLoad(data) {
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "width", data.width);
            loadProperty(this, "height", data.height);
        }
    }

    class ParticlesNumberLimit extends OptionLoader {
        mode = exports.LimitMode.delete;
        value = 0;
        doLoad(data) {
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "value", data.value);
        }
    }

    class ParticlesNumber extends OptionLoader {
        density = new ParticlesDensity();
        limit = new ParticlesNumberLimit();
        value = 0;
        doLoad(data) {
            this.density.load(data.density);
            this.limit.load(data.limit);
            loadProperty(this, "value", data.value);
        }
    }

    class Shape extends OptionLoader {
        close = true;
        options = {};
        type = "circle";
        doLoad(data) {
            const options = data.options;
            if (options !== undefined) {
                for (const shape in options) {
                    const item = options[shape];
                    if (item) {
                        this.options[shape] = deepExtend(this.options[shape] ?? {}, item);
                    }
                }
            }
            loadProperty(this, "close", data.close);
            loadProperty(this, "type", data.type);
        }
    }

    class ZIndex extends ValueWithRandom {
        opacityRate = 1;
        sizeRate = 1;
        velocityRate = 1;
        doLoad(data) {
            super.doLoad(data);
            loadProperty(this, "opacityRate", data.opacityRate);
            loadProperty(this, "sizeRate", data.sizeRate);
            loadProperty(this, "velocityRate", data.velocityRate);
        }
    }

    class ParticlesOptions extends OptionLoader {
        bounce = new ParticlesBounce();
        effect = new Effect();
        groups = {};
        move = new Move();
        number = new ParticlesNumber();
        paint;
        palette;
        reduceDuplicates = false;
        shape = new Shape();
        zIndex = new ZIndex();
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            super();
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.paint = new Paint();
            this.paint.color = new AnimatableColor();
            this.paint.color.value = "#fff";
            this.paint.fill = new Fill();
            this.paint.fill.enable = true;
        }
        doLoad(data) {
            if (data.palette) {
                this.palette = data.palette;
                this.#importPalette(this.palette);
            }
            if (data.groups !== undefined) {
                for (const group of Object.keys(data.groups)) {
                    if (!(group in data.groups)) {
                        continue;
                    }
                    const item = data.groups[group];
                    if (item !== undefined) {
                        this.groups[group] = deepExtend(this.groups[group] ?? {}, item);
                    }
                }
            }
            if (data.reduceDuplicates !== undefined) {
                this.reduceDuplicates = data.reduceDuplicates;
            }
            this.bounce.load(data.bounce);
            this.effect.load(data.effect);
            this.move.load(data.move);
            this.number.load(data.number);
            const paintToLoad = data.paint;
            if (paintToLoad) {
                if (isArray(paintToLoad)) {
                    this.paint = executeOnSingleOrMultiple(paintToLoad, t => {
                        const tmp = new Paint();
                        tmp.load(t);
                        return tmp;
                    });
                }
                else if (isArray(this.paint)) {
                    this.paint = new Paint();
                    this.paint.load(paintToLoad);
                }
                else {
                    this.paint.load(paintToLoad);
                }
            }
            this.shape.load(data.shape);
            this.zIndex.load(data.zIndex);
            if (this.#container) {
                for (const plugin of this.#pluginManager.plugins) {
                    if (plugin.loadParticlesOptions) {
                        plugin.loadParticlesOptions(this.#container, this, data);
                    }
                }
                const updaters = this.#pluginManager.updaters.get(this.#container);
                if (updaters) {
                    for (const updater of updaters) {
                        if (updater.loadOptions) {
                            updater.loadOptions(this, data);
                        }
                    }
                }
            }
        }
        #importPalette(palette) {
            const paletteData = this.#pluginManager.getPalette(palette);
            if (!paletteData) {
                return;
            }
            const paletteColors = paletteData.colors, defaultPaintStrokeWidth = 0, defaultPaintVariantsLength = 1, firstPaintVariantIndex = 0, defaultPalettePaintVariant = {}, colorVariants = isArray(paletteColors) ? paletteColors : [paletteColors], palettePaintVariants = colorVariants.flatMap(variant => {
                const paletteFill = variant.fill, paletteStroke = variant.stroke, fillPart = paletteFill
                    ? {
                        color: {
                            value: paletteFill.value,
                        },
                        enable: paletteFill.enable,
                        opacity: paletteFill.opacity,
                    }
                    : undefined;
                if (!paletteStroke) {
                    return [
                        {
                            fill: fillPart,
                        },
                    ];
                }
                return [
                    {
                        fill: fillPart,
                        stroke: {
                            color: {
                                value: paletteStroke.value,
                            },
                            opacity: paletteStroke.opacity,
                            width: paletteStroke.width || defaultPaintStrokeWidth,
                        },
                    },
                ];
            }), palettePaint = palettePaintVariants.length > defaultPaintVariantsLength
                ? palettePaintVariants
                : (palettePaintVariants[firstPaintVariantIndex] ?? defaultPalettePaintVariant);
            this.load({
                paint: palettePaint,
                blend: {
                    enable: true,
                    mode: paletteData.blendMode,
                },
            });
        }
    }

    function loadParticlesOptions(pluginManager, container, ...sourceOptionsArr) {
        const options = new ParticlesOptions(pluginManager, container);
        loadOptions(options, ...sourceOptionsArr);
        return options;
    }

    class Options extends OptionLoader {
        autoPlay = true;
        background;
        clear = true;
        defaultThemes = {};
        delay = 0;
        detectRetina = true;
        duration = 0;
        fpsLimit = 120;
        fullScreen;
        hdr;
        key;
        name;
        palette;
        particles;
        pauseOnBlur = true;
        pauseOnOutsideViewport = true;
        preset;
        resize;
        smooth = false;
        style = {};
        zLayers = 100;
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            super();
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.background = new Background();
            this.fullScreen = new FullScreen();
            this.hdr = new HDROptions();
            this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
            this.resize = new ResizeEvent();
        }
        doLoad(data) {
            if (data.preset !== undefined) {
                this.preset = data.preset;
                executeOnSingleOrMultiple(this.preset, preset => {
                    this.#importPreset(preset);
                });
            }
            if (data.palette !== undefined) {
                this.palette = data.palette;
                this.#importPalette(this.palette);
            }
            loadProperty(this, "autoPlay", data.autoPlay);
            loadProperty(this, "clear", data.clear);
            loadProperty(this, "key", data.key);
            loadProperty(this, "name", data.name);
            loadRangeProperty(this, "delay", data.delay);
            loadProperty(this, "detectRetina", data.detectRetina);
            loadRangeProperty(this, "duration", data.duration);
            loadProperty(this, "fpsLimit", data.fpsLimit);
            const hdrData = data.hdr;
            if (isBoolean(hdrData)) {
                this.hdr.enable = hdrData;
                this.hdr.mode = exports.HdrMode.standard;
                this.hdr.peakNits = 400;
            }
            else {
                this.hdr.load(hdrData);
            }
            loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
            loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
            loadProperty(this, "zLayers", data.zLayers);
            this.background.load(data.background);
            const fullScreen = data.fullScreen;
            if (isBoolean(fullScreen)) {
                this.fullScreen.enable = fullScreen;
            }
            else {
                this.fullScreen.load(fullScreen);
            }
            this.particles.load(data.particles);
            this.resize.load(data.resize);
            this.style = deepExtend(this.style, data.style);
            loadProperty(this, "smooth", data.smooth);
            this.#pluginManager.plugins.forEach(plugin => {
                plugin.loadOptions(this.#container, this, data);
            });
        }
        #importPalette(palette) {
            const paletteData = this.#pluginManager.getPalette(palette);
            if (!paletteData) {
                return;
            }
            this.load({
                background: {
                    color: paletteData.background,
                },
                blend: {
                    enable: true,
                    mode: paletteData.blendMode,
                },
                particles: {
                    palette,
                },
            });
        }
        #importPreset(preset) {
            this.load(this.#pluginManager.getPreset(preset));
        }
    }

    const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, acesA = 2.51, acesB = 0.03, acesC = 2.43, acesD = 0.59, acesE = 0.14, saturationBoost = 1.15, lightnessBoost = 1.05, temperatureR = 1.05, temperatureB = 0.95, contrastFactor = 1.1, luminanceR = 0.2126, luminanceG = 0.7152, luminanceB = 0.0722, dynamicLuminanceFactor = 2, channelCount = 3, srgbThreshold = 0.04045, srgbDivisor = 12.92, srgbOffset = 0.055, srgbScale = 1.055, srgbExponent = 2.4, linearThreshold = 0.0031308, linearScale = 12.92;
    function getCachedStyle(key, generator) {
        let cached = styleCache.get(key);
        if (!cached) {
            cached = generator();
            if (styleCache.size > maxStyleCacheSize) {
                styleCache.clear();
            }
            styleCache.set(key, cached);
        }
        return cached;
    }
    function acesFilmic(x) {
        return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
    }
    function srgbToLinear(c) {
        return c <= srgbThreshold ? c / srgbDivisor : Math.pow((c + srgbOffset) / srgbScale, srgbExponent);
    }
    function linearToSrgb(c) {
        return c <= linearThreshold ? c * linearScale : srgbScale * Math.pow(c, one / srgbExponent) - srgbOffset;
    }
    function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
        switch (mode) {
            case exports.HdrMode.vivid: {
                const avg = (r + g + b) / channelCount;
                return {
                    b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
                    g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
                    r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
                };
            }
            case exports.HdrMode.cinematic: {
                const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
                return {
                    b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
                    g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
                    r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
                };
            }
            case exports.HdrMode.dynamic: {
                const luminance = luminanceR * r + luminanceG * g + luminanceB * b, vividWeight = Math.min(one, luminance * dynamicLuminanceFactor), naturalWeight = one - vividWeight, avg = (r + g + b) / channelCount, vividR = clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, vividG = clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, vividB = clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost;
                return {
                    b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
                    g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
                    r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
                };
            }
            case exports.HdrMode.standard:
                return { b, g, r };
            case exports.HdrMode.natural:
            default:
                return { b, g, r };
        }
    }
    function stringToRgba(pluginManager, input) {
        if (!input) {
            return;
        }
        for (const manager of pluginManager.colorManagers.values()) {
            if (manager.accepts(input)) {
                return manager.parseString(input);
            }
        }
        return undefined;
    }
    function rangeColorToRgb(pluginManager, input, index, useIndex = true) {
        if (!input) {
            return;
        }
        const color = isString(input) ? { value: input } : input;
        if (isString(color.value)) {
            return colorToRgb(pluginManager, color.value, index, useIndex);
        }
        if (isArray(color.value)) {
            const value = itemFromArray(color.value, index, useIndex);
            if (!value) {
                return;
            }
            return rangeColorToRgb(pluginManager, {
                value,
            });
        }
        for (const manager of pluginManager.colorManagers.values()) {
            const res = manager.handleRangeColor(color);
            if (res) {
                return res;
            }
        }
        return undefined;
    }
    function colorToRgb(pluginManager, input, index, useIndex = true) {
        if (!input) {
            return;
        }
        const color = isString(input) ? { value: input } : input;
        if (isString(color.value)) {
            return color.value === randomColorValue ? getRandomRgbColor() : stringToRgb(pluginManager, color.value);
        }
        if (isArray(color.value)) {
            const value = itemFromArray(color.value, index, useIndex);
            if (!value) {
                return;
            }
            return colorToRgb(pluginManager, {
                value,
            });
        }
        for (const manager of pluginManager.colorManagers.values()) {
            const res = manager.handleColor(color);
            if (res) {
                return res;
            }
        }
        return undefined;
    }
    function rangeColorToHsl(pluginManager, color, index, useIndex = true) {
        const rgb = rangeColorToRgb(pluginManager, color, index, useIndex);
        return rgb ? rgbToHsl(rgb) : undefined;
    }
    function rgbToHsl(color) {
        const r1 = color.r / rgbMax, g1 = color.g / rgbMax, b1 = color.b / rgbMax, max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1), res = {
            h: hMin,
            l: (max + min) * half$2,
            s: sMin,
        };
        if (max !== min) {
            res.s = res.l < half$2 ? (max - min) / (max + min) : (max - min) / (double - max - min);
            if (r1 === max) {
                res.h = (g1 - b1) / (max - min);
            }
            else if (g1 === max) {
                res.h = double + (b1 - r1) / (max - min);
            }
            else {
                res.h = double * double + (r1 - g1) / (max - min);
            }
        }
        res.l *= lMax;
        res.s *= sMax;
        res.h *= hPhase;
        if (res.h < hMin) {
            res.h += hMax;
        }
        if (res.h >= hMax) {
            res.h -= hMax;
        }
        return res;
    }
    function stringToAlpha(pluginManager, input) {
        return stringToRgba(pluginManager, input)?.a;
    }
    function stringToRgb(pluginManager, input) {
        return stringToRgba(pluginManager, input);
    }
    function hslChannel(temp1, temp2, temp3) {
        const temp3Min = 0, temp3Max = 1;
        if (temp3 < temp3Min) {
            temp3++;
        }
        if (temp3 > temp3Max) {
            temp3--;
        }
        if (temp3 * sextuple < temp3Max) {
            return temp1 + (temp2 - temp1) * sextuple * temp3;
        }
        if (temp3 * double < temp3Max) {
            return temp2;
        }
        if (temp3 * triple < temp3Max * double) {
            const temp3Offset = double / triple;
            return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
        }
        return temp1;
    }
    function hslToRgb(hsl) {
        const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
        if (s === sMin) {
            const grayscaleValue = Math.round(lNormalized * rgbMax);
            return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
        }
        const temp1 = lNormalized < half$2
            ? lNormalized * (sNormalizedOffset + sNormalized)
            : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
        return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
    }
    function hslToRgbFloat(hsl) {
        const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
        if (s === sMin) {
            const grayscaleValue = lNormalized * rgbMax;
            return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
        }
        const temp1 = lNormalized < half$2
            ? lNormalized * (sNormalizedOffset + sNormalized)
            : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
        return { r: red, g: green, b: blue };
    }
    function hslaToRgba(hsla) {
        const rgbResult = hslToRgb(hsla);
        return {
            a: hsla.a,
            b: rgbResult.b,
            g: rgbResult.g,
            r: rgbResult.r,
        };
    }
    function getRandomRgbColor(min, hdr) {
        const fixedMin = min ?? defaultRgbMin;
        if (hdr) {
            return {
                r: getRandomInRange(fixedMin, rgbMax),
                g: getRandomInRange(fixedMin, rgbMax),
                b: getRandomInRange(fixedMin, rgbMax),
            };
        }
        const fixedMax = rgbMax + identity$3, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
        return {
            b: getRgbInRangeValue(),
            g: getRgbInRangeValue(),
            r: getRgbInRangeValue(),
        };
    }
    function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
        const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$3, key = hdr
            ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
            : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
        return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
    }
    function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = exports.HdrMode.standard) {
        const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
        return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$3).toString()})`;
    }
    function hdrToneMapColor(color, headroom, middleGray, mode) {
        const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
        if (mode !== exports.HdrMode.natural && mode !== exports.HdrMode.vivid && mode !== exports.HdrMode.cinematic && mode !== exports.HdrMode.dynamic) {
            return { b: bNorm, g: gNorm, r: rNorm };
        }
        const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
        return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
    }
    function hdrToneMap(normalized, headroom, middleGray) {
        if (normalized <= middleGray) {
            return acesFilmic(normalized);
        }
        const expanded = normalized + (normalized - middleGray) * (headroom - one);
        return acesFilmic(expanded);
    }
    function getSdrStyleFromRgb(color, opacity) {
        return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$3).toString()})`;
    }
    function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
        const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$3, key = hdr
            ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
            : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
        return getCachedStyle(key, () => hdr
            ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
            : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
    }
    function colorMix(color1, color2, size1, size2, hdr) {
        let rgb1 = color1, rgb2 = color2;
        if (!("r" in rgb1)) {
            rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
        }
        if (!("r" in rgb2)) {
            rgb2 = hdr ? hslToRgbFloat(color2) : hslToRgb(color2);
        }
        if (hdr) {
            const lin1 = {
                b: srgbToLinear(rgb1.b / rgbMax),
                g: srgbToLinear(rgb1.g / rgbMax),
                r: srgbToLinear(rgb1.r / rgbMax),
            }, lin2 = {
                b: srgbToLinear(rgb2.b / rgbMax),
                g: srgbToLinear(rgb2.g / rgbMax),
                r: srgbToLinear(rgb2.r / rgbMax),
            }, totalWeight = size1 + size2;
            return {
                b: linearToSrgb((lin1.b * size1 + lin2.b * size2) / totalWeight) * rgbMax,
                g: linearToSrgb((lin1.g * size1 + lin2.g * size2) / totalWeight) * rgbMax,
                r: linearToSrgb((lin1.r * size1 + lin2.r * size2) / totalWeight) * rgbMax,
            };
        }
        return {
            b: mix(rgb1.b, rgb2.b, size1, size2),
            g: mix(rgb1.g, rgb2.g, size1, size2),
            r: mix(rgb1.r, rgb2.r, size1, size2),
        };
    }
    function getLinkColor(p1, p2, linkColor, hdr) {
        if (linkColor === randomColorValue) {
            return getRandomRgbColor();
        }
        else if (linkColor === midColorValue) {
            const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
            if (sourceColor && destColor && p2) {
                return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
            }
            else {
                const hslColor = sourceColor ?? destColor;
                if (hslColor) {
                    return hslToRgb(hslColor);
                }
            }
        }
        else {
            return linkColor;
        }
        return undefined;
    }
    function getLinkRandomColor(pluginManager, optColor, blink, consent) {
        const color = isString(optColor) ? optColor : optColor.value;
        if (color === randomColorValue) {
            if (consent) {
                return rangeColorToRgb(pluginManager, {
                    value: color,
                });
            }
            if (blink) {
                return randomColorValue;
            }
            return midColorValue;
        }
        else if (color === midColorValue) {
            return midColorValue;
        }
        else {
            return rangeColorToRgb(pluginManager, {
                value: color,
            });
        }
    }
    function getHslFromAnimation(animation) {
        return animation === undefined
            ? undefined
            : {
                h: animation.h.value,
                s: animation.s.value,
                l: animation.l.value,
            };
    }
    function getHslAnimationFromHsl(hsl, animationOptions, reduceFactor) {
        const resColor = {
            h: {
                enable: false,
                value: hsl.h,
                min: hMin,
                max: hMax,
            },
            s: {
                enable: false,
                value: hsl.s,
                min: sMin,
                max: sMax,
            },
            l: {
                enable: false,
                value: hsl.l,
                min: lMin,
                max: lMax,
            },
        };
        if (animationOptions) {
            setColorAnimation(resColor.h, animationOptions.h, reduceFactor);
            setColorAnimation(resColor.s, animationOptions.s, reduceFactor);
            setColorAnimation(resColor.l, animationOptions.l, reduceFactor);
        }
        return resColor;
    }
    function setColorAnimation(colorValue, colorAnimation, reduceFactor) {
        colorValue.enable = colorAnimation.enable;
        colorValue.min = colorAnimation.min;
        colorValue.max = colorAnimation.max;
        if (colorValue.enable) {
            colorValue.velocity = (getRangeValue(colorAnimation.speed) / percentDenominator) * reduceFactor;
            colorValue.decay = decayOffset - getRangeValue(colorAnimation.decay);
            colorValue.status = exports.AnimationStatus.increasing;
            colorValue.loops = defaultLoops;
            colorValue.maxLoops = getRangeValue(colorAnimation.count);
            colorValue.time = defaultTime;
            colorValue.delayTime = getRangeValue(colorAnimation.delay) * millisecondsToSeconds$1;
            if (!colorAnimation.sync) {
                colorValue.velocity *= getRandom();
                colorValue.value *= getRandom();
            }
            colorValue.initialValue = colorValue.value;
            colorValue.offset = setRangeValue(colorAnimation.offset);
        }
        else {
            colorValue.velocity = defaultVelocity;
        }
    }
    function updateColorValue(data, decrease, delta, _hdr) {
        const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
        if (!data.enable ||
            ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
            return;
        }
        data.time ??= 0;
        if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
            data.time += delta.value;
        }
        if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
            return;
        }
        const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor, decay = data.decay ?? identity, max = data.max, min = data.min;
        if (!decrease || data.status === exports.AnimationStatus.increasing) {
            data.value += velocity;
            if (data.value > max) {
                data.loops ??= 0;
                data.loops++;
                if (decrease) {
                    data.status = exports.AnimationStatus.decreasing;
                }
                else {
                    data.value -= max;
                }
            }
        }
        else {
            data.value -= velocity;
            if (data.value < min) {
                data.loops ??= 0;
                data.loops++;
                data.status = exports.AnimationStatus.increasing;
            }
        }
        if (data.velocity && decay !== identity) {
            data.velocity *= decay;
        }
        data.value = clamp(data.value, min, max);
    }
    function updateColor(color, delta, hdr) {
        if (!color) {
            return;
        }
        const { h, s, l } = color;
        updateColorValue(h, false, delta);
        updateColorValue(s, true, delta);
        updateColorValue(l, true, delta);
    }
    function alterHsl(color, type, value) {
        return {
            h: color.h,
            s: color.s,
            l: color.l + (type === exports.AlterType.darken ? -lFactor : lFactor) * value,
        };
    }

    const tsParticles = initEngine();

    const defaultHeightFactor$1 = half$2, defaultHeadWidthFactor$1 = 0.2, defaultBodyHeightFactor$1 = half$2;
    function drawArrow(data) {
        const { context, particle, radius } = data, width = radius * double, heightFactor = particle.heightFactor ?? defaultHeightFactor$1, headWidthFactor = particle.headWidthFactor ?? defaultHeadWidthFactor$1, bodyHeightFactor = particle.bodyHeightFactor ?? defaultBodyHeightFactor$1, height = width * heightFactor, headWidth = width * headWidthFactor, bodyHeight = height * bodyHeightFactor;
        context.moveTo(-width * half$2, originPoint.y);
        context.lineTo(-width * half$2, -bodyHeight * half$2);
        context.lineTo(width * half$2 - headWidth, -bodyHeight * half$2);
        context.lineTo(width * half$2 - headWidth, -height * half$2);
        context.lineTo(width * half$2 + headWidth, originPoint.y);
        context.lineTo(width * half$2 - headWidth, height * half$2);
        context.lineTo(width * half$2 - headWidth, bodyHeight * half$2);
        context.lineTo(-width * half$2, bodyHeight * half$2);
        context.lineTo(-width * half$2, originPoint.y);
    }

    const defaultHeightFactor = 0.5, defaultHeadWidthFactor = 0.2, defaultBodyHeightFactor = 0.5;
    class ArrowDrawer {
        draw(data) {
            drawArrow(data);
        }
        particleInit(_container, particle) {
            const shapeData = particle.shapeData;
            particle.heightFactor = getRangeValue(shapeData?.heightFactor ?? defaultHeightFactor);
            particle.headWidthFactor = getRangeValue(shapeData?.headWidthFactor ?? defaultHeadWidthFactor);
            particle.bodyHeightFactor = getRangeValue(shapeData?.bodyHeightFactor ?? defaultBodyHeightFactor);
        }
    }

    async function loadArrowShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["arrow"], () => Promise.resolve(new ArrowDrawer()));
        });
    }

    class BackgroundMaskCover {
        color;
        draw;
        element;
        image;
        opacity = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "draw", data.draw);
            loadProperty(this, "element", data.element);
            loadProperty(this, "image", data.image);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    class BackgroundMask {
        composite = "destination-out";
        cover = new BackgroundMaskCover();
        enable = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "composite", data.composite);
            if (data.cover !== undefined) {
                const cover = data.cover, color = (isString(data.cover) ? { color: data.cover } : data.cover);
                this.cover.load(cover.color !== undefined ||
                    cover.draw !== undefined ||
                    cover.element !== undefined ||
                    cover.image !== undefined
                    ? cover
                    : { color: color });
            }
            loadProperty(this, "enable", data.enable);
        }
    }

    class BackgroundMaskPlugin {
        id = "background-mask";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { BackgroundMaskPluginInstance } = await Promise.resolve().then(function () { return BackgroundMaskPluginInstance$1; });
            return new BackgroundMaskPluginInstance(this.#pluginManager, container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let backgroundMaskOptions = options.backgroundMask;
            if (!backgroundMaskOptions?.load) {
                options.backgroundMask = backgroundMaskOptions = new BackgroundMask();
            }
            backgroundMaskOptions.load(source?.backgroundMask);
        }
        needsPlugin(options) {
            return !!options?.backgroundMask?.enable;
        }
    }

    async function loadBackgroundMaskPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new BackgroundMaskPlugin(e.pluginManager));
        });
    }

    class MovePlugin {
        id = "move";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { MovePluginInstance } = await Promise.resolve().then(function () { return MovePluginInstance$1; });
            return new MovePluginInstance(this.#pluginManager, container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadMovePlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            const moveEngine = e, movePluginManager = moveEngine.pluginManager;
            movePluginManager.initializers.pathGenerators ??= new Map();
            movePluginManager.pathGenerators ??= new Map();
            movePluginManager.addPathGenerator = (name, generator) => {
                movePluginManager.initializers.pathGenerators ??= new Map();
                movePluginManager.initializers.pathGenerators.set(name, generator);
            };
            movePluginManager.getPathGenerators = async (container, force = false) => {
                movePluginManager.initializers.pathGenerators ??= new Map();
                movePluginManager.pathGenerators ??= new Map();
                return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
            };
            e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
        });
    }
    function ensureBaseMoverLoaded(e) {
        if (!e.pluginManager.addPathGenerator) {
            throw new Error("tsParticles Base Mover is not loaded");
        }
    }

    const defaultOptions$6 = {
        segmentLength: 20,
        branchChance: 0.2,
        maxAngle: Math.PI / 3,
        speedVariation: 0.3,
        inertia: {
            enable: false,
            factor: 0.1,
        },
    };
    class BranchesPathGenerator {
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.options = {
                ...defaultOptions$6,
                inertia: { ...defaultOptions$6.inertia },
            };
        }
        generate(p) {
            const opts = this.options;
            p.branching ??= {
                angle: getRandom() * doublePI,
                remaining: opts.segmentLength,
                baseSpeed: p.velocity.length,
                speed: p.velocity.length,
            };
            const b = p.branching;
            if (b.remaining <= 0) {
                const branch = getRandom() < (opts.branchChance ?? 0), maxAngle = opts.maxAngle ?? defaultOptions$6.maxAngle, delta = (getRandom() * 2 - 1) * (branch ? maxAngle : maxAngle * 0.3);
                b.angle += delta;
                b.remaining = opts.segmentLength;
                const speedFactor = 1 + (getRandom() * 2 - 1) * (opts.speedVariation ?? 0);
                b.speed = b.baseSpeed * speedFactor;
            }
            b.remaining -= b.speed;
            const targetX = Math.cos(b.angle) * b.speed, targetY = Math.sin(b.angle) * b.speed, inertia = opts.inertia;
            if (inertia?.enable) {
                const factor = inertia.factor ?? 0.1;
                p.velocity.x += (targetX - p.velocity.x) * factor;
                p.velocity.y += (targetY - p.velocity.y) * factor;
                this.#res.x = p.velocity.x;
                this.#res.y = p.velocity.y;
            }
            else {
                p.velocity.x = 0;
                p.velocity.y = 0;
                this.#res.x = targetX;
                this.#res.y = targetY;
            }
            return this.#res;
        }
        init() {
            const source = this.#container.actualOptions.particles.move.path.options;
            this.options.segmentLength = source["segmentLength"] ?? this.options.segmentLength;
            this.options.branchChance = source["branchChance"] ?? this.options.branchChance;
            this.options.maxAngle = source["maxAngle"] ?? this.options.maxAngle;
            this.options.speedVariation = source["speedVariation"] ?? this.options.speedVariation;
            const inertiaSource = source["inertia"];
            if (inertiaSource) {
                const inertiaOptions = { ...defaultOptions$6.inertia };
                inertiaOptions.enable = inertiaSource.enable ?? inertiaOptions.enable;
                inertiaOptions.factor = inertiaSource.factor ?? inertiaOptions.factor;
                this.options.inertia = inertiaOptions;
            }
        }
        reset(p) {
            delete p.branching;
        }
        update() {
        }
    }

    const branchingPathName = "branchesPathGenerator";
    async function loadBranchesPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(branchingPathName, container => {
                return Promise.resolve(new BranchesPathGenerator(container));
            });
        });
    }

    class BrownianPathGenerator {
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.options = {
                angleDelta: Math.PI / 12,
                damping: identity$3,
            };
        }
        generate(p) {
            p.brownian ??= {
                angle: getRandom() * doublePI,
                speed: p.velocity.length,
            };
            const b = p.brownian, delta = (getRandom() * 2 - 1) * (this.options.angleDelta ?? 0);
            b.angle += delta;
            const damping = this.options.damping ?? identity$3;
            p.velocity.x = 0;
            p.velocity.y = 0;
            this.#res.length = b.speed * damping;
            this.#res.angle = b.angle;
            return this.#res;
        }
        init() {
            const source = this.#container.actualOptions.particles.move.path.options;
            this.options.angleDelta = source["angleDelta"] ?? this.options.angleDelta;
            this.options.damping = source["damping"] ?? this.options.damping;
        }
        reset(p) {
            delete p.brownian;
        }
        update() {
        }
    }

    const brownianPathName = "brownianPathGenerator";
    async function loadBrownianPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(brownianPathName, container => {
                return Promise.resolve(new BrownianPathGenerator(container));
            });
        });
    }

    const bubbleFactor = 3;
    class BubbleDrawer {
        drawAfter(data) {
            const { context, radius } = data, bubbleRadius = radius / bubbleFactor;
            context.beginPath();
            context.arc(bubbleRadius, -bubbleRadius, bubbleRadius, defaultAngle$1, doublePI, false);
            context.closePath();
            context.fillStyle = "#fff9";
            context.fill();
        }
    }

    async function loadBubbleEffect(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addEffect("bubble", () => {
                return Promise.resolve(new BubbleDrawer());
            });
        });
    }

    class CanvasMaskOverride {
        color = true;
        opacity = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "color", data.color);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    const minAlpha$1 = 0;
    class CanvasMaskPixels {
        offset = 4;
        filter = (pixel) => pixel.a > minAlpha$1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.filter !== undefined) {
                if (isString(data.filter)) {
                    if (data.filter in globalThis) {
                        const filter = globalThis[data.filter];
                        if (isFunction(filter)) {
                            this.filter = filter;
                        }
                    }
                }
                else {
                    this.filter = data.filter;
                }
            }
            loadProperty(this, "offset", data.offset);
        }
    }

    class ImageMask {
        src = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "src", data.src);
        }
    }

    class FontTextMask {
        family = "sans-serif";
        size = 100;
        style = "";
        variant = "";
        weight = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "family", data.family);
            loadProperty(this, "size", data.size);
            loadProperty(this, "style", data.style);
            loadProperty(this, "variant", data.variant);
            loadProperty(this, "weight", data.weight);
        }
    }

    class TextMaskLine {
        separator = "\n";
        spacing = 10;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "separator", data.separator);
            loadProperty(this, "spacing", data.spacing);
        }
    }

    class TextMask {
        color = "#000000";
        fill = true;
        font = new FontTextMask();
        lines = new TextMaskLine();
        text = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "color", data.color);
            loadProperty(this, "fill", data.fill);
            this.font.load(data.font);
            this.lines.load(data.lines);
            loadProperty(this, "text", data.text);
        }
    }

    class CanvasMask {
        element;
        enable = false;
        image;
        override = new CanvasMaskOverride();
        pixels = new CanvasMaskPixels();
        position;
        scale = 1;
        selector;
        text;
        constructor() {
            this.position = {
                x: 50,
                y: 50,
            };
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.element !== undefined && data.element instanceof HTMLCanvasElement) {
                this.element = data.element;
            }
            loadProperty(this, "enable", data.enable);
            if (data.image) {
                this.image ??= new ImageMask();
                this.image.load(data.image);
            }
            this.pixels.load(data.pixels);
            if (data.position) {
                this.position = {
                    x: data.position.x ?? this.position.x,
                    y: data.position.y ?? this.position.y,
                };
            }
            this.override.load(data.override);
            loadProperty(this, "scale", data.scale);
            loadProperty(this, "selector", data.selector);
            if (data.text) {
                this.text ??= new TextMask();
                this.text.load(data.text);
            }
        }
    }

    class CanvasMaskPlugin {
        id = "canvas-mask";
        async getPlugin(container) {
            const { CanvasMaskPluginInstance } = await Promise.resolve().then(function () { return CanvasMaskPluginInstance$1; });
            return new CanvasMaskPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let canvasMaskOptions = options.canvasMask;
            if (canvasMaskOptions?.load === undefined) {
                options.canvasMask = canvasMaskOptions = new CanvasMask();
            }
            canvasMaskOptions.load(source?.canvasMask);
        }
        needsPlugin(options) {
            return options?.canvasMask?.enable ?? false;
        }
    }

    async function loadCanvasMaskPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new CanvasMaskPlugin());
        });
    }

    var SegmentType;
    (function (SegmentType) {
        SegmentType["move"] = "move";
        SegmentType["line"] = "line";
        SegmentType["bezier"] = "bezier";
        SegmentType["quadratic"] = "quadratic";
        SegmentType["arc"] = "arc";
        SegmentType["ellipse"] = "ellipse";
    })(SegmentType || (SegmentType = {}));

    const firstIndex$5 = 0, index2 = 1, index3 = 2, index4 = 3;
    function drawPath(ctx, radius, path) {
        const firstSegment = path.segments[firstIndex$5];
        if (!firstSegment) {
            return;
        }
        const firstValue = firstSegment.values[firstIndex$5];
        if (!firstValue) {
            return;
        }
        ctx.moveTo(firstValue.x * radius, firstValue.y * radius);
        for (const segment of path.segments) {
            const value = segment.values[firstIndex$5];
            if (!value) {
                continue;
            }
            const segmentValue2 = segment.values[index2], segmentValue3 = segment.values[index3], segmentValue4 = segment.values[index4];
            switch (segment.type) {
                case SegmentType.move:
                    ctx.moveTo(value.x * radius, value.y * radius);
                    break;
                case SegmentType.line:
                    ctx.lineTo(value.x * radius, value.y * radius);
                    break;
                case SegmentType.bezier:
                    if (!segmentValue2 || !segmentValue3 || !segmentValue4) {
                        continue;
                    }
                    ctx.bezierCurveTo(segmentValue2.x * radius, segmentValue2.y * radius, segmentValue3.x * radius, segmentValue3.y * radius, segmentValue4.x * radius, segmentValue4.y * radius);
                    break;
                case SegmentType.quadratic:
                    if (!segmentValue2 || !segmentValue3) {
                        continue;
                    }
                    ctx.quadraticCurveTo(segmentValue2.x * radius, segmentValue2.y * radius, segmentValue3.x * radius, segmentValue3.y * radius);
                    break;
                case SegmentType.arc:
                    if (!segmentValue2 || !segmentValue3) {
                        continue;
                    }
                    ctx.arc(value.x * radius, value.y * radius, segmentValue2.x * radius, segmentValue3.x, segmentValue3.y);
                    break;
                case SegmentType.ellipse:
                    if (!segmentValue2 || !segmentValue3 || !segmentValue4) {
                        continue;
                    }
                    ctx.ellipse(value.x * radius, value.y * radius, segmentValue2.x * radius, segmentValue2.y * radius, segmentValue3.x, segmentValue4.x, segmentValue4.y);
                    break;
            }
        }
        if (!path.half) {
            return;
        }
        const lengthOffset = 1, minLength = 0;
        for (let i = path.segments.length - lengthOffset; i >= minLength; i--) {
            const segment = path.segments[i];
            if (!segment) {
                continue;
            }
            const value = segment.values[firstIndex$5], index2 = 1, index3 = 2, segmentValue2 = segment.values[index2], segmentValue3 = segment.values[index3];
            switch (segment.type) {
                case SegmentType.line:
                    if (!value) {
                        break;
                    }
                    ctx.lineTo(value.x * -radius, value.y * radius);
                    break;
                case SegmentType.bezier:
                    if (!value || !segmentValue2 || !segmentValue3) {
                        break;
                    }
                    ctx.bezierCurveTo(-segmentValue3.x * radius, segmentValue3.y * radius, -segmentValue2.x * radius, segmentValue2.y * radius, -value.x * radius, value.y * radius);
                    break;
                case SegmentType.quadratic:
                    if (!segmentValue2 || !segmentValue3) {
                        break;
                    }
                    ctx.quadraticCurveTo(-segmentValue2.x * radius, segmentValue2.y * radius, -segmentValue3.x * radius, segmentValue3.y * radius);
                    break;
                case SegmentType.arc:
                case SegmentType.ellipse:
            }
        }
    }

    var SuitType;
    (function (SuitType) {
        SuitType["hearts"] = "hearts";
        SuitType["diamonds"] = "diamonds";
        SuitType["clubs"] = "clubs";
        SuitType["spades"] = "spades";
    })(SuitType || (SuitType = {}));

    const eighth = quarter$2 * half$2, n = half$2, halfN = n * half$2, oppositeN = -n, oppositeHalfN = -halfN, eighthN = n * eighth, threeQuarterN = n * threeQuarter;
    const club = {
        half: true,
        segments: [
            {
                type: SegmentType.bezier,
                values: [
                    { x: empty$1, y: oppositeN },
                    { x: empty$1, y: oppositeN },
                    { x: halfN, y: oppositeN },
                    { x: halfN, y: oppositeHalfN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: halfN, y: oppositeHalfN },
                    { x: halfN, y: oppositeHalfN },
                    { x: n, y: oppositeHalfN },
                    { x: n, y: empty$1 },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: n, y: empty$1 },
                    { x: n, y: empty$1 },
                    { x: n, y: halfN },
                    { x: halfN, y: halfN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: halfN, y: halfN },
                    { x: halfN, y: halfN },
                    { x: eighthN, y: halfN },
                    { x: eighthN, y: eighthN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: eighthN, y: eighthN },
                    { x: eighthN, y: halfN },
                    { x: halfN, y: n },
                    { x: halfN, y: n },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: halfN, y: n },
                    { x: halfN, y: n },
                    { x: empty$1, y: n },
                    { x: empty$1, y: n },
                ],
            },
        ],
    };
    const diamond = {
        half: true,
        segments: [
            {
                type: SegmentType.bezier,
                values: [
                    { x: empty$1, y: n },
                    { x: empty$1, y: n },
                    { x: threeQuarterN, y: empty$1 },
                    { x: threeQuarterN, y: empty$1 },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: threeQuarterN, y: empty$1 },
                    { x: threeQuarterN, y: empty$1 },
                    { x: empty$1, y: oppositeN },
                    { x: empty$1, y: oppositeN },
                ],
            },
        ],
    };
    const heart = {
        half: true,
        segments: [
            {
                type: SegmentType.bezier,
                values: [
                    { x: empty$1, y: n },
                    { x: empty$1, y: n },
                    { x: n, y: empty$1 },
                    { x: n, y: oppositeHalfN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: n, y: oppositeHalfN },
                    { x: n, y: oppositeHalfN },
                    { x: n, y: oppositeN },
                    { x: halfN, y: oppositeN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: halfN, y: oppositeN },
                    { x: halfN, y: oppositeN },
                    { x: empty$1, y: oppositeN },
                    { x: empty$1, y: oppositeHalfN },
                ],
            },
        ],
    };
    const spade = {
        half: true,
        segments: [
            {
                type: SegmentType.bezier,
                values: [
                    { x: empty$1, y: oppositeN },
                    { x: empty$1, y: oppositeN },
                    { x: n, y: oppositeHalfN },
                    { x: n, y: empty$1 },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: n, y: empty$1 },
                    { x: n, y: empty$1 },
                    { x: n, y: halfN },
                    { x: halfN, y: halfN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: halfN, y: halfN },
                    { x: halfN, y: halfN },
                    { x: eighthN, y: halfN },
                    { x: eighthN, y: eighthN },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: eighthN, y: eighthN },
                    { x: eighthN, y: halfN },
                    { x: halfN, y: n },
                    { x: halfN, y: n },
                ],
            },
            {
                type: SegmentType.bezier,
                values: [
                    { x: halfN, y: n },
                    { x: halfN, y: n },
                    { x: empty$1, y: n },
                    { x: empty$1, y: n },
                ],
            },
        ],
    };
    const paths = {
        [SuitType.hearts]: heart,
        [SuitType.diamonds]: diamond,
        [SuitType.clubs]: club,
        [SuitType.spades]: spade,
    };

    class ClubDrawer {
        draw(data) {
            const { context, radius } = data;
            drawPath(context, radius, paths.clubs);
        }
    }

    async function loadClubsSuitShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["club", "clubs"], () => Promise.resolve(new ClubDrawer()));
        });
    }

    class DiamondDrawer {
        draw(data) {
            const { context, radius } = data;
            drawPath(context, radius, paths.diamonds);
        }
    }

    async function loadDiamondsSuitShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["diamond", "diamonds"], () => Promise.resolve(new DiamondDrawer()));
        });
    }

    let HeartDrawer$1 = class HeartDrawer {
        draw(data) {
            const { context, radius } = data;
            drawPath(context, radius, paths.hearts);
        }
    };

    async function loadHeartsSuitShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["heart", "hearts"], () => Promise.resolve(new HeartDrawer$1()));
        });
    }

    class SpadeDrawer {
        draw(data) {
            const { context, radius } = data;
            drawPath(context, radius, paths.spades);
        }
    }

    async function loadSpadesSuitShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["spade", "spades"], () => Promise.resolve(new SpadeDrawer()));
        });
    }

    async function loadCardSuitsShape(engine) {
        engine.checkVersion("4.4.0");
        await Promise.all([
            loadClubsSuitShape(engine),
            loadDiamondsSuitShape(engine),
            loadHeartsSuitShape(engine),
            loadSpadesSuitShape(engine),
        ]);
    }

    const cardWidthRatio = (double * double) / triple, cardHeightRatio = double, cornerRadiusRatio = 0.2, cornerFontRatio = 0.4, cornerSuitRatio = 0.3, centerSuitRatio = 0.7, cornerPaddingRatio = 0.2, textHorizontalOffsetRatio = 0.25, minRadius$6 = 0, minAngle$5 = 0, suitEdgeBufferFactor = 0.1, fixedCacheKey = 2, cardsCache = new Map(), redSuitColor = { r: 215, g: 20, b: 20 }, blackSuitColor = { r: 18, g: 18, b: 18 };
    function drawRoundedCard(ctx, radius, cardData, hdr, flipped, canvasSettings, peakNits, mode) {
        if (flipped) {
            drawRoundedCardBack(ctx, radius);
        }
        else {
            const cacheKey = getCacheKey(radius, hdr, cardData, peakNits, mode), cardWidth = radius * cardWidthRatio, cardHeight = radius * cardHeightRatio, halfWidth = cardWidth * half$2, halfHeight = cardHeight * half$2;
            let cachedData = cardsCache.get(cacheKey);
            if (!cachedData) {
                const cacheCanvas = new OffscreenCanvas(cardWidth, cardHeight), cacheCtx = cacheCanvas.getContext("2d", canvasSettings);
                if (cacheCtx) {
                    cacheCtx.translate(halfWidth, halfHeight);
                    drawRoundedCardFront(cacheCtx, radius, cardData, hdr, peakNits, mode);
                    cachedData = cacheCanvas instanceof HTMLCanvasElement ? cacheCanvas : cacheCanvas.transferToImageBitmap();
                    cardsCache.set(cacheKey, cachedData);
                }
            }
            if (cachedData) {
                ctx.drawImage(cachedData, -halfWidth, -halfHeight, cardWidth, cardHeight);
            }
            else {
                drawRoundedCardFront(ctx, radius, cardData, hdr, peakNits, mode);
            }
        }
    }
    function getCacheKey(radius, hdr, cardData, peakNits, mode) {
        return `${radius.toFixed(fixedCacheKey)}-${hdr ? "hdr" : "sdr"}-${peakNits !== undefined ? peakNits.toFixed(fixedCacheKey) : "default"}-${mode ?? "default"}-${cardData.suit}-${cardData.value}`;
    }
    function drawRoundedCardBack(ctx, radius) {
        drawCardBody(ctx, radius);
    }
    function drawRoundedCardFront(ctx, radius, cardData, hdr, peakNits, mode) {
        const { suit, value } = cardData, cardWidth = radius * cardWidthRatio, cardHeight = radius * cardHeightRatio, halfWidth = cardWidth * half$2, halfHeight = cardHeight * half$2, cornerPadding = radius * cornerPaddingRatio, cornerFontSize = radius * cornerFontRatio, cornerSuitSize = radius * cornerSuitRatio, centerSuitSize = radius * centerSuitRatio, textOffset = radius * textHorizontalOffsetRatio, suitEdgeBuffer = radius * suitEdgeBufferFactor, isRed = suit === SuitType.hearts || suit === SuitType.diamonds, color = isRed
            ? getStyleFromRgb(redSuitColor, hdr, undefined, peakNits, mode)
            : getStyleFromRgb(blackSuitColor, hdr, undefined, peakNits, mode);
        ctx.save();
        drawCardBody(ctx, radius);
        ctx.fillStyle = getStyleFromRgb({ r: 255, g: 255, b: 255 }, hdr, undefined, peakNits, mode);
        ctx.fill();
        ctx.strokeStyle = getStyleFromRgb({ r: 0, g: 0, b: 0 }, hdr, undefined, peakNits, mode);
        ctx.stroke();
        ctx.fillStyle = color;
        ctx.font = `bold ${cornerFontSize.toString()}px Arial, serif`;
        ctx.textAlign = "left";
        ctx.textBaseline = "middle";
        const topLeftX = -halfWidth + cornerPadding + suitEdgeBuffer, topLeftY = -halfHeight + cornerPadding + cornerFontSize * half$2;
        ctx.save();
        ctx.translate(topLeftX, topLeftY);
        ctx.beginPath();
        drawPath(ctx, cornerSuitSize, paths[suit]);
        ctx.fill();
        ctx.restore();
        ctx.fillText(value, topLeftX + textOffset, topLeftY);
        ctx.save();
        ctx.translate(halfWidth - cornerPadding - suitEdgeBuffer, halfHeight - cornerPadding - cornerFontSize * half$2);
        ctx.rotate(Math.PI);
        ctx.save();
        ctx.beginPath();
        drawPath(ctx, cornerSuitSize, paths[suit]);
        ctx.fill();
        ctx.restore();
        ctx.fillText(value, originPoint.x + textOffset, originPoint.y);
        ctx.restore();
        ctx.save();
        ctx.beginPath();
        drawPath(ctx, centerSuitSize, paths[suit]);
        ctx.fillStyle = color;
        ctx.fill();
        ctx.restore();
        ctx.beginPath();
        ctx.arc(originPoint.x, originPoint.y, minRadius$6, minAngle$5, doublePI, false);
        ctx.closePath();
        ctx.restore();
    }
    function drawCardBody(ctx, radius) {
        const cardWidth = radius * cardWidthRatio, cardHeight = radius * cardHeightRatio, halfWidth = cardWidth * half$2, halfHeight = cardHeight * half$2, cornerRadius = radius * cornerRadiusRatio;
        ctx.beginPath();
        ctx.moveTo(-halfWidth + cornerRadius, -halfHeight);
        ctx.lineTo(halfWidth - cornerRadius, -halfHeight);
        ctx.quadraticCurveTo(halfWidth, -halfHeight, halfWidth, -halfHeight + cornerRadius);
        ctx.lineTo(halfWidth, halfHeight - cornerRadius);
        ctx.quadraticCurveTo(halfWidth, halfHeight, halfWidth - cornerRadius, halfHeight);
        ctx.lineTo(-halfWidth + cornerRadius, halfHeight);
        ctx.quadraticCurveTo(-halfWidth, halfHeight, -halfWidth, halfHeight - cornerRadius);
        ctx.lineTo(-halfWidth, -halfHeight + cornerRadius);
        ctx.quadraticCurveTo(-halfWidth, -halfHeight, -halfWidth + cornerRadius, -halfHeight);
        ctx.closePath();
    }

    class CardDrawer {
        #container;
        constructor(container) {
            this.#container = container;
        }
        draw(data) {
            const { context, particle, opacity, radius } = data;
            if (!particle.cardData) {
                return;
            }
            const defaultOpacity = context.globalAlpha, container = this.#container;
            context.globalAlpha = opacity;
            drawRoundedCard(context, radius, particle.cardData, container.hdr, particle.isShowingBack(), container.canvas.render.settings, container.peakNits, container.hdrMode);
            context.globalAlpha = defaultOpacity;
        }
        particleInit(_container, particle) {
            const shape = particle.shapeData;
            if (!shape) {
                return;
            }
            particle.cardData = deepExtend({}, shape);
        }
    }

    async function loadFullCardsShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["card"], container => Promise.resolve(new CardDrawer(container)));
        });
    }

    async function loadCardsShape(engine) {
        engine.checkVersion("4.4.0");
        await Promise.all([
            loadFullCardsShape(engine),
            loadCardSuitsShape(engine),
        ]);
    }

    const minAngle$4 = 0, taperFactor = 0.005;
    function drawCogHole(data) {
        const { context, particle, radius } = data;
        if (particle.cogHoleRadius === undefined ||
            particle.cogInnerRadius === undefined ||
            particle.cogInnerTaper === undefined ||
            particle.cogNotches === undefined ||
            particle.cogOuterTaper === undefined) {
            return;
        }
        const holeRadius = (radius * particle.cogHoleRadius) / percentDenominator;
        context.globalCompositeOperation = "destination-out";
        context.beginPath();
        context.moveTo(holeRadius, originPoint.y);
        context.arc(originPoint.x, originPoint.y, holeRadius, minAngle$4, doublePI);
        context.closePath();
        context.fill();
        context.globalCompositeOperation = "source-over";
    }
    function drawCog(data) {
        const { context, particle, radius } = data;
        if (particle.cogHoleRadius === undefined ||
            particle.cogInnerRadius === undefined ||
            particle.cogInnerTaper === undefined ||
            particle.cogNotches === undefined ||
            particle.cogOuterTaper === undefined) {
            return;
        }
        const angle = doublePI / (particle.cogNotches * double), taperAI = angle * particle.cogInnerTaper * taperFactor, taperAO = angle * particle.cogOuterTaper * taperFactor, innerRadius = (radius * particle.cogInnerRadius) / percentDenominator;
        let a = angle, toggle = false;
        context.moveTo(radius * Math.cos(taperAO), radius * Math.sin(taperAO));
        for (; a <= doublePI; a += angle) {
            if (toggle) {
                context.lineTo(innerRadius * Math.cos(a - taperAI), innerRadius * Math.sin(a - taperAI));
                context.lineTo(radius * Math.cos(a + taperAO), radius * Math.sin(a + taperAO));
            }
            else {
                context.lineTo(radius * Math.cos(a - taperAO), radius * Math.sin(a - taperAO));
                context.lineTo(innerRadius * Math.cos(a + taperAI), innerRadius * Math.sin(a + taperAI));
            }
            toggle = !toggle;
        }
    }

    const defaultHoleRadius = 44, defaultInnerRadius$1 = 72, defaultInnerTaper = 35, defaultNotches = 7, defaultOuterTaper = 50;
    class CogDrawer {
        afterDraw(data) {
            drawCogHole(data);
        }
        draw(data) {
            drawCog(data);
        }
        particleInit(_container, particle) {
            const shapeData = particle.shapeData;
            particle.cogHoleRadius = getRangeValue(shapeData?.holeRadius ?? defaultHoleRadius);
            particle.cogInnerRadius = getRangeValue(shapeData?.innerRadius ?? defaultInnerRadius$1);
            particle.cogInnerTaper = getRangeValue(shapeData?.innerTaper ?? defaultInnerTaper);
            particle.cogNotches = getRangeValue(shapeData?.notches ?? defaultNotches);
            particle.cogOuterTaper = getRangeValue(shapeData?.outerTaper ?? defaultOuterTaper);
        }
    }

    async function loadCogShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["cog"], () => Promise.resolve(new CogDrawer()));
        });
    }

    function shuffleSeed(seed) {
        const newSeed = new Uint32Array(1);
        newSeed[0] = seed[0] * 1664525 + 1013904223;
        return newSeed;
    }

    const half$1 = 0.5;
    class SimplexNoise2D {
        #NORM_2D;
        #SQUISH_2D;
        #STRETCH_2D;
        #base2D;
        #gradients2D;
        #lookup;
        #lookupPairs2D;
        #p2D;
        #perm;
        #perm2D;
        constructor() {
            this.#NORM_2D = 1 / 47;
            this.#SQUISH_2D = (Math.sqrt(2 + 1) - 1) * half$1;
            this.#STRETCH_2D = (1 / Math.sqrt(2 + 1) - 1) * half$1;
            this.#base2D = [
                [1, 1, 0, 1, 0, 1, 0, 0, 0],
                [1, 1, 0, 1, 0, 1, 2, 1, 1],
            ];
            this.#gradients2D = [
                5,
                2,
                2,
                5,
                -5,
                2,
                -2,
                5,
                5,
                -2,
                2,
                -5,
                -5,
                -2,
                -2,
                -5,
            ];
            this.#lookup = [];
            this.#lookupPairs2D = [
                0,
                1,
                1,
                0,
                4,
                1,
                17,
                0,
                20,
                2,
                21,
                2,
                22,
                5,
                23,
                5,
                26,
                4,
                39,
                3,
                42,
                4,
                43,
                3,
            ];
            this.#p2D = [
                0,
                0,
                1,
                -1,
                0,
                0,
                -1,
                1,
                0,
                2,
                1,
                1,
                1,
                2,
                2,
                0,
                1,
                2,
                0,
                2,
                1,
                0,
                0,
                0,
            ];
            this.#perm = new Uint8Array(256);
            this.#perm2D = new Uint8Array(256);
        }
        noise(x, y) {
            const gradients2D = this.#gradients2D, NORM_2D = this.#NORM_2D, SQUISH_2D = this.#SQUISH_2D, STRETCH_2D = this.#STRETCH_2D, lookup = this.#lookup, perm = this.#perm, perm2D = this.#perm2D, stretchOffset = (x + y) * STRETCH_2D, xs = x + stretchOffset, ys = y + stretchOffset, xsb = Math.floor(xs), ysb = Math.floor(ys), squishOffset = (xsb + ysb) * SQUISH_2D, dx0 = x - (xsb + squishOffset), dy0 = y - (ysb + squishOffset), xins = xs - xsb, yins = ys - ysb, inSum = xins + yins, hash = (xins - yins + 1) | (inSum << 1) | ((inSum + yins) << 2) | ((inSum + xins) << 4);
            let value = 0;
            for (let c = lookup[hash]; c !== undefined; c = c.next) {
                const dx = dx0 + c.dx, dy = dy0 + c.dy, attn = 2 - dx * dx - dy * dy;
                if (attn <= 0) {
                    continue;
                }
                const px = xsb + c.xsb, py = ysb + c.ysb, indexPartA = perm[px & 0xff], index = perm2D[(indexPartA + py) & 0xff], valuePart = gradients2D[index] * dx + gradients2D[index + 1] * dy;
                value += attn * attn * attn * attn * valuePart;
            }
            return value * NORM_2D;
        }
        seed(clientSeed) {
            const p2D = this.#p2D, base2D = this.#base2D, lookupPairs2D = this.#lookupPairs2D, contributions = [];
            for (let i = 0; i < p2D.length; i += 4) {
                const baseSet = base2D[p2D[i]];
                let previous = null, current = null;
                for (let k = 0; k < baseSet.length; k += 3) {
                    current = this.#contribution2D(baseSet[k], baseSet[k + 1], baseSet[k + 2]);
                    if (previous === null) {
                        contributions[i / 4] = current;
                    }
                    else {
                        previous.next = current;
                    }
                    previous = current;
                }
                if (current) {
                    current.next = this.#contribution2D(p2D[i + 1], p2D[i + 2], p2D[i + 3]);
                }
            }
            this.#lookup = [];
            for (let i = 0; i < lookupPairs2D.length; i += 2) {
                this.#lookup[lookupPairs2D[i]] = contributions[lookupPairs2D[i + 1]];
            }
            this.#perm = new Uint8Array(256);
            this.#perm2D = new Uint8Array(256);
            const source = new Uint8Array(256);
            for (let i = 0; i < 256; i++) {
                source[i] = i;
            }
            let seed = new Uint32Array(1);
            seed[0] = clientSeed;
            seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));
            for (let i = 255; i >= 0; i--) {
                seed = shuffleSeed(seed);
                const r = new Uint32Array(1);
                r[0] = (seed[0] + 31) % (i + 1);
                if (r[0] < 0) {
                    r[0] += i + 1;
                }
                this.#perm[i] = source[r[0]];
                this.#perm2D[i] = this.#perm[i] & 0x0e;
                source[r[0]] = source[i];
            }
        }
        #contribution2D(multiplier, xsb, ysb) {
            const SQUISH_2D = this.#SQUISH_2D;
            return {
                dx: -xsb - multiplier * SQUISH_2D,
                dy: -ysb - multiplier * SQUISH_2D,
                xsb,
                ysb,
            };
        }
    }

    const third = 1 / 3;
    class SimplexNoise3D {
        #NORM_3D;
        #SQUISH_3D;
        #STRETCH_3D;
        #base3D;
        #gradients3D;
        #lookup;
        #lookupPairs3D;
        #p3D;
        #perm;
        #perm3D;
        constructor() {
            this.#NORM_3D = 1 / 103;
            this.#SQUISH_3D = (Math.sqrt(3 + 1) - 1) * third;
            this.#STRETCH_3D = (1 / Math.sqrt(3 + 1) - 1) * third;
            this.#base3D = [
                [0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1],
                [2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1, 3, 1, 1, 1],
                [1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1],
            ];
            this.#gradients3D = [
                -11,
                4,
                4,
                -4,
                11,
                4,
                -4,
                4,
                11,
                11,
                4,
                4,
                4,
                11,
                4,
                4,
                4,
                11,
                -11,
                -4,
                4,
                -4,
                -11,
                4,
                -4,
                -4,
                11,
                11,
                -4,
                4,
                4,
                -11,
                4,
                4,
                -4,
                11,
                -11,
                4,
                -4,
                -4,
                11,
                -4,
                -4,
                4,
                -11,
                11,
                4,
                -4,
                4,
                11,
                -4,
                4,
                4,
                -11,
                -11,
                -4,
                -4,
                -4,
                -11,
                -4,
                -4,
                -4,
                -11,
                11,
                -4,
                -4,
                4,
                -11,
                -4,
                4,
                -4,
                -11,
            ];
            this.#lookup = [];
            this.#lookupPairs3D = [
                0,
                2,
                1,
                1,
                2,
                2,
                5,
                1,
                6,
                0,
                7,
                0,
                32,
                2,
                34,
                2,
                129,
                1,
                133,
                1,
                160,
                5,
                161,
                5,
                518,
                0,
                519,
                0,
                546,
                4,
                550,
                4,
                645,
                3,
                647,
                3,
                672,
                5,
                673,
                5,
                674,
                4,
                677,
                3,
                678,
                4,
                679,
                3,
                680,
                13,
                681,
                13,
                682,
                12,
                685,
                14,
                686,
                12,
                687,
                14,
                712,
                20,
                714,
                18,
                809,
                21,
                813,
                23,
                840,
                20,
                841,
                21,
                1198,
                19,
                1199,
                22,
                1226,
                18,
                1230,
                19,
                1325,
                23,
                1327,
                22,
                1352,
                15,
                1353,
                17,
                1354,
                15,
                1357,
                17,
                1358,
                16,
                1359,
                16,
                1360,
                11,
                1361,
                10,
                1362,
                11,
                1365,
                10,
                1366,
                9,
                1367,
                9,
                1392,
                11,
                1394,
                11,
                1489,
                10,
                1493,
                10,
                1520,
                8,
                1521,
                8,
                1878,
                9,
                1879,
                9,
                1906,
                7,
                1910,
                7,
                2005,
                6,
                2007,
                6,
                2032,
                8,
                2033,
                8,
                2034,
                7,
                2037,
                6,
                2038,
                7,
                2039,
                6,
            ];
            this.#p3D = [
                0,
                0,
                1,
                -1,
                0,
                0,
                1,
                0,
                -1,
                0,
                0,
                -1,
                1,
                0,
                0,
                0,
                1,
                -1,
                0,
                0,
                -1,
                0,
                1,
                0,
                0,
                -1,
                1,
                0,
                2,
                1,
                1,
                0,
                1,
                1,
                1,
                -1,
                0,
                2,
                1,
                0,
                1,
                1,
                1,
                -1,
                1,
                0,
                2,
                0,
                1,
                1,
                1,
                -1,
                1,
                1,
                1,
                3,
                2,
                1,
                0,
                3,
                1,
                2,
                0,
                1,
                3,
                2,
                0,
                1,
                3,
                1,
                0,
                2,
                1,
                3,
                0,
                2,
                1,
                3,
                0,
                1,
                2,
                1,
                1,
                1,
                0,
                0,
                2,
                2,
                0,
                0,
                1,
                1,
                0,
                1,
                0,
                2,
                0,
                2,
                0,
                1,
                1,
                0,
                0,
                1,
                2,
                0,
                0,
                2,
                2,
                0,
                0,
                0,
                0,
                1,
                1,
                -1,
                1,
                2,
                0,
                0,
                0,
                0,
                1,
                -1,
                1,
                1,
                2,
                0,
                0,
                0,
                0,
                1,
                1,
                1,
                -1,
                2,
                3,
                1,
                1,
                1,
                2,
                0,
                0,
                2,
                2,
                3,
                1,
                1,
                1,
                2,
                2,
                0,
                0,
                2,
                3,
                1,
                1,
                1,
                2,
                0,
                2,
                0,
                2,
                1,
                1,
                -1,
                1,
                2,
                0,
                0,
                2,
                2,
                1,
                1,
                -1,
                1,
                2,
                2,
                0,
                0,
                2,
                1,
                -1,
                1,
                1,
                2,
                0,
                0,
                2,
                2,
                1,
                -1,
                1,
                1,
                2,
                0,
                2,
                0,
                2,
                1,
                1,
                1,
                -1,
                2,
                2,
                0,
                0,
                2,
                1,
                1,
                1,
                -1,
                2,
                0,
                2,
                0,
            ];
            this.#perm = new Uint8Array(256);
            this.#perm3D = new Uint8Array(256);
        }
        noise(x, y, z) {
            const STRETCH_3D = this.#STRETCH_3D, NORM_3D = this.#NORM_3D, SQUISH_3D = this.#SQUISH_3D, lookup = this.#lookup, perm = this.#perm, perm3D = this.#perm3D, gradients3D = this.#gradients3D, stretchOffset = (x + y + z) * STRETCH_3D, xs = x + stretchOffset, ys = y + stretchOffset, zs = z + stretchOffset, xsb = Math.floor(xs), ysb = Math.floor(ys), zsb = Math.floor(zs), squishOffset = (xsb + ysb + zsb) * SQUISH_3D, dx0 = x - (xsb + squishOffset), dy0 = y - (ysb + squishOffset), dz0 = z - (zsb + squishOffset), xins = xs - xsb, yins = ys - ysb, zins = zs - zsb, inSum = xins + yins + zins, hash = (yins - zins + 1) |
                ((xins - yins + 1) << 1) |
                ((xins - zins + 1) << 2) |
                (inSum << 3) |
                ((inSum + zins) << 5) |
                ((inSum + yins) << 7) |
                ((inSum + xins) << 9);
            let value = 0;
            for (let c = lookup[hash]; c !== undefined; c = c.next) {
                const dx = dx0 + c.dx, dy = dy0 + c.dy, dz = dz0 + c.dz, attn = 2 - dx * dx - dy * dy - dz * dz;
                if (attn > 0) {
                    const px = xsb + c.xsb, py = ysb + c.ysb, pz = zsb + c.zsb, indexPartA = perm[px & 0xff], indexPartB = perm[(indexPartA + py) & 0xff], index = perm3D[(indexPartB + pz) & 0xff], valuePart = gradients3D[index] * dx + gradients3D[index + 1] * dy + gradients3D[index + 2] * dz;
                    value += attn * attn * attn * attn * valuePart;
                }
            }
            return value * NORM_3D;
        }
        seed(clientSeed) {
            const base3D = this.#base3D, lookupPairs3D = this.#lookupPairs3D, p3D = this.#p3D, contributions = [];
            for (let i = 0; i < p3D.length; i += 9) {
                const baseSet = base3D[p3D[i]];
                let previous = null, current = null;
                for (let k = 0; k < baseSet.length; k += 4) {
                    current = this.#contribution3D(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3]);
                    if (previous === null) {
                        contributions[i / 9] = current;
                    }
                    else {
                        previous.next = current;
                    }
                    previous = current;
                }
                if (current) {
                    current.next = this.#contribution3D(p3D[i + 1], p3D[i + 2], p3D[i + 3], p3D[i + 4]);
                    current.next.next = this.#contribution3D(p3D[i + 5], p3D[i + 6], p3D[i + 7], p3D[i + 8]);
                }
            }
            this.#lookup = [];
            for (let i = 0; i < lookupPairs3D.length; i += 2) {
                this.#lookup[lookupPairs3D[i]] = contributions[lookupPairs3D[i + 1]];
            }
            this.#perm = new Uint8Array(256);
            this.#perm3D = new Uint8Array(256);
            const source = new Uint8Array(256);
            for (let i = 0; i < 256; i++) {
                source[i] = i;
            }
            let seed = new Uint32Array(1);
            seed[0] = clientSeed;
            seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));
            for (let i = 255; i >= 0; i--) {
                seed = shuffleSeed(seed);
                const r = new Uint32Array(1);
                r[0] = (seed[0] + 31) % (i + 1);
                if (r[0] < 0) {
                    r[0] += i + 1;
                }
                this.#perm[i] = source[r[0]];
                this.#perm3D[i] = (this.#perm[i] % 24) * 3;
                source[r[0]] = source[i];
            }
        }
        #contribution3D(multiplier, xsb, ysb, zsb) {
            const SQUISH_3D = this.#SQUISH_3D;
            return {
                dx: -xsb - multiplier * SQUISH_3D,
                dy: -ysb - multiplier * SQUISH_3D,
                dz: -zsb - multiplier * SQUISH_3D,
                xsb,
                ysb,
                zsb,
            };
        }
    }

    const quarter$1 = 0.25;
    class SimplexNoise4D {
        #NORM_4D;
        #SQUISH_4D;
        #STRETCH_4D;
        #base4D;
        #gradients4D;
        #lookup;
        #lookupPairs4D;
        #p4D;
        #perm;
        #perm4D;
        constructor() {
            this.#NORM_4D = 1 / 30;
            this.#SQUISH_4D = (Math.sqrt(4 + 1) - 1) * quarter$1;
            this.#STRETCH_4D = (1 / Math.sqrt(4 + 1) - 1) * quarter$1;
            this.#lookup = [];
            this.#perm = new Uint8Array(0);
            this.#perm4D = new Uint8Array(0);
            this.#base4D = [
                [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1],
                [3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 4, 1, 1, 1, 1],
                [
                    1,
                    1,
                    0,
                    0,
                    0,
                    1,
                    0,
                    1,
                    0,
                    0,
                    1,
                    0,
                    0,
                    1,
                    0,
                    1,
                    0,
                    0,
                    0,
                    1,
                    2,
                    1,
                    1,
                    0,
                    0,
                    2,
                    1,
                    0,
                    1,
                    0,
                    2,
                    1,
                    0,
                    0,
                    1,
                    2,
                    0,
                    1,
                    1,
                    0,
                    2,
                    0,
                    1,
                    0,
                    1,
                    2,
                    0,
                    0,
                    1,
                    1,
                ],
                [
                    3,
                    1,
                    1,
                    1,
                    0,
                    3,
                    1,
                    1,
                    0,
                    1,
                    3,
                    1,
                    0,
                    1,
                    1,
                    3,
                    0,
                    1,
                    1,
                    1,
                    2,
                    1,
                    1,
                    0,
                    0,
                    2,
                    1,
                    0,
                    1,
                    0,
                    2,
                    1,
                    0,
                    0,
                    1,
                    2,
                    0,
                    1,
                    1,
                    0,
                    2,
                    0,
                    1,
                    0,
                    1,
                    2,
                    0,
                    0,
                    1,
                    1,
                ],
            ];
            this.#gradients4D = [
                3,
                1,
                1,
                1,
                1,
                3,
                1,
                1,
                1,
                1,
                3,
                1,
                1,
                1,
                1,
                3,
                -3,
                1,
                1,
                1,
                -1,
                3,
                1,
                1,
                -1,
                1,
                3,
                1,
                -1,
                1,
                1,
                3,
                3,
                -1,
                1,
                1,
                1,
                -3,
                1,
                1,
                1,
                -1,
                3,
                1,
                1,
                -1,
                1,
                3,
                -3,
                -1,
                1,
                1,
                -1,
                -3,
                1,
                1,
                -1,
                -1,
                3,
                1,
                -1,
                -1,
                1,
                3,
                3,
                1,
                -1,
                1,
                1,
                3,
                -1,
                1,
                1,
                1,
                -3,
                1,
                1,
                1,
                -1,
                3,
                -3,
                1,
                -1,
                1,
                -1,
                3,
                -1,
                1,
                -1,
                1,
                -3,
                1,
                -1,
                1,
                -1,
                3,
                3,
                -1,
                -1,
                1,
                1,
                -3,
                -1,
                1,
                1,
                -1,
                -3,
                1,
                1,
                -1,
                -1,
                3,
                -3,
                -1,
                -1,
                1,
                -1,
                -3,
                -1,
                1,
                -1,
                -1,
                -3,
                1,
                -1,
                -1,
                -1,
                3,
                3,
                1,
                1,
                -1,
                1,
                3,
                1,
                -1,
                1,
                1,
                3,
                -1,
                1,
                1,
                1,
                -3,
                -3,
                1,
                1,
                -1,
                -1,
                3,
                1,
                -1,
                -1,
                1,
                3,
                -1,
                -1,
                1,
                1,
                -3,
                3,
                -1,
                1,
                -1,
                1,
                -3,
                1,
                -1,
                1,
                -1,
                3,
                -1,
                1,
                -1,
                1,
                -3,
                -3,
                -1,
                1,
                -1,
                -1,
                -3,
                1,
                -1,
                -1,
                -1,
                3,
                -1,
                -1,
                -1,
                1,
                -3,
                3,
                1,
                -1,
                -1,
                1,
                3,
                -1,
                -1,
                1,
                1,
                -3,
                -1,
                1,
                1,
                -1,
                -3,
                -3,
                1,
                -1,
                -1,
                -1,
                3,
                -1,
                -1,
                -1,
                1,
                -3,
                -1,
                -1,
                1,
                -1,
                -3,
                3,
                -1,
                -1,
                -1,
                1,
                -3,
                -1,
                -1,
                1,
                -1,
                -3,
                -1,
                1,
                -1,
                -1,
                -3,
                -3,
                -1,
                -1,
                -1,
                -1,
                -3,
                -1,
                -1,
                -1,
                -1,
                -3,
                -1,
                -1,
                -1,
                -1,
                -3,
            ];
            this.#lookupPairs4D = [
                0,
                3,
                1,
                2,
                2,
                3,
                5,
                2,
                6,
                1,
                7,
                1,
                8,
                3,
                9,
                2,
                10,
                3,
                13,
                2,
                16,
                3,
                18,
                3,
                22,
                1,
                23,
                1,
                24,
                3,
                26,
                3,
                33,
                2,
                37,
                2,
                38,
                1,
                39,
                1,
                41,
                2,
                45,
                2,
                54,
                1,
                55,
                1,
                56,
                0,
                57,
                0,
                58,
                0,
                59,
                0,
                60,
                0,
                61,
                0,
                62,
                0,
                63,
                0,
                256,
                3,
                258,
                3,
                264,
                3,
                266,
                3,
                272,
                3,
                274,
                3,
                280,
                3,
                282,
                3,
                2049,
                2,
                2053,
                2,
                2057,
                2,
                2061,
                2,
                2081,
                2,
                2085,
                2,
                2089,
                2,
                2093,
                2,
                2304,
                9,
                2305,
                9,
                2312,
                9,
                2313,
                9,
                16390,
                1,
                16391,
                1,
                16406,
                1,
                16407,
                1,
                16422,
                1,
                16423,
                1,
                16438,
                1,
                16439,
                1,
                16642,
                8,
                16646,
                8,
                16658,
                8,
                16662,
                8,
                18437,
                6,
                18439,
                6,
                18469,
                6,
                18471,
                6,
                18688,
                9,
                18689,
                9,
                18690,
                8,
                18693,
                6,
                18694,
                8,
                18695,
                6,
                18696,
                9,
                18697,
                9,
                18706,
                8,
                18710,
                8,
                18725,
                6,
                18727,
                6,
                131128,
                0,
                131129,
                0,
                131130,
                0,
                131131,
                0,
                131132,
                0,
                131133,
                0,
                131134,
                0,
                131135,
                0,
                131352,
                7,
                131354,
                7,
                131384,
                7,
                131386,
                7,
                133161,
                5,
                133165,
                5,
                133177,
                5,
                133181,
                5,
                133376,
                9,
                133377,
                9,
                133384,
                9,
                133385,
                9,
                133400,
                7,
                133402,
                7,
                133417,
                5,
                133421,
                5,
                133432,
                7,
                133433,
                5,
                133434,
                7,
                133437,
                5,
                147510,
                4,
                147511,
                4,
                147518,
                4,
                147519,
                4,
                147714,
                8,
                147718,
                8,
                147730,
                8,
                147734,
                8,
                147736,
                7,
                147738,
                7,
                147766,
                4,
                147767,
                4,
                147768,
                7,
                147770,
                7,
                147774,
                4,
                147775,
                4,
                149509,
                6,
                149511,
                6,
                149541,
                6,
                149543,
                6,
                149545,
                5,
                149549,
                5,
                149558,
                4,
                149559,
                4,
                149561,
                5,
                149565,
                5,
                149566,
                4,
                149567,
                4,
                149760,
                9,
                149761,
                9,
                149762,
                8,
                149765,
                6,
                149766,
                8,
                149767,
                6,
                149768,
                9,
                149769,
                9,
                149778,
                8,
                149782,
                8,
                149784,
                7,
                149786,
                7,
                149797,
                6,
                149799,
                6,
                149801,
                5,
                149805,
                5,
                149814,
                4,
                149815,
                4,
                149816,
                7,
                149817,
                5,
                149818,
                7,
                149821,
                5,
                149822,
                4,
                149823,
                4,
                149824,
                37,
                149825,
                37,
                149826,
                36,
                149829,
                34,
                149830,
                36,
                149831,
                34,
                149832,
                37,
                149833,
                37,
                149842,
                36,
                149846,
                36,
                149848,
                35,
                149850,
                35,
                149861,
                34,
                149863,
                34,
                149865,
                33,
                149869,
                33,
                149878,
                32,
                149879,
                32,
                149880,
                35,
                149881,
                33,
                149882,
                35,
                149885,
                33,
                149886,
                32,
                149887,
                32,
                150080,
                49,
                150082,
                48,
                150088,
                49,
                150098,
                48,
                150104,
                47,
                150106,
                47,
                151873,
                46,
                151877,
                45,
                151881,
                46,
                151909,
                45,
                151913,
                44,
                151917,
                44,
                152128,
                49,
                152129,
                46,
                152136,
                49,
                152137,
                46,
                166214,
                43,
                166215,
                42,
                166230,
                43,
                166247,
                42,
                166262,
                41,
                166263,
                41,
                166466,
                48,
                166470,
                43,
                166482,
                48,
                166486,
                43,
                168261,
                45,
                168263,
                42,
                168293,
                45,
                168295,
                42,
                168512,
                31,
                168513,
                28,
                168514,
                31,
                168517,
                28,
                168518,
                25,
                168519,
                25,
                280952,
                40,
                280953,
                39,
                280954,
                40,
                280957,
                39,
                280958,
                38,
                280959,
                38,
                281176,
                47,
                281178,
                47,
                281208,
                40,
                281210,
                40,
                282985,
                44,
                282989,
                44,
                283001,
                39,
                283005,
                39,
                283208,
                30,
                283209,
                27,
                283224,
                30,
                283241,
                27,
                283256,
                22,
                283257,
                22,
                297334,
                41,
                297335,
                41,
                297342,
                38,
                297343,
                38,
                297554,
                29,
                297558,
                24,
                297562,
                29,
                297590,
                24,
                297594,
                21,
                297598,
                21,
                299365,
                26,
                299367,
                23,
                299373,
                26,
                299383,
                23,
                299389,
                20,
                299391,
                20,
                299584,
                31,
                299585,
                28,
                299586,
                31,
                299589,
                28,
                299590,
                25,
                299591,
                25,
                299592,
                30,
                299593,
                27,
                299602,
                29,
                299606,
                24,
                299608,
                30,
                299610,
                29,
                299621,
                26,
                299623,
                23,
                299625,
                27,
                299629,
                26,
                299638,
                24,
                299639,
                23,
                299640,
                22,
                299641,
                22,
                299642,
                21,
                299645,
                20,
                299646,
                21,
                299647,
                20,
                299648,
                61,
                299649,
                60,
                299650,
                61,
                299653,
                60,
                299654,
                59,
                299655,
                59,
                299656,
                58,
                299657,
                57,
                299666,
                55,
                299670,
                54,
                299672,
                58,
                299674,
                55,
                299685,
                52,
                299687,
                51,
                299689,
                57,
                299693,
                52,
                299702,
                54,
                299703,
                51,
                299704,
                56,
                299705,
                56,
                299706,
                53,
                299709,
                50,
                299710,
                53,
                299711,
                50,
                299904,
                61,
                299906,
                61,
                299912,
                58,
                299922,
                55,
                299928,
                58,
                299930,
                55,
                301697,
                60,
                301701,
                60,
                301705,
                57,
                301733,
                52,
                301737,
                57,
                301741,
                52,
                301952,
                79,
                301953,
                79,
                301960,
                76,
                301961,
                76,
                316038,
                59,
                316039,
                59,
                316054,
                54,
                316071,
                51,
                316086,
                54,
                316087,
                51,
                316290,
                78,
                316294,
                78,
                316306,
                73,
                316310,
                73,
                318085,
                77,
                318087,
                77,
                318117,
                70,
                318119,
                70,
                318336,
                79,
                318337,
                79,
                318338,
                78,
                318341,
                77,
                318342,
                78,
                318343,
                77,
                430776,
                56,
                430777,
                56,
                430778,
                53,
                430781,
                50,
                430782,
                53,
                430783,
                50,
                431000,
                75,
                431002,
                72,
                431032,
                75,
                431034,
                72,
                432809,
                74,
                432813,
                69,
                432825,
                74,
                432829,
                69,
                433032,
                76,
                433033,
                76,
                433048,
                75,
                433065,
                74,
                433080,
                75,
                433081,
                74,
                447158,
                71,
                447159,
                68,
                447166,
                71,
                447167,
                68,
                447378,
                73,
                447382,
                73,
                447386,
                72,
                447414,
                71,
                447418,
                72,
                447422,
                71,
                449189,
                70,
                449191,
                70,
                449197,
                69,
                449207,
                68,
                449213,
                69,
                449215,
                68,
                449408,
                67,
                449409,
                67,
                449410,
                66,
                449413,
                64,
                449414,
                66,
                449415,
                64,
                449416,
                67,
                449417,
                67,
                449426,
                66,
                449430,
                66,
                449432,
                65,
                449434,
                65,
                449445,
                64,
                449447,
                64,
                449449,
                63,
                449453,
                63,
                449462,
                62,
                449463,
                62,
                449464,
                65,
                449465,
                63,
                449466,
                65,
                449469,
                63,
                449470,
                62,
                449471,
                62,
                449472,
                19,
                449473,
                19,
                449474,
                18,
                449477,
                16,
                449478,
                18,
                449479,
                16,
                449480,
                19,
                449481,
                19,
                449490,
                18,
                449494,
                18,
                449496,
                17,
                449498,
                17,
                449509,
                16,
                449511,
                16,
                449513,
                15,
                449517,
                15,
                449526,
                14,
                449527,
                14,
                449528,
                17,
                449529,
                15,
                449530,
                17,
                449533,
                15,
                449534,
                14,
                449535,
                14,
                449728,
                19,
                449729,
                19,
                449730,
                18,
                449734,
                18,
                449736,
                19,
                449737,
                19,
                449746,
                18,
                449750,
                18,
                449752,
                17,
                449754,
                17,
                449784,
                17,
                449786,
                17,
                451520,
                19,
                451521,
                19,
                451525,
                16,
                451527,
                16,
                451528,
                19,
                451529,
                19,
                451557,
                16,
                451559,
                16,
                451561,
                15,
                451565,
                15,
                451577,
                15,
                451581,
                15,
                451776,
                19,
                451777,
                19,
                451784,
                19,
                451785,
                19,
                465858,
                18,
                465861,
                16,
                465862,
                18,
                465863,
                16,
                465874,
                18,
                465878,
                18,
                465893,
                16,
                465895,
                16,
                465910,
                14,
                465911,
                14,
                465918,
                14,
                465919,
                14,
                466114,
                18,
                466118,
                18,
                466130,
                18,
                466134,
                18,
                467909,
                16,
                467911,
                16,
                467941,
                16,
                467943,
                16,
                468160,
                13,
                468161,
                13,
                468162,
                13,
                468163,
                13,
                468164,
                13,
                468165,
                13,
                468166,
                13,
                468167,
                13,
                580568,
                17,
                580570,
                17,
                580585,
                15,
                580589,
                15,
                580598,
                14,
                580599,
                14,
                580600,
                17,
                580601,
                15,
                580602,
                17,
                580605,
                15,
                580606,
                14,
                580607,
                14,
                580824,
                17,
                580826,
                17,
                580856,
                17,
                580858,
                17,
                582633,
                15,
                582637,
                15,
                582649,
                15,
                582653,
                15,
                582856,
                12,
                582857,
                12,
                582872,
                12,
                582873,
                12,
                582888,
                12,
                582889,
                12,
                582904,
                12,
                582905,
                12,
                596982,
                14,
                596983,
                14,
                596990,
                14,
                596991,
                14,
                597202,
                11,
                597206,
                11,
                597210,
                11,
                597214,
                11,
                597234,
                11,
                597238,
                11,
                597242,
                11,
                597246,
                11,
                599013,
                10,
                599015,
                10,
                599021,
                10,
                599023,
                10,
                599029,
                10,
                599031,
                10,
                599037,
                10,
                599039,
                10,
                599232,
                13,
                599233,
                13,
                599234,
                13,
                599235,
                13,
                599236,
                13,
                599237,
                13,
                599238,
                13,
                599239,
                13,
                599240,
                12,
                599241,
                12,
                599250,
                11,
                599254,
                11,
                599256,
                12,
                599257,
                12,
                599258,
                11,
                599262,
                11,
                599269,
                10,
                599271,
                10,
                599272,
                12,
                599273,
                12,
                599277,
                10,
                599279,
                10,
                599282,
                11,
                599285,
                10,
                599286,
                11,
                599287,
                10,
                599288,
                12,
                599289,
                12,
                599290,
                11,
                599293,
                10,
                599294,
                11,
                599295,
                10,
            ];
            this.#p4D = [
                0,
                0,
                1,
                -1,
                0,
                0,
                0,
                1,
                0,
                -1,
                0,
                0,
                1,
                0,
                0,
                -1,
                0,
                0,
                -1,
                1,
                0,
                0,
                0,
                0,
                1,
                -1,
                0,
                0,
                0,
                1,
                0,
                -1,
                0,
                0,
                -1,
                0,
                1,
                0,
                0,
                0,
                -1,
                1,
                0,
                0,
                0,
                0,
                1,
                -1,
                0,
                0,
                -1,
                0,
                0,
                1,
                0,
                0,
                -1,
                0,
                1,
                0,
                0,
                0,
                -1,
                1,
                0,
                2,
                1,
                1,
                0,
                0,
                1,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                0,
                2,
                1,
                0,
                1,
                0,
                1,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                0,
                2,
                0,
                1,
                1,
                0,
                1,
                -1,
                1,
                1,
                0,
                1,
                0,
                1,
                1,
                -1,
                0,
                2,
                1,
                0,
                0,
                1,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                0,
                2,
                0,
                1,
                0,
                1,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                1,
                0,
                2,
                0,
                0,
                1,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                1,
                1,
                4,
                2,
                1,
                1,
                0,
                4,
                1,
                2,
                1,
                0,
                4,
                1,
                1,
                2,
                0,
                1,
                4,
                2,
                1,
                0,
                1,
                4,
                1,
                2,
                0,
                1,
                4,
                1,
                1,
                0,
                2,
                1,
                4,
                2,
                0,
                1,
                1,
                4,
                1,
                0,
                2,
                1,
                4,
                1,
                0,
                1,
                2,
                1,
                4,
                0,
                2,
                1,
                1,
                4,
                0,
                1,
                2,
                1,
                4,
                0,
                1,
                1,
                2,
                1,
                2,
                1,
                1,
                0,
                0,
                3,
                2,
                1,
                0,
                0,
                3,
                1,
                2,
                0,
                0,
                1,
                2,
                1,
                0,
                1,
                0,
                3,
                2,
                0,
                1,
                0,
                3,
                1,
                0,
                2,
                0,
                1,
                2,
                0,
                1,
                1,
                0,
                3,
                0,
                2,
                1,
                0,
                3,
                0,
                1,
                2,
                0,
                1,
                2,
                1,
                0,
                0,
                1,
                3,
                2,
                0,
                0,
                1,
                3,
                1,
                0,
                0,
                2,
                1,
                2,
                0,
                1,
                0,
                1,
                3,
                0,
                2,
                0,
                1,
                3,
                0,
                1,
                0,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                3,
                0,
                0,
                2,
                1,
                3,
                0,
                0,
                1,
                2,
                2,
                3,
                1,
                1,
                1,
                0,
                2,
                1,
                1,
                1,
                -1,
                2,
                2,
                0,
                0,
                0,
                2,
                3,
                1,
                1,
                0,
                1,
                2,
                1,
                1,
                -1,
                1,
                2,
                2,
                0,
                0,
                0,
                2,
                3,
                1,
                0,
                1,
                1,
                2,
                1,
                -1,
                1,
                1,
                2,
                2,
                0,
                0,
                0,
                2,
                3,
                1,
                1,
                1,
                0,
                2,
                1,
                1,
                1,
                -1,
                2,
                0,
                2,
                0,
                0,
                2,
                3,
                1,
                1,
                0,
                1,
                2,
                1,
                1,
                -1,
                1,
                2,
                0,
                2,
                0,
                0,
                2,
                3,
                0,
                1,
                1,
                1,
                2,
                -1,
                1,
                1,
                1,
                2,
                0,
                2,
                0,
                0,
                2,
                3,
                1,
                1,
                1,
                0,
                2,
                1,
                1,
                1,
                -1,
                2,
                0,
                0,
                2,
                0,
                2,
                3,
                1,
                0,
                1,
                1,
                2,
                1,
                -1,
                1,
                1,
                2,
                0,
                0,
                2,
                0,
                2,
                3,
                0,
                1,
                1,
                1,
                2,
                -1,
                1,
                1,
                1,
                2,
                0,
                0,
                2,
                0,
                2,
                3,
                1,
                1,
                0,
                1,
                2,
                1,
                1,
                -1,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                3,
                1,
                0,
                1,
                1,
                2,
                1,
                -1,
                1,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                3,
                0,
                1,
                1,
                1,
                2,
                -1,
                1,
                1,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                1,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                0,
                0,
                0,
                0,
                0,
                2,
                1,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                0,
                0,
                0,
                0,
                0,
                2,
                1,
                -1,
                1,
                1,
                0,
                1,
                0,
                1,
                1,
                -1,
                0,
                0,
                0,
                0,
                0,
                2,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                0,
                0,
                0,
                0,
                0,
                2,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                1,
                0,
                0,
                0,
                0,
                0,
                2,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                1,
                0,
                0,
                0,
                0,
                0,
                2,
                1,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                2,
                2,
                0,
                0,
                0,
                2,
                1,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                2,
                2,
                0,
                0,
                0,
                2,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                2,
                2,
                0,
                0,
                0,
                2,
                1,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                2,
                0,
                2,
                0,
                0,
                2,
                1,
                -1,
                1,
                1,
                0,
                1,
                0,
                1,
                1,
                -1,
                2,
                0,
                2,
                0,
                0,
                2,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                1,
                2,
                0,
                2,
                0,
                0,
                2,
                1,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                2,
                0,
                0,
                2,
                0,
                2,
                1,
                -1,
                1,
                1,
                0,
                1,
                0,
                1,
                1,
                -1,
                2,
                0,
                0,
                2,
                0,
                2,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                1,
                2,
                0,
                0,
                2,
                0,
                2,
                1,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                1,
                -1,
                1,
                0,
                1,
                1,
                0,
                1,
                -1,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                1,
                -1,
                0,
                1,
                1,
                1,
                0,
                -1,
                1,
                1,
                2,
                0,
                0,
                0,
                2,
                3,
                1,
                1,
                0,
                0,
                0,
                2,
                2,
                0,
                0,
                0,
                2,
                1,
                1,
                1,
                -1,
                3,
                1,
                0,
                1,
                0,
                0,
                2,
                0,
                2,
                0,
                0,
                2,
                1,
                1,
                1,
                -1,
                3,
                1,
                0,
                0,
                1,
                0,
                2,
                0,
                0,
                2,
                0,
                2,
                1,
                1,
                1,
                -1,
                3,
                1,
                1,
                0,
                0,
                0,
                2,
                2,
                0,
                0,
                0,
                2,
                1,
                1,
                -1,
                1,
                3,
                1,
                0,
                1,
                0,
                0,
                2,
                0,
                2,
                0,
                0,
                2,
                1,
                1,
                -1,
                1,
                3,
                1,
                0,
                0,
                0,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                1,
                1,
                -1,
                1,
                3,
                1,
                1,
                0,
                0,
                0,
                2,
                2,
                0,
                0,
                0,
                2,
                1,
                -1,
                1,
                1,
                3,
                1,
                0,
                0,
                1,
                0,
                2,
                0,
                0,
                2,
                0,
                2,
                1,
                -1,
                1,
                1,
                3,
                1,
                0,
                0,
                0,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                1,
                -1,
                1,
                1,
                3,
                1,
                0,
                1,
                0,
                0,
                2,
                0,
                2,
                0,
                0,
                2,
                -1,
                1,
                1,
                1,
                3,
                1,
                0,
                0,
                1,
                0,
                2,
                0,
                0,
                2,
                0,
                2,
                -1,
                1,
                1,
                1,
                3,
                1,
                0,
                0,
                0,
                1,
                2,
                0,
                0,
                0,
                2,
                2,
                -1,
                1,
                1,
                1,
                3,
                3,
                2,
                1,
                0,
                0,
                3,
                1,
                2,
                0,
                0,
                4,
                1,
                1,
                1,
                1,
                3,
                3,
                2,
                0,
                1,
                0,
                3,
                1,
                0,
                2,
                0,
                4,
                1,
                1,
                1,
                1,
                3,
                3,
                0,
                2,
                1,
                0,
                3,
                0,
                1,
                2,
                0,
                4,
                1,
                1,
                1,
                1,
                3,
                3,
                2,
                0,
                0,
                1,
                3,
                1,
                0,
                0,
                2,
                4,
                1,
                1,
                1,
                1,
                3,
                3,
                0,
                2,
                0,
                1,
                3,
                0,
                1,
                0,
                2,
                4,
                1,
                1,
                1,
                1,
                3,
                3,
                0,
                0,
                2,
                1,
                3,
                0,
                0,
                1,
                2,
                4,
                1,
                1,
                1,
                1,
                3,
                3,
                2,
                1,
                0,
                0,
                3,
                1,
                2,
                0,
                0,
                2,
                1,
                1,
                1,
                -1,
                3,
                3,
                2,
                0,
                1,
                0,
                3,
                1,
                0,
                2,
                0,
                2,
                1,
                1,
                1,
                -1,
                3,
                3,
                0,
                2,
                1,
                0,
                3,
                0,
                1,
                2,
                0,
                2,
                1,
                1,
                1,
                -1,
                3,
                3,
                2,
                1,
                0,
                0,
                3,
                1,
                2,
                0,
                0,
                2,
                1,
                1,
                -1,
                1,
                3,
                3,
                2,
                0,
                0,
                1,
                3,
                1,
                0,
                0,
                2,
                2,
                1,
                1,
                -1,
                1,
                3,
                3,
                0,
                2,
                0,
                1,
                3,
                0,
                1,
                0,
                2,
                2,
                1,
                1,
                -1,
                1,
                3,
                3,
                2,
                0,
                1,
                0,
                3,
                1,
                0,
                2,
                0,
                2,
                1,
                -1,
                1,
                1,
                3,
                3,
                2,
                0,
                0,
                1,
                3,
                1,
                0,
                0,
                2,
                2,
                1,
                -1,
                1,
                1,
                3,
                3,
                0,
                0,
                2,
                1,
                3,
                0,
                0,
                1,
                2,
                2,
                1,
                -1,
                1,
                1,
                3,
                3,
                0,
                2,
                1,
                0,
                3,
                0,
                1,
                2,
                0,
                2,
                -1,
                1,
                1,
                1,
                3,
                3,
                0,
                2,
                0,
                1,
                3,
                0,
                1,
                0,
                2,
                2,
                -1,
                1,
                1,
                1,
                3,
                3,
                0,
                0,
                2,
                1,
                3,
                0,
                0,
                1,
                2,
                2,
                -1,
                1,
                1,
                1,
            ];
        }
        noise(x, y, z, w) {
            const perm = this.#perm, perm4D = this.#perm4D, lookup = this.#lookup, STRETCH_4D = this.#STRETCH_4D, SQUISH_4D = this.#SQUISH_4D, gradients4D = this.#gradients4D, NORM_4D = this.#NORM_4D, stretchOffset = (x + y + z + w) * STRETCH_4D, xs = x + stretchOffset, ys = y + stretchOffset, zs = z + stretchOffset, ws = w + stretchOffset, xsb = Math.floor(xs), ysb = Math.floor(ys), zsb = Math.floor(zs), wsb = Math.floor(ws), squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_4D, dx0 = x - (xsb + squishOffset), dy0 = y - (ysb + squishOffset), dz0 = z - (zsb + squishOffset), dw0 = w - (wsb + squishOffset), xins = xs - xsb, yins = ys - ysb, zins = zs - zsb, wins = ws - wsb, inSum = xins + yins + zins + wins, hash = (zins - wins + 1) |
                ((yins - zins + 1) << 1) |
                ((yins - wins + 1) << 2) |
                ((xins - yins + 1) << 3) |
                ((xins - zins + 1) << 4) |
                ((xins - wins + 1) << 5) |
                (inSum << 6) |
                ((inSum + wins) << 8) |
                ((inSum + zins) << 11) |
                ((inSum + yins) << 14) |
                ((inSum + xins) << 17);
            let value = 0;
            for (let c = lookup[hash]; c !== undefined; c = c.next) {
                const dx = dx0 + c.dx, dy = dy0 + c.dy, dz = dz0 + c.dz, dw = dw0 + c.dw, attn = 2 - dx * dx - dy * dy - dz * dz - dw * dw;
                if (attn > 0) {
                    const px = xsb + c.xsb, py = ysb + c.ysb, pz = zsb + c.zsb, pw = wsb + c.wsb, indexPartA = perm[px & 0xff], indexPartB = perm[(indexPartA + py) & 0xff], indexPartC = perm[(indexPartB + pz) & 0xff], index = perm4D[(indexPartC + pw) & 0xff], valuePart = gradients4D[index] * dx +
                        gradients4D[index + 1] * dy +
                        gradients4D[index + 2] * dz +
                        gradients4D[index + 3] * dw;
                    value += attn * attn * attn * attn * valuePart;
                }
            }
            return value * NORM_4D;
        }
        seed(clientSeed) {
            const p4D = this.#p4D, base4D = this.#base4D, lookupPairs4D = this.#lookupPairs4D, contributions = [];
            for (let i = 0; i < p4D.length; i += 16) {
                const baseSet = base4D[p4D[i]];
                let previous = null, current = null;
                for (let k = 0; k < baseSet.length; k += 5) {
                    current = this.#contribution4D(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3], baseSet[k + 4]);
                    if (previous === null) {
                        contributions[i / 16] = current;
                    }
                    else {
                        previous.next = current;
                    }
                    previous = current;
                }
                if (current) {
                    current.next = this.#contribution4D(p4D[i + 1], p4D[i + 2], p4D[i + 3], p4D[i + 4], p4D[i + 5]);
                    current.next.next = this.#contribution4D(p4D[i + 6], p4D[i + 7], p4D[i + 8], p4D[i + 9], p4D[i + 10]);
                    current.next.next.next = this.#contribution4D(p4D[i + 11], p4D[i + 12], p4D[i + 13], p4D[i + 14], p4D[i + 15]);
                }
            }
            this.#lookup = [];
            for (let i = 0; i < lookupPairs4D.length; i += 2) {
                this.#lookup[lookupPairs4D[i]] = contributions[lookupPairs4D[i + 1]];
            }
            this.#perm = new Uint8Array(256);
            this.#perm4D = new Uint8Array(256);
            const source = new Uint8Array(256);
            for (let i = 0; i < 256; i++) {
                source[i] = i;
            }
            let seed = new Uint32Array(1);
            seed[0] = clientSeed;
            seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));
            for (let i = 255; i >= 0; i--) {
                seed = shuffleSeed(seed);
                const r = new Uint32Array(1);
                r[0] = (seed[0] + 31) % (i + 1);
                if (r[0] < 0) {
                    r[0] += i + 1;
                }
                this.#perm[i] = source[r[0]];
                this.#perm4D[i] = this.#perm[i] & 0xfc;
                source[r[0]] = source[i];
            }
        }
        #contribution4D(multiplier, xsb, ysb, zsb, wsb) {
            const SQUISH_4D = this.#SQUISH_4D;
            return {
                dx: -xsb - multiplier * SQUISH_4D,
                dy: -ysb - multiplier * SQUISH_4D,
                dz: -zsb - multiplier * SQUISH_4D,
                dw: -wsb - multiplier * SQUISH_4D,
                xsb,
                ysb,
                zsb,
                wsb,
            };
        }
    }

    class SimplexNoise {
        noise2d;
        noise3d;
        noise4d;
        constructor() {
            this.noise2d = new SimplexNoise2D();
            this.noise3d = new SimplexNoise3D();
            this.noise4d = new SimplexNoise4D();
        }
    }

    const defaultOptions$5 = {
        speed: 0.2,
        step: 250,
    };
    class CurlNoiseGenerator {
        options;
        #container;
        #res;
        #simplex;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            const simplex = new SimplexNoise();
            this.#simplex = simplex.noise2d;
            this.options = deepExtend({}, defaultOptions$5);
        }
        generate(particle) {
            const pos = particle.getPosition(), { speed, step } = this.options, x = pos.x / step, y = pos.y / step, eps = 0.001, n1a = this.#simplex.noise(x, y + eps), n2a = this.#simplex.noise(x, y - eps), a = (n1a - n2a) / (double * eps), n1b = this.#simplex.noise(x + eps, y), n2b = this.#simplex.noise(x - eps, y), b = (n1b - n2b) / (double * eps);
            particle.velocity.x = 0;
            particle.velocity.y = 0;
            this.#res.x = speed * a;
            this.#res.y = speed * -b;
            return this.#res;
        }
        init() {
            const container = this.#container, sourceOptions = container.actualOptions.particles.move.path.options;
            this.options.seed = sourceOptions["seed"];
            this.options.speed =
                (sourceOptions["speed"] ?? defaultOptions$5.speed) * container.retina.pixelRatio;
            this.options.step = sourceOptions["step"] ?? defaultOptions$5.step;
            this.#simplex.seed(this.options.seed ?? getRandom());
        }
        reset() {
        }
        update() {
        }
    }

    const curlNoisePathName = "curlNoise";
    async function loadCurlNoisePath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(curlNoisePathName, container => {
                return Promise.resolve(new CurlNoiseGenerator(container));
            });
        });
    }

    function CurvesPathGen(rndFunc, period, nbHarmonics, attenHarmonics, lowValue = 0, highValue = 1) {
        const arP0 = [], arP1 = [], amplitudes = [], increments = [], phases = [], randomFunc = rndFunc ?? getRandom;
        let globAmplitude = 0;
        if (nbHarmonics < 1)
            nbHarmonics = 1;
        for (let kh = 1; kh <= nbHarmonics; ++kh) {
            arP0[kh] = randomFunc();
            arP1[kh] = randomFunc();
            amplitudes[kh] = kh === 1 ? 1 : amplitudes[kh - 1] * attenHarmonics;
            globAmplitude += amplitudes[kh];
            increments[kh] = kh / period;
            phases[kh] = randomFunc();
        }
        amplitudes.forEach((value, kh) => (amplitudes[kh] = (value / globAmplitude) * (highValue - lowValue)));
        return () => {
            let pf, pfl, signal = 0;
            for (let kh = nbHarmonics; kh >= 1; --kh) {
                pf = phases[kh] += increments[kh];
                if (phases[kh] >= 1) {
                    pf = phases[kh] -= 1;
                    arP0[kh] = arP1[kh];
                    arP1[kh] = randomFunc();
                }
                pfl = pf ** 2 * (3 - 2 * pf);
                signal += (arP0[kh] * (1 - pfl) + arP1[kh] * pfl) * amplitudes[kh];
            }
            return signal + lowValue;
        };
    }

    const defaultOptions$4 = {
        rndFunc: null,
        period: 100,
        nbHarmonics: 2,
        attenHarmonics: 0.8,
        lowValue: -0.03,
        highValue: 0.03,
    };
    function randomVelocity() {
        const offset = 0.8, factor = 0.6;
        return getRandom() * factor + offset;
    }
    class CurvesPathGenerator {
        options;
        #container;
        constructor(container) {
            this.#container = container;
            this.options = deepExtend({}, defaultOptions$4);
        }
        generate(particle) {
            if (!particle.pathGen) {
                const options = this.options;
                particle.pathGen = CurvesPathGen(options.rndFunc, options.period, options.nbHarmonics, options.attenHarmonics, options.lowValue, options.highValue);
            }
            if (particle.curveVelocity) {
                particle.curveVelocity.length += 0.01;
                particle.curveVelocity.angle = (particle.curveVelocity.angle + particle.pathGen()) % doublePI;
            }
            else {
                particle.curveVelocity = Vector.origin;
                particle.curveVelocity.length = randomVelocity();
                particle.curveVelocity.angle = getRandom() * doublePI;
            }
            particle.velocity.x = 0;
            particle.velocity.y = 0;
            return particle.curveVelocity;
        }
        init() {
            const sourceOptions = this.#container.actualOptions.particles.move.path.options;
            if (isFunction(sourceOptions["rndFunc"])) {
                this.options.rndFunc = sourceOptions["rndFunc"];
            }
            else if (isString(sourceOptions["rndFunc"])) {
                this.options.rndFunc =
                    globalThis[sourceOptions["rndFunc"]] ??
                        this.options.rndFunc;
            }
            this.options.period = sourceOptions["period"] ?? this.options.period;
            this.options.nbHarmonics = sourceOptions["nbHarmonics"] ?? this.options.nbHarmonics;
            this.options.attenHarmonics =
                sourceOptions["attenHarmonics"] ?? this.options.attenHarmonics;
            this.options.lowValue = sourceOptions["lowValue"] ?? this.options.lowValue;
            this.options.highValue = sourceOptions["highValue"] ?? this.options.highValue;
        }
        reset(particle) {
            delete particle.pathGen;
            delete particle.curveVelocity;
        }
        update() {
        }
    }

    const curvesPathName = "curvesPathGenerator";
    async function loadCurvesPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(curvesPathName, container => {
                return Promise.resolve(new CurvesPathGenerator(container));
            });
        });
    }

    const easingsFunctions$d = new Map();
    easingsFunctions$d.set("ease-in-back", value => {
        const c1 = 1.70158, c3 = c1 + 1;
        return c3 * value ** 3 - c1 * value ** 2;
    });
    easingsFunctions$d.set("ease-out-back", value => {
        const c1 = 1.70158, c3 = c1 + 1;
        return 1 + c3 * Math.pow(value - 1, 3) + c1 * Math.pow(value - 1, 2);
    });
    easingsFunctions$d.set("ease-in-out-back", value => {
        const c1 = 1.70158, c2 = c1 * 1.525;
        return value < 0.5
            ? ((2 * value) ** 2 * ((c2 + 1) * 2 * value - c2)) / 2
            : ((2 * value - 2) ** 2 * ((c2 + 1) * (value * 2 - 2) + c2) + 2) / 2;
    });

    async function loadEasingBackPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$d) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$c = new Map(), bounceOut = (t) => {
        const n1 = 7.5625, d1 = 2.75;
        if (t < 1 / d1) {
            return n1 * t * t;
        }
        else if (t < 2 / d1) {
            t -= 1.5 / d1;
            return n1 * t * t + 0.75;
        }
        else if (t < 2.5 / d1) {
            t -= 2.25 / d1;
            return n1 * t * t + 0.9375;
        }
        else {
            t -= 2.625 / d1;
            return n1 * t * t + 0.984375;
        }
    };
    easingsFunctions$c.set("ease-out-bounce", value => bounceOut(value));
    easingsFunctions$c.set("ease-in-bounce", value => 1 - bounceOut(1 - value));
    easingsFunctions$c.set("ease-in-out-bounce", value => value < 0.5 ? (1 - bounceOut(1 - value * 2)) / 2 : (1 + bounceOut(value * 2 - 1)) / 2);

    async function loadEasingBouncePlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$c) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$b = new Map();
    easingsFunctions$b.set("ease-in-circ", value => 1 - Math.sqrt(1 - value ** 2));
    easingsFunctions$b.set("ease-out-circ", value => Math.sqrt(1 - (value - 1) ** 2));
    easingsFunctions$b.set("ease-in-out-circ", value => value < 0.5 ? (1 - Math.sqrt(1 - (2 * value) ** 2)) / 2 : (Math.sqrt(1 - (-2 * value + 2) ** 2) + 1) / 2);

    async function loadEasingCircPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$b) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$a = new Map();
    easingsFunctions$a.set("ease-in-cubic", value => value ** 3);
    easingsFunctions$a.set("ease-out-cubic", value => 1 - (1 - value) ** 3);
    easingsFunctions$a.set("ease-in-out-cubic", value => (value < 0.5 ? 4 * value ** 3 : 1 - (-2 * value + 2) ** 3 / 2));

    async function loadEasingCubicPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$a) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$9 = new Map();
    easingsFunctions$9.set("ease-in-elastic", value => {
        if (value === 0 || value === 1) {
            return value;
        }
        return -Math.pow(2, 10 * (value - 1)) * Math.sin(((value - 1.075) * (2 * Math.PI)) / 0.3);
    });
    easingsFunctions$9.set("ease-out-elastic", value => {
        if (value === 0 || value === 1) {
            return value;
        }
        return Math.pow(2, -10 * value) * Math.sin(((value - 0.075) * (2 * Math.PI)) / 0.3) + 1;
    });
    easingsFunctions$9.set("ease-in-out-elastic", value => {
        if (value === 0 || value === 1) {
            return value;
        }
        value *= 2;
        if (value < 1) {
            return -0.5 * Math.pow(2, 10 * (value - 1)) * Math.sin(((value - 1.1125) * (2 * Math.PI)) / 0.45);
        }
        return Math.pow(2, -10 * (value - 1)) * Math.sin(((value - 1.1125) * (2 * Math.PI)) / 0.45) * 0.5 + 1;
    });

    async function loadEasingElasticPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$9) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$8 = new Map();
    easingsFunctions$8.set("ease-in-expo", value => (value ? 2 ** (10 * value - 10) : 0));
    easingsFunctions$8.set("ease-out-expo", value => (value === 1 ? 1 : 1 - Math.pow(2, -10 * value)));
    easingsFunctions$8.set("ease-in-out-expo", value => {
        if (value === 1) {
            return 1;
        }
        else if (value) {
            return value < 0.5 ? 2 ** (20 * value - 10) / 2 : (2 - 2 ** (-20 * value + 10)) / 2;
        }
        else {
            return 0;
        }
    });

    async function loadEasingExpoPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$8) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$7 = new Map(), gaussian = (t) => Math.exp(-4 * (1 - t) * (1 - t));
    easingsFunctions$7.set("ease-in-gaussian", value => gaussian(value));
    easingsFunctions$7.set("ease-out-gaussian", value => gaussian(value));
    easingsFunctions$7.set("ease-in-out-gaussian", value => gaussian(value));

    async function loadEasingGaussianPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$7) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$6 = new Map();
    easingsFunctions$6.set("ease-in-linear", value => value);
    easingsFunctions$6.set("ease-out-linear", value => value);
    easingsFunctions$6.set("ease-in-out-linear", value => value);

    async function loadEasingLinearPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$6) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$5 = new Map();
    easingsFunctions$5.set("ease-in-quart", value => value ** 4);
    easingsFunctions$5.set("ease-out-quart", value => 1 - (1 - value) ** 4);
    easingsFunctions$5.set("ease-in-out-quart", value => (value < 0.5 ? 8 * value ** 4 : 1 - (-2 * value + 2) ** 4 / 2));

    async function loadEasingQuartPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$5) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$4 = new Map();
    easingsFunctions$4.set("ease-in-quint", value => value ** 5);
    easingsFunctions$4.set("ease-out-quint", value => 1 - (1 - value) ** 5);
    easingsFunctions$4.set("ease-in-out-quint", value => (value < 0.5 ? 16 * value ** 5 : 1 - (-2 * value + 2) ** 5 / 2));

    async function loadEasingQuintPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$4) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$3 = new Map(), sigmoid = (t) => 1 / (1 + Math.exp(-10 * (t - 0.5)));
    easingsFunctions$3.set("ease-in-sigmoid", value => sigmoid(value));
    easingsFunctions$3.set("ease-out-sigmoid", value => sigmoid(value));
    easingsFunctions$3.set("ease-in-out-sigmoid", value => sigmoid(value));

    async function loadEasingSigmoidPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$3) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$2 = new Map();
    easingsFunctions$2.set("ease-in-sine", value => 1 - Math.cos((value * Math.PI) / 2));
    easingsFunctions$2.set("ease-out-sine", value => Math.sin((value * Math.PI) / 2));
    easingsFunctions$2.set("ease-in-out-sine", value => -(Math.cos(Math.PI * value) - 1) / 2);

    async function loadEasingSinePlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$2) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const easingsFunctions$1 = new Map(), smoothstep$1 = (t) => t * t * (3 - 2 * t);
    easingsFunctions$1.set("ease-in-smoothstep", value => smoothstep$1(value));
    easingsFunctions$1.set("ease-out-smoothstep", value => smoothstep$1(value));
    easingsFunctions$1.set("ease-in-out-smoothstep", value => smoothstep$1(value));

    async function loadEasingSmoothstepPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions$1) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    class ClickEvent {
        enable = false;
        mode = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "mode", data.mode);
        }
    }

    var DivType;
    (function (DivType) {
        DivType["circle"] = "circle";
        DivType["rectangle"] = "rectangle";
    })(DivType || (DivType = {}));

    class DivEvent {
        enable = false;
        mode = [];
        selectors = [];
        type = DivType.circle;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "selectors", data.selectors);
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "type", data.type);
        }
    }

    class HoverEvent {
        enable = false;
        mode = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "mode", data.mode);
        }
    }

    class Events {
        onClick = new ClickEvent();
        onDiv = new DivEvent();
        onHover = new HoverEvent();
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.onClick.load(data.onClick);
            const onDiv = data.onDiv;
            if (onDiv !== undefined) {
                this.onDiv = executeOnSingleOrMultiple(onDiv, t => {
                    const tmp = new DivEvent();
                    tmp.load(t);
                    return tmp;
                });
            }
            this.onHover.load(data.onHover);
        }
    }

    var InteractivityDetect;
    (function (InteractivityDetect) {
        InteractivityDetect["canvas"] = "canvas";
        InteractivityDetect["parent"] = "parent";
        InteractivityDetect["window"] = "window";
    })(InteractivityDetect || (InteractivityDetect = {}));

    class Modes {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (!this.#container) {
                return;
            }
            const interactors = this.#pluginManager.interactors?.get(this.#container);
            if (!interactors) {
                return;
            }
            for (const interactor of interactors) {
                if (!interactor.loadModeOptions) {
                    continue;
                }
                interactor.loadModeOptions(this, data);
            }
        }
    }

    class Interactivity {
        detectsOn = InteractivityDetect.window;
        events = new Events();
        modes;
        constructor(pluginManager, container) {
            this.modes = new Modes(pluginManager, container);
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            const detectsOn = data.detectsOn;
            if (detectsOn !== undefined) {
                this.detectsOn = detectsOn;
            }
            this.events.load(data.events);
            this.modes.load(data.modes);
        }
    }

    class InteractivityPlugin {
        id = "interactivity";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { InteractivityPluginInstance } = await Promise.resolve().then(function () { return InteractivityPluginInstance$1; });
            return new InteractivityPluginInstance(this.#pluginManager, container);
        }
        loadOptions(container, options, source) {
            if (!this.needsPlugin()) {
                return;
            }
            let interactivityOptions = options.interactivity;
            if (!interactivityOptions?.load) {
                options.interactivity = interactivityOptions = new Interactivity(this.#pluginManager, container);
            }
            interactivityOptions.load(source?.interactivity);
            const interactors = this.#pluginManager.interactors?.get(container);
            if (!interactors) {
                return;
            }
            for (const interactor of interactors) {
                if (interactor.loadOptions) {
                    interactor.loadOptions(options, source);
                }
            }
        }
        loadParticlesOptions(container, options, source) {
            if (source?.interactivity) {
                options.interactivity = deepExtend({}, source.interactivity);
            }
            const interactors = this.#pluginManager.interactors?.get(container);
            if (!interactors) {
                return;
            }
            for (const interactor of interactors) {
                interactor.loadParticlesOptions?.(options, source);
            }
        }
        needsPlugin() {
            return true;
        }
    }

    var InteractorType;
    (function (InteractorType) {
        InteractorType["external"] = "external";
        InteractorType["particles"] = "particles";
    })(InteractorType || (InteractorType = {}));

    class ExternalInteractorBase {
        type = InteractorType.external;
        container;
        constructor(container) {
            this.container = container;
        }
    }

    class ParticlesInteractorBase {
        type = InteractorType.particles;
        container;
        constructor(container) {
            this.container = container;
        }
    }

    const clickEvent = "click", mouseDownEvent$1 = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent$1 = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";

    function findItemFromSingleOrMultiple(obj, callback) {
        if (isArray(obj)) {
            return obj.find((t, index) => callback(t, index));
        }
        const defaultIndex = 0;
        return callback(obj, defaultIndex) ? obj : undefined;
    }
    function checkSelector(element, selectors) {
        const res = executeOnSingleOrMultiple(selectors, selector => {
            return element.matches(selector);
        });
        return isArray(res) ? res.some(t => t) : res;
    }
    function isDivModeEnabled(mode, divs) {
        return !!findItemFromSingleOrMultiple(divs, t => t.enable && isInArray(mode, t.mode));
    }
    function divModeExecute(mode, divs, callback) {
        executeOnSingleOrMultiple(divs, div => {
            const divMode = div.mode, divEnabled = div.enable;
            if (divEnabled && isInArray(mode, divMode)) {
                singleDivModeExecute(div, callback);
            }
        });
    }
    function singleDivModeExecute(div, callback) {
        const selectors = div.selectors;
        executeOnSingleOrMultiple(selectors, selector => {
            callback(selector, div);
        });
    }
    function divMode(divs, element) {
        if (!element || !divs) {
            return;
        }
        return findItemFromSingleOrMultiple(divs, div => {
            return checkSelector(element, div.selectors);
        });
    }

    async function loadInteractivityPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
            interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
            interactivityPluginManager.initializers.interactors ??= new Map();
            interactivityPluginManager.interactors ??= new Map();
            interactivityPluginManager.addInteractor = (name, interactorInitializer) => {
                interactivityPluginManager.initializers.interactors ??= new Map();
                interactivityPluginManager.initializers.interactors.set(name, interactorInitializer);
            };
            interactivityPluginManager.getInteractors = async (container, force = false) => {
                interactivityPluginManager.interactors ??= new Map();
                interactivityPluginManager.initializers.interactors ??= new Map();
                return getItemsFromInitializer(container, interactivityPluginManager.interactors, interactivityPluginManager.initializers.interactors, force);
            };
            interactivityPluginManager.setOnClickHandler = (callback) => {
                const { items } = interactivityEngine;
                if (!items.length) {
                    throw new Error("Click handlers can only be set after calling tsParticles.load()");
                }
                items.forEach(item => {
                    const interactivityContainer = item;
                    interactivityContainer.addClickHandler?.(callback);
                });
            };
        });
    }
    function ensureInteractivityPluginLoaded(e) {
        if (!e.pluginManager.addInteractor) {
            throw new Error("tsParticles Interactivity Plugin is not loaded");
        }
    }

    class EmitterLife {
        count;
        delay;
        duration;
        wait = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "count", data.count);
            loadRangeProperty(this, "delay", data.delay);
            loadRangeProperty(this, "duration", data.duration);
            loadProperty(this, "wait", data.wait);
        }
    }

    class EmitterRate {
        delay = 0.1;
        quantity = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "quantity", data.quantity);
            loadRangeProperty(this, "delay", data.delay);
        }
    }

    class EmitterShapeReplace {
        color = false;
        opacity = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "color", data.color);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    class EmitterShape {
        options = {};
        replace = new EmitterShapeReplace();
        type = "square";
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.options !== undefined) {
                this.options = deepExtend({}, data.options ?? {});
            }
            this.replace.load(data.replace);
            loadProperty(this, "type", data.type);
        }
    }

    class EmitterSize {
        height = 0;
        mode = exports.PixelMode.percent;
        width = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "height", data.height);
            loadProperty(this, "width", data.width);
        }
    }

    class EmitterSpawn {
        fill;
        stroke;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.fill) {
                this.fill ??= new Fill();
                this.fill.load(data.fill);
            }
            if (data.stroke) {
                this.stroke ??= new Stroke();
                this.stroke.load(data.stroke);
            }
        }
    }

    class Emitter {
        autoPlay = true;
        direction;
        domId;
        fill = true;
        life = new EmitterLife();
        name;
        particles;
        position;
        rate = new EmitterRate();
        shape = new EmitterShape();
        size;
        spawn = new EmitterSpawn();
        spawnFillColor;
        spawnStrokeColor;
        startCount = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "autoPlay", data.autoPlay);
            if (data.size !== undefined) {
                this.size ??= new EmitterSize();
                this.size.load(data.size);
            }
            loadProperty(this, "direction", data.direction);
            loadProperty(this, "domId", data.domId);
            loadProperty(this, "fill", data.fill);
            this.life.load(data.life);
            loadProperty(this, "name", data.name);
            this.particles = executeOnSingleOrMultiple(data.particles, particles => {
                return deepExtend({}, particles);
            });
            this.rate.load(data.rate);
            this.shape.load(data.shape);
            this.spawn.load(data.spawn);
            if (data.position !== undefined) {
                this.position = {};
                if (data.position.x !== undefined) {
                    this.position.x = setRangeValue(data.position.x);
                }
                if (data.position.y !== undefined) {
                    this.position.y = setRangeValue(data.position.y);
                }
            }
            if (data.spawnFillColor !== undefined) {
                this.spawnFillColor ??= new AnimatableColor();
                this.spawnFillColor.load(data.spawnFillColor);
            }
            if (data.spawnStrokeColor !== undefined) {
                this.spawnStrokeColor ??= new AnimatableColor();
                this.spawnStrokeColor.load(data.spawnStrokeColor);
            }
            loadProperty(this, "startCount", data.startCount);
        }
    }

    const defaultRandomOptions = {
        count: 1,
        enable: true,
    };

    const emittersMode = "emitters";
    class EmittersInteractor extends ExternalInteractorBase {
        handleClickMode;
        maxDistance;
        #instancesManager;
        constructor(instancesManager, container) {
            super(container);
            this.#instancesManager = instancesManager;
            this.maxDistance = 0;
            this.handleClickMode = (mode, interactivityData) => {
                const container = this.container, options = container.actualOptions, modeEmitters = options.interactivity.modes.emitters;
                if (!modeEmitters || mode !== emittersMode) {
                    return;
                }
                let emittersModeOptions;
                if (isArray(modeEmitters.value)) {
                    const minLength = 0, modeEmittersCount = modeEmitters.value.length;
                    if (modeEmittersCount > minLength && modeEmitters.random.enable) {
                        emittersModeOptions = [];
                        const usedIndexes = new Set();
                        for (let i = 0; i < modeEmitters.random.count; i++) {
                            const idx = Math.floor(getRandom() * modeEmitters.value.length);
                            if (usedIndexes.has(idx) && usedIndexes.size < modeEmittersCount) {
                                i--;
                                continue;
                            }
                            usedIndexes.add(idx);
                            const selectedOptions = itemFromArray(modeEmitters.value, idx);
                            if (!selectedOptions) {
                                continue;
                            }
                            emittersModeOptions.push(selectedOptions);
                        }
                    }
                    else {
                        emittersModeOptions = modeEmitters.value;
                    }
                }
                else {
                    emittersModeOptions = modeEmitters.value;
                }
                const emittersOptions = emittersModeOptions, ePosition = interactivityData.mouse.clickPosition;
                void executeOnSingleOrMultiple(emittersOptions, async (emitter) => {
                    await this.#instancesManager.addEmitter(this.container, emitter, ePosition);
                });
            };
        }
        clear() {
        }
        init() {
        }
        interact(_interactivityData, delta) {
            for (const emitter of this.#instancesManager.getArray(this.container)) {
                emitter.update(delta);
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity).events;
            if (!mouse.clickPosition || !events.onClick.enable) {
                return false;
            }
            return isInArray(emittersMode, events.onClick.mode);
        }
        loadModeOptions(options, ...sources) {
            options.emitters = {
                random: defaultRandomOptions,
                value: [],
            };
            for (const source of sources) {
                if (!source?.emitters) {
                    continue;
                }
                if (isArray(source.emitters)) {
                    for (const emitter of source.emitters) {
                        const tmp = new Emitter();
                        tmp.load(emitter);
                        options.emitters.value.push(tmp);
                    }
                }
                else if ("value" in source.emitters) {
                    const emitterModeOptions = source.emitters;
                    options.emitters.random.enable = emitterModeOptions.random?.enable ?? options.emitters.random.enable;
                    options.emitters.random.count = emitterModeOptions.random?.count ?? options.emitters.random.count;
                    if (isArray(emitterModeOptions.value)) {
                        for (const emitter of emitterModeOptions.value) {
                            const tmp = new Emitter();
                            tmp.load(emitter);
                            options.emitters.value.push(tmp);
                        }
                    }
                    else {
                        const tmp = new Emitter();
                        tmp.load(emitterModeOptions.value);
                        options.emitters.value.push(tmp);
                    }
                }
                else {
                    const tmp = new Emitter();
                    tmp.load(source.emitters);
                    options.emitters.value.push(tmp);
                }
            }
        }
        removeEmitter(emitter) {
            const index = this.#instancesManager.getArray(this.container).indexOf(emitter), minIndex = 0, deleteCount = 1;
            if (index >= minIndex) {
                this.#instancesManager.getArray(this.container).splice(index, deleteCount);
            }
        }
        reset() {
        }
    }

    async function addEmittersShapesManager(e) {
        const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
        pluginManager.emitterShapeManager ??= new ShapeManager();
        pluginManager.addEmitterShapeGenerator ??= (name, generator) => {
            pluginManager.emitterShapeManager?.addShapeGenerator(name, generator);
        };
    }

    const instancesManagers$1 = new WeakMap();
    function getEmittersInstancesManager(e) {
        const pluginManager = e.pluginManager;
        let manager = instancesManagers$1.get(pluginManager);
        if (!manager) {
            manager = Promise.resolve().then(function () { return EmittersInstancesManager$1; })
                .then(({ EmittersInstancesManager }) => new EmittersInstancesManager(pluginManager))
                .catch((error) => {
                instancesManagers$1.delete(pluginManager);
                throw error;
            });
            instancesManagers$1.set(pluginManager, manager);
        }
        return manager;
    }

    class EmitterShapeBase {
        fill;
        options;
        position;
        size;
        constructor(position, size, fill, options) {
            this.position = position;
            this.size = size;
            this.fill = fill;
            this.options = options;
        }
        resize(position, size) {
            this.position = position;
            this.size = size;
        }
    }

    var EmitterClickMode;
    (function (EmitterClickMode) {
        EmitterClickMode["emitter"] = "emitter";
    })(EmitterClickMode || (EmitterClickMode = {}));

    async function loadEmittersInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const instancesManager = await getEmittersInstancesManager(e);
            ensureInteractivityPluginLoaded(e);
            await addEmittersShapesManager(e);
            e.pluginManager.addInteractor?.("externalEmitters", container => {
                return Promise.resolve(new EmittersInteractor(instancesManager, container));
            });
        });
    }

    class EmittersPlugin {
        id = "emitters";
        #instancesManager;
        constructor(instancesManager) {
            this.#instancesManager = instancesManager;
        }
        async getPlugin(container) {
            const { EmittersPluginInstance } = await Promise.resolve().then(function () { return EmittersPluginInstance$1; });
            return new EmittersPluginInstance(this.#instancesManager, container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            if (source?.emitters) {
                options.emitters = executeOnSingleOrMultiple(source.emitters, emitter => {
                    const tmp = new Emitter();
                    tmp.load(emitter);
                    return tmp;
                });
            }
        }
        needsPlugin(options) {
            if (!options) {
                return false;
            }
            const emitters = options.emitters;
            return (isArray(emitters) && !!emitters.length) || emitters !== undefined;
        }
    }

    async function loadEmittersPluginSimple(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const instancesManager = await getEmittersInstancesManager(e);
            await addEmittersShapesManager(e);
            e.pluginManager.addPlugin(new EmittersPlugin(instancesManager));
        });
    }

    function ensureEmittersPluginLoaded(e) {
        if (!e.pluginManager.addEmitterShapeGenerator) {
            throw new Error("tsParticles Emitters Plugin is not loaded");
        }
    }

    async function loadEmittersPlugin(engine) {
        await loadEmittersPluginSimple(engine);
        await loadEmittersInteraction(engine);
    }

    const defaultWidth$3 = 0, indexesOffset = {
        r: 0,
        g: 1,
        b: 2,
        a: 3,
    }, alphaMax = 255, alphaFactor$1 = identity$3 / alphaMax;
    function drawLine$1(context, begin, end) {
        context.beginPath();
        context.moveTo(begin.x, begin.y);
        context.lineTo(end.x, end.y);
        context.closePath();
    }
    function getCanvasImageData(ctx, size, offset, clear = true) {
        const imageData = ctx.getImageData(originPoint.x, originPoint.y, size.width, size.height).data;
        if (clear) {
            ctx.clearRect(originPoint.x, originPoint.y, size.width, size.height);
        }
        const pixels = [];
        for (let i = 0; i < imageData.length; i += offset) {
            const idx = i / offset, pos = {
                x: idx % size.width,
                y: Math.floor(idx / size.width),
            };
            pixels[pos.y] ??= [];
            const row = pixels[pos.y];
            if (!row) {
                continue;
            }
            row[pos.x] = {
                r: imageData[i + indexesOffset.r] ?? defaultRgbMin,
                g: imageData[i + indexesOffset.g] ?? defaultRgbMin,
                b: imageData[i + indexesOffset.b] ?? defaultRgbMin,
                a: (imageData[i + indexesOffset.a] ?? defaultAlpha$1) * alphaFactor$1,
            };
        }
        return {
            pixels,
            width: Math.min(...pixels.map(row => row.length)),
            height: pixels.length,
        };
    }
    function getImageData(src, offset, canvasSettings) {
        const image = new Image();
        image.crossOrigin = "Anonymous";
        const p = new Promise((resolve, reject) => {
            image.onerror = reject;
            image.onload = () => {
                const canvas = safeDocument().createElement("canvas");
                canvas.width = image.width;
                canvas.height = image.height;
                const context = canvas.getContext("2d", canvasSettings);
                if (!context) {
                    reject(new Error("Could not get canvas context"));
                    return;
                }
                context.drawImage(image, originPoint.x, originPoint.y, image.width, image.height, originPoint.x, originPoint.y, canvas.width, canvas.height);
                resolve(getCanvasImageData(context, canvas, offset));
            };
        });
        image.src = src;
        return p;
    }
    function getTextData(textOptions, offset, fill, canvasSettings) {
        const canvas = safeDocument().createElement("canvas"), context = canvas.getContext("2d", canvasSettings), { font, text, lines: linesOptions, color } = textOptions;
        if (!text || !context) {
            return;
        }
        const lines = text.split(linesOptions.separator), fontSize = isNumber(font.size) ? `${font.size.toString()}px` : font.size, linesData = [];
        let maxWidth = 0, totalHeight = 0;
        for (const line of lines) {
            context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
            const measure = context.measureText(line), lineData = {
                measure,
                text: line,
                height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
                width: measure.width,
            };
            maxWidth = Math.max(maxWidth || defaultWidth$3, lineData.width);
            totalHeight += lineData.height + linesOptions.spacing;
            linesData.push(lineData);
        }
        canvas.width = maxWidth;
        canvas.height = totalHeight;
        let currentHeight = 0;
        for (const line of linesData) {
            context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
            if (fill) {
                context.fillStyle = color;
                context.fillText(line.text, originPoint.x, currentHeight + line.measure.actualBoundingBoxAscent);
            }
            else {
                context.strokeStyle = color;
                context.strokeText(line.text, originPoint.x, currentHeight + line.measure.actualBoundingBoxAscent);
            }
            currentHeight += line.height + linesOptions.spacing;
        }
        return getCanvasImageData(context, canvas, offset);
    }
    async function loadFont(font, weight) {
        try {
            await safeDocument().fonts.load(`${weight ?? "400"} 36px '${font ?? "Verdana"}'`);
        }
        catch {
        }
    }

    const maxRetries = 100;
    class EmittersCanvasShape extends EmitterShapeBase {
        filter;
        pixelData;
        scale;
        #container;
        constructor(container, position, size, fill, options) {
            super(position, size, fill, options);
            this.#container = container;
            const filter = options.filter, minAlpha = 0;
            let filterFunc = (pixel) => pixel.a > minAlpha;
            if (isString(filter)) {
                if (filter in globalThis) {
                    const wndFilter = globalThis[filter];
                    if (isFunction(wndFilter)) {
                        filterFunc = wndFilter;
                    }
                }
            }
            else {
                filterFunc = filter;
            }
            this.filter = filterFunc;
            this.scale = options.scale;
            this.pixelData = {
                pixels: [],
                height: 0,
                width: 0,
            };
        }
        async init() {
            let pixelData;
            const options = this.options, selector = options.selector, pixels = options.pixels, image = options.image, element = options.element, text = options.text, offset = pixels.offset;
            if (image) {
                const url = image.src;
                if (!url) {
                    return;
                }
                pixelData = await getImageData(url, offset, this.#container.canvas.render.settings);
            }
            else if (element ?? selector) {
                const canvas = element ?? (selector && safeDocument().querySelector(selector));
                if (!canvas) {
                    return;
                }
                const context = canvas.getContext("2d", this.#container.canvas.render.settings);
                if (!context) {
                    return;
                }
                pixelData = getCanvasImageData(context, canvas, offset);
            }
            else {
                const data = getTextData(text, offset, this.fill, this.#container.canvas.render.settings);
                if (isNull(data)) {
                    return;
                }
                pixelData = data;
            }
            this.pixelData = pixelData;
        }
        randomPosition() {
            const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
                x: position.x - width * scale * half$2,
                y: position.y - height * scale * half$2,
            };
            for (let i = 0; i < maxRetries; i++) {
                const nextIndex = Math.floor(getRandom() * width * height), pixelPos = {
                    x: nextIndex % width,
                    y: Math.floor(nextIndex / width),
                }, row = data.pixels[pixelPos.y];
                if (!row) {
                    continue;
                }
                const pixel = row[pixelPos.x];
                if (!pixel) {
                    continue;
                }
                const shouldCreateParticle = this.filter(pixel);
                if (!shouldCreateParticle) {
                    continue;
                }
                return {
                    position: {
                        x: pixelPos.x * scale + positionOffset.x,
                        y: pixelPos.y * scale + positionOffset.y,
                    },
                    color: { ...pixel },
                    opacity: pixel.a,
                };
            }
            return null;
        }
        resize(position, size) {
            super.resize(position, size);
        }
    }

    class PixelsOptions {
        offset = 4;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.offset !== undefined) {
                this.offset = data.offset;
            }
        }
    }

    class TextFontOptions {
        family = "Verdana";
        size = 32;
        style = "";
        variant = "";
        weight = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.family !== undefined) {
                this.family = data.family;
            }
            if (data.size !== undefined) {
                this.size = data.size;
            }
            if (data.style !== undefined) {
                this.style = data.style;
            }
            if (data.variant !== undefined) {
                this.variant = data.variant;
            }
            if (data.weight !== undefined) {
                this.weight = data.weight;
            }
        }
    }

    class TextLinesOptions {
        separator = "\n";
        spacing = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.separator !== undefined) {
                this.separator = data.separator;
            }
            if (data.spacing !== undefined) {
                this.spacing = data.spacing;
            }
        }
    }

    class TextOptions {
        color = "#000000";
        font = new TextFontOptions();
        lines = new TextLinesOptions();
        text = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = data.color;
            }
            this.font.load(data.font);
            this.lines.load(data.lines);
            if (data.text !== undefined) {
                this.text = data.text;
            }
        }
    }

    const minAlpha = 0;
    class EmittersCanvasShapeOptions {
        element;
        image;
        pixels = new PixelsOptions();
        scale = 1;
        selector = "";
        text = new TextOptions();
        filter = (pixel) => pixel.a > minAlpha;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.element !== undefined) {
                this.element = data.element;
            }
            if (data.filter !== undefined) {
                this.filter = data.filter;
            }
            this.pixels.load(data.pixels);
            if (data.scale !== undefined) {
                this.scale = data.scale;
            }
            if (data.selector !== undefined) {
                this.selector = data.selector;
            }
            if (data.image !== undefined) {
                this.image = data.image;
            }
            this.text.load(data.text);
        }
    }

    class EmittersCanvasShapeGenerator {
        generate(container, position, size, fill, options) {
            const shapeOptions = new EmittersCanvasShapeOptions();
            shapeOptions.load(options);
            return new EmittersCanvasShape(container, position, size, fill, shapeOptions);
        }
    }

    async function loadEmittersShapeCanvas(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureEmittersPluginLoaded(e);
            e.pluginManager.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
        });
    }

    const maxAttempts$1 = 100;
    function generateRandomPointWithinPath(ctx, path, center, size) {
        let randomPoint = null;
        for (let attempts = 0; attempts < maxAttempts$1; attempts++) {
            const tmpPoint = {
                x: center.x + getRandom() * size.width - size.width * half$2,
                y: center.y + getRandom() * size.height - size.height * half$2,
            };
            if (ctx.isPointInPath(path, tmpPoint.x, tmpPoint.y)) {
                randomPoint = tmpPoint;
                break;
            }
        }
        return randomPoint;
    }
    function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
        let randomPoint = null;
        for (let attempts = 0; attempts < maxAttempts$1; attempts++) {
            const tmpPoint = {
                x: center.x + getRandom() * size.width - size.width * half$2,
                y: center.y + getRandom() * size.height - size.height * half$2,
            };
            if (ctx.isPointInStroke(path, tmpPoint.x, tmpPoint.y)) {
                randomPoint = tmpPoint;
                break;
            }
        }
        return randomPoint;
    }

    class EmittersPathShape extends EmitterShapeBase {
        checkContext;
        path;
        points;
        constructor(container, position, size, fill, options) {
            super(position, size, fill, options);
            const ctx = safeDocument().createElement("canvas").getContext("2d", container.canvas.render.settings);
            if (!ctx) {
                throw new Error(`No 2d context available`);
            }
            this.checkContext = ctx;
            this.points = options.points;
            const pathData = this.points, path = new Path2D(), offset = {
                x: position.x - size.width * half$2,
                y: position.y - size.height * half$2,
            };
            for (const [index, point] of pathData.entries()) {
                const coords = {
                    x: offset.x + (point.x * size.width) / percentDenominator,
                    y: offset.y + (point.y * size.height) / percentDenominator,
                };
                if (!index) {
                    path.moveTo(coords.x, coords.y);
                }
                else {
                    path.lineTo(coords.x, coords.y);
                }
            }
            const firstIndex = 0, firstPathData = pathData[firstIndex];
            if (!firstPathData) {
                throw new Error(`No path data available`);
            }
            const coords = {
                x: offset.x + (firstPathData.x * size.width) / percentDenominator,
                y: offset.y + (firstPathData.y * size.height) / percentDenominator,
            };
            path.lineTo(coords.x, coords.y);
            this.path = path;
        }
        async init() {
        }
        randomPosition() {
            const ctx = this.checkContext, position = this.position, size = this.size, fill = this.fill, path = this.path, res = fill
                ? generateRandomPointWithinPath(ctx, path, position, size)
                : generateRandomPointOnPathPerimeter(ctx, path, position, size);
            return res ? { position: res } : null;
        }
        resize(position, size) {
            super.resize(position, size);
            const pathData = this.points, path = new Path2D(), offset = {
                x: position.x - size.width * half$2,
                y: position.y - size.height * half$2,
            };
            for (const [index, point] of pathData.entries()) {
                const coords = {
                    x: offset.x + (point.x * size.width) / percentDenominator,
                    y: offset.y + (point.y * size.height) / percentDenominator,
                };
                if (!index) {
                    path.moveTo(coords.x, coords.y);
                }
                else {
                    path.lineTo(coords.x, coords.y);
                }
            }
            const firstIndex = 0, firstPathData = pathData[firstIndex];
            if (!firstPathData) {
                throw new Error(`No path data available`);
            }
            const coords = {
                x: offset.x + (firstPathData.x * size.width) / percentDenominator,
                y: offset.y + (firstPathData.y * size.height) / percentDenominator,
            };
            path.lineTo(coords.x, coords.y);
            this.path = path;
        }
    }

    const defaultPosition = { x: 50, y: 50 };
    class EmittersPathShapeOptions {
        points = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.points !== undefined) {
                this.points = data.points.map(t => ({ x: t.x ?? defaultPosition.x, y: t.y ?? defaultPosition.y }));
            }
        }
    }

    class EmittersPathShapeGenerator {
        generate(container, position, size, fill, options) {
            const shapeOptions = new EmittersPathShapeOptions();
            shapeOptions.load(options);
            return new EmittersPathShape(container, position, size, fill, shapeOptions);
        }
    }

    async function loadEmittersShapePath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureEmittersPluginLoaded(e);
            e.pluginManager.addEmitterShapeGenerator?.("path", new EmittersPathShapeGenerator());
        });
    }

    const defaultRotation$2 = 0, maxAttempts = 100;
    function generateRandomPolygon(position, sides, radius, rotationAngle = defaultRotation$2) {
        const polygon = [], angle = doublePI / sides;
        for (let i = 0; i < sides; i++) {
            const currentAngle = angle * i + rotationAngle;
            polygon.push({
                x: position.x + radius * Math.cos(currentAngle),
                y: position.y + radius * Math.sin(currentAngle),
            });
        }
        return polygon;
    }
    function generateRandomPointWithinPolygon(polygon) {
        const firstIndex = 0, firstPoint = polygon[firstIndex];
        if (!firstPoint) {
            return null;
        }
        const min = { ...firstPoint }, max = { ...firstPoint };
        for (const point of polygon) {
            if (point.x < min.x) {
                min.x = point.x;
            }
            if (point.x > max.x) {
                max.x = point.x;
            }
            if (point.y < min.y) {
                min.y = point.y;
            }
            if (point.y > max.y) {
                max.y = point.y;
            }
        }
        let randomPoint = null;
        for (let attempts = 0; attempts < maxAttempts; attempts++) {
            const tmpPoint = {
                x: min.x + getRandom() * (max.x - min.x),
                y: min.y + getRandom() * (max.y - min.y),
            };
            if (isPointInPolygon(tmpPoint, polygon)) {
                randomPoint = tmpPoint;
                break;
            }
        }
        return randomPoint;
    }
    function generateRandomPointOnPolygonPerimeter(polygon) {
        const sideIndex = Math.floor(getRandom() * polygon.length), startPoint = polygon[sideIndex];
        if (!startPoint) {
            return;
        }
        const offset = 1, endPoint = polygon[(sideIndex + offset) % polygon.length];
        if (!endPoint) {
            return;
        }
        const t = getRandom();
        return { x: startPoint.x + (endPoint.x - startPoint.x) * t, y: startPoint.y + (endPoint.y - startPoint.y) * t };
    }
    function isPointInPolygon(point, polygon) {
        let inside = false;
        const offset = 1;
        for (let i = 0, j = polygon.length - offset; i < polygon.length; j = i++) {
            const pi = polygon[i], pj = polygon[j];
            if (!pi || !pj) {
                continue;
            }
            const intersect = pi.y > point.y !== pj.y > point.y && point.x < ((pj.x - pi.x) * (point.y - pi.y)) / (pj.y - pi.y) + pi.x;
            if (intersect) {
                inside = !inside;
            }
        }
        return inside;
    }

    class EmittersPolygonShape extends EmitterShapeBase {
        angle;
        polygon;
        sides;
        constructor(position, size, fill, options) {
            super(position, size, fill, options);
            this.sides = options.sides;
            this.angle = degToRad(options.angle);
            this.polygon = generateRandomPolygon(position, this.sides, size.width * half$2, this.angle);
        }
        async init() {
        }
        randomPosition() {
            const fill = this.fill, polygon = this.polygon, res = fill ? generateRandomPointWithinPolygon(polygon) : generateRandomPointOnPolygonPerimeter(polygon);
            return res ? { position: res } : null;
        }
        resize(position, size) {
            super.resize(position, size);
            this.polygon = generateRandomPolygon(position, this.sides, size.width * half$2, this.angle);
        }
    }

    class EmittersPolygonShapeOptions {
        angle = 0;
        sides = 5;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.angle !== undefined) {
                this.angle = data.angle;
            }
            if (data.sides !== undefined) {
                this.sides = data.sides;
            }
        }
    }

    class EmittersPolygonShapeGenerator {
        generate(_container, position, size, fill, options) {
            const shapeOptions = new EmittersPolygonShapeOptions();
            shapeOptions.load(options);
            return new EmittersPolygonShape(position, size, fill, shapeOptions);
        }
    }

    async function loadEmittersShapePolygon(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureEmittersPluginLoaded(e);
            e.pluginManager.addEmitterShapeGenerator?.("polygon", new EmittersPolygonShapeGenerator());
        });
    }

    class ExportImagePlugin {
        id = "export-image";
        async getPlugin(container) {
            const { ExportImagePluginInstance } = await Promise.resolve().then(function () { return ExportImagePluginInstance$1; });
            return new ExportImagePluginInstance(container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadExportImagePlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ExportImagePlugin());
        });
    }

    class ExportJSONPlugin {
        id = "export-json";
        async getPlugin(container) {
            const { ExportJSONPluginInstance } = await Promise.resolve().then(function () { return ExportJSONPluginInstance$1; });
            return new ExportJSONPluginInstance(container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadExportJSONPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ExportJSONPlugin());
        });
    }

    class ExportVideoPlugin {
        id = "export-video";
        async getPlugin(container) {
            const { ExportVideoPluginInstance } = await Promise.resolve().then(function () { return ExportVideoPluginInstance$1; });
            return new ExportVideoPluginInstance(container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadExportVideoPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ExportVideoPlugin());
        });
    }

    class Cannon {
        drawVector = true;
        maxDragDistance = 0;
        maxParticles = 200;
        minParticles = 5;
        particleFactor = 0.2;
        spread = 30;
        vectorColor = "#ffffff80";
        velocityFactor = 0.5;
        load(data) {
            if (!data) {
                return;
            }
            loadProperty(this, "spread", data.spread);
            loadProperty(this, "velocityFactor", data.velocityFactor);
            loadProperty(this, "particleFactor", data.particleFactor);
            loadProperty(this, "minParticles", data.minParticles);
            loadProperty(this, "maxParticles", data.maxParticles);
            loadProperty(this, "maxDragDistance", data.maxDragDistance);
            loadProperty(this, "drawVector", data.drawVector);
            loadProperty(this, "vectorColor", data.vectorColor);
        }
    }

    var CannonState;
    (function (CannonState) {
        CannonState[CannonState["idle"] = 0] = "idle";
        CannonState[CannonState["aiming"] = 1] = "aiming";
        CannonState[CannonState["fired"] = 2] = "fired";
    })(CannonState || (CannonState = {}));
    const cannonMode = "cannon", minAngle$3 = 0, powerRadiusMin = 4, powerRadiusMaxDenominator = 20, powerRadiusMaxFactor = identity$3 / powerRadiusMaxDenominator, minTapsLength = 2, piDeg = 180, quarter = 0.25, minDistance$6 = 0;
    function angleRad(x0, y0, x1, y1) {
        return Math.atan2(y1 - y0, x1 - x0);
    }
    class Cannoner extends ExternalInteractorBase {
        maxDistance = 0;
        #data;
        #gesture = {
            origin: Vector.origin,
            current: Vector.origin,
            active: false,
        };
        #lastDownPosition = undefined;
        #state = CannonState.idle;
        constructor(container) {
            super(container);
        }
        clear(_particle, _delta) {
        }
        init() {
            const options = this.container.actualOptions.interactivity?.modes.cannon ?? new Cannon();
            this.#data = {
                spread: degToRad(options.spread),
                maxDragDistance: options.maxDragDistance,
                velocityFactor: options.velocityFactor,
                particleFactor: options.particleFactor,
                minParticles: options.minParticles,
                maxParticles: options.maxParticles,
                drawVector: options.drawVector,
                vectorColor: options.vectorColor,
            };
        }
        interact(interactivityData, _delta) {
            const mouse = interactivityData.mouse, mousePos = mouse.position, clicking = mouse.clicking, downPos = mouse.downPosition;
            if (clicking && downPos && downPos !== this.#lastDownPosition && this.#state === CannonState.idle) {
                this.#lastDownPosition = downPos;
                this.#gesture = {
                    origin: { x: downPos.x, y: downPos.y },
                    current: { x: downPos.x, y: downPos.y },
                    active: true,
                };
                this.#state = CannonState.aiming;
            }
            if (this.#state === CannonState.aiming && mousePos) {
                this.#gesture.current = { x: mousePos.x, y: mousePos.y };
                this.#drawVector();
            }
            if (!clicking && this.#state === CannonState.aiming) {
                this.#gesture.active = false;
                this.#fire();
                this.#state = CannonState.idle;
            }
        }
        isEnabled(interactivityData) {
            const container = this.container, events = container.actualOptions.interactivity?.events;
            if (!events?.onClick.enable) {
                return false;
            }
            const modes = events.onClick.mode, modeEnabled = Array.isArray(modes) ? modes.includes(cannonMode) : modes === cannonMode;
            if (!modeEnabled) {
                return false;
            }
            return this.#state !== CannonState.idle || interactivityData.mouse.clicking;
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "cannon", Cannon, ...sources);
        }
        reset(_interactivityData, _particle) {
        }
        #drawVector() {
            this.container.canvas.render.draw(ctx => {
                const opts = this.#data;
                if (!opts) {
                    return;
                }
                const { origin, current } = this.#gesture, pxRatio = this.container.retina.pixelRatio, dragDist = getDistance(origin, current), clampedDist = opts.maxDragDistance > none ? Math.min(dragDist, opts.maxDragDistance * pxRatio) : dragDist, clampRatio = dragDist > minDistance$6 ? clampedDist / dragDist : minDistance$6, clampedX = origin.x + (current.x - origin.x) * clampRatio, clampedY = origin.y + (current.y - origin.y) * clampRatio;
                ctx.save();
                ctx.strokeStyle = opts.vectorColor;
                ctx.lineWidth = double * pxRatio;
                ctx.beginPath();
                ctx.moveTo(origin.x, origin.y);
                ctx.lineTo(clampedX, clampedY);
                ctx.stroke();
                const radius = Math.max(powerRadiusMin, clampedDist * powerRadiusMaxFactor) * pxRatio;
                ctx.beginPath();
                ctx.arc(origin.x, origin.y, radius, minAngle$3, doublePI);
                ctx.strokeStyle = opts.vectorColor;
                ctx.lineWidth = double * pxRatio;
                ctx.stroke();
                ctx.restore();
            });
        }
        #fire() {
            const opts = this.#data;
            if (!opts) {
                return;
            }
            const { origin, current } = this.#gesture, pxRatio = this.container.retina.pixelRatio, dist = getDistance(origin, current), dragLength = opts.maxDragDistance > none ? Math.min(dist, opts.maxDragDistance * pxRatio) : dist;
            if (dragLength < minTapsLength) {
                return;
            }
            const pxRatioFactor = identity$3 / pxRatio, launchAngle = angleRad(current.x, current.y, origin.x, origin.y), velocity = dragLength * pxRatioFactor * opts.velocityFactor, count = Math.min(opts.maxParticles, Math.max(opts.minParticles, Math.round(dragLength * opts.particleFactor))), toDeg = piDeg / Math.PI;
            for (let i = 0; i < count; i++) {
                const spreadAngle = launchAngle + getRandomInRange(-opts.spread, opts.spread), speed = getRandomInRange(velocity * quarter, velocity);
                this.container.particles.addParticle(origin, {
                    move: {
                        enable: true,
                        speed,
                        direction: spreadAngle * toDeg,
                    },
                });
            }
        }
    }

    async function loadExternalCannonInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalCannon", container => {
                return Promise.resolve(new Cannoner(container));
            });
        });
    }

    class InteractivityParticleOptions {
        options;
        pauseOnStop = false;
        replaceCursor = false;
        stopDelay = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.options !== undefined) {
                this.options = deepExtend({}, data.options);
            }
            loadProperty(this, "replaceCursor", data.replaceCursor);
            loadProperty(this, "pauseOnStop", data.pauseOnStop);
            loadProperty(this, "stopDelay", data.stopDelay);
        }
    }

    const particleMode = "particle";
    class InteractivityParticleMaker extends ExternalInteractorBase {
        maxDistance = 0;
        #clearTimeout;
        #lastPosition;
        #particle;
        constructor(container) {
            super(container);
        }
        clear() {
        }
        init() {
        }
        interact(interactivityData) {
            const container = this.container, options = container.actualOptions;
            if (!container.retina.reduceFactor) {
                return;
            }
            const mousePos = interactivityData.mouse.position, interactivityParticleOptions = options.interactivity?.modes.particle;
            if (!interactivityParticleOptions) {
                return;
            }
            const mouseStopped = interactivityParticleOptions.pauseOnStop &&
                (interactivityData.mouse.position === this.#lastPosition ||
                    (interactivityData.mouse.position?.x === this.#lastPosition?.x &&
                        interactivityData.mouse.position?.y === this.#lastPosition?.y)), clearDelay = interactivityParticleOptions.stopDelay;
            if (mousePos) {
                this.#lastPosition = { ...mousePos };
            }
            else {
                this.#lastPosition = undefined;
            }
            if (!this.#lastPosition) {
                return;
            }
            if (mouseStopped) {
                if (this.#clearTimeout) {
                    return;
                }
                this.#clearTimeout = setTimeout(() => {
                    if (!this.#particle) {
                        return;
                    }
                    if (interactivityParticleOptions.replaceCursor) {
                        const element = interactivityData.element;
                        if (element) {
                            if (element instanceof Window || element instanceof Document) {
                                safeDocument().body.style.cursor = "";
                            }
                            else {
                                element.style.cursor = "";
                            }
                        }
                    }
                    this.#particle.destroy(true);
                    this.#particle = undefined;
                }, clearDelay);
                return;
            }
            if (this.#clearTimeout) {
                clearTimeout(this.#clearTimeout);
                this.#clearTimeout = undefined;
            }
            if (!this.#particle) {
                const particleOptions = deepExtend(interactivityParticleOptions.options, {
                    move: {
                        enable: false,
                    },
                });
                this.#particle = container.particles.addParticle(this.#lastPosition, particleOptions);
                if (interactivityParticleOptions.replaceCursor) {
                    const element = interactivityData.element;
                    if (element) {
                        if (element instanceof Window || element instanceof Document) {
                            safeDocument().body.style.cursor = "none";
                        }
                        else {
                            element.style.cursor = "none";
                        }
                    }
                }
            }
            if (!this.#particle) {
                return;
            }
            this.#particle.position.x = this.#lastPosition.x;
            this.#particle.position.y = this.#lastPosition.y;
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            return (!!events &&
                ((mouse.clicking && mouse.inside && !!mouse.position && isInArray(particleMode, events.onClick.mode)) ||
                    (mouse.inside && !!mouse.position && isInArray(particleMode, events.onHover.mode))));
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "particle", InteractivityParticleOptions, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalParticleInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalParticle", container => {
                return Promise.resolve(new InteractivityParticleMaker(container));
            });
        });
    }

    const popMode = "pop";
    class Popper extends ExternalInteractorBase {
        handleClickMode;
        maxDistance = 0;
        constructor(container) {
            super(container);
            this.handleClickMode = (mode, interactivityData) => {
                const container = this.container;
                if (mode !== popMode) {
                    return;
                }
                const clickPos = interactivityData.mouse.clickPosition;
                if (!clickPos) {
                    return;
                }
                const poppedParticles = container.particles.grid.queryCircle(clickPos, container.retina.pixelRatio);
                if (!poppedParticles.length) {
                    return;
                }
                for (const particle of poppedParticles) {
                    particle.destroy();
                }
            };
        }
        clear() {
        }
        init() {
        }
        interact() {
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            return !!events && mouse.clicking && mouse.inside && !!mouse.position && isInArray(popMode, events.onClick.mode);
        }
        reset() {
        }
    }

    async function loadExternalPopInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalPop", container => {
                return Promise.resolve(new Popper(container));
            });
        });
    }

    class FilterDrawer {
        drawAfter(data) {
            const { context } = data;
            context.restore();
        }
        drawBefore(data) {
            const { context, particle } = data;
            context.save();
            const blurValue = typeof particle.filterBlur === "number" ? `${particle.filterBlur}px` : particle.filterBlur, brightnessValue = particle.filterBrightness, contrastValue = particle.filterContrast, dropShadowValue = particle.filterDropShadow, grayscaleValue = particle.filterGrayscale, hueRotateValue = typeof particle.filterHueRotate === "number" ? `${particle.filterHueRotate}deg` : particle.filterHueRotate, invertValue = particle.filterInvert, opacityValue = particle.filterOpacity, saturateValue = particle.filterSaturate, sepiaValue = particle.filterSepia, urlValue = particle.filterUrl, blurString = blurValue ? `blur(${blurValue})` : "", brightnessString = isNull(brightnessValue) ? "" : `brightness(${brightnessValue})`, contrastString = isNull(contrastValue) ? "" : `contrast(${contrastValue})`, dropShadowString = dropShadowValue ? `drop-shadow(${dropShadowValue})` : "", grayscaleString = isNull(grayscaleValue) ? "" : `grayscale(${grayscaleValue})`, hueRotateString = isNull(hueRotateValue) ? "" : `hue-rotate(${hueRotateValue})`, invertString = isNull(invertValue) ? "" : `invert(${invertValue})`, opacityString = isNull(opacityValue) ? "" : `opacity(${opacityValue})`, saturateString = isNull(saturateValue) ? "" : `saturate(${saturateValue})`, sepiaString = isNull(sepiaValue) ? "" : `sepia(${sepiaValue})`, urlString = urlValue ? `url(${urlValue})` : "";
            context.filter =
                `${blurString} ${brightnessString} ${contrastString} ${dropShadowString} ${grayscaleString} ${hueRotateString} ${invertString} ${opacityString} ${saturateString} ${sepiaString} ${urlString}`.trim();
        }
        particleInit(_container, particle) {
            const effectData = particle.effectData;
            if (!effectData) {
                return;
            }
            particle.filterBlur = effectData.blur;
            particle.filterBrightness = effectData.brightness;
            particle.filterContrast = effectData.contrast;
            particle.filterDropShadow = effectData.dropShadow;
            particle.filterGrayscale = effectData.grayscale;
            particle.filterHueRotate = effectData.hueRotate;
            particle.filterInvert = effectData.invert;
            particle.filterOpacity = effectData.opacity;
            particle.filterSaturate = effectData.saturate;
            particle.filterSepia = effectData.sepia;
            particle.filterUrl = effectData.url;
        }
    }

    async function loadFilterEffect(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addEffect("filter", () => {
                return Promise.resolve(new FilterDrawer());
            });
        });
    }

    const lerp = (a, b, t) => {
        return a + t * (b - a);
    }, smoothstep = (t) => {
        return t * t * (3 - 2 * t);
    }, fract = (x) => {
        return x - Math.floor(x);
    };
    class SmoothValueNoise {
        #coeffW = 29.537;
        #coeffX = 127.1;
        #coeffY = 311.7;
        #coeffZ = 78.233;
        #coeffZW = 37.719;
        #scaleFactor = 43758.5453;
        noise2d(x, y) {
            const x0 = Math.floor(x), y0 = Math.floor(y), x1 = x0 + 1, y1 = y0 + 1, sx = smoothstep(x - x0), sy = smoothstep(y - y0), n00 = this.#valueNoise2D(x0, y0), n10 = this.#valueNoise2D(x1, y0), n01 = this.#valueNoise2D(x0, y1), n11 = this.#valueNoise2D(x1, y1), ix0 = lerp(n00, n10, sx), ix1 = lerp(n01, n11, sx);
            return lerp(ix0, ix1, sy);
        }
        noise3d(x, y, z) {
            const x0 = Math.floor(x), y0 = Math.floor(y), z0 = Math.floor(z), x1 = x0 + 1, y1 = y0 + 1, z1 = z0 + 1, sx = smoothstep(x - x0), sy = smoothstep(y - y0), sz = smoothstep(z - z0), n000 = this.#valueNoise3D(x0, y0, z0), n100 = this.#valueNoise3D(x1, y0, z0), n010 = this.#valueNoise3D(x0, y1, z0), n110 = this.#valueNoise3D(x1, y1, z0), n001 = this.#valueNoise3D(x0, y0, z1), n101 = this.#valueNoise3D(x1, y0, z1), n011 = this.#valueNoise3D(x0, y1, z1), n111 = this.#valueNoise3D(x1, y1, z1), ix00 = lerp(n000, n100, sx), ix10 = lerp(n010, n110, sx), ix01 = lerp(n001, n101, sx), ix11 = lerp(n011, n111, sx), iy0 = lerp(ix00, ix10, sy), iy1 = lerp(ix01, ix11, sy);
            return lerp(iy0, iy1, sz);
        }
        noise4d(x, y, z, w) {
            const x0 = Math.floor(x), y0 = Math.floor(y), z0 = Math.floor(z), w0 = Math.floor(w), x1 = x0 + 1, y1 = y0 + 1, z1 = z0 + 1, w1 = w0 + 1, sx = smoothstep(x - x0), sy = smoothstep(y - y0), sz = smoothstep(z - z0), sw = smoothstep(w - w0), n0000 = this.#valueNoise4D(x0, y0, z0, w0), n1000 = this.#valueNoise4D(x1, y0, z0, w0), n0100 = this.#valueNoise4D(x0, y1, z0, w0), n1100 = this.#valueNoise4D(x1, y1, z0, w0), n0010 = this.#valueNoise4D(x0, y0, z1, w0), n1010 = this.#valueNoise4D(x1, y0, z1, w0), n0110 = this.#valueNoise4D(x0, y1, z1, w0), n1110 = this.#valueNoise4D(x1, y1, z1, w0), n0001 = this.#valueNoise4D(x0, y0, z0, w1), n1001 = this.#valueNoise4D(x1, y0, z0, w1), n0101 = this.#valueNoise4D(x0, y1, z0, w1), n1101 = this.#valueNoise4D(x1, y1, z0, w1), n0011 = this.#valueNoise4D(x0, y0, z1, w1), n1011 = this.#valueNoise4D(x1, y0, z1, w1), n0111 = this.#valueNoise4D(x0, y1, z1, w1), n1111 = this.#valueNoise4D(x1, y1, z1, w1), ix000 = lerp(n0000, n1000, sx), ix100 = lerp(n0100, n1100, sx), ix010 = lerp(n0010, n1010, sx), ix110 = lerp(n0110, n1110, sx), ix001 = lerp(n0001, n1001, sx), ix101 = lerp(n0101, n1101, sx), ix011 = lerp(n0011, n1011, sx), ix111 = lerp(n0111, n1111, sx), iy00 = lerp(ix000, ix100, sy), iy10 = lerp(ix010, ix110, sy), iy01 = lerp(ix001, ix101, sy), iy11 = lerp(ix011, ix111, sy), iz0 = lerp(iy00, iy10, sz), iz1 = lerp(iy01, iy11, sz);
            return lerp(iz0, iz1, sw);
        }
        seed(seed) {
            const s = Math.sin(seed) * 10000;
            this.#coeffX = fract(s * 15731);
            this.#coeffY = fract(s * 789221);
            this.#coeffZ = fract(s * 1376312589);
            this.#coeffZW = fract(s * 974634777);
            this.#coeffW = fract(s * 592558533);
            this.#scaleFactor = 43758.5453;
        }
        #valueNoise2D(x, y) {
            const n = Math.sin(x * this.#coeffX + y * this.#coeffY) * this.#scaleFactor;
            return (n - Math.floor(n)) * 2 - 1;
        }
        #valueNoise3D(x, y, z) {
            const n = Math.sin(x * this.#coeffX + y * this.#coeffY + z * this.#coeffZ) * this.#scaleFactor;
            return (n - Math.floor(n)) * 2 - 1;
        }
        #valueNoise4D(x, y, z, w) {
            const n = Math.sin(x * this.#coeffX + y * this.#coeffY + z * this.#coeffZW + w * this.#coeffW) * this.#scaleFactor;
            return (n - Math.floor(n)) * 2 - 1;
        }
    }

    class FractalNoise {
        #smoothValueNoise;
        constructor() {
            this.#smoothValueNoise = new SmoothValueNoise();
        }
        noise2d(x, y, octaves = 5, persistence = 0.5, lacunarity = 2) {
            let total = 0, frequency = 1, amplitude = 1, maxValue = 0;
            for (let i = 0; i < octaves; i++) {
                total += this.#smoothValueNoise.noise2d(x * frequency, y * frequency) * amplitude;
                maxValue += amplitude;
                amplitude *= persistence;
                frequency *= lacunarity;
            }
            return total / maxValue;
        }
        noise3d(x, y, z, octaves = 5, persistence = 0.5, lacunarity = 2) {
            let total = 0, frequency = 1, amplitude = 1, maxValue = 0;
            for (let i = 0; i < octaves; i++) {
                total += this.#smoothValueNoise.noise3d(x * frequency, y * frequency, z * frequency) * amplitude;
                maxValue += amplitude;
                amplitude *= persistence;
                frequency *= lacunarity;
            }
            return total / maxValue;
        }
        noise4d(x, y, z, w, octaves = 5, persistence = 0.5, lacunarity = 2) {
            let total = 0, frequency = 1, amplitude = 1, maxValue = 0;
            for (let i = 0; i < octaves; i++) {
                total += this.#smoothValueNoise.noise4d(x * frequency, y * frequency, z * frequency, w * frequency) * amplitude;
                maxValue += amplitude;
                amplitude *= persistence;
                frequency *= lacunarity;
            }
            return total / maxValue;
        }
        seed(seed) {
            this.#smoothValueNoise.seed(seed);
        }
    }

    const originCoordinate = 0, firstIndex$4 = 0, empty = 0, optionsSizeOffset = 1, transformDefaultValues = {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
        e: 0,
        f: 0,
    }, defaultOptions$3 = {
        draw: false,
        size: 20,
        increment: 0.004,
        columns: 0,
        rows: 0,
        layers: 0,
        width: 0,
        height: 0,
        factor: {
            angle: 0.02,
            length: 0.01,
        },
        offset: {
            x: 40000,
            y: 40000,
            z: 40000,
        },
    };
    class NoiseFieldGenerator {
        container;
        field;
        noiseGen;
        noiseW;
        options;
        #res;
        constructor(container, noiseGen) {
            this.container = container;
            this.noiseGen = noiseGen;
            this.field = [];
            this.noiseW = 0;
            this.#res = Vector.origin;
            this.options = deepExtend({}, defaultOptions$3);
        }
        generate(particle) {
            const pos = particle.getPosition(), { size } = this.options, sizeFactor = identity$3 / size, point = {
                x: Math.max(Math.floor(pos.x * sizeFactor), originCoordinate),
                y: Math.max(Math.floor(pos.y * sizeFactor), originCoordinate),
                z: Math.max(Math.floor(pos.z * sizeFactor), originCoordinate),
            }, { field } = this, fieldPoint = field[point.x]?.[point.y]?.[point.z];
            if (fieldPoint) {
                this.#res.x = fieldPoint.x;
                this.#res.y = fieldPoint.y;
            }
            else {
                this.#res.x = 0;
                this.#res.y = 0;
            }
            return this.#res;
        }
        init() {
            this.#setup();
        }
        reset() {
        }
        update() {
            this.#calculateField();
            this.noiseW += this.options.increment;
            if (!this.options.draw) {
                return;
            }
            this.container.canvas.render.draw(ctx => {
                this.#drawField(ctx);
            });
        }
        #calculateField() {
            const field = this.field, noiseGen = this.noiseGen, options = this.options, noiseW = this.noiseW, lengthFactor = options.factor.length, angleFactor = options.factor.angle;
            for (let x = 0; x < options.columns; x++) {
                const xColumn = field[x];
                if (!xColumn) {
                    continue;
                }
                for (let y = 0; y < options.rows; y++) {
                    const yColumn = xColumn[y];
                    if (!yColumn) {
                        continue;
                    }
                    for (let z = 0; z < options.layers; z++) {
                        const cell = yColumn[z];
                        if (!cell) {
                            continue;
                        }
                        cell.length = noiseGen.noise4d(x * lengthFactor + options.offset.x, y * lengthFactor + options.offset.y, z * lengthFactor + options.offset.z, noiseW);
                        cell.angle = noiseGen.noise4d(x * angleFactor, y * angleFactor, z * angleFactor, noiseW) * doublePI;
                    }
                }
            }
        }
        #drawField(ctx) {
            const { field, options } = this;
            for (let x = 0; x < options.columns; x++) {
                const xColumn = field[x];
                if (!xColumn) {
                    continue;
                }
                for (let y = 0; y < options.rows; y++) {
                    const yColumn = xColumn[y];
                    if (!yColumn) {
                        continue;
                    }
                    const cell = yColumn[firstIndex$4];
                    if (!cell) {
                        continue;
                    }
                    const { angle, length } = cell;
                    ctx.setTransform(transformDefaultValues.a, transformDefaultValues.b, transformDefaultValues.c, transformDefaultValues.d, x * this.options.size, y * this.options.size);
                    ctx.rotate(angle);
                    ctx.strokeStyle = "white";
                    ctx.beginPath();
                    ctx.moveTo(originCoordinate, originCoordinate);
                    ctx.lineTo(originCoordinate, this.options.size * length);
                    ctx.stroke();
                    ctx.setTransform(transformDefaultValues.a, transformDefaultValues.b, transformDefaultValues.c, transformDefaultValues.d, transformDefaultValues.e, transformDefaultValues.f);
                }
            }
        }
        #initField() {
            const { columns, rows, layers } = this.options;
            this.field = new Array(columns);
            for (let x = 0; x < columns; x++) {
                const newX = new Array(rows);
                for (let y = 0; y < rows; y++) {
                    const newY = new Array(layers);
                    for (let z = 0; z < layers; z++) {
                        newY[z] = Vector.origin;
                    }
                    newX[y] = newY;
                }
                this.field[x] = newX;
            }
        }
        #resetField() {
            const container = this.container, sourceOptions = container.actualOptions.particles.move.path.options, { options } = this;
            options.width = container.canvas.size.width;
            options.height = container.canvas.size.height;
            options.size = sourceOptions["size"] > empty ? sourceOptions["size"] : defaultOptions$3.size;
            options.increment =
                sourceOptions["increment"] > empty
                    ? sourceOptions["increment"]
                    : defaultOptions$3.increment;
            options.draw = !!sourceOptions["draw"];
            const offset = sourceOptions["offset"];
            options.offset.x = offset?.x ?? defaultOptions$3.offset.x;
            options.offset.y = offset?.y ?? defaultOptions$3.offset.y;
            options.offset.z = offset?.z ?? defaultOptions$3.offset.z;
            const factor = sourceOptions["factor"];
            options.factor.angle = factor?.angle ?? defaultOptions$3.factor.angle;
            options.factor.length = factor?.length ?? defaultOptions$3.factor.length;
            options.seed = sourceOptions["seed"];
            this.noiseGen.seed(options.seed ?? getRandom());
            options.columns = Math.floor(options.width / options.size) + optionsSizeOffset;
            options.rows = Math.floor(options.height / options.size) + optionsSizeOffset;
            options.layers = Math.floor(container.zLayers / options.size) + optionsSizeOffset;
            this.#initField();
        }
        #setup() {
            this.noiseW = 0;
            this.#resetField();
            addEventListener("resize", () => {
                this.#resetField();
            });
        }
    }

    class FractalNoiseGenerator extends NoiseFieldGenerator {
        constructor(container) {
            const fractalNoise = new FractalNoise();
            super(container, {
                noise4d: (x, y, z, w) => fractalNoise.noise4d(x, y, z, w),
                seed: seed => {
                    fractalNoise.seed(seed);
                },
            });
        }
    }

    const fractalNoisePathName = "fractalNoise";
    async function loadFractalNoisePath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(fractalNoisePathName, container => {
                return Promise.resolve(new FractalNoiseGenerator(container));
            });
        });
    }

    class AbsorberLife {
        count;
        delay;
        duration;
        wait = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "count", data.count);
            loadRangeProperty(this, "delay", data.delay);
            loadRangeProperty(this, "duration", data.duration);
            loadProperty(this, "wait", data.wait);
        }
    }

    class AbsorberSizeLimit {
        mass = 0;
        radius = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "mass", data.mass);
            loadProperty(this, "radius", data.radius);
        }
    }

    class AbsorberSize extends ValueWithRandom {
        density = 5;
        limit = new AbsorberSizeLimit();
        value = 50;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "density", data.density);
            if (isNumber(data.limit)) {
                this.limit.radius = data.limit;
            }
            else {
                this.limit.load(data.limit);
            }
        }
    }

    class Absorber {
        color;
        destroy;
        draggable;
        life;
        name;
        opacity;
        orbits;
        position;
        size;
        constructor() {
            this.color = new OptionsColor();
            this.color.value = "#000000";
            this.draggable = false;
            this.opacity = 1;
            this.destroy = true;
            this.orbits = false;
            this.life = new AbsorberLife();
            this.size = new AbsorberSize();
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "draggable", data.draggable);
            if (data.life !== undefined) {
                this.life.load(data.life);
            }
            this.name = data.name;
            loadProperty(this, "opacity", data.opacity);
            if (data.position !== undefined) {
                this.position = {};
                if (data.position.x !== undefined) {
                    this.position.x = setRangeValue(data.position.x);
                }
                if (data.position.y !== undefined) {
                    this.position.y = setRangeValue(data.position.y);
                }
            }
            if (data.size !== undefined) {
                this.size.load(data.size);
            }
            loadProperty(this, "destroy", data.destroy);
            loadProperty(this, "orbits", data.orbits);
        }
    }

    const absorbersMode = "absorbers";
    class AbsorbersInteractor extends ExternalInteractorBase {
        handleClickMode;
        maxDistance;
        #dragging = false;
        #draggingAbsorber;
        #instancesManager;
        constructor(container, instancesManager) {
            super(container);
            this.maxDistance = 0;
            this.#instancesManager = instancesManager;
            this.#instancesManager.initContainer(container);
            this.handleClickMode = (mode, interactivityData) => {
                const container = this.container, options = container.actualOptions, absorbers = options.interactivity.modes.absorbers;
                if (!absorbers || mode !== absorbersMode) {
                    return;
                }
                const { clickPosition } = interactivityData.mouse;
                if (clickPosition) {
                    const existingAbsorber = instancesManager
                        .getArray(this.container)
                        .some(t => getDistance(t.position, clickPosition) < t.size);
                    if (existingAbsorber) {
                        return;
                    }
                }
                const absorbersModeOptions = itemFromArray(absorbers) ?? new Absorber();
                void this.#instancesManager.addAbsorber(container, absorbersModeOptions, clickPosition);
            };
        }
        clear() {
        }
        init() {
        }
        interact(interactivityData, delta) {
            for (const particle of this.container.particles.filter(p => this.isEnabled(interactivityData, p))) {
                for (const absorber of this.#instancesManager.getArray(this.container)) {
                    if (absorber.options.draggable) {
                        const mouse = interactivityData.mouse;
                        if (mouse.clicking && mouse.downPosition) {
                            const mouseDist = getDistance(absorber.position, mouse.downPosition);
                            if (mouseDist <= absorber.size) {
                                this.#dragging = true;
                                this.#draggingAbsorber = absorber;
                            }
                        }
                        else {
                            this.#dragging = false;
                            this.#draggingAbsorber = undefined;
                        }
                        if (this.#dragging && this.#draggingAbsorber == absorber && mouse.position) {
                            absorber.position.x = mouse.position.x;
                            absorber.position.y = mouse.position.y;
                        }
                    }
                    absorber.attract(particle, delta);
                    if (particle.destroyed) {
                        break;
                    }
                }
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity).events;
            if (!mouse.clickPosition || !events.onClick.enable) {
                return false;
            }
            return isInArray(absorbersMode, events.onClick.mode);
        }
        loadModeOptions(options, ...sources) {
            options.absorbers ??= [];
            for (const source of sources) {
                if (!source) {
                    continue;
                }
                if (isArray(source.absorbers)) {
                    for (const absorber of source.absorbers) {
                        const tmp = new Absorber();
                        tmp.load(absorber);
                        options.absorbers.push(tmp);
                    }
                }
                else {
                    const tmp = new Absorber();
                    tmp.load(source.absorbers);
                    options.absorbers.push(tmp);
                }
            }
        }
        reset() {
        }
    }

    const instancesManagers = new WeakMap();
    function getAbsorbersInstancesManager(e) {
        const pluginManager = e.pluginManager;
        let manager = instancesManagers.get(pluginManager);
        if (!manager) {
            manager = Promise.resolve().then(function () { return AbsorbersInstancesManager$1; })
                .then(({ AbsorbersInstancesManager }) => new AbsorbersInstancesManager(pluginManager))
                .catch((error) => {
                instancesManagers.delete(pluginManager);
                throw error;
            });
            instancesManagers.set(pluginManager, manager);
        }
        return manager;
    }

    async function loadAbsorbersInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const pluginManager = e.pluginManager, instancesManager = await getAbsorbersInstancesManager(e);
            ensureInteractivityPluginLoaded(e);
            pluginManager.addInteractor?.("externalAbsorbers", container => {
                return Promise.resolve(new AbsorbersInteractor(container, instancesManager));
            });
        });
    }

    class AbsorbersPlugin {
        id = "absorbers";
        #instancesManager;
        constructor(instancesManager) {
            this.#instancesManager = instancesManager;
        }
        async getPlugin(container) {
            const { AbsorbersPluginInstance } = await Promise.resolve().then(function () { return AbsorbersPluginInstance$1; });
            return new AbsorbersPluginInstance(container, this.#instancesManager);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            if (source?.absorbers) {
                options.absorbers = executeOnSingleOrMultiple(source.absorbers, absorber => {
                    const tmp = new Absorber();
                    tmp.load(absorber);
                    return tmp;
                });
            }
        }
        needsPlugin(options) {
            if (!options) {
                return false;
            }
            const absorbers = options.absorbers;
            if (isArray(absorbers)) {
                return !!absorbers.length;
            }
            else if (absorbers) {
                return true;
            }
            return false;
        }
    }

    async function loadAbsorbersPluginSimple(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const pluginManager = e.pluginManager, instancesManager = await getAbsorbersInstancesManager(e);
            pluginManager.addPlugin(new AbsorbersPlugin(instancesManager));
        });
    }

    async function loadAbsorbersPlugin(engine) {
        await loadAbsorbersPluginSimple(engine);
        await loadAbsorbersInteraction(engine);
    }

    class DestroyBounds {
        bottom;
        left;
        right;
        top;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "bottom", data.bottom);
            loadRangeProperty(this, "left", data.left);
            loadRangeProperty(this, "right", data.right);
            loadRangeProperty(this, "top", data.top);
        }
    }

    var DestroyMode;
    (function (DestroyMode) {
        DestroyMode["explode"] = "explode";
        DestroyMode["none"] = "none";
        DestroyMode["split"] = "split";
    })(DestroyMode || (DestroyMode = {}));

    class Explode {
        maxSizeFactor = 3;
        speed = 2;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "maxSizeFactor", data.maxSizeFactor);
            loadProperty(this, "speed", data.speed);
        }
    }

    class SplitFactor extends ValueWithRandom {
        value = 3;
    }

    class SplitRate extends ValueWithRandom {
        value = { min: 4, max: 9 };
    }

    class Split {
        count = 1;
        factor = new SplitFactor();
        fillColor;
        fillColorOffset;
        particles;
        rate = new SplitRate();
        sizeOffset = true;
        strokeColor;
        strokeColorOffset;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.fillColor !== undefined) {
                this.fillColor = OptionsColor.create(this.fillColor, data.fillColor);
            }
            if (data.strokeColor !== undefined) {
                this.strokeColor = OptionsColor.create(this.strokeColor, data.strokeColor);
            }
            loadProperty(this, "count", data.count);
            this.factor.load(data.factor);
            this.rate.load(data.rate);
            this.particles = executeOnSingleOrMultiple(data.particles, particles => {
                return deepExtend({}, particles);
            });
            loadProperty(this, "sizeOffset", data.sizeOffset);
            if (data.fillColorOffset) {
                this.fillColorOffset = this.fillColorOffset ?? {};
                if (data.fillColorOffset.h !== undefined) {
                    this.fillColorOffset.h = data.fillColorOffset.h;
                }
                if (data.fillColorOffset.s !== undefined) {
                    this.fillColorOffset.s = data.fillColorOffset.s;
                }
                if (data.fillColorOffset.l !== undefined) {
                    this.fillColorOffset.l = data.fillColorOffset.l;
                }
            }
            if (data.strokeColorOffset) {
                this.strokeColorOffset = this.strokeColorOffset ?? {};
                if (data.strokeColorOffset.h !== undefined) {
                    this.strokeColorOffset.h = data.strokeColorOffset.h;
                }
                if (data.strokeColorOffset.s !== undefined) {
                    this.strokeColorOffset.s = data.strokeColorOffset.s;
                }
                if (data.strokeColorOffset.l !== undefined) {
                    this.strokeColorOffset.l = data.strokeColorOffset.l;
                }
            }
        }
    }

    let Destroy$1 = class Destroy {
        bounds = new DestroyBounds();
        explode = new Explode();
        mode = DestroyMode.none;
        split = new Split();
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.mode) {
                this.mode = data.mode;
            }
            if (data.bounds) {
                this.bounds.load(data.bounds);
            }
            this.explode.load(data.explode);
            this.split.load(data.split);
        }
    };

    const defaultOffset = 0, minDestroySize = 0.5, defaultSplitCount = 0, increment = 1, unbreakableTime = 500, minSplitCount = 0, minHue = 0, hueRange = 360, minSaturation = 0, maxSaturation = 100, minLightness = 0, maxLightness = 100;
    function createParentColor(parentColor) {
        return AnimatableColor.create(undefined, {
            value: {
                hsl: parentColor,
            },
        });
    }
    function createOffsetColor(parentColor, offset) {
        const offsetH = getRangeValue(offset.h ?? defaultOffset), offsetS = getRangeValue(offset.s ?? defaultOffset), offsetL = getRangeValue(offset.l ?? defaultOffset), h = (parentColor.h + offsetH) % hueRange, s = Math.max(minSaturation, Math.min(maxSaturation, parentColor.s + offsetS)), l = Math.max(minLightness, Math.min(maxLightness, parentColor.l + offsetL));
        return AnimatableColor.create(undefined, {
            value: {
                hsl: {
                    h: h < minHue ? h + hueRange : h,
                    s,
                    l,
                },
            },
        });
    }
    function resolveSplitColor(offset, splitColor, splitParticlesColor, parentColor) {
        if (offset && parentColor) {
            return createOffsetColor(parentColor, offset);
        }
        if (splitColor) {
            return AnimatableColor.create(undefined, splitColor);
        }
        if (splitParticlesColor) {
            return AnimatableColor.create(undefined, splitParticlesColor);
        }
        return parentColor ? createParentColor(parentColor) : undefined;
    }
    function addSplitParticle(pluginManager, container, parent, splitParticlesOptions) {
        const destroyOptions = parent.options.destroy;
        if (!destroyOptions) {
            return;
        }
        const splitOptions = destroyOptions.split, splitParticleOptions = loadParticlesOptions(pluginManager, container, parent.options), splitFillColor = itemFromSingleOrMultiple(splitOptions.fillColor), splitStrokeColor = itemFromSingleOrMultiple(splitOptions.strokeColor), parentFillColor = parent.getFillColor(), parentStrokeColor = parent.getStrokeColor();
        splitParticleOptions.move.load({
            center: {
                x: parent.position.x,
                y: parent.position.y,
                mode: exports.PixelMode.precise,
            },
        });
        const factor = identity$3 / getRangeValue(splitOptions.factor.value), sizeOptions = splitParticleOptions["size"];
        if (sizeOptions) {
            if (isNumber(sizeOptions.value)) {
                sizeOptions.value *= factor;
            }
            else {
                sizeOptions.value.min *= factor;
                sizeOptions.value.max *= factor;
            }
        }
        splitParticleOptions.load(splitParticlesOptions);
        const splitParticlePaintOptions = itemFromSingleOrMultiple(splitParticleOptions.paint), splitParticleFillOptions = splitParticlePaintOptions?.fill, splitParticleStrokeOptions = splitParticlePaintOptions?.stroke, fillColor = resolveSplitColor(splitOptions.fillColorOffset, splitFillColor, splitParticleFillOptions?.color, parentFillColor), strokeColor = resolveSplitColor(splitOptions.strokeColorOffset, splitStrokeColor, splitParticleStrokeOptions?.color, parentStrokeColor);
        if (fillColor && splitParticleFillOptions) {
            splitParticleFillOptions.color = fillColor;
        }
        if (strokeColor && splitParticleStrokeOptions) {
            splitParticleStrokeOptions.color = strokeColor;
        }
        const offset = splitOptions.sizeOffset ? setRangeValue(-parent.size.value, parent.size.value) : defaultOffset, position = {
            x: parent.position.x + randomInRangeValue(offset),
            y: parent.position.y + randomInRangeValue(offset),
        };
        return container.particles.addParticle(position, splitParticleOptions, parent.group, (particle) => {
            if (particle.size.value < minDestroySize) {
                return false;
            }
            particle.velocity.length = randomInRangeValue(setRangeValue(parent.velocity.length, particle.velocity.length));
            particle.splitCount = (parent.splitCount ?? defaultSplitCount) + increment;
            particle.unbreakable = true;
            particle.unbreakableUntil = performance.now() + unbreakableTime;
            return true;
        });
    }
    function split(pluginManager, container, particle) {
        const destroyOptions = particle.options.destroy;
        if (!destroyOptions) {
            return;
        }
        const splitOptions = destroyOptions.split;
        if (splitOptions.count >= minSplitCount) {
            if (particle.splitCount === undefined || particle.splitCount > splitOptions.count) {
                return;
            }
            particle.splitCount++;
        }
        const rate = getRangeValue(splitOptions.rate.value), particlesSplitOptions = itemFromSingleOrMultiple(splitOptions.particles);
        for (let i = 0; i < rate; i++) {
            addSplitParticle(pluginManager, container, particle, particlesSplitOptions);
        }
    }

    const defaultDeltaFactor$1 = 1, fpsFactor = 60, minExplodeSpeed = 0.01, maxExplodeProgress = 1;
    class DestroyUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
        }
        init(particle) {
            const container = this.#container, particlesOptions = particle.options, destroyOptions = particlesOptions.destroy;
            if (!destroyOptions) {
                return;
            }
            particle.exploding = undefined;
            particle.splitCount = 0;
            const destroyBoundsOptions = destroyOptions.bounds;
            particle.destroyBounds ??= {};
            const { bottom, left, right, top } = destroyBoundsOptions, { destroyBounds } = particle, canvasSize = container.canvas.size;
            if (bottom) {
                destroyBounds.bottom = (getRangeValue(bottom) * canvasSize.height) / percentDenominator;
            }
            if (left) {
                destroyBounds.left = (getRangeValue(left) * canvasSize.width) / percentDenominator;
            }
            if (right) {
                destroyBounds.right = (getRangeValue(right) * canvasSize.width) / percentDenominator;
            }
            if (top) {
                destroyBounds.top = (getRangeValue(top) * canvasSize.height) / percentDenominator;
            }
        }
        isEnabled(particle) {
            const destroyParticle = particle;
            return !destroyParticle.destroyed || !!destroyParticle.exploding;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "destroy", Destroy$1, ...sources);
        }
        particleDestroyed(particle, override) {
            if (override) {
                return;
            }
            const destroyOptions = particle.options.destroy;
            switch (destroyOptions?.mode) {
                case DestroyMode.split:
                    split(this.#pluginManager, this.#container, particle);
                    break;
                case DestroyMode.explode: {
                    if (particle.exploding) {
                        particle.destroyed = false;
                        break;
                    }
                    const { explode } = destroyOptions, initialSize = particle.size.value, maxSize = initialSize * explode.maxSizeFactor, opacity = particle.getOpacity();
                    particle.exploding = {
                        initialFillOpacity: opacity.fillOpacity,
                        initialSize,
                        initialStrokeOpacity: opacity.strokeOpacity,
                        maxSize,
                        progress: 0,
                        speed: Math.max(explode.speed, minExplodeSpeed),
                    };
                    particle.fillOpacity = opacity.fillOpacity;
                    particle.strokeOpacity = opacity.strokeOpacity;
                    particle.destroyed = false;
                    break;
                }
            }
        }
        update(particle, delta) {
            if (particle.exploding) {
                const explosionState = particle.exploding, deltaFactor = delta.factor || defaultDeltaFactor$1;
                explosionState.progress = Math.min(maxExplodeProgress, explosionState.progress + (explosionState.speed * deltaFactor) / fpsFactor);
                const progress = explosionState.progress;
                particle.size.value =
                    explosionState.initialSize + (explosionState.maxSize - explosionState.initialSize) * progress;
                particle.fillOpacity = explosionState.initialFillOpacity * (maxExplodeProgress - progress);
                particle.strokeOpacity = explosionState.initialStrokeOpacity * (maxExplodeProgress - progress);
                if (progress >= maxExplodeProgress) {
                    particle.exploding = undefined;
                    particle.destroy(true);
                }
                return;
            }
            if (particle.unbreakableUntil !== undefined && performance.now() >= particle.unbreakableUntil) {
                particle.unbreakable = false;
                particle.unbreakableUntil = undefined;
            }
            const position = particle.getPosition(), bounds = particle.destroyBounds;
            if (!bounds) {
                return;
            }
            if ((bounds.bottom !== undefined && position.y >= bounds.bottom) ||
                (bounds.left !== undefined && position.x <= bounds.left) ||
                (bounds.right !== undefined && position.x >= bounds.right) ||
                (bounds.top !== undefined && position.y <= bounds.top)) {
                particle.destroy();
            }
        }
    }

    async function loadDestroyUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("destroy", container => {
                return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
            });
        });
    }

    class EmittersCircleShape extends EmitterShapeBase {
        constructor(position, size, fill, options) {
            super(position, size, fill, options);
        }
        async init() {
        }
        randomPosition() {
            const size = this.size, fill = this.fill, position = this.position, generateTheta = (x, y) => {
                const u = getRandom() * quarter$2, theta = Math.atan((y / x) * Math.tan(doublePI * u)), v = getRandom();
                if (v < quarter$2) {
                    return theta;
                }
                else if (v < double * quarter$2) {
                    return Math.PI - theta;
                }
                else if (v < double * quarter$2 + quarter$2) {
                    return Math.PI + theta;
                }
                else {
                    return -theta;
                }
            }, radius = (x, y, theta) => (x * y) / Math.sqrt((y * Math.cos(theta)) ** squareExp + (x * Math.sin(theta)) ** squareExp), [a, b] = [size.width * half$2, size.height * half$2], randomTheta = generateTheta(a, b), maxRadius = radius(a, b, randomTheta), randomRadius = fill ? maxRadius * Math.sqrt(getRandom()) : maxRadius;
            return {
                position: {
                    x: position.x + randomRadius * Math.cos(randomTheta),
                    y: position.y + randomRadius * Math.sin(randomTheta),
                },
            };
        }
    }

    class EmittersCircleShapeGenerator {
        generate(_container, position, size, fill, options) {
            return new EmittersCircleShape(position, size, fill, options);
        }
    }

    async function loadEmittersShapeCircle(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureEmittersPluginLoaded(e);
            e.pluginManager.addEmitterShapeGenerator?.("circle", new EmittersCircleShapeGenerator());
        });
    }

    const sides$5 = 4;
    var Sides;
    (function (Sides) {
        Sides[Sides["TopLeft"] = 0] = "TopLeft";
        Sides[Sides["TopRight"] = 1] = "TopRight";
        Sides[Sides["BottomRight"] = 2] = "BottomRight";
        Sides[Sides["BottomLeft"] = 3] = "BottomLeft";
    })(Sides || (Sides = {}));
    function randomSquareCoordinate(position, offset) {
        return position + offset * (getRandom() - half$2);
    }
    function getRandomSize(sides) {
        return Math.floor(getRandom() * sides);
    }
    class EmittersSquareShape extends EmitterShapeBase {
        constructor(position, size, fill, options) {
            super(position, size, fill, options);
        }
        async init() {
        }
        randomPosition() {
            const fill = this.fill, position = this.position, size = this.size;
            if (fill) {
                return {
                    position: {
                        x: randomSquareCoordinate(position.x, size.width),
                        y: randomSquareCoordinate(position.y, size.height),
                    },
                };
            }
            else {
                const halfW = size.width * half$2, halfH = size.height * half$2, side = getRandomSize(sides$5), v = (getRandom() - half$2) * double;
                switch (side) {
                    case Sides.TopLeft:
                        return {
                            position: {
                                x: position.x + v * halfW,
                                y: position.y - halfH,
                            },
                        };
                    case Sides.TopRight:
                        return {
                            position: {
                                x: position.x - halfW,
                                y: position.y + v * halfH,
                            },
                        };
                    case Sides.BottomRight:
                        return {
                            position: {
                                x: position.x + v * halfW,
                                y: position.y + halfH,
                            },
                        };
                    case Sides.BottomLeft:
                    default:
                        return {
                            position: {
                                x: position.x + halfW,
                                y: position.y + v * halfH,
                            },
                        };
                }
            }
        }
    }

    class EmittersSquareShapeGenerator {
        generate(_container, position, size, fill, options) {
            return new EmittersSquareShape(position, size, fill, options);
        }
    }

    async function loadEmittersShapeSquare(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureEmittersPluginLoaded(e);
            e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
        });
    }

    const defaultMomentumFactor$1 = 0.03, defaultPreserveMomentum = false;
    class Drag {
        momentumFactor = defaultMomentumFactor$1;
        preserveMomentum = defaultPreserveMomentum;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "momentumFactor", data.momentumFactor);
            loadProperty(this, "preserveMomentum", data.preserveMomentum);
        }
    }

    const clickReleaseDelayMs = 50, defaultMomentumFactor = 0.03, dragMode = "drag", firstSampleIndex = 0, lastSampleOffset = 1, maxMomentumSamples = 5, minSamplesForMomentum = 2, momentumToVelocityFactor = millisecondsToSeconds$1 / defaultFps, zeroValue = 0;
    class Dragger extends ExternalInteractorBase {
        maxDistance = 0;
        #dragStartClickTime;
        #dragStartClickingFalseTime;
        #draggedParticle;
        #grabOffset;
        #lastMousePosition;
        #momentumSamples = [];
        #mouseDownHandled = false;
        #savedVelocity;
        constructor(container) {
            super(container);
        }
        clear(_particle, _delta) {
        }
        init() {
        }
        interact(interactivityData, _delta) {
            const mouse = interactivityData.mouse, mousePos = mouse.position;
            if (mousePos) {
                this.#lastMousePosition = mousePos;
            }
            if (this.#draggedParticle) {
                const now = performance.now();
                if (!mouse.clicking) {
                    this.#dragStartClickingFalseTime ??= now;
                }
                else {
                    this.#dragStartClickingFalseTime = undefined;
                }
                const hasStableClickEndWithoutClickTime = this.#dragStartClickTime === undefined &&
                    this.#dragStartClickingFalseTime !== undefined &&
                    now - this.#dragStartClickingFalseTime >= clickReleaseDelayMs;
                if (!mouse.inside || this.#hasClickEnded(mouse) || hasStableClickEndWithoutClickTime) {
                    this.#releaseDragged();
                    this.#mouseDownHandled = false;
                    return;
                }
                const pointerPos = mousePos ?? this.#lastMousePosition;
                if (!pointerPos) {
                    return;
                }
                this.#momentumSamples.push({ x: pointerPos.x, y: pointerPos.y, t: now });
                if (this.#momentumSamples.length > maxMomentumSamples) {
                    this.#momentumSamples.shift();
                }
                const targetX = pointerPos.x + (this.#grabOffset?.x ?? zeroValue), targetY = pointerPos.y + (this.#grabOffset?.y ?? zeroValue);
                this.#draggedParticle.position.x = targetX - this.#draggedParticle.offset.x;
                this.#draggedParticle.position.y = targetY - this.#draggedParticle.offset.y;
                this.#draggedParticle.velocity.x = zeroValue;
                this.#draggedParticle.velocity.y = zeroValue;
                this.#draggedParticle.initialPosition.x = this.#draggedParticle.position.x;
                this.#draggedParticle.initialPosition.y = this.#draggedParticle.position.y;
                this.#draggedParticle.misplaced = false;
                return;
            }
            if (!mouse.clicking) {
                this.#releaseDragged();
                this.#mouseDownHandled = false;
                return;
            }
            if (this.#mouseDownHandled) {
                return;
            }
            this.#mouseDownHandled = true;
            const downPos = mouse.downPosition ?? mousePos ?? this.#lastMousePosition, closest = this.#findParticleUnderCursor(interactivityData, downPos);
            if (!closest || !mousePos) {
                if (!closest) {
                    this.#mouseDownHandled = false;
                }
                return;
            }
            const renderedPos = closest.getPosition();
            this.#draggedParticle = closest;
            this.#dragStartClickTime = mouse.clickTime;
            this.#grabOffset = {
                x: renderedPos.x - mousePos.x,
                y: renderedPos.y - mousePos.y,
            };
            this.#savedVelocity = { x: closest.velocity.x, y: closest.velocity.y };
            this.#dragStartClickingFalseTime = undefined;
            this.#momentumSamples = [{ x: mousePos.x, y: mousePos.y, t: performance.now() }];
            closest.velocity.x = zeroValue;
            closest.velocity.y = zeroValue;
            closest.position.x = renderedPos.x - closest.offset.x;
            closest.position.y = renderedPos.y - closest.offset.y;
            closest.initialPosition.x = closest.position.x;
            closest.initialPosition.y = closest.position.y;
            closest.misplaced = false;
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, mouse = interactivityData.mouse, events = (particle?.interactivity ?? container.actualOptions.interactivity)?.events;
            if (this.#draggedParticle || this.#mouseDownHandled) {
                return true;
            }
            return !!events?.onClick.enable && mouse.clicking && !!mouse.position && isInArray(dragMode, events.onClick.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "drag", Drag, ...sources);
        }
        reset(_interactivityData, _particle) {
        }
        #findParticleUnderCursor(interactivityData, mousePos) {
            if (!mousePos) {
                return;
            }
            const candidates = this.container.particles.filter(p => this.isEnabled(interactivityData, p));
            let closest, closestDist = Infinity;
            for (const candidate of candidates) {
                const dist = getDistance(candidate.getPosition(), mousePos), radius = candidate.getRadius();
                if (!Number.isFinite(dist) || !Number.isFinite(radius) || dist > radius || dist >= closestDist) {
                    continue;
                }
                closest = candidate;
                closestDist = dist;
            }
            return closest;
        }
        #hasClickEnded(mouse) {
            return (this.#dragStartClickTime !== undefined &&
                mouse.clickTime !== undefined &&
                mouse.clickTime !== this.#dragStartClickTime);
        }
        #releaseDragged() {
            if (this.#draggedParticle) {
                const dragOptions = this.container.actualOptions.interactivity?.modes.drag, preserveMomentum = dragOptions?.preserveMomentum ?? false;
                if (preserveMomentum && this.#momentumSamples.length >= minSamplesForMomentum) {
                    const first = this.#momentumSamples[firstSampleIndex], last = this.#momentumSamples[this.#momentumSamples.length - lastSampleOffset];
                    if (first && last) {
                        const dt = last.t - first.t;
                        if (dt > zeroValue) {
                            const factor = dragOptions?.momentumFactor ?? defaultMomentumFactor;
                            this.#draggedParticle.velocity.x = ((last.x - first.x) / dt) * momentumToVelocityFactor * factor;
                            this.#draggedParticle.velocity.y = ((last.y - first.y) / dt) * momentumToVelocityFactor * factor;
                        }
                        else if (this.#savedVelocity) {
                            this.#draggedParticle.velocity.x = this.#savedVelocity.x;
                            this.#draggedParticle.velocity.y = this.#savedVelocity.y;
                        }
                    }
                    else if (this.#savedVelocity) {
                        this.#draggedParticle.velocity.x = this.#savedVelocity.x;
                        this.#draggedParticle.velocity.y = this.#savedVelocity.y;
                    }
                }
                else if (this.#savedVelocity) {
                    this.#draggedParticle.velocity.x = this.#savedVelocity.x;
                    this.#draggedParticle.velocity.y = this.#savedVelocity.y;
                }
            }
            this.#draggedParticle = undefined;
            this.#dragStartClickTime = undefined;
            this.#dragStartClickingFalseTime = undefined;
            this.#grabOffset = undefined;
            this.#lastMousePosition = undefined;
            this.#momentumSamples = [];
            this.#savedVelocity = undefined;
        }
    }

    async function loadExternalDragInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalDrag", container => {
                return Promise.resolve(new Dragger(container));
            });
        });
    }

    class TrailColorWeight {
        x = 0;
        y = 0;
        load(data) {
            if (!data) {
                return;
            }
            loadProperty(this, "x", data.x);
            loadProperty(this, "y", data.y);
        }
    }

    class TrailColorComponent {
        value;
        weights = new TrailColorWeight();
        load(data) {
            if (!data) {
                return;
            }
            if (data.weights) {
                this.weights ??= new TrailColorWeight();
                this.weights.load(data.weights);
            }
            if (!isNull(data.value)) {
                this.value = setRangeValue(data.value);
            }
        }
    }

    class TrailColorCoords {
        h = new TrailColorComponent();
        l = new TrailColorComponent();
        s = new TrailColorComponent();
        load(data) {
            if (!data) {
                return;
            }
            if (data.h) {
                this.h ??= new TrailColorComponent();
                this.h.load(data.h);
            }
            if (data.s) {
                this.s ??= new TrailColorComponent();
                this.s.load(data.s);
            }
            if (data.l) {
                this.l ??= new TrailColorComponent();
                this.l.load(data.l);
            }
        }
    }

    let Trail$1 = class Trail {
        colorCoords = new TrailColorCoords();
        delay = 1;
        particles;
        pauseOnStop = false;
        quantity = 1;
        load(data) {
            if (isNull(data))
                return;
            loadProperty(this, "delay", data.delay);
            loadProperty(this, "quantity", data.quantity);
            loadProperty(this, "pauseOnStop", data.pauseOnStop);
            if (data.particles !== undefined) {
                this.particles = deepExtend({}, data.particles);
            }
            if (data.colorCoords) {
                this.colorCoords ??= new TrailColorCoords();
                this.colorCoords.load(data.colorCoords);
            }
        }
    };

    const trailMode = "trail", defaultMin = 0, defaultWeight = 0;
    class TrailMaker extends ExternalInteractorBase {
        maxDistance = 0;
        #delay;
        #lastPosition;
        #pluginManager;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.#delay = 0;
        }
        clear() {
        }
        init() {
        }
        interact(interactivityData, delta) {
            const container = this.container;
            if (!container.retina.reduceFactor)
                return;
            const options = container.actualOptions, trailOptions = options.interactivity?.modes.trail;
            if (!trailOptions)
                return;
            const optDelay = (trailOptions.delay * millisecondsToSeconds$1) / this.container.retina.reduceFactor;
            if (this.#delay < optDelay) {
                this.#delay += delta.value;
            }
            if (this.#delay < optDelay)
                return;
            const mousePos = interactivityData.mouse.position, canEmit = !(trailOptions.pauseOnStop &&
                (mousePos === this.#lastPosition ||
                    (mousePos?.x === this.#lastPosition?.x && mousePos?.y === this.#lastPosition?.y)));
            if (mousePos) {
                this.#lastPosition = { ...mousePos };
            }
            else {
                this.#lastPosition = undefined;
            }
            if (canEmit && mousePos) {
                let particleOptions = trailOptions.particles;
                const colorCoords = trailOptions.colorCoords;
                if (colorCoords) {
                    const { width, height } = container.canvas.size, norm = {
                        x: mousePos.x / width,
                        y: mousePos.y / height,
                    }, hasWeights = (comp) => {
                        return !!(comp?.weights?.x ?? comp?.weights?.y);
                    }, calculateValue = (comp, originalValue, defaultMax) => {
                        if (!hasWeights(comp))
                            return undefined;
                        const w = comp?.weights, factor = norm.x * (w?.x ?? defaultWeight) + norm.y * (w?.y ?? defaultWeight), rangeSource = comp?.value ?? originalValue, min = getRangeMin(rangeSource ?? defaultMin), max = getRangeMax(rangeSource ?? defaultMax), result = min + factor * (max - min);
                        return Math.min(max, Math.max(min, result));
                    }, trailPaintOptions = trailOptions.particles?.paint
                        ? itemFromSingleOrMultiple(trailOptions.particles.paint)
                        : undefined, fillData = trailPaintOptions?.fill, baseHsl = fillData
                        ? rangeColorToHsl(this.#pluginManager, AnimatableColor.create(undefined, fillData.color))
                        : undefined, h = calculateValue(colorCoords.h, baseHsl?.h, hMax), s = calculateValue(colorCoords.s, baseHsl?.s, sMax), l = calculateValue(colorCoords.l, baseHsl?.l, lMax);
                    if (h !== undefined || s !== undefined || l !== undefined) {
                        particleOptions = deepExtend({}, trailOptions.particles, {
                            paint: {
                                fill: {
                                    color: {
                                        value: {
                                            h: h ?? baseHsl?.h,
                                            s: s ?? baseHsl?.s,
                                            l: l ?? baseHsl?.l,
                                        },
                                    },
                                },
                            },
                        });
                    }
                }
                container.particles.push(trailOptions.quantity, mousePos, particleOptions);
            }
            this.#delay -= optDelay;
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            return (!!events &&
                ((mouse.clicking && mouse.inside && !!mouse.position && isInArray(trailMode, events.onClick.mode)) ||
                    (mouse.inside && !!mouse.position && isInArray(trailMode, events.onHover.mode))));
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "trail", Trail$1, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalTrailInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalTrail", container => {
                return Promise.resolve(new TrailMaker(e.pluginManager, container));
            });
        });
    }

    var RollMode;
    (function (RollMode) {
        RollMode["both"] = "both";
        RollMode["horizontal"] = "horizontal";
        RollMode["vertical"] = "vertical";
    })(RollMode || (RollMode = {}));

    const maxAngle$4 = 360;
    function initParticle(pluginManager, particle) {
        const rollOpt = particle.options.roll;
        if (!rollOpt?.enable) {
            particle.roll = {
                enable: false,
                horizontal: false,
                vertical: false,
                angle: 0,
                speed: 0,
            };
            return;
        }
        particle.roll = {
            enable: rollOpt.enable,
            horizontal: rollOpt.mode === RollMode.horizontal || rollOpt.mode === RollMode.both,
            vertical: rollOpt.mode === RollMode.vertical || rollOpt.mode === RollMode.both,
            angle: getRandom() * doublePI,
            speed: getRangeValue(rollOpt.speed) / maxAngle$4,
        };
        if (rollOpt.backColor) {
            particle.backColor = rangeColorToHsl(pluginManager, rollOpt.backColor);
        }
        else if (rollOpt.darken.enable && rollOpt.enlighten.enable) {
            const alterType = getRandom() >= half$2 ? exports.AlterType.darken : exports.AlterType.enlighten;
            particle.roll.alter = {
                type: alterType,
                value: getRangeValue(alterType === exports.AlterType.darken ? rollOpt.darken.value : rollOpt.enlighten.value),
            };
        }
        else if (rollOpt.darken.enable) {
            particle.roll.alter = {
                type: exports.AlterType.darken,
                value: getRangeValue(rollOpt.darken.value),
            };
        }
        else if (rollOpt.enlighten.enable) {
            particle.roll.alter = {
                type: exports.AlterType.enlighten,
                value: getRangeValue(rollOpt.enlighten.value),
            };
        }
    }
    function updateRoll(particle, delta) {
        const roll = particle.options.roll, data = particle.roll;
        if (!data || !roll?.enable) {
            return;
        }
        const speed = data.speed * delta.factor, max = doublePI;
        data.angle += speed;
        if (data.angle > max) {
            data.angle -= max;
        }
    }

    class RollLight {
        enable = false;
        value = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "value", data.value);
        }
    }

    class Roll {
        backColor;
        darken = new RollLight();
        enable = false;
        enlighten = new RollLight();
        mode = RollMode.vertical;
        speed = 25;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.backColor !== undefined) {
                this.backColor = OptionsColor.create(this.backColor, data.backColor);
            }
            this.darken.load(data.darken);
            loadProperty(this, "enable", data.enable);
            this.enlighten.load(data.enlighten);
            loadProperty(this, "mode", data.mode);
            loadRangeProperty(this, "speed", data.speed);
        }
    }

    class RollUpdater {
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        getTransformValues(particle) {
            const roll = particle.roll?.enable && particle.roll, rollHorizontal = roll && roll.horizontal, rollVertical = roll && roll.vertical;
            return {
                a: rollHorizontal ? Math.cos(roll.angle) : undefined,
                d: rollVertical ? Math.sin(roll.angle) : undefined,
            };
        }
        init(particle) {
            initParticle(this.#pluginManager, particle);
        }
        isEnabled(particle) {
            const roll = particle.options.roll;
            return !particle.destroyed && !particle.spawning && !!roll?.enable;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "roll", Roll, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            updateRoll(particle, delta);
        }
    }

    async function loadRollUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("roll", () => {
                return Promise.resolve(new RollUpdater(e.pluginManager));
            });
        });
    }

    class Blend {
        enable = false;
        mode = "destination-out";
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "enable", data.enable);
        }
    }

    class BlendPlugin {
        id = "blend";
        async getPlugin(container) {
            const { BlendPluginInstance } = await Promise.resolve().then(function () { return BlendPluginInstance$1; });
            return new BlendPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let blendOptions = options.blend;
            if (!blendOptions?.load) {
                options.blend = blendOptions = new Blend();
            }
            blendOptions.load(source?.blend);
        }
        loadParticlesOptions(_container, options, source) {
            options.blend ??= new Blend();
            options.blend.load(source?.blend);
        }
        needsPlugin(options) {
            return !!options?.blend?.enable || !!options?.particles?.blend?.enable;
        }
    }

    async function loadBlendPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new BlendPlugin());
        });
    }

    const minAngle$2 = 0;
    function drawCircle(data) {
        const { context, particle, radius } = data;
        particle.circleRange ??= { min: minAngle$2, max: doublePI };
        const circleRange = particle.circleRange;
        context.arc(originPoint.x, originPoint.y, radius, circleRange.min, circleRange.max, false);
    }

    const sides$4 = 12, maxAngle$3 = 360, minAngle$1 = 0;
    class CircleDrawer {
        draw(data) {
            drawCircle(data);
        }
        getSidesCount() {
            return sides$4;
        }
        particleInit(_container, particle) {
            const shapeData = particle.shapeData, angle = shapeData?.angle ?? {
                max: maxAngle$3,
                min: minAngle$1,
            };
            particle.circleRange = isObject(angle)
                ? { min: degToRad(angle.min), max: degToRad(angle.max) }
                : {
                    min: minAngle$1,
                    max: degToRad(angle),
                };
        }
    }

    async function loadCircleShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["circle"], () => {
                return Promise.resolve(new CircleDrawer());
            });
        });
    }

    var RgbIndexes$1;
    (function (RgbIndexes) {
        RgbIndexes[RgbIndexes["r"] = 1] = "r";
        RgbIndexes[RgbIndexes["g"] = 2] = "g";
        RgbIndexes[RgbIndexes["b"] = 3] = "b";
        RgbIndexes[RgbIndexes["a"] = 4] = "a";
    })(RgbIndexes$1 || (RgbIndexes$1 = {}));
    const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, hexRadix = 16, defaultAlpha = 1, alphaFactor = 0xff;
    class HexColorManager {
        accepts(input) {
            return input.startsWith("#");
        }
        handleColor(color) {
            return this.#parseString(color.value);
        }
        handleRangeColor(color) {
            return this.#parseString(color.value);
        }
        parseString(input) {
            return this.#parseString(input);
        }
        #parseString(hexColor) {
            if (typeof hexColor !== "string" || !this.accepts(hexColor)) {
                return;
            }
            const hexFixed = hexColor.replace(shorthandHexRegex, (_, r, g, b, a) => {
                return r + r + g + g + b + b + (a === undefined ? "" : a + a);
            }), result = hexRegex.exec(hexFixed);
            return result
                ? {
                    a: result[RgbIndexes$1.a] ? Number.parseInt(result[RgbIndexes$1.a], hexRadix) / alphaFactor : defaultAlpha,
                    b: Number.parseInt(result[RgbIndexes$1.b] ?? "0", hexRadix),
                    g: Number.parseInt(result[RgbIndexes$1.g] ?? "0", hexRadix),
                    r: Number.parseInt(result[RgbIndexes$1.r] ?? "0", hexRadix),
                }
                : undefined;
        }
    }

    async function loadHexColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("hex", new HexColorManager());
        });
    }

    var HslIndexes;
    (function (HslIndexes) {
        HslIndexes[HslIndexes["h"] = 1] = "h";
        HslIndexes[HslIndexes["s"] = 2] = "s";
        HslIndexes[HslIndexes["l"] = 3] = "l";
        HslIndexes[HslIndexes["a"] = 5] = "a";
    })(HslIndexes || (HslIndexes = {}));
    const hslRegex = /hsla?\(\s*(\d+)\s*[\s,]\s*(\d+)%\s*[\s,]\s*(\d+)%\s*([\s,]\s*(0|1|0?\.\d+|(\d{1,3})%)\s*)?\)/i;
    class HslColorManager {
        accepts(input) {
            return input.startsWith("hsl");
        }
        handleColor(color) {
            const colorValue = color.value, hslColor = colorValue.hsl ?? color.value;
            if (!("h" in hslColor) || !("s" in hslColor) || !("l" in hslColor)) {
                return;
            }
            return hslToRgb(hslColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, hslColor = colorValue.hsl ?? color.value;
            if (!("h" in hslColor) || !("s" in hslColor) || !("l" in hslColor)) {
                return;
            }
            return hslToRgb({
                h: getRangeValue(hslColor.h),
                l: getRangeValue(hslColor.l),
                s: getRangeValue(hslColor.s),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
            return result
                ? hslaToRgba({
                    a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
                    h: Number.parseInt(result[HslIndexes.h] ?? "0", radix),
                    l: Number.parseInt(result[HslIndexes.l] ?? "0", radix),
                    s: Number.parseInt(result[HslIndexes.s] ?? "0", radix),
                })
                : undefined;
        }
    }

    async function loadHslColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("hsl", new HslColorManager());
        });
    }

    function checkDestroy(particle, destroyType, value, minValue, maxValue) {
        switch (destroyType) {
            case exports.DestroyType.max:
                if (value >= maxValue) {
                    particle.destroy();
                }
                break;
            case exports.DestroyType.min:
                if (value <= minValue) {
                    particle.destroy();
                }
                break;
        }
    }
    function initParticleNumericAnimationValue(options, pxRatio) {
        const valueRange = options.value, animationOptions = options.animation, res = {
            delayTime: getRangeValue(animationOptions.delay) * millisecondsToSeconds$1,
            enable: animationOptions.enable,
            value: getRangeValue(options.value) * pxRatio,
            max: getRangeMax(valueRange) * pxRatio,
            min: getRangeMin(valueRange) * pxRatio,
            loops: 0,
            maxLoops: getRangeValue(animationOptions.count),
            time: 0,
        }, decayOffset = 1;
        if (animationOptions.enable) {
            res.decay = decayOffset - getRangeValue(animationOptions.decay);
            switch (animationOptions.mode) {
                case exports.AnimationMode.increase:
                    res.status = exports.AnimationStatus.increasing;
                    break;
                case exports.AnimationMode.decrease:
                    res.status = exports.AnimationStatus.decreasing;
                    break;
                case exports.AnimationMode.random:
                    res.status = getRandom() >= half$2 ? exports.AnimationStatus.increasing : exports.AnimationStatus.decreasing;
                    break;
            }
            const autoStatus = animationOptions.mode === exports.AnimationMode.auto;
            switch (animationOptions.startValue) {
                case exports.StartValueType.min:
                    res.value = res.min;
                    if (autoStatus) {
                        res.status = exports.AnimationStatus.increasing;
                    }
                    break;
                case exports.StartValueType.max:
                    res.value = res.max;
                    if (autoStatus) {
                        res.status = exports.AnimationStatus.decreasing;
                    }
                    break;
                case exports.StartValueType.random:
                default:
                    res.value = randomInRangeValue(res);
                    if (autoStatus) {
                        res.status = getRandom() >= half$2 ? exports.AnimationStatus.increasing : exports.AnimationStatus.decreasing;
                    }
                    break;
            }
        }
        res.initialValue = res.value;
        return res;
    }
    function updateAnimation(particle, data, changeDirection, destroyType, delta) {
        const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minDecay = 1;
        if (particle.destroyed ||
            !data.enable ||
            ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
            return;
        }
        const velocity = (data.velocity ?? minVelocity) * delta.factor, minValue = data.min, maxValue = data.max, decay = data.decay ?? minDecay;
        data.time ??= 0;
        const delayTime = data.delayTime ?? minDelay;
        if (delayTime > minDelay && data.time < delayTime) {
            data.time += delta.value;
            if (data.time < delayTime) {
                return;
            }
        }
        switch (data.status) {
            case exports.AnimationStatus.increasing:
                data.value += velocity;
                break;
            case exports.AnimationStatus.decreasing:
                data.value -= velocity;
                break;
        }
        if (data.velocity && decay !== identity) {
            data.velocity *= decay;
        }
        switch (data.status) {
            case exports.AnimationStatus.increasing:
                if (data.value >= maxValue) {
                    if (changeDirection) {
                        data.status = exports.AnimationStatus.decreasing;
                    }
                    else {
                        data.value -= maxValue;
                    }
                    data.loops ??= minLoops;
                    data.loops++;
                }
                break;
            case exports.AnimationStatus.decreasing:
                if (data.value <= minValue) {
                    if (changeDirection) {
                        data.status = exports.AnimationStatus.increasing;
                    }
                    else {
                        data.value += maxValue;
                    }
                    data.loops ??= minLoops;
                    data.loops++;
                }
                break;
        }
        checkDestroy(particle, destroyType, data.value, minValue, maxValue);
        if (!particle.destroyed) {
            data.value = clamp(data.value, minValue, maxValue);
        }
    }

    class OpacityAnimation extends RangedAnimationOptions {
        destroy = exports.DestroyType.none;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "destroy", data.destroy);
        }
    }

    class Opacity extends RangedAnimationValueWithRandom {
        animation = new OpacityAnimation();
        value = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            const animation = data.animation;
            if (animation !== undefined) {
                this.animation.load(animation);
            }
        }
    }

    class OpacityUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const opacityOptions = particle.options.opacity, pxRatio = 1;
            if (!opacityOptions) {
                return;
            }
            particle.opacity = initParticleNumericAnimationValue(opacityOptions, pxRatio);
            const opacityAnimation = opacityOptions.animation;
            if (opacityAnimation.enable) {
                particle.opacity.velocity =
                    (getRangeValue(opacityAnimation.speed) / percentDenominator) * this.#container.retina.reduceFactor;
                if (!opacityAnimation.sync) {
                    particle.opacity.velocity *= getRandom();
                }
            }
        }
        isEnabled(particle) {
            const none = 0;
            return (!particle.destroyed &&
                !particle.spawning &&
                !!particle.opacity &&
                particle.opacity.enable &&
                ((particle.opacity.maxLoops ?? none) <= none ||
                    ((particle.opacity.maxLoops ?? none) > none &&
                        (particle.opacity.loops ?? none) < (particle.opacity.maxLoops ?? none))));
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "opacity", Opacity, ...sources);
        }
        reset(particle) {
            if (!particle.opacity) {
                return;
            }
            particle.opacity.time = 0;
            particle.opacity.loops = 0;
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.opacity || !particle.options.opacity) {
                return;
            }
            updateAnimation(particle, particle.opacity, true, particle.options.opacity.animation.destroy, delta);
        }
    }

    async function loadOpacityUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("opacity", container => {
                return Promise.resolve(new OpacityUpdater(container));
            });
        });
    }

    const boundsMin = 0;
    function bounceHorizontal(data) {
        if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
            (data.direction !== exports.OutModeDirection.left && data.direction !== exports.OutModeDirection.right)) {
            return;
        }
        if (data.bounds.right < boundsMin && data.direction === exports.OutModeDirection.left) {
            data.particle.position.x = data.size + data.offset.x;
        }
        else if (data.bounds.left > data.canvasSize.width && data.direction === exports.OutModeDirection.right) {
            data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
        }
        const velocity = data.particle.velocity.x;
        let bounced = false;
        if (data.outOfCanvas &&
            ((data.direction === exports.OutModeDirection.right && velocity > minVelocity) ||
                (data.direction === exports.OutModeDirection.left && velocity < minVelocity))) {
            const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
            data.particle.velocity.x *= -newVelocity;
            bounced = true;
        }
        if (!bounced) {
            return;
        }
        const minPos = data.offset.x + data.size;
        if (data.outOfCanvas && data.direction === exports.OutModeDirection.right) {
            data.particle.position.x = data.canvasSize.width - minPos;
        }
        else if (data.outOfCanvas && data.direction === exports.OutModeDirection.left) {
            data.particle.position.x = minPos;
        }
        if (data.outMode === exports.OutMode.split) {
            data.particle.destroy();
        }
    }
    function bounceVertical(data) {
        if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
            (data.direction !== exports.OutModeDirection.bottom && data.direction !== exports.OutModeDirection.top)) {
            return;
        }
        if (data.bounds.bottom < boundsMin && data.direction === exports.OutModeDirection.top) {
            data.particle.position.y = data.size + data.offset.y;
        }
        else if (data.bounds.top > data.canvasSize.height && data.direction === exports.OutModeDirection.bottom) {
            data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
        }
        const velocity = data.particle.velocity.y;
        let bounced = false;
        if (data.outOfCanvas &&
            ((data.direction === exports.OutModeDirection.bottom && velocity > minVelocity) ||
                (data.direction === exports.OutModeDirection.top && velocity < minVelocity))) {
            const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
            data.particle.velocity.y *= -newVelocity;
            bounced = true;
        }
        if (!bounced) {
            return;
        }
        const minPos = data.offset.y + data.size;
        if (data.outOfCanvas && data.direction === exports.OutModeDirection.bottom) {
            data.particle.position.y = data.canvasSize.height - minPos;
        }
        else if (data.outOfCanvas && data.direction === exports.OutModeDirection.top) {
            data.particle.position.y = minPos;
        }
        if (data.outMode === exports.OutMode.split) {
            data.particle.destroy();
        }
    }

    class BounceOutMode {
        modes;
        #container;
        #particleBouncePlugins;
        constructor(container) {
            this.#container = container;
            this.modes = [
                exports.OutMode.bounce,
                exports.OutMode.split,
            ];
            this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
        }
        update(particle, direction, delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            const container = this.#container;
            let handled = false;
            for (const plugin of this.#particleBouncePlugins) {
                handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
                if (handled) {
                    break;
                }
            }
            if (handled) {
                return;
            }
            const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
            bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
            bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
        }
    }

    class DestroyOutMode {
        modes;
        constructor(_container) {
            this.modes = [exports.OutMode.destroy];
        }
        update(particle, direction, _delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            switch (particle.outType) {
                case exports.ParticleOutType.normal:
                case exports.ParticleOutType.outside:
                    if (particle.isInsideCanvasForOutMode(outMode, direction)) {
                        return;
                    }
                    break;
                case exports.ParticleOutType.inside: {
                    const { dx, dy } = getDistances(particle.position, particle.moveCenter), { x: vx, y: vy } = particle.velocity;
                    if ((vx < minVelocity && dx > particle.moveCenter.radius) ||
                        (vy < minVelocity && dy > particle.moveCenter.radius) ||
                        (vx >= minVelocity && dx < -particle.moveCenter.radius) ||
                        (vy >= minVelocity && dy < -particle.moveCenter.radius)) {
                        return;
                    }
                    break;
                }
            }
            particle.destroy(true);
        }
    }

    class NoneOutMode {
        modes;
        #container;
        constructor(container) {
            this.#container = container;
            this.modes = [exports.OutMode.none];
        }
        update(particle, direction, _delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            if ((particle.options.move.distance.horizontal &&
                (direction === exports.OutModeDirection.left || direction === exports.OutModeDirection.right)) ??
                (particle.options.move.distance.vertical &&
                    (direction === exports.OutModeDirection.top || direction === exports.OutModeDirection.bottom))) {
                return;
            }
            const gravityOptions = particle.options.move.gravity, container = this.#container, canvasSize = container.canvas.size, pRadius = particle.getRadius();
            if (!gravityOptions.enable) {
                if ((particle.velocity.y > minVelocity && particle.position.y <= canvasSize.height + pRadius) ||
                    (particle.velocity.y < minVelocity && particle.position.y >= -pRadius) ||
                    (particle.velocity.x > minVelocity && particle.position.x <= canvasSize.width + pRadius) ||
                    (particle.velocity.x < minVelocity && particle.position.x >= -pRadius)) {
                    return;
                }
                if (!isPointInside(particle.position, container.canvas.size, originPoint, pRadius, direction)) {
                    particle.destroy();
                }
            }
            else {
                const position = particle.position;
                if ((!gravityOptions.inverse &&
                    position.y > canvasSize.height + pRadius &&
                    direction === exports.OutModeDirection.bottom) ||
                    (gravityOptions.inverse && position.y < -pRadius && direction === exports.OutModeDirection.top)) {
                    particle.destroy();
                }
            }
        }
    }

    const updateVector$1 = Vector.origin;
    class OutOutMode {
        modes;
        #container;
        constructor(container) {
            this.#container = container;
            this.modes = [exports.OutMode.out];
        }
        update(particle, direction, _delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            const container = this.#container;
            switch (particle.outType) {
                case exports.ParticleOutType.inside: {
                    const { x: vx, y: vy } = particle.velocity;
                    updateVector$1.setTo(originPoint);
                    updateVector$1.length = particle.moveCenter.radius;
                    updateVector$1.angle = particle.velocity.angle + Math.PI;
                    updateVector$1.addTo(particle.moveCenter);
                    const { dx, dy } = getDistances(particle.position, updateVector$1);
                    if ((vx <= minVelocity && dx >= minDistance$7) ||
                        (vy <= minVelocity && dy >= minDistance$7) ||
                        (vx >= minVelocity && dx <= minDistance$7) ||
                        (vy >= minVelocity && dy <= minDistance$7)) {
                        return;
                    }
                    particle.position.x = Math.floor(randomInRangeValue({
                        min: 0,
                        max: container.canvas.size.width,
                    }));
                    particle.position.y = Math.floor(randomInRangeValue({
                        min: 0,
                        max: container.canvas.size.height,
                    }));
                    const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
                    particle.direction = Math.atan2(-newDy, -newDx);
                    particle.velocity.angle = particle.direction;
                    particle.justWarped = true;
                    break;
                }
                default: {
                    if (particle.isInsideCanvasForOutMode(outMode, direction)) {
                        return;
                    }
                    switch (particle.outType) {
                        case exports.ParticleOutType.outside: {
                            particle.position.x =
                                Math.floor(randomInRangeValue({
                                    min: -particle.moveCenter.radius,
                                    max: particle.moveCenter.radius,
                                })) + particle.moveCenter.x;
                            particle.position.y =
                                Math.floor(randomInRangeValue({
                                    min: -particle.moveCenter.radius,
                                    max: particle.moveCenter.radius,
                                })) + particle.moveCenter.y;
                            const { dx, dy } = getDistances(particle.position, particle.moveCenter);
                            if (particle.moveCenter.radius) {
                                particle.direction = Math.atan2(dy, dx);
                                particle.velocity.angle = particle.direction;
                            }
                            particle.justWarped = true;
                            break;
                        }
                        case exports.ParticleOutType.normal: {
                            const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
                                bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
                                left: -particle.getRadius() - particle.offset.x,
                                right: canvasSize.width + particle.getRadius() + particle.offset.x,
                                top: -particle.getRadius() - particle.offset.y,
                            }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
                            if (direction === exports.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
                                particle.position.x = newPos.left;
                                particle.initialPosition.x = particle.position.x;
                                if (!warp) {
                                    particle.position.y = getRandom() * canvasSize.height;
                                    particle.initialPosition.y = particle.position.y;
                                }
                                particle.justWarped = true;
                            }
                            else if (direction === exports.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
                                particle.position.x = newPos.right;
                                particle.initialPosition.x = particle.position.x;
                                if (!warp) {
                                    particle.position.y = getRandom() * canvasSize.height;
                                    particle.initialPosition.y = particle.position.y;
                                }
                                particle.justWarped = true;
                            }
                            if (direction === exports.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
                                if (!warp) {
                                    particle.position.x = getRandom() * canvasSize.width;
                                    particle.initialPosition.x = particle.position.x;
                                }
                                particle.position.y = newPos.top;
                                particle.initialPosition.y = particle.position.y;
                                particle.justWarped = true;
                            }
                            else if (direction === exports.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
                                if (!warp) {
                                    particle.position.x = getRandom() * canvasSize.width;
                                    particle.initialPosition.x = particle.position.x;
                                }
                                particle.position.y = newPos.bottom;
                                particle.initialPosition.y = particle.position.y;
                                particle.justWarped = true;
                            }
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }

    const checkOutMode = (outModes, outMode) => {
        return (outModes.default === outMode ||
            outModes.bottom === outMode ||
            outModes.left === outMode ||
            outModes.right === outMode ||
            outModes.top === outMode);
    };
    class OutOfCanvasUpdater {
        updaters;
        #container;
        constructor(container) {
            this.#container = container;
            this.updaters = new Map();
        }
        init(particle) {
            this.#addUpdaterIfMissing(particle, exports.OutMode.bounce, container => new BounceOutMode(container));
            this.#addUpdaterIfMissing(particle, exports.OutMode.out, container => new OutOutMode(container));
            this.#addUpdaterIfMissing(particle, exports.OutMode.destroy, container => new DestroyOutMode(container));
            this.#addUpdaterIfMissing(particle, exports.OutMode.none, container => new NoneOutMode(container));
        }
        isEnabled(particle) {
            return !particle.destroyed && !particle.spawning;
        }
        update(particle, delta) {
            const outModes = particle.options.move.outModes;
            particle.justWarped = false;
            this.#updateOutMode(particle, delta, outModes.bottom ?? outModes.default, exports.OutModeDirection.bottom);
            this.#updateOutMode(particle, delta, outModes.left ?? outModes.default, exports.OutModeDirection.left);
            this.#updateOutMode(particle, delta, outModes.right ?? outModes.default, exports.OutModeDirection.right);
            this.#updateOutMode(particle, delta, outModes.top ?? outModes.default, exports.OutModeDirection.top);
        }
        #addUpdaterIfMissing(particle, outMode, getUpdater) {
            const outModes = particle.options.move.outModes;
            if (!this.updaters.has(outMode) && checkOutMode(outModes, outMode)) {
                this.updaters.set(outMode, getUpdater(this.#container));
            }
        }
        #updateOutMode(particle, delta, outMode, direction) {
            for (const updater of this.updaters.values()) {
                updater.update(particle, direction, delta, outMode);
            }
        }
    }

    async function loadOutModesUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("outModes", container => {
                return Promise.resolve(new OutOfCanvasUpdater(container));
            });
        });
    }

    const defaultOpacity$2 = 1;
    class PaintUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
        }
        init(particle) {
            const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates), color = paint?.color, paintColor = color ?? undefined, fill = paint?.fill, stroke = paint?.stroke;
            if (fill) {
                const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
                particle.fillEnabled = fill.enable;
                particle.fillOpacity = getRangeValue(fill.opacity);
                particle.fillAnimation = fillColor.animation;
                const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
                if (fillHslColor) {
                    particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
                }
            }
            else {
                particle.fillEnabled = false;
                particle.fillAnimation = undefined;
                particle.fillColor = undefined;
                particle.fillOpacity = defaultOpacity$2;
            }
            if (stroke) {
                const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
                particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
                particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity$2);
                particle.strokeAnimation = strokeColor.animation;
                const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
                if (strokeHslColor) {
                    particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
                }
            }
            else {
                particle.strokeAnimation = undefined;
                particle.strokeColor = undefined;
                particle.strokeOpacity = defaultOpacity$2;
                particle.strokeWidth = 0;
            }
        }
        isEnabled(particle) {
            const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
                ((fillColor?.h.value !== undefined && fillColor.h.enable) ||
                    (fillColor?.s.value !== undefined && fillColor.s.enable) ||
                    (fillColor?.l.value !== undefined && fillColor.l.enable)), strokeEnabled = !!strokeAnimation &&
                ((strokeColor?.h.value !== undefined && strokeColor.h.enable) ||
                    (strokeColor?.s.value !== undefined && strokeColor.s.enable) ||
                    (strokeColor?.l.value !== undefined && strokeColor.l.enable));
            return !particle.destroyed && !particle.spawning && (fillEnabled || strokeEnabled);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            updateColor(particle.fillColor, delta, this.#container.hdr);
            updateColor(particle.strokeColor, delta, this.#container.hdr);
        }
    }

    async function loadPaintUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("paint", container => {
                return Promise.resolve(new PaintUpdater(e.pluginManager, container));
            });
        });
    }

    var RgbIndexes;
    (function (RgbIndexes) {
        RgbIndexes[RgbIndexes["r"] = 1] = "r";
        RgbIndexes[RgbIndexes["g"] = 2] = "g";
        RgbIndexes[RgbIndexes["b"] = 3] = "b";
        RgbIndexes[RgbIndexes["a"] = 5] = "a";
    })(RgbIndexes || (RgbIndexes = {}));
    const rgbRegex = /rgba?\(\s*(\d{1,3})\s*[\s,]\s*(\d{1,3})\s*[\s,]\s*(\d{1,3})\s*([\s,]\s*(0|1|0?\.\d+|(\d{1,3})%)\s*)?\)/i;
    class RgbColorManager {
        accepts(input) {
            return input.startsWith("rgb");
        }
        handleColor(color) {
            const colorValue = color.value, rgbColor = colorValue.rgb ?? color.value;
            if (!("r" in rgbColor) || !("g" in rgbColor) || !("b" in rgbColor)) {
                return;
            }
            return rgbColor;
        }
        handleRangeColor(color) {
            const colorValue = color.value, rgbColor = colorValue.rgb ?? color.value;
            if (!("r" in rgbColor) || !("g" in rgbColor) || !("b" in rgbColor)) {
                return;
            }
            return {
                r: getRangeValue(rgbColor.r),
                g: getRangeValue(rgbColor.g),
                b: getRangeValue(rgbColor.b),
            };
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
            return result
                ? {
                    a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
                    b: parseInt(result[RgbIndexes.b] ?? "0", radix),
                    g: parseInt(result[RgbIndexes.g] ?? "0", radix),
                    r: parseInt(result[RgbIndexes.r] ?? "0", radix),
                }
                : undefined;
        }
    }

    async function loadRgbColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("rgb", new RgbColorManager());
        });
    }

    class SizeAnimation extends RangedAnimationOptions {
        destroy = exports.DestroyType.none;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "destroy", data.destroy);
        }
    }

    class Size extends RangedAnimationValueWithRandom {
        animation = new SizeAnimation();
        value = 3;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            const animation = data.animation;
            if (animation !== undefined) {
                this.animation.load(animation);
            }
        }
    }

    const minLoops = 0;
    class SizeUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const container = this.#container, sizeOptions = particle.options.size;
            if (!sizeOptions) {
                return;
            }
            const sizeAnimation = sizeOptions.animation;
            if (!sizeAnimation.enable) {
                return;
            }
            particle.size.velocity = (particle.retina.sizeAnimationSpeed / percentDenominator) * container.retina.reduceFactor;
            if (sizeAnimation.sync) {
                return;
            }
            particle.size.velocity *= getRandom();
        }
        isEnabled(particle) {
            return (!particle.destroyed &&
                !particle.spawning &&
                particle.size.enable &&
                ((particle.size.maxLoops ?? minLoops) <= minLoops ||
                    ((particle.size.maxLoops ?? minLoops) > minLoops &&
                        (particle.size.loops ?? minLoops) < (particle.size.maxLoops ?? minLoops))));
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "size", Size, ...sources);
        }
        preInit(particle) {
            const pxRatio = this.#container.retina.pixelRatio, options = particle.options, sizeOptions = options.size;
            if (!sizeOptions) {
                return;
            }
            particle.size = initParticleNumericAnimationValue(sizeOptions, pxRatio);
            particle.retina.sizeAnimationSpeed = getRangeValue(sizeOptions.animation.speed) * pxRatio;
        }
        reset(particle) {
            particle.size.time = 0;
            particle.size.loops = 0;
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.options.size) {
                return;
            }
            updateAnimation(particle, particle.size, true, particle.options.size.animation.destroy, delta);
        }
    }

    async function loadSizeUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("size", container => {
                return Promise.resolve(new SizeUpdater(container));
            });
        });
    }

    async function loadBasic(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            await Promise.all([
                loadBlendPlugin(e),
                loadHexColorPlugin(e),
                loadHslColorPlugin(e),
                loadRgbColorPlugin(e),
                loadMovePlugin(e),
                loadCircleShape(e),
                loadPaintUpdater(e),
                loadOpacityUpdater(e),
                loadOutModesUpdater(e),
                loadSizeUpdater(e),
            ]);
        });
    }

    const easingsFunctions = new Map();
    easingsFunctions.set("ease-in-quad", value => value ** 2);
    easingsFunctions.set("ease-out-quad", value => 1 - (1 - value) ** 2);
    easingsFunctions.set("ease-in-out-quad", value => (value < 0.5 ? 2 * value ** 2 : 1 - (-2 * value + 2) ** 2 / 2));

    async function loadEasingQuadPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            for (const [easing, easingFn] of easingsFunctions) {
                e.pluginManager.addEasing(easing, easingFn);
            }
        });
    }

    const validTypes$1 = ["emoji"];
    function drawEmoji(data, image) {
        const { context, opacity } = data, previousAlpha = context.globalAlpha, diameter = image.width, radius = diameter * half$2;
        context.globalAlpha = opacity;
        context.drawImage(image, -radius, -radius, diameter, diameter);
        context.globalAlpha = previousAlpha;
    }

    const defaultFont = '"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif', noPadding = 0, firstItem = 0;
    class EmojiDrawer {
        #emojiShapeDict = new Map();
        destroy() {
            for (const [key, data] of this.#emojiShapeDict) {
                if (data instanceof ImageBitmap) {
                    data.close();
                }
                this.#emojiShapeDict.delete(key);
            }
        }
        draw(data) {
            const key = data.particle.emojiDataKey;
            if (!key) {
                return;
            }
            const image = this.#emojiShapeDict.get(key);
            if (!image) {
                return;
            }
            drawEmoji(data, image);
        }
        async init(container) {
            const options = container.actualOptions, shapeData = options.particles.shape;
            if (!validTypes$1.some(t => isInArray(t, shapeData.type))) {
                return;
            }
            const promises = [loadFont(defaultFont)], shapeOptions = validTypes$1.map(t => shapeData.options[t])[firstItem];
            executeOnSingleOrMultiple(shapeOptions, shape => {
                if (shape.font) {
                    promises.push(loadFont(shape.font));
                }
            });
            await Promise.all(promises);
        }
        particleDestroy(particle) {
            particle.emojiDataKey = undefined;
        }
        particleInit(container, particle) {
            const shapeData = particle.shapeData;
            if (!shapeData.value) {
                return;
            }
            const emoji = itemFromSingleOrMultiple(shapeData.value, particle.randomIndexData);
            if (!emoji) {
                return;
            }
            const emojiOptions = typeof emoji === "string"
                ? {
                    font: shapeData.font ?? defaultFont,
                    padding: shapeData.padding ?? noPadding,
                    value: emoji,
                }
                : {
                    font: defaultFont,
                    padding: noPadding,
                    ...shapeData,
                    ...emoji,
                }, font = emojiOptions.font, value = emojiOptions.value, cacheKey = `${value}_${font}`;
            if (this.#emojiShapeDict.has(cacheKey)) {
                particle.emojiDataKey = cacheKey;
                return;
            }
            const padding = emojiOptions.padding * double, maxSize = getRangeMax(particle.size.value), fullSize = maxSize + padding, canvasSize = fullSize * double, cacheCanvas = new OffscreenCanvas(canvasSize, canvasSize), context = cacheCanvas.getContext("2d", container.canvas.render.settings);
            if (!context) {
                return;
            }
            context.font = `400 ${(maxSize * double).toString()}px ${font}`;
            context.textBaseline = "middle";
            context.textAlign = "center";
            context.fillText(value, fullSize, fullSize);
            const image = cacheCanvas instanceof HTMLCanvasElement ? cacheCanvas : cacheCanvas.transferToImageBitmap();
            this.#emojiShapeDict.set(cacheKey, image);
            particle.emojiDataKey = cacheKey;
        }
    }

    async function loadEmojiShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(validTypes$1, () => Promise.resolve(new EmojiDrawer()));
        });
    }

    const minFactor = 1, minRadius$5 = 0, updateVector = Vector.origin;
    function processAttract(pluginManager, container, position, attractRadius, area, queryCb, onAttractParticle) {
        const attractOptions = container.actualOptions.interactivity?.modes.attract;
        if (!attractOptions) {
            return;
        }
        const query = container.particles.grid.query(area, queryCb);
        for (const particle of query) {
            const { dx, dy, distance } = getDistances(particle.position, position), velocity = attractOptions.speed * attractOptions.factor, attractFactor = clamp(pluginManager.getEasing(attractOptions.easing)(identity$3 - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed);
            updateVector.x = !distance ? velocity : (dx / distance) * attractFactor;
            updateVector.y = !distance ? velocity : (dy / distance) * attractFactor;
            onAttractParticle?.(particle);
            particle.position.subFrom(updateVector);
        }
    }
    function clickAttract(pluginManager, container, interactivityData, enabledCb, onAttractParticle) {
        container.attract ??= { particles: [] };
        const { attract } = container;
        if (!attract.finish) {
            attract.count ??= 0;
            attract.count++;
            if (attract.count === container.particles.count) {
                attract.finish = true;
            }
        }
        if (attract.clicking) {
            const mousePos = interactivityData.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
            if (!attractRadius || attractRadius < minRadius$5 || !mousePos) {
                return;
            }
            processAttract(pluginManager, container, mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius), (p) => enabledCb(p), onAttractParticle);
        }
        else if (attract.clicking === false) {
            attract.particles = [];
        }
    }
    function hoverAttract(pluginManager, container, interactivityData, enabledCb, onAttractParticle) {
        const mousePos = interactivityData.mouse.position, attractRadius = container.retina.attractModeDistance;
        if (!attractRadius || attractRadius < minRadius$5 || !mousePos) {
            return;
        }
        processAttract(pluginManager, container, mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius), (p) => enabledCb(p), onAttractParticle);
    }

    let Attract$1 = class Attract {
        distance = 200;
        duration = 0.4;
        easing = "ease-out-quad";
        factor = 1;
        maxSpeed = 50;
        restore;
        speed = 1;
        constructor() {
            this.restore = {
                enable: false,
                delay: 0,
                speed: 0.08,
                follow: true,
            };
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
            loadProperty(this, "duration", data.duration);
            if (data.easing !== undefined) {
                this.easing = data.easing;
            }
            loadProperty(this, "factor", data.factor);
            if (data.maxSpeed !== undefined) {
                this.maxSpeed = data.maxSpeed;
            }
            loadProperty(this, "speed", data.speed);
            if (data.restore !== undefined) {
                this.restore.enable = data.restore.enable ?? this.restore.enable;
                this.restore.delay = data.restore.delay ?? this.restore.delay;
                this.restore.speed = data.restore.speed ?? this.restore.speed;
                this.restore.follow = data.restore.follow ?? this.restore.follow;
            }
        }
    };

    const attractMode = "attract", minVelocityLengthSq = 0, minRestoreSpeed$1 = 0.001, maxRestoreSpeed$1 = 1, restoreEpsilon$1 = 0.5;
    let Attractor$1 = class Attractor extends ExternalInteractorBase {
        handleClickMode;
        #interactedThisFrame;
        #maxDistance;
        #pluginManager;
        #restoreData;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.#maxDistance = 0;
            this.#interactedThisFrame = new Set();
            this.#restoreData = new Map();
            container.attract ??= { particles: [] };
            this.handleClickMode = (mode, interactivityData) => {
                const options = this.container.actualOptions, attract = options.interactivity?.modes.attract;
                if (!attract || mode !== attractMode) {
                    return;
                }
                container.attract ??= { particles: [] };
                container.attract.clicking = true;
                container.attract.count = 0;
                for (const particle of container.attract.particles) {
                    if (!this.isEnabled(interactivityData, particle)) {
                        continue;
                    }
                    particle.velocity.setTo(particle.initialVelocity);
                }
                container.attract.particles = [];
                container.attract.finish = false;
                setTimeout(() => {
                    if (container.destroyed) {
                        return;
                    }
                    container.attract ??= { particles: [] };
                    container.attract.clicking = false;
                }, attract.duration * millisecondsToSeconds$1);
            };
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            const container = this.container, attract = container.actualOptions.interactivity?.modes.attract;
            if (!attract) {
                return;
            }
            this.#maxDistance = attract.distance;
            container.retina.attractModeDistance = attract.distance * container.retina.pixelRatio;
        }
        interact(interactivityData) {
            this.#interactedThisFrame.clear();
            const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
            if (!events) {
                return;
            }
            const { enable: hoverEnabled, mode: hoverMode } = events.onHover, { enable: clickEnabled, mode: clickMode } = events.onClick;
            if (mouseMoveStatus && hoverEnabled && isInArray(attractMode, hoverMode)) {
                hoverAttract(this.#pluginManager, this.container, interactivityData, p => this.isEnabled(interactivityData, p), p => {
                    this.#trackInteractedParticle(p);
                });
            }
            else if (clickEnabled && isInArray(attractMode, clickMode)) {
                clickAttract(this.#pluginManager, this.container, interactivityData, p => this.isEnabled(interactivityData, p), p => {
                    this.#trackInteractedParticle(p);
                });
            }
            this.#restoreParticles();
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            if ((!mouse.position || !events?.onHover.enable) && (!mouse.clickPosition || !events?.onClick.enable)) {
                return false;
            }
            const hoverMode = events.onHover.mode, clickMode = events.onClick.mode;
            return isInArray(attractMode, hoverMode) || isInArray(attractMode, clickMode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "attract", Attract$1, ...sources);
        }
        reset() {
        }
        #restoreParticles() {
            const restore = this.container.actualOptions.interactivity?.modes.attract?.restore;
            if (!restore?.enable || !this.#restoreData.size) {
                return;
            }
            const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds$1, restoreSpeed = Math.max(minRestoreSpeed$1, Math.min(maxRestoreSpeed$1, restore.speed));
            for (const [particle, restoreData] of this.#restoreData) {
                if (this.#interactedThisFrame.has(particle)) {
                    continue;
                }
                if (particle.destroyed) {
                    this.#restoreData.delete(particle);
                    continue;
                }
                const target = restoreData.target;
                if (now - restoreData.lastInteractionTime < restoreDelay) {
                    continue;
                }
                let dx = target.x - particle.position.x, dy = target.y - particle.position.y, dz = target.z - particle.position.z;
                if (restore.follow && particle.options.move.enable) {
                    const { x: vx, y: vy, z: vz } = particle.velocity, velocityLengthSq = vx * vx + vy * vy + vz * vz;
                    if (velocityLengthSq > minVelocityLengthSq) {
                        const parallelScale = (dx * vx + dy * vy + dz * vz) / velocityLengthSq;
                        dx -= vx * parallelScale;
                        dy -= vy * parallelScale;
                        dz -= vz * parallelScale;
                    }
                }
                particle.position.x += dx * restoreSpeed;
                particle.position.y += dy * restoreSpeed;
                particle.position.z += dz * restoreSpeed;
                if (Math.abs(dx) <= restoreEpsilon$1 && Math.abs(dy) <= restoreEpsilon$1) {
                    particle.position.x = target.x;
                    particle.position.y = target.y;
                    particle.position.z = target.z;
                    this.#restoreData.delete(particle);
                    continue;
                }
            }
        }
        #trackInteractedParticle(particle) {
            this.#interactedThisFrame.add(particle);
            const restore = this.container.actualOptions.interactivity?.modes.attract?.restore;
            if (!restore?.enable) {
                return;
            }
            const now = Date.now();
            let restoreData = this.#restoreData.get(particle);
            if (!restoreData) {
                restoreData = {
                    target: particle.position.copy(),
                    lastInteractionTime: now,
                };
                this.#restoreData.set(particle, restoreData);
            }
            restoreData.lastInteractionTime = now;
        }
    };

    async function loadExternalAttractInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalAttract", container => {
                return Promise.resolve(new Attractor$1(e.pluginManager, container));
            });
        });
    }

    const halfPI$3 = Math.PI * half$2, toleranceFactor$1 = 10;
    function processBounce(container, position, radius, area, enabledCb) {
        const query = container.particles.grid.query(area, enabledCb);
        for (const particle of query) {
            if (area instanceof Circle) {
                circleBounce(circleBounceDataFromParticle(particle), {
                    position,
                    mass: radius ** squareExp * halfPI$3,
                    velocity: Vector.origin,
                    factor: Vector.origin,
                });
            }
            else if (area instanceof Rectangle) {
                rectBounce(particle, calculateBounds(position, radius));
            }
        }
    }
    function singleSelectorBounce(container, selector, div, bounceCb) {
        const query = safeDocument().querySelectorAll(selector);
        if (!query.length) {
            return;
        }
        query.forEach(item => {
            const elem = item, pxRatio = container.retina.pixelRatio, pos = {
                x: (elem.offsetLeft + elem.offsetWidth * half$2) * pxRatio,
                y: (elem.offsetTop + elem.offsetHeight * half$2) * pxRatio,
            }, radius = elem.offsetWidth * half$2 * pxRatio, tolerance = toleranceFactor$1 * pxRatio, area = div.type === DivType.circle
                ? new Circle(pos.x, pos.y, radius + tolerance)
                : new Rectangle(elem.offsetLeft * pxRatio - tolerance, elem.offsetTop * pxRatio - tolerance, elem.offsetWidth * pxRatio + tolerance * double, elem.offsetHeight * pxRatio + tolerance * double);
            bounceCb(pos, radius, area);
        });
    }
    function divBounce(container, divs, bounceMode, enabledCb) {
        divModeExecute(bounceMode, divs, (selector, div) => {
            singleSelectorBounce(container, selector, div, (pos, radius, area) => {
                processBounce(container, pos, radius, area, enabledCb);
            });
        });
    }
    function mouseBounce(container, interactivityData, enabledCb) {
        const pxRatio = container.retina.pixelRatio, tolerance = toleranceFactor$1 * pxRatio, mousePos = interactivityData.mouse.position, radius = container.retina.bounceModeDistance;
        if (!radius || radius < minRadius$8 || !mousePos) {
            return;
        }
        processBounce(container, mousePos, radius, new Circle(mousePos.x, mousePos.y, radius + tolerance), enabledCb);
    }
    function rectSideBounce(data) {
        const res = { bounced: false }, { pSide, pOtherSide, rectSide, rectOtherSide, velocity, factor } = data;
        if (pOtherSide.min < rectOtherSide.min ||
            pOtherSide.min > rectOtherSide.max ||
            pOtherSide.max < rectOtherSide.min ||
            pOtherSide.max > rectOtherSide.max) {
            return res;
        }
        if ((pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * half$2 && velocity > minVelocity) ||
            (pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * half$2 && velocity < minVelocity)) {
            res.velocity = velocity * -factor;
            res.bounced = true;
        }
        return res;
    }
    function rectBounce(particle, divBounds) {
        const pPos = particle.getPosition(), size = particle.getRadius(), bounds = calculateBounds(pPos, size), bounceOptions = particle.options.bounce, resH = rectSideBounce({
            pSide: {
                min: bounds.left,
                max: bounds.right,
            },
            pOtherSide: {
                min: bounds.top,
                max: bounds.bottom,
            },
            rectSide: {
                min: divBounds.left,
                max: divBounds.right,
            },
            rectOtherSide: {
                min: divBounds.top,
                max: divBounds.bottom,
            },
            velocity: particle.velocity.x,
            factor: getRangeValue(bounceOptions.horizontal.value),
        });
        if (resH.bounced) {
            if (resH.velocity !== undefined) {
                particle.velocity.x = resH.velocity;
            }
            if (resH.position !== undefined) {
                particle.position.x = resH.position;
            }
        }
        const resV = rectSideBounce({
            pSide: {
                min: bounds.top,
                max: bounds.bottom,
            },
            pOtherSide: {
                min: bounds.left,
                max: bounds.right,
            },
            rectSide: {
                min: divBounds.top,
                max: divBounds.bottom,
            },
            rectOtherSide: {
                min: divBounds.left,
                max: divBounds.right,
            },
            velocity: particle.velocity.y,
            factor: getRangeValue(bounceOptions.vertical.value),
        });
        if (resV.bounced) {
            if (resV.velocity !== undefined) {
                particle.velocity.y = resV.velocity;
            }
            if (resV.position !== undefined) {
                particle.position.y = resV.position;
            }
        }
    }

    class Bounce {
        distance = 200;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
        }
    }

    const bounceMode = "bounce";
    class Bouncer extends ExternalInteractorBase {
        #maxDistance;
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            const container = this.container, bounce = container.actualOptions.interactivity?.modes.bounce;
            if (!bounce) {
                return;
            }
            this.#maxDistance = bounce.distance;
            container.retina.bounceModeDistance = bounce.distance * container.retina.pixelRatio;
        }
        interact(interactivityData) {
            const container = this.container, options = container.actualOptions, events = options.interactivity?.events, mouseMoveStatus = interactivityData.status === mouseMoveEvent;
            if (!events) {
                return;
            }
            const hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, divs = events.onDiv;
            if (mouseMoveStatus && hoverEnabled && isInArray(bounceMode, hoverMode)) {
                mouseBounce(this.container, interactivityData, p => this.isEnabled(interactivityData, p));
            }
            else {
                divBounce(this.container, divs, bounceMode, p => this.isEnabled(interactivityData, p));
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            if (!events) {
                return false;
            }
            const divs = events.onDiv;
            return ((!!mouse.position && events.onHover.enable && isInArray(bounceMode, events.onHover.mode)) ||
                isDivModeEnabled(bounceMode, divs));
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "bounce", Bounce, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalBounceInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalBounce", container => {
                return Promise.resolve(new Bouncer(container));
            });
        });
    }

    class BubbleBase {
        color;
        distance = 200;
        duration = 0.4;
        mix = false;
        opacity;
        size;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
            loadProperty(this, "duration", data.duration);
            loadProperty(this, "mix", data.mix);
            loadRangeProperty(this, "opacity", data.opacity);
            if (data.color !== undefined) {
                const sourceColor = isArray(this.color) ? undefined : this.color;
                this.color = executeOnSingleOrMultiple(data.color, color => {
                    return OptionsColor.create(sourceColor, color);
                });
            }
            loadProperty(this, "size", data.size);
        }
    }

    class BubbleDiv extends BubbleBase {
        selectors = [];
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "selectors", data.selectors);
        }
    }

    class Bubble extends BubbleBase {
        divs;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            this.divs = executeOnSingleOrMultiple(data.divs, div => {
                const tmp = new BubbleDiv();
                tmp.load(div);
                return tmp;
            });
        }
    }

    class BubbleModifier {
        div;
        enabled = false;
        fillColor;
        finalColor;
        id = "bubble";
        inRange = false;
        opacity;
        priority = 100;
        radius;
        strokeColor;
    }

    var ProcessBubbleType;
    (function (ProcessBubbleType) {
        ProcessBubbleType["color"] = "color";
        ProcessBubbleType["opacity"] = "opacity";
        ProcessBubbleType["size"] = "size";
    })(ProcessBubbleType || (ProcessBubbleType = {}));

    function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
        if (modeValue >= optionsValue) {
            const value = particleValue + (modeValue - optionsValue) * ratio;
            return clamp(value, particleValue, modeValue);
        }
        else if (modeValue < optionsValue) {
            const value = particleValue - (optionsValue - modeValue) * ratio;
            return clamp(value, modeValue, particleValue);
        }
        return undefined;
    }

    const bubbleMode = "bubble", minDistance$5 = 0, defaultClickTime = 0, defaultOpacity$1 = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;
    class Bubbler extends ExternalInteractorBase {
        handleClickMode;
        #maxDistance;
        #modifiers = new WeakMap();
        #pluginManager;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.#maxDistance = 0;
            container.bubble ??= {};
            this.handleClickMode = (mode) => {
                if (mode !== bubbleMode) {
                    return;
                }
                container.bubble ??= {};
                container.bubble.clicking = true;
            };
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear(particle, _delta, force) {
            const mod = this.#modifiers.get(particle);
            if (mod?.inRange && !force) {
                return;
            }
            particle.removeModifier(bubbleMode);
            this.#modifiers.delete(particle);
        }
        getOrCreateModifier(particle) {
            let mod = this.#modifiers.get(particle);
            if (!mod) {
                mod = new BubbleModifier();
                this.#modifiers.set(particle, mod);
                particle.addModifier(mod);
            }
            return mod;
        }
        init() {
            const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
            if (!bubble) {
                return;
            }
            this.#maxDistance = bubble.distance;
            container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;
            if (bubble.size !== undefined) {
                container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
            }
        }
        interact(interactivityData, delta) {
            const options = this.container.actualOptions, events = options.interactivity?.events;
            if (!events) {
                return;
            }
            const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
            if (hoverEnabled && isInArray(bubbleMode, hoverMode)) {
                this.#hoverBubble(interactivityData);
            }
            else if (clickEnabled && isInArray(bubbleMode, clickMode)) {
                this.#clickBubble(interactivityData);
            }
            else {
                divModeExecute(bubbleMode, divs, (selector, div) => {
                    this.#singleSelectorHover(interactivityData, delta, selector, div);
                });
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            if (!events) {
                return false;
            }
            const { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
            if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
                return false;
            }
            return isInArray(bubbleMode, onHover.mode) || isInArray(bubbleMode, onClick.mode) || divBubble;
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "bubble", Bubble, ...sources);
        }
        reset(_interactivityData, particle) {
            const mod = this.#modifiers.get(particle);
            if (mod) {
                mod.enabled = false;
                mod.inRange = false;
            }
        }
        #clickBubble(interactivityData) {
            const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
            if (!bubbleOptions || !mouseClickPos) {
                return;
            }
            container.bubble ??= {};
            const distance = container.retina.bubbleModeDistance;
            if (!distance || distance < minDistance$5) {
                return;
            }
            const query = container.particles.grid.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
            for (const particle of query) {
                if (!bubble.clicking) {
                    continue;
                }
                const mod = this.getOrCreateModifier(particle);
                mod.enabled = !bubble.durationEnd;
                mod.inRange = !bubble.durationEnd;
                const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (performance.now() - (interactivityData.mouse.clickTime ?? defaultClickTime)) / millisecondsToSeconds$1;
                if (timeSpent > bubbleOptions.duration) {
                    bubble.durationEnd = true;
                }
                if (timeSpent > bubbleOptions.duration * double) {
                    bubble.clicking = false;
                    bubble.durationEnd = false;
                }
                const sizeData = {
                    bubbleObj: {
                        optValue: container.retina.bubbleModeSize,
                        value: mod.radius,
                    },
                    particlesObj: {
                        optValue: particle.size.max,
                        value: particle.size.value,
                    },
                    type: ProcessBubbleType.size,
                };
                this.#process(particle, distMouse, timeSpent, sizeData);
                const opacityData = {
                    bubbleObj: {
                        optValue: bubbleOptions.opacity,
                        value: mod.opacity,
                    },
                    particlesObj: {
                        optValue: particle.opacity?.max ?? defaultOpacity$1,
                        value: particle.opacity?.value ?? defaultOpacity$1,
                    },
                    type: ProcessBubbleType.opacity,
                };
                this.#process(particle, distMouse, timeSpent, opacityData);
                if (!bubble.durationEnd && distMouse <= distance) {
                    this.#hoverBubbleColor(particle, distMouse);
                }
                else {
                    mod.fillColor = undefined;
                    mod.strokeColor = undefined;
                }
            }
        }
        #hoverBubble(interactivityData) {
            const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;
            if (!distance || distance < minDistance$5 || !mousePos) {
                return;
            }
            const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
            for (const particle of query) {
                const mod = this.getOrCreateModifier(particle);
                mod.enabled = true;
                mod.inRange = true;
                const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
                if (pointDistance <= distance) {
                    if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
                        this.#hoverBubbleSize(particle, ratio);
                        this.#hoverBubbleOpacity(particle, ratio);
                        this.#hoverBubbleColor(particle, ratio);
                    }
                }
                else {
                    this.reset(interactivityData, particle);
                }
                if (interactivityData.status === mouseLeaveEvent) {
                    this.reset(interactivityData, particle);
                }
            }
        }
        #hoverBubbleColor(particle, ratio, divBubble) {
            const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble, mod = this.getOrCreateModifier(particle);
            if (!bubbleOptions) {
                return;
            }
            if (!mod.finalColor) {
                const modeColor = bubbleOptions.color;
                if (!modeColor) {
                    return;
                }
                const bubbleColor = itemFromSingleOrMultiple(modeColor);
                mod.finalColor = rangeColorToHsl(this.#pluginManager, bubbleColor);
            }
            if (!mod.finalColor) {
                return;
            }
            if (bubbleOptions.mix) {
                mod.fillColor = undefined;
                mod.strokeColor = undefined;
                const pColor = particle.getFillColor();
                if (pColor) {
                    const mixedColor = rgbToHsl(colorMix(pColor, mod.finalColor, ratioOffset - ratio, ratio, this.container.hdr));
                    mod.fillColor = mixedColor;
                    mod.strokeColor = mixedColor;
                }
                else {
                    mod.fillColor = mod.finalColor;
                    mod.strokeColor = mod.finalColor;
                }
            }
            else {
                mod.fillColor = mod.finalColor;
                mod.strokeColor = mod.finalColor;
            }
        }
        #hoverBubbleOpacity(particle, ratio, divBubble) {
            const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;
            if (!modeOpacity) {
                return;
            }
            const pOpacity = particle.opacity?.value ?? defaultOpacity$1, opacity = calculateBubbleValue(pOpacity, modeOpacity, particle.opacity?.max ?? defaultOpacity$1, ratio);
            if (opacity !== undefined) {
                const mod = this.getOrCreateModifier(particle);
                mod.opacity = opacity;
            }
        }
        #hoverBubbleSize(particle, ratio, divBubble) {
            const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
            if (modeSize === undefined) {
                return;
            }
            const pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, particle.size.max, ratio);
            if (size !== undefined) {
                const mod = this.getOrCreateModifier(particle);
                mod.radius = size;
            }
        }
        #process(particle, distMouse, timeSpent, data) {
            const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;
            if (!bubbleOptions || bubbleParam === undefined) {
                return;
            }
            const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;
            if (!bubbleDistance || bubbleDistance < minDistance$5 || bubbleParam === particlesParam) {
                return;
            }
            container.bubble ??= {};
            const mod = this.getOrCreateModifier(particle);
            if (container.bubble.durationEnd) {
                if (pObjBubble) {
                    if (type === ProcessBubbleType.size) {
                        mod.radius = undefined;
                    }
                    if (type === ProcessBubbleType.opacity) {
                        mod.opacity = undefined;
                    }
                }
            }
            else {
                if (distMouse <= bubbleDistance) {
                    const obj = pObjBubble ?? pObj;
                    if (obj !== bubbleParam) {
                        const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
                        if (type === ProcessBubbleType.size) {
                            mod.radius = value;
                        }
                        if (type === ProcessBubbleType.opacity) {
                            mod.opacity = value;
                        }
                    }
                }
                else {
                    if (type === ProcessBubbleType.size) {
                        mod.radius = undefined;
                    }
                    if (type === ProcessBubbleType.opacity) {
                        mod.opacity = undefined;
                    }
                }
            }
        }
        #singleSelectorHover(interactivityData, delta, selector, div) {
            const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;
            if (!bubble || !selectors.length) {
                return;
            }
            selectors.forEach(item => {
                const elem = item, pxRatio = container.retina.pixelRatio, pos = {
                    x: (elem.offsetLeft + elem.offsetWidth * half$2) * pxRatio,
                    y: (elem.offsetTop + elem.offsetHeight * half$2) * pxRatio,
                }, repulseRadius = elem.offsetWidth * half$2 * pxRatio, area = div.type === DivType.circle
                    ? new Circle(pos.x, pos.y, repulseRadius)
                    : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p));
                for (const particle of query) {
                    if (!area.contains(particle.getPosition())) {
                        continue;
                    }
                    const mod = this.getOrCreateModifier(particle);
                    mod.enabled = true;
                    mod.inRange = true;
                    const divs = bubble.divs, divBubble = divMode(divs, elem);
                    if (!mod.div || mod.div !== elem) {
                        this.clear(particle, delta, true);
                        mod.div = elem;
                    }
                    this.#hoverBubbleSize(particle, defaultRatio, divBubble);
                    this.#hoverBubbleOpacity(particle, defaultRatio, divBubble);
                    this.#hoverBubbleColor(particle, defaultRatio, divBubble);
                }
            });
        }
    }

    async function loadExternalBubbleInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalBubble", container => {
                return Promise.resolve(new Bubbler(e.pluginManager, container));
            });
        });
    }

    class ConnectLinks {
        opacity = 0.5;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class Connect {
        distance = 80;
        links = new ConnectLinks();
        radius = 60;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
            this.links.load(data.links);
            loadProperty(this, "radius", data.radius);
        }
    }

    const gradientMin = 0, gradientMax = 1, defaultLinksWidth = 0;
    function gradient(container, context, p1, p2, opacity) {
        const gradStop = Math.floor(p2.getRadius() / p1.getRadius()), color1 = p1.getFillColor(), color2 = p2.getFillColor();
        if (!color1 || !color2) {
            return;
        }
        const sourcePos = p1.getPosition(), destPos = p2.getPosition(), midRgb = colorMix(color1, color2, p1.getRadius(), p2.getRadius(), container.hdr), grad = context.createLinearGradient(sourcePos.x, sourcePos.y, destPos.x, destPos.y);
        grad.addColorStop(gradientMin, getStyleFromHsl(color1, container.hdr, opacity, container.peakNits, container.hdrMode));
        grad.addColorStop(clamp(gradStop, gradientMin, gradientMax), getStyleFromRgb(midRgb, container.hdr, opacity, container.peakNits, container.hdrMode));
        grad.addColorStop(gradientMax, getStyleFromHsl(color2, container.hdr, opacity, container.peakNits, container.hdrMode));
        return grad;
    }
    function drawConnectLine(context, width, lineStyle, begin, end) {
        drawLine$1(context, begin, end);
        context.lineWidth = width;
        context.strokeStyle = lineStyle;
        context.stroke();
    }
    function lineStyle(container, ctx, p1, p2) {
        const options = container.actualOptions, connectOptions = options.interactivity?.modes.connect;
        if (!connectOptions) {
            return;
        }
        return gradient(container, ctx, p1, p2, connectOptions.links.opacity);
    }
    function drawConnection(container, p1, p2) {
        container.canvas.render.draw(ctx => {
            const ls = lineStyle(container, ctx, p1, p2);
            if (!ls) {
                return;
            }
            const pos1 = p1.getPosition(), pos2 = p2.getPosition();
            drawConnectLine(ctx, p1.retina.linksWidth ?? defaultLinksWidth, ls, pos1, pos2);
        });
    }

    const connectMode = "connect", minDistance$4 = 0;
    class Connector extends ExternalInteractorBase {
        #maxDistance;
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            const container = this.container, connect = container.actualOptions.interactivity?.modes.connect;
            if (!connect) {
                return;
            }
            this.#maxDistance = connect.distance;
            container.retina.connectModeDistance = connect.distance * container.retina.pixelRatio;
            container.retina.connectModeRadius = connect.radius * container.retina.pixelRatio;
        }
        interact(interactivityData) {
            const container = this.container, options = container.actualOptions;
            if (options.interactivity?.events.onHover.enable && interactivityData.status === "pointermove") {
                const mousePos = interactivityData.mouse.position, { connectModeDistance, connectModeRadius } = container.retina;
                if (!connectModeDistance ||
                    connectModeDistance < minDistance$4 ||
                    !connectModeRadius ||
                    connectModeRadius < minDistance$4 ||
                    !mousePos) {
                    return;
                }
                const distance = Math.abs(connectModeRadius), query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
                query.forEach((p1, i) => {
                    const pos1 = p1.getPosition(), indexOffset = 1;
                    for (const p2 of query.slice(i + indexOffset)) {
                        const pos2 = p2.getPosition(), distMax = Math.abs(connectModeDistance), xDiff = Math.abs(pos1.x - pos2.x), yDiff = Math.abs(pos1.y - pos2.y);
                        if (xDiff < distMax && yDiff < distMax) {
                            drawConnection(container, p1, p2);
                        }
                    }
                });
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, mouse = interactivityData.mouse, events = (particle?.interactivity ?? container.actualOptions.interactivity)?.events;
            if (!(events?.onHover.enable && mouse.position)) {
                return false;
            }
            return isInArray(connectMode, events.onHover.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "connect", Connect, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalConnectInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalConnect", container => {
                return Promise.resolve(new Connector(container));
            });
        });
    }

    const toleranceFactor = 10;
    function processDestroy(container, area) {
        const query = container.particles.grid.query(area);
        for (const particle of query) {
            particle.destroy();
        }
    }
    function singleSelectorDestroy(container, selector, div) {
        const query = safeDocument().querySelectorAll(selector);
        if (!query.length) {
            return;
        }
        query.forEach(item => {
            const elem = item, pxRatio = container.retina.pixelRatio, pos = {
                x: (elem.offsetLeft + elem.offsetWidth * half$2) * pxRatio,
                y: (elem.offsetTop + elem.offsetHeight * half$2) * pxRatio,
            }, radius = elem.offsetWidth * half$2 * pxRatio, tolerance = toleranceFactor * pxRatio, area = div.type === DivType.circle
                ? new Circle(pos.x, pos.y, radius + tolerance)
                : new Rectangle(elem.offsetLeft * pxRatio - tolerance, elem.offsetTop * pxRatio - tolerance, elem.offsetWidth * pxRatio + tolerance * double, elem.offsetHeight * pxRatio + tolerance * double);
            processDestroy(container, area);
        });
    }
    function divDestroy(container, divs, destroyMode) {
        divModeExecute(destroyMode, divs, (selector, div) => {
            singleSelectorDestroy(container, selector, div);
        });
    }
    function mouseDestroy(container, interactivityData) {
        const pxRatio = container.retina.pixelRatio, tolerance = toleranceFactor * pxRatio, mousePos = interactivityData.mouse.position, radius = container.retina.destroyModeDistance;
        if (!radius || radius < minRadius$8 || !mousePos) {
            return;
        }
        processDestroy(container, new Circle(mousePos.x, mousePos.y, radius + tolerance));
    }

    class Destroy {
        distance = 200;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
        }
    }

    const destroyMode = "destroy";
    class Destroyer extends ExternalInteractorBase {
        #maxDistance;
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            const container = this.container, destroy = container.actualOptions.interactivity?.modes.destroy;
            if (!destroy) {
                return;
            }
            this.#maxDistance = destroy.distance;
            container.retina.destroyModeDistance = destroy.distance * container.retina.pixelRatio;
        }
        interact(interactivityData) {
            const container = this.container, options = container.actualOptions, events = options.interactivity?.events, mouseMoveStatus = interactivityData.status === mouseMoveEvent;
            if (!events) {
                return;
            }
            const hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, divs = events.onDiv;
            if (mouseMoveStatus && hoverEnabled && isInArray(destroyMode, hoverMode)) {
                mouseDestroy(this.container, interactivityData);
            }
            else {
                divDestroy(this.container, divs, destroyMode);
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            if (!events) {
                return false;
            }
            const divs = events.onDiv;
            return ((!!mouse.position && events.onHover.enable && isInArray(destroyMode, events.onHover.mode)) ||
                isDivModeEnabled(destroyMode, divs));
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "destroy", Destroy, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalDestroyInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalDestroy", async (container) => {
                return Promise.resolve(new Destroyer(container));
            });
        });
    }

    class GrabLinks {
        blink = false;
        color;
        consent = false;
        opacity = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "blink", data.blink);
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "consent", data.consent);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class Grab {
        distance = 100;
        links = new GrabLinks();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
            this.links.load(data.links);
        }
    }

    const defaultWidth$2 = 0;
    function drawGrabLine(context, width, begin, end, colorLine, opacity, hdr = false, peakNits, mode) {
        drawLine$1(context, begin, end);
        context.strokeStyle = getStyleFromRgb(colorLine, hdr, opacity, peakNits, mode);
        context.lineWidth = width;
        context.stroke();
    }
    function drawGrab(container, particle, lineColor, opacity, mousePos) {
        container.canvas.render.draw(ctx => {
            const beginPos = particle.getPosition();
            drawGrabLine(ctx, particle.retina.linksWidth ?? defaultWidth$2, beginPos, mousePos, lineColor, opacity, container.hdr, container.peakNits, container.hdrMode);
        });
    }

    const grabMode = "grab", minDistance$3 = 0, minOpacity$1 = 0;
    class Grabber extends ExternalInteractorBase {
        #maxDistance;
        #pluginManager;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            const container = this.container, grab = container.actualOptions.interactivity?.modes.grab;
            if (!grab) {
                return;
            }
            this.#maxDistance = grab.distance;
            container.retina.grabModeDistance = grab.distance * container.retina.pixelRatio;
        }
        interact(interactivityData) {
            const container = this.container, options = container.actualOptions, interactivity = options.interactivity;
            if (!interactivity?.modes.grab ||
                !interactivity.events.onHover.enable ||
                interactivityData.status !== mouseMoveEvent) {
                return;
            }
            const mousePos = interactivityData.mouse.position;
            if (!mousePos) {
                return;
            }
            const distance = container.retina.grabModeDistance;
            if (!distance || distance < minDistance$3) {
                return;
            }
            const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
            for (const particle of query) {
                const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos);
                if (pointDistance > distance) {
                    continue;
                }
                const grabLineOptions = interactivity.modes.grab.links, lineOpacity = grabLineOptions.opacity, opacityLine = lineOpacity - (pointDistance * lineOpacity) / distance;
                if (opacityLine <= minOpacity$1) {
                    continue;
                }
                const optColor = grabLineOptions.color ?? particle.options.links?.color;
                if (!container.particles.grabLineColor && optColor) {
                    const linksOptions = interactivity.modes.grab.links;
                    container.particles.grabLineColor = getLinkRandomColor(this.#pluginManager, optColor, linksOptions.blink, linksOptions.consent);
                }
                const colorLine = getLinkColor(particle, undefined, container.particles.grabLineColor, container.hdr);
                if (!colorLine) {
                    continue;
                }
                drawGrab(container, particle, colorLine, opacityLine, mousePos);
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, mouse = interactivityData.mouse, events = (particle?.interactivity ?? container.actualOptions.interactivity)?.events;
            return !!events?.onHover.enable && !!mouse.position && isInArray(grabMode, events.onHover.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "grab", Grab, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalGrabInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalGrab", container => {
                return Promise.resolve(new Grabber(e.pluginManager, container));
            });
        });
    }

    class Parallax {
        force = 2;
        smooth = 10;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "force", data.force);
            loadProperty(this, "smooth", data.smooth);
        }
    }

    const parallaxMode = "parallax";
    class Parallaxer extends ExternalInteractorBase {
        maxDistance = 0;
        constructor(container) {
            super(container);
        }
        clear() {
        }
        init() {
        }
        interact(interactivityData) {
            for (const particle of this.container.particles.filter(p => this.isEnabled(interactivityData, p))) {
                this.#parallaxInteract(interactivityData, particle);
            }
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, mouse = interactivityData.mouse, events = (particle?.interactivity ?? container.actualOptions.interactivity)?.events;
            return !!events?.onHover.enable && !!mouse.position && isInArray(parallaxMode, events.onHover.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "parallax", Parallax, ...sources);
        }
        reset() {
        }
        #parallaxInteract(interactivityData, particle) {
            if (!this.isEnabled(interactivityData, particle)) {
                return;
            }
            const container = this.container, options = container.actualOptions, parallaxOptions = options.interactivity?.modes.parallax;
            if (!parallaxOptions) {
                return;
            }
            const parallaxForce = parallaxOptions.force, mousePos = interactivityData.mouse.position;
            if (!mousePos) {
                return;
            }
            const canvasSize = container.canvas.size, canvasCenter = {
                x: canvasSize.width * half$2,
                y: canvasSize.height * half$2,
            }, parallaxSmooth = parallaxOptions.smooth, factor = particle.getRadius() / parallaxForce, centerDistance = {
                x: (mousePos.x - canvasCenter.x) * factor,
                y: (mousePos.y - canvasCenter.y) * factor,
            }, { offset } = particle;
            offset.x += (centerDistance.x - offset.x) / parallaxSmooth;
            offset.y += (centerDistance.y - offset.y) / parallaxSmooth;
        }
    }

    async function loadExternalParallaxInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalParallax", container => {
                return Promise.resolve(new Parallaxer(container));
            });
        });
    }

    const pauseMode = "pause";
    class Pauser extends ExternalInteractorBase {
        handleClickMode;
        maxDistance = 0;
        constructor(container) {
            super(container);
            this.handleClickMode = (mode) => {
                if (mode !== pauseMode) {
                    return;
                }
                const container = this.container;
                if (container.animationStatus) {
                    container.pause();
                }
                else {
                    container.play();
                }
            };
        }
        clear() {
        }
        init() {
        }
        interact() {
        }
        isEnabled(_interactivityData, particle) {
            const container = this.container, options = container.actualOptions, events = (particle?.interactivity ?? options.interactivity)?.events;
            return !!events && isInArray(pauseMode, events.onClick.mode);
        }
        reset() {
        }
    }

    async function loadExternalPauseInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalPause", container => {
                return Promise.resolve(new Pauser(container));
            });
        });
    }

    class Push {
        default = true;
        groups = [];
        particles;
        quantity = 4;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "default", data.default);
            if (data.groups !== undefined) {
                this.groups = data.groups.map(t => t);
            }
            if (!this.groups.length) {
                this.default = true;
            }
            loadRangeProperty(this, "quantity", data.quantity);
            this.particles = executeOnSingleOrMultiple(data.particles, particles => {
                return deepExtend({}, particles);
            });
        }
    }

    const pushMode = "push", minQuantity = 0;
    class Pusher extends ExternalInteractorBase {
        handleClickMode;
        maxDistance = 0;
        constructor(container) {
            super(container);
            this.handleClickMode = (mode, interactivityData) => {
                if (mode !== pushMode) {
                    return;
                }
                const container = this.container, options = container.actualOptions, pushOptions = options.interactivity?.modes.push;
                if (!pushOptions) {
                    return;
                }
                const quantity = getRangeValue(pushOptions.quantity);
                if (quantity <= minQuantity) {
                    return;
                }
                const group = itemFromArray([undefined, ...pushOptions.groups]), groupOptions = group !== undefined ? container.actualOptions.particles.groups[group] : undefined, particlesOptions = itemFromSingleOrMultiple(pushOptions.particles), overrideOptions = deepExtend(groupOptions, particlesOptions);
                container.particles.push(quantity, interactivityData.mouse.position, overrideOptions, group);
            };
        }
        clear() {
        }
        init() {
        }
        interact() {
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            return !!events && mouse.clicking && mouse.inside && !!mouse.position && isInArray(pushMode, events.onClick.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "push", Push, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalPushInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalPush", container => {
                return Promise.resolve(new Pusher(container));
            });
        });
    }

    class Remove {
        quantity = 2;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "quantity", data.quantity);
        }
    }

    const removeMode = "remove";
    class Remover extends ExternalInteractorBase {
        handleClickMode;
        maxDistance = 0;
        constructor(container) {
            super(container);
            this.handleClickMode = (mode) => {
                const container = this.container, options = container.actualOptions;
                if (!options.interactivity?.modes.remove || mode !== removeMode) {
                    return;
                }
                const removeNb = getRangeValue(options.interactivity.modes.remove.quantity);
                for (let i = 0; i < removeNb; i++) {
                    container.particles.get(i)?.destroy();
                }
            };
        }
        clear() {
        }
        init() {
        }
        interact() {
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            return !!events && mouse.clicking && mouse.inside && !!mouse.position && isInArray(removeMode, events.onClick.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "remove", Remove, ...sources);
        }
        reset() {
        }
    }

    async function loadExternalRemoveInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalRemove", container => {
                return Promise.resolve(new Remover(container));
            });
        });
    }

    class RepulseBase {
        distance = 200;
        duration = 0.4;
        easing = "ease-out-quad";
        factor = 100;
        maxSpeed = 50;
        restore;
        speed = 1;
        constructor() {
            this.restore = {
                enable: false,
                delay: 0,
                speed: 0.08,
                follow: true,
            };
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "distance", data.distance);
            loadProperty(this, "duration", data.duration);
            loadProperty(this, "easing", data.easing);
            loadProperty(this, "factor", data.factor);
            loadProperty(this, "speed", data.speed);
            loadProperty(this, "maxSpeed", data.maxSpeed);
            if (data.restore !== undefined) {
                this.restore.enable = data.restore.enable ?? this.restore.enable;
                this.restore.delay = data.restore.delay ?? this.restore.delay;
                this.restore.speed = data.restore.speed ?? this.restore.speed;
                this.restore.follow = data.restore.follow ?? this.restore.follow;
            }
        }
    }

    class RepulseDiv extends RepulseBase {
        selectors = [];
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "selectors", data.selectors);
        }
    }

    class Repulse extends RepulseBase {
        divs;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            this.divs = executeOnSingleOrMultiple(data.divs, div => {
                const tmp = new RepulseDiv();
                tmp.load(div);
                return tmp;
            });
        }
    }

    const repulseMode = "repulse", minDistance$2 = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius$4 = 0, minSpeed = 0, easingOffset = 1, minRestoreSpeed = 0.001, maxRestoreSpeed = 1, restoreEpsilon = 0.5;
    let Repulser$1 = class Repulser extends ExternalInteractorBase {
        handleClickMode;
        #clickVec;
        #interactedThisFrame;
        #maxDistance;
        #normVec;
        #pluginManager;
        #restoreData;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.#maxDistance = 0;
            this.#normVec = Vector.origin;
            this.#interactedThisFrame = new Set();
            this.#clickVec = Vector.origin;
            this.#restoreData = new Map();
            container.repulse ??= { particles: [] };
            this.handleClickMode = (mode, interactivityData) => {
                const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
                if (!repulseOpts || mode !== repulseMode) {
                    return;
                }
                container.repulse ??= { particles: [] };
                const repulse = container.repulse;
                repulse.clicking = true;
                repulse.count = 0;
                for (const particle of container.repulse.particles) {
                    if (!this.isEnabled(interactivityData, particle)) {
                        continue;
                    }
                    particle.velocity.setTo(particle.initialVelocity);
                }
                repulse.particles = [];
                repulse.finish = false;
                setTimeout(() => {
                    if (container.destroyed) {
                        return;
                    }
                    repulse.clicking = false;
                }, repulseOpts.duration * millisecondsToSeconds$1);
            };
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
            if (!repulse) {
                return;
            }
            this.#maxDistance = repulse.distance;
            container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
        }
        interact(interactivityData) {
            this.#interactedThisFrame.clear();
            const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
            if (!events) {
                return;
            }
            const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
            if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
                this.#hoverRepulse(interactivityData);
            }
            else if (clickEnabled && isInArray(repulseMode, clickMode)) {
                this.#clickRepulse(interactivityData);
            }
            else {
                divModeExecute(repulseMode, divs, (selector, div) => {
                    this.#singleSelectorRepulse(interactivityData, selector, div);
                });
            }
            this.#restoreParticles();
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
            if (!events) {
                return false;
            }
            const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
            if (!(divRepulse || (hover.enable && !!mouse.position) || (click.enable && mouse.clickPosition))) {
                return false;
            }
            const hoverMode = hover.mode, clickMode = click.mode;
            return isInArray(repulseMode, hoverMode) || isInArray(repulseMode, clickMode) || divRepulse;
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "repulse", Repulse, ...sources);
        }
        reset() {
        }
        #clickRepulse(interactivityData) {
            const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
            if (!repulseOptions) {
                return;
            }
            const repulse = container.repulse ?? { particles: [] };
            if (!repulse.finish) {
                repulse.count ??= 0;
                repulse.count++;
                if (repulse.count === container.particles.count) {
                    repulse.finish = true;
                }
            }
            if (repulse.clicking) {
                const repulseDistance = container.retina.repulseModeDistance;
                if (!repulseDistance || repulseDistance < minDistance$2) {
                    return;
                }
                const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = interactivityData.mouse.clickPosition;
                if (mouseClickPos === undefined) {
                    return;
                }
                const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.grid.query(range, p => this.isEnabled(interactivityData, p));
                for (const particle of query) {
                    const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
                    if (d <= repulseRadius) {
                        this.#trackInteractedParticle(particle);
                        repulse.particles.push(particle);
                        this.#clickVec.x = dx;
                        this.#clickVec.y = dy;
                        this.#clickVec.length = force;
                        particle.velocity.setTo(this.#clickVec);
                    }
                }
            }
            else if (repulse.clicking === false) {
                for (const particle of repulse.particles) {
                    particle.velocity.setTo(particle.initialVelocity);
                }
                repulse.particles = [];
            }
        }
        #hoverRepulse(interactivityData) {
            const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
            if (!repulseRadius || repulseRadius < minRadius$4 || !mousePos) {
                return;
            }
            this.#processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
        }
        #processRepulse(interactivityData, position, repulseRadius, area, divRepulse) {
            const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
            if (!repulseOptions) {
                return;
            }
            const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.#pluginManager.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
            for (const particle of query) {
                const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
                this.#normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
                this.#normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
                this.#trackInteractedParticle(particle);
                particle.position.addTo(this.#normVec);
            }
        }
        #restoreParticles() {
            const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
            if (!restore?.enable || !this.#restoreData.size) {
                return;
            }
            const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds$1, restoreSpeed = Math.max(minRestoreSpeed, Math.min(maxRestoreSpeed, restore.speed));
            for (const [particle, restoreData] of this.#restoreData) {
                if (this.#interactedThisFrame.has(particle)) {
                    continue;
                }
                if (particle.destroyed) {
                    this.#restoreData.delete(particle);
                    continue;
                }
                const target = restoreData.target;
                if (now - restoreData.lastInteractionTime < restoreDelay) {
                    continue;
                }
                if (restore.follow && particle.options.move.enable) {
                    target.x += particle.velocity.x;
                    target.y += particle.velocity.y;
                    target.z += particle.velocity.z;
                }
                const dx = target.x - particle.position.x, dy = target.y - particle.position.y, dz = target.z - particle.position.z;
                particle.position.x += dx * restoreSpeed;
                particle.position.y += dy * restoreSpeed;
                particle.position.z += dz * restoreSpeed;
                if (Math.abs(dx) <= restoreEpsilon && Math.abs(dy) <= restoreEpsilon) {
                    particle.position.x = target.x;
                    particle.position.y = target.y;
                    particle.position.z = target.z;
                    this.#restoreData.delete(particle);
                    continue;
                }
            }
        }
        #singleSelectorRepulse(interactivityData, selector, div) {
            const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
            if (!repulse) {
                return;
            }
            const query = safeDocument().querySelectorAll(selector);
            if (!query.length) {
                return;
            }
            query.forEach(item => {
                const elem = item, pxRatio = container.retina.pixelRatio, pos = {
                    x: (elem.offsetLeft + elem.offsetWidth * half$2) * pxRatio,
                    y: (elem.offsetTop + elem.offsetHeight * half$2) * pxRatio,
                }, repulseRadius = elem.offsetWidth * half$2 * pxRatio, area = div.type === DivType.circle
                    ? new Circle(pos.x, pos.y, repulseRadius)
                    : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
                this.#processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
            });
        }
        #trackInteractedParticle(particle) {
            this.#interactedThisFrame.add(particle);
            const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
            if (!restore?.enable) {
                return;
            }
            const now = Date.now();
            let restoreData = this.#restoreData.get(particle);
            if (!restoreData) {
                restoreData = {
                    target: particle.position.copy(),
                    lastInteractionTime: now,
                };
                this.#restoreData.set(particle, restoreData);
            }
            restoreData.lastInteractionTime = now;
            if (restore.follow && particle.options.move.enable) {
                restoreData.target.x += particle.velocity.x;
                restoreData.target.y += particle.velocity.y;
                restoreData.target.z += particle.velocity.z;
            }
        }
    };

    async function loadExternalRepulseInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            const pluginManager = e.pluginManager;
            pluginManager.addInteractor?.("externalRepulse", container => {
                return Promise.resolve(new Repulser$1(pluginManager, container));
            });
        });
    }

    class Slow {
        factor = 3;
        radius = 200;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "factor", data.factor);
            loadProperty(this, "radius", data.radius);
        }
    }

    class SlowModifier {
        enabled = false;
        id = "slow";
        priority = 100;
        speedFactor = 1;
    }

    const slowMode = "slow", minRadius$3 = 0;
    class Slower extends ExternalInteractorBase {
        #maxDistance;
        #modifiers = new WeakMap();
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear(particle, _delta, force) {
            const mod = this.#modifiers.get(particle);
            if (mod?.enabled && !force) {
                return;
            }
            particle.removeModifier(slowMode);
            this.#modifiers.delete(particle);
        }
        getOrCreateModifier(particle) {
            let mod = this.#modifiers.get(particle);
            if (!mod) {
                mod = new SlowModifier();
                this.#modifiers.set(particle, mod);
                particle.addModifier(mod);
            }
            return mod;
        }
        init() {
            const container = this.container, slow = container.actualOptions.interactivity?.modes.slow;
            if (!slow) {
                return;
            }
            this.#maxDistance = slow.radius;
            container.retina.slowModeRadius = slow.radius * container.retina.pixelRatio;
        }
        interact() {
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, mouse = interactivityData.mouse, events = (particle?.interactivity ?? container.actualOptions.interactivity)?.events;
            return !!events?.onHover.enable && !!mouse.position && isInArray(slowMode, events.onHover.mode);
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "slow", Slow, ...sources);
        }
        reset(interactivityData, particle) {
            const mod = this.#modifiers.get(particle);
            if (mod) {
                mod.enabled = false;
            }
            const container = this.container, options = container.actualOptions, mousePos = interactivityData.mouse.position, radius = container.retina.slowModeRadius, slowOptions = options.interactivity?.modes.slow;
            if (!slowOptions || !radius || radius < minRadius$3 || !mousePos) {
                return;
            }
            const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor;
            if (dist > radius) {
                return;
            }
            const activeMod = this.getOrCreateModifier(particle);
            activeMod.enabled = true;
            activeMod.speedFactor = proximityFactor / slowFactor;
        }
    }

    async function loadExternalSlowInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalSlow", container => {
                return Promise.resolve(new Slower(container));
            });
        });
    }

    const shapeTypes = ["image", "images"];
    const stringStart = 0, defaultOpacity = 1;
    const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
    function replaceColorSvg(imageShape, color, opacity, hdr = false, peakNits, mode) {
        const { svgData } = imageShape;
        if (!svgData) {
            return "";
        }
        const colorStyle = getStyleFromHsl(color, hdr, opacity, peakNits, mode);
        if (svgData.includes("fill")) {
            return svgData.replaceAll(currentColorRegex, () => colorStyle);
        }
        const preFillIndex = svgData.indexOf(">");
        return `${svgData.substring(stringStart, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
    }
    async function loadImage(image) {
        return new Promise(resolve => {
            image.loading = true;
            const img = new Image();
            image.element = img;
            img.addEventListener("load", () => {
                image.loading = false;
                resolve();
            });
            img.addEventListener("error", () => {
                image.element = undefined;
                image.error = true;
                image.loading = false;
                getLogger().error(`Error loading image: ${image.source}`);
                resolve();
            });
            img.src = image.source;
        });
    }
    async function downloadSvgImage(image) {
        if (image.type !== "svg") {
            await loadImage(image);
            return;
        }
        image.loading = true;
        const response = await fetch(image.source);
        if (response.ok) {
            image.svgData = await response.text();
        }
        else {
            getLogger().error("Image not found");
            image.error = true;
        }
        image.loading = false;
    }
    function replaceImageColor(image, imageData, color, particle, hdr = false, peakNits, mode) {
        const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity, hdr, peakNits, mode), imageRes = {
            color,
            data: {
                ...image,
                svgData: svgColoredData,
            },
            loaded: false,
            ratio: imageData.width / imageData.height,
            replaceColor: imageData.replaceColor,
            source: imageData.src,
        };
        return new Promise(resolve => {
            const svg = new Blob([svgColoredData], { type: "image/svg+xml" }), url = URL.createObjectURL(svg), img = new Image();
            img.addEventListener("load", () => {
                imageRes.loaded = true;
                imageRes.element = img;
                resolve(imageRes);
                URL.revokeObjectURL(url);
            });
            const errorHandler = async () => {
                URL.revokeObjectURL(url);
                const img2 = {
                    ...image,
                    error: false,
                    loading: true,
                };
                await loadImage(img2);
                imageRes.loaded = true;
                imageRes.element = img2.element;
                resolve(imageRes);
            };
            img.addEventListener("error", () => void errorHandler());
            img.src = url;
        });
    }

    const sides$3 = 12;
    class ImageDrawer {
        #container;
        #engine;
        constructor(engine, container) {
            this.#engine = engine;
            this.#container = container;
        }
        draw(data) {
            const { context, radius, particle, opacity } = data, image = particle.image, element = image?.element;
            if (!image) {
                return;
            }
            context.globalAlpha = opacity;
            if (element) {
                const ratio = image.ratio, pos = {
                    x: -radius,
                    y: -radius,
                }, diameter = radius * double;
                context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);
            }
            context.globalAlpha = defaultAlpha$1;
        }
        getSidesCount() {
            return sides$3;
        }
        async init(container) {
            const options = container.actualOptions;
            if (!options.preload || !this.#engine.loadImage) {
                return;
            }
            const promises = [];
            for (const imageData of options.preload) {
                promises.push(this.#engine.loadImage(container, imageData));
            }
            await Promise.all(promises);
        }
        loadShape(particle) {
            const container = this.#container;
            if (!particle.shape || !shapeTypes.includes(particle.shape)) {
                return;
            }
            const imageData = particle.shapeData;
            if (!imageData) {
                return;
            }
            const images = this.#engine.getImages?.(container), image = images?.find((t) => t.name === imageData.name || t.source === imageData.src);
            if (image) {
                return;
            }
            void this.#loadImageShape(container, imageData).then(() => {
                this.loadShape(particle);
            });
        }
        particleInit(container, particle) {
            if (particle.shape !== "image" && particle.shape !== "images") {
                return;
            }
            const images = this.#engine.getImages?.(container), imageData = particle.shapeData;
            if (!imageData) {
                return;
            }
            const color = particle.getFillColor(), image = images?.find((t) => t.name === imageData.name || t.source === imageData.src);
            if (!image) {
                return;
            }
            const replaceColor = imageData.replaceColor;
            if (image.loading) {
                setTimeout(() => {
                    this.particleInit(container, particle);
                });
                return;
            }
            void (async () => {
                let imageRes;
                if (image.svgData && color) {
                    imageRes = await replaceImageColor(image, imageData, color, particle, container.hdr, container.peakNits, container.hdrMode);
                }
                else {
                    imageRes = {
                        color,
                        data: image,
                        element: image.element,
                        loaded: true,
                        ratio: imageData.width && imageData.height ? imageData.width / imageData.height : (image.ratio ?? defaultRatio$1),
                        replaceColor: replaceColor,
                        source: imageData.src,
                    };
                }
                if (!imageRes.ratio) {
                    imageRes.ratio = 1;
                }
                const close = imageData.close ?? particle.shapeClose, imageShape = {
                    image: imageRes,
                    close,
                };
                particle.image = imageShape.image;
                particle.shapeClose = imageShape.close;
            })();
        }
        #loadImageShape = async (container, imageShape) => {
            if (!this.#engine.loadImage) {
                throw new Error(`Image shape not initialized`);
            }
            await this.#engine.loadImage(container, {
                name: imageShape.name,
                replaceColor: imageShape.replaceColor,
                src: imageShape.src,
            });
        };
    }

    class Preload {
        height;
        name;
        replaceColor;
        src = "";
        width;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "height", data.height);
            loadProperty(this, "name", data.name);
            loadProperty(this, "replaceColor", data.replaceColor);
            loadProperty(this, "src", data.src);
            loadProperty(this, "width", data.width);
        }
    }

    class ImagePreloaderPlugin {
        id = "image-preloader";
        #engine;
        constructor(engine) {
            this.#engine = engine;
        }
        async getPlugin(container) {
            const { ImagePreloaderInstance } = await Promise.resolve().then(function () { return ImagePreloaderInstance$1; });
            return new ImagePreloaderInstance(this.#engine, container);
        }
        loadOptions(_container, options, source) {
            if (!source?.preload) {
                return;
            }
            options.preload ??= [];
            const preloadOptions = options.preload;
            for (const item of source.preload) {
                const existing = preloadOptions.find(t => t.name === item.name || t.src === item.src);
                if (existing) {
                    existing.load(item);
                }
                else {
                    const preload = new Preload();
                    preload.load(item);
                    preloadOptions.push(preload);
                }
            }
        }
        needsPlugin() {
            return true;
        }
    }

    const extLength = 3;
    function addLoadImageToEngine(engine) {
        engine.getImages ??= (container) => {
            engine.images ??= new Map();
            let images = engine.images.get(container);
            if (!images) {
                images = [];
                engine.images.set(container, images);
            }
            return images;
        };
        engine.loadImage ??= async (container, data) => {
            if (!engine.getImages) {
                throw new Error("No images collection found");
            }
            if (!data.name && !data.src) {
                throw new Error("No image source provided");
            }
            engine.images ??= new Map();
            const containerImages = engine.getImages(container);
            if (containerImages.some((t) => t.name === data.name || t.source === data.src)) {
                return;
            }
            try {
                const image = {
                    name: data.name ?? data.src,
                    source: data.src,
                    type: data.src.substring(data.src.length - extLength),
                    error: false,
                    loading: true,
                    replaceColor: data.replaceColor,
                    ratio: data.width && data.height ? data.width / data.height : undefined,
                };
                containerImages.push(image);
                engine.images.set(container, containerImages);
                let imageFunc;
                if (data.replaceColor) {
                    imageFunc = downloadSvgImage;
                }
                else {
                    imageFunc = loadImage;
                }
                await imageFunc(image);
            }
            catch {
                throw new Error(`${data.name ?? data.src} not found`);
            }
        };
    }
    async function loadImageShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            addLoadImageToEngine(e);
            e.pluginManager.addPlugin(new ImagePreloaderPlugin(e));
            e.pluginManager.addShape(shapeTypes, container => Promise.resolve(new ImageDrawer(e, container)));
        });
    }

    class LifeDelay extends ValueWithRandom {
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "sync", data.sync);
        }
    }

    class LifeDuration extends ValueWithRandom {
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "sync", data.sync);
        }
    }

    class Life {
        count = 0;
        delay = new LifeDelay();
        duration = new LifeDuration();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "count", data.count);
            this.delay.load(data.delay);
            this.duration.load(data.duration);
        }
    }

    const noTime$1 = 0, infiniteValue$1 = -1, noLife = 0, minCanvasSize = 0;
    function updateLife(particle, delta, canvasSize) {
        if (!particle.life) {
            return;
        }
        const life = particle.life;
        let justSpawned = false;
        if (particle.spawning) {
            life.delayTime += delta.value;
            if (life.delayTime >= particle.life.delay) {
                justSpawned = true;
                particle.spawning = false;
                life.delayTime = noTime$1;
                life.time = noTime$1;
            }
            else {
                return;
            }
        }
        if (life.duration === infiniteValue$1) {
            return;
        }
        if (justSpawned) {
            life.time = noTime$1;
        }
        else {
            life.time += delta.value;
        }
        if (life.time < life.duration) {
            return;
        }
        life.time = noTime$1;
        if (particle.life.count > noLife) {
            particle.life.count--;
        }
        if (particle.life.count === noLife) {
            particle.destroy();
            return;
        }
        const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.width);
        particle.position.x = randomInRangeValue(widthRange);
        particle.position.y = randomInRangeValue(heightRange);
        particle.spawning = true;
        life.delayTime = noTime$1;
        life.time = noTime$1;
        particle.reset();
        const lifeOptions = particle.options.life;
        if (lifeOptions) {
            life.delay = getRangeValue(lifeOptions.delay.value) * millisecondsToSeconds$1;
            life.duration = getRangeValue(lifeOptions.duration.value) * millisecondsToSeconds$1;
        }
    }

    const noTime = 0, identity$2 = 1, infiniteValue = -1;
    class LifeUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const container = this.#container, particlesOptions = particle.options, lifeOptions = particlesOptions.life;
            if (!lifeOptions) {
                return;
            }
            const delayFactor = lifeOptions.delay.sync ? identity$2 : getRandom(), durationFactor = lifeOptions.duration.sync ? identity$2 : getRandom();
            particle.life = {
                delay: container.retina.reduceFactor
                    ? ((getRangeValue(lifeOptions.delay.value) * delayFactor) / container.retina.reduceFactor) *
                        millisecondsToSeconds$1
                    : noTime,
                delayTime: noTime,
                duration: container.retina.reduceFactor
                    ? ((getRangeValue(lifeOptions.duration.value) * durationFactor) / container.retina.reduceFactor) *
                        millisecondsToSeconds$1
                    : noTime,
                time: noTime,
                count: lifeOptions.count,
            };
            if (particle.life.duration <= noTime) {
                particle.life.duration = infiniteValue;
            }
            if (particle.life.count <= noTime) {
                particle.life.count = infiniteValue;
            }
            particle.spawning = particle.life.delay > noTime;
        }
        isEnabled(particle) {
            return !particle.destroyed;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "life", Life, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.life) {
                return;
            }
            updateLife(particle, delta, this.#container.canvas.size);
        }
    }

    async function loadLifeUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("life", container => {
                return Promise.resolve(new LifeUpdater(container));
            });
        });
    }

    function drawLine(data) {
        const { context, particle, radius } = data, shapeData = particle.shapeData, centerY = 0;
        context.moveTo(-radius, centerY);
        context.lineTo(radius, centerY);
        context.lineCap = shapeData?.cap ?? "butt";
    }

    const sides$2 = 1;
    class LineDrawer {
        draw(data) {
            drawLine(data);
        }
        getSidesCount() {
            return sides$2;
        }
    }

    async function loadLineShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
        });
    }

    class Attract {
        distance = 200;
        enable = false;
        rotate;
        constructor() {
            this.rotate = {
                x: 3000,
                y: 3000,
            };
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "distance", data.distance);
            loadProperty(this, "enable", data.enable);
            if (data.rotate) {
                const rotateX = data.rotate.x;
                if (rotateX !== undefined) {
                    this.rotate.x = rotateX;
                }
                const rotateY = data.rotate.y;
                if (rotateY !== undefined) {
                    this.rotate.y = rotateY;
                }
            }
        }
    }

    const attractFactor = 1000, identity$1 = 1;
    class Attractor extends ParticlesInteractorBase {
        #maxDistance;
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
        }
        interact(p1) {
            if (!p1.options.attract?.enable) {
                return;
            }
            const container = this.container;
            if (isNull(p1.attractDistance)) {
                const attractDistance = getRangeValue(p1.options.attract.distance);
                if (attractDistance > this.#maxDistance) {
                    this.#maxDistance = attractDistance;
                }
                p1.attractDistance = attractDistance * container.retina.pixelRatio;
            }
            const distance = p1.attractDistance, pos1 = p1.getPosition(), query = container.particles.grid.queryCircle(pos1, distance);
            for (const p2 of query) {
                if (p1 === p2 || !p2.options.attract?.enable || p2.destroyed || p2.spawning) {
                    continue;
                }
                const pos2 = p2.getPosition(), { dx, dy } = getDistances(pos1, pos2), rotate = p1.options.attract.rotate, ax = dx / (rotate.x * attractFactor), ay = dy / (rotate.y * attractFactor), p1Factor = p2.size.value / p1.size.value, p2Factor = identity$1 / p1Factor;
                p1.velocity.x -= ax * p1Factor;
                p1.velocity.y -= ay * p1Factor;
                p2.velocity.x += ax * p2Factor;
                p2.velocity.y += ay * p2Factor;
            }
        }
        isEnabled(particle) {
            return particle.options.attract?.enable ?? false;
        }
        loadParticlesOptions(options, ...sources) {
            loadOptionProperty(options, "attract", Attract, ...sources);
        }
        reset() {
        }
    }

    async function loadParticlesAttractInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("particlesAttract", container => {
                return Promise.resolve(new Attractor(container));
            });
        });
    }

    var CollisionMode;
    (function (CollisionMode) {
        CollisionMode["absorb"] = "absorb";
        CollisionMode["bounce"] = "bounce";
        CollisionMode["destroy"] = "destroy";
    })(CollisionMode || (CollisionMode = {}));

    class CollisionsAbsorb {
        speed = 2;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "speed", data.speed);
        }
    }

    class CollisionsOverlap {
        enable = true;
        retries = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "retries", data.retries);
        }
    }

    class Collisions {
        absorb = new CollisionsAbsorb();
        bounce = new ParticlesBounce();
        enable = false;
        maxSpeed = 50;
        mode = CollisionMode.bounce;
        overlap = new CollisionsOverlap();
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.absorb.load(data.absorb);
            this.bounce.load(data.bounce);
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "maxSpeed", data.maxSpeed);
            loadProperty(this, "mode", data.mode);
            this.overlap.load(data.overlap);
        }
    }

    const minAbsorbAmount = 0;
    function updateAbsorb(p1, r1, p2, r2, delta, pixelRatio) {
        if (!p1.options.collisions || !p2.options.collisions) {
            return;
        }
        const absorbSpeed = p1.options.collisions.absorb.speed, shrinkAmount = clamp(absorbSpeed * delta.factor, minAbsorbAmount, r2);
        p1.size.value = Math.sqrt(r1 * r1 + shrinkAmount * shrinkAmount);
        p2.size.value -= shrinkAmount;
        if (p2.size.value <= pixelRatio) {
            p2.size.value = 0;
            p2.destroy();
        }
    }
    function absorb(p1, p2, delta, pixelRatio) {
        const r1 = p1.getRadius(), r2 = p2.getRadius();
        if (!r1 && r2) {
            p1.destroy();
        }
        else if (r1 && !r2) {
            p2.destroy();
        }
        else if (r1 && r2) {
            if (r1 >= r2) {
                updateAbsorb(p1, r1, p2, r2, delta, pixelRatio);
            }
            else {
                updateAbsorb(p2, r2, p1, r1, delta, pixelRatio);
            }
        }
    }

    const energyCorrectionMinRatio = 1e-6, energyDriftThreshold = 1e-4, correctionFactorNeutral = 1, fixBounceSpeed = (p) => {
        if (!p.options.collisions) {
            return;
        }
        p.collisionMaxSpeed ??= getRangeValue(p.options.collisions.maxSpeed);
        if (p.velocity.length > p.collisionMaxSpeed) {
            p.velocity.length = p.collisionMaxSpeed;
        }
    };
    function bounce(p1, p2) {
        const m1 = p1.getMass(), m2 = p2.getMass(), speed1Before = p1.velocity.length, speed2Before = p2.velocity.length, keBefore = m1 * speed1Before * speed1Before + m2 * speed2Before * speed2Before;
        circleBounce(circleBounceDataFromParticle(p1), circleBounceDataFromParticle(p2));
        const speed1After = p1.velocity.length, speed2After = p2.velocity.length, keAfter = m1 * speed1After * speed1After + m2 * speed2After * speed2After;
        if (keAfter > keBefore * energyCorrectionMinRatio) {
            const correctionFactor = Math.sqrt(keBefore / keAfter);
            if (Math.abs(correctionFactor - correctionFactorNeutral) > energyDriftThreshold) {
                p1.velocity.length = speed1After * correctionFactor;
                p2.velocity.length = speed2After * correctionFactor;
            }
        }
        fixBounceSpeed(p1);
        fixBounceSpeed(p2);
    }

    function destroy(p1, p2) {
        if (!p1.unbreakable && !p2.unbreakable) {
            bounce(p1, p2);
        }
        const p1Radius = p1.getRadius(), p2Radius = p2.getRadius();
        if (!p1Radius && p2Radius) {
            p1.destroy();
        }
        else if (p1Radius && !p2Radius) {
            p2.destroy();
        }
        else if (p1Radius && p2Radius) {
            const deleteP = p1.getRadius() >= p2.getRadius() ? p2 : p1;
            deleteP.destroy();
        }
    }

    function resolveCollision(p1, p2, delta, pixelRatio) {
        if (!p1.options.collisions || !p2.options.collisions) {
            return;
        }
        switch (p1.options.collisions.mode) {
            case CollisionMode.absorb: {
                absorb(p1, p2, delta, pixelRatio);
                break;
            }
            case CollisionMode.bounce: {
                bounce(p1, p2);
                break;
            }
            case CollisionMode.destroy: {
                destroy(p1, p2);
                break;
            }
        }
    }

    class Collider extends ParticlesInteractorBase {
        maxDistance;
        constructor(container) {
            super(container);
            this.maxDistance = 0;
        }
        clear() {
        }
        init() {
        }
        interact(p1, _interactivityData, delta) {
            if (p1.destroyed || p1.spawning) {
                return;
            }
            const container = this.container, pos1 = p1.getPosition(), radius1 = p1.getRadius(), query = container.particles.grid.queryCircle(pos1, radius1 * double);
            for (const p2 of query) {
                if (p1 === p2 ||
                    p1.id >= p2.id ||
                    !p1.options.collisions?.enable ||
                    !p2.options.collisions?.enable ||
                    p1.options.collisions.mode !== p2.options.collisions.mode ||
                    p2.destroyed ||
                    p2.spawning) {
                    continue;
                }
                const pos2 = p2.getPosition(), radius2 = p2.getRadius();
                if (Math.abs(Math.round(pos1.z) - Math.round(pos2.z)) > radius1 + radius2) {
                    continue;
                }
                const dist = getDistance(pos1, pos2), distP = radius1 + radius2;
                if (dist > distP) {
                    continue;
                }
                resolveCollision(p1, p2, delta, container.retina.pixelRatio);
            }
        }
        isEnabled(particle) {
            return !!particle.options.collisions?.enable;
        }
        loadParticlesOptions(options, ...sources) {
            loadOptionProperty(options, "collisions", Collisions, ...sources);
        }
        reset() {
        }
    }

    class OverlapPlugin {
        id = "overlap";
        async getPlugin(container) {
            const { OverlapPluginInstance } = await Promise.resolve().then(function () { return OverlapPluginInstance$1; });
            return new OverlapPluginInstance(container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadParticlesCollisionsInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addPlugin(new OverlapPlugin());
            e.pluginManager.addInteractor?.("particlesCollisions", container => {
                return Promise.resolve(new Collider(container));
            });
        });
    }

    class CircleWarp extends Circle {
        #canvasSize;
        constructor(x, y, radius, canvasSize) {
            super(x, y, radius);
            this.#canvasSize = canvasSize;
        }
        contains(point) {
            if (super.contains(point))
                return true;
            const { width, height } = this.#canvasSize, { x, y } = point;
            return (super.contains({ x: x - width, y }) ||
                super.contains({ x: x + width, y }) ||
                super.contains({ x, y: y - height }) ||
                super.contains({ x, y: y + height }) ||
                super.contains({ x: x - width, y: y - height }) ||
                super.contains({ x: x + width, y: y + height }) ||
                super.contains({ x: x - width, y: y + height }) ||
                super.contains({ x: x + width, y: y - height }));
        }
        intersects(range) {
            if (super.intersects(range))
                return true;
            const { width, height } = this.#canvasSize, pos = range.position, shifts = [
                { x: -width, y: 0 },
                { x: width, y: 0 },
                { x: 0, y: -height },
                { x: 0, y: height },
                { x: -width, y: -height },
                { x: width, y: height },
                { x: -width, y: height },
                { x: width, y: -height },
            ];
            for (const shift of shifts) {
                const shiftedPos = { x: pos.x + shift.x, y: pos.y + shift.y };
                let shiftedRange;
                if (range instanceof Circle) {
                    shiftedRange = new Circle(shiftedPos.x, shiftedPos.y, range.radius);
                }
                else {
                    const rect = range;
                    shiftedRange = new Rectangle(shiftedPos.x, shiftedPos.y, rect.size.width, rect.size.height);
                }
                if (super.intersects(shiftedRange))
                    return true;
            }
            return false;
        }
    }

    class LinksShadow {
        blur = 5;
        color = new OptionsColor();
        enable = false;
        constructor() {
            this.color.value = "#000";
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "blur", data.blur);
            this.color = OptionsColor.create(this.color, data.color);
            loadProperty(this, "enable", data.enable);
        }
    }

    class LinksTriangle {
        color;
        enable = false;
        frequency = 1;
        opacity;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "frequency", data.frequency);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    class Links {
        blink = false;
        color = new OptionsColor();
        consent = false;
        distance = 100;
        enable = false;
        frequency = 1;
        id;
        opacity = 1;
        shadow = new LinksShadow();
        triangles = new LinksTriangle();
        warp = false;
        width = 1;
        constructor() {
            this.color.value = "#fff";
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "id", data.id);
            loadProperty(this, "blink", data.blink);
            this.color = OptionsColor.create(this.color, data.color);
            loadProperty(this, "consent", data.consent);
            loadProperty(this, "distance", data.distance);
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "frequency", data.frequency);
            loadProperty(this, "opacity", data.opacity);
            this.shadow.load(data.shadow);
            this.triangles.load(data.triangles);
            loadProperty(this, "width", data.width);
            loadProperty(this, "warp", data.warp);
        }
    }

    const opacityOffset = 1, minDistance$1 = 0;
    function getWarpDistance(pos1, pos2, canvasSize) {
        const { dx, dy } = getDistances(pos1, pos2), absDiffs = { x: Math.abs(dx), y: Math.abs(dy) }, warpDistances = {
            x: Math.min(absDiffs.x, canvasSize.width - absDiffs.x),
            y: Math.min(absDiffs.y, canvasSize.height - absDiffs.y),
        };
        return Math.hypot(warpDistances.x, warpDistances.y);
    }
    class Linker extends ParticlesInteractorBase {
        #maxDistance;
        #pluginManager;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
            this.container.particles.linksColor = undefined;
            this.container.particles.linksColors = new Map();
        }
        interact(p1) {
            if (!p1.options.links) {
                return;
            }
            p1.links = [];
            if (p1.linksDistance && p1.linksDistance > this.#maxDistance) {
                this.#maxDistance = p1.linksDistance;
            }
            const pos1 = p1.getPosition(), container = this.container, canvasSize = container.canvas.size;
            if (pos1.x < originPoint.x || pos1.y < originPoint.y || pos1.x > canvasSize.width || pos1.y > canvasSize.height) {
                return;
            }
            const linkOpt1 = p1.options.links, optOpacity = linkOpt1.opacity, optDistance = p1.retina.linksDistance ?? minDistance$1, warp = linkOpt1.warp, range = warp ? new CircleWarp(pos1.x, pos1.y, optDistance, canvasSize) : new Circle(pos1.x, pos1.y, optDistance), query = container.particles.grid.query(range);
            for (const p2 of query) {
                const linkOpt2 = p2.options.links;
                if (p1 === p2 ||
                    !linkOpt2?.enable ||
                    linkOpt1.id !== linkOpt2.id ||
                    p2.spawning ||
                    p2.destroyed ||
                    !p2.links ||
                    p1.links.some(t => t.destination === p2) ||
                    p2.links.some(t => t.destination === p1)) {
                    continue;
                }
                const pos2 = p2.getPosition();
                if (pos2.x < originPoint.x || pos2.y < originPoint.y || pos2.x > canvasSize.width || pos2.y > canvasSize.height) {
                    continue;
                }
                const distDirect = getDistances(pos1, pos2).distance, distWarp = warp && linkOpt2.warp ? getWarpDistance(pos1, pos2, canvasSize) : distDirect, distance = Math.min(distDirect, distWarp);
                if (distance > optDistance) {
                    continue;
                }
                const opacityLine = (opacityOffset - distance / optDistance) * optOpacity;
                this.#setColor(p1);
                p1.links.push({
                    destination: p2,
                    opacity: opacityLine,
                    color: this.#getLinkColor(p1, p2),
                    isWarped: distWarp < distDirect,
                });
            }
        }
        isEnabled(particle) {
            return !!particle.options.links?.enable;
        }
        loadParticlesOptions(options, ...sources) {
            loadOptionProperty(options, "links", Links, ...sources);
        }
        reset() {
        }
        #getLinkColor(p1, p2) {
            const container = this.container, linksOptions = p1.options.links;
            if (!linksOptions) {
                return;
            }
            const linkColor = linksOptions.id !== undefined
                ? container.particles.linksColors.get(linksOptions.id)
                : container.particles.linksColor;
            return getLinkColor(p1, p2, linkColor, container.hdr);
        }
        #setColor(p1) {
            if (!p1.options.links) {
                return;
            }
            const container = this.container, linksOptions = p1.options.links;
            let linkColor = linksOptions.id === undefined
                ? container.particles.linksColor
                : container.particles.linksColors.get(linksOptions.id);
            if (linkColor) {
                return;
            }
            linkColor = getLinkRandomColor(this.#pluginManager, linksOptions.color, linksOptions.blink, linksOptions.consent);
            if (linksOptions.id === undefined) {
                container.particles.linksColor = linkColor;
            }
            else {
                container.particles.linksColors.set(linksOptions.id, linkColor);
            }
        }
    }

    class LinksPlugin {
        id = "links";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { LinkInstance } = await Promise.resolve().then(function () { return LinkInstance$1; });
            return new LinkInstance(this.#pluginManager, container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadParticlesLinksInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            const pluginManager = e.pluginManager;
            ensureInteractivityPluginLoaded(e);
            pluginManager.addPlugin(new LinksPlugin(pluginManager));
            pluginManager.addInteractor?.("particlesLinks", container => {
                return Promise.resolve(new Linker(pluginManager, container));
            });
        });
    }

    const polygonCache = new Map(), noOffset = 0;
    function getUnitPolygon(sides) {
        const cached = polygonCache.get(sides);
        if (cached) {
            return cached;
        }
        const step = doublePI / sides, isOdd = !!(sides % double), baseAngle = (-Math.PI + (isOdd ? noOffset : step)) * half$2, verts = [];
        for (let i = 0; i < sides; i++) {
            const angle = baseAngle + i * step;
            verts[i] = {
                x: Math.cos(angle),
                y: Math.sin(angle),
            };
        }
        polygonCache.set(sides, verts);
        return verts;
    }
    function drawPolygon(data, side) {
        const { context, radius } = data, sides = side.count.numerator / side.count.denominator, verts = getUnitPolygon(sides);
        context.beginPath();
        for (let i = 0; i < verts.length; i++) {
            const vert = verts[i];
            if (!vert) {
                continue;
            }
            const x = vert.x * radius, y = vert.y * radius;
            if (i) {
                context.lineTo(x, y);
            }
            else {
                context.moveTo(x, y);
            }
        }
        context.closePath();
    }

    const defaultSides$3 = 5;
    class PolygonDrawerBase {
        draw(data) {
            const { particle, radius } = data, side = this.getSidesData(particle, radius);
            drawPolygon(data, side);
        }
        getSidesCount(particle) {
            const polygon = particle.shapeData;
            return Math.round(getRangeValue(polygon?.sides ?? defaultSides$3));
        }
    }

    const yFactor$1 = 2.66, sidesFactor$1 = 3;
    class PolygonDrawer extends PolygonDrawerBase {
        getSidesData(particle, radius) {
            const { sides } = particle;
            return {
                count: {
                    denominator: 1,
                    numerator: sides,
                },
                length: (radius * yFactor$1) / (sides / sidesFactor$1),
            };
        }
    }

    const sides$1 = 3, yFactor = 2.66, sidesFactor = 3;
    class TriangleDrawer extends PolygonDrawerBase {
        getSidesCount() {
            return sides$1;
        }
        getSidesData(_particle, radius) {
            return {
                count: {
                    denominator: 1,
                    numerator: sides$1,
                },
                length: (radius * yFactor) / (sides$1 / sidesFactor),
            };
        }
    }

    async function loadGenericPolygonShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["polygon"], () => Promise.resolve(new PolygonDrawer()));
        });
    }
    async function loadTriangleShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["triangle"], () => Promise.resolve(new TriangleDrawer()));
        });
    }
    async function loadPolygonShape(engine) {
        engine.checkVersion("4.4.0");
        await Promise.all([
            loadGenericPolygonShape(engine),
            loadTriangleShape(engine),
        ]);
    }

    class RotateAnimation {
        decay = 0;
        enable = false;
        speed = 0;
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "decay", data.decay);
            loadProperty(this, "sync", data.sync);
        }
    }

    class Rotate extends ValueWithRandom {
        animation = new RotateAnimation();
        direction = exports.RotateDirection.clockwise;
        path = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "direction", data.direction);
            this.animation.load(data.animation);
            loadProperty(this, "path", data.path);
        }
    }

    const doublePIDeg = 360;
    class RotateUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const rotateOptions = particle.options.rotate;
            if (!rotateOptions) {
                return;
            }
            particle.rotate = {
                enable: rotateOptions.animation.enable,
                value: degToRad(getRangeValue(rotateOptions.value)),
                min: 0,
                max: doublePI,
            };
            particle.pathRotation = rotateOptions.path;
            let rotateDirection = rotateOptions.direction;
            if (rotateDirection === exports.RotateDirection.random) {
                const index = Math.floor(getRandom() * double), minIndex = 0;
                rotateDirection = index > minIndex ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
            }
            switch (rotateDirection) {
                case exports.RotateDirection.counterClockwise:
                case "counterClockwise":
                    particle.rotate.status = exports.AnimationStatus.decreasing;
                    break;
                case exports.RotateDirection.clockwise:
                    particle.rotate.status = exports.AnimationStatus.increasing;
                    break;
            }
            const rotateAnimation = rotateOptions.animation;
            if (rotateAnimation.enable) {
                particle.rotate.decay = identity$3 - getRangeValue(rotateAnimation.decay);
                particle.rotate.velocity =
                    (getRangeValue(rotateAnimation.speed) / doublePIDeg) * this.#container.retina.reduceFactor;
                if (!rotateAnimation.sync) {
                    particle.rotate.velocity *= getRandom();
                }
            }
            particle.rotation = particle.rotate.value;
        }
        isEnabled(particle) {
            const rotate = particle.options.rotate;
            if (!rotate) {
                return false;
            }
            return !particle.destroyed && !particle.spawning && (!!rotate.value || rotate.animation.enable || rotate.path);
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "rotate", Rotate, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            particle.isRotating = !!particle.rotate;
            if (!particle.rotate) {
                return;
            }
            updateAnimation(particle, particle.rotate, false, exports.DestroyType.none, delta);
            particle.rotation = particle.rotate.value;
        }
    }

    async function loadRotateUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("rotate", container => {
                return Promise.resolve(new RotateUpdater(container));
            });
        });
    }

    function drawSquare(data) {
        const { context, radius } = data, fixedRadius = radius * Math.SQRT1_2, fixedDiameter = fixedRadius * double;
        context.rect(-fixedRadius, -fixedRadius, fixedDiameter, fixedDiameter);
    }

    const sides = 4;
    class SquareDrawer {
        draw(data) {
            drawSquare(data);
        }
        getSidesCount() {
            return sides;
        }
    }

    async function loadSquareShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
        });
    }

    const defaultInset$1 = 2, origin = { x: 0, y: 0 };
    function drawStar(data) {
        const { context, particle, radius } = data, sides = particle.sides, inset = particle.starInset ?? defaultInset$1;
        context.moveTo(origin.x, origin.y - radius);
        for (let i = 0; i < sides; i++) {
            context.rotate(Math.PI / sides);
            context.lineTo(origin.x, origin.y - radius * inset);
            context.rotate(Math.PI / sides);
            context.lineTo(origin.x, origin.y - radius);
        }
    }

    const defaultInset = 2, defaultSides$2 = 5;
    class StarDrawer {
        draw(data) {
            drawStar(data);
        }
        getSidesCount(particle) {
            const star = particle.shapeData;
            return Math.round(getRangeValue(star?.sides ?? defaultSides$2));
        }
        particleInit(_container, particle) {
            const star = particle.shapeData;
            particle.starInset = getRangeValue(star?.inset ?? defaultInset);
        }
    }

    async function loadStarShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["star"], () => Promise.resolve(new StarDrawer()));
        });
    }

    async function loadSlim(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const loadInteractivityForSlim = async (e) => {
                await loadInteractivityPlugin(e);
                await Promise.all([
                    loadExternalParallaxInteraction(e),
                    loadExternalAttractInteraction(e),
                    loadExternalBounceInteraction(e),
                    loadExternalBubbleInteraction(e),
                    loadExternalConnectInteraction(e),
                    loadExternalDestroyInteraction(e),
                    loadExternalGrabInteraction(e),
                    loadExternalPauseInteraction(e),
                    loadExternalPushInteraction(e),
                    loadExternalRemoveInteraction(e),
                    loadExternalRepulseInteraction(e),
                    loadExternalSlowInteraction(e),
                    loadParticlesAttractInteraction(e),
                    loadParticlesCollisionsInteraction(e),
                    loadParticlesLinksInteraction(e),
                ]);
            };
            await Promise.all([
                loadBasic(e),
                loadInteractivityForSlim(e),
                loadEasingQuadPlugin(e),
                loadEmojiShape(e),
                loadImageShape(e),
                loadLineShape(e),
                loadPolygonShape(e),
                loadSquareShape(e),
                loadStarShape(e),
                loadLifeUpdater(e),
                loadPaintUpdater(e),
                loadRotateUpdater(e),
            ]);
        });
    }

    const validTypes = ["text", "character", "char", "multiline-text"];
    const firstIndex$3 = 0, minLength$2 = 0;
    function drawText(data) {
        const { context, particle, fill, stroke, radius, opacity } = data, character = particle.shapeData;
        if (!character) {
            return;
        }
        const textData = character.value;
        particle.textLines ??= itemFromSingleOrMultiple(textData, particle.randomIndexData)?.split("\n") ?? [];
        particle.maxTextLength ??= particle.textLines.length
            ? Math.max(...particle.textLines.map(t => t.length))
            : (particle.textLines[firstIndex$3]?.length ?? minLength$2);
        if (!particle.textLines.length || !particle.maxTextLength) {
            return;
        }
        const lines = particle.textLines, style = character.style ?? "", weight = character.weight ?? "400", font = character.font ?? "Verdana", size = (Math.round(radius) * double) / (lines.length * particle.maxTextLength);
        context.font = `${style} ${weight} ${size.toString()}px "${font}"`;
        const originalGlobalAlpha = context.globalAlpha;
        context.globalAlpha = opacity;
        for (let i = 0; i < lines.length; i++) {
            const currentLine = lines[i];
            if (!currentLine) {
                continue;
            }
            drawTextLine(context, currentLine, size, i, fill, stroke);
        }
        context.globalAlpha = originalGlobalAlpha;
    }
    function drawTextLine(context, line, size, index, fill, stroke) {
        const pos = {
            x: -(line.length * size * half$2),
            y: size * half$2 + index * size,
        };
        if (fill) {
            context.fillText(line, pos.x, pos.y);
        }
        if (stroke) {
            context.strokeText(line, pos.x, pos.y);
        }
    }

    const firstIndex$2 = 0, minLength$1 = 0;
    class TextDrawer {
        draw(data) {
            drawText(data);
        }
        async init(container) {
            const options = container.actualOptions;
            if (validTypes.find(t => isInArray(t, options.particles.shape.type))) {
                const shapeOptions = validTypes
                    .map(t => options.particles.shape.options[t])
                    .find(t => !!t), promises = [];
                executeOnSingleOrMultiple(shapeOptions, shape => {
                    promises.push(loadFont(shape.font, shape.weight));
                });
                await Promise.all(promises);
            }
        }
        particleInit(_container, particle) {
            if (!particle.shape || !validTypes.includes(particle.shape)) {
                return;
            }
            const character = particle.shapeData;
            if (character === undefined) {
                return;
            }
            const textData = character.value;
            if (!textData) {
                return;
            }
            particle.textLines = itemFromSingleOrMultiple(textData, particle.randomIndexData)?.split("\n") ?? [];
            particle.maxTextLength = particle.textLines.length
                ? Math.max(...particle.textLines.map(t => t.length))
                : (particle.textLines[firstIndex$2]?.length ?? minLength$1);
        }
    }

    async function loadTextShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(validTypes, () => Promise.resolve(new TextDrawer()));
        });
    }

    var TiltDirection;
    (function (TiltDirection) {
        TiltDirection["clockwise"] = "clockwise";
        TiltDirection["counterClockwise"] = "counter-clockwise";
        TiltDirection["random"] = "random";
    })(TiltDirection || (TiltDirection = {}));

    class TiltAnimation {
        decay = 0;
        enable = false;
        speed = 0;
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "decay", data.decay);
            loadProperty(this, "sync", data.sync);
        }
    }

    class Tilt extends ValueWithRandom {
        animation = new TiltAnimation();
        direction = TiltDirection.clockwise;
        enable = false;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            this.animation.load(data.animation);
            loadProperty(this, "direction", data.direction);
            loadProperty(this, "enable", data.enable);
        }
    }

    const maxAngle$2 = 360;
    class TiltUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        getTransformValues(particle) {
            const tilt = particle.tilt?.enable && particle.tilt;
            return {
                b: tilt ? Math.cos(tilt.value) * tilt.cosDirection : undefined,
                c: tilt ? Math.sin(tilt.value) * tilt.sinDirection : undefined,
            };
        }
        init(particle) {
            const tiltOptions = particle.options.tilt;
            if (!tiltOptions) {
                return;
            }
            particle.tilt = {
                enable: tiltOptions.enable,
                value: degToRad(getRangeValue(tiltOptions.value)),
                sinDirection: getRandom() >= half$2 ? identity$3 : -identity$3,
                cosDirection: getRandom() >= half$2 ? identity$3 : -identity$3,
                min: 0,
                max: doublePI,
            };
            let tiltDirection = tiltOptions.direction;
            if (tiltDirection === TiltDirection.random) {
                const index = Math.floor(getRandom() * double), minIndex = 0;
                tiltDirection = index > minIndex ? TiltDirection.counterClockwise : TiltDirection.clockwise;
            }
            switch (tiltDirection) {
                case TiltDirection.counterClockwise:
                case "counterClockwise":
                    particle.tilt.status = exports.AnimationStatus.decreasing;
                    break;
                case TiltDirection.clockwise:
                    particle.tilt.status = exports.AnimationStatus.increasing;
                    break;
            }
            const tiltAnimation = particle.options.tilt?.animation;
            if (tiltAnimation?.enable) {
                particle.tilt.decay = identity$3 - getRangeValue(tiltAnimation.decay);
                particle.tilt.velocity = (getRangeValue(tiltAnimation.speed) / maxAngle$2) * this.#container.retina.reduceFactor;
                if (!tiltAnimation.sync) {
                    particle.tilt.velocity *= getRandom();
                }
            }
        }
        isEnabled(particle) {
            const tiltAnimation = particle.options.tilt?.animation;
            return !particle.destroyed && !particle.spawning && !!tiltAnimation?.enable;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "tilt", Tilt, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.tilt) {
                return;
            }
            updateAnimation(particle, particle.tilt, false, exports.DestroyType.none, delta);
        }
    }

    async function loadTiltUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("tilt", container => {
                return Promise.resolve(new TiltUpdater(container));
            });
        });
    }

    class TwinkleLinksValues {
        color;
        enable = false;
        frequency = 0.05;
        opacity = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "frequency", data.frequency);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class TwinkleParticlesValues {
        enable = false;
        fillColor;
        frequency = 0.05;
        opacity = 1;
        strokeColor;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.fillColor !== undefined) {
                this.fillColor = OptionsColor.create(this.fillColor, data.fillColor);
            }
            if (data.strokeColor !== undefined) {
                this.strokeColor = OptionsColor.create(this.strokeColor, data.strokeColor);
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "frequency", data.frequency);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class Twinkle {
        links = new TwinkleLinksValues();
        particles = new TwinkleParticlesValues();
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.links.load(data.links);
            this.particles.load(data.particles);
        }
    }

    class TwinkleUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        getColorStyles(particle, _context, _radius, opacity) {
            const pOptions = particle.options, container = this.#container, twinkleOptions = pOptions["twinkle"];
            if (!twinkleOptions) {
                return {};
            }
            const twinkle = twinkleOptions.particles, twinkling = twinkle.enable && getRandom() < twinkle.frequency, zIndexOptions = particle.options.zIndex, zOffset = 1, zOpacityFactor = (zOffset - particle.zIndexFactor) ** zIndexOptions.opacityRate, twinklingOpacity = twinkling ? getRangeValue(twinkle.opacity) * zOpacityFactor : opacity, twinkleFillRgb = rangeColorToHsl(this.#pluginManager, twinkle.fillColor), twinkleStrokeRgb = rangeColorToHsl(this.#pluginManager, twinkle.strokeColor), getTwinkleFillStyle = () => {
                if (!twinkleFillRgb) {
                    return undefined;
                }
                return getStyleFromHsl(twinkleFillRgb, container.hdr, twinklingOpacity, container.peakNits, container.hdrMode);
            }, getTwinkleStrokeStyle = () => {
                if (!twinkleStrokeRgb) {
                    return undefined;
                }
                return getStyleFromHsl(twinkleStrokeRgb, container.hdr, twinklingOpacity, container.peakNits, container.hdrMode);
            }, twinkleFillStyle = getTwinkleFillStyle(), twinkleStrokeStyle = getTwinkleStrokeStyle(), res = {}, needsTwinkle = twinkling && (!!twinkleFillStyle || !!twinkleStrokeStyle);
            res.fill = needsTwinkle ? twinkleFillStyle : undefined;
            res.stroke = needsTwinkle ? twinkleStrokeStyle : undefined;
            return res;
        }
        init() {
        }
        isEnabled(particle) {
            const pOptions = particle.options, twinkleOptions = pOptions.twinkle;
            if (!twinkleOptions) {
                return false;
            }
            return twinkleOptions.particles.enable;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "twinkle", Twinkle, ...sources);
        }
        update() {
        }
    }

    async function loadTwinkleUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("twinkle", container => {
                return Promise.resolve(new TwinkleUpdater(e.pluginManager, container));
            });
        });
    }

    class WobbleSpeed {
        angle = 50;
        move = 10;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "angle", data.angle);
            loadRangeProperty(this, "move", data.move);
        }
    }

    class Wobble {
        distance = 5;
        enable = false;
        speed = new WobbleSpeed();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "distance", data.distance);
            loadProperty(this, "enable", data.enable);
            if (data.speed !== undefined) {
                if (isNumber(data.speed)) {
                    this.speed.load({ angle: data.speed });
                }
                else {
                    const rangeSpeed = data.speed;
                    if ("min" in rangeSpeed) {
                        this.speed.load({ angle: rangeSpeed });
                    }
                    else {
                        this.speed.load(data.speed);
                    }
                }
            }
        }
    }

    const defaultDistance$1 = 0, distanceFactor = 60;
    function updateWobble(container, particle, delta) {
        const { wobble: wobbleOptions } = particle.options, { wobble } = particle;
        if (!wobbleOptions?.enable || !wobble) {
            return;
        }
        const reduceFactor = container.retina.reduceFactor, angleSpeed = wobble.angleSpeed * delta.factor * reduceFactor, moveSpeed = wobble.moveSpeed * delta.factor * reduceFactor, distance = (moveSpeed * (particle.retina.wobbleDistance ?? defaultDistance$1)) / (millisecondsToSeconds$1 / distanceFactor), max = doublePI, { position } = particle;
        wobble.angle += angleSpeed;
        if (wobble.angle > max) {
            wobble.angle -= max;
        }
        position.x += distance * Math.cos(wobble.angle);
        position.y += distance * Math.abs(Math.sin(wobble.angle));
    }

    const maxAngle$1 = 360, moveSpeedFactor$1 = 10, defaultDistance = 0;
    class WobbleUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const wobbleOpt = particle.options.wobble;
            if (wobbleOpt?.enable) {
                particle.wobble = {
                    angle: getRandom() * doublePI,
                    angleSpeed: getRangeValue(wobbleOpt.speed.angle) / maxAngle$1,
                    moveSpeed: getRangeValue(wobbleOpt.speed.move) / moveSpeedFactor$1,
                };
            }
            else {
                particle.wobble = {
                    angle: 0,
                    angleSpeed: 0,
                    moveSpeed: 0,
                };
            }
            particle.retina.wobbleDistance =
                getRangeValue(wobbleOpt?.distance ?? defaultDistance) * this.#container.retina.pixelRatio;
        }
        isEnabled(particle) {
            return !particle.destroyed && !particle.spawning && !!particle.options.wobble?.enable;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "wobble", Wobble, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            updateWobble(this.#container, particle, delta);
        }
    }

    async function loadWobbleUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("wobble", container => {
                return Promise.resolve(new WobbleUpdater(container));
            });
        });
    }

    async function loadFull(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const loadEmittersPluginBundle = async (e) => {
                await loadEmittersPlugin(e);
                await Promise.all([
                    loadEmittersShapeCircle(e),
                    loadEmittersShapeSquare(e),
                ]);
            }, loadInteractivityForFull = async (e) => {
                await loadSlim(e);
                await Promise.all([
                    loadExternalDragInteraction(e),
                    loadExternalTrailInteraction(e),
                    loadAbsorbersPlugin(e),
                    loadEmittersPluginBundle(e),
                ]);
            };
            await Promise.all([
                loadInteractivityForFull(e),
                loadDestroyUpdater(e),
                loadRollUpdater(e),
                loadTiltUpdater(e),
                loadTwinkleUpdater(e),
                loadWobbleUpdater(e),
                loadTextShape(e),
            ]);
        });
    }

    const InterlaceOffsets = [0, 4, 2, 1];
    const InterlaceSteps = [8, 8, 4, 2];

    class ByteStream {
        data;
        pos;
        constructor(bytes) {
            this.pos = 0;
            this.data = new Uint8ClampedArray(bytes);
        }
        getString(count) {
            const slice = this.data.slice(this.pos, this.pos + count);
            this.pos += slice.length;
            return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), "");
        }
        nextByte() {
            return this.data[this.pos++];
        }
        nextTwoBytes() {
            const increment = 2, previous = 1, shift = 8;
            this.pos += increment;
            return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
        }
        readSubBlocks() {
            let blockString = "", size;
            const minCount = 0, emptySize = 0;
            do {
                size = this.data[this.pos++];
                for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
                }
            } while (size !== emptySize);
            return blockString;
        }
        readSubBlocksBin() {
            let size = this.data[this.pos], len = 0;
            const emptySize = 0, increment = 1;
            for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
                len += size;
            }
            const blockData = new Uint8Array(len);
            size = this.data[this.pos++];
            for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
                for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
                }
            }
            return blockData;
        }
        skipSubBlocks() {
            for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
            }
            this.pos++;
        }
    }

    var DisposalMethod;
    (function (DisposalMethod) {
        DisposalMethod[DisposalMethod["Replace"] = 0] = "Replace";
        DisposalMethod[DisposalMethod["Combine"] = 1] = "Combine";
        DisposalMethod[DisposalMethod["RestoreBackground"] = 2] = "RestoreBackground";
        DisposalMethod[DisposalMethod["RestorePrevious"] = 3] = "RestorePrevious";
        DisposalMethod[DisposalMethod["UndefinedA"] = 4] = "UndefinedA";
        DisposalMethod[DisposalMethod["UndefinedB"] = 5] = "UndefinedB";
        DisposalMethod[DisposalMethod["UndefinedC"] = 6] = "UndefinedC";
        DisposalMethod[DisposalMethod["UndefinedD"] = 7] = "UndefinedD";
    })(DisposalMethod || (DisposalMethod = {}));

    var GIFDataHeaders;
    (function (GIFDataHeaders) {
        GIFDataHeaders[GIFDataHeaders["Extension"] = 33] = "Extension";
        GIFDataHeaders[GIFDataHeaders["ApplicationExtension"] = 255] = "ApplicationExtension";
        GIFDataHeaders[GIFDataHeaders["GraphicsControlExtension"] = 249] = "GraphicsControlExtension";
        GIFDataHeaders[GIFDataHeaders["PlainTextExtension"] = 1] = "PlainTextExtension";
        GIFDataHeaders[GIFDataHeaders["CommentExtension"] = 254] = "CommentExtension";
        GIFDataHeaders[GIFDataHeaders["Image"] = 44] = "Image";
        GIFDataHeaders[GIFDataHeaders["EndOfFile"] = 59] = "EndOfFile";
    })(GIFDataHeaders || (GIFDataHeaders = {}));

    const defaultFrame = 0, initialTime = 0, firstIndex$1 = 0, defaultLoopCount = 0;
    function parseColorTable(byteStream, count) {
        const colors = [];
        for (let i = 0; i < count; i++) {
            colors.push({
                r: byteStream.data[byteStream.pos],
                g: byteStream.data[byteStream.pos + 1],
                b: byteStream.data[byteStream.pos + 2],
            });
            byteStream.pos += 3;
        }
        return colors;
    }
    function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
        switch (byteStream.nextByte()) {
            case GIFDataHeaders.GraphicsControlExtension: {
                const frame = gif.frames[getFrameIndex(false)];
                byteStream.pos++;
                const packedByte = byteStream.nextByte();
                frame.GCreserved = (packedByte & 0xe0) >>> 5;
                frame.disposalMethod = (packedByte & 0x1c) >>> 2;
                frame.userInputDelayFlag = (packedByte & 2) === 2;
                const transparencyFlag = (packedByte & 1) === 1;
                frame.delayTime = byteStream.nextTwoBytes() * 0xa;
                const transparencyIndex = byteStream.nextByte();
                if (transparencyFlag) {
                    getTransparencyIndex(transparencyIndex);
                }
                byteStream.pos++;
                break;
            }
            case GIFDataHeaders.ApplicationExtension: {
                byteStream.pos++;
                const applicationExtension = {
                    identifier: byteStream.getString(8),
                    authenticationCode: byteStream.getString(3),
                    data: byteStream.readSubBlocksBin(),
                };
                gif.applicationExtensions.push(applicationExtension);
                break;
            }
            case GIFDataHeaders.CommentExtension: {
                gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
                break;
            }
            case GIFDataHeaders.PlainTextExtension: {
                if (gif.globalColorTable.length === 0) {
                    throw new EvalError("plain text extension without global color table");
                }
                byteStream.pos++;
                gif.frames[getFrameIndex(false)].plainTextData = {
                    left: byteStream.nextTwoBytes(),
                    top: byteStream.nextTwoBytes(),
                    width: byteStream.nextTwoBytes(),
                    height: byteStream.nextTwoBytes(),
                    charSize: {
                        width: byteStream.nextTwoBytes(),
                        height: byteStream.nextTwoBytes(),
                    },
                    foregroundColor: byteStream.nextByte(),
                    backgroundColor: byteStream.nextByte(),
                    text: byteStream.readSubBlocks(),
                };
                break;
            }
            default:
                byteStream.skipSubBlocks();
                break;
        }
    }
    function readBits(imageData, pos, len) {
        const bytePos = pos >>> 3, bitPos = pos & 7;
        return (((imageData[bytePos] + (imageData[bytePos + 1] << 8) + (imageData[bytePos + 2] << 16)) &
            (((1 << len) - 1) << bitPos)) >>>
            bitPos);
    }
    async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
        const frame = gif.frames[getFrameIndex(true)];
        frame.left = byteStream.nextTwoBytes();
        frame.top = byteStream.nextTwoBytes();
        frame.width = byteStream.nextTwoBytes();
        frame.height = byteStream.nextTwoBytes();
        const packedByte = byteStream.nextByte(), localColorTableFlag = (packedByte & 0x80) === 0x80, interlacedFlag = (packedByte & 0x40) === 0x40;
        frame.sortFlag = (packedByte & 0x20) === 0x20;
        frame.reserved = (packedByte & 0x18) >>> 3;
        const localColorCount = 1 << ((packedByte & 7) + 1);
        if (localColorTableFlag) {
            frame.localColorTable = parseColorTable(byteStream, localColorCount);
        }
        const getColor = (index) => {
            const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
            if (index !== getTransparencyIndex(null)) {
                return { r, g, b, a: 255 };
            }
            return { r, g, b, a: avgAlpha ? Math.trunc((r + g + b) / 3) : 0 };
        }, image = (() => {
            try {
                return new ImageData(frame.width, frame.height, canvasSettings);
            }
            catch (error) {
                if (error instanceof DOMException && error.name === "IndexSizeError") {
                    return null;
                }
                throw error;
            }
        })();
        if (image == null) {
            throw new EvalError("GIF frame size is to large");
        }
        const minCodeSize = byteStream.nextByte(), imageData = byteStream.readSubBlocksBin(), clearCode = 1 << minCodeSize;
        if (interlacedFlag) {
            for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
                if (InterlaceOffsets[pass] < frame.height) {
                    let pixelPos = 0, lineIndex = 0, exit = false;
                    while (!exit) {
                        const last = code;
                        code = readBits(imageData, pos, size);
                        pos += size + 1;
                        if (code === clearCode) {
                            size = minCodeSize + 1;
                            dic.length = clearCode + 2;
                            for (let i = 0; i < dic.length; i++) {
                                dic[i] = i < clearCode ? [i] : [];
                            }
                        }
                        else {
                            if (code >= dic.length) {
                                dic.push(dic[last].concat(dic[last][0]));
                            }
                            else if (last !== clearCode) {
                                dic.push(dic[last].concat(dic[code][0]));
                            }
                            for (const item of dic[code]) {
                                const { r, g, b, a } = getColor(item);
                                image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
                                    InterlaceSteps[pass] * lineIndex +
                                    (pixelPos % (frame.width * 4)));
                                pixelPos += 4;
                            }
                            if (dic.length === 1 << size && size < 0xc) {
                                size++;
                            }
                        }
                        if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
                            lineIndex++;
                            if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
                                exit = true;
                            }
                        }
                    }
                }
            }
            frame.image = image;
            frame.bitmap = await createImageBitmap(image);
        }
        else {
            let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4;
            const dic = [[0]];
            for (;;) {
                const last = code;
                code = readBits(imageData, pos, size);
                pos += size;
                if (code === clearCode) {
                    size = minCodeSize + 1;
                    dic.length = clearCode + 2;
                    for (let i = 0; i < dic.length; i++) {
                        dic[i] = i < clearCode ? [i] : [];
                    }
                }
                else {
                    if (code === clearCode + 1) {
                        break;
                    }
                    if (code >= dic.length) {
                        dic.push(dic[last].concat(dic[last][0]));
                    }
                    else if (last !== clearCode) {
                        dic.push(dic[last].concat(dic[code][0]));
                    }
                    for (const item of dic[code]) {
                        const { r, g, b, a } = getColor(item);
                        pixelPos += 4;
                        image.data.set([r, g, b, a], pixelPos);
                    }
                    if (dic.length >= 1 << size && size < 0xc) {
                        size++;
                    }
                }
            }
            frame.image = image;
            frame.bitmap = await createImageBitmap(image);
        }
    }
    async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
        switch (byteStream.nextByte()) {
            case GIFDataHeaders.EndOfFile:
                return true;
            case GIFDataHeaders.Image:
                await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings);
                break;
            case GIFDataHeaders.Extension:
                parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
                break;
            default:
                throw new EvalError("undefined block found");
        }
        return false;
    }
    function getGIFLoopAmount(gif) {
        for (const extension of gif.applicationExtensions) {
            if (extension.identifier + extension.authenticationCode !== "NETSCAPE2.0") {
                continue;
            }
            return extension.data[1] + (extension.data[2] << 8);
        }
        return Number.NaN;
    }
    async function decodeGIF(gifURL, canvasSettings, progressCallback, avgAlpha) {
        avgAlpha ??= false;
        const res = await fetch(gifURL);
        if (!res.ok && res.status === 404) {
            throw new EvalError("file not found");
        }
        const buffer = await res.arrayBuffer(), gif = {
            width: 0,
            height: 0,
            totalTime: 0,
            colorRes: 0,
            pixelAspectRatio: 0,
            frames: [],
            sortFlag: false,
            globalColorTable: [],
            backgroundImage: new ImageData(1, 1, canvasSettings),
            comments: [],
            applicationExtensions: [],
        }, byteStream = new ByteStream(new Uint8ClampedArray(buffer));
        if (byteStream.getString(6) !== "GIF89a") {
            throw new Error("not a supported GIF file");
        }
        gif.width = byteStream.nextTwoBytes();
        gif.height = byteStream.nextTwoBytes();
        const packedByte = byteStream.nextByte(), globalColorTableFlag = (packedByte & 0x80) === 0x80;
        gif.colorRes = (packedByte & 0x70) >>> 4;
        gif.sortFlag = (packedByte & 8) === 8;
        const globalColorCount = 1 << ((packedByte & 7) + 1), backgroundColorIndex = byteStream.nextByte();
        gif.pixelAspectRatio = byteStream.nextByte();
        if (gif.pixelAspectRatio !== 0) {
            gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;
        }
        if (globalColorTableFlag) {
            gif.globalColorTable = parseColorTable(byteStream, globalColorCount);
        }
        const backgroundImage = (() => {
            try {
                return new ImageData(gif.width, gif.height, canvasSettings);
            }
            catch (error) {
                if (error instanceof DOMException && error.name === "IndexSizeError") {
                    return null;
                }
                throw error;
            }
        })();
        if (backgroundImage == null) {
            throw new Error("GIF frame size is to large");
        }
        const { r, g, b } = gif.globalColorTable[backgroundColorIndex];
        backgroundImage.data.set(globalColorTableFlag ? [r, g, b, 255] : [0, 0, 0, 0]);
        for (let i = 4; i < backgroundImage.data.length; i *= 2) {
            backgroundImage.data.copyWithin(i, 0, i);
        }
        gif.backgroundImage = backgroundImage;
        let frameIndex = -1, incrementFrameIndex = true, transparencyIndex = -1;
        const getframeIndex = (increment) => {
            if (increment) {
                incrementFrameIndex = true;
            }
            return frameIndex;
        }, getTransparencyIndex = (newValue) => {
            if (newValue != null) {
                transparencyIndex = newValue;
            }
            return transparencyIndex;
        };
        try {
            do {
                if (incrementFrameIndex) {
                    gif.frames.push({
                        left: 0,
                        top: 0,
                        width: 0,
                        height: 0,
                        disposalMethod: DisposalMethod.Replace,
                        image: new ImageData(1, 1, canvasSettings),
                        plainTextData: null,
                        userInputDelayFlag: false,
                        delayTime: 0,
                        sortFlag: false,
                        localColorTable: [],
                        reserved: 0,
                        GCreserved: 0,
                    });
                    frameIndex++;
                    transparencyIndex = -1;
                    incrementFrameIndex = false;
                }
            } while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, canvasSettings, progressCallback)));
            gif.frames.length--;
            for (const frame of gif.frames) {
                if (frame.userInputDelayFlag && frame.delayTime === 0) {
                    gif.totalTime = Infinity;
                    break;
                }
                gif.totalTime += frame.delayTime;
            }
            return gif;
        }
        catch (error) {
            if (error instanceof EvalError) {
                throw new Error(`error while parsing frame ${frameIndex.toString()} "${error.message}"`, { cause: error });
            }
            throw error;
        }
    }
    function drawGif(data, canvasSettings) {
        const { context, radius, particle, delta } = data, gifData = particle.gifData;
        if (!gifData) {
            return;
        }
        const offscreenCanvas = new OffscreenCanvas(gifData.width, gifData.height), offscreenContext = offscreenCanvas.getContext("2d", canvasSettings);
        if (!offscreenContext) {
            throw new Error("could not create offscreen canvas context");
        }
        offscreenContext.imageSmoothingQuality = "low";
        offscreenContext.imageSmoothingEnabled = false;
        offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
        let frameIndex = particle.gifFrame ?? defaultFrame;
        const pos = { x: -gifData.width * half$2, y: -gifData.height * half$2 }, frame = gifData.frames[frameIndex];
        particle.gifTime ??= initialTime;
        if (!frame.bitmap) {
            return;
        }
        context.scale(radius / gifData.width, radius / gifData.height);
        switch (frame.disposalMethod) {
            case DisposalMethod.UndefinedA:
            case DisposalMethod.UndefinedB:
            case DisposalMethod.UndefinedC:
            case DisposalMethod.UndefinedD:
            case DisposalMethod.Replace:
                offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
                context.drawImage(offscreenCanvas, pos.x, pos.y);
                offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
                break;
            case DisposalMethod.Combine:
                offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
                context.drawImage(offscreenCanvas, pos.x, pos.y);
                break;
            case DisposalMethod.RestoreBackground:
                offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
                context.drawImage(offscreenCanvas, pos.x, pos.y);
                offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
                if (!gifData.globalColorTable.length) {
                    offscreenContext.putImageData(gifData.frames[firstIndex$1].image, pos.x + frame.left, pos.y + frame.top);
                }
                else {
                    offscreenContext.putImageData(gifData.backgroundImage, pos.x, pos.y);
                }
                break;
            case DisposalMethod.RestorePrevious:
                {
                    const previousImageData = offscreenContext.getImageData(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
                    offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
                    context.drawImage(offscreenCanvas, pos.x, pos.y);
                    offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
                    offscreenContext.putImageData(previousImageData, originPoint.x, originPoint.y);
                }
                break;
        }
        particle.gifTime += delta.value;
        if (particle.gifTime > frame.delayTime) {
            particle.gifTime -= frame.delayTime;
            if (++frameIndex >= gifData.frames.length) {
                if (particle.gifLoopCount == null || --particle.gifLoopCount <= defaultLoopCount) {
                    return;
                }
                frameIndex = firstIndex$1;
                offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
            }
            particle.gifFrame = frameIndex;
        }
        context.scale(gifData.width / radius, gifData.height / radius);
    }

    class GifDrawer {
        #container;
        #gifCache;
        constructor(container) {
            this.#container = container;
            this.#gifCache = new Map();
        }
        destroy() {
            this.#gifCache.clear();
        }
        draw(data) {
            const { context, opacity } = data;
            if (!data.particle.gifData)
                return;
            context.globalAlpha = opacity;
            drawGif(data, this.#container.canvas.render.settings);
            context.globalAlpha = 1;
        }
        loadShape(particle) {
            const shapeData = particle.shapeData;
            if (!shapeData?.src)
                return;
            if (this.#gifCache.has(shapeData.src))
                return;
            void decodeGIF(shapeData.src, { colorSpace: "srgb" }).then(gifData => {
                this.#gifCache.set(shapeData.src, gifData);
            });
        }
        particleInit(container, particle) {
            const shapeData = particle.shapeData;
            if (!shapeData?.src)
                return;
            const gifData = this.#gifCache.get(shapeData.src);
            if (!gifData) {
                setTimeout(() => {
                    this.particleInit(container, particle);
                });
                return;
            }
            particle.gifData = gifData;
            particle.gifFrame = 0;
            particle.gifTime = 0;
            particle.gifLoopCount = getGIFLoopAmount(gifData);
            if (particle.gifLoopCount === 0) {
                particle.gifLoopCount = Number.POSITIVE_INFINITY;
            }
            if (shapeData.loopCount !== undefined) {
                particle.gifLoopCount = shapeData.loopCount;
            }
        }
    }

    async function loadGifShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["gif", "gifs"], container => Promise.resolve(new GifDrawer(container)));
        });
    }

    class GradientColorOpacityAnimation {
        count = 0;
        decay = 0;
        delay = 0;
        enable = false;
        speed = 0;
        startValue = exports.StartValueType.random;
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "count", data.count);
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadProperty(this, "sync", data.sync);
            loadProperty(this, "startValue", data.startValue);
            loadRangeProperty(this, "decay", data.decay);
            loadRangeProperty(this, "delay", data.delay);
        }
    }

    class GradientColorOpacity {
        animation = new GradientColorOpacityAnimation();
        value = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.animation.load(data.animation);
            loadRangeProperty(this, "value", data.value);
        }
    }

    class AnimatableGradientColor {
        opacity;
        stop = 0;
        value = new AnimatableColor();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "stop", data.stop);
            this.value = AnimatableColor.create(this.value, data.value);
            if (data.opacity !== undefined) {
                this.opacity = new GradientColorOpacity();
                if (isNumber(data.opacity)) {
                    this.opacity.value = data.opacity;
                }
                else {
                    this.opacity.load(data.opacity);
                }
            }
        }
    }

    class GradientAngleAnimation {
        count = 0;
        decay = 0;
        delay = 0;
        enable = false;
        speed = 0;
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "count", data.count);
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "decay", data.decay);
            loadRangeProperty(this, "delay", data.delay);
            loadProperty(this, "sync", data.sync);
        }
    }

    class GradientAngle {
        animation = new GradientAngleAnimation();
        direction = exports.RotateDirection.clockwise;
        value = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.animation.load(data.animation);
            loadRangeProperty(this, "value", data.value);
            loadProperty(this, "direction", data.direction);
        }
    }

    class AnimatableGradient {
        angle = new GradientAngle();
        colors = [];
        type = exports.GradientType.random;
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.angle.load(data.angle);
            if (data.colors !== undefined) {
                this.colors = data.colors.map(s => {
                    const tmp = new AnimatableGradientColor();
                    tmp.load(s);
                    return tmp;
                });
            }
            loadProperty(this, "type", data.type);
        }
    }

    function updateGradient(particle, delta, hdr) {
        const { gradient } = particle;
        if (!gradient) {
            return;
        }
        updateAnimation(particle, gradient.angle, false, exports.DestroyType.none, delta);
        for (const color of gradient.colors) {
            updateColor(color.value, delta);
            if (color.opacity) {
                updateAnimation(particle, color.opacity, true, exports.DestroyType.none, delta);
            }
        }
    }

    class GradientUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        getColorStyles(particle, context, radius, opacity) {
            const gradient = particle.gradient;
            if (!gradient) {
                return {};
            }
            const container = this.#container, gradientAngle = gradient.angle.value, origin = { x: 0, y: 0 }, minRadius = 0, fillGradient = gradient.type === exports.GradientType.radial
                ? context.createRadialGradient(origin.x, origin.y, minRadius, origin.x, origin.y, radius)
                : context.createLinearGradient(Math.cos(gradientAngle) * -radius, Math.sin(gradientAngle) * -radius, Math.cos(gradientAngle) * radius, Math.sin(gradientAngle) * radius);
            for (const { stop, value, opacity: cOpacity } of gradient.colors) {
                const hsl = {
                    h: value.h.value,
                    s: value.s.value,
                    l: value.l.value,
                };
                fillGradient.addColorStop(stop, getStyleFromHsl(hsl, container.hdr, cOpacity?.value ?? opacity, container.peakNits, container.hdrMode));
            }
            return { fill: fillGradient };
        }
        init(particle) {
            const gradient = itemFromSingleOrMultiple(particle.options.gradient);
            if (!gradient) {
                return;
            }
            const container = this.#container, { angle } = gradient, speedFactor = 360, delayOffset = 1;
            particle.gradient = {
                angle: {
                    value: getRangeValue(angle.value),
                    enable: angle.animation.enable,
                    velocity: (getRangeValue(angle.animation.speed) / speedFactor) * container.retina.reduceFactor,
                    decay: delayOffset - getRangeValue(angle.animation.decay),
                    delayTime: getRangeValue(angle.animation.delay) * millisecondsToSeconds$1,
                    max: doublePI,
                    min: 0,
                    time: 0,
                },
                type: gradient.type,
                colors: [],
            };
            let rotateDirection = gradient.angle.direction;
            if (rotateDirection === exports.RotateDirection.random) {
                rotateDirection = getRandom() > half$2 ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
            }
            switch (rotateDirection) {
                case exports.RotateDirection.counterClockwise:
                case "counterClockwise":
                    particle.gradient.angle.status = exports.AnimationStatus.decreasing;
                    break;
                case exports.RotateDirection.clockwise:
                    particle.gradient.angle.status = exports.AnimationStatus.increasing;
                    break;
            }
            const reduceDuplicates = particle.options.reduceDuplicates;
            for (const grColor of gradient.colors) {
                const grHslColor = rangeColorToHsl(this.#pluginManager, grColor.value, particle.id, reduceDuplicates);
                if (!grHslColor) {
                    continue;
                }
                const grHslAnimation = getHslAnimationFromHsl(grHslColor, grColor.value.animation, container.retina.reduceFactor), addColor = {
                    stop: grColor.stop,
                    value: grHslAnimation,
                    opacity: grColor.opacity
                        ? {
                            enable: grColor.opacity.animation.enable,
                            max: getRangeMax(grColor.opacity.value),
                            min: getRangeMin(grColor.opacity.value),
                            status: exports.AnimationStatus.increasing,
                            value: getRangeValue(grColor.opacity.value),
                            velocity: (getRangeValue(grColor.opacity.animation.speed) / percentDenominator) * container.retina.reduceFactor,
                            decay: delayOffset - getRangeValue(grColor.opacity.animation.decay),
                            delayTime: getRangeValue(grColor.opacity.animation.delay) * millisecondsToSeconds$1,
                            time: 0,
                        }
                        : undefined,
                }, { opacity: addOpacity } = addColor;
                if (grColor.opacity && addOpacity) {
                    const opacityRange = grColor.opacity.value;
                    addOpacity.min = getRangeMin(opacityRange);
                    addOpacity.max = getRangeMax(opacityRange);
                    const opacityAnimation = grColor.opacity.animation;
                    switch (opacityAnimation.startValue) {
                        case exports.StartValueType.min:
                            addOpacity.value = addOpacity.min;
                            addOpacity.status = exports.AnimationStatus.increasing;
                            break;
                        case exports.StartValueType.max:
                            addOpacity.value = addOpacity.max;
                            addOpacity.status = exports.AnimationStatus.decreasing;
                            break;
                        case exports.StartValueType.random:
                        default:
                            addOpacity.value = randomInRangeValue(addOpacity);
                            addOpacity.status = getRandom() >= half$2 ? exports.AnimationStatus.increasing : exports.AnimationStatus.decreasing;
                            break;
                    }
                }
                particle.gradient.colors.push(addColor);
            }
        }
        isEnabled(particle) {
            return (!particle.destroyed &&
                !particle.spawning &&
                (!!particle.gradient?.angle.enable ||
                    (particle.gradient?.colors.some(c => c.value.h.enable || c.value.s.enable || c.value.l.enable) ?? false)));
        }
        loadOptions(options, ...sources) {
            for (const source of sources) {
                if (!source?.gradient) {
                    continue;
                }
                const gradientToLoad = source.gradient;
                options.gradient = executeOnSingleOrMultiple(gradientToLoad, gradient => {
                    const tmp = new AnimatableGradient();
                    tmp.load(gradient);
                    return tmp;
                });
            }
        }
        update(particle, delta) {
            updateGradient(particle, delta, this.#container.hdr);
        }
    }

    async function loadGradientUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("gradient", container => {
                return Promise.resolve(new GradientUpdater(e.pluginManager, container));
            });
        });
    }

    const dirs = [
        Vector.create(identity$3, originPoint.y),
        Vector.create(originPoint.x, identity$3),
        Vector.create(-identity$3, originPoint.y),
        Vector.create(originPoint.x, -identity$3),
    ], opposite = [2, 3, 0, 1], minLength = 0;
    class GridPathGenerator {
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.options = {
                cellSize: 40,
                graph: undefined,
                autoMaze: false,
            };
        }
        generate(p) {
            const size = this.options.cellSize;
            p.grid ??= {
                direction: Math.trunc(getRandom() * dirs.length),
                speed: p.velocity.length,
                cellPosition: {
                    x: Math.floor(p.position.x / size),
                    y: Math.floor(p.position.y / size),
                },
            };
            const grid = p.grid, c = {
                x: Math.floor(p.position.x / size),
                y: Math.floor(p.position.y / size),
            };
            if (c.x !== grid.cellPosition.x || c.y !== grid.cellPosition.y) {
                grid.cellPosition.x = c.x;
                grid.cellPosition.y = c.y;
                const key = `${c.x},${c.y}`, allowed = this.options.graph?.[key];
                if (allowed && allowed.length > minLength) {
                    grid.direction = allowed[Math.trunc(getRandom() * allowed.length)];
                }
                else if (!this.options.graph) {
                    const turn = Math.trunc(getRandom() * 3) - 1;
                    grid.direction = (grid.direction + turn + 4) % dirs.length;
                }
            }
            p.velocity.x = 0;
            p.velocity.y = 0;
            const d = dirs[grid.direction];
            this.#res.x = d.x * grid.speed;
            this.#res.y = d.y * grid.speed;
            return this.#res;
        }
        init() {
            const source = this.#container.actualOptions.particles.move.path.options;
            this.options.cellSize = source["cellSize"] ?? this.options.cellSize;
            this.options.autoMaze = source["autoMaze"] ?? this.options.autoMaze;
            this.options.graph = source["graph"];
            if (this.options.autoMaze) {
                const canvas = this.#container.canvas.size, cellSize = this.options.cellSize, size = {
                    width: Math.ceil(canvas.width / cellSize),
                    height: Math.ceil(canvas.height / cellSize),
                };
                this.options.graph = this.#generateMazeGraph(size);
            }
        }
        reset(p) {
            delete p.grid;
        }
        update() {
        }
        #generateMazeGraph({ height, width }) {
            const graph = {}, visited = [];
            for (let y = 0; y < height; y++) {
                visited[y] = [];
            }
            const stack = [{ x: originPoint.x, y: originPoint.y }];
            while (stack.length > 0) {
                const { x, y } = stack[stack.length - 1];
                if (!visited[y][x]) {
                    visited[y][x] = true;
                }
                const dirsOrder = [0, 1, 2, 3].sort(() => getRandom() - 0.5);
                let moved = false;
                for (const d of dirsOrder) {
                    const n = {
                        x: x + (d === 0 ? 1 : d === 2 ? -1 : 0),
                        y: y + (d === 1 ? 1 : d === 3 ? -1 : 0),
                    };
                    if (n.x < 0 || n.y < 0 || n.x >= width || n.y >= height) {
                        continue;
                    }
                    if (!visited[n.y][n.x]) {
                        const key = `${x},${y}`, nKey = `${n.x},${n.y}`;
                        graph[key] ??= [];
                        graph[nKey] ??= [];
                        graph[key].push(d);
                        graph[nKey].push(opposite[d]);
                        stack.push(n);
                        moved = true;
                        break;
                    }
                }
                if (!moved) {
                    stack.pop();
                }
            }
            return graph;
        }
    }

    const gridPathName = "gridPathGenerator";
    async function loadGridPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(gridPathName, container => {
                return Promise.resolve(new GridPathGenerator(container));
            });
        });
    }

    function drawHeart(data) {
        const { context, radius } = data, diameter = radius * double, halfRadius = radius * half$2, radiusAndHalf = radius + halfRadius, x = -radius, y = -radius;
        context.moveTo(x, y + halfRadius);
        context.quadraticCurveTo(x, y, x + halfRadius, y);
        context.quadraticCurveTo(x + radius, y, x + radius, y + halfRadius);
        context.quadraticCurveTo(x + radius, y, x + radiusAndHalf, y);
        context.quadraticCurveTo(x + diameter, y, x + diameter, y + halfRadius);
        context.quadraticCurveTo(x + diameter, y + radius, x + radiusAndHalf, y + radiusAndHalf);
        context.lineTo(x + radius, y + diameter);
        context.lineTo(x + halfRadius, y + radiusAndHalf);
        context.quadraticCurveTo(x, y + radius, x, y + halfRadius);
    }

    class HeartDrawer {
        draw(data) {
            drawHeart(data);
        }
    }

    async function loadHeartShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["heart"], () => Promise.resolve(new HeartDrawer()));
        });
    }

    function hsvToRgb(hsv) {
        const result = { b: 0, g: 0, r: 0 }, phase = 60, hsvPercent = {
            h: hsv.h / phase,
            s: hsv.s / percentDenominator,
            v: hsv.v / percentDenominator,
        }, offset = 1, hPercentFactor = 2, c = hsvPercent.v * hsvPercent.s, x = c * (offset - Math.abs((hsvPercent.h % hPercentFactor) - offset));
        let tempRgb;
        const cxzRange = { min: 0, max: 1 }, xczRange = { min: 1, max: 2 }, zcxRange = { min: 2, max: 3 }, zxcRange = { min: 3, max: 4 }, xzcRange = { min: 4, max: 5 }, czxRange = { min: 5, max: 6 };
        if (hsvPercent.h >= cxzRange.min && hsvPercent.h <= cxzRange.max) {
            tempRgb = {
                r: c,
                g: x,
                b: 0,
            };
        }
        else if (hsvPercent.h > xczRange.min && hsvPercent.h <= xczRange.max) {
            tempRgb = {
                r: x,
                g: c,
                b: 0,
            };
        }
        else if (hsvPercent.h > zcxRange.min && hsvPercent.h <= zcxRange.max) {
            tempRgb = {
                r: 0,
                g: c,
                b: x,
            };
        }
        else if (hsvPercent.h > zxcRange.min && hsvPercent.h <= zxcRange.max) {
            tempRgb = {
                r: 0,
                g: x,
                b: c,
            };
        }
        else if (hsvPercent.h > xzcRange.min && hsvPercent.h <= xzcRange.max) {
            tempRgb = {
                r: x,
                g: 0,
                b: c,
            };
        }
        else if (hsvPercent.h > czxRange.min && hsvPercent.h <= czxRange.max) {
            tempRgb = {
                r: c,
                g: 0,
                b: x,
            };
        }
        if (tempRgb) {
            const m = hsvPercent.v - c;
            result.r = Math.floor((tempRgb.r + m) * rgbMax);
            result.g = Math.floor((tempRgb.g + m) * rgbMax);
            result.b = Math.floor((tempRgb.b + m) * rgbMax);
        }
        return result;
    }
    function hsvaToRgba(hsva) {
        return {
            a: hsva.a,
            ...hsvToRgb(hsva),
        };
    }

    const hsvRegex = /hsva?\(\s*(\d+)°\s*[\s,]\s*(\d+)%\s*[\s,]\s*(\d+)%\s*([\s,]\s*(0|1|0?\.\d+|(\d{1,3})%)\s*)?\)/i;
    class HsvColorManager {
        accepts(input) {
            return input.startsWith("hsv");
        }
        handleColor(color) {
            const colorValue = color.value, hsvColor = colorValue.hsv ?? color.value;
            if (!("h" in hsvColor) || !("s" in hsvColor) || !("v" in hsvColor)) {
                return;
            }
            return hsvToRgb(hsvColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, hsvColor = colorValue.hsv ?? color.value;
            if (!("h" in hsvColor) || !("s" in hsvColor) || !("v" in hsvColor)) {
                return;
            }
            return hsvToRgb({
                h: getRangeValue(hsvColor.h),
                s: getRangeValue(hsvColor.s),
                v: getRangeValue(hsvColor.v),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = hsvRegex.exec(input), fullLength = 4, indexes = {
                h: 1,
                s: 2,
                v: 3,
                a: 5,
            }, defaultAlpha = 1, radix = 10;
            return result
                ? hsvaToRgba({
                    a: result.length > fullLength ? parseAlpha(result[indexes.a]) : defaultAlpha,
                    h: parseInt(result[indexes.h] ?? "0", radix),
                    s: parseInt(result[indexes.s] ?? "0", radix),
                    v: parseInt(result[indexes.v] ?? "0", radix),
                })
                : undefined;
        }
    }

    async function loadHsvColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("hsv", new HsvColorManager());
        });
    }

    var HwbIndexes;
    (function (HwbIndexes) {
        HwbIndexes[HwbIndexes["h"] = 1] = "h";
        HwbIndexes[HwbIndexes["w"] = 2] = "w";
        HwbIndexes[HwbIndexes["b"] = 3] = "b";
        HwbIndexes[HwbIndexes["a"] = 5] = "a";
    })(HwbIndexes || (HwbIndexes = {}));
    const hwbRegex = /hwba?\(\s*(\d{1,3}(?:\.\d+)?(?:deg|rad|grad|turn)?)\s*[\s,]\s*(\d{1,3}(?:\.\d+)?)%\s*[\s,]\s*(\d{1,3}(?:\.\d+)?)%\s*([\s,]\s*(0|1|0?\.\d+|(\d{1,3})%)\s*)?\)/i, maxDegree = 360, maxPercentage = 100, maxHwbValue = 255, hueSectors = 6, redOffset = 5, greenOffset = 3, blueOffset = 1, clampingMin = 0, clampingMax = 1, clampingReference = 4, unitValue = 1, defaultFallbackValue = 0;
    function hwbToRgb(hwb) {
        const normalizedHue = hwb.h / maxDegree, whiteness = hwb.w / maxPercentage, blackness = hwb.b / maxPercentage, totalWhitenessBlackness = whiteness + blackness;
        let red, green, blue;
        if (totalWhitenessBlackness >= unitValue) {
            const greyShade = whiteness / totalWhitenessBlackness;
            red = greyShade;
            green = greyShade;
            blue = greyShade;
        }
        else {
            const calculateChannel = (channelOffset) => {
                const sectorPosition = (channelOffset + normalizedHue * hueSectors) % hueSectors, availableChroma = unitValue - whiteness - blackness, intensityFactor = Math.max(clampingMin, Math.min(sectorPosition, clampingReference - sectorPosition, clampingMax));
                return unitValue - blackness - availableChroma * intensityFactor;
            };
            red = calculateChannel(redOffset);
            green = calculateChannel(greenOffset);
            blue = calculateChannel(blueOffset);
        }
        return {
            r: Math.round(red * maxHwbValue),
            g: Math.round(green * maxHwbValue),
            b: Math.round(blue * maxHwbValue),
        };
    }
    function hwbaToRgba(hwba) {
        return {
            a: hwba.a,
            ...hwbToRgb(hwba),
        };
    }
    class HwbColorManager {
        accepts(input) {
            return input.startsWith("hwb");
        }
        handleColor(color) {
            const colorValue = color.value, hwbColor = colorValue.hwb ?? color.value;
            if (!("h" in hwbColor) || !("w" in hwbColor) || !("b" in hwbColor)) {
                return;
            }
            return hwbToRgb(hwbColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, hwbColor = colorValue.hwb ?? color.value;
            if (!("h" in hwbColor) || !("w" in hwbColor) || !("b" in hwbColor)) {
                return;
            }
            return hwbToRgb({
                h: getRangeValue(hwbColor.h),
                w: getRangeValue(hwbColor.w),
                b: getRangeValue(hwbColor.b),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = hwbRegex.exec(input), minLength = 4, defaultAlpha = 1;
            if (!result) {
                return;
            }
            const h = result[HwbIndexes.h], w = result[HwbIndexes.w], b = result[HwbIndexes.b];
            return hwbaToRgba({
                a: result.length > minLength ? parseAlpha(result[HwbIndexes.a]) : defaultAlpha,
                h: h !== undefined ? parseFloat(h) : defaultFallbackValue,
                w: w !== undefined ? parseFloat(w) : defaultFallbackValue,
                b: b !== undefined ? parseFloat(b) : defaultFallbackValue,
            });
        }
    }

    async function loadHwbColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("hwb", new HwbColorManager());
        });
    }

    class InfectionStage {
        color = new OptionsColor();
        duration;
        infectedStage;
        radius = 0;
        rate = 1;
        constructor() {
            this.color.value = "#ff0000";
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            this.duration = data.duration;
            this.infectedStage = data.infectedStage;
            loadProperty(this, "radius", data.radius);
            loadProperty(this, "rate", data.rate);
        }
    }

    class Infection {
        cure;
        delay;
        enable;
        infections;
        stages;
        constructor() {
            this.cure = false;
            this.delay = 0;
            this.enable = false;
            this.infections = 0;
            this.stages = [];
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "cure", data.cure);
            loadProperty(this, "delay", data.delay);
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "infections", data.infections);
            if (data.stages === undefined) {
                return;
            }
            this.stages = data.stages.map(t => {
                const s = new InfectionStage();
                s.load(t);
                return s;
            });
        }
    }

    class InfectionPlugin {
        id = "infection";
        async getPlugin(container) {
            const { InfectionPluginInstance } = await Promise.resolve().then(function () { return InfectionPluginInstance$1; });
            return new InfectionPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let infectionOptions = options.infection;
            if (infectionOptions?.load === undefined) {
                options.infection = infectionOptions = new Infection();
            }
            infectionOptions.load(source?.infection);
        }
        needsPlugin(options) {
            return options?.infection?.enable ?? false;
        }
    }

    const minStagesCount = 1;
    class ParticlesInfecter extends ParticlesInteractorBase {
        #maxDistance;
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
        }
        interact(p1, _interactivityData, delta) {
            const infecter = this.container.infecter;
            if (!infecter) {
                return;
            }
            infecter.updateInfection(p1, delta.value);
            if (p1.infection?.stage === undefined) {
                return;
            }
            const container = this.container, options = container.actualOptions, infectionOptions = options.infection;
            if (!infectionOptions?.enable || infectionOptions.stages.length < minStagesCount) {
                return;
            }
            const infectionStage1 = infectionOptions.stages[p1.infection.stage];
            if (!infectionStage1) {
                return;
            }
            this.#maxDistance = Math.max(this.#maxDistance, infectionStage1.radius);
            const pxRatio = container.retina.pixelRatio, radius = p1.getRadius() * double + infectionStage1.radius * pxRatio, pos = p1.getPosition(), infectedStage1 = infectionStage1.infectedStage ?? p1.infection.stage, query = container.particles.grid.queryCircle(pos, radius), infections = infectionStage1.rate, neighbors = query.length;
            for (const p2 of query) {
                const infP2 = p2;
                if (infP2 === p1 ||
                    infP2.destroyed ||
                    infP2.spawning ||
                    !(infP2.infection?.stage === undefined || infP2.infection.stage !== p1.infection.stage) ||
                    getRandom() >= infections / neighbors) {
                    continue;
                }
                if (infP2.infection?.stage === undefined) {
                    infecter.startInfection(infP2, infectedStage1);
                }
                else if (infP2.infection.stage < p1.infection.stage) {
                    infecter.updateInfectionStage(infP2, infectedStage1);
                }
                else if (infP2.infection.stage > p1.infection.stage) {
                    const infectionStage2 = infectionOptions.stages[infP2.infection.stage];
                    if (!infectionStage2) {
                        continue;
                    }
                    const infectedStage2 = infectionStage2.infectedStage ?? infP2.infection.stage;
                    infecter.updateInfectionStage(p1, infectedStage2);
                }
            }
        }
        isEnabled() {
            return this.container.actualOptions.infection?.enable ?? false;
        }
        reset() {
        }
    }

    async function loadInfectionPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addPlugin(new InfectionPlugin());
            e.pluginManager.addInteractor?.("particlesInfection", (container) => {
                return Promise.resolve(new ParticlesInfecter(container));
            });
        });
    }

    const loopSizeFactor = 0.55;
    function drawInfinity(data) {
        const { context, radius } = data, loopControl = radius * loopSizeFactor;
        context.moveTo(originPoint.x, originPoint.y);
        context.bezierCurveTo(loopControl, -radius, loopControl, radius, originPoint.x, originPoint.y);
        context.moveTo(originPoint.x, originPoint.y);
        context.bezierCurveTo(-loopControl, -radius, originPoint.x - loopControl, radius, originPoint.x, originPoint.y);
    }

    class InfinityDrawer {
        draw(data) {
            drawInfinity(data);
        }
    }

    async function loadInfinityShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["infinity"], () => Promise.resolve(new InfinityDrawer()));
        });
    }

    const RGB$1 = {
        MAX: 255,
    }, WHITE_POINT_D65$1 = {
        X: 0.95047,
        Y: 1.0,
        Z: 1.08883,
    }, CIE$1 = {
        LAB_EPSILON_NUMERATOR: 216,
        LAB_EPSILON_DENOMINATOR: 24389,
        LAB_KAPPA_NUMERATOR: 24389,
        LAB_KAPPA_DENOMINATOR: 27,
        LAB_L_OFFSET: 16,
        LAB_L_SCALE: 116,
        LAB_A_SCALE: 500,
        LAB_B_SCALE: 200,
    }, LAB$1 = {
        EPSILON: CIE$1.LAB_EPSILON_NUMERATOR / CIE$1.LAB_EPSILON_DENOMINATOR,
        KAPPA: CIE$1.LAB_KAPPA_NUMERATOR / CIE$1.LAB_KAPPA_DENOMINATOR,
        L_OFFSET: CIE$1.LAB_L_OFFSET,
        L_SCALE: CIE$1.LAB_L_SCALE,
        A_SCALE: CIE$1.LAB_A_SCALE,
        B_SCALE: CIE$1.LAB_B_SCALE,
    }, XYZ_TO_LINEAR_RGB$1 = {
        r: { x: 3.2404542, y: -1.5371385, z: -0.4985314 },
        g: { x: -0.969266, y: 1.8760108, z: 0.041556 },
        b: { x: 0.0556434, y: -0.2040259, z: 1.0572252 },
    }, SRGB$3 = {
        GAMMA: 2.4,
        LINEAR_THRESHOLD: 0.0031308,
        LINEAR_SCALE: 12.92,
        SCALE: 1.055,
        OFFSET: 0.055,
    }, minSrgbValue$3 = 0, maxSrgbValue$3 = 1;
    function labToRgb(lab) {
        const L = lab.l, a = lab.aAxis, b = lab.bAxis, fy = (L + LAB$1.L_OFFSET) / LAB$1.L_SCALE, fx = fy + a / LAB$1.A_SCALE, fz = fy - b / LAB$1.B_SCALE, cubic = 3, fx3 = fx ** cubic, fz3 = fz ** cubic, xr = fx3 > LAB$1.EPSILON ? fx3 : (LAB$1.L_SCALE * fx - LAB$1.L_OFFSET) / LAB$1.KAPPA, yr = L > LAB$1.KAPPA * LAB$1.EPSILON ? fy ** cubic : L / LAB$1.KAPPA, zr = fz3 > LAB$1.EPSILON ? fz3 : (LAB$1.L_SCALE * fz - LAB$1.L_OFFSET) / LAB$1.KAPPA, X = xr * WHITE_POINT_D65$1.X, Y = yr * WHITE_POINT_D65$1.Y, Z = zr * WHITE_POINT_D65$1.Z, rLinear = XYZ_TO_LINEAR_RGB$1.r.x * X + XYZ_TO_LINEAR_RGB$1.r.y * Y + XYZ_TO_LINEAR_RGB$1.r.z * Z, gLinear = XYZ_TO_LINEAR_RGB$1.g.x * X + XYZ_TO_LINEAR_RGB$1.g.y * Y + XYZ_TO_LINEAR_RGB$1.g.z * Z, bLinear = XYZ_TO_LINEAR_RGB$1.b.x * X + XYZ_TO_LINEAR_RGB$1.b.y * Y + XYZ_TO_LINEAR_RGB$1.b.z * Z, toSrgb = (x) => x <= SRGB$3.LINEAR_THRESHOLD
            ? SRGB$3.LINEAR_SCALE * x
            : SRGB$3.SCALE * Math.pow(x, inverseFactorNumerator / SRGB$3.GAMMA) - SRGB$3.OFFSET, toSrgbFixed = num => Math.round(clamp(toSrgb(num), minSrgbValue$3, maxSrgbValue$3) * RGB$1.MAX);
        return {
            r: toSrgbFixed(rLinear),
            g: toSrgbFixed(gLinear),
            b: toSrgbFixed(bLinear),
        };
    }
    function labaToRgba(laba) {
        return {
            a: laba.a,
            ...labToRgb(laba),
        };
    }

    const labRegex = /lab\(\s*(\d+(\.\d+)?)%\s+(\d+(\.\d+)?)\s+(\d+(\.\d+)?)(?:\s*\/\s*(0|1|0?\.\d+|\d{1,3}%))?\s*\)/i;
    class LabColorManager {
        accepts(input) {
            return input.startsWith("lab");
        }
        handleColor(color) {
            const colorValue = color.value, labColor = colorValue.lab ?? color.value;
            if (!("l" in labColor) || !("aAxis" in labColor) || !("bAxis" in labColor)) {
                return;
            }
            return labToRgb(labColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, labColor = colorValue.lab ?? color.value;
            if (!("l" in labColor) || !("aAxis" in labColor) || !("bAxis" in labColor)) {
                return;
            }
            return labToRgb({
                l: getRangeValue(labColor.l),
                aAxis: getRangeValue(labColor.aAxis),
                bAxis: getRangeValue(labColor.bAxis),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = labRegex.exec(input), indexes = {
                l: 1,
                aAxis: 3,
                bAxis: 5,
                a: 7,
            }, defaultAlpha = 1;
            return result
                ? labaToRgba({
                    a: result[indexes.a] ? parseAlpha(result[indexes.a]) : defaultAlpha,
                    aAxis: parseFloat(result[indexes.aAxis] ?? "0"),
                    bAxis: parseFloat(result[indexes.bAxis] ?? "0"),
                    l: parseFloat(result[indexes.l] ?? "0"),
                })
                : undefined;
        }
    }

    async function loadLabColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("lab", new LabColorManager());
        });
    }

    const RGB = {
        MAX: 255,
    }, WHITE_POINT_D65 = {
        X: 0.95047,
        Y: 1.0,
        Z: 1.08883,
    }, CIE = {
        LAB_EPSILON_NUMERATOR: 216,
        LAB_EPSILON_DENOMINATOR: 24389,
        LAB_KAPPA_NUMERATOR: 24389,
        LAB_KAPPA_DENOMINATOR: 27,
        LAB_L_OFFSET: 16,
        LAB_L_SCALE: 116,
        LAB_A_SCALE: 500,
        LAB_B_SCALE: 200,
    }, LAB = {
        EPSILON: CIE.LAB_EPSILON_NUMERATOR / CIE.LAB_EPSILON_DENOMINATOR,
        KAPPA: CIE.LAB_KAPPA_NUMERATOR / CIE.LAB_KAPPA_DENOMINATOR,
        L_OFFSET: CIE.LAB_L_OFFSET,
        L_SCALE: CIE.LAB_L_SCALE,
        A_SCALE: CIE.LAB_A_SCALE,
        B_SCALE: CIE.LAB_B_SCALE,
    }, XYZ_TO_LINEAR_RGB = {
        r: { x: 3.2404542, y: -1.5371385, z: -0.4985314 },
        g: { x: -0.969266, y: 1.8760108, z: 0.041556 },
        b: { x: 0.0556434, y: -0.2040259, z: 1.0572252 },
    }, SRGB$2 = {
        GAMMA: 2.4,
        LINEAR_THRESHOLD: 0.0031308,
        LINEAR_SCALE: 12.92,
        SCALE: 1.055,
        OFFSET: 0.055,
    }, minSrgbValue$2 = 0, maxSrgbValue$2 = 1;
    function lchToRgb(lch) {
        const L = lch.l, C = lch.c, hRad = degToRad(lch.h), a = C * Math.cos(hRad), b = C * Math.sin(hRad), fy = (L + LAB.L_OFFSET) / LAB.L_SCALE, fx = fy + a / LAB.A_SCALE, fz = fy - b / LAB.B_SCALE, cubic = 3, fx3 = fx ** cubic, fz3 = fz ** cubic, xr = fx3 > LAB.EPSILON ? fx3 : (LAB.L_SCALE * fx - LAB.L_OFFSET) / LAB.KAPPA, yr = L > LAB.KAPPA * LAB.EPSILON ? fy ** cubic : L / LAB.KAPPA, zr = fz3 > LAB.EPSILON ? fz3 : (LAB.L_SCALE * fz - LAB.L_OFFSET) / LAB.KAPPA, X = xr * WHITE_POINT_D65.X, Y = yr * WHITE_POINT_D65.Y, Z = zr * WHITE_POINT_D65.Z, rLinear = XYZ_TO_LINEAR_RGB.r.x * X + XYZ_TO_LINEAR_RGB.r.y * Y + XYZ_TO_LINEAR_RGB.r.z * Z, gLinear = XYZ_TO_LINEAR_RGB.g.x * X + XYZ_TO_LINEAR_RGB.g.y * Y + XYZ_TO_LINEAR_RGB.g.z * Z, bLinear = XYZ_TO_LINEAR_RGB.b.x * X + XYZ_TO_LINEAR_RGB.b.y * Y + XYZ_TO_LINEAR_RGB.b.z * Z, toSrgb = (x) => x <= SRGB$2.LINEAR_THRESHOLD
            ? SRGB$2.LINEAR_SCALE * x
            : SRGB$2.SCALE * Math.pow(x, inverseFactorNumerator / SRGB$2.GAMMA) - SRGB$2.OFFSET, toSrgbFixed = num => Math.round(clamp(toSrgb(num), minSrgbValue$2, maxSrgbValue$2) * RGB.MAX);
        return {
            r: toSrgbFixed(rLinear),
            g: toSrgbFixed(gLinear),
            b: toSrgbFixed(bLinear),
        };
    }
    function lchaToRgba(lcha) {
        return {
            a: lcha.a,
            ...lchToRgb(lcha),
        };
    }

    const lchRegex = /lch\(\s*(\d+(\.\d+)?)%\s+(\d+(\.\d+)?)\s+(\d+(\.\d+)?)(?:\s*\/\s*(0|1|0?\.\d+|\d{1,3}%))?\s*\)/i;
    class LchColorManager {
        accepts(input) {
            return input.startsWith("lch");
        }
        handleColor(color) {
            const colorValue = color.value, lchColor = colorValue.lch ?? color.value;
            if (!("l" in lchColor) || !("c" in lchColor) || !("h" in lchColor)) {
                return;
            }
            return lchToRgb(lchColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, lchColor = colorValue.lch ?? color.value;
            if (!("l" in lchColor) || !("c" in lchColor) || !("h" in lchColor)) {
                return;
            }
            return lchToRgb({
                l: getRangeValue(lchColor.l),
                c: getRangeValue(lchColor.c),
                h: getRangeValue(lchColor.h),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = lchRegex.exec(input), indexes = {
                l: 1,
                c: 3,
                h: 5,
                a: 7,
            }, defaultAlpha = 1;
            return result
                ? lchaToRgba({
                    a: result[indexes.a] ? parseAlpha(result[indexes.a]) : defaultAlpha,
                    c: parseFloat(result[indexes.c] ?? "0"),
                    h: parseFloat(result[indexes.h] ?? "0"),
                    l: parseFloat(result[indexes.l] ?? "0"),
                })
                : undefined;
        }
    }

    async function loadLchColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("lch", new LchColorManager());
        });
    }

    const defaultScale = 1, defaultLevyAlpha = 1.5;
    class LevyPathGenerator {
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.options = {
                alpha: defaultLevyAlpha,
                scale: defaultScale,
                maxStep: 10,
            };
        }
        generate(p) {
            p.levy ??= {
                angle: getRandom() * Math.PI * 2,
                baseSpeed: p.velocity.length,
            };
            const opts = this.options, l = p.levy;
            l.angle += (getRandom() - 0.5) * 0.2;
            const u = Math.max(getRandom(), 1e-6), scale = opts.scale ?? defaultScale, levyAlpha = opts.alpha ?? defaultLevyAlpha;
            let step = scale / Math.pow(u, 1 / levyAlpha);
            if (opts.maxStep !== undefined) {
                step = Math.min(step, opts.maxStep);
            }
            const speed = l.baseSpeed * step;
            p.velocity.x = 0;
            p.velocity.y = 0;
            this.#res.length = speed;
            this.#res.angle = l.angle;
            return this.#res;
        }
        init() {
            const source = this.#container.actualOptions.particles.move.path.options;
            this.options.alpha = source["alpha"] ?? this.options.alpha;
            this.options.scale = source["scale"] ?? this.options.scale;
            this.options.maxStep = source["maxStep"] ?? this.options.maxStep;
        }
        reset(p) {
            delete p.levy;
        }
        update() {
        }
    }

    const levyPathName = "levyPathGenerator";
    async function loadLevyPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(levyPathName, container => {
                return Promise.resolve(new LevyPathGenerator(container));
            });
        });
    }

    const gradientPos = {
        max: 1,
        min: 0,
    }, halfPI$2 = Math.PI * half$2, quarterPI = Math.PI * quarter$2, arcStart = 0;
    const lightMode = "light";
    function drawLight(container, context, mousePos) {
        const lightOptions = container.actualOptions.interactivity?.modes.light?.area;
        if (!lightOptions) {
            return;
        }
        context.beginPath();
        context.arc(mousePos.x, mousePos.y, lightOptions.radius, arcStart, doublePI);
        const gradientAmbientLight = context.createRadialGradient(mousePos.x, mousePos.y, arcStart, mousePos.x, mousePos.y, lightOptions.radius), gradientRgb = container.canvas.mouseLight;
        if (!gradientRgb?.start || !gradientRgb.stop) {
            return;
        }
        gradientAmbientLight.addColorStop(gradientPos.min, getStyleFromRgb(gradientRgb.start, container.hdr, undefined, container.peakNits, container.hdrMode));
        gradientAmbientLight.addColorStop(gradientPos.max, getStyleFromRgb(gradientRgb.stop, container.hdr, undefined, container.peakNits, container.hdrMode));
        context.fillStyle = gradientAmbientLight;
        context.fill();
    }
    function drawParticleShadow(container, context, particle, mousePos) {
        const pos = particle.getPosition(), shadowOptions = container.actualOptions.interactivity?.modes.light?.shadow;
        if (!shadowOptions) {
            return;
        }
        const shadowRgb = particle.lightShadow;
        if (!shadowRgb) {
            return;
        }
        const radius = particle.getRadius(), sides = particle.sides, full = doublePI / sides, angle = -particle.getAngle() + quarterPI, factor = 1, dots = [];
        for (let i = 0; i < sides; i++) {
            dots.push({
                x: pos.x + radius * Math.sin(angle + full * i) * factor,
                y: pos.y + radius * Math.cos(angle + full * i) * factor,
            });
        }
        const points = [], shadowLength = shadowOptions.length;
        for (const dot of dots) {
            const dotAngle = Math.atan2(mousePos.y - dot.y, mousePos.x - dot.x), end = {
                x: dot.x + shadowLength * Math.sin(-dotAngle - halfPI$2),
                y: dot.y + shadowLength * Math.cos(-dotAngle - halfPI$2),
            };
            points.push({
                end: end,
                start: dot,
            });
        }
        const shadowColor = getStyleFromRgb(shadowRgb, container.hdr, undefined, container.peakNits, container.hdrMode), lastOffset = 1, firstPos = 0, last = points.length - lastOffset;
        for (let i = last, n = 0; i >= firstPos; n = i--) {
            context.beginPath();
            const iPoint = points[i], nPoint = points[n];
            if (!iPoint || !nPoint) {
                continue;
            }
            context.moveTo(iPoint.start.x, iPoint.start.y);
            context.lineTo(nPoint.start.x, nPoint.start.y);
            context.lineTo(nPoint.end.x, nPoint.end.y);
            context.lineTo(iPoint.end.x, iPoint.end.y);
            context.fillStyle = shadowColor;
            context.fill();
        }
    }

    class LightGradient {
        start = new OptionsColor();
        stop = new OptionsColor();
        constructor() {
            this.start.value = "#ffffff";
            this.stop.value = "#000000";
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.start = OptionsColor.create(this.start, data.start);
            this.stop = OptionsColor.create(this.stop, data.stop);
        }
    }

    class LightArea {
        gradient = new LightGradient();
        radius = 1000;
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.gradient.load(data.gradient);
            loadProperty(this, "radius", data.radius);
        }
    }

    class LightShadow {
        color = new OptionsColor();
        length = 2000;
        constructor() {
            this.color.value = "#000000";
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.color = OptionsColor.create(this.color, data.color);
            loadProperty(this, "length", data.length);
        }
    }

    class Light {
        area = new LightArea();
        shadow = new LightShadow();
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.area.load(data.area);
            this.shadow.load(data.shadow);
        }
    }

    class ExternalLighter extends ExternalInteractorBase {
        maxDistance = 0;
        #pluginManager;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
        }
        clear() {
        }
        init() {
        }
        interact(interactivityData) {
            const container = this.container, options = container.actualOptions, interactivity = interactivityData;
            if (!options.interactivity?.events.onHover.enable || interactivity.status !== "pointermove") {
                return;
            }
            const mousePos = interactivity.mouse.position;
            if (!mousePos) {
                return;
            }
            container.canvas.render.draw(ctx => {
                drawLight(container, ctx, mousePos);
            });
        }
        isEnabled(interactivityData, particle) {
            const container = this.container, mouse = interactivityData.mouse, interactivity = particle?.interactivity ?? container.actualOptions.interactivity, events = interactivity?.events;
            if (!(events?.onHover.enable && mouse.position)) {
                return false;
            }
            const res = isInArray(lightMode, events.onHover.mode);
            if (res && interactivity?.modes.light) {
                const lightGradient = interactivity.modes.light.area.gradient;
                container.canvas.mouseLight = {
                    start: rangeColorToRgb(this.#pluginManager, lightGradient.start),
                    stop: rangeColorToRgb(this.#pluginManager, lightGradient.stop),
                };
            }
            return res;
        }
        loadModeOptions(options, ...sources) {
            loadOptionProperty(options, "light", Light, ...sources);
        }
        reset() {
        }
    }

    class ParticlesLighter extends ParticlesInteractorBase {
        maxDistance;
        #pluginManager;
        constructor(pluginManager, container) {
            super(container);
            this.#pluginManager = pluginManager;
            this.maxDistance = 0;
        }
        clear() {
        }
        init() {
        }
        interact(particle, interactivityData) {
            const container = this.container, options = container.actualOptions;
            if (!options.interactivity?.events.onHover.enable || interactivityData.status !== "pointermove") {
                return;
            }
            const mousePos = interactivityData.mouse.position;
            if (!mousePos) {
                return;
            }
            container.canvas.render.draw(ctx => {
                drawParticleShadow(container, ctx, particle, mousePos);
            });
        }
        isEnabled(particle, interactivityData) {
            const interactivity = particle.interactivity, mouse = interactivityData.mouse, events = interactivity.events;
            if (!(events.onHover.enable && mouse.position)) {
                return false;
            }
            const res = isInArray(lightMode, events.onHover.mode);
            if (res && interactivity.modes.light) {
                const shadowOptions = interactivity.modes.light.shadow;
                particle.lightShadow = rangeColorToRgb(this.#pluginManager, shadowOptions.color);
            }
            return res;
        }
        reset() {
        }
    }

    async function loadLightInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("externalLight", container => {
                return Promise.resolve(new ExternalLighter(e.pluginManager, container));
            });
            e.pluginManager.addInteractor?.("particlesLight", container => {
                return Promise.resolve(new ParticlesLighter(e.pluginManager, container));
            });
        });
    }

    const manualDefaultPosition = 50;
    class ManualParticle {
        options;
        position;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.position) {
                this.position = {
                    x: data.position.x ?? manualDefaultPosition,
                    y: data.position.y ?? manualDefaultPosition,
                    mode: data.position.mode ?? exports.PixelMode.percent,
                };
            }
            if (data.options) {
                this.options = deepExtend({}, data.options);
            }
        }
    }

    class ManualParticlesPlugin {
        id = "manual-particles";
        async getPlugin(container) {
            const { ManualParticlesPluginInstance } = await Promise.resolve().then(function () { return ManualParticlesPluginInstance$1; });
            return new ManualParticlesPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            options.manualParticles ??= [];
            if (source?.manualParticles) {
                options.manualParticles = source.manualParticles.map(t => {
                    const tmp = new ManualParticle();
                    tmp.load(t);
                    return tmp;
                });
            }
        }
        needsPlugin(options) {
            return !!options?.manualParticles?.length;
        }
    }

    async function loadManualParticlesPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ManualParticlesPlugin());
        });
    }

    const matrixChars = [
        "ア",
        "\u30A4",
        "\u30A6",
        "\u30A8",
        "\u30AA",
        "\u30AB",
        "\u30AD",
        "\u30AF",
        "\u30B1",
        "\u30B3",
        "\u30B5",
        "\u30B7",
        "\u30B9",
        "\u30BB",
        "\u30BD",
        "\u30BF",
        "\u30C1",
        "\u30C4",
        "\u30C6",
        "\u30C8",
        "\u30CA",
        "\u30CB",
        "\u30CC",
        "\u30CD",
        "\u30CE",
        "\u30CF",
        "\u30D2",
        "\u30D5",
        "\u30D8",
        "\u30DB",
        "\u30DE",
        "\u30DF",
        "\u30E0",
        "\u30E1",
        "\u30E2",
        "\u30E4",
        "\u30E6",
        "\u30E8",
        "\u30E9",
        "\u30EA",
        "\u30EB",
        "\u30EC",
        "\u30ED",
        "\u30EF",
        "\u30F2",
        "\u30F3",
        "\u30AC",
        "\u30AE",
        "\u30B0",
        "\u30B2",
        "\u30B4",
        "\u30B6",
        "\u30B8",
        "\u30BA",
        "\u30BC",
        "\u30BE",
        "\u30C0",
        "\u30C2",
        "\u30C5",
        "\u30C7",
        "\u30C9",
        "\u30D0",
        "\u30D3",
        "\u30D6",
        "\u30D9",
        "\u30DC",
        "\u30D1",
        "\u30D4",
        "\u30D7",
        "\u30DA",
        "\u30DD",
        "\u30A1",
        "\u30A3",
        "\u30A5",
        "\u30A7",
        "\u30A9",
        "\u30E3",
        "\u30E5",
        "\u30E7",
        "\u30C3",
        "\u30FC",
        "\u30F4",
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "\uFF10",
        "\uFF11",
        "\uFF12",
        "\uFF13",
        "\uFF14",
        "\uFF15",
        "\uFF16",
        "\uFF17",
        "\uFF18",
        "\uFF19",
        "A",
        "B",
        "C",
        "D",
        "E",
        "F",
        "G",
        "H",
        "I",
        "J",
        "K",
        "L",
        "M",
        "N",
        "O",
        "P",
        "Q",
        "R",
        "S",
        "T",
        "U",
        "V",
        "W",
        "X",
        "Y",
        "Z",
        "\u65E5",
        "\u672C",
        "\u4EBA",
        "\u5927",
        "\u4E2D",
        "\u5C0F",
        "\u4E0A",
        "\u4E0B",
        "\u5DE6",
        "\u53F3",
        "\u529B",
        "\u6642",
        "\u7A7A",
        "\u751F",
        "\u6B7B",
        "\u7121",
        "\u6709",
        "!",
        "@",
        "#",
        "$",
        "%",
        "&",
        "*",
        "+",
        "-",
        "=",
        "?",
        "/",
        "\\",
        "|",
        "<",
        ">",
        "{",
        "}",
        "[",
        "]",
        "(",
        ")",
    ];
    const defaultMinInterval = 100, defaultMaxInterval = 2000, charCache = new WeakMap();
    function randomChar() {
        return matrixChars[Math.floor(getRandom() * matrixChars.length)] ?? " ";
    }
    function randomInterval(minInterval, maxInterval) {
        return minInterval + getRandom() * (maxInterval - minInterval);
    }
    function getState(particle, minInterval, maxInterval) {
        let state = charCache.get(particle);
        if (!state) {
            state = {
                char: randomChar(),
                elapsed: 0,
                interval: randomInterval(minInterval, maxInterval),
            };
            charCache.set(particle, state);
        }
        return state;
    }
    function drawMatrix(data) {
        const { context, radius, particle, delta, fill, stroke } = data, shapeData = particle.shapeData, minInterval = getRangeMin(shapeData?.interval ?? defaultMinInterval), maxInterval = getRangeMax(shapeData?.interval ?? defaultMaxInterval), state = getState(particle, minInterval, maxInterval);
        state.elapsed += delta.value;
        if (state.elapsed >= state.interval) {
            state.char = randomChar();
            state.elapsed -= state.interval;
            state.interval = randomInterval(minInterval, maxInterval);
        }
        const fontSize = Math.round(radius * double);
        context.font = `bold ${fontSize}px "Courier New", Courier, monospace`;
        context.textAlign = "center";
        context.textBaseline = "middle";
        if (fill) {
            context.fillText(state.char, originPoint.x, originPoint.y);
        }
        if (stroke) {
            context.strokeText(state.char, originPoint.x, originPoint.y);
        }
    }

    class MatrixDrawer {
        draw(data) {
            drawMatrix(data);
        }
    }

    async function loadMatrixShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["matrix"], () => Promise.resolve(new MatrixDrawer()));
        });
    }

    class MotionReduce {
        factor = 4;
        value = true;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "factor", data.factor);
            loadProperty(this, "value", data.value);
        }
    }

    class Motion {
        disable = true;
        reduce = new MotionReduce();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "disable", data.disable);
            this.reduce.load(data.reduce);
        }
    }

    class MotionPlugin {
        id = "motion";
        async getPlugin(container) {
            const { MotionPluginInstance } = await Promise.resolve().then(function () { return MotionPluginInstance$1; });
            return new MotionPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin()) {
                return;
            }
            let motionOptions = options.motion;
            if (!motionOptions?.load) {
                options.motion = motionOptions = new Motion();
            }
            motionOptions.load(source?.motion);
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadMotionPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new MotionPlugin());
        });
    }

    const namedColors = new Map([
        ["aliceblue", { r: 240, g: 248, b: 255 }],
        ["antiquewhite", { r: 250, g: 235, b: 215 }],
        ["aqua", { r: 0, g: 255, b: 255 }],
        ["aquamarine", { r: 127, g: 255, b: 212 }],
        ["azure", { r: 240, g: 255, b: 255 }],
        ["beige", { r: 245, g: 245, b: 220 }],
        ["bisque", { r: 255, g: 228, b: 196 }],
        ["black", { r: 0, g: 0, b: 0 }],
        ["blanchedalmond", { r: 255, g: 235, b: 205 }],
        ["blue", { r: 0, g: 0, b: 255 }],
        ["blueviolet", { r: 138, g: 43, b: 226 }],
        ["brown", { r: 165, g: 42, b: 42 }],
        ["burlywood", { r: 222, g: 184, b: 135 }],
        ["cadetblue", { r: 95, g: 158, b: 160 }],
        ["chartreuse", { r: 127, g: 255, b: 0 }],
        ["chocolate", { r: 210, g: 105, b: 30 }],
        ["coral", { r: 255, g: 127, b: 80 }],
        ["cornflowerblue", { r: 100, g: 149, b: 237 }],
        ["cornsilk", { r: 255, g: 248, b: 220 }],
        ["crimson", { r: 220, g: 20, b: 60 }],
        ["cyan", { r: 0, g: 255, b: 255 }],
        ["darkblue", { r: 0, g: 0, b: 139 }],
        ["darkcyan", { r: 0, g: 139, b: 139 }],
        ["darkgoldenrod", { r: 184, g: 134, b: 11 }],
        ["darkgray", { r: 169, g: 169, b: 169 }],
        ["darkgreen", { r: 0, g: 100, b: 0 }],
        ["darkgrey", { r: 169, g: 169, b: 169 }],
        ["darkkhaki", { r: 189, g: 183, b: 107 }],
        ["darkmagenta", { r: 139, g: 0, b: 139 }],
        ["darkolivegreen", { r: 85, g: 107, b: 47 }],
        ["darkorange", { r: 255, g: 140, b: 0 }],
        ["darkorchid", { r: 153, g: 50, b: 204 }],
        ["darkred", { r: 139, g: 0, b: 0 }],
        ["darksalmon", { r: 233, g: 150, b: 122 }],
        ["darkseagreen", { r: 143, g: 188, b: 143 }],
        ["darkslateblue", { r: 72, g: 61, b: 139 }],
        ["darkslategray", { r: 47, g: 79, b: 79 }],
        ["darkslategrey", { r: 47, g: 79, b: 79 }],
        ["darkturquoise", { r: 0, g: 206, b: 209 }],
        ["darkviolet", { r: 148, g: 0, b: 211 }],
        ["deeppink", { r: 255, g: 20, b: 147 }],
        ["deepskyblue", { r: 0, g: 191, b: 255 }],
        ["dimgray", { r: 105, g: 105, b: 105 }],
        ["dimgrey", { r: 105, g: 105, b: 105 }],
        ["dodgerblue", { r: 30, g: 144, b: 255 }],
        ["firebrick", { r: 178, g: 34, b: 34 }],
        ["floralwhite", { r: 255, g: 250, b: 240 }],
        ["forestgreen", { r: 34, g: 139, b: 34 }],
        ["fuchsia", { r: 255, g: 0, b: 255 }],
        ["gainsboro", { r: 220, g: 220, b: 220 }],
        ["ghostwhite", { r: 248, g: 248, b: 255 }],
        ["gold", { r: 255, g: 215, b: 0 }],
        ["goldenrod", { r: 218, g: 165, b: 32 }],
        ["gray", { r: 128, g: 128, b: 128 }],
        ["green", { r: 0, g: 128, b: 0 }],
        ["greenyellow", { r: 173, g: 255, b: 47 }],
        ["grey", { r: 128, g: 128, b: 128 }],
        ["honeydew", { r: 240, g: 255, b: 240 }],
        ["hotpink", { r: 255, g: 105, b: 180 }],
        ["indianred", { r: 205, g: 92, b: 92 }],
        ["indigo", { r: 75, g: 0, b: 130 }],
        ["ivory", { r: 255, g: 255, b: 240 }],
        ["khaki", { r: 240, g: 230, b: 140 }],
        ["lavender", { r: 230, g: 230, b: 250 }],
        ["lavenderblush", { r: 255, g: 240, b: 245 }],
        ["lawngreen", { r: 124, g: 252, b: 0 }],
        ["lemonchiffon", { r: 255, g: 250, b: 205 }],
        ["lightblue", { r: 173, g: 216, b: 230 }],
        ["lightcoral", { r: 240, g: 128, b: 128 }],
        ["lightcyan", { r: 224, g: 255, b: 255 }],
        ["lightgoldenrodyellow", { r: 250, g: 250, b: 210 }],
        ["lightgray", { r: 211, g: 211, b: 211 }],
        ["lightgreen", { r: 144, g: 238, b: 144 }],
        ["lightgrey", { r: 211, g: 211, b: 211 }],
        ["lightpink", { r: 255, g: 182, b: 193 }],
        ["lightsalmon", { r: 255, g: 160, b: 122 }],
        ["lightseagreen", { r: 32, g: 178, b: 170 }],
        ["lightskyblue", { r: 135, g: 206, b: 250 }],
        ["lightslategray", { r: 119, g: 136, b: 153 }],
        ["lightslategrey", { r: 119, g: 136, b: 153 }],
        ["lightsteelblue", { r: 176, g: 196, b: 222 }],
        ["lightyellow", { r: 255, g: 255, b: 224 }],
        ["lime", { r: 0, g: 255, b: 0 }],
        ["limegreen", { r: 50, g: 205, b: 50 }],
        ["linen", { r: 250, g: 240, b: 230 }],
        ["magenta", { r: 255, g: 0, b: 255 }],
        ["maroon", { r: 128, g: 0, b: 0 }],
        ["mediumaquamarine", { r: 102, g: 205, b: 170 }],
        ["mediumblue", { r: 0, g: 0, b: 205 }],
        ["mediumorchid", { r: 186, g: 85, b: 211 }],
        ["mediumpurple", { r: 147, g: 112, b: 219 }],
        ["mediumseagreen", { r: 60, g: 179, b: 113 }],
        ["mediumslateblue", { r: 123, g: 104, b: 238 }],
        ["mediumspringgreen", { r: 0, g: 250, b: 154 }],
        ["mediumturquoise", { r: 72, g: 209, b: 204 }],
        ["mediumvioletred", { r: 199, g: 21, b: 133 }],
        ["midnightblue", { r: 25, g: 25, b: 112 }],
        ["mintcream", { r: 245, g: 255, b: 250 }],
        ["mistyrose", { r: 255, g: 228, b: 225 }],
        ["moccasin", { r: 255, g: 228, b: 181 }],
        ["navajowhite", { r: 255, g: 222, b: 173 }],
        ["navy", { r: 0, g: 0, b: 128 }],
        ["oldlace", { r: 253, g: 245, b: 230 }],
        ["olive", { r: 128, g: 128, b: 0 }],
        ["olivedrab", { r: 107, g: 142, b: 35 }],
        ["orange", { r: 255, g: 165, b: 0 }],
        ["orangered", { r: 255, g: 69, b: 0 }],
        ["orchid", { r: 218, g: 112, b: 214 }],
        ["palegoldenrod", { r: 238, g: 232, b: 170 }],
        ["palegreen", { r: 152, g: 251, b: 152 }],
        ["paleturquoise", { r: 175, g: 238, b: 238 }],
        ["palevioletred", { r: 219, g: 112, b: 147 }],
        ["papayawhip", { r: 255, g: 239, b: 213 }],
        ["peachpuff", { r: 255, g: 218, b: 185 }],
        ["peru", { r: 205, g: 133, b: 63 }],
        ["pink", { r: 255, g: 192, b: 203 }],
        ["plum", { r: 221, g: 160, b: 221 }],
        ["powderblue", { r: 176, g: 224, b: 230 }],
        ["purple", { r: 128, g: 0, b: 128 }],
        ["rebeccapurple", { r: 102, g: 51, b: 153 }],
        ["red", { r: 255, g: 0, b: 0 }],
        ["rosybrown", { r: 188, g: 143, b: 143 }],
        ["royalblue", { r: 65, g: 105, b: 225 }],
        ["saddlebrown", { r: 139, g: 69, b: 19 }],
        ["salmon", { r: 250, g: 128, b: 114 }],
        ["sandybrown", { r: 244, g: 164, b: 96 }],
        ["seagreen", { r: 46, g: 139, b: 87 }],
        ["seashell", { r: 255, g: 245, b: 238 }],
        ["sienna", { r: 160, g: 82, b: 45 }],
        ["silver", { r: 192, g: 192, b: 192 }],
        ["skyblue", { r: 135, g: 206, b: 235 }],
        ["slateblue", { r: 106, g: 90, b: 205 }],
        ["slategray", { r: 112, g: 128, b: 144 }],
        ["slategrey", { r: 112, g: 128, b: 144 }],
        ["snow", { r: 255, g: 250, b: 250 }],
        ["springgreen", { r: 0, g: 255, b: 127 }],
        ["steelblue", { r: 70, g: 130, b: 180 }],
        ["tan", { r: 210, g: 180, b: 140 }],
        ["teal", { r: 0, g: 128, b: 128 }],
        ["thistle", { r: 216, g: 191, b: 216 }],
        ["tomato", { r: 255, g: 99, b: 71 }],
        ["turquoise", { r: 64, g: 224, b: 208 }],
        ["violet", { r: 238, g: 130, b: 238 }],
        ["wheat", { r: 245, g: 222, b: 179 }],
        ["white", { r: 255, g: 255, b: 255 }],
        ["whitesmoke", { r: 245, g: 245, b: 245 }],
        ["yellow", { r: 255, g: 255, b: 0 }],
        ["yellowgreen", { r: 154, g: 205, b: 50 }],
    ]);
    class NamedColorManager {
        accepts(input) {
            return namedColors.has(input.toLowerCase());
        }
        handleColor(color) {
            return this.#parseString(color.value);
        }
        handleRangeColor(color) {
            return this.#parseString(color.value);
        }
        parseString(input) {
            return this.#parseString(input);
        }
        #parseString(input) {
            if (!input || typeof input !== "string") {
                return undefined;
            }
            const rgbColor = namedColors.get(input.toLowerCase());
            if (!rgbColor) {
                getLogger().error("Color not found", input);
                return undefined;
            }
            return { ...rgbColor, a: 1 };
        }
    }

    async function loadNamedColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("named", new NamedColorManager());
        });
    }

    const OKLAB_LMS$1 = {
        l: { L: 1, a: 0.3963377774, b: 0.2158037573 },
        m: { L: 1, a: -0.1055613458, b: -0.0638541728 },
        s: { L: 1, a: -0.0894841775, b: -1.291485548 },
    }, LMS_TO_LINEAR_RGB$1 = {
        r: { l: 4.0767416621, m: -3.3077115913, s: 0.2309699292 },
        g: { l: -1.2684380046, m: 2.6097574011, s: -0.3413193965 },
        b: { l: -0.0041960863, m: -0.7034186147, s: 1.707614701 },
    }, SRGB$1 = {
        GAMMA: 2.4,
        LINEAR_THRESHOLD: 0.0031308,
        LINEAR_SCALE: 12.92,
        OFFSET: 0.055,
        SCALE: 1.055,
    }, minSrgbValue$1 = 0, maxSrgbValue$1 = 1;
    function oklabToRgb(oklab) {
        const L = oklab.l / percentDenominator, a = oklab.aAxis, b = oklab.bAxis, l_ = OKLAB_LMS$1.l.L * L + OKLAB_LMS$1.l.a * a + OKLAB_LMS$1.l.b * b, m_ = OKLAB_LMS$1.m.L * L + OKLAB_LMS$1.m.a * a + OKLAB_LMS$1.m.b * b, s_ = OKLAB_LMS$1.s.L * L + OKLAB_LMS$1.s.a * a + OKLAB_LMS$1.s.b * b, cubic = 3, l = l_ ** cubic, m = m_ ** cubic, s = s_ ** cubic, rLinear = LMS_TO_LINEAR_RGB$1.r.l * l + LMS_TO_LINEAR_RGB$1.r.m * m + LMS_TO_LINEAR_RGB$1.r.s * s, gLinear = LMS_TO_LINEAR_RGB$1.g.l * l + LMS_TO_LINEAR_RGB$1.g.m * m + LMS_TO_LINEAR_RGB$1.g.s * s, bLinear = LMS_TO_LINEAR_RGB$1.b.l * l + LMS_TO_LINEAR_RGB$1.b.m * m + LMS_TO_LINEAR_RGB$1.b.s * s, toSrgb = (x) => x <= SRGB$1.LINEAR_THRESHOLD
            ? SRGB$1.LINEAR_SCALE * x
            : SRGB$1.SCALE * Math.pow(x, inverseFactorNumerator / SRGB$1.GAMMA) - SRGB$1.OFFSET, toSrgbFixed = num => Math.round(clamp(toSrgb(num), minSrgbValue$1, maxSrgbValue$1) * rgbMax);
        return {
            r: toSrgbFixed(rLinear),
            g: toSrgbFixed(gLinear),
            b: toSrgbFixed(bLinear),
        };
    }
    function oklabaToRgba(oklaba) {
        return {
            a: oklaba.a,
            ...oklabToRgb(oklaba),
        };
    }

    const oklabRegex = /oklab\(\s*(\d+(?:\.\d+)?)(%?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)(?:\s*\/\s*(0|1|0?\.\d+|\d{1,3}%))?\s*\)/i;
    class OklabColorManager {
        accepts(input) {
            return input.startsWith("oklab");
        }
        handleColor(color) {
            const colorValue = color.value, oklabColor = colorValue.oklab ?? color.value;
            if (!("l" in oklabColor) || !("aAxis" in oklabColor) || !("bAxis" in oklabColor)) {
                return;
            }
            return oklabToRgb(oklabColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, oklabColor = colorValue.oklab ?? color.value;
            if (!("l" in oklabColor) || !("aAxis" in oklabColor) || !("bAxis" in oklabColor)) {
                return;
            }
            return oklabToRgb({
                l: getRangeValue(oklabColor.l),
                aAxis: getRangeValue(oklabColor.aAxis),
                bAxis: getRangeValue(oklabColor.bAxis),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = oklabRegex.exec(input), indexes = {
                l: 1,
                lPercent: 2,
                aAxis: 3,
                bAxis: 4,
                a: 5,
            }, defaultAlpha = 1;
            if (!result) {
                return undefined;
            }
            const rawL = parseFloat(result[indexes.l] ?? "0");
            if (result[indexes.lPercent]) {
                if (rawL < none || rawL > percentDenominator) {
                    return undefined;
                }
            }
            else {
                if (rawL < none || rawL > identity$3) {
                    return undefined;
                }
            }
            return oklabaToRgba({
                a: result[indexes.a] ? parseAlpha(result[indexes.a]) : defaultAlpha,
                l: rawL * (result[indexes.lPercent] ? identity$3 : percentDenominator),
                aAxis: parseFloat(result[indexes.aAxis] ?? "0"),
                bAxis: parseFloat(result[indexes.bAxis] ?? "0"),
            });
        }
    }

    async function loadOklabColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("oklab", new OklabColorManager());
        });
    }

    const OKLAB_LMS = {
        l: { L: 1, a: 0.3963377774, b: 0.2158037573 },
        m: { L: 1, a: -0.1055613458, b: -0.0638541728 },
        s: { L: 1, a: -0.0894841775, b: -1.291485548 },
    }, LMS_TO_LINEAR_RGB = {
        r: { l: 4.0767416621, m: -3.3077115913, s: 0.2309699292 },
        g: { l: -1.2684380046, m: 2.6097574011, s: -0.3413193965 },
        b: { l: -0.0041960863, m: -0.7034186147, s: 1.707614701 },
    }, SRGB = {
        GAMMA: 2.4,
        LINEAR_THRESHOLD: 0.0031308,
        LINEAR_SCALE: 12.92,
        SCALE: 1.055,
        OFFSET: 0.055,
    }, minSrgbValue = 0, maxSrgbValue = 1;
    function oklchToRgb(oklch) {
        const L = oklch.l / percentDenominator, C = oklch.c, hRad = degToRad(oklch.h), a = C * Math.cos(hRad), b = C * Math.sin(hRad), l_ = OKLAB_LMS.l.L * L + OKLAB_LMS.l.a * a + OKLAB_LMS.l.b * b, m_ = OKLAB_LMS.m.L * L + OKLAB_LMS.m.a * a + OKLAB_LMS.m.b * b, s_ = OKLAB_LMS.s.L * L + OKLAB_LMS.s.a * a + OKLAB_LMS.s.b * b, cubic = 3, l = l_ ** cubic, m = m_ ** cubic, s = s_ ** cubic, rLinear = LMS_TO_LINEAR_RGB.r.l * l + LMS_TO_LINEAR_RGB.r.m * m + LMS_TO_LINEAR_RGB.r.s * s, gLinear = LMS_TO_LINEAR_RGB.g.l * l + LMS_TO_LINEAR_RGB.g.m * m + LMS_TO_LINEAR_RGB.g.s * s, bLinear = LMS_TO_LINEAR_RGB.b.l * l + LMS_TO_LINEAR_RGB.b.m * m + LMS_TO_LINEAR_RGB.b.s * s, toSrgb = (x) => x <= SRGB.LINEAR_THRESHOLD
            ? SRGB.LINEAR_SCALE * x
            : SRGB.SCALE * Math.pow(x, inverseFactorNumerator / SRGB.GAMMA) - SRGB.OFFSET, toSrgbFixed = num => Math.round(clamp(toSrgb(num), minSrgbValue, maxSrgbValue) * rgbMax);
        return {
            r: toSrgbFixed(rLinear),
            g: toSrgbFixed(gLinear),
            b: toSrgbFixed(bLinear),
        };
    }
    function oklchaToRgba(oklcha) {
        return {
            a: oklcha.a,
            ...oklchToRgb(oklcha),
        };
    }

    const oklchRegex = /oklch\(\s*(\d+(?:\.\d+)?)(%?)\s+(\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)(°)?(?:\s*\/\s*(0|1|0?\.\d+|\d{1,3}%))?\s*\)/i;
    class OklchColorManager {
        accepts(input) {
            return input.startsWith("oklch");
        }
        handleColor(color) {
            const colorValue = color.value, oklchColor = colorValue.oklch ?? color.value;
            if (!("l" in oklchColor) || !("c" in oklchColor) || !("h" in oklchColor)) {
                return;
            }
            return oklchToRgb(oklchColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, oklchColor = colorValue.oklch ?? color.value;
            if (!("l" in oklchColor) || !("c" in oklchColor) || !("h" in oklchColor)) {
                return;
            }
            return oklchToRgb({
                l: getRangeValue(oklchColor.l),
                c: getRangeValue(oklchColor.c),
                h: getRangeValue(oklchColor.h),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = oklchRegex.exec(input), indexes = {
                l: 1,
                lPercent: 2,
                c: 3,
                h: 4,
                a: 6,
            }, defaultAlpha = 1;
            if (!result) {
                return undefined;
            }
            const rawL = parseFloat(result[indexes.l] ?? "0");
            if (result[indexes.lPercent]) {
                if (rawL < none || rawL > percentDenominator) {
                    return undefined;
                }
            }
            else {
                if (rawL < none || rawL > identity$3) {
                    return undefined;
                }
            }
            return oklchaToRgba({
                a: result[indexes.a] ? parseAlpha(result[indexes.a]) : defaultAlpha,
                c: parseFloat(result[indexes.c] ?? "0"),
                h: parseFloat(result[indexes.h] ?? "0"),
                l: rawL * (result[indexes.lPercent] ? identity$3 : percentDenominator),
            });
        }
    }

    async function loadOklchColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("oklch", new OklchColorManager());
        });
    }

    class OrbitRotation extends ValueWithRandom {
        value = 45;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
        }
    }

    class Orbit {
        animation = new AnimationOptions();
        color;
        enable = false;
        opacity = 1;
        radius;
        rotation = new OrbitRotation();
        width = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.animation.load(data.animation);
            this.rotation.load(data.rotation);
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "opacity", data.opacity);
            loadRangeProperty(this, "width", data.width);
            loadRangeProperty(this, "radius", data.radius);
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
        }
    }

    var OrbitType;
    (function (OrbitType) {
        OrbitType["front"] = "front";
        OrbitType["back"] = "back";
    })(OrbitType || (OrbitType = {}));

    const minWidth$3 = 0;
    function drawEllipse(container, context, particle, fillColorValue, radius, opacity, width, rotation, start, end) {
        if (width <= minWidth$3) {
            return;
        }
        const pos = particle.getPosition();
        if (fillColorValue) {
            context.strokeStyle = getStyleFromHsl(fillColorValue, container.hdr, opacity, container.peakNits, container.hdrMode);
        }
        context.lineWidth = width;
        const rotationRadian = degToRad(rotation);
        context.beginPath();
        context.ellipse(pos.x, pos.y, radius * half$2, radius * double, rotationRadian, start, end);
        context.stroke();
    }

    const defaultOrbitSpeed = 0, halfPI$1 = Math.PI * half$2, piAndAHalf = Math.PI + halfPI$1, startAngle = 0, defaultWidth$1 = 1, defaultRotation$1 = 0;
    class OrbitUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        afterDraw(particle) {
            const orbitOptions = particle.options.orbit;
            if (orbitOptions?.enable) {
                this.drawOrbit(particle, OrbitType.front);
            }
        }
        beforeDraw(particle) {
            const orbitOptions = particle.options.orbit;
            if (orbitOptions?.enable) {
                this.drawOrbit(particle, OrbitType.back);
            }
        }
        drawOrbit(particle, type) {
            const container = this.#container;
            let start, end;
            switch (type) {
                case OrbitType.back:
                    start = halfPI$1;
                    end = piAndAHalf;
                    break;
                case OrbitType.front:
                    start = piAndAHalf;
                    end = halfPI$1;
                    break;
                default:
                    start = startAngle;
                    end = doublePI;
            }
            container.canvas.render.draw(ctx => {
                drawEllipse(container, ctx, particle, particle.orbitColor ?? particle.getFillColor(), particle.retina.orbitRadius ?? container.retina.orbitRadius ?? particle.getRadius(), particle.orbitOpacity ?? defaultOpacity$3, particle.orbitWidth ?? defaultWidth$1, (particle.orbitRotation ?? defaultRotation$1) * container.retina.pixelRatio, start, end);
            });
        }
        init(particle) {
            const container = this.#container, particlesOptions = particle.options, orbitOptions = particlesOptions.orbit;
            if (!orbitOptions?.enable) {
                return;
            }
            particle.orbitRotation = getRangeValue(orbitOptions.rotation.value);
            particle.orbitColor = rangeColorToHsl(this.#pluginManager, orbitOptions.color);
            particle.retina.orbitRadius =
                orbitOptions.radius !== undefined ? getRangeValue(orbitOptions.radius) * container.retina.pixelRatio : undefined;
            container.retina.orbitRadius = particle.retina.orbitRadius;
            particle.orbitAnimationSpeed = orbitOptions.animation.enable
                ? getRangeValue(orbitOptions.animation.speed)
                : defaultOrbitSpeed;
            particle.orbitWidth = getRangeValue(orbitOptions.width);
            particle.orbitOpacity = getRangeValue(orbitOptions.opacity);
        }
        isEnabled(particle) {
            const orbitAnimations = particle.options.orbit?.animation;
            return !particle.destroyed && !particle.spawning && !!orbitAnimations?.enable;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "orbit", Orbit, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            particle.orbitRotation ??= defaultRotation$1;
            particle.orbitRotation += (particle.orbitAnimationSpeed ?? defaultOrbitSpeed / doublePI) * delta.factor;
        }
    }

    async function loadOrbitUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("orbit", container => {
                return Promise.resolve(new OrbitUpdater(e.pluginManager, container));
            });
        });
    }

    const minSpawnRate = 0, defaultSpawnRate = 1, defaultSpawnQuantity = 1;
    class ParticlesDrawer {
        #container;
        constructor(container) {
            this.#container = container;
        }
        drawAfter(data) {
            const { particle } = data, container = this.#container;
            if (!particle.particlesNextSpawn) {
                return;
            }
            const currentTime = performance.now();
            if (currentTime < particle.particlesNextSpawn) {
                return;
            }
            particle.particlesNextSpawn =
                currentTime + (particle.particlesSpawnRate ?? defaultSpawnRate * millisecondsToSeconds$1);
            const quantity = particle.particlesSpawnQuantity ?? defaultSpawnQuantity, pOptions = deepExtend({}, particle.particlesData?.spawn?.particles), pos = { ...particle.getPosition() };
            for (let i = 0; i < quantity; i++) {
                container.particles.addParticle(pos, pOptions);
            }
        }
        particleInit(_container, particle) {
            const effectData = particle.effectData, spawnRate = getRangeValue(effectData?.spawn?.rate?.delay ?? defaultSpawnRate);
            particle.particlesSpawnQuantity = getRangeValue(effectData?.spawn?.rate?.quantity ?? defaultSpawnQuantity);
            particle.particlesSpawnRate = (spawnRate > minSpawnRate ? spawnRate : defaultSpawnRate) * millisecondsToSeconds$1;
            particle.particlesNextSpawn = performance.now() + particle.particlesSpawnRate;
            particle.particlesData = effectData;
        }
    }

    async function loadParticlesEffect(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addEffect("particles", container => {
                return Promise.resolve(new ParticlesDrawer(container));
            });
        });
    }

    class ParticlesRepulse extends ValueWithRandom {
        distance = 1;
        duration = 1;
        enabled = false;
        factor = 1;
        speed = 1;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enabled", data.enabled);
            loadRangeProperty(this, "distance", data.distance);
            loadRangeProperty(this, "duration", data.duration);
            loadRangeProperty(this, "factor", data.factor);
            loadRangeProperty(this, "speed", data.speed);
        }
    }

    class Repulser extends ParticlesInteractorBase {
        #maxDistance;
        #normVec;
        #velocityVec;
        constructor(container) {
            super(container);
            this.#maxDistance = 0;
            this.#normVec = Vector.origin;
            this.#velocityVec = Vector.origin;
        }
        get maxDistance() {
            return this.#maxDistance;
        }
        clear() {
        }
        init() {
        }
        interact(p1) {
            const container = this.container;
            if (!p1.repulse) {
                const repulseOpt1 = p1.options.repulse;
                if (!repulseOpt1) {
                    return;
                }
                const repulseDistance = getRangeValue(repulseOpt1.distance);
                if (repulseDistance > this.maxDistance) {
                    this.#maxDistance = repulseDistance;
                }
                p1.repulse = {
                    distance: repulseDistance * container.retina.pixelRatio,
                    speed: getRangeValue(repulseOpt1.speed),
                    factor: getRangeValue(repulseOpt1.factor),
                };
            }
            const pos1 = p1.getPosition(), query = container.particles.grid.queryCircle(pos1, p1.repulse.distance), p1DistanceFactor = identity$3 / p1.repulse.distance;
            for (const p2 of query) {
                if (p1 === p2 || p2.destroyed) {
                    continue;
                }
                const pos2 = p2.getPosition(), { dx, dy, distance } = getDistances(pos2, pos1), distanceFactor = identity$3 / distance, velocity = p1.repulse.speed * p1.repulse.factor;
                if (distance > minDistance$7) {
                    const repulseFactor = clamp((identity$3 - Math.pow(distance * p1DistanceFactor, squareExp)) * velocity, minVelocity, velocity) *
                        distanceFactor;
                    this.#normVec.x = dx * repulseFactor;
                    this.#normVec.y = dy * repulseFactor;
                    p2.position.addTo(this.#normVec);
                }
                else {
                    this.#velocityVec.x = velocity;
                    this.#velocityVec.y = velocity;
                    p2.position.addTo(this.#velocityVec);
                }
            }
        }
        isEnabled(particle) {
            return particle.options.repulse?.enabled ?? false;
        }
        loadParticlesOptions(options, ...sources) {
            loadOptionProperty(options, "repulse", ParticlesRepulse, ...sources);
        }
        reset() {
        }
    }

    async function loadParticlesRepulseInteraction(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureInteractivityPluginLoaded(e);
            e.pluginManager.addInteractor?.("particlesRepulse", container => {
                return Promise.resolve(new Repulser(container));
            });
        });
    }

    class PathDrawer {
        draw(data) {
            const { context, particle, radius } = data;
            if (!particle.pathData) {
                return;
            }
            drawPath(context, radius, particle.pathData);
        }
        particleInit(_container, particle) {
            const shape = particle.shapeData;
            if (!shape) {
                return;
            }
            particle.pathData = deepExtend({}, shape);
        }
    }

    async function loadPathShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["path"], () => Promise.resolve(new PathDrawer()));
        });
    }

    class Grad {
        w;
        x;
        y;
        z;
        constructor(x, y, z, w) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.w = w;
        }
        dot2(x, y) {
            return this.x * x + this.y * y;
        }
        dot3(x, y, z) {
            return this.dot2(x, y) + this.z * z;
        }
        dot4(x, y, z, w) {
            return this.dot3(x, y, z) + this.w * w;
        }
    }

    class PerlinNoise {
        #grad4;
        #gradP;
        #p;
        #perm;
        constructor() {
            this.#grad4 = [
                new Grad(0, 1, 1, 1),
                new Grad(0, 1, 1, -1),
                new Grad(0, 1, -1, 1),
                new Grad(0, 1, -1, -1),
                new Grad(0, -1, 1, 1),
                new Grad(0, -1, 1, -1),
                new Grad(0, -1, -1, 1),
                new Grad(0, -1, -1, -1),
                new Grad(1, 0, 1, 1),
                new Grad(1, 0, 1, -1),
                new Grad(1, 0, -1, 1),
                new Grad(1, 0, -1, -1),
                new Grad(-1, 0, 1, 1),
                new Grad(-1, 0, 1, -1),
                new Grad(-1, 0, -1, 1),
                new Grad(-1, 0, -1, -1),
                new Grad(1, 1, 0, 1),
                new Grad(1, 1, 0, -1),
                new Grad(1, -1, 0, 1),
                new Grad(1, -1, 0, -1),
                new Grad(-1, 1, 0, 1),
                new Grad(-1, 1, 0, -1),
                new Grad(-1, -1, 0, 1),
                new Grad(-1, -1, 0, -1),
                new Grad(1, 1, 1, 0),
                new Grad(1, 1, -1, 0),
                new Grad(1, -1, 1, 0),
                new Grad(1, -1, -1, 0),
                new Grad(-1, 1, 1, 0),
                new Grad(-1, 1, -1, 0),
                new Grad(-1, -1, 1, 0),
                new Grad(-1, -1, -1, 0),
            ];
            this.#p = [
                151,
                160,
                137,
                91,
                90,
                15,
                131,
                13,
                201,
                95,
                96,
                53,
                194,
                233,
                7,
                225,
                140,
                36,
                103,
                30,
                69,
                142,
                8,
                99,
                37,
                240,
                21,
                10,
                23,
                190,
                6,
                148,
                247,
                120,
                234,
                75,
                0,
                26,
                197,
                62,
                94,
                252,
                219,
                203,
                117,
                35,
                11,
                32,
                57,
                177,
                33,
                88,
                237,
                149,
                56,
                87,
                174,
                20,
                125,
                136,
                171,
                168,
                68,
                175,
                74,
                165,
                71,
                134,
                139,
                48,
                27,
                166,
                77,
                146,
                158,
                231,
                83,
                111,
                229,
                122,
                60,
                211,
                133,
                230,
                220,
                105,
                92,
                41,
                55,
                46,
                245,
                40,
                244,
                102,
                143,
                54,
                65,
                25,
                63,
                161,
                1,
                216,
                80,
                73,
                209,
                76,
                132,
                187,
                208,
                89,
                18,
                169,
                200,
                196,
                135,
                130,
                116,
                188,
                159,
                86,
                164,
                100,
                109,
                198,
                173,
                186,
                3,
                64,
                52,
                217,
                226,
                250,
                124,
                123,
                5,
                202,
                38,
                147,
                118,
                126,
                255,
                82,
                85,
                212,
                207,
                206,
                59,
                227,
                47,
                16,
                58,
                17,
                182,
                189,
                28,
                42,
                223,
                183,
                170,
                213,
                119,
                248,
                152,
                2,
                44,
                154,
                163,
                70,
                221,
                153,
                101,
                155,
                167,
                43,
                172,
                9,
                129,
                22,
                39,
                253,
                19,
                98,
                108,
                110,
                79,
                113,
                224,
                232,
                178,
                185,
                112,
                104,
                218,
                246,
                97,
                228,
                251,
                34,
                242,
                193,
                238,
                210,
                144,
                12,
                191,
                179,
                162,
                241,
                81,
                51,
                145,
                235,
                249,
                14,
                239,
                107,
                49,
                192,
                214,
                31,
                181,
                199,
                106,
                157,
                184,
                84,
                204,
                176,
                115,
                121,
                50,
                45,
                127,
                4,
                150,
                254,
                138,
                236,
                205,
                93,
                222,
                114,
                67,
                29,
                24,
                72,
                243,
                141,
                128,
                195,
                78,
                66,
                215,
                61,
                156,
                180,
            ];
            this.#gradP = new Array(512);
            this.#perm = new Array(512);
        }
        noise2d(x, y) {
            const gradP = this.#gradP, perm = this.#perm;
            let X = Math.floor(x), Y = Math.floor(y);
            x -= X;
            y -= Y;
            X &= 255;
            Y &= 255;
            const n00 = gradP[X + perm[Y]].dot2(x, y), n01 = gradP[X + perm[Y + 1]].dot2(x, y - 1), n10 = gradP[X + 1 + perm[Y]].dot2(x - 1, y), n11 = gradP[X + 1 + perm[Y + 1]].dot2(x - 1, y - 1), u = this.#fade(x);
            return this.#lerp(this.#lerp(n00, n10, u), this.#lerp(n01, n11, u), this.#fade(y));
        }
        noise3d(x, y, z) {
            const gradP = this.#gradP, perm = this.#perm;
            let X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z);
            x = x - X;
            y = y - Y;
            z = z - Z;
            X = X & 255;
            Y = Y & 255;
            Z = Z & 255;
            const n000 = gradP[X + perm[Y + perm[Z]]].dot3(x, y, z), n001 = gradP[X + perm[Y + perm[Z + 1]]].dot3(x, y, z - 1), n010 = gradP[X + perm[Y + 1 + perm[Z]]].dot3(x, y - 1, z), n011 = gradP[X + perm[Y + 1 + perm[Z + 1]]].dot3(x, y - 1, z - 1), n100 = gradP[X + 1 + perm[Y + perm[Z]]].dot3(x - 1, y, z), n101 = gradP[X + 1 + perm[Y + perm[Z + 1]]].dot3(x - 1, y, z - 1), n110 = gradP[X + 1 + perm[Y + 1 + perm[Z]]].dot3(x - 1, y - 1, z), n111 = gradP[X + 1 + perm[Y + 1 + perm[Z + 1]]].dot3(x - 1, y - 1, z - 1), u = this.#fade(x), v = this.#fade(y), w = this.#fade(z);
            return this.#lerp(this.#lerp(this.#lerp(n000, n100, u), this.#lerp(n001, n101, u), w), this.#lerp(this.#lerp(n010, n110, u), this.#lerp(n011, n111, u), w), v);
        }
        noise4d(x, y, z, w) {
            const gradP = this.#gradP, perm = this.#perm;
            let X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z), W = Math.floor(w);
            x -= X;
            y -= Y;
            z -= Z;
            w -= W;
            X &= 255;
            Y &= 255;
            Z &= 255;
            W &= 255;
            const u = this.#fade(x), v = this.#fade(y), s = this.#fade(z), t = this.#fade(w), gi = (i, j, k, l) => gradP[X + i + perm[Y + j + perm[Z + k + perm[W + l]]]], n0000 = gi(0, 0, 0, 0).dot4(x, y, z, w), n0001 = gi(0, 0, 0, 1).dot4(x, y, z, w - 1), n0010 = gi(0, 0, 1, 0).dot4(x, y, z - 1, w), n0011 = gi(0, 0, 1, 1).dot4(x, y, z - 1, w - 1), n0100 = gi(0, 1, 0, 0).dot4(x, y - 1, z, w), n0101 = gi(0, 1, 0, 1).dot4(x, y - 1, z, w - 1), n0110 = gi(0, 1, 1, 0).dot4(x, y - 1, z - 1, w), n0111 = gi(0, 1, 1, 1).dot4(x, y - 1, z - 1, w - 1), n1000 = gi(1, 0, 0, 0).dot4(x - 1, y, z, w), n1001 = gi(1, 0, 0, 1).dot4(x - 1, y, z, w - 1), n1010 = gi(1, 0, 1, 0).dot4(x - 1, y, z - 1, w), n1011 = gi(1, 0, 1, 1).dot4(x - 1, y, z - 1, w - 1), n1100 = gi(1, 1, 0, 0).dot4(x - 1, y - 1, z, w), n1101 = gi(1, 1, 0, 1).dot4(x - 1, y - 1, z, w - 1), n1110 = gi(1, 1, 1, 0).dot4(x - 1, y - 1, z - 1, w), n1111 = gi(1, 1, 1, 1).dot4(x - 1, y - 1, z - 1, w - 1), x00 = this.#lerp(n0000, n1000, u), x01 = this.#lerp(n0001, n1001, u), x10 = this.#lerp(n0010, n1010, u), x11 = this.#lerp(n0011, n1011, u), y00 = this.#lerp(x00, x10, s), y01 = this.#lerp(x01, x11, s), x20 = this.#lerp(n0100, n1100, u), x21 = this.#lerp(n0101, n1101, u), x30 = this.#lerp(n0110, n1110, u), x31 = this.#lerp(n0111, n1111, u), y10 = this.#lerp(x20, x30, s), y11 = this.#lerp(x21, x31, s), z0 = this.#lerp(y00, y10, v), z1 = this.#lerp(y01, y11, v);
            return this.#lerp(z0, z1, t);
        }
        seed(inputSeed) {
            const grad4 = this.#grad4, gradP = this.#gradP, perm = this.#perm, p = this.#p;
            let seed = inputSeed;
            if (seed > 0 && seed < 1) {
                seed *= 65536;
            }
            seed = Math.floor(seed);
            if (seed < 256) {
                seed |= seed << 8;
            }
            const grad4Length = grad4.length;
            for (let i = 0; i < 256; i++) {
                const v = i & 1 ? p[i] ^ (seed & 255) : p[i] ^ ((seed >> 8) & 255);
                perm[i] = perm[i + 256] = v;
                gradP[i] = gradP[i + 256] = grad4[v % grad4Length];
            }
        }
        #fade(t) {
            return t * t * t * (t * (t * 6 - 15) + 10);
        }
        #lerp(a, b, t) {
            return (1 - t) * a + t * b;
        }
    }

    class PerlinNoiseGenerator extends NoiseFieldGenerator {
        constructor(container) {
            const perlinNoise = new PerlinNoise();
            super(container, {
                noise4d: (x, y, z, w) => perlinNoise.noise4d(x, y, z, w),
                seed: seed => {
                    perlinNoise.seed(seed);
                },
            });
        }
    }

    const perlinNoisePathName = "perlinNoise";
    async function loadPerlinNoisePath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(perlinNoisePathName, container => {
                return Promise.resolve(new PerlinNoiseGenerator(container));
            });
        });
    }

    class Poisson {
        dimensions = 2;
        enable = false;
        radius = 0;
        retries = 30;
        steps = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "dimensions", data.dimensions);
            loadProperty(this, "radius", data.radius);
            loadProperty(this, "retries", data.retries);
        }
    }

    class PoissonDiscPlugin {
        id = "poisson";
        async getPlugin(container) {
            const { PoissonDiscPluginInstance } = await Promise.resolve().then(function () { return PoissonDiscPluginInstance$1; });
            return new PoissonDiscPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let poissonOptions = options.poisson;
            if (poissonOptions?.load === undefined) {
                options.poisson = poissonOptions = new Poisson();
            }
            poissonOptions.load(source?.poisson);
        }
        needsPlugin(options) {
            return options?.poisson?.enable ?? false;
        }
    }

    async function loadPoissonDiscPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new PoissonDiscPlugin());
        });
    }

    class PolygonMaskDrawStroke {
        color = new OptionsColor();
        opacity = 1;
        width = 0.5;
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.color = OptionsColor.create(this.color, data.color);
            if (isString(this.color.value)) {
                this.opacity = stringToAlpha(this.#pluginManager, this.color.value) ?? this.opacity;
            }
            loadProperty(this, "opacity", data.opacity);
            loadProperty(this, "width", data.width);
        }
    }

    class PolygonMaskDraw {
        enable = false;
        stroke;
        constructor(pluginManager) {
            this.stroke = new PolygonMaskDrawStroke(pluginManager);
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            const stroke = data.stroke;
            this.stroke.load(stroke);
        }
    }

    var PolygonMaskInlineArrangement;
    (function (PolygonMaskInlineArrangement) {
        PolygonMaskInlineArrangement["equidistant"] = "equidistant";
        PolygonMaskInlineArrangement["onePerPoint"] = "one-per-point";
        PolygonMaskInlineArrangement["perPoint"] = "per-point";
        PolygonMaskInlineArrangement["randomLength"] = "random-length";
        PolygonMaskInlineArrangement["randomPoint"] = "random-point";
    })(PolygonMaskInlineArrangement || (PolygonMaskInlineArrangement = {}));

    class PolygonMaskInline {
        arrangement;
        constructor() {
            this.arrangement = PolygonMaskInlineArrangement.onePerPoint;
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "arrangement", data.arrangement);
        }
    }

    class PolygonMaskLocalSvg {
        path = [];
        size;
        constructor() {
            this.size = {
                height: 0,
                width: 0,
            };
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "path", data.path);
            if (data.size !== undefined) {
                if (data.size.width !== undefined) {
                    this.size.width = data.size.width;
                }
                if (data.size.height !== undefined) {
                    this.size.height = data.size.height;
                }
            }
        }
    }

    var PolygonMaskMoveType;
    (function (PolygonMaskMoveType) {
        PolygonMaskMoveType["path"] = "path";
        PolygonMaskMoveType["radius"] = "radius";
    })(PolygonMaskMoveType || (PolygonMaskMoveType = {}));

    class PolygonMaskMove {
        radius = 10;
        type = PolygonMaskMoveType.path;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "radius", data.radius);
            loadProperty(this, "type", data.type);
        }
    }

    var PolygonMaskType;
    (function (PolygonMaskType) {
        PolygonMaskType["inline"] = "inline";
        PolygonMaskType["inside"] = "inside";
        PolygonMaskType["outside"] = "outside";
        PolygonMaskType["none"] = "none";
    })(PolygonMaskType || (PolygonMaskType = {}));

    class PolygonMask {
        data;
        draw;
        enable = false;
        inline = new PolygonMaskInline();
        move = new PolygonMaskMove();
        position;
        scale = 1;
        type = PolygonMaskType.none;
        url;
        constructor(pluginManager) {
            this.draw = new PolygonMaskDraw(pluginManager);
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.draw.load(data.draw);
            this.inline.load(data.inline);
            this.move.load(data.move);
            loadProperty(this, "scale", data.scale);
            loadProperty(this, "type", data.type);
            if (data.enable !== undefined) {
                this.enable = data.enable;
            }
            else {
                this.enable = this.type !== PolygonMaskType.none;
            }
            loadProperty(this, "url", data.url);
            if (data.data !== undefined) {
                if (isString(data.data)) {
                    this.data = data.data;
                }
                else {
                    this.data = new PolygonMaskLocalSvg();
                    this.data.load(data.data);
                }
            }
            if (data.position !== undefined) {
                this.position = deepExtend({}, data.position);
            }
        }
    }

    class PolygonMaskPlugin {
        id = "polygon-mask";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { PolygonMaskInstance } = await Promise.resolve().then(function () { return PolygonMaskInstance$1; });
            return new PolygonMaskInstance(this.#pluginManager, container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let polygonOptions = options.polygon;
            if (polygonOptions?.load === undefined) {
                options.polygon = polygonOptions = new PolygonMask(this.#pluginManager);
            }
            polygonOptions.load(source?.polygon);
        }
        needsPlugin(options) {
            return (options?.polygon?.enable ??
                (options?.polygon?.type !== undefined && options.polygon.type !== PolygonMaskType.none));
        }
    }

    async function loadPolygonMaskPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new PolygonMaskPlugin(e.pluginManager));
        });
    }

    const defaultOptions$2 = {
        sides: 6,
        turnSteps: 20,
        angle: 30,
    };
    class PolygonPathGenerator {
        dirsList;
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.dirsList = [];
            this.options = deepExtend({}, defaultOptions$2);
        }
        generate(p) {
            const { sides, turnSteps } = this.options;
            p.hexStep ??= 0;
            p.hexDirection ??= sides === 6 ? ((getRandom() * 3) | 0) * 2 : (getRandom() * sides) | 0;
            p.hexSpeed ??= p.velocity.length;
            if (p.hexStep % turnSteps === 0) {
                p.hexDirection = getRandom() > 0.5 ? (p.hexDirection + 1) % sides : (p.hexDirection + sides - 1) % sides;
            }
            p.velocity.x = 0;
            p.velocity.y = 0;
            p.hexStep++;
            const direction = this.dirsList[p.hexDirection];
            this.#res.x = direction.x * p.hexSpeed;
            this.#res.y = direction.y * p.hexSpeed;
            return this.#res;
        }
        init() {
            const container = this.#container, sourceOptions = container.actualOptions.particles.move.path.options;
            this.options.sides =
                sourceOptions["sides"] > 0 ? sourceOptions["sides"] : this.options.sides;
            this.options.angle = sourceOptions["angle"] ?? this.options.angle;
            this.options.turnSteps =
                sourceOptions["turnSteps"] >= 0 ? sourceOptions["turnSteps"] : this.options.turnSteps;
            this.#createDirs();
        }
        reset(particle) {
            delete particle.hexStep;
            delete particle.hexDirection;
            delete particle.hexSpeed;
        }
        update() {
        }
        #createDirs() {
            const options = this.options;
            this.dirsList = [];
            for (let i = 0; i < 360; i += 360 / options.sides) {
                const angle = options.angle + i;
                this.dirsList.push(Vector.create(Math.cos((angle * Math.PI) / 180), Math.sin((angle * Math.PI) / 180)));
            }
        }
    }

    const polygonPathName = "polygonPathGenerator";
    async function loadPolygonPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(polygonPathName, container => {
                return Promise.resolve(new PolygonPathGenerator(container));
            });
        });
    }

    const minRandom = -1, maxRandom = 1;
    class RandomPathGenerator {
        #res;
        constructor() {
            this.#res = Vector.origin;
        }
        generate() {
            this.#res.x = getRandomInRange(minRandom, maxRandom);
            this.#res.y = getRandomInRange(minRandom, maxRandom);
            return this.#res;
        }
        init() {
        }
        reset() {
        }
        update() {
        }
    }

    const randomPathName = "randomPathGenerator";
    async function loadRandomPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(randomPathName, () => {
                return Promise.resolve(new RandomPathGenerator());
            });
        });
    }

    var ResponsiveMode;
    (function (ResponsiveMode) {
        ResponsiveMode["screen"] = "screen";
        ResponsiveMode["window"] = "window";
        ResponsiveMode["canvas"] = "canvas";
    })(ResponsiveMode || (ResponsiveMode = {}));

    class Responsive {
        maxWidth = Infinity;
        mode = ResponsiveMode.canvas;
        options = {};
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (!isNull(data.maxWidth)) {
                this.maxWidth = data.maxWidth;
            }
            if (!isNull(data.mode)) {
                if (data.mode === ResponsiveMode.screen) {
                    this.mode = ResponsiveMode.screen;
                }
                else {
                    this.mode = ResponsiveMode.canvas;
                }
            }
            if (!isNull(data.options)) {
                this.options = deepExtend({}, data.options);
            }
        }
    }

    class ResponsivePlugin {
        id = "responsive";
        async getPlugin(container) {
            const { ResponsivePluginInstance } = await Promise.resolve().then(function () { return ResponsivePluginInstance$1; });
            return new ResponsivePluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            const setResponsive = (width, pxRatio, defaultOptions) => {
                options.load(defaultOptions);
                const logicalWidth = width / pxRatio, widthMap = {
                    [ResponsiveMode.screen]: screen.availWidth,
                    [ResponsiveMode.window]: innerWidth,
                    [ResponsiveMode.canvas]: logicalWidth,
                }, responsiveOptions = options.responsive?.find(t => t.maxWidth > widthMap[t.mode]);
                options.load(responsiveOptions?.options);
                return responsiveOptions?.maxWidth;
            };
            options.setResponsive = setResponsive;
            options.responsive ??= [];
            if (source?.responsive !== undefined) {
                for (const responsive of source.responsive) {
                    const optResponsive = new Responsive();
                    if (responsive) {
                        optResponsive.load(responsive);
                    }
                    options.responsive.push(optResponsive);
                }
            }
            options.responsive.sort((a, b) => a.maxWidth - b.maxWidth);
        }
        needsPlugin(options) {
            return !!options?.responsive?.length;
        }
    }

    async function loadResponsivePlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ResponsivePlugin());
        });
    }

    const defaultParticleDist = 8, defaultMass = 1, defaultDrag = 0.05, defaultVelocityInherit = 5, defaultOscillationSpeed = 3, defaultOscillationDistance = 40, defaultAngle = 45, defaultPointCount = 30, minPointCount = 4, noPoint = 0, firstPoint = 1, secondPoint = 2, lineWidth = 1, randomTimeFactor = 100, degrees = 180, fixedDurationFrames = 50, fixedDuration = firstPoint / fixedDurationFrames, millisecondsToSeconds = 1000, minDelta = 1e-6, maxVelocityInherit = 800, noDistance = 0, half = 0.5;
    function setRibbonBounds(particle, width, height) {
        particle.ribbonBounds = Vector.create(width, height);
    }
    function getMass(particle) {
        return particle.ribbonMass ?? defaultMass;
    }
    function getDrag(particle) {
        return particle.ribbonDrag ?? defaultDrag;
    }
    function getVelocityInherit(particle) {
        return particle.ribbonVelocityInherit ?? defaultVelocityInherit;
    }
    function getParticleDist(particle) {
        return particle.ribbonParticleDist ?? defaultParticleDist;
    }
    function getOscillationSpeed(particle) {
        return particle.ribbonOscillationSpeed ?? defaultOscillationSpeed;
    }
    function getOscillationDistance(particle) {
        return particle.ribbonOscillationDistance ?? defaultOscillationDistance;
    }
    function getHead(particle) {
        particle.ribbonHead ??= Vector.create(particle.position.x, particle.position.y);
        return particle.ribbonHead;
    }
    function getPreviousHead(particle) {
        particle.ribbonPreviousHead ??= Vector.create(particle.position.x, particle.position.y);
        return particle.ribbonPreviousHead;
    }
    function createRibbonState(particle) {
        const shapeData = particle.shapeData, count = Math.max(minPointCount, Math.round(getRangeValue(shapeData?.count ?? defaultPointCount))), particleDist = getRangeValue(shapeData?.particleDist ?? defaultParticleDist), mass = getRangeValue(shapeData?.mass ?? defaultMass), drag = getRangeValue(shapeData?.drag ?? defaultDrag), velocityInherit = getRangeValue(shapeData?.velocityInherit ?? defaultVelocityInherit), oscillationSpeed = getRangeValue(shapeData?.oscillationSpeed ?? defaultOscillationSpeed), oscillationDistance = getRangeValue(shapeData?.oscillationDistance ?? defaultOscillationDistance), angle = getRangeValue(shapeData?.angle ?? defaultAngle), angleRad = (Math.PI / degrees) * angle, head = Vector.create(particle.position.x, particle.position.y), bounds = particle.ribbonBounds;
        if (!bounds) {
            return;
        }
        particle.ribbonParticleDist = particleDist;
        particle.ribbonMass = mass;
        particle.ribbonDrag = drag;
        particle.ribbonVelocityInherit = velocityInherit;
        particle.ribbonOscillationSpeed = oscillationSpeed;
        particle.ribbonOscillationDistance = oscillationDistance;
        particle.ribbonTime = getRandom() * randomTimeFactor;
        particle.ribbonOffsets = Vector.create(Math.cos(angleRad), Math.sin(angleRad));
        particle.ribbonHead = head;
        particle.ribbonPreviousHead = Vector.create(head.x, head.y);
        particle.ribbonPreviousPosition = Vector.create(particle.position.x, particle.position.y);
        const trailAngle = particle.velocity.angle + Math.PI, noiseScale = particleDist * half;
        particle.ribbonPoints = new Array(count);
        for (let i = noPoint; i < count; i++) {
            const offset = i * particleDist, perpNoise = (getRandom() - half) * noiseScale, perpAngle = trailAngle + Math.PI * half;
            particle.ribbonPoints[i] = {
                force: Vector.origin,
                position: Vector.create(head.x + Math.cos(trailAngle) * offset + Math.cos(perpAngle) * perpNoise, head.y + Math.sin(trailAngle) * offset + Math.sin(perpAngle) * perpNoise),
                velocity: Vector.origin,
            };
        }
    }
    function resetRibbonState(particle) {
        const points = particle.ribbonPoints, bounds = particle.ribbonBounds, width = bounds?.x ?? noDistance, height = bounds?.y ?? noDistance, position = Vector.create(getRandom() * width, -getRandom() * height);
        if (!bounds) {
            return;
        }
        if (!points?.length) {
            createRibbonState(particle);
            return;
        }
        particle.position.x = position.x;
        particle.position.y = position.y;
        particle.ribbonHead = Vector.create(position.x, position.y);
        particle.ribbonPreviousHead = Vector.create(position.x, position.y);
        particle.ribbonPreviousPosition = Vector.create(position.x, position.y);
        particle.ribbonTime = getRandom() * randomTimeFactor;
        for (let i = noPoint; i < points.length; i++) {
            const point = points[i];
            if (!point) {
                continue;
            }
            point.position = Vector.create(position.x, position.y - i * getParticleDist(particle));
            point.force = Vector.origin;
            point.velocity = Vector.origin;
        }
    }
    function addPointForce(particle, index, force) {
        const point = particle.ribbonPoints?.[index];
        if (!point) {
            return;
        }
        point.force.addTo(force);
    }
    function integratePoint(particle, index, dt) {
        const point = particle.ribbonPoints?.[index];
        if (!point) {
            return;
        }
        const mass = getMass(particle), drag = getDrag(particle), totalForce = Vector.create(point.force.x, point.force.y), speed = point.velocity.length, dragVelocity = Vector.create(point.velocity.x, point.velocity.y);
        dragVelocity.multTo(drag * mass * speed);
        totalForce.subFrom(dragVelocity);
        const acceleration = totalForce.div(mass);
        point.position.addTo(point.velocity.mult(dt));
        point.velocity.addTo(acceleration.mult(dt));
        point.force = Vector.origin;
    }
    function updateRibbon(data) {
        const { particle, delta } = data, points = particle.ribbonPoints, offsets = particle.ribbonOffsets, bounds = particle.ribbonBounds;
        if (!points?.length || !offsets || !bounds) {
            return;
        }
        const dt = Math.min(fixedDuration, Math.max(delta.value / millisecondsToSeconds, minDelta)), head = getHead(particle), previousHead = getPreviousHead(particle), velocityInherit = getVelocityInherit(particle), followsParticleMotion = particle.options.move.enable;
        particle.ribbonTime = (particle.ribbonTime ?? noPoint) + dt * getOscillationSpeed(particle);
        if (followsParticleMotion) {
            head.x =
                particle.position.x +
                    (Math.cos(particle.ribbonTime) * getOscillationDistance(particle)) / getOscillationSpeed(particle);
            head.y = particle.position.y;
        }
        else {
            head.x += Math.cos(particle.ribbonTime) * getOscillationDistance(particle) * dt;
        }
        if (particle.justWarped) {
            const trailAngle = particle.velocity.angle + Math.PI, dist = getParticleDist(particle), firstPointObj = points[noPoint];
            if (firstPointObj) {
                firstPointObj.position = Vector.create(head.x, head.y);
                firstPointObj.velocity = Vector.origin;
                firstPointObj.force = Vector.origin;
            }
            for (let i = firstPoint; i < points.length; i++) {
                const point = points[i];
                if (!point) {
                    continue;
                }
                const offset = i * dist;
                point.position = Vector.create(head.x + Math.cos(trailAngle) * offset, head.y + Math.sin(trailAngle) * offset);
                point.velocity = Vector.origin;
                point.force = Vector.origin;
            }
        }
        const particleDist = getParticleDist(particle);
        if (!Number.isFinite(head.x) || !Number.isFinite(head.y)) {
            resetRibbonState(particle);
            return;
        }
        const first = points[noPoint];
        if (!first) {
            return;
        }
        first.position = Vector.create(head.x, head.y);
        const dX = previousHead.x - head.x, dY = previousHead.y - head.y, movement = Math.sqrt(dX * dX + dY * dY), velocityFactor = Math.min((movement / dt) * velocityInherit, maxVelocityInherit);
        particle.ribbonPreviousHead = Vector.create(head.x, head.y);
        particle.ribbonPreviousPosition = Vector.create(particle.position.x, particle.position.y);
        for (let i = firstPoint; i < points.length; i++) {
            const point = points[i], previousPoint = points[i - firstPoint];
            if (!point || !previousPoint) {
                continue;
            }
            const direction = previousPoint.position.sub(point.position).copy();
            direction.normalize();
            direction.multTo(velocityFactor);
            addPointForce(particle, i, direction);
        }
        for (let i = firstPoint; i < points.length; i++) {
            integratePoint(particle, i, dt);
        }
        for (let i = firstPoint; i < points.length; i++) {
            const point = points[i], previousPoint = points[i - firstPoint];
            if (!point || !previousPoint) {
                continue;
            }
            const normalized = point.position.sub(previousPoint.position).copy();
            normalized.normalize();
            normalized.multTo(particleDist);
            point.position = previousPoint.position.add(normalized);
            if (!Number.isFinite(point.position.x) ||
                !Number.isFinite(point.position.y) ||
                !Number.isFinite(point.velocity.x) ||
                !Number.isFinite(point.velocity.y)) {
                resetRibbonState(particle);
                return;
            }
        }
    }
    function getSegmentSide(x1, y1, x2, y2, x3, y3) {
        return (x1 - x2) * (y3 - y2) - (y1 - y2) * (x3 - x2);
    }
    function getMidpoint(a, b) {
        return Vector.create((a.x + b.x) * half, (a.y + b.y) * half);
    }
    function drawPolygonSegment(context, drawData) {
        context.beginPath();
        context.moveTo(drawData.a.x, drawData.a.y);
        context.lineTo(drawData.b.x, drawData.b.y);
        context.lineTo(drawData.c.x, drawData.c.y);
        if (drawData.d) {
            context.lineTo(drawData.d.x, drawData.d.y);
        }
        context.closePath();
        if (drawData.stroke) {
            context.stroke();
        }
        if (drawData.fill) {
            context.fill();
        }
    }
    function resolveBackFill(hasStroke, frontFill, frontStroke, shapeData, particle, hdr, peakNits, mode) {
        let backFill = hasStroke ? frontStroke : frontFill;
        if (shapeData?.backColor) {
            backFill = shapeData.backColor;
        }
        else if (shapeData?.darken?.enable) {
            const frontHsl = getHslFromAnimation(particle.fillColor);
            if (frontHsl) {
                const altered = alterHsl(frontHsl, exports.AlterType.darken, getRangeValue(shapeData.darken.value));
                backFill = getStyleFromHsl(altered, hdr, undefined, peakNits, mode);
            }
        }
        else if (shapeData?.enlighten?.enable) {
            const frontHsl = getHslFromAnimation(particle.fillColor);
            if (frontHsl) {
                const altered = alterHsl(frontHsl, exports.AlterType.enlighten, getRangeValue(shapeData.enlighten.value));
                backFill = getStyleFromHsl(altered, hdr, undefined, peakNits, mode);
            }
        }
        return backFill;
    }
    function drawEdgeSegments(context, currentBase, nextBase, currentSide, nextSide, isFirst, isLast, hasFill, hasStroke) {
        if (isFirst) {
            drawPolygonSegment(context, {
                a: currentBase,
                b: nextBase,
                c: getMidpoint(nextBase, nextSide),
                fill: hasFill,
                stroke: hasStroke,
            });
            drawPolygonSegment(context, {
                a: nextSide,
                b: currentSide,
                c: getMidpoint(nextBase, nextSide),
                fill: hasFill,
                stroke: hasStroke,
            });
        }
        else if (isLast) {
            drawPolygonSegment(context, {
                a: currentBase,
                b: nextBase,
                c: getMidpoint(currentBase, currentSide),
                fill: hasFill,
                stroke: hasStroke,
            });
            drawPolygonSegment(context, {
                a: nextSide,
                b: currentSide,
                c: getMidpoint(currentBase, currentSide),
                fill: hasFill,
                stroke: hasStroke,
            });
        }
        else {
            drawPolygonSegment(context, {
                a: currentBase,
                b: nextBase,
                c: nextSide,
                d: currentSide,
                fill: hasFill,
                stroke: hasStroke,
            });
        }
    }
    function drawRibbon(data, hdr, peakNits, mode) {
        const { context, particle, radius } = data, points = particle.ribbonPoints, offsets = particle.ribbonOffsets, bounds = particle.ribbonBounds, hasFill = data.fill, hasStroke = data.stroke;
        if (!points || !offsets || !bounds || points.length < minPointCount || (!hasFill && !hasStroke)) {
            return;
        }
        const drawOffsets = offsets.mult(radius), center = particle.position, frontFill = typeof context.fillStyle === "string" ? context.fillStyle : "", frontStroke = typeof context.strokeStyle === "string" ? context.strokeStyle : "", shapeData = particle.shapeData, backFill = resolveBackFill(hasStroke, frontFill, frontStroke, shapeData, particle, hdr, peakNits, mode);
        context.lineWidth = lineWidth;
        context.lineJoin = "round";
        context.lineCap = "round";
        for (let i = noPoint; i < points.length - firstPoint; i++) {
            const current = points[i], next = points[i + firstPoint];
            if (!current || !next) {
                continue;
            }
            const currentOffset = current.position.add(drawOffsets), nextOffset = next.position.add(drawOffsets), currentBase = current.position.sub(center), nextBase = next.position.sub(center), currentSide = currentOffset.sub(center), nextSide = nextOffset.sub(center), minY = Math.min(current.position.y, next.position.y, currentOffset.y, nextOffset.y), maxY = Math.max(current.position.y, next.position.y, currentOffset.y, nextOffset.y), isFront = getSegmentSide(current.position.x, current.position.y, next.position.x, next.position.y, nextOffset.x, nextOffset.y) < noDistance, segmentStyle = isFront ? frontFill : backFill;
            if (minY > bounds.y + drawOffsets.length || maxY < -drawOffsets.length) {
                continue;
            }
            context.fillStyle = segmentStyle;
            if (hasStroke) {
                context.strokeStyle = segmentStyle;
            }
            if (i === noPoint) {
                drawEdgeSegments(context, currentBase, nextBase, currentSide, nextSide, true, false, hasFill, hasStroke);
            }
            else if (i === points.length - secondPoint) {
                drawEdgeSegments(context, currentBase, nextBase, currentSide, nextSide, false, true, hasFill, hasStroke);
            }
            else {
                drawEdgeSegments(context, currentBase, nextBase, currentSide, nextSide, false, false, hasFill, hasStroke);
            }
        }
        context.fillStyle = frontFill;
        if (hasStroke) {
            context.strokeStyle = frontStroke;
        }
        context.beginPath();
    }

    const defaultSides$1 = 12, defaultRibbonCount = 30, minRibbonCount = 4, sidesMultiplier = 2, minRadius$2 = 0, insideMargin = 0;
    function prepareRibbonParticle(particle, width, height) {
        setRibbonBounds(particle, width, height);
        if (!particle.ribbonPoints?.length) {
            createRibbonState(particle);
        }
    }
    function getRibbonCount(particle) {
        return Math.max(minRibbonCount, Math.round(getRangeValue(particle.shapeData?.count ?? defaultRibbonCount)));
    }
    function isInsideByDirection(data, minX, maxX, minY, maxY, margin) {
        const { canvasSize, direction } = data;
        if (direction === exports.OutModeDirection.bottom) {
            return minY <= canvasSize.height + margin;
        }
        if (direction === exports.OutModeDirection.left) {
            return maxX >= -margin;
        }
        if (direction === exports.OutModeDirection.right) {
            return minX <= canvasSize.width + margin;
        }
        if (direction === exports.OutModeDirection.top) {
            return maxY >= -margin;
        }
        return maxX >= -margin && maxY >= -margin && minX <= canvasSize.width + margin && minY <= canvasSize.height + margin;
    }
    class RibbonDrawer {
        #container;
        constructor(container) {
            this.#container = container;
        }
        draw(data) {
            const bounds = this.#container.canvas.size;
            prepareRibbonParticle(data.particle, bounds.width, bounds.height);
            if (data.particle.ribbonPoints && data.particle.ribbonPoints.length !== getRibbonCount(data.particle)) {
                createRibbonState(data.particle);
            }
            updateRibbon(data);
            drawRibbon(data, this.#container.hdr, this.#container.peakNits, this.#container.hdrMode);
        }
        getSidesCount(particle) {
            const pointsLen = particle.ribbonPoints?.length;
            if (!pointsLen) {
                return defaultSides$1;
            }
            return Math.max(defaultSides$1, pointsLen * sidesMultiplier);
        }
        isInsideCanvas(data) {
            const { outMode, particle, radius } = data, points = particle.ribbonPoints, offsets = particle.ribbonOffsets, position = particle.position, strictBounds = outMode === exports.OutMode.destroy || outMode === exports.OutMode.out, scaledOffsetLen = (offsets?.length ?? minRadius$2) * radius, headRadius = Math.max(radius, scaledOffsetLen);
            if (!strictBounds) {
                return isInsideByDirection(data, position.x - headRadius, position.x + headRadius, position.y - headRadius, position.y + headRadius, insideMargin);
            }
            if (!points?.length || !offsets) {
                return isInsideByDirection(data, position.x - headRadius, position.x + headRadius, position.y - headRadius, position.y + headRadius, insideMargin);
            }
            let minX = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
            for (const point of points) {
                const baseX = point.position.x, baseY = point.position.y, sideX = baseX + offsets.x * radius, sideY = baseY + offsets.y * radius;
                minX = Math.min(minX, baseX, sideX);
                maxX = Math.max(maxX, baseX, sideX);
                minY = Math.min(minY, baseY, sideY);
                maxY = Math.max(maxY, baseY, sideY);
            }
            if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {
                return false;
            }
            const oscAmp = particle.ribbonOscillationSpeed && particle.ribbonOscillationDistance
                ? particle.ribbonOscillationDistance / particle.ribbonOscillationSpeed
                : minRadius$2, margin = Math.max(headRadius, particle.ribbonParticleDist ?? minRadius$2) + oscAmp;
            return isInsideByDirection(data, minX, maxX, minY, maxY, margin);
        }
        loadShape(particle) {
            if (!particle.shapeData) {
                return;
            }
            const count = getRibbonCount(particle);
            if (!particle.ribbonPoints?.length || particle.ribbonPoints.length !== count) {
                createRibbonState(particle);
            }
        }
        particleDestroy(particle) {
            delete particle.ribbonPoints;
            delete particle.ribbonHead;
            delete particle.ribbonPreviousHead;
            delete particle.ribbonPreviousPosition;
            delete particle.ribbonTime;
            delete particle.ribbonOffsets;
            delete particle.ribbonParticleDist;
            delete particle.ribbonMass;
            delete particle.ribbonDrag;
            delete particle.ribbonVelocityInherit;
            delete particle.ribbonOscillationSpeed;
            delete particle.ribbonOscillationDistance;
        }
        particleInit(container, particle) {
            prepareRibbonParticle(particle, container.canvas.size.width, container.canvas.size.height);
        }
    }

    async function loadRibbonShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["ribbon"], (container) => Promise.resolve(new RibbonDrawer(container)));
        });
    }

    const defaultRotation = 0;
    function polygon(sides, radius, rot = defaultRotation) {
        const step = doublePI / sides, path = [];
        for (let i = 0; i < sides; i++) {
            path.push({ x: Math.cos(i * step + rot) * radius, y: Math.sin(i * step + rot) * radius });
        }
        return path;
    }
    function roundedPath(context, path, radius) {
        const index1 = 0, index2 = 1, increment = 1;
        let p1 = path[index1], p2 = path[index2];
        if (!p1 || !p2) {
            return;
        }
        const len = path.length;
        context.moveTo((p1.x + p2.x) * half$2, (p1.y + p2.y) * half$2);
        for (let i = 1; i <= len; i++) {
            p1 = p2;
            p2 = path[(i + increment) % len];
            if (!p1 || !p2) {
                continue;
            }
            context.arcTo(p1.x, p1.y, (p1.x + p2.x) * half$2, (p1.y + p2.y) * half$2, radius);
        }
    }

    const defaultSides = 5, defaultRadius$1 = 5;
    class RoundedPolygonDrawer {
        draw(data) {
            const { context, particle, radius } = data;
            roundedPath(context, polygon(particle.sides, radius), particle.borderRadius ?? defaultRadius$1);
        }
        getSidesCount(particle) {
            const roundedPolygon = particle.shapeData;
            return Math.round(getRangeValue(roundedPolygon?.sides ?? defaultSides));
        }
        particleInit(container, particle) {
            const shapeData = particle.shapeData;
            particle.borderRadius = Math.round(getRangeValue(shapeData?.radius ?? defaultSides)) * container.retina.pixelRatio;
        }
    }

    async function loadRoundedPolygonShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["rounded-polygon"], () => Promise.resolve(new RoundedPolygonDrawer()));
        });
    }

    function drawRoundedRect(ctx, fixedRadius, fixedDiameter, borderRadius) {
        const info = {
            x: -fixedRadius,
            y: -fixedRadius,
            height: fixedDiameter,
            width: fixedDiameter,
        }, radius = {
            topLeft: borderRadius,
            topRight: borderRadius,
            bottomLeft: borderRadius,
            bottomRight: borderRadius,
        }, { x, y, width, height } = info, r = x + width, b = y + height;
        ctx.moveTo(x + radius.topLeft, y);
        ctx.lineTo(r - radius.topRight, y);
        ctx.quadraticCurveTo(r, y, r, y + radius.topRight);
        ctx.lineTo(r, y + height - radius.bottomRight);
        ctx.quadraticCurveTo(r, b, r - radius.bottomRight, b);
        ctx.lineTo(x + radius.bottomLeft, b);
        ctx.quadraticCurveTo(x, b, x, b - radius.bottomLeft);
        ctx.lineTo(x, y + radius.topLeft);
        ctx.quadraticCurveTo(x, y, x + radius.topLeft, y);
    }

    const defaultRadius = 5;
    class RoundedRectDrawer {
        draw(data) {
            const { context, particle, radius } = data, fixedRadius = radius * Math.SQRT1_2, fixedDiameter = fixedRadius * double, borderRadius = particle.borderRadius ?? defaultRadius;
            if ("roundRect" in context) {
                context.roundRect(-fixedRadius, -fixedRadius, fixedDiameter, fixedDiameter, borderRadius);
            }
            else {
                drawRoundedRect(context, fixedRadius, fixedDiameter, borderRadius);
            }
        }
        particleInit(container, particle) {
            const shapeData = particle.shapeData;
            particle.borderRadius = getRangeValue(shapeData?.radius ?? defaultRadius) * container.retina.pixelRatio;
        }
    }

    async function loadRoundedRectShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["rounded-rect"], () => Promise.resolve(new RoundedRectDrawer()));
        });
    }

    function createSVGPaths(data) {
        const doc = safeDocument();
        return data.map(d => {
            const element = doc.createElementNS("http://www.w3.org/2000/svg", "path");
            element.setAttribute("d", d);
            return {
                element,
                length: element.getTotalLength(),
            };
        });
    }

    function loadSVGFromString(svgText) {
        const parser = new DOMParser(), doc = parser.parseFromString(svgText, "image/svg+xml"), svg = doc.querySelector("svg");
        if (!svg) {
            return { paths: [], size: { width: 0, height: 0 } };
        }
        const pathElements = svg.querySelectorAll("path"), paths = [];
        for (const node of pathElements) {
            if (!(node instanceof SVGPathElement)) {
                continue;
            }
            paths.push({
                element: node,
                length: node.getTotalLength(),
            });
        }
        const size = {
            width: Number.parseFloat(svg.getAttribute("width") ?? "0"),
            height: Number.parseFloat(svg.getAttribute("height") ?? "0"),
        };
        return {
            paths,
            size,
        };
    }

    var SVGPathDirection;
    (function (SVGPathDirection) {
        SVGPathDirection[SVGPathDirection["normal"] = 0] = "normal";
        SVGPathDirection[SVGPathDirection["reverse"] = 1] = "reverse";
    })(SVGPathDirection || (SVGPathDirection = {}));
    const minStep = 0, minIndex = 0, minWidth$2 = 0, minScale = 1;
    class SVGPathGenerator {
        #container;
        #offset;
        #paths;
        #res;
        #reverse;
        #scale;
        #size;
        #width;
        constructor(container) {
            this.#container = container;
            this.#paths = [];
            this.#reverse = false;
            this.#size = { width: 0, height: 0 };
            this.#scale = 1;
            this.#offset = { x: 0, y: 0, mode: exports.PixelMode.percent };
            this.#width = 0;
            this.#res = Vector.origin;
        }
        generate(particle, delta) {
            const container = this.#container, pxRatio = container.retina.pixelRatio;
            particle.svgDirection ??= getRandom() > half$2 ? SVGPathDirection.normal : SVGPathDirection.reverse;
            particle.svgPathIndex ??= Math.floor(getRandom() * this.#paths.length);
            particle.svgSpeed ??= particle.velocity.mult(particle.retina.moveSpeed * half$2).length;
            particle.svgStep ??= randomInRangeValue({ min: 0, max: this.#paths[particle.svgPathIndex].length }) * pxRatio;
            particle.svgOffset ??= {
                width: randomInRangeValue({ min: -this.#width * half$2, max: this.#width * half$2 }) * pxRatio,
                height: randomInRangeValue({ min: -this.#width * half$2, max: this.#width * half$2 }) * pxRatio,
            };
            particle.svgInitialPosition ??= particle.position.copy();
            particle.velocity.x = 0;
            particle.velocity.y = 0;
            if (particle.svgDirection === SVGPathDirection.normal) {
                particle.svgStep += particle.svgSpeed * delta.factor;
            }
            else {
                particle.svgStep -= particle.svgSpeed * delta.factor;
            }
            let path = this.#paths[particle.svgPathIndex];
            const pathLength = path.length, indexOffset = 1;
            if (particle.svgStep >= pathLength) {
                particle.svgPathIndex = particle.svgPathIndex + indexOffset;
                if (particle.svgPathIndex >= this.#paths.length) {
                    if (this.#reverse) {
                        particle.svgPathIndex = this.#paths.length - indexOffset;
                        particle.svgDirection = SVGPathDirection.reverse;
                    }
                    else {
                        particle.svgPathIndex = 0;
                        particle.svgStep = 0;
                    }
                }
            }
            else if (particle.svgStep <= minStep) {
                particle.svgPathIndex = particle.svgPathIndex - indexOffset;
                if (particle.svgPathIndex < minIndex) {
                    if (this.#reverse) {
                        particle.svgPathIndex = 0;
                        particle.svgDirection = SVGPathDirection.normal;
                    }
                    else {
                        particle.svgPathIndex = this.#paths.length - indexOffset;
                        path = this.#paths[particle.svgPathIndex];
                        particle.svgStep = path.length;
                    }
                }
            }
            path = this.#paths[particle.svgPathIndex];
            const pathElement = path.element, pos = pathElement.getPointAtLength(particle.svgStep), canvasSize = this.#container.canvas.size, offset = getPosition(this.#offset, canvasSize), scale = this.#scale * pxRatio;
            particle.position.x =
                (pos.x - this.#size.width * half$2) * scale + particle.svgInitialPosition.x + offset.x + particle.svgOffset.width;
            particle.position.y =
                (pos.y - this.#size.height * half$2) * scale + particle.svgInitialPosition.y + offset.y + particle.svgOffset.height;
            this.#res.x = 0;
            this.#res.y = 0;
            return this.#res;
        }
        init() {
            const options = this.#container.actualOptions.particles.move.path.options, position = options.position ?? this.#offset;
            this.#reverse = options.reverse ?? this.#reverse;
            this.#scale = options.scale ?? minScale;
            this.#offset.x = position.x;
            this.#offset.y = position.y;
            this.#offset.mode = position.mode;
            this.#width = options.width ?? minWidth$2;
            if (options.url && !options.path) {
                const url = options.url;
                void (async () => {
                    const response = await fetch(url), data = await response.text(), { paths, size } = loadSVGFromString(data);
                    this.#paths = paths;
                    this.#size.width = size.width;
                    this.#size.height = size.height;
                })();
            }
            else if (options.path) {
                const path = options.path;
                this.#paths = createSVGPaths(options.path.data);
                this.#size.height = path.size.height;
                this.#size.width = path.size.width;
            }
        }
        reset() {
        }
        update() {
        }
    }

    const svgPathName = "svgPathGenerator";
    async function loadSVGPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(svgPathName, container => {
                return Promise.resolve(new SVGPathGenerator(container));
            });
        });
    }

    const defaultShadowBlur = 0, defaultShadowOffsetValue = 0;
    class ShadowDrawer {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        drawAfter(data) {
            const { context } = data;
            context.restore();
        }
        drawBefore(data) {
            const { particle, context } = data, container = this.#container, shadowParticle = particle, shadowColor = shadowParticle.shadowColor, shadowOffset = shadowParticle.shadowOffset;
            if (!shadowColor) {
                return;
            }
            context.save();
            context.shadowBlur = shadowParticle.shadowBlur ?? defaultShadowBlur;
            context.shadowColor = getStyleFromRgb(shadowColor, container.hdr, undefined, container.peakNits, container.hdrMode);
            context.shadowOffsetX = shadowOffset?.x ?? defaultShadowOffsetValue;
            context.shadowOffsetY = shadowOffset?.y ?? defaultShadowOffsetValue;
        }
        particleInit(_container, particle) {
            const effectData = particle.effectData, shadowColor = OptionsColor.create(new OptionsColor(), effectData?.color);
            particle.shadowColor = rangeColorToRgb(this.#pluginManager, shadowColor);
            particle.shadowBlur = effectData?.blur ?? defaultShadowBlur;
            particle.shadowOffset = effectData?.offset ?? originPoint;
        }
    }

    async function loadShadowEffect(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addEffect("shadow", container => {
                return Promise.resolve(new ShadowDrawer(e.pluginManager, container));
            });
        });
    }

    class SimplexNoiseGenerator extends NoiseFieldGenerator {
        constructor(container) {
            const simplex = new SimplexNoise();
            super(container, {
                noise4d: (x, y, z, w) => simplex.noise4d.noise(x, y, z, w),
                seed: seed => {
                    simplex.noise4d.seed(seed);
                },
            });
        }
    }

    const simplexNoisePathName = "simplexNoise";
    async function loadSimplexNoisePath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(simplexNoisePathName, container => {
                return Promise.resolve(new SimplexNoiseGenerator(container));
            });
        });
    }

    const mouseDownEvent = "pointerdown", touchStartEvent = "touchstart";

    class SoundsAudio {
        loop = false;
        source = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (isObject(data)) {
                loadProperty(this, "loop", data.loop);
                if (data.source !== undefined) {
                    this.source = data.source;
                }
            }
            else {
                this.source = data;
            }
        }
    }

    class SoundsNote {
        duration = 500;
        value = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "duration", data.duration);
            loadProperty(this, "value", data.value);
        }
    }

    class SoundsMelody {
        loop = false;
        melodies = [];
        notes = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "loop", data.loop);
            if (data.melodies !== undefined) {
                this.melodies = data.melodies.map(s => {
                    const tmp = new SoundsMelody();
                    tmp.load(s);
                    return tmp;
                });
            }
            if (data.notes !== undefined) {
                this.notes = data.notes.map(s => {
                    const tmp = new SoundsNote();
                    tmp.load(s);
                    return tmp;
                });
            }
        }
    }

    class SoundsEvent {
        audio;
        event = [];
        filter;
        melodies;
        notes = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "event", data.event);
            if (data.audio !== undefined) {
                if (isArray(data.audio)) {
                    this.audio = data.audio.map(s => {
                        const tmp = new SoundsAudio();
                        tmp.load(s);
                        return tmp;
                    });
                }
                else {
                    this.audio = new SoundsAudio();
                    this.audio.load(data.audio);
                }
            }
            if (data.notes !== undefined) {
                this.notes = data.notes.map(t => {
                    const tmp = new SoundsNote();
                    tmp.load(t);
                    return tmp;
                });
            }
            if (data.melodies !== undefined) {
                this.melodies = data.melodies.map(t => {
                    const tmp = new SoundsMelody();
                    tmp.load(t);
                    return tmp;
                });
            }
            if (data.filter) {
                if (isString(data.filter)) {
                    const filterFunc = globalThis[data.filter];
                    if (isFunction(filterFunc)) {
                        this.filter = filterFunc;
                    }
                }
                else {
                    this.filter = data.filter;
                }
            }
        }
    }

    class SoundsIcon {
        height = 24;
        path;
        style = "";
        svg;
        width = 24;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "path", data.path);
            loadProperty(this, "svg", data.svg);
            loadProperty(this, "width", data.width);
            loadProperty(this, "height", data.height);
        }
    }

    class SoundsIcons {
        enable;
        mute;
        unmute;
        volumeDown;
        volumeUp;
        constructor() {
            this.mute = new SoundsIcon();
            this.unmute = new SoundsIcon();
            this.volumeDown = new SoundsIcon();
            this.volumeUp = new SoundsIcon();
            this.enable = false;
            this.mute.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M19.707,5.293c-0.391-0.391-1.023-0.391-1.414,0l-1.551,1.551c-0.345-0.688-0.987-1.02-1.604-1.02c-0.449,0-0.905,0.152-1.356,0.453l-2.672,1.781C10.357,8.561,8.904,9,8,9c-1.654,0-3,1.346-3,3v2c0,1.237,0.754,2.302,1.826,2.76l-1.533,1.533c-0.391,0.391-0.391,1.023,0,1.414C5.488,19.902,5.744,20,6,20s0.512-0.098,0.707-0.293l2.527-2.527c0.697,0.174,1.416,0.455,1.875,0.762l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C16.035,20.176,17,19.495,17,18V9.414l2.707-2.707C20.098,6.316,20.098,5.684,19.707,5.293z M14.891,7.941c0.038-0.025,0.073-0.046,0.104-0.062C14.998,7.914,15,7.954,15,8v1.293l-2,2V9.202L14.891,7.941z M7,12c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146v2.439l-2.83,2.83C8.757,15.046,8.356,15,8,15c-0.552,0-1-0.448-1-1V12z M10.301,15.406L12,13.707v2.439C11.519,15.859,10.925,15.604,10.301,15.406z M14.994,18.12c-0.03-0.016-0.065-0.036-0.104-0.062L13,16.798v-4.091l2-2V18C15,18.046,14.998,18.086,14.994,18.12z"/>
    </g>
</svg>`;
            this.unmute.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M17.138,5.824c-0.449,0-0.905,0.152-1.356,0.453l-2.672,1.781C12.357,8.561,10.904,9,10,9c-1.654,0-3,1.346-3,3v2c0,1.654,1.346,3,3,3c0.904,0,2.357,0.439,3.109,0.941l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C18.035,20.176,19,19.495,19,18V8C19,6.505,18.035,5.824,17.138,5.824z M14,16.146C12.907,15.495,11.211,15,10,15c-0.552,0-1-0.448-1-1v-2c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146V16.146z M17,18c0,0.046-0.002,0.086-0.006,0.12c-0.03-0.016-0.065-0.036-0.104-0.062L15,16.798V9.202l1.891-1.261c0.038-0.025,0.073-0.046,0.104-0.062C16.998,7.914,17,7.954,17,8V18z"/>
    </g>
</svg>`;
            this.volumeDown.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M15.138,5.824c-0.449,0-0.905,0.152-1.356,0.453l-2.672,1.781C10.357,8.561,8.904,9,8,9c-1.654,0-3,1.346-3,3v2c0,1.654,1.346,3,3,3c0.904,0,2.357,0.439,3.109,0.941l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C16.035,20.176,17,19.495,17,18V8C17,6.505,16.035,5.824,15.138,5.824z M8,15c-0.552,0-1-0.448-1-1v-2c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146v6.293C10.907,15.495,9.211,15,8,15z M15,18c0,0.046-0.002,0.086-0.006,0.12c-0.03-0.016-0.065-0.036-0.104-0.062L13,16.798V9.202l1.891-1.261c0.038-0.025,0.073-0.046,0.104-0.062C14.998,7.914,15,7.954,15,8V18z"/>
        <path fill="#fff" d="M18.292,10.294c-0.39,0.391-0.39,1.023,0.002,1.414c0.345,0.345,0.535,0.803,0.535,1.291c0,0.489-0.19,0.948-0.536,1.294c-0.391,0.39-0.391,1.023,0,1.414C18.488,15.902,18.744,16,19,16s0.512-0.098,0.707-0.293c0.724-0.723,1.122-1.685,1.122-2.708s-0.398-1.984-1.123-2.707C19.317,9.903,18.683,9.901,18.292,10.294z"/>
    </g>
</svg>`;
            this.volumeUp.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M16.706,10.292c-0.389-0.389-1.023-0.391-1.414,0.002c-0.39,0.391-0.39,1.023,0.002,1.414c0.345,0.345,0.535,0.803,0.535,1.291c0,0.489-0.19,0.948-0.536,1.294c-0.391,0.39-0.391,1.023,0,1.414C15.488,15.902,15.744,16,16,16s0.512-0.098,0.707-0.293c0.724-0.723,1.122-1.685,1.122-2.708S17.431,11.015,16.706,10.292z"/>
        <path fill="#fff" d="M18.706,8.292c-0.391-0.389-1.023-0.39-1.414,0.002c-0.39,0.391-0.39,1.024,0.002,1.414c0.879,0.877,1.363,2.044,1.364,3.287c0.001,1.246-0.484,2.417-1.365,3.298c-0.391,0.391-0.391,1.023,0,1.414C17.488,17.902,17.744,18,18,18s0.512-0.098,0.707-0.293c1.259-1.259,1.952-2.933,1.951-4.713C20.657,11.217,19.964,9.547,18.706,8.292z"/>
        <path fill="#fff" d="M20.706,6.292c-0.391-0.389-1.023-0.39-1.414,0.002c-0.39,0.391-0.39,1.024,0.002,1.414c1.412,1.409,2.191,3.285,2.192,5.284c0.002,2.002-0.777,3.885-2.193,5.301c-0.391,0.391-0.391,1.023,0,1.414C19.488,19.902,19.744,20,20,20s0.512-0.098,0.707-0.293c1.794-1.794,2.781-4.18,2.779-6.717C23.485,10.457,22.497,8.078,20.706,6.292z"/>
        <path fill="#fff" d="M12.138,5.824c-0.449,0-0.905,0.152-1.356,0.453L8.109,8.059C7.357,8.561,5.904,9,5,9c-1.654,0-3,1.346-3,3v2c0,1.654,1.346,3,3,3c0.904,0,2.357,0.439,3.109,0.941l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C13.035,20.176,14,19.495,14,18V8C14,6.505,13.035,5.824,12.138,5.824z M5,15c-0.552,0-1-0.448-1-1v-2c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146v6.293C7.907,15.495,6.211,15,5,15z M12,18c0,0.046-0.002,0.086-0.006,0.12c-0.03-0.016-0.065-0.036-0.104-0.062L10,16.798V9.202l1.891-1.261c0.038-0.025,0.073-0.046,0.104-0.062C11.998,7.914,12,7.954,12,8V18z"/>
    </g>
</svg>`;
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            this.mute.load(data.mute);
            this.unmute.load(data.unmute);
            this.volumeDown.load(data.volumeDown);
            this.volumeUp.load(data.volumeUp);
        }
    }

    class SoundsVolume {
        max = 100;
        min = 0;
        step = 10;
        value = 100;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (isObject(data)) {
                loadProperty(this, "max", data.max);
                loadProperty(this, "min", data.min);
                loadProperty(this, "step", data.step);
                if (data.value !== undefined) {
                    this.value = data.value;
                }
            }
            else {
                this.value = data;
            }
        }
    }

    class Sounds {
        autoPlay = true;
        enable = false;
        events = [];
        icons = new SoundsIcons();
        volume = new SoundsVolume();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "autoPlay", data.autoPlay);
            loadProperty(this, "enable", data.enable);
            if (data.events !== undefined) {
                this.events = data.events.map(t => {
                    const event = new SoundsEvent();
                    event.load(t);
                    return event;
                });
            }
            this.icons.load(data.icons);
            if (data.volume !== undefined) {
                this.volume.load(data.volume);
            }
        }
    }

    const notes = new Map();
    notes.set("C", [16.35, 32.7, 65.41, 130.81, 261.63, 523.25, 1046.5, 2093.0, 4186.01]);
    notes.set("Db", [17.32, 34.65, 69.3, 138.59, 277.18, 554.37, 1108.73, 2217.46, 4434.92]);
    notes.set("D", [18.35, 36.71, 73.42, 146.83, 293.66, 587.33, 1174.66, 2349.32, 4698.63]);
    notes.set("Eb", [19.45, 38.89, 77.78, 155.56, 311.13, 622.25, 1244.51, 2489.02, 4978.03]);
    notes.set("E", [20.6, 41.2, 82.41, 164.81, 329.63, 659.25, 1318.51, 2637.02, 5274.04]);
    notes.set("F", [21.83, 43.65, 87.31, 174.61, 349.23, 698.46, 1396.91, 2793.83, 5587.65]);
    notes.set("Gb", [23.12, 46.25, 92.5, 185.0, 369.99, 739.99, 1479.98, 2959.96, 5919.91]);
    notes.set("G", [24.5, 49.0, 98.0, 196.0, 392.0, 783.99, 1567.98, 3135.96, 6271.93]);
    notes.set("Ab", [25.96, 51.91, 103.83, 207.65, 415.3, 830.61, 1661.22, 3322.44, 6644.88]);
    notes.set("A", [27.5, 55.0, 110.0, 220.0, 440.0, 880.0, 1760.0, 3520.0, 7040.0]);
    notes.set("Bb", [29.14, 58.27, 116.54, 233.08, 466.16, 932.33, 1864.66, 3729.31, 7458.62]);
    notes.set("B", [30.87, 61.74, 123.47, 246.94, 493.88, 987.77, 1975.53, 3951.07, 7902.13]);
    notes.set("pause", [0]);
    function getNoteFrequency(note) {
        const regex = /(([A-G]b?)(\d))|pause/i, result = regex.exec(note), groupKey = 2, defaultMatchKey = 0, innerGroupKey = 3;
        if (!result?.length) {
            return;
        }
        const noteKey = result[groupKey] ?? result[defaultMatchKey], noteItem = notes.get(noteKey);
        if (!noteItem) {
            return;
        }
        return noteItem[parseInt(result[innerGroupKey] ?? "0")];
    }
    let muted = true;
    const isWindowMuted = () => {
        return muted;
    };
    const unmuteWindow = () => {
        muted = false;
    };

    const generalFirstClickHandler = () => {
        removeEventListener(mouseDownEvent, generalFirstClickHandler);
        removeEventListener(touchStartEvent, generalFirstClickHandler);
        unmuteWindow();
    };
    class SoundsPlugin {
        id = "sounds";
        #engine;
        constructor(engine) {
            this.#engine = engine;
            const listenerOptions = {
                capture: true,
                once: true,
            };
            addEventListener(mouseDownEvent, generalFirstClickHandler, listenerOptions);
            addEventListener(touchStartEvent, generalFirstClickHandler, listenerOptions);
        }
        async getPlugin(container) {
            const { SoundsPluginInstance } = await Promise.resolve().then(function () { return SoundsPluginInstance$1; });
            return new SoundsPluginInstance(container, this.#engine);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let soundsOptions = options.sounds;
            if (soundsOptions?.load === undefined) {
                options.sounds = soundsOptions = new Sounds();
            }
            soundsOptions.load(source?.sounds);
        }
        needsPlugin(options) {
            return options?.sounds?.enable ?? false;
        }
    }

    async function loadSoundsPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new SoundsPlugin(e));
        });
    }

    var SpiralDirection;
    (function (SpiralDirection) {
        SpiralDirection[SpiralDirection["positive"] = 1] = "positive";
        SpiralDirection[SpiralDirection["negative"] = -1] = "negative";
    })(SpiralDirection || (SpiralDirection = {}));

    const minRadius$1 = 0, speedFactor = 0.01, defaultOptions$1 = {
        maxRadius: { min: 10, max: 50 },
        angularSpeed: { min: 0.01, max: 0.04 },
        radialSpeed: { min: 0.1, max: 0.3 },
    };
    class SpiralPathGenerator {
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.options = deepExtend({}, defaultOptions$1);
        }
        generate(particle, delta) {
            const options = this.options;
            particle.spiral ??= {
                angle: getRandom() * doublePI,
                radius: minRadius$1,
                direction: SpiralDirection.positive,
                maxRadius: getRangeValue(options.maxRadius),
                angularSpeed: getRangeValue(options.angularSpeed) * speedFactor,
                radialSpeed: getRangeValue(options.radialSpeed) * speedFactor,
            };
            const spiral = particle.spiral;
            spiral.angle += spiral.angularSpeed * delta.factor;
            spiral.radius += spiral.radialSpeed * spiral.direction * delta.factor;
            if (spiral.radius > spiral.maxRadius && spiral.direction === SpiralDirection.positive) {
                spiral.radius = spiral.maxRadius;
                spiral.direction = SpiralDirection.negative;
            }
            else if (spiral.radius < minRadius$1 && spiral.direction === SpiralDirection.negative) {
                spiral.radius = minRadius$1;
                spiral.direction = SpiralDirection.positive;
            }
            const offsetX = Math.cos(spiral.angle) * spiral.radius, offsetY = Math.sin(spiral.angle) * spiral.radius;
            particle.position.x += offsetX;
            particle.position.y += offsetY;
            this.#res.x = 0;
            this.#res.y = 0;
            return this.#res;
        }
        init() {
            const sourceOptions = this.#container.actualOptions.particles.move.path.options;
            this.options.maxRadius = sourceOptions["maxRadius"] ?? this.options.maxRadius;
            this.options.angularSpeed = sourceOptions["angularSpeed"] ?? this.options.angularSpeed;
            this.options.radialSpeed = sourceOptions["radialSpeed"] ?? this.options.radialSpeed;
        }
        reset(particle) {
            delete particle.spiral;
        }
        update() {
        }
    }

    const spiralPathName = "spiralPathGenerator";
    async function loadSpiralPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(spiralPathName, container => {
                return Promise.resolve(new SpiralPathGenerator(container));
            });
        });
    }

    function drawSpiral(data) {
        const { context, particle, radius } = data;
        if (particle.spiralInnerRadius === undefined ||
            particle.spiralLineSpacing === undefined ||
            particle.spiralWidthFactor === undefined) {
            return;
        }
        const realWidth = (radius - particle.spiralInnerRadius) / particle.spiralLineSpacing, widthFactor = 10;
        for (let i = 0; i < realWidth * widthFactor; i++) {
            const angle = i / widthFactor, factor = particle.spiralInnerRadius + particle.spiralLineSpacing * angle, pos = {
                x: factor * Math.cos(angle),
                y: factor * Math.sin(angle),
            };
            context.lineTo(pos.x, pos.y);
        }
    }

    const defaultInnerRadius = 1, defaultLineSpacing = 1, defaultWidthFactor = 10;
    class SpiralDrawer {
        draw(data) {
            drawSpiral(data);
        }
        particleInit(container, particle) {
            const pixelRatio = container.retina.pixelRatio, shapeData = particle.shapeData;
            particle.spiralInnerRadius = getRangeValue(shapeData?.innerRadius ?? defaultInnerRadius) * pixelRatio;
            particle.spiralLineSpacing = getRangeValue(shapeData?.lineSpacing ?? defaultLineSpacing) * pixelRatio;
            particle.spiralWidthFactor = getRangeValue(shapeData?.widthFactor ?? defaultWidthFactor);
        }
    }

    async function loadSpiralShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["spiral"], () => Promise.resolve(new SpiralDrawer()));
        });
    }

    const defaultExponent = 4, defaultSteps = 64;
    function sign(v) {
        return v < none ? -identity$3 : identity$3;
    }
    function drawSquircle(data) {
        const { context, particle, radius } = data;
        if (particle.squircleExponent === undefined || particle.squircleSteps === undefined) {
            return;
        }
        const steps = particle.squircleSteps, step = doublePI / steps, exponent = double / particle.squircleExponent;
        context.save();
        context.scale(radius, radius);
        context.beginPath();
        for (let i = 0; i <= steps; i++) {
            const t = i * step, cos = Math.cos(t), sin = Math.sin(t), x = sign(cos) * Math.pow(Math.abs(cos), exponent), y = sign(sin) * Math.pow(Math.abs(sin), exponent);
            if (i) {
                context.lineTo(x, y);
            }
            else {
                context.moveTo(x, y);
            }
        }
        context.closePath();
        context.restore();
    }

    class SquircleDrawer {
        draw(data) {
            drawSquircle(data);
        }
        particleInit(_container, particle) {
            const shapeData = particle.shapeData;
            particle.squircleExponent = getRangeValue(shapeData?.exponent ?? defaultExponent);
            particle.squircleSteps = getRangeValue(shapeData?.steps ?? defaultSteps);
        }
    }

    async function loadSquircleShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["squircle"], () => Promise.resolve(new SquircleDrawer()));
        });
    }

    var ThemeMode;
    (function (ThemeMode) {
        ThemeMode["any"] = "any";
        ThemeMode["dark"] = "dark";
        ThemeMode["light"] = "light";
    })(ThemeMode || (ThemeMode = {}));

    class ThemeDefault {
        auto = false;
        mode = ThemeMode.any;
        value = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "auto", data.auto);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "value", data.value);
        }
    }

    class Theme {
        default = new ThemeDefault();
        name = "";
        options;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "name", data.name);
            this.default.load(data.default);
            if (data.options !== undefined) {
                this.options = deepExtend({}, data.options);
            }
        }
    }

    class ThemesPlugin {
        id = "theme";
        async getPlugin(container) {
            const { ThemesPluginInstance } = await Promise.resolve().then(function () { return ThemesPluginInstance$1; });
            return new ThemesPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            const findDefaultTheme = (mode) => {
                if (!options.themes) {
                    return;
                }
                return (options.themes.find(theme => theme.default.value && theme.default.mode === mode) ??
                    options.themes.find(theme => theme.default.value && theme.default.mode === ThemeMode.any));
            }, setTheme = (name) => {
                if (!options.themes) {
                    return;
                }
                if (name) {
                    const chosenTheme = options.themes.find(theme => theme.name === name);
                    if (chosenTheme) {
                        options.load(chosenTheme.options);
                    }
                }
                else {
                    const mediaMatch = safeMatchMedia("(prefers-color-scheme: dark)"), clientDarkMode = mediaMatch?.matches, defaultTheme = findDefaultTheme(clientDarkMode ? ThemeMode.dark : ThemeMode.light);
                    if (defaultTheme) {
                        options.load(defaultTheme.options);
                    }
                }
            };
            options.findDefaultTheme = findDefaultTheme;
            options.setTheme = setTheme;
            options.themes ??= [];
            if (source?.themes !== undefined) {
                for (const theme of source.themes) {
                    if (!theme) {
                        continue;
                    }
                    const existingTheme = options.themes.find(t => t.name === theme.name);
                    if (existingTheme) {
                        existingTheme.load(theme);
                    }
                    else {
                        const optTheme = new Theme();
                        optTheme.load(theme);
                        options.themes.push(optTheme);
                    }
                }
            }
            options.defaultThemes.dark = findDefaultTheme(ThemeMode.dark)?.name;
            options.defaultThemes.light = findDefaultTheme(ThemeMode.light)?.name;
        }
        needsPlugin(options) {
            return !!options?.themes?.length;
        }
    }

    async function loadThemesPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ThemesPlugin());
        });
    }

    const minTrailLength = 3, trailLengthOffset = 1, minWidth$1 = -1, firstIndex = 0, defaultLength = 10, loopTrailLengthOffset = 2, loopTrailLengthMinIndex = 0, defaultWidth = 0, minBound = 0;
    const defaultTransform = {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
    };
    class TrailDrawer {
        #container;
        constructor(container) {
            this.#container = container;
        }
        drawAfter(data) {
            const { context, drawPosition, drawRadius, drawScale, particle, transformData } = data, container = this.#container, diameter = drawRadius * double, pxRatio = container.retina.pixelRatio, trail = particle.trail;
            if (!trail || !particle.trailLength) {
                return;
            }
            const currentPos = drawPosition, pathLength = particle.trailLength * drawScale + drawRadius;
            trail.push({
                break: particle.justWarped,
                color: context.fillStyle || context.strokeStyle,
                position: {
                    x: currentPos.x,
                    y: currentPos.y,
                },
                transformData,
            });
            if (trail.length < minTrailLength) {
                return;
            }
            const pathLengthFloor = Math.floor(pathLength);
            if (trail.length > pathLengthFloor) {
                trail.splice(firstIndex, trail.length - pathLengthFloor);
            }
            const trailLength = Math.min(trail.length, pathLength);
            context.save();
            context.lineCap = "butt";
            context.lineJoin = "round";
            for (let i = trailLength - loopTrailLengthOffset; i > loopTrailLengthMinIndex; i--) {
                const previousStep = trail[i + trailLengthOffset], step = trail[i], nextStep = trail[i - trailLengthOffset];
                if (!previousStep || !step || !nextStep) {
                    continue;
                }
                const previousPosition = previousStep.position, position = step.position, nextPosition = nextStep.position, stepTransformData = particle.trailTransform ? (step.transformData ?? defaultTransform) : defaultTransform;
                if (step.break || previousStep.break || nextStep.break) {
                    continue;
                }
                context.setTransform(stepTransformData.a, stepTransformData.b, stepTransformData.c, stepTransformData.d, position.x, position.y);
                const startX = (previousPosition.x + position.x) * half$2 - position.x, startY = (previousPosition.y + position.y) * half$2 - position.y, endX = (position.x + nextPosition.x) * half$2 - position.x, endY = (position.y + nextPosition.y) * half$2 - position.y;
                context.beginPath();
                context.moveTo(startX, startY);
                context.quadraticCurveTo(originPoint.x, originPoint.y, endX, endY);
                const width = Math.max((i / trailLength) * diameter, pxRatio, (particle.trailMinWidth ?? minWidth$1) * drawScale), oldAlpha = context.globalAlpha;
                context.globalAlpha = particle.trailFade ? i / trailLength : defaultAlpha$1;
                context.lineWidth = particle.trailMaxWidth ? Math.min(width, particle.trailMaxWidth * drawScale) : width;
                context.strokeStyle = step.color;
                context.stroke();
                context.globalAlpha = oldAlpha;
            }
            context.restore();
        }
        isInsideCanvas(data) {
            const { canvasSize, direction, outMode, particle, radius } = data, position = particle.position, trail = particle.trail;
            let minX = position.x - radius, maxX = position.x + radius, minY = position.y - radius, maxY = position.y + radius;
            if (trail?.length) {
                const widthPadding = Math.max(radius, particle.trailMaxWidth ?? defaultWidth, particle.trailMinWidth ?? defaultWidth);
                for (const step of trail) {
                    minX = Math.min(minX, step.position.x - widthPadding);
                    maxX = Math.max(maxX, step.position.x + widthPadding);
                    minY = Math.min(minY, step.position.y - widthPadding);
                    maxY = Math.max(maxY, step.position.y + widthPadding);
                }
            }
            const strictBounds = outMode === exports.OutMode.destroy;
            if (direction === exports.OutModeDirection.bottom) {
                return minY <= canvasSize.height;
            }
            if (direction === exports.OutModeDirection.left) {
                return maxX >= minBound;
            }
            if (direction === exports.OutModeDirection.right) {
                return minX <= canvasSize.width;
            }
            if (direction === exports.OutModeDirection.top) {
                return maxY >= minBound;
            }
            if (!strictBounds) {
                return (position.x + radius >= minBound &&
                    position.y + radius >= minBound &&
                    position.x - radius <= canvasSize.width &&
                    position.y - radius <= canvasSize.height);
            }
            return maxX >= minBound && maxY >= minBound && minX <= canvasSize.width && minY <= canvasSize.height;
        }
        particleInit(container, particle) {
            particle.trail = [];
            const effectData = particle.effectData;
            particle.trailFade = effectData?.fade ?? true;
            particle.trailLength = getRangeValue(effectData?.length ?? defaultLength) * container.retina.pixelRatio;
            particle.trailMaxWidth = effectData?.maxWidth
                ? getRangeValue(effectData.maxWidth) * container.retina.pixelRatio
                : undefined;
            particle.trailMinWidth = effectData?.minWidth
                ? getRangeValue(effectData.minWidth) * container.retina.pixelRatio
                : undefined;
            particle.trailTransform = effectData?.transform ?? false;
        }
    }

    async function loadTrailEffect(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addEffect("trail", container => {
                return Promise.resolve(new TrailDrawer(container));
            });
        });
    }

    class TrailFill {
        color;
        image;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "image", data.image);
        }
    }

    class Trail {
        enable = false;
        fill = new TrailFill();
        length = 10;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            if (data.fill !== undefined) {
                this.fill.load(data.fill);
            }
            loadProperty(this, "length", data.length);
        }
    }

    class TrailPlugin {
        id = "trail";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { TrailPluginInstance } = await Promise.resolve().then(function () { return TrailPluginInstance$1; });
            return new TrailPluginInstance(this.#pluginManager, container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin()) {
                return;
            }
            let trailOptions = options.trail;
            if (!trailOptions?.load) {
                options.trail = trailOptions = new Trail();
            }
            trailOptions.load(source?.trail);
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadTrailPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
        });
    }

    const angularFrequencyFactor = 0.5, halfPI = Math.PI * half$2;
    const defaultOptions = {
        waveHeight: { min: 0, max: 3 },
        waveLength: { min: 0, max: 5 },
    };
    class ZigZagPathGenerator {
        options;
        #container;
        #res;
        constructor(container) {
            this.#container = container;
            this.#res = Vector.origin;
            this.options = deepExtend({}, defaultOptions);
        }
        generate(particle, delta) {
            const options = this.options;
            particle.zigzag ??= {
                counter: getRandom(),
                waveHeight: getRangeValue(options.waveHeight),
                waveLength: getRangeValue(options.waveLength),
            };
            const angularFrequency = (angularFrequencyFactor / particle.zigzag.waveLength) * delta.factor;
            particle.zigzag.counter += angularFrequency;
            const zigzagAngle = particle.zigzag.waveHeight * Math.sin(particle.zigzag.counter);
            particle.position.x += zigzagAngle * Math.cos(particle.velocity.angle + halfPI);
            particle.position.y += zigzagAngle * Math.sin(particle.velocity.angle + halfPI);
            this.#res.x = 0;
            this.#res.y = 0;
            return this.#res;
        }
        init() {
            const sourceOptions = this.#container.actualOptions.particles.move.path.options;
            this.options.waveLength = sourceOptions["waveLength"] ?? this.options.waveLength;
            this.options.waveHeight = sourceOptions["waveHeight"] ?? this.options.waveHeight;
        }
        reset() {
        }
        update() {
        }
    }

    const zigZagPathName = "zigZagPathGenerator";
    async function loadZigZagPath(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureBaseMoverLoaded(e);
            e.pluginManager.addPathGenerator?.(zigZagPathName, container => {
                return Promise.resolve(new ZigZagPathGenerator(container));
            });
        });
    }

    const minZoom = 0.1;
    const maxZoom = 5;
    const zoomInFactor = 1.05;
    const zoomOutFactor = 0.95;
    const zoomGestureFactor = 0.25;
    const touchPointsCount = 2;
    const touchPointIndexFirst = 0;
    const touchPointIndexSecond = 1;
    const touchCenterDivisor = 2;
    const initialTouchDistance = 0;

    class Zoom {
        enable = false;
        max = maxZoom;
        min = minZoom;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "min", data.min);
            loadProperty(this, "max", data.max);
        }
    }

    class ZoomPlugin {
        id = "zoom";
        async getPlugin(container) {
            const { ZoomPluginInstance } = await Promise.resolve().then(function () { return ZoomPluginInstance$1; });
            return new ZoomPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin()) {
                return;
            }
            let zoomOptions = options.zoom;
            if (!zoomOptions) {
                zoomOptions = new Zoom();
                options.zoom = zoomOptions;
            }
            zoomOptions.load(source?.zoom);
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadZoomPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new ZoomPlugin());
        });
    }

    async function loadAll(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const loadInteractionsForAll = async (e) => {
                await loadFull(e);
                await Promise.all([
                    loadExternalCannonInteraction(e),
                    loadExternalParticleInteraction(e),
                    loadExternalPopInteraction(e),
                    loadLightInteraction(e),
                    loadParticlesRepulseInteraction(e),
                    loadInfectionPlugin(e),
                    loadEmittersShapeCanvas(e),
                    loadEmittersShapePath(e),
                    loadEmittersShapePolygon(e),
                    loadBranchesPath(e),
                    loadBrownianPath(e),
                    loadCurlNoisePath(e),
                    loadCurvesPath(e),
                    loadFractalNoisePath(e),
                    loadGridPath(e),
                    loadLevyPath(e),
                    loadPerlinNoisePath(e),
                    loadPolygonPath(e),
                    loadRandomPath(e),
                    loadSVGPath(e),
                    loadSpiralPath(e),
                    loadZigZagPath(e),
                    loadSimplexNoisePath(e),
                ]);
            };
            await Promise.all([
                loadInteractionsForAll(e),
                loadHsvColorPlugin(e),
                loadHwbColorPlugin(e),
                loadLabColorPlugin(e),
                loadLchColorPlugin(e),
                loadOklabColorPlugin(e),
                loadOklchColorPlugin(e),
                loadNamedColorPlugin(e),
                loadEasingBackPlugin(e),
                loadEasingBouncePlugin(e),
                loadEasingCircPlugin(e),
                loadEasingCubicPlugin(e),
                loadEasingElasticPlugin(e),
                loadEasingExpoPlugin(e),
                loadEasingGaussianPlugin(e),
                loadEasingLinearPlugin(e),
                loadEasingQuartPlugin(e),
                loadEasingQuintPlugin(e),
                loadEasingSigmoidPlugin(e),
                loadEasingSinePlugin(e),
                loadEasingSmoothstepPlugin(e),
                loadBackgroundMaskPlugin(e),
                loadCanvasMaskPlugin(e),
                loadManualParticlesPlugin(e),
                loadMotionPlugin(e),
                loadPoissonDiscPlugin(e),
                loadPolygonMaskPlugin(e),
                loadResponsivePlugin(e),
                loadSoundsPlugin(e),
                loadThemesPlugin(e),
                loadTrailPlugin(e),
                loadZoomPlugin(e),
                loadExportImagePlugin(e),
                loadExportJSONPlugin(e),
                loadExportVideoPlugin(e),
                loadGradientUpdater(e),
                loadOrbitUpdater(e),
                loadBubbleEffect(e),
                loadFilterEffect(e),
                loadParticlesEffect(e),
                loadShadowEffect(e),
                loadTrailEffect(e),
                loadArrowShape(e),
                loadCardsShape(e),
                loadCogShape(e),
                loadGifShape(e),
                loadHeartShape(e),
                loadInfinityShape(e),
                loadMatrixShape(e),
                loadPathShape(e),
                loadRibbonShape(e),
                loadRoundedPolygonShape(e),
                loadRoundedRectShape(e),
                loadSpiralShape(e),
                loadSquircleShape(e),
            ]);
        });
    }

    const globalObject = globalThis;
    globalObject.loadAll = loadAll;
    globalObject.tsParticles = tsParticles;

    const fColorIndex = 0, sColorIndex = 1;
    function setTransformValue(factor, newFactor, key) {
        const newValue = newFactor[key];
        if (newValue !== undefined) {
            factor[key] = (factor[key] ?? defaultTransformValue) * newValue;
        }
    }
    class RenderManager {
        #backgroundElement;
        #backgroundWarnings;
        #canvasClearPlugins;
        #canvasManager;
        #colorPlugins;
        #container;
        #context;
        #contextSettings;
        #drawParticlePlugins;
        #drawParticlesCleanupPlugins;
        #drawParticlesSetupPlugins;
        #layers;
        #pluginManager;
        #postDrawUpdaters;
        #preDrawUpdaters;
        #reusableColorStyles = {};
        #reusablePluginColors = [undefined, undefined];
        #reusableTransform = {};
        constructor(pluginManager, container, canvasManager) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#canvasManager = canvasManager;
            this.#context = null;
            this.#backgroundElement = null;
            this.#backgroundWarnings = new Set();
            this.#preDrawUpdaters = [];
            this.#postDrawUpdaters = [];
            this.#canvasClearPlugins = [];
            this.#colorPlugins = [];
            this.#drawParticlePlugins = [];
            this.#drawParticlesCleanupPlugins = [];
            this.#drawParticlesSetupPlugins = [];
            this.#layers = {
                0: [],
                1: [],
                2: [],
                3: [],
                4: [],
                5: [],
                6: [],
                7: [],
            };
        }
        get settings() {
            return this.#contextSettings;
        }
        canvasClear() {
            if (!this.#container.actualOptions.clear) {
                return;
            }
            this.draw(ctx => {
                ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
            });
        }
        clear() {
            for (const plugin of this.#canvasClearPlugins) {
                if (plugin.canvasClear?.() ?? false) {
                    return;
                }
            }
            for (const layer of Object.values(exports.DrawLayer)) {
                if (typeof layer === "number") {
                    for (const plugin of this.#getLayerPlugins(layer)) {
                        if (plugin.canvasClear?.() ?? false) {
                            return;
                        }
                    }
                }
            }
            this.canvasClear();
        }
        destroy() {
            this.stop();
            this.#backgroundElement = null;
            this.#backgroundWarnings.clear();
            this.#preDrawUpdaters = [];
            this.#postDrawUpdaters = [];
            this.#canvasClearPlugins = [];
            this.#colorPlugins = [];
            this.#drawParticlePlugins = [];
            this.#drawParticlesCleanupPlugins = [];
            this.#drawParticlesSetupPlugins = [];
            for (const layer of Object.values(exports.DrawLayer)) {
                if (typeof layer === "number") {
                    this.#layers[layer] = [];
                }
            }
        }
        draw(cb) {
            const ctx = this.#context;
            if (!ctx) {
                return;
            }
            return cb(ctx);
        }
        drawParticle(particle, delta) {
            if (particle.spawning || particle.destroyed) {
                return;
            }
            const radius = particle.getRadius();
            if (radius <= minimumSize) {
                return;
            }
            const pfColor = particle.getFillColor(), psColor = particle.getStrokeColor();
            let [fColor, sColor] = this.#getPluginParticleColors(particle);
            fColor ??= pfColor;
            sColor ??= psColor;
            if (!fColor && !sColor) {
                return;
            }
            const container = this.#container, zIndexOptions = particle.options.zIndex, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, { fillOpacity, opacity, strokeOpacity } = particle.getOpacity(), transform = this.#reusableTransform, colorStyles = this.#reusableColorStyles, fill = fColor
                ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
                : undefined, stroke = sColor
                ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
                : fill;
            transform.a = transform.b = transform.c = transform.d = undefined;
            colorStyles.fill = fill;
            colorStyles.stroke = stroke;
            this.draw((context) => {
                for (const plugin of this.#drawParticlesSetupPlugins) {
                    plugin.drawParticleSetup?.(context, particle, delta);
                }
                this.#applyPreDrawUpdaters(context, particle, radius, opacity, colorStyles, transform);
                this.#drawParticle({
                    container,
                    context,
                    particle,
                    delta,
                    colorStyles,
                    radius: radius * zIndexFactor ** zIndexOptions.sizeRate,
                    opacity: opacity,
                    transform,
                });
                this.#applyPostDrawUpdaters(particle);
                for (const plugin of this.#drawParticlesCleanupPlugins) {
                    plugin.drawParticleCleanup?.(context, particle, delta);
                }
            });
        }
        drawParticlePlugins(particle, delta) {
            this.draw(ctx => {
                for (const plugin of this.#drawParticlePlugins) {
                    this.#drawParticlePlugin(ctx, plugin, particle, delta);
                }
            });
        }
        drawParticles(delta) {
            const { particles, actualOptions } = this.#container;
            this.clear();
            particles.update(delta);
            this.draw(ctx => {
                const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
                if (this.#backgroundElement) {
                    try {
                        ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
                    }
                    catch {
                        this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
                    }
                }
                const background = actualOptions.background;
                if (background.draw) {
                    try {
                        background.draw(ctx, delta);
                    }
                    catch {
                        this.#warnOnce("background-draw-error", "Error in background.draw callback");
                    }
                }
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
                    plugin.canvasPaint?.();
                }
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
                    plugin.drawSettingsSetup?.(ctx, delta);
                }
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
                    plugin.draw?.(ctx, delta);
                }
                particles.drawParticles(delta);
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
                    plugin.clearDraw?.(ctx, delta);
                    plugin.drawSettingsCleanup?.(ctx, delta);
                }
            });
        }
        init() {
            this.initUpdaters();
            this.initPlugins();
            this.#resolveBackgroundElement();
            this.paint();
        }
        initPlugins() {
            this.#canvasClearPlugins = [];
            this.#colorPlugins = [];
            this.#drawParticlePlugins = [];
            this.#drawParticlesSetupPlugins = [];
            this.#drawParticlesCleanupPlugins = [];
            for (const layer of Object.values(exports.DrawLayer)) {
                if (typeof layer === "number") {
                    this.#layers[layer] = [];
                }
            }
            for (const plugin of this.#container.plugins) {
                if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
                    this.#colorPlugins.push(plugin);
                }
                if (plugin.drawParticle) {
                    this.#drawParticlePlugins.push(plugin);
                }
                if (plugin.drawParticleSetup) {
                    this.#drawParticlesSetupPlugins.push(plugin);
                }
                if (plugin.drawParticleCleanup) {
                    this.#drawParticlesCleanupPlugins.push(plugin);
                }
                if (plugin.canvasClear) {
                    this.#canvasClearPlugins.push(plugin);
                }
                if (plugin.canvasPaint) {
                    this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
                }
                if (plugin.drawSettingsSetup) {
                    this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
                }
                if (plugin.draw) {
                    this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
                }
                if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
                    this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
                }
            }
        }
        initUpdaters() {
            this.#preDrawUpdaters = [];
            this.#postDrawUpdaters = [];
            for (const updater of this.#container.particleUpdaters) {
                if (updater.afterDraw) {
                    this.#postDrawUpdaters.push(updater);
                }
                if (updater.getColorStyles ?? updater.getTransformValues ?? updater.beforeDraw) {
                    this.#preDrawUpdaters.push(updater);
                }
            }
        }
        paint() {
            let handled = false;
            for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
                handled = plugin.canvasPaint?.() ?? false;
                if (handled) {
                    break;
                }
            }
            if (handled) {
                return;
            }
            this.paintBase();
        }
        paintBase(baseColor) {
            this.draw(ctx => {
                ctx.fillStyle = baseColor ?? "rgba(0,0,0,0)";
                ctx.fillRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
            });
        }
        paintImage(image, opacity) {
            this.draw(ctx => {
                if (!image) {
                    return;
                }
                const prevAlpha = ctx.globalAlpha;
                ctx.globalAlpha = opacity;
                ctx.drawImage(image, originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
                ctx.globalAlpha = prevAlpha;
            });
        }
        setContext(context) {
            this.#context = context;
            if (this.#context) {
                this.#context.globalCompositeOperation = defaultCompositeValue;
            }
        }
        setContextSettings(settings) {
            this.#contextSettings = settings;
        }
        stop() {
            this.draw(ctx => {
                ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
            });
        }
        #applyPostDrawUpdaters(particle) {
            for (const updater of this.#postDrawUpdaters) {
                updater.afterDraw?.(particle);
            }
        }
        #applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) {
            for (const updater of this.#preDrawUpdaters) {
                if (updater.getColorStyles) {
                    const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity);
                    if (fill) {
                        colorStyles.fill = fill;
                    }
                    if (stroke) {
                        colorStyles.stroke = stroke;
                    }
                }
                if (updater.getTransformValues) {
                    const updaterTransform = updater.getTransformValues(particle);
                    for (const key in updaterTransform) {
                        setTransformValue(transform, updaterTransform, key);
                    }
                }
                updater.beforeDraw?.(particle);
            }
        }
        #drawAfterEffect(drawer, data) {
            if (!drawer?.drawAfter) {
                return;
            }
            const { particle } = data;
            if (!particle.effect) {
                return;
            }
            drawer.drawAfter(data);
        }
        #drawBeforeEffect(drawer, data) {
            if (!drawer?.drawBefore) {
                return;
            }
            const { particle } = data;
            if (!particle.effect) {
                return;
            }
            drawer.drawBefore(data);
        }
        #drawParticle(data) {
            const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
                x: pos.x,
                y: pos.y,
            };
            context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
            if (colorStyles.fill) {
                context.fillStyle = colorStyles.fill;
            }
            const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
            context.lineWidth = strokeWidth;
            if (colorStyles.stroke) {
                context.strokeStyle = colorStyles.stroke;
            }
            const drawData = {
                context,
                particle,
                radius,
                drawRadius: radius * drawScale,
                opacity,
                delta,
                pixelRatio: container.retina.pixelRatio,
                fill: fillEnabled,
                stroke: strokeWidth > minStrokeWidth,
                transformData,
                position: { ...pos },
                drawPosition,
                drawScale,
            };
            for (const plugin of container.plugins) {
                plugin.drawParticleTransform?.(drawData);
            }
            const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
            this.#drawBeforeEffect(effect, drawData);
            this.#drawShapeBeforeDraw(shape, drawData);
            this.#drawShape(shape, drawData);
            this.#drawShapeAfterDraw(shape, drawData);
            this.#drawAfterEffect(effect, drawData);
            context.resetTransform();
        }
        #drawParticlePlugin(context, plugin, particle, delta) {
            if (!plugin.drawParticle) {
                return;
            }
            plugin.drawParticle(context, particle, delta);
        }
        #drawShape(drawer, data) {
            if (!drawer) {
                return;
            }
            const { context, fill, particle, stroke } = data;
            if (!particle.shape) {
                return;
            }
            context.beginPath();
            drawer.draw(data);
            if (particle.shapeClose) {
                context.closePath();
            }
            if (fill) {
                context.fill();
            }
            if (stroke) {
                context.stroke();
            }
        }
        #drawShapeAfterDraw(drawer, data) {
            if (!drawer?.afterDraw) {
                return;
            }
            const { particle } = data;
            if (!particle.shape) {
                return;
            }
            drawer.afterDraw(data);
        }
        #drawShapeBeforeDraw(drawer, data) {
            if (!drawer?.beforeDraw) {
                return;
            }
            const { particle } = data;
            if (!particle.shape) {
                return;
            }
            drawer.beforeDraw(data);
        }
        #getLayerPlugins(layer) {
            return this.#layers[layer];
        }
        #getPluginParticleColors(particle) {
            let fColor, sColor;
            for (const plugin of this.#colorPlugins) {
                if (!fColor && plugin.particleFillColor) {
                    fColor = rangeColorToHsl(this.#pluginManager, plugin.particleFillColor(particle));
                }
                if (!sColor && plugin.particleStrokeColor) {
                    sColor = rangeColorToHsl(this.#pluginManager, plugin.particleStrokeColor(particle));
                }
                if (fColor && sColor) {
                    break;
                }
            }
            this.#reusablePluginColors[fColorIndex] = fColor;
            this.#reusablePluginColors[sColorIndex] = sColor;
            return this.#reusablePluginColors;
        }
        #resolveBackgroundElement() {
            const background = this.#container.actualOptions.background;
            this.#backgroundElement = null;
            if (!background.element) {
                return;
            }
            if (typeof background.element === "string") {
                if (typeof document !== "undefined") {
                    const node = document.querySelector(background.element);
                    if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
                        (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
                        (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
                        this.#backgroundElement = node;
                    }
                    else if (node) {
                        this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
                    }
                    else {
                        this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
                    }
                }
            }
            else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
                (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
                (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
                (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
                this.#backgroundElement = background.element;
            }
        }
        #warnOnce(key, message) {
            if (!this.#backgroundWarnings.has(key)) {
                this.#backgroundWarnings.add(key);
                getLogger().warning(message);
            }
        }
    }

    const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
        const transferredCanvas = transferredCanvases.get(canvas);
        if (transferredCanvas) {
            return transferredCanvas;
        }
        if (typeof canvas.transferControlToOffscreen !== "function") {
            throw new TypeError("OffscreenCanvas is required but not supported by this browser");
        }
        try {
            const offscreenCanvas = canvas.transferControlToOffscreen();
            transferredCanvases.set(canvas, offscreenCanvas);
            return offscreenCanvas;
        }
        catch {
            throw new TypeError("OffscreenCanvas transfer failed");
        }
    }, isHtmlCanvasElement = (canvas) => {
        return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
    };
    function setStyle(canvas, style, important = false) {
        if (!style) {
            return;
        }
        const element = canvas, elementStyle = element.style, keys = new Set();
        for (let i = 0; i < elementStyle.length; i++) {
            const key = elementStyle.item(i);
            if (!key) {
                continue;
            }
            keys.add(key);
        }
        for (let i = 0; i < style.length; i++) {
            const key = style.item(i);
            if (!key) {
                continue;
            }
            keys.add(key);
        }
        for (const key of keys) {
            const value = style.getPropertyValue(key);
            if (value) {
                elementStyle.setProperty(key, value, important ? "important" : "");
            }
            else {
                elementStyle.removeProperty(key);
            }
        }
    }
    class CanvasManager {
        domElement;
        render;
        renderCanvas;
        size;
        zoom = defaultZoom;
        #container;
        #generated;
        #hdrMediaListeners;
        #mutationObserver;
        #originalStyle;
        #pluginManager;
        #pointerEvents;
        #resizePlugins;
        #standardSize;
        #zoomCenter;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.render = new RenderManager(pluginManager, container, this);
            this.#standardSize = {
                height: 0,
                width: 0,
            };
            const pxRatio = container.retina.pixelRatio, stdSize = this.#standardSize;
            this.size = {
                height: stdSize.height * pxRatio,
                width: stdSize.width * pxRatio,
            };
            this.#generated = false;
            this.#resizePlugins = [];
            this.#pointerEvents = "none";
        }
        get #fullScreen() {
            return this.#container.actualOptions.fullScreen.enable;
        }
        destroy() {
            this.stop();
            if (this.#generated) {
                const element = this.domElement;
                element?.remove();
                this.domElement = undefined;
                this.renderCanvas = undefined;
            }
            else {
                this.#resetOriginalStyle();
            }
            this.render.destroy();
            this.#resizePlugins = [];
        }
        getZoomCenter() {
            const pxRatio = this.#container.retina.pixelRatio, { width, height } = this.size;
            if (this.#zoomCenter) {
                return this.#zoomCenter;
            }
            return {
                x: (width * half$2) / pxRatio,
                y: (height * half$2) / pxRatio,
            };
        }
        init() {
            this.#safeMutationObserver(obs => {
                obs.disconnect();
            });
            this.#mutationObserver = safeMutationObserver(records => {
                for (const record of records) {
                    if (record.type === "attributes" && record.attributeName === "style") {
                        this.#repairStyle();
                    }
                }
            });
            this.resize();
            this.#initStyle();
            this.#safeMutationObserver(obs => {
                const element = this.domElement;
                if (!element || !(element instanceof Node)) {
                    return;
                }
                obs.observe(element, { attributes: true });
            });
            this.initPlugins();
            this.#initContext();
            this.initBackground();
            this.#initHdrListeners();
            this.render.init();
        }
        initBackground() {
            const container = this.#container, options = container.actualOptions, background = options.background, element = this.domElement;
            if (!element) {
                return;
            }
            const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
            if (color) {
                const hdrOptions = container.actualOptions.hdr;
                elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
            }
            else {
                elementStyle.backgroundColor = "";
            }
            elementStyle.backgroundImage = background.image || "";
            elementStyle.backgroundPosition = background.position || "";
            elementStyle.backgroundRepeat = background.repeat || "";
            elementStyle.backgroundSize = background.size || "";
        }
        initPlugins() {
            this.#resizePlugins = [];
            for (const plugin of this.#container.plugins) {
                if (plugin.resize) {
                    this.#resizePlugins.push(plugin);
                }
            }
        }
        loadCanvas(canvas) {
            if (this.#generated && this.domElement) {
                this.domElement.remove();
            }
            const domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
            this.domElement = domCanvas;
            this.#generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
            this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
            const domElement = this.domElement;
            if (domElement) {
                domElement.ariaHidden = "true";
                this.#originalStyle = cloneStyle(domElement.style);
            }
            const standardSize = this.#standardSize, renderCanvas = this.renderCanvas;
            if (domElement) {
                standardSize.height = domElement.offsetHeight;
                standardSize.width = domElement.offsetWidth;
            }
            else {
                standardSize.height = renderCanvas.height;
                standardSize.width = renderCanvas.width;
            }
            const pxRatio = this.#container.retina.pixelRatio, retinaSize = this.size;
            renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
            renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
        }
        resize() {
            const element = this.domElement;
            if (!element) {
                return false;
            }
            const container = this.#container, renderCanvas = this.renderCanvas;
            if (renderCanvas === undefined) {
                return false;
            }
            const currentSize = container.canvas.#standardSize, newSize = {
                width: element.offsetWidth,
                height: element.offsetHeight,
            }, pxRatio = container.retina.pixelRatio, retinaSize = {
                width: newSize.width * pxRatio,
                height: newSize.height * pxRatio,
            };
            if (newSize.height === currentSize.height &&
                newSize.width === currentSize.width &&
                retinaSize.height === renderCanvas.height &&
                retinaSize.width === renderCanvas.width) {
                return false;
            }
            const oldSize = { ...currentSize };
            currentSize.height = newSize.height;
            currentSize.width = newSize.width;
            const canvasSize = this.size;
            renderCanvas.width = canvasSize.width = retinaSize.width;
            renderCanvas.height = canvasSize.height = retinaSize.height;
            if (this.#container.started) {
                container.particles.setResizeFactor({
                    width: currentSize.width / oldSize.width,
                    height: currentSize.height / oldSize.height,
                });
            }
            return true;
        }
        setPointerEvents(type) {
            const element = this.domElement;
            if (!element) {
                return;
            }
            this.#pointerEvents = type;
            this.#repairStyle();
        }
        setZoom(zoomLevel, center) {
            this.zoom = zoomLevel;
            this.#zoomCenter = center;
        }
        stop() {
            this.#safeMutationObserver(obs => {
                obs.disconnect();
            });
            this.#mutationObserver = undefined;
            this.#removeHdrListeners();
            this.render.stop();
        }
        async windowResize() {
            if (!this.domElement || !this.resize()) {
                return;
            }
            const container = this.#container, needsRefresh = container.updateActualOptions();
            container.particles.setDensity();
            this.#applyResizePlugins();
            if (needsRefresh) {
                await container.refresh();
            }
        }
        #applyResizePlugins() {
            for (const plugin of this.#resizePlugins) {
                plugin.resize?.();
            }
        }
        #initContext() {
            const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
                safeMatchMedia("(color-gamut: p3)")?.matches &&
                safeMatchMedia("(dynamic-range: high)")?.matches;
            container.hdr = canSupportHdr ?? false;
            container.hdrMode = container.actualOptions.hdr.mode;
            container.peakNits = container.actualOptions.hdr.peakNits;
            const renderCanvas = this.renderCanvas;
            if (!renderCanvas) {
                return;
            }
            this.render.setContextSettings({
                alpha: true,
                desynchronized: true,
                willReadFrequently: false,
                ...(canSupportHdr
                    ? { colorSpace: "display-p3", colorType: "float16" }
                    : { colorSpace: "srgb" }),
            });
            let context;
            try {
                context = renderCanvas.getContext("2d", this.render.settings);
            }
            catch {
                context = null;
            }
            if (canSupportHdr && !context) {
                container.hdr = false;
                const sdrSettings = {
                    alpha: true,
                    desynchronized: true,
                    willReadFrequently: false,
                    colorSpace: "srgb",
                };
                this.render.setContextSettings(sdrSettings);
                try {
                    context = renderCanvas.getContext("2d", sdrSettings);
                }
                catch {
                    context = null;
                }
            }
            this.render.setContext(context);
        }
        #initHdrListeners() {
            this.#removeHdrListeners();
            const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
                this.#recreateRenderCanvas();
                this.#initContext();
                this.initBackground();
            }, listeners = [];
            if (p3Query) {
                p3Query.addEventListener("change", handleChange);
                listeners.push({ handler: handleChange, mql: p3Query });
            }
            if (hdrQuery) {
                hdrQuery.addEventListener("change", handleChange);
                listeners.push({ handler: handleChange, mql: hdrQuery });
            }
            this.#hdrMediaListeners = listeners;
        }
        #initStyle() {
            const element = this.domElement, options = this.#container.actualOptions;
            if (!element) {
                return;
            }
            if (this.#fullScreen) {
                this.#setFullScreenStyle();
            }
            else {
                this.#resetOriginalStyle();
            }
            for (const key in options.style) {
                if (!key || !(key in options.style)) {
                    continue;
                }
                const value = options.style[key];
                if (!value) {
                    continue;
                }
                element.style.setProperty(key, value, "important");
            }
        }
        #recreateRenderCanvas() {
            const renderCanvas = this.renderCanvas;
            if (!renderCanvas) {
                return;
            }
            if (this.domElement) {
                return;
            }
            this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
        }
        #removeHdrListeners() {
            if (!this.#hdrMediaListeners) {
                return;
            }
            for (const { handler, mql } of this.#hdrMediaListeners) {
                mql.removeEventListener("change", handler);
            }
            this.#hdrMediaListeners = undefined;
        }
        #repairStyle() {
            const element = this.domElement;
            if (!element) {
                return;
            }
            this.#safeMutationObserver(observer => {
                observer.disconnect();
            });
            this.#initStyle();
            this.initBackground();
            const pointerEvents = this.#pointerEvents;
            element.style.pointerEvents = pointerEvents;
            element.style.setProperty("pointer-events", pointerEvents);
            this.#safeMutationObserver(observer => {
                if (!(element instanceof Node)) {
                    return;
                }
                observer.observe(element, { attributes: true });
            });
        }
        #resetOriginalStyle() {
            const element = this.domElement, originalStyle = this.#originalStyle;
            if (!element || !originalStyle) {
                return;
            }
            setStyle(element, originalStyle, true);
        }
        #safeMutationObserver(callback) {
            if (!this.#mutationObserver) {
                return;
            }
            callback(this.#mutationObserver);
        }
        #setFullScreenStyle() {
            const element = this.domElement;
            if (!element) {
                return;
            }
            setStyle(element, getFullScreenStyle(this.#container.actualOptions.fullScreen.zIndex), true);
        }
    }

    class EventListeners {
        #container;
        #handlers;
        #resizeObserver;
        #resizeTimeout;
        constructor(container) {
            this.#container = container;
            this.#handlers = {
                visibilityChange: () => {
                    this.#handleVisibilityChange();
                },
                resize: () => {
                    this.#handleWindowResize();
                },
            };
        }
        addListeners() {
            this.#manageListeners(true);
        }
        removeListeners() {
            this.#manageListeners(false);
        }
        #handleVisibilityChange() {
            const container = this.#container, options = container.actualOptions;
            if (!options.pauseOnBlur) {
                return;
            }
            if (safeDocument().hidden) {
                container.pageHidden = true;
                container.pause();
            }
            else {
                container.pageHidden = false;
                if (container.animationStatus) {
                    container.play(true);
                }
                else {
                    container.draw(true);
                }
            }
        }
        #handleWindowResize() {
            if (this.#resizeTimeout) {
                clearTimeout(this.#resizeTimeout);
                this.#resizeTimeout = undefined;
            }
            const handleResize = async () => {
                const canvas = this.#container.canvas;
                await canvas.windowResize();
            };
            this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds$1);
        }
        #manageListeners(add) {
            const handlers = this.#handlers;
            this.#manageResize(add);
            manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
        }
        #manageResize(add) {
            const handlers = this.#handlers, container = this.#container, options = container.actualOptions;
            if (!options.resize.enable) {
                return;
            }
            if (typeof ResizeObserver === "undefined") {
                manageListener(globalThis, resizeEvent, handlers.resize, add);
                return;
            }
            const canvasEl = container.canvas.domElement;
            if (this.#resizeObserver && !add) {
                if (canvasEl) {
                    this.#resizeObserver.unobserve(canvasEl);
                }
                this.#resizeObserver.disconnect();
                this.#resizeObserver = undefined;
            }
            else if (!this.#resizeObserver && add && canvasEl) {
                this.#resizeObserver = new ResizeObserver((entries) => {
                    const entry = entries.find(e => e.target === canvasEl);
                    if (!entry) {
                        return;
                    }
                    this.#handleWindowResize();
                });
                this.#resizeObserver.observe(canvasEl);
            }
        }
    }

    function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
        const effectData = effectOptions.options[effect];
        return deepExtend({
            close: effectOptions.close,
        }, itemFromSingleOrMultiple(effectData, id, reduceDuplicates));
    }
    function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
        const shapeData = shapeOptions.options[shape];
        return deepExtend({
            close: shapeOptions.close,
        }, itemFromSingleOrMultiple(shapeData, id, reduceDuplicates));
    }
    function fixOutMode(data) {
        if (!isInArray(data.outMode, data.checkModes)) {
            return;
        }
        const diameter = data.radius * double;
        if (data.coord > data.maxCoord - diameter) {
            data.setCb(-data.radius);
        }
        else if (data.coord < diameter) {
            data.setCb(data.radius);
        }
    }
    function normalizeAngle(angle, modulus) {
        const normalized = angle % modulus;
        return normalized < defaultAngle$1 ? normalized + modulus : normalized;
    }
    function initParticleState(particle, id, group) {
        particle.id = id;
        particle.group = group;
        particle.justWarped = false;
        particle.effectClose = true;
        particle.shapeClose = true;
        particle.pathRotation = false;
        particle.lastPathTime = 0;
        particle.destroyed = false;
        particle.unbreakable = false;
        particle.isRotating = false;
        particle.rotation = 0;
        particle.misplaced = false;
        particle.retina = {
            maxDistance: {},
            maxSpeed: 0,
            moveDrift: 0,
            moveSpeed: 0,
            sizeAnimationSpeed: 0,
        };
        particle.size = {
            value: 1,
            max: 1,
            min: 1,
            enable: false,
        };
        particle.outType = exports.ParticleOutType.normal;
        particle.ignoresResizeRatio = true;
    }
    function resolveParticleOptions(particle, container, pluginManager, overrideOptions) {
        const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates;
        particle.effect = itemFromSingleOrMultiple(particlesOptions.effect.type, particle.id, reduceDuplicates);
        particle.shape = itemFromSingleOrMultiple(particlesOptions.shape.type, particle.id, reduceDuplicates);
        const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
        if (overrideOptions) {
            if (overrideOptions.effect) {
                const overrideEffectType = overrideOptions.effect.type;
                if (overrideEffectType && overrideEffectType !== particle.effect) {
                    const effect = itemFromSingleOrMultiple(overrideEffectType, particle.id, reduceDuplicates);
                    if (effect) {
                        particle.effect = effect;
                    }
                }
                effectOptions.load(overrideOptions.effect);
            }
            if (overrideOptions.shape) {
                const overrideShapeType = overrideOptions.shape.type;
                if (overrideShapeType && overrideShapeType !== particle.shape) {
                    const shape = itemFromSingleOrMultiple(overrideShapeType, particle.id, reduceDuplicates);
                    if (shape) {
                        particle.shape = shape;
                    }
                }
                shapeOptions.load(overrideOptions.shape);
            }
        }
        if (particle.effect === randomColorValue) {
            const availableEffects = [...container.effectDrawers.keys()];
            particle.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
        }
        if (particle.shape === randomColorValue) {
            const availableShapes = [...container.shapeDrawers.keys()];
            particle.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
        }
        particle.effectData = particle.effect
            ? loadEffectData(particle.effect, effectOptions, particle.id, reduceDuplicates)
            : undefined;
        particle.shapeData = particle.shape
            ? loadShapeData(particle.shape, shapeOptions, particle.id, reduceDuplicates)
            : undefined;
        particlesOptions.load(overrideOptions);
        const effectData = particle.effectData, shapeData = particle.shapeData;
        if (effectData) {
            particlesOptions.load(effectData.particles);
        }
        if (shapeData) {
            particlesOptions.load(shapeData.particles);
        }
        particle.effectClose = effectData?.close ?? particlesOptions.effect.close;
        particle.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
        return particlesOptions;
    }
    function initParticleDrawers(particle, container) {
        let effectDrawer, shapeDrawer;
        if (particle.effect) {
            effectDrawer = container.effectDrawers.get(particle.effect);
        }
        if (effectDrawer?.loadEffect) {
            effectDrawer.loadEffect(particle);
        }
        if (particle.shape) {
            shapeDrawer = container.shapeDrawers.get(particle.shape);
        }
        if (shapeDrawer?.loadShape) {
            shapeDrawer.loadShape(particle);
        }
        const sideCountFunc = shapeDrawer?.getSidesCount;
        if (sideCountFunc) {
            particle.sides = sideCountFunc(particle);
        }
    }
    function runUpdaterPreInit(updaters, particle) {
        for (const updater of updaters) {
            updater.preInit?.(particle);
        }
    }
    function runUpdaterInit(updaters, particle) {
        for (const updater of updaters) {
            updater.init(particle);
        }
    }
    function runDrawerInit(container, particle) {
        const shapeDrawer = particle.shape ? container.shapeDrawers.get(particle.shape) : undefined, effectDrawer = particle.effect ? container.effectDrawers.get(particle.effect) : undefined;
        effectDrawer?.particleInit?.(container, particle);
        shapeDrawer?.particleInit?.(container, particle);
    }
    function runParticleCreatedPlugins(container, particle) {
        for (const plugin of container.particleCreatedPlugins) {
            plugin.particleCreated?.(particle);
        }
    }
    class Particle {
        backColor;
        destroyed;
        direction;
        effect;
        effectClose;
        effectData;
        fillColor;
        fillEnabled;
        fillOpacity;
        group;
        id;
        ignoresResizeRatio;
        initialPosition;
        initialVelocity;
        isRotating;
        justWarped;
        lastPathTime;
        misplaced;
        moveCenter;
        offset;
        opacity;
        options;
        outType;
        pathRotation;
        position;
        randomIndexData;
        retina;
        roll;
        rotation;
        shape;
        shapeClose;
        shapeData;
        sides;
        size;
        spawning;
        strokeColor;
        strokeOpacity;
        strokeWidth;
        unbreakable;
        velocity;
        zIndexFactor;
        #cachedOpacityData = {
            fillOpacity: defaultOpacity$3,
            opacity: defaultOpacity$3,
            strokeOpacity: defaultOpacity$3,
        };
        #cachedPosition = Vector3d.origin;
        #cachedRotateData = { sin: 0, cos: 0 };
        #cachedTransform = {
            a: 1,
            b: 0,
            c: 0,
            d: 1,
        };
        #container;
        #modifiers = [];
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        addModifier(modifier) {
            this.#modifiers.push(modifier);
            this.#modifiers.sort((a, b) => a.priority - b.priority);
        }
        clearModifiers() {
            this.#modifiers.length = 0;
        }
        destroy(override) {
            if (this.unbreakable || this.destroyed) {
                return;
            }
            this.destroyed = true;
            this.clearModifiers();
            const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
            shapeDrawer?.particleDestroy?.(this);
            for (const plugin of container.particleDestroyedPlugins) {
                plugin.particleDestroyed?.(this, override);
            }
            for (const updater of container.particleUpdaters) {
                updater.particleDestroyed?.(this, override);
            }
            this.#container.dispatchEvent(exports.EventType.particleDestroyed, {
                particle: this,
            });
        }
        draw(delta) {
            const container = this.#container, render = container.canvas.render;
            render.drawParticlePlugins(this, delta);
            render.drawParticle(this, delta);
        }
        getAngle() {
            return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle$1);
        }
        getFillColor() {
            return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
        }
        getMass() {
            return this.getRadius() ** squareExp * Math.PI * half$2;
        }
        getModifier(id) {
            return this.#modifiers.find(m => m.id === id);
        }
        getOpacity() {
            const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$3), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$3, strokeOpacity = this.strokeOpacity ?? defaultOpacity$3;
            this.#cachedOpacityData.fillOpacity = fillOpacity;
            this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
            this.#cachedOpacityData.strokeOpacity = strokeOpacity;
            return this.#cachedOpacityData;
        }
        getPosition() {
            this.#cachedPosition.x = this.position.x + this.offset.x;
            this.#cachedPosition.y = this.position.y + this.offset.y;
            this.#cachedPosition.z = this.position.z;
            return this.#cachedPosition;
        }
        getRadius() {
            return this.#applyModifiers(this.size.value, m => m.radius);
        }
        getRotateData() {
            const angle = this.getAngle();
            this.#cachedRotateData.sin = Math.sin(angle);
            this.#cachedRotateData.cos = Math.cos(angle);
            return this.#cachedRotateData;
        }
        getStrokeColor() {
            return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
        }
        getTransformData(externalTransform) {
            const rotateData = this.getRotateData(), rotating = this.isRotating;
            this.#cachedTransform.a = rotateData.cos * (externalTransform.a ?? defaultTransform$1.a);
            this.#cachedTransform.b = rotating
                ? rotateData.sin * (externalTransform.b ?? identity$3)
                : (externalTransform.b ?? defaultTransform$1.b);
            this.#cachedTransform.c = rotating
                ? -rotateData.sin * (externalTransform.c ?? identity$3)
                : (externalTransform.c ?? defaultTransform$1.c);
            this.#cachedTransform.d = rotateData.cos * (externalTransform.d ?? defaultTransform$1.d);
            return this.#cachedTransform;
        }
        init(id, position, overrideOptions, group) {
            const container = this.#container;
            initParticleState(this, id, group);
            this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
            container.retina.initParticle(this);
            runUpdaterPreInit(container.particleUpdaters, this);
            this.#initPosition(position);
            this.initialVelocity = this.#calculateVelocity();
            this.velocity = this.initialVelocity.copy();
            this.zIndexFactor = this.position.z / container.zLayers;
            this.sides = 24;
            initParticleDrawers(this, container);
            this.spawning = false;
            runUpdaterInit(container.particleUpdaters, this);
            runDrawerInit(container, this);
            runParticleCreatedPlugins(container, this);
        }
        isInsideCanvas(direction) {
            return this.#getInsideCanvasResult({ direction }).inside;
        }
        isInsideCanvasForOutMode(outMode, direction) {
            return this.#getInsideCanvasResult({ direction, outMode }).inside;
        }
        isShowingBack() {
            if (!this.roll) {
                return false;
            }
            const angle = this.roll.angle;
            if (this.roll.horizontal && this.roll.vertical) {
                const adjustedAngle = normalizeAngle(angle, doublePI);
                return adjustedAngle >= Math.PI * half$2 && adjustedAngle < Math.PI * triple * half$2;
            }
            if (this.roll.horizontal) {
                const adjustedAngle = normalizeAngle(angle + Math.PI * half$2, doublePI);
                return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
            }
            if (this.roll.vertical) {
                const adjustedAngle = normalizeAngle(angle, doublePI);
                return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
            }
            return false;
        }
        isVisible() {
            return !this.destroyed && !this.spawning && this.isInsideCanvas();
        }
        removeModifier(id) {
            const idx = this.#modifiers.findIndex(m => m.id === id);
            if (idx >= defaultAngle$1) {
                this.#modifiers.splice(idx, identity$3);
            }
        }
        reset() {
            for (const updater of this.#container.particleUpdaters) {
                updater.reset?.(this);
            }
        }
        #applyModifiers(base, getter) {
            let value = base;
            for (const mod of this.#modifiers) {
                if (mod.enabled) {
                    const override = getter(mod);
                    if (override !== undefined) {
                        value = override;
                    }
                }
            }
            return value;
        }
        #calcPosition(position, zIndex) {
            let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
            const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
            for (;;) {
                for (const plugin of plugins) {
                    const pluginPos = plugin.particlePosition?.(posVec, this);
                    if (pluginPos) {
                        return Vector3d.create(pluginPos.x, pluginPos.y, zIndex);
                    }
                }
                const exactPosition = calcExactPositionOrRandomFromSize({
                    size: canvasSize,
                    position: posVec,
                }), pos = Vector3d.create(exactPosition.x, exactPosition.y, zIndex);
                this.#fixHorizontal(pos, radius, outModes.left ?? outModes.default);
                this.#fixHorizontal(pos, radius, outModes.right ?? outModes.default);
                this.#fixVertical(pos, radius, outModes.top ?? outModes.default);
                this.#fixVertical(pos, radius, outModes.bottom ?? outModes.default);
                let isValidPosition = true;
                for (const plugin of container.particles.checkParticlePositionPlugins) {
                    isValidPosition = plugin.checkParticlePosition?.(this, pos, tryCount) ?? true;
                    if (!isValidPosition) {
                        break;
                    }
                }
                if (isValidPosition) {
                    return pos;
                }
                tryCount += tryCountIncrement;
                posVec = undefined;
            }
        }
        #calculateVelocity() {
            const moveOptions = this.options.move, baseVelocity = getParticleBaseVelocity(this.direction), res = baseVelocity.copy();
            if (moveOptions.direction === exports.MoveDirection.inside || moveOptions.direction === exports.MoveDirection.outside) {
                return res;
            }
            const rad = degToRad(getRangeValue(moveOptions.angle.value)), radOffset = degToRad(getRangeValue(moveOptions.angle.offset)), range = {
                left: radOffset - rad * half$2,
                right: radOffset + rad * half$2,
            };
            if (!moveOptions.straight) {
                res.angle += randomInRangeValue(setRangeValue(range.left, range.right));
            }
            if (moveOptions.random && typeof moveOptions.speed === "number") {
                res.length *= getRandom();
            }
            return res;
        }
        #fixHorizontal(pos, radius, outMode) {
            fixOutMode({
                outMode,
                checkModes: [exports.OutMode.bounce],
                coord: pos.x,
                maxCoord: this.#container.canvas.size.width,
                setCb: (value) => (pos.x += value),
                radius,
            });
        }
        #fixVertical(pos, radius, outMode) {
            fixOutMode({
                outMode,
                checkModes: [exports.OutMode.bounce],
                coord: pos.y,
                maxCoord: this.#container.canvas.size.height,
                setCb: (value) => (pos.y += value),
                radius,
            });
        }
        #getDefaultInsideCanvasResult(direction, outMode) {
            const radius = this.getRadius(), canvasSize = this.#container.canvas.size, position = this.position, isBounce = outMode === exports.OutMode.bounce;
            if (direction === exports.OutModeDirection.bottom) {
                return {
                    inside: isBounce ? position.y + radius < canvasSize.height : position.y - radius < canvasSize.height,
                    reason: "default",
                };
            }
            if (direction === exports.OutModeDirection.left) {
                return {
                    inside: isBounce ? position.x - radius > defaultAngle$1 : position.x + radius > defaultAngle$1,
                    reason: "default",
                };
            }
            if (direction === exports.OutModeDirection.right) {
                return {
                    inside: isBounce ? position.x + radius < canvasSize.width : position.x - radius < canvasSize.width,
                    reason: "default",
                };
            }
            if (direction === exports.OutModeDirection.top) {
                return {
                    inside: isBounce ? position.y - radius > defaultAngle$1 : position.y + radius > defaultAngle$1,
                    reason: "default",
                };
            }
            return {
                inside: position.x >= -radius &&
                    position.y >= -radius &&
                    position.y <= canvasSize.height + radius &&
                    position.x <= canvasSize.width + radius,
                reason: "default",
            };
        }
        #getInsideCanvasCallbackData(direction, outMode) {
            return {
                canvasSize: this.#container.canvas.size,
                direction,
                outMode,
                particle: this,
                radius: this.getRadius(),
            };
        }
        #getInsideCanvasResult(data) {
            const defaultResult = this.#getDefaultInsideCanvasResult(data.direction, data.outMode), container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined, effectDrawer = this.effect ? container.effectDrawers.get(this.effect) : undefined, shapeCheck = shapeDrawer?.isInsideCanvas, effectCheck = effectDrawer?.isInsideCanvas;
            if (!shapeCheck && !effectCheck) {
                return defaultResult;
            }
            const callbackData = this.#getInsideCanvasCallbackData(data.direction, data.outMode), shapeResult = shapeCheck ? this.#normalizeInsideCanvasResult(shapeCheck(callbackData), "shape") : undefined, effectResult = effectCheck ? this.#normalizeInsideCanvasResult(effectCheck(callbackData), "effect") : undefined;
            if (shapeResult && effectResult) {
                const margin = Math.max(shapeResult.margin ?? defaultAngle$1, effectResult.margin ?? defaultAngle$1);
                return {
                    inside: shapeResult.inside && effectResult.inside,
                    margin: margin > defaultAngle$1 ? margin : undefined,
                    reason: "combined",
                };
            }
            return shapeResult ?? effectResult ?? defaultResult;
        }
        #getRollColor(color) {
            if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
                return color;
            }
            if (!this.isShowingBack()) {
                return color;
            }
            if (this.backColor) {
                return this.backColor;
            }
            if (this.roll.alter) {
                return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
            }
            return color;
        }
        #initPosition(position) {
            const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
            if (!initialPosition) {
                throw new Error("a valid position cannot be found for particle");
            }
            this.position = initialPosition;
            this.initialPosition = this.position.copy();
            const canvasSize = container.canvas.size;
            this.moveCenter = {
                ...getPosition(this.options.move.center, canvasSize),
                radius: this.options.move.center.radius,
                mode: this.options.move.center.mode,
            };
            this.direction = getParticleDirectionAngle(this.options.move.direction, this.position, this.moveCenter);
            switch (this.options.move.direction) {
                case exports.MoveDirection.inside:
                    this.outType = exports.ParticleOutType.inside;
                    break;
                case exports.MoveDirection.outside:
                    this.outType = exports.ParticleOutType.outside;
                    break;
            }
            this.offset = Vector.origin;
        }
        #normalizeInsideCanvasResult(result, reason) {
            if (typeof result === "boolean") {
                return {
                    inside: result,
                    reason,
                };
            }
            return {
                inside: result.inside,
                margin: result.margin,
                reason: result.reason ?? reason,
            };
        }
    }

    class SpatialHashGrid {
        #cellSize;
        #cells = new Map();
        #circlePool = [];
        #circlePoolIdx;
        #pendingCellSize;
        #rectanglePool = [];
        #rectanglePoolIdx;
        constructor(cellSize) {
            this.#cellSize = cellSize;
            this.#circlePoolIdx = 0;
            this.#rectanglePoolIdx = 0;
        }
        clear() {
            this.#cells.clear();
            const pendingCellSize = this.#pendingCellSize;
            if (pendingCellSize) {
                this.#cellSize = pendingCellSize;
            }
            this.#pendingCellSize = undefined;
        }
        insert(particle) {
            const { x, y } = particle.getPosition(), key = this.#cellKeyFromCoords(x, y);
            if (!this.#cells.has(key)) {
                this.#cells.set(key, []);
            }
            this.#cells.get(key)?.push(particle);
        }
        query(range, check, out = []) {
            const bounds = this.#getRangeBounds(range);
            if (!bounds) {
                return out;
            }
            const minCellX = Math.floor(bounds.minX / this.#cellSize), maxCellX = Math.floor(bounds.maxX / this.#cellSize), minCellY = Math.floor(bounds.minY / this.#cellSize), maxCellY = Math.floor(bounds.maxY / this.#cellSize);
            for (let cx = minCellX; cx <= maxCellX; cx++) {
                for (let cy = minCellY; cy <= maxCellY; cy++) {
                    const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
                    if (!cellParticles) {
                        continue;
                    }
                    for (const p of cellParticles) {
                        if (check && !check(p)) {
                            continue;
                        }
                        if (range.contains(p.getPosition())) {
                            out.push(p);
                        }
                    }
                }
            }
            return out;
        }
        queryCircle(position, radius, check, out = []) {
            const circle = this.#acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
            this.#releaseShapes();
            return result;
        }
        queryRectangle(position, size, check, out = []) {
            const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
            this.#releaseShapes();
            return result;
        }
        setCellSize(cellSize) {
            this.#pendingCellSize = cellSize;
        }
        #acquireCircle(x, y, r) {
            return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
        }
        #acquireRectangle(x, y, w, h) {
            return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
        }
        #cellKeyFromCoords(x, y) {
            const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
            return `${cellX}_${cellY}`;
        }
        #getRangeBounds(range) {
            if (range instanceof Circle) {
                const r = range.radius, { x, y } = range.position;
                return {
                    minX: x - r,
                    maxX: x + r,
                    minY: y - r,
                    maxY: y + r,
                };
            }
            if (range instanceof Rectangle) {
                const { x, y } = range.position, { width, height } = range.size;
                return {
                    minX: x,
                    maxX: x + width,
                    minY: y,
                    maxY: y + height,
                };
            }
            return null;
        }
        #releaseShapes() {
            this.#circlePoolIdx = 0;
            this.#rectanglePoolIdx = 0;
        }
    }

    class ParticlesManager {
        checkParticlePositionPlugins;
        grid;
        #array;
        #container;
        #groupLimits;
        #limit;
        #nextId;
        #particleBuckets;
        #particleResetPlugins;
        #particleUpdatePlugins;
        #pluginManager;
        #pool;
        #postParticleUpdatePlugins;
        #postUpdatePlugins;
        #resizeFactor;
        #updatePlugins;
        #zBuckets;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#nextId = 0;
            this.#array = [];
            this.#pool = [];
            this.#limit = 0;
            this.#groupLimits = new Map();
            this.#particleBuckets = new Map();
            this.#zBuckets = this.#createBuckets(this.#container.zLayers);
            this.grid = new SpatialHashGrid(spatialHashGridCellSize);
            this.checkParticlePositionPlugins = [];
            this.#particleResetPlugins = [];
            this.#particleUpdatePlugins = [];
            this.#postUpdatePlugins = [];
            this.#postParticleUpdatePlugins = [];
            this.#updatePlugins = [];
        }
        get count() {
            return this.#array.length;
        }
        addParticle(position, overrideOptions, group, initializer) {
            const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
            if (limit > minLimit) {
                switch (limitMode) {
                    case exports.LimitMode.delete: {
                        const countToRemove = currentCount + countOffset - limit;
                        if (countToRemove > minCount) {
                            this.removeQuantity(countToRemove);
                        }
                        break;
                    }
                    case exports.LimitMode.wait:
                        if (currentCount >= limit) {
                            return;
                        }
                        break;
                }
            }
            try {
                const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
                particle.init(this.#nextId, position, overrideOptions, group);
                let canAdd = true;
                if (initializer) {
                    canAdd = initializer(particle);
                }
                if (!canAdd) {
                    this.#pool.push(particle);
                    return;
                }
                this.#array.push(particle);
                this.#insertParticleIntoBucket(particle);
                this.#nextId++;
                this.#container.dispatchEvent(exports.EventType.particleAdded, {
                    particle,
                });
                return particle;
            }
            catch (e) {
                getLogger().warning(`error adding particle: ${e}`);
            }
            return undefined;
        }
        clear() {
            this.#array = [];
            this.#particleBuckets.clear();
            this.#resetBuckets(this.#container.zLayers);
        }
        destroy() {
            this.#array = [];
            this.#pool.length = 0;
            this.#particleBuckets.clear();
            this.#zBuckets = [];
            this.checkParticlePositionPlugins = [];
            this.#particleResetPlugins = [];
            this.#particleUpdatePlugins = [];
            this.#postUpdatePlugins = [];
            this.#postParticleUpdatePlugins = [];
            this.#updatePlugins = [];
        }
        drawParticles(delta) {
            for (let i = this.#zBuckets.length - one; i >= minIndex$1; i--) {
                const bucket = this.#zBuckets[i];
                if (!bucket) {
                    continue;
                }
                for (const particle of bucket) {
                    particle.draw(delta);
                }
            }
        }
        filter(condition) {
            return this.#array.filter(condition);
        }
        find(condition) {
            return this.#array.find(condition);
        }
        get(index) {
            return this.#array[index];
        }
        async init() {
            const container = this.#container, options = container.actualOptions;
            this.checkParticlePositionPlugins = [];
            this.#updatePlugins = [];
            this.#particleUpdatePlugins = [];
            this.#postUpdatePlugins = [];
            this.#particleResetPlugins = [];
            this.#postParticleUpdatePlugins = [];
            this.#particleBuckets.clear();
            this.#resetBuckets(container.zLayers);
            this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
            for (const plugin of container.plugins) {
                if (plugin.redrawInit) {
                    await plugin.redrawInit();
                }
                if (plugin.checkParticlePosition) {
                    this.checkParticlePositionPlugins.push(plugin);
                }
                if (plugin.update) {
                    this.#updatePlugins.push(plugin);
                }
                if (plugin.particleUpdate) {
                    this.#particleUpdatePlugins.push(plugin);
                }
                if (plugin.postUpdate) {
                    this.#postUpdatePlugins.push(plugin);
                }
                if (plugin.particleReset) {
                    this.#particleResetPlugins.push(plugin);
                }
                if (plugin.postParticleUpdate) {
                    this.#postParticleUpdatePlugins.push(plugin);
                }
            }
            await this.#container.initDrawersAndUpdaters();
            for (const drawer of this.#container.effectDrawers.values()) {
                await drawer.init?.(container);
            }
            for (const drawer of this.#container.shapeDrawers.values()) {
                await drawer.init?.(container);
            }
            let handled = false;
            for (const plugin of container.plugins) {
                handled = plugin.particlesInitialization?.() ?? handled;
                if (handled) {
                    break;
                }
            }
            if (!handled) {
                const particlesOptions = options.particles, groups = particlesOptions.groups;
                for (const group in groups) {
                    const groupOptions = groups[group];
                    if (!groupOptions) {
                        continue;
                    }
                    for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
                        this.addParticle(undefined, groupOptions, group);
                    }
                }
                for (let i = this.count; i < particlesOptions.number.value; i++) {
                    this.addParticle();
                }
            }
        }
        push(nb, position, overrideOptions, group) {
            for (let i = 0; i < nb; i++) {
                this.addParticle(position, overrideOptions, group);
            }
        }
        async redraw() {
            this.clear();
            await this.init();
            this.#container.canvas.render.drawParticles({ value: 0, factor: 0 });
        }
        remove(particle, group, override) {
            this.removeAt(this.#array.indexOf(particle), undefined, group, override);
        }
        removeAt(index, quantity = defaultRemoveQuantity, group, override) {
            if (index < minIndex$1 || index > this.count) {
                return;
            }
            let deleted = 0;
            for (let i = index; deleted < quantity && i < this.count; i++) {
                if (this.#removeParticle(i, group, override)) {
                    i--;
                    deleted++;
                }
            }
        }
        removeQuantity(quantity, group) {
            this.removeAt(minIndex$1, quantity, group);
        }
        setDensity() {
            const options = this.#container.actualOptions, groups = options.particles.groups;
            let pluginsCount = 0;
            for (const plugin of this.#container.plugins) {
                if (plugin.particlesDensityCount) {
                    pluginsCount += plugin.particlesDensityCount();
                }
            }
            for (const group in groups) {
                const groupData = groups[group];
                if (!groupData) {
                    continue;
                }
                const groupDataOptions = loadParticlesOptions(this.#pluginManager, this.#container, groupData);
                this.#applyDensity(groupDataOptions, pluginsCount, group);
            }
            this.#applyDensity(options.particles, pluginsCount);
        }
        setResizeFactor(factor) {
            this.#resizeFactor = factor;
        }
        update(delta) {
            this.grid.clear();
            for (const plugin of this.#updatePlugins) {
                plugin.update?.(delta);
            }
            const particlesToDelete = this.#updateParticlesPhase1(delta);
            for (const plugin of this.#postUpdatePlugins) {
                plugin.postUpdate?.(delta);
            }
            this.#updateParticlesPhase2(delta, particlesToDelete);
            if (particlesToDelete.size) {
                for (const particle of particlesToDelete) {
                    this.remove(particle);
                }
            }
            this.#resizeFactor = undefined;
        }
        #addToPool(...particles) {
            this.#pool.push(...particles);
        }
        #applyDensity(options, pluginsCount, group, groupOptions) {
            const numberOptions = options.number;
            if (!numberOptions.density.enable) {
                if (group === undefined) {
                    this.#limit = numberOptions.limit.value;
                }
                else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
                    this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
                }
                return;
            }
            const densityFactor = this.#initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + pluginsCount, particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
            if (group === undefined) {
                this.#limit = numberOptions.limit.value * densityFactor;
            }
            else {
                this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
            }
            if (particlesCount < particlesNumber) {
                this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
            }
            else if (particlesCount > particlesNumber) {
                this.removeQuantity(particlesCount - particlesNumber, group);
            }
        }
        #createBuckets(zLayers) {
            const bucketCount = Math.max(Math.floor(zLayers), one);
            return Array.from({ length: bucketCount }, () => []);
        }
        #getBucketIndex(zIndex) {
            const maxBucketIndex = this.#zBuckets.length - one;
            if (maxBucketIndex <= minIndex$1) {
                return minIndex$1;
            }
            return Math.min(Math.max(Math.floor(zIndex), minIndex$1), maxBucketIndex);
        }
        #initDensityFactor(densityOptions) {
            const container = this.#container;
            if (!densityOptions.enable) {
                return defaultDensityFactor;
            }
            const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
            if (!canvasSize.width || !canvasSize.height) {
                return defaultDensityFactor;
            }
            return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
        }
        #insertParticleIntoBucket(particle) {
            const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
            if (!bucket) {
                return;
            }
            bucket.push(particle);
            this.#particleBuckets.set(particle.id, bucketIndex);
        }
        #removeParticle(index, group, override) {
            const particle = this.#array[index];
            if (!particle) {
                return false;
            }
            if (particle.group !== group) {
                return false;
            }
            this.#array.splice(index, deleteCount);
            this.#removeParticleFromBucket(particle);
            particle.destroy(override);
            this.#container.dispatchEvent(exports.EventType.particleRemoved, {
                particle,
            });
            this.#addToPool(particle);
            return true;
        }
        #removeParticleFromBucket(particle) {
            const bucketIndex = this.#particleBuckets.get(particle.id) ?? this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
            if (!bucket) {
                this.#particleBuckets.delete(particle.id);
                return;
            }
            const idx = bucket.findIndex(p => p.id === particle.id);
            if (idx >= minIndex$1) {
                bucket.splice(idx, deleteCount);
            }
            this.#particleBuckets.delete(particle.id);
        }
        #resetBuckets(zLayers) {
            const bucketCount = Math.max(Math.floor(zLayers), one);
            if (this.#zBuckets.length !== bucketCount) {
                this.#zBuckets = this.#createBuckets(bucketCount);
                return;
            }
            for (const bucket of this.#zBuckets) {
                bucket.length = minIndex$1;
            }
        }
        #updateParticleBucket(particle) {
            const newBucketIndex = this.#getBucketIndex(particle.position.z), currentBucketIndex = this.#particleBuckets.get(particle.id);
            if (currentBucketIndex === undefined) {
                this.#insertParticleIntoBucket(particle);
                return;
            }
            if (currentBucketIndex === newBucketIndex) {
                return;
            }
            const currentBucket = this.#zBuckets[currentBucketIndex];
            if (currentBucket) {
                const idx = currentBucket.findIndex(p => p.id === particle.id);
                if (idx >= minIndex$1) {
                    currentBucket.splice(idx, deleteCount);
                }
            }
            const newBucket = this.#zBuckets[newBucketIndex];
            if (!newBucket) {
                this.#particleBuckets.set(particle.id, newBucketIndex);
                return;
            }
            newBucket.push(particle);
            if (newBucket.length >= double) {
                const prev = newBucket[newBucket.length - double];
                if (prev && particle.id < prev.id) {
                    newBucket.sort((a, b) => a.id - b.id);
                }
            }
            this.#particleBuckets.set(particle.id, newBucketIndex);
        }
        #updateParticlesPhase1(delta) {
            const particlesToDelete = new Set(), resizeFactor = this.#resizeFactor;
            for (const particle of this.#array) {
                if (resizeFactor && !particle.ignoresResizeRatio) {
                    particle.position.x *= resizeFactor.width;
                    particle.position.y *= resizeFactor.height;
                    particle.initialPosition.x *= resizeFactor.width;
                    particle.initialPosition.y *= resizeFactor.height;
                }
                particle.ignoresResizeRatio = false;
                for (const plugin of this.#particleResetPlugins) {
                    plugin.particleReset?.(particle);
                }
                for (const plugin of this.#particleUpdatePlugins) {
                    if (particle.destroyed) {
                        break;
                    }
                    plugin.particleUpdate?.(particle, delta);
                }
                if (particle.destroyed) {
                    particlesToDelete.add(particle);
                    continue;
                }
                this.grid.insert(particle);
            }
            return particlesToDelete;
        }
        #updateParticlesPhase2(delta, particlesToDelete) {
            for (const particle of this.#array) {
                if (particle.destroyed) {
                    particlesToDelete.add(particle);
                    continue;
                }
                for (const updater of this.#container.particleUpdaters) {
                    updater.update(particle, delta);
                }
                if (!particle.spawning) {
                    for (const plugin of this.#postParticleUpdatePlugins) {
                        plugin.postParticleUpdate?.(particle, delta);
                    }
                }
                this.#updateParticleBucket(particle);
            }
        }
    }

    class Retina {
        pixelRatio;
        reduceFactor;
        #container;
        constructor(container) {
            this.#container = container;
            this.pixelRatio = defaultRatio$1;
            this.reduceFactor = defaultReduceFactor;
        }
        init() {
            const container = this.#container, options = container.actualOptions;
            this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio$1;
            this.reduceFactor = defaultReduceFactor;
            const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
            if (element) {
                canvas.size.width = element.offsetWidth * ratio;
                canvas.size.height = element.offsetHeight * ratio;
            }
        }
        initParticle(particle) {
            const options = particle.options, ratio = this.pixelRatio, moveOptions = options.move, moveDistance = moveOptions.distance, props = particle.retina;
            props.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
            props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
            props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
            const maxDistance = props.maxDistance;
            maxDistance.horizontal = moveDistance.horizontal === undefined ? undefined : moveDistance.horizontal * ratio;
            maxDistance.vertical = moveDistance.vertical === undefined ? undefined : moveDistance.vertical * ratio;
        }
    }

    function guardCheck(container) {
        return !container.destroyed;
    }
    function updateDelta(delta, value, fpsLimit = defaultFps, smooth = false) {
        delta.value = value;
        delta.factor = smooth ? defaultFps / fpsLimit : (defaultFps * value) / millisecondsToSeconds$1;
    }
    function loadContainerOptions(pluginManager, container, ...sourceOptionsArr) {
        const options = new Options(pluginManager, container);
        loadOptions(options, ...sourceOptionsArr);
        return options;
    }
    class Container {
        actualOptions;
        canvas;
        destroyed;
        effectDrawers;
        fpsLimit;
        hdr;
        hdrMode;
        id;
        pageHidden;
        particleCreatedPlugins;
        particleDestroyedPlugins;
        particlePositionPlugins;
        particleUpdaters;
        particles;
        peakNits;
        plugins;
        retina;
        shapeDrawers;
        started;
        zLayers;
        #delay;
        #delayTimeout;
        #delta = { value: 0, factor: 0 };
        #dispatchCallback;
        #drawAnimationFrame;
        #duration;
        #eventListeners;
        #firstStart;
        #initialSourceOptions;
        #lastFrameTime;
        #lifeTime;
        #onDestroy;
        #options;
        #paused;
        #pluginManager;
        #smooth;
        #sourceOptions;
        constructor(params) {
            const { dispatchCallback, pluginManager, id, onDestroy, sourceOptions } = params;
            this.#pluginManager = pluginManager;
            this.#dispatchCallback = dispatchCallback;
            this.#onDestroy = onDestroy;
            this.id = Symbol(id);
            this.fpsLimit = 120;
            this.hdr = false;
            this.hdrMode = exports.HdrMode.standard;
            this.peakNits = 400;
            this.#smooth = false;
            this.#delay = 0;
            this.#duration = 0;
            this.#lifeTime = 0;
            this.#firstStart = true;
            this.started = false;
            this.destroyed = false;
            this.#paused = true;
            this.#lastFrameTime = 0;
            this.zLayers = 100;
            this.pageHidden = false;
            this.#sourceOptions = sourceOptions;
            this.#initialSourceOptions = sourceOptions;
            this.effectDrawers = new Map();
            this.shapeDrawers = new Map();
            this.particleUpdaters = [];
            this.retina = new Retina(this);
            this.canvas = new CanvasManager(this.#pluginManager, this);
            this.particles = new ParticlesManager(this.#pluginManager, this);
            this.plugins = [];
            this.particleDestroyedPlugins = [];
            this.particleCreatedPlugins = [];
            this.particlePositionPlugins = [];
            this.#options = loadContainerOptions(this.#pluginManager, this);
            this.actualOptions = loadContainerOptions(this.#pluginManager, this);
            this.#eventListeners = new EventListeners(this);
            this.dispatchEvent(exports.EventType.containerBuilt);
        }
        get animationStatus() {
            return !this.#paused && !this.pageHidden && guardCheck(this);
        }
        get options() {
            return this.#options;
        }
        get sourceOptions() {
            return this.#sourceOptions;
        }
        addLifeTime(value) {
            this.#lifeTime += value;
        }
        alive() {
            return !this.#duration || this.#lifeTime <= this.#duration;
        }
        destroy(remove = true) {
            if (!guardCheck(this)) {
                return;
            }
            this.stop();
            this.particles.destroy();
            this.canvas.destroy();
            for (const [, effectDrawer] of this.effectDrawers) {
                effectDrawer.destroy?.(this);
            }
            for (const [, shapeDrawer] of this.shapeDrawers) {
                shapeDrawer.destroy?.(this);
            }
            for (const plugin of this.plugins) {
                plugin.destroy?.();
            }
            this.effectDrawers = new Map();
            this.shapeDrawers = new Map();
            this.particleUpdaters = [];
            this.plugins.length = 0;
            this.#pluginManager.clearPlugins(this);
            this.destroyed = true;
            this.#onDestroy(remove);
            this.dispatchEvent(exports.EventType.containerDestroyed);
        }
        dispatchEvent(type, data) {
            this.#dispatchCallback(type, {
                container: this,
                data,
            });
        }
        draw(force) {
            if (!guardCheck(this)) {
                return;
            }
            let refreshTime = force;
            this.#drawAnimationFrame = animate((timestamp) => {
                if (refreshTime) {
                    this.#lastFrameTime = undefined;
                    refreshTime = false;
                }
                this.#nextFrame(timestamp);
            });
        }
        async export(type, options = {}) {
            for (const plugin of this.plugins) {
                if (!plugin.export) {
                    continue;
                }
                const res = await plugin.export(type, options);
                if (!res.supported) {
                    continue;
                }
                return res.blob;
            }
            getLogger().error(`Export plugin with type ${type} not found`);
            return undefined;
        }
        async init() {
            if (!guardCheck(this)) {
                return;
            }
            const allContainerPlugins = new Map();
            for (const plugin of this.#pluginManager.plugins) {
                const containerPlugin = await plugin.getPlugin(this);
                if (containerPlugin.preInit) {
                    await containerPlugin.preInit();
                }
                allContainerPlugins.set(plugin, containerPlugin);
            }
            await this.initDrawersAndUpdaters();
            this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
            this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
            this.plugins.length = 0;
            this.particleDestroyedPlugins.length = 0;
            this.particleCreatedPlugins.length = 0;
            this.particlePositionPlugins.length = 0;
            for (const [plugin, containerPlugin] of allContainerPlugins) {
                if (plugin.needsPlugin(this.actualOptions)) {
                    this.plugins.push(containerPlugin);
                    if (containerPlugin.particleCreated) {
                        this.particleCreatedPlugins.push(containerPlugin);
                    }
                    if (containerPlugin.particleDestroyed) {
                        this.particleDestroyedPlugins.push(containerPlugin);
                    }
                    if (containerPlugin.particlePosition) {
                        this.particlePositionPlugins.push(containerPlugin);
                    }
                }
            }
            this.retina.init();
            this.canvas.init();
            this.updateActualOptions();
            this.canvas.initBackground();
            this.canvas.resize();
            const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
            this.hdrMode = hdrOptions.mode;
            this.peakNits = hdrOptions.peakNits;
            this.zLayers = zLayers;
            this.#duration = getRangeValue(duration) * millisecondsToSeconds$1;
            this.#delay = getRangeValue(delay) * millisecondsToSeconds$1;
            this.#lifeTime = 0;
            this.fpsLimit = fpsLimit > minFpsLimit ? fpsLimit : defaultFpsLimit;
            this.#smooth = smooth;
            for (const plugin of this.plugins) {
                await plugin.init?.();
            }
            await this.particles.init();
            this.dispatchEvent(exports.EventType.containerInit);
            this.particles.setDensity();
            for (const plugin of this.plugins) {
                plugin.particlesSetup?.();
            }
            this.dispatchEvent(exports.EventType.particlesSetup);
        }
        async initDrawersAndUpdaters() {
            const pluginManager = this.#pluginManager;
            this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
            this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
            this.particleUpdaters = await pluginManager.getUpdaters(this, true);
        }
        pause() {
            if (!guardCheck(this)) {
                return;
            }
            if (this.#drawAnimationFrame !== undefined) {
                cancelAnimation(this.#drawAnimationFrame);
                this.#drawAnimationFrame = undefined;
            }
            if (this.#paused) {
                return;
            }
            for (const plugin of this.plugins) {
                plugin.pause?.();
            }
            if (!this.pageHidden) {
                this.#paused = true;
            }
            this.dispatchEvent(exports.EventType.containerPaused);
        }
        play(force) {
            if (!guardCheck(this)) {
                return;
            }
            const needsUpdate = this.#paused || force;
            if (this.#firstStart && !this.actualOptions.autoPlay) {
                this.#firstStart = false;
                return;
            }
            if (this.#paused) {
                this.#paused = false;
            }
            if (needsUpdate) {
                for (const plugin of this.plugins) {
                    if (plugin.play) {
                        plugin.play();
                    }
                }
            }
            this.dispatchEvent(exports.EventType.containerPlay);
            this.draw(needsUpdate ?? false);
        }
        async refresh() {
            if (!guardCheck(this)) {
                return;
            }
            this.stop();
            return this.start();
        }
        async reset(sourceOptions) {
            if (!guardCheck(this)) {
                return;
            }
            this.#initialSourceOptions = sourceOptions;
            this.#sourceOptions = sourceOptions;
            this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
            this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
            return this.refresh();
        }
        async start() {
            if (!guardCheck(this) || this.started) {
                return;
            }
            await this.init();
            this.started = true;
            await new Promise(resolve => {
                const start = async () => {
                    this.#eventListeners.addListeners();
                    for (const plugin of this.plugins) {
                        await plugin.start?.();
                    }
                    this.dispatchEvent(exports.EventType.containerStarted);
                    this.play();
                    resolve();
                };
                this.#delayTimeout = setTimeout(() => void start(), this.#delay);
            });
        }
        stop() {
            if (!guardCheck(this) || !this.started) {
                return;
            }
            if (this.#delayTimeout) {
                clearTimeout(this.#delayTimeout);
                this.#delayTimeout = undefined;
            }
            this.#firstStart = true;
            this.started = false;
            this.#eventListeners.removeListeners();
            this.pause();
            this.particles.clear();
            this.canvas.stop();
            for (const plugin of this.plugins) {
                plugin.stop?.();
            }
            this.particleCreatedPlugins.length = 0;
            this.particleDestroyedPlugins.length = 0;
            this.particlePositionPlugins.length = 0;
            this.#sourceOptions = this.#options;
            this.dispatchEvent(exports.EventType.containerStopped);
        }
        updateActualOptions() {
            let refresh = false;
            for (const plugin of this.plugins) {
                if (plugin.updateActualOptions) {
                    refresh = plugin.updateActualOptions() || refresh;
                }
            }
            return refresh;
        }
        #nextFrame(timestamp) {
            try {
                if (!this.#smooth &&
                    this.#lastFrameTime !== undefined &&
                    timestamp < this.#lastFrameTime + millisecondsToSeconds$1 / this.fpsLimit) {
                    this.draw(false);
                    return;
                }
                this.#lastFrameTime ??= timestamp;
                updateDelta(this.#delta, timestamp - this.#lastFrameTime, this.fpsLimit, this.#smooth);
                this.addLifeTime(this.#delta.value);
                this.#lastFrameTime = timestamp;
                if (this.#delta.value > millisecondsToSeconds$1) {
                    this.draw(false);
                    return;
                }
                this.canvas.render.drawParticles(this.#delta);
                if (!this.alive()) {
                    this.destroy();
                    return;
                }
                if (this.animationStatus) {
                    this.draw(false);
                }
            }
            catch (e) {
                getLogger().error("error in animation loop", e);
            }
        }
    }

    var Container$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        Container: Container
    });

    class BackgroundMaskPluginInstance {
        layer = exports.DrawLayer.BackgroundMask;
        #container;
        #coverColorStyle;
        #coverImage;
        #defaultCompositeValue;
        #maskElement;
        #maskWarnings = new Set();
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        canvasClear() {
            const backgroundMask = this.#container.actualOptions.backgroundMask;
            if (!backgroundMask?.enable) {
                return false;
            }
            return this.canvasPaint();
        }
        canvasPaint() {
            const { backgroundMask } = this.#container.actualOptions;
            if (!backgroundMask?.enable) {
                return false;
            }
            const canvas = this.#container.canvas;
            canvas.render.canvasClear();
            const cover = backgroundMask.cover;
            let dynamicUsed = false;
            const maskElement = this.#maskElement;
            if (maskElement) {
                dynamicUsed = true;
                canvas.render.draw(ctx => {
                    try {
                        ctx.drawImage(maskElement, originPoint.x, originPoint.y, canvas.size.width, canvas.size.height);
                    }
                    catch {
                        this.#maskWarnOnce("mask-element-draw-error", "Error drawing background mask cover element onto canvas");
                    }
                });
            }
            if (cover.draw) {
                dynamicUsed = true;
                const drawFn = cover.draw;
                canvas.render.draw(ctx => {
                    try {
                        drawFn(ctx, { value: 0, factor: 1 });
                    }
                    catch {
                        this.#maskWarnOnce("mask-draw-error", "Error in mask cover.draw callback");
                    }
                });
            }
            if (!dynamicUsed) {
                if (this.#coverImage) {
                    canvas.render.paintImage(this.#coverImage.image, this.#coverImage.opacity);
                }
                else {
                    canvas.render.paintBase(this.#coverColorStyle);
                }
            }
            return true;
        }
        destroy() {
            this.#maskElement = null;
            this.#maskWarnings.clear();
        }
        drawSettingsCleanup(context) {
            if (!this.#defaultCompositeValue) {
                return;
            }
            context.globalCompositeOperation = this.#defaultCompositeValue;
        }
        drawSettingsSetup(context) {
            const previousComposite = context.globalCompositeOperation, backgroundMask = this.#container.actualOptions.backgroundMask;
            this.#defaultCompositeValue = previousComposite;
            context.globalCompositeOperation = backgroundMask?.enable ? backgroundMask.composite : previousComposite;
        }
        async init() {
            this.#maskWarnings.clear();
            await this.#initCover();
            this.#resolveMaskElement();
        }
        #initCover = async () => {
            const options = this.#container.actualOptions, cover = options.backgroundMask?.cover, color = cover?.color;
            if (color) {
                const coverRgb = rangeColorToRgb(this.#pluginManager, color);
                if (coverRgb) {
                    const coverColor = {
                        ...coverRgb,
                        a: cover.opacity,
                    };
                    this.#coverColorStyle = getStyleFromRgb(coverColor, this.#container.hdr, coverColor.a, this.#container.peakNits, this.#container.hdrMode);
                }
            }
            else if (cover?.image) {
                const coverImage = cover.image;
                await new Promise((resolve, reject) => {
                    const img = safeDocument().createElement("img");
                    img.addEventListener("load", () => {
                        this.#coverImage = {
                            image: img,
                            opacity: cover.opacity,
                        };
                        resolve();
                    });
                    img.addEventListener("error", () => {
                        reject(new Error("Error loading image"));
                    });
                    img.src = coverImage;
                });
            }
        };
        #maskWarnOnce = (key, message) => {
            if (this.#maskWarnings.has(key)) {
                return;
            }
            this.#maskWarnings.add(key);
            getLogger().warning(`[tsParticles BackgroundMask] ${message}`);
        };
        #resolveMaskElement = () => {
            const cover = this.#container.actualOptions.backgroundMask?.cover;
            this.#maskElement = null;
            if (!cover?.element) {
                return;
            }
            if (typeof cover.element === "string") {
                if (typeof document !== "undefined") {
                    const node = document.querySelector(cover.element);
                    if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
                        this.#maskElement = node;
                    }
                    else if (node) {
                        this.#maskWarnOnce("mask-element-not-supported", `Mask cover element "${cover.element}" matched a non-drawable element (expected canvas, video, or img)`);
                    }
                    else {
                        this.#maskWarnOnce("mask-element-not-found", `Mask cover element selector "${cover.element}" not found in the DOM`);
                    }
                }
            }
            else if (cover.element instanceof HTMLCanvasElement ||
                cover.element instanceof OffscreenCanvas ||
                cover.element instanceof HTMLVideoElement ||
                cover.element instanceof HTMLImageElement) {
                this.#maskElement = cover.element;
            }
        };
    }

    var BackgroundMaskPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        BackgroundMaskPluginInstance: BackgroundMaskPluginInstance
    });

    const moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
    function applyDistance(particle) {
        const initialPosition = particle.initialPosition, { dx, dy } = getDistances(initialPosition, particle.position), dxFixed = Math.abs(dx), dyFixed = Math.abs(dy), { maxDistance } = particle.retina, hDistance = maxDistance.horizontal, vDistance = maxDistance.vertical;
        if (!hDistance && !vDistance) {
            return;
        }
        const hasHDistance = (hDistance && dxFixed >= hDistance) ?? false, hasVDistance = (vDistance && dyFixed >= vDistance) ?? false;
        if ((hasHDistance || hasVDistance) && !particle.misplaced) {
            particle.misplaced = (!!hDistance && dxFixed > hDistance) || (!!vDistance && dyFixed > vDistance);
            if (hDistance) {
                particle.velocity.x = particle.velocity.y * half$2 - particle.velocity.x;
            }
            if (vDistance) {
                particle.velocity.y = particle.velocity.x * half$2 - particle.velocity.y;
            }
        }
        else if ((!hDistance || dxFixed < hDistance) && (!vDistance || dyFixed < vDistance) && particle.misplaced) {
            particle.misplaced = false;
        }
        else if (particle.misplaced) {
            const pos = particle.position, vel = particle.velocity;
            if (hDistance &&
                ((pos.x < initialPosition.x && vel.x < minVelocity) || (pos.x > initialPosition.x && vel.x > minVelocity))) {
                vel.x *= -getRandom();
            }
            if (vDistance &&
                ((pos.y < initialPosition.y && vel.y < minVelocity) || (pos.y > initialPosition.y && vel.y > minVelocity))) {
                vel.y *= -getRandom();
            }
        }
    }
    function move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, reduceFactor, delta) {
        applyPath(particle, delta);
        const gravityOptions = particle.gravity, gravityFactor = gravityOptions?.enable && gravityOptions.inverse ? -identity$3 : identity$3;
        if (moveDrift && moveSpeed) {
            particle.velocity.x += (moveDrift * delta.factor) / (moveSpeedFactor * moveSpeed);
        }
        if (gravityOptions?.enable && moveSpeed) {
            particle.velocity.y +=
                (gravityFactor * (gravityOptions.acceleration * delta.factor)) / (moveSpeedFactor * moveSpeed);
        }
        const decay = particle.moveDecay;
        particle.velocity.multTo(decay ?? noDecay);
        const velocity = particle.velocity.mult(moveSpeed);
        if (gravityOptions?.enable &&
            maxSpeed > minVelocity &&
            ((!gravityOptions.inverse && velocity.y >= minVelocity && velocity.y >= maxSpeed) ||
                (gravityOptions.inverse && velocity.y <= minVelocity && velocity.y <= -maxSpeed))) {
            velocity.y = gravityFactor * maxSpeed;
            if (moveSpeed) {
                particle.velocity.y = velocity.y / moveSpeed;
            }
        }
        const zIndexOptions = particle.options.zIndex, zVelocityFactor = (identity$3 - particle.zIndexFactor) ** zIndexOptions.velocityRate;
        velocity.multTo(zVelocityFactor);
        velocity.multTo(reduceFactor);
        const { position } = particle;
        position.addTo(velocity);
        if (moveOptions.vibrate) {
            position.x += Math.sin(position.x * Math.cos(position.y)) * reduceFactor;
            position.y += Math.cos(position.y * Math.sin(position.x)) * reduceFactor;
        }
    }
    function spin(container, particle, moveSpeed, reduceFactor) {
        if (!particle.spin) {
            return;
        }
        const spinClockwise = particle.spin.direction === exports.RotateDirection.clockwise, updateFunc = {
            x: spinClockwise ? Math.cos : Math.sin,
            y: spinClockwise ? Math.sin : Math.cos,
        };
        particle.position.x =
            particle.spin.center.x + particle.spin.radius * updateFunc.x(particle.spin.angle) * reduceFactor;
        particle.position.y =
            particle.spin.center.y + particle.spin.radius * updateFunc.y(particle.spin.angle) * reduceFactor;
        particle.spin.radius += particle.spin.acceleration * reduceFactor;
        const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height), halfMaxSize = maxCanvasSize * half$2;
        if (particle.spin.radius > halfMaxSize) {
            particle.spin.radius = halfMaxSize;
            particle.spin.acceleration *= -identity$3;
        }
        else if (particle.spin.radius < minSpinRadius) {
            particle.spin.radius = minSpinRadius;
            particle.spin.acceleration *= -identity$3;
        }
        particle.spin.angle += moveSpeed * spinFactor * (identity$3 - particle.spin.radius / maxCanvasSize);
    }
    function applyPath(particle, delta) {
        const particlesOptions = particle.options, pathOptions = particlesOptions.move.path, pathEnabled = pathOptions.enable;
        if (!pathEnabled) {
            return;
        }
        const pathDelay = particle.pathDelay ?? defaultPathDelay;
        if (particle.lastPathTime <= pathDelay) {
            particle.lastPathTime += delta.value;
            return;
        }
        const path = particle.pathGenerator?.generate(particle, delta);
        if (path) {
            particle.velocity.addTo(path);
        }
        if (pathOptions.clamp) {
            particle.velocity.x = clamp(particle.velocity.x, -identity$3, identity$3);
            particle.velocity.y = clamp(particle.velocity.y, -identity$3, identity$3);
        }
        particle.lastPathTime -= pathDelay;
    }
    function getProximitySpeedFactor(particle) {
        const mod = particle.getModifier("slow");
        return mod?.enabled ? (mod.speedFactor ?? identity$3) : identity$3;
    }
    function initSpin(container, particle) {
        const options = particle.options, spinOptions = options.move.spin;
        if (!spinOptions.enable) {
            return;
        }
        const spinPos = spinOptions.position ?? { x: 50, y: 50 }, spinFactor = 0.01, spinCenter = {
            x: spinPos.x * spinFactor * container.canvas.size.width,
            y: spinPos.y * spinFactor * container.canvas.size.height,
        }, pos = particle.getPosition(), distance = getDistance(pos, spinCenter), spinAcceleration = getRangeValue(spinOptions.acceleration);
        particle.retina.spinAcceleration = spinAcceleration * container.retina.pixelRatio;
        particle.spin = {
            center: spinCenter,
            direction: particle.velocity.x >= minVelocity ? exports.RotateDirection.clockwise : exports.RotateDirection.counterClockwise,
            angle: getRandom() * doublePI,
            radius: distance,
            acceleration: particle.retina.spinAcceleration,
        };
    }

    const defaultSizeFactor = 1, defaultDeltaFactor = 1;
    class MovePluginInstance {
        availablePathGenerators;
        pathGenerators;
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.availablePathGenerators = new Map();
            this.pathGenerators = new Map();
        }
        destroy() {
            this.availablePathGenerators = new Map();
            this.pathGenerators = new Map();
        }
        isEnabled(particle) {
            return !particle.destroyed && particle.options.move.enable;
        }
        particleCreated(particle) {
            const options = particle.options, moveOptions = options.move, gravityOptions = moveOptions.gravity, pathOptions = moveOptions.path;
            particle.moveDecay = decayOffset - getRangeValue(moveOptions.decay);
            particle.pathDelay = getRangeValue(pathOptions.delay.value) * millisecondsToSeconds$1;
            if (pathOptions.generator) {
                let pathGenerator = this.pathGenerators.get(pathOptions.generator);
                if (!pathGenerator) {
                    pathGenerator = this.availablePathGenerators.get(pathOptions.generator);
                    if (pathGenerator) {
                        this.pathGenerators.set(pathOptions.generator, pathGenerator);
                        pathGenerator.init();
                    }
                }
                particle.pathGenerator = pathGenerator;
            }
            particle.gravity = {
                enable: gravityOptions.enable,
                acceleration: getRangeValue(gravityOptions.acceleration),
                inverse: gravityOptions.inverse,
            };
            initSpin(this.#container, particle);
        }
        particleDestroyed(particle) {
            const pathGenerator = particle.pathGenerator;
            pathGenerator?.reset(particle);
        }
        particleUpdate(particle, delta) {
            const particleOptions = particle.options, moveOptions = particleOptions.move;
            if (!moveOptions.enable) {
                return;
            }
            const container = this.#container, slowFactor = getProximitySpeedFactor(particle), reduceFactor = container.retina.reduceFactor, baseSpeed = particle.retina.moveSpeed, moveDrift = particle.retina.moveDrift, maxSize = particle.size.max, sizeFactor = moveOptions.size ? particle.getRadius() / maxSize : defaultSizeFactor, deltaFactor = delta.factor || defaultDeltaFactor, moveSpeed = baseSpeed * sizeFactor * slowFactor * deltaFactor * half$2, maxSpeed = particle.retina.maxSpeed;
            if (moveOptions.spin.enable) {
                spin(container, particle, moveSpeed, reduceFactor);
            }
            else {
                move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, reduceFactor, delta);
            }
            applyDistance(particle);
        }
        preInit() {
            return this.#init();
        }
        redrawInit() {
            return this.#init();
        }
        update() {
            for (const pathGenerator of this.pathGenerators.values()) {
                pathGenerator.update();
            }
        }
        async #init() {
            const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
            if (!availablePathGenerators) {
                return;
            }
            this.availablePathGenerators = availablePathGenerators;
            this.pathGenerators = new Map();
            for (const pathGenerator of this.pathGenerators.values()) {
                pathGenerator.init();
            }
        }
    }

    var MovePluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        MovePluginInstance: MovePluginInstance
    });

    function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
        const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
        let selectedPixels = 0;
        const positionOffset = {
            x: (canvasSize.width * position.x) / percentDenominator - width * scale * half$2,
            y: (canvasSize.height * position.y) / percentDenominator - height * scale * half$2,
        };
        while (selectedPixels < maxParticles && indexArray.length) {
            const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
                x: nextIndex % width,
                y: Math.floor(nextIndex / width),
            }, row = data.pixels[pixelPos.y];
            if (!row) {
                continue;
            }
            const pixel = row[pixelPos.x];
            if (!pixel) {
                continue;
            }
            const shouldCreateParticle = filter(pixel);
            if (!shouldCreateParticle) {
                continue;
            }
            const pos = {
                x: pixelPos.x * scale + positionOffset.x,
                y: pixelPos.y * scale + positionOffset.y,
            }, pOptions = {};
            if (override.color) {
                pOptions.paint = {
                    fill: {
                        color: {
                            value: pixel,
                        },
                        enable: true,
                    },
                };
            }
            if (override.opacity) {
                pOptions["opacity"] = {
                    value: pixel.a,
                };
            }
            container.particles.addParticle(pos, pOptions);
            selectedPixels++;
        }
    }
    function shuffle(array) {
        const lengthOffset = 1, minIndex = 0;
        for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
            const randomIndex = Math.floor(getRandom() * currentIndex), currentItem = array[currentIndex], randomItem = array[randomIndex];
            if (randomItem === currentItem) {
                continue;
            }
            if (randomItem === undefined || currentItem === undefined) {
                continue;
            }
            array[currentIndex] = randomItem;
            array[randomIndex] = currentItem;
        }
        return array;
    }
    const range = (n) => [...Array(n).keys()];

    class CanvasMaskPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        async init() {
            const container = this.#container, options = container.actualOptions.canvasMask;
            if (!options?.enable) {
                return;
            }
            let pixelData = {
                pixels: [],
                height: 0,
                width: 0,
            };
            const offset = options.pixels.offset;
            if (options.image) {
                const url = options.image.src;
                if (!url) {
                    return;
                }
                pixelData = await getImageData(url, offset, container.canvas.render.settings);
            }
            else if (options.text) {
                const textOptions = options.text, data = getTextData(textOptions, offset, textOptions.fill, container.canvas.render.settings);
                if (isNull(data)) {
                    return;
                }
                pixelData = data;
            }
            else if (options.element ?? options.selector) {
                const canvas = options.element ?? (options.selector && safeDocument().querySelector(options.selector));
                if (!canvas) {
                    return;
                }
                const context = canvas.getContext("2d", container.canvas.render.settings);
                if (!context) {
                    return;
                }
                pixelData = getCanvasImageData(context, canvas, offset);
            }
            addParticlesFromCanvasPixels(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);
        }
    }

    var CanvasMaskPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        CanvasMaskPluginInstance: CanvasMaskPluginInstance
    });

    const touchDelay = 500;
    class InteractivityEventListeners {
        #canPush = true;
        #clickPositionPlugins;
        #container;
        #handlers;
        #interactionManager;
        #touches;
        constructor(container, interactionManager) {
            this.#container = container;
            this.#clickPositionPlugins = [];
            this.#interactionManager = interactionManager;
            this.#touches = new Map();
            this.#handlers = {
                mouseDown: () => {
                    this.#mouseDown();
                },
                mouseLeave: () => {
                    this.#mouseTouchFinish();
                },
                mouseMove: (e) => {
                    this.#mouseTouchMove(e);
                },
                mouseUp: (e) => {
                    this.#mouseTouchClick(e);
                },
                touchStart: (e) => {
                    this.#touchStart(e);
                },
                touchMove: (e) => {
                    this.#mouseTouchMove(e);
                },
                touchEnd: (e) => {
                    this.#touchEnd(e);
                },
                touchCancel: (e) => {
                    this.#touchEnd(e);
                },
                touchEndClick: (e) => {
                    this.#touchEndClick(e);
                },
                visibilityChange: () => {
                    this.#handleVisibilityChange();
                },
            };
        }
        addListeners() {
            this.#manageListeners(true);
        }
        init() {
            this.#clickPositionPlugins.length = 0;
            for (const plugin of this.#container.plugins.filter(p => !!p.clickPositionValid)) {
                this.#clickPositionPlugins.push(plugin);
            }
        }
        removeListeners() {
            this.#manageListeners(false);
        }
        #doMouseTouchClick(e) {
            const container = this.#container, interactionManager = this.#interactionManager, options = container.actualOptions;
            if (this.#canPush) {
                const mouseInteractivity = interactionManager.interactivityData.mouse, mousePos = mouseInteractivity.position;
                if (!mousePos) {
                    return;
                }
                mouseInteractivity.clickPosition = { ...mousePos };
                mouseInteractivity.clickTime = performance.now();
                const onClick = options.interactivity?.events.onClick;
                if (!onClick?.mode) {
                    return;
                }
                executeOnSingleOrMultiple(onClick.mode, mode => {
                    interactionManager.handleClickMode(mode);
                });
            }
            if (e.type === "touchend") {
                setTimeout(() => {
                    this.#mouseTouchFinish();
                }, touchDelay);
            }
        }
        #handleVisibilityChange() {
            this.#mouseTouchFinish();
        }
        #manageInteractivityListeners(add) {
            const handlers = this.#handlers, container = this.#container, interactionManager = this.#interactionManager, options = container.actualOptions, interactivityEl = interactionManager.interactivityData.element;
            if (!interactivityEl) {
                return;
            }
            const html = interactivityEl, canvas = container.canvas;
            canvas.setPointerEvents(html === canvas.domElement ? "initial" : "none");
            if (add && !(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
                return;
            }
            manageListener(interactivityEl, mouseMoveEvent, handlers.mouseMove, add);
            manageListener(interactivityEl, touchStartEvent$1, handlers.touchStart, add);
            manageListener(interactivityEl, touchMoveEvent, handlers.touchMove, add);
            if (add) {
                if (options.interactivity?.events.onClick.enable) {
                    manageListener(interactivityEl, touchEndEvent, handlers.touchEndClick, add);
                    manageListener(interactivityEl, mouseUpEvent, handlers.mouseUp, add);
                    manageListener(interactivityEl, mouseDownEvent$1, handlers.mouseDown, add);
                }
                else {
                    manageListener(interactivityEl, touchEndEvent, handlers.touchEnd, add);
                }
            }
            else {
                manageListener(interactivityEl, touchEndEvent, handlers.touchEndClick, add);
                manageListener(interactivityEl, mouseUpEvent, handlers.mouseUp, add);
                manageListener(interactivityEl, mouseDownEvent$1, handlers.mouseDown, add);
                manageListener(interactivityEl, touchEndEvent, handlers.touchEnd, add);
            }
            manageListener(interactivityEl, mouseLeaveEvent, handlers.mouseLeave, add);
            manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
        }
        #manageListeners(add) {
            const handlers = this.#handlers, container = this.#container, interactionManager = this.#interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.domElement;
            if (detectType === InteractivityDetect.window) {
                interactionManager.interactivityData.element = safeDocument();
            }
            else if (detectType === InteractivityDetect.parent && canvasEl) {
                interactionManager.interactivityData.element = canvasEl.parentElement ?? canvasEl.parentNode;
            }
            else {
                interactionManager.interactivityData.element = canvasEl;
            }
            this.#manageInteractivityListeners(add);
            manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
        }
        #mouseDown() {
            const { interactivityData } = this.#interactionManager, { mouse } = interactivityData;
            mouse.clicking = true;
            mouse.downPosition = mouse.position;
        }
        #mouseTouchClick(e) {
            const container = this.#container, interactionManager = this.#interactionManager, options = container.actualOptions, { mouse } = interactionManager.interactivityData;
            mouse.inside = true;
            let handled = false;
            const mousePosition = mouse.position;
            if (!mousePosition || !options.interactivity?.events.onClick.enable) {
                return;
            }
            for (const plugin of this.#clickPositionPlugins) {
                handled = plugin.clickPositionValid?.(mousePosition) ?? false;
                if (handled) {
                    break;
                }
            }
            if (!handled) {
                this.#doMouseTouchClick(e);
            }
            mouse.clicking = false;
        }
        #mouseTouchFinish() {
            const { interactivityData } = this.#interactionManager, { mouse } = interactivityData;
            delete mouse.position;
            delete mouse.clickPosition;
            delete mouse.downPosition;
            interactivityData.status = mouseLeaveEvent;
            mouse.inside = false;
            mouse.clicking = false;
        }
        #mouseTouchMove(e) {
            const container = this.#container, interactionManager = this.#interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.domElement;
            if (!interactivity.element) {
                return;
            }
            interactivity.mouse.inside = true;
            let pos;
            if (e.type.startsWith("pointer")) {
                this.#canPush = true;
                const mouseEvent = e;
                if (interactivity.element === safeDocument()) {
                    if (canvasEl) {
                        const clientRect = canvasEl.getBoundingClientRect();
                        pos = {
                            x: mouseEvent.clientX - clientRect.left,
                            y: mouseEvent.clientY - clientRect.top,
                        };
                    }
                }
                else if (options.interactivity?.detectsOn === InteractivityDetect.parent) {
                    const source = mouseEvent.target, target = mouseEvent.currentTarget;
                    if (canvasEl) {
                        const sourceRect = source.getBoundingClientRect(), targetRect = target.getBoundingClientRect(), canvasRect = canvasEl.getBoundingClientRect();
                        pos = {
                            x: mouseEvent.offsetX + double * sourceRect.left - (targetRect.left + canvasRect.left),
                            y: mouseEvent.offsetY + double * sourceRect.top - (targetRect.top + canvasRect.top),
                        };
                    }
                    else {
                        pos = {
                            x: mouseEvent.offsetX,
                            y: mouseEvent.offsetY,
                        };
                    }
                }
                else if (mouseEvent.target === canvasEl) {
                    pos = {
                        x: mouseEvent.offsetX,
                        y: mouseEvent.offsetY,
                    };
                }
            }
            else {
                this.#canPush = e.type !== "touchmove";
                if (canvasEl) {
                    const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset], canvasRect = canvasEl.getBoundingClientRect();
                    if (!lastTouch) {
                        return;
                    }
                    pos = {
                        x: lastTouch.clientX - canvasRect.left,
                        y: lastTouch.clientY - canvasRect.top,
                    };
                }
            }
            const pxRatio = container.retina.pixelRatio;
            if (pos) {
                pos.x *= pxRatio;
                pos.y *= pxRatio;
            }
            interactivity.mouse.position = pos;
            interactivity.status = mouseMoveEvent;
        }
        #touchEnd(e) {
            const evt = e, touches = Array.from(evt.changedTouches);
            for (const touch of touches) {
                this.#touches.delete(touch.identifier);
            }
            this.#mouseTouchFinish();
        }
        #touchEndClick(e) {
            const evt = e, touches = Array.from(evt.changedTouches);
            for (const touch of touches) {
                this.#touches.delete(touch.identifier);
            }
            this.#mouseTouchClick(e);
        }
        #touchStart(e) {
            const evt = e, touches = Array.from(evt.changedTouches);
            for (const touch of touches) {
                this.#touches.set(touch.identifier, performance.now());
            }
            this.#mouseTouchMove(e);
        }
    }

    const clickRadius = 1, touchEndLengthOffset = 1, minCoordinate = 0;
    function safeIntersectionObserver(callback) {
        if (typeof IntersectionObserver === "undefined") {
            return;
        }
        return new IntersectionObserver(callback);
    }
    class InteractionManager {
        interactivityData;
        #clickHandlers;
        #container;
        #eventListeners;
        #externalInteractors;
        #interactors;
        #intersectionObserver;
        #particleInteractors;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
            this.#interactors = [];
            this.#externalInteractors = [];
            this.#particleInteractors = [];
            this.#clickHandlers = new Map();
            this.#eventListeners = new InteractivityEventListeners(container, this);
            this.interactivityData = {
                mouse: {
                    clicking: false,
                    inside: false,
                },
            };
            this.#intersectionObserver = safeIntersectionObserver(entries => {
                this.#intersectionManager(entries);
            });
        }
        addClickHandler(callback) {
            const container = this.#container, interactivityData = this.interactivityData;
            if (container.destroyed) {
                return;
            }
            const el = interactivityData.element;
            if (!el) {
                return;
            }
            const clickOrTouchHandler = (e, pos, radius) => {
                if (container.destroyed) {
                    return;
                }
                const pxRatio = container.retina.pixelRatio, posRetina = {
                    x: pos.x * pxRatio,
                    y: pos.y * pxRatio,
                }, particles = container.particles.grid.queryCircle(posRetina, radius * pxRatio);
                callback(e, particles);
            }, clickHandler = (e) => {
                if (container.destroyed) {
                    return;
                }
                const mouseEvent = e, pos = {
                    x: mouseEvent.offsetX,
                    y: mouseEvent.offsetY,
                };
                clickOrTouchHandler(e, pos, clickRadius);
            }, touchStartHandler = () => {
                if (container.destroyed) {
                    return;
                }
                touched = true;
                touchMoved = false;
            }, touchMoveHandler = () => {
                if (container.destroyed) {
                    return;
                }
                touchMoved = true;
            }, touchEndHandler = (e) => {
                if (container.destroyed) {
                    return;
                }
                if (touched && !touchMoved) {
                    const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - touchEndLengthOffset];
                    if (!lastTouch) {
                        return;
                    }
                    const element = container.canvas.domElement, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
                        x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
                        y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
                    };
                    clickOrTouchHandler(e, pos, Math.max(lastTouch.radiusX, lastTouch.radiusY));
                }
                touched = false;
                touchMoved = false;
            }, touchCancelHandler = () => {
                if (container.destroyed) {
                    return;
                }
                touched = false;
                touchMoved = false;
            };
            let touched = false, touchMoved = false;
            this.#clickHandlers.set(clickEvent, clickHandler);
            this.#clickHandlers.set(touchStartEvent$1, touchStartHandler);
            this.#clickHandlers.set(touchMoveEvent, touchMoveHandler);
            this.#clickHandlers.set(touchEndEvent, touchEndHandler);
            this.#clickHandlers.set(touchCancelEvent, touchCancelHandler);
            for (const [key, handler] of this.#clickHandlers) {
                el.addEventListener(key, handler);
            }
        }
        addListeners() {
            this.#eventListeners.addListeners();
        }
        clearClickHandlers() {
            const container = this.#container, interactivityData = this.interactivityData;
            if (container.destroyed) {
                return;
            }
            for (const [key, handler] of this.#clickHandlers) {
                interactivityData.element?.removeEventListener(key, handler);
            }
            this.#clickHandlers.clear();
        }
        externalInteract(delta) {
            for (const interactor of this.#externalInteractors) {
                const interactivityData = this.interactivityData;
                if (interactor.isEnabled(interactivityData)) {
                    interactor.interact(interactivityData, delta);
                }
            }
        }
        handleClickMode(mode) {
            if (this.#container.destroyed) {
                return;
            }
            const interactivityData = this.interactivityData;
            for (const interactor of this.#externalInteractors) {
                interactor.handleClickMode?.(mode, interactivityData);
            }
        }
        init() {
            this.#eventListeners.init();
            for (const interactor of this.#interactors) {
                switch (interactor.type) {
                    case InteractorType.external:
                        this.#externalInteractors.push(interactor);
                        break;
                    case InteractorType.particles:
                        this.#particleInteractors.push(interactor);
                        break;
                }
                interactor.init();
            }
        }
        async initInteractors() {
            const interactors = await this.#pluginManager.getInteractors?.(this.#container, true);
            if (!interactors) {
                return;
            }
            this.#interactors = interactors;
            this.#externalInteractors = [];
            this.#particleInteractors = [];
        }
        particlesInteract(particle, delta) {
            const interactivityData = this.interactivityData;
            for (const interactor of this.#externalInteractors) {
                interactor.clear(particle, delta);
            }
            for (const interactor of this.#particleInteractors) {
                if (interactor.isEnabled(particle, interactivityData)) {
                    interactor.interact(particle, interactivityData, delta);
                }
            }
        }
        removeListeners() {
            this.#eventListeners.removeListeners();
        }
        reset(particle) {
            const interactivityData = this.interactivityData;
            for (const interactor of this.#externalInteractors) {
                if (interactor.isEnabled(interactivityData)) {
                    interactor.reset(interactivityData, particle);
                }
            }
            for (const interactor of this.#particleInteractors) {
                if (interactor.isEnabled(particle, interactivityData)) {
                    interactor.reset(interactivityData, particle);
                }
            }
        }
        startObserving() {
            const interactivityData = this.interactivityData;
            if (interactivityData.element instanceof HTMLElement && this.#intersectionObserver) {
                this.#intersectionObserver.observe(interactivityData.element);
            }
        }
        stopObserving() {
            const interactivityData = this.interactivityData;
            if (interactivityData.element instanceof HTMLElement && this.#intersectionObserver) {
                this.#intersectionObserver.unobserve(interactivityData.element);
            }
        }
        updateMaxDistance() {
            let maxTotalDistance = 0;
            for (const interactor of this.#interactors) {
                if (interactor.maxDistance > maxTotalDistance) {
                    maxTotalDistance = interactor.maxDistance;
                }
            }
            const container = this.#container;
            container.particles.grid.setCellSize(maxTotalDistance * container.retina.pixelRatio);
        }
        #intersectionManager(entries) {
            const container = this.#container;
            if (container.destroyed || !container.actualOptions.pauseOnOutsideViewport) {
                return;
            }
            for (const entry of entries) {
                if (entry.target !== this.interactivityData.element) {
                    continue;
                }
                if (entry.isIntersecting) {
                    container.play();
                }
                else {
                    container.pause();
                }
            }
        }
    }

    class InteractivityPluginInstance {
        interactionManager;
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
            this.interactionManager = new InteractionManager(pluginManager, container);
            this.#container.addClickHandler = (callback) => {
                this.interactionManager.addClickHandler(callback);
            };
        }
        addClickHandler(callback) {
            this.interactionManager.addClickHandler(callback);
        }
        clearClickHandlers() {
            this.interactionManager.clearClickHandlers();
        }
        destroy() {
            this.clearClickHandlers();
            this.#pluginManager.interactors?.delete(this.#container);
        }
        particleCreated(particle) {
            const interactivityParticle = particle, interactivity = new Interactivity(this.#pluginManager, this.#container);
            interactivity.load(this.#container.actualOptions.interactivity);
            interactivity.load(interactivityParticle.options.interactivity);
            interactivityParticle.interactivity = interactivity;
        }
        particleReset(particle) {
            this.interactionManager.reset(particle);
        }
        postParticleUpdate(particle, delta) {
            this.interactionManager.particlesInteract(particle, delta);
        }
        postUpdate(delta) {
            this.interactionManager.externalInteract(delta);
            this.interactionManager.updateMaxDistance();
        }
        async preInit() {
            await this.interactionManager.initInteractors();
            this.interactionManager.init();
        }
        async redrawInit() {
            await this.interactionManager.initInteractors();
            this.interactionManager.init();
        }
        start() {
            this.interactionManager.addListeners();
            this.interactionManager.startObserving();
            return Promise.resolve();
        }
        stop() {
            this.interactionManager.removeListeners();
            this.interactionManager.stopObserving();
        }
    }

    var InteractivityPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        InteractivityPluginInstance: InteractivityPluginInstance
    });

    const shapeGenerators = new Map();
    class ShapeManager {
        addShapeGenerator(name, generator) {
            if (!this.getShapeGenerator(name)) {
                shapeGenerators.set(name, generator);
            }
        }
        getShapeGenerator(name) {
            return shapeGenerators.get(name);
        }
        getSupportedShapeGenerators() {
            return shapeGenerators.keys();
        }
    }

    var ShapeManager$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ShapeManager: ShapeManager
    });

    const defaultIndex$1 = 0;
    class EmittersInstancesManager {
        #containerArrays;
        #pluginManager;
        constructor(pluginManager) {
            this.#containerArrays = new Map();
            this.#pluginManager = pluginManager;
        }
        async addEmitter(container, options, position) {
            const emitterOptions = new Emitter();
            emitterOptions.load(options);
            const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
                this.removeEmitter(container, emitter);
            }, emitterOptions, position);
            await emitter.init();
            this.getArray(container).push(emitter);
            return emitter;
        }
        clear(container) {
            this.initContainer(container);
            this.#containerArrays.set(container, []);
        }
        getArray(container) {
            this.initContainer(container);
            let array = this.#containerArrays.get(container);
            if (!array) {
                array = [];
                this.#containerArrays.set(container, array);
            }
            return array;
        }
        initContainer(container) {
            if (this.#containerArrays.has(container)) {
                return;
            }
            this.#containerArrays.set(container, []);
            container.getEmitter = (idxOrName) => {
                const array = this.getArray(container);
                return idxOrName === undefined || isNumber(idxOrName)
                    ? array[idxOrName ?? defaultIndex$1]
                    : array.find(t => t.name === idxOrName);
            };
            container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
            container.removeEmitter = (idxOrName) => {
                const emitter = container.getEmitter?.(idxOrName);
                if (emitter) {
                    this.removeEmitter(container, emitter);
                }
            };
            container.playEmitter = (idxOrName) => {
                const emitter = container.getEmitter?.(idxOrName);
                if (emitter) {
                    emitter.externalPlay();
                }
            };
            container.pauseEmitter = (idxOrName) => {
                const emitter = container.getEmitter?.(idxOrName);
                if (emitter) {
                    emitter.externalPause();
                }
            };
        }
        removeEmitter(container, emitter) {
            const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
            if (index >= minIndex) {
                this.getArray(container).splice(index, deleteCount);
            }
        }
    }

    var EmittersInstancesManager$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        EmittersInstancesManager: EmittersInstancesManager
    });

    class EmittersPluginInstance {
        #container;
        #instancesManager;
        constructor(instancesManager, container) {
            this.#instancesManager = instancesManager;
            this.#container = container;
            this.#instancesManager.initContainer(container);
        }
        async init() {
            const emittersOptions = this.#container.actualOptions.emitters;
            if (isArray(emittersOptions)) {
                for (const emitterOptions of emittersOptions) {
                    await this.#instancesManager.addEmitter(this.#container, emitterOptions);
                }
            }
            else {
                await this.#instancesManager.addEmitter(this.#container, emittersOptions);
            }
        }
        pause() {
            for (const emitter of this.#instancesManager.getArray(this.#container)) {
                emitter.pause();
            }
        }
        play() {
            for (const emitter of this.#instancesManager.getArray(this.#container)) {
                emitter.play();
            }
        }
        resize() {
            for (const emitter of this.#instancesManager.getArray(this.#container)) {
                emitter.resize();
            }
        }
        stop() {
            this.#instancesManager.clear(this.#container);
        }
        update(delta) {
            this.#instancesManager.getArray(this.#container).forEach(emitter => {
                emitter.update(delta);
            });
        }
    }

    var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        EmittersPluginInstance: EmittersPluginInstance
    });

    class ExportImagePluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        async export(type, data) {
            const res = {
                supported: false,
            };
            switch (type) {
                case "image":
                    res.supported = true;
                    res.blob = await this.#exportImage(data);
                    break;
            }
            return res;
        }
        async #exportImage(data) {
            const element = this.#container.canvas.domElement;
            if (!element) {
                return;
            }
            return new Promise(resolve => {
                element.toBlob(blob => {
                    if (!blob) {
                        resolve(undefined);
                        return;
                    }
                    resolve(blob);
                }, data.type ?? "image/png", data.quality);
            });
        }
    }

    var ExportImagePluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ExportImagePluginInstance: ExportImagePluginInstance
    });

    const indent = 2;
    class ExportJSONPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        async export(type) {
            const res = {
                supported: false,
            };
            switch (type) {
                case "json":
                    res.supported = true;
                    res.blob = await this.#exportJSON();
                    break;
            }
            return res;
        }
        #exportJSON = async () => {
            const json = JSON.stringify(this.#container.actualOptions, (key, value) => {
                if (key.startsWith("_")) {
                    return;
                }
                return value;
            }, indent);
            return Promise.resolve(new Blob([json], { type: "application/json" }));
        };
    }

    var ExportJSONPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ExportJSONPluginInstance: ExportJSONPluginInstance
    });

    const videoTypes = ["webm", "ogg", "mp4", "x-matroska"], codecs = [
        "vp9",
        "vp9.0",
        "vp8",
        "vp8.0",
        "avc1",
        "av1",
        "h265",
        "h.265",
        "h264",
        "h.264",
        "opus",
        "pcm",
        "aac",
        "mpeg",
        "mp4a",
    ];
    function getVideoSupportedMimeTypes() {
        const isSupported = (type) => MediaRecorder.isTypeSupported(type), supported = [];
        videoTypes.forEach(type => {
            const mimeType = `video/${type}`;
            codecs.forEach(codec => {
                [
                    `${mimeType};codecs=${codec}`,
                    `${mimeType};codecs=${codec.toUpperCase()}`,
                ].forEach(variation => {
                    if (isSupported(variation)) {
                        supported.push(variation);
                    }
                });
            });
            if (isSupported(mimeType)) {
                supported.push(mimeType);
            }
        });
        return supported;
    }
    class ExportVideoPluginInstance {
        #container;
        #supportedTypes = [];
        constructor(container) {
            this.#container = container;
            this.#supportedTypes = getVideoSupportedMimeTypes();
        }
        async export(type, data) {
            const res = {
                supported: false,
            };
            switch (type) {
                case "video":
                    res.supported = true;
                    res.blob = await this.#exportVideo(data);
                    break;
            }
            return res;
        }
        async #exportVideo(data) {
            const element = this.#container.canvas.domElement;
            if (!element) {
                return;
            }
            return new Promise(resolve => {
                const stream = element.captureStream(data.fps ?? this.#container.actualOptions.fpsLimit), firstIndex = 0, mimeType = data.mimeType ?? this.#supportedTypes[firstIndex], recorder = new MediaRecorder(stream, {
                    mimeType,
                }), chunks = [], defaultDuration = 5;
                recorder.addEventListener("dataavailable", (event) => {
                    chunks.push(event.data);
                });
                recorder.addEventListener("stop", () => {
                    resolve(new Blob(chunks, { type: mimeType }));
                });
                recorder.start();
                setTimeout(() => {
                    recorder.stop();
                }, data.duration ?? defaultDuration * millisecondsToSeconds$1);
            });
        }
    }

    var ExportVideoPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ExportVideoPluginInstance: ExportVideoPluginInstance
    });

    const defaultIndex = 0;
    class AbsorbersInstancesManager {
        #containerArrays;
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
            this.#containerArrays = new Map();
        }
        async addAbsorber(container, options, position) {
            const { AbsorberInstance } = await Promise.resolve().then(function () { return AbsorberInstance$1; }), absorber = new AbsorberInstance(this.#pluginManager, container, options, position), array = this.getArray(container);
            array.push(absorber);
            return absorber;
        }
        clear(container) {
            this.initContainer(container);
            this.#containerArrays.set(container, []);
        }
        getArray(container) {
            this.initContainer(container);
            let array = this.#containerArrays.get(container);
            if (!array) {
                array = [];
                this.#containerArrays.set(container, array);
            }
            return array;
        }
        initContainer(container) {
            if (this.#containerArrays.has(container)) {
                return;
            }
            this.#containerArrays.set(container, []);
            container.getAbsorber ??= (idxOrName) => {
                const array = this.getArray(container);
                return idxOrName === undefined || isNumber(idxOrName)
                    ? array[idxOrName ?? defaultIndex]
                    : array.find(t => t.name === idxOrName);
            };
            container.addAbsorber ??= (options, position) => {
                return this.addAbsorber(container, options, position);
            };
        }
        removeAbsorber(container, absorber) {
            const index = this.getArray(container).indexOf(absorber), deleteCount = 1;
            if (index >= defaultIndex) {
                this.getArray(container).splice(index, deleteCount);
            }
        }
    }

    var AbsorbersInstancesManager$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        AbsorbersInstancesManager: AbsorbersInstancesManager
    });

    class AbsorbersPluginInstance {
        #container;
        #instancesManager;
        constructor(container, instancesManager) {
            this.#container = container;
            this.#instancesManager = instancesManager;
            this.#instancesManager.initContainer(container);
        }
        draw(context) {
            for (const absorber of this.#instancesManager.getArray(this.#container)) {
                absorber.draw(context);
            }
        }
        async init() {
            const absorbers = this.#container.actualOptions.absorbers, promises = executeOnSingleOrMultiple(absorbers, async (absorber) => {
                await this.#instancesManager.addAbsorber(this.#container, absorber);
            });
            if (isArray(promises)) {
                await Promise.all(promises);
            }
            else {
                await promises;
            }
        }
        particleUpdate(particle, delta) {
            for (const absorber of this.#instancesManager.getArray(this.#container)) {
                absorber.attract(particle, delta);
                if (particle.destroyed) {
                    break;
                }
            }
        }
        resize() {
            for (const absorber of this.#instancesManager.getArray(this.#container)) {
                absorber.resize();
            }
        }
        stop() {
            this.#instancesManager.clear(this.#container);
        }
    }

    var AbsorbersPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        AbsorbersPluginInstance: AbsorbersPluginInstance
    });

    class BlendPluginInstance {
        layer = exports.DrawLayer.CanvasSetup;
        #container;
        #defaultCompositeValue;
        constructor(container) {
            this.#container = container;
        }
        drawParticleCleanup(context, particle) {
            if (!particle.options.blend?.enable) {
                return;
            }
            context.globalCompositeOperation = particle.originalBlendMode ?? defaultCompositeValue;
            particle.originalBlendMode = undefined;
        }
        drawParticleSetup(context, particle) {
            if (!particle.options.blend?.enable) {
                return;
            }
            particle.originalBlendMode = context.globalCompositeOperation;
            context.globalCompositeOperation = particle.options.blend.mode;
        }
        drawSettingsCleanup(context) {
            if (!this.#defaultCompositeValue) {
                return;
            }
            context.globalCompositeOperation = this.#defaultCompositeValue;
        }
        drawSettingsSetup(context) {
            const previousComposite = context.globalCompositeOperation, blend = this.#container.actualOptions.blend;
            this.#defaultCompositeValue = previousComposite;
            context.globalCompositeOperation = blend?.enable ? blend.mode : previousComposite;
        }
    }

    var BlendPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        BlendPluginInstance: BlendPluginInstance
    });

    class ImagePreloaderInstance {
        #container;
        #engine;
        constructor(engine, container) {
            this.#engine = engine;
            this.#container = container;
        }
        destroy() {
            this.#engine.images?.delete(this.#container);
        }
    }

    var ImagePreloaderInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ImagePreloaderInstance: ImagePreloaderInstance
    });

    const minRetries = 0;
    class OverlapPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        checkParticlePosition(particle, position, tryCount) {
            return !this.#hasOverlaps(particle, position, tryCount);
        }
        #hasOverlaps(particle, pos, tryCount) {
            const collisionsOptions = particle.options.collisions;
            if (!collisionsOptions?.enable) {
                return false;
            }
            const overlapOptions = collisionsOptions.overlap;
            if (overlapOptions.enable) {
                return false;
            }
            const retries = overlapOptions.retries;
            if (retries >= minRetries && tryCount > retries) {
                throw new Error(`Particle is overlapping and can't be placed`);
            }
            return !!this.#container.particles.find(p => getDistance(pos, p.position) < particle.getRadius() + p.getRadius());
        }
    }

    var OverlapPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        OverlapPluginInstance: OverlapPluginInstance
    });

    function getLinkKey(ids) {
        return [...ids].sort((a, b) => a - b).join("_");
    }
    function setLinkFrequency(particles, dictionary) {
        const key = getLinkKey(particles.map(t => t.id));
        let res = dictionary.get(key);
        if (res === undefined) {
            res = getRandom();
            dictionary.set(key, res);
        }
        return res;
    }

    const minOpacity = 0, minWidth = 0, minDistance = 0, maxFrequency = 1, defaultFrequency = 0;
    class LinkInstance {
        #colorCache = new Map();
        #container;
        #freqs;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#freqs = { links: new Map(), triangles: new Map() };
        }
        drawParticle(context, particle) {
            const { links, options } = particle;
            if (!links?.length || !options.links) {
                return;
            }
            const linkOpts = options.links, width = particle.retina.linksWidth ?? minWidth, pos1 = particle.getPosition(), twinkle = particle.options["twinkle"]?.links, trianglesEnabled = linkOpts.triangles.enable, p1Destinations = trianglesEnabled ? new Set(links.map(l => l.destination.id)) : null, originalAlpha = context.globalAlpha;
            let currentColorStyle = "", currentWidth = -1, currentAlpha = -1, pathOpen = false;
            const flushLines = () => {
                if (pathOpen) {
                    context.stroke();
                    pathOpen = false;
                }
            };
            for (const link of links) {
                if (linkOpts.frequency < maxFrequency &&
                    this.#getLinkFrequency(particle, link.destination) > linkOpts.frequency) {
                    continue;
                }
                const pos2 = link.destination.getPosition();
                if (trianglesEnabled && !link.isWarped && p1Destinations) {
                    flushLines();
                    this.#drawTriangles(options, particle, link, p1Destinations, pos1, pos2, context);
                }
                if (link.opacity <= minOpacity || width <= minWidth) {
                    continue;
                }
                if (!linkOpts.enable) {
                    continue;
                }
                let opacity = link.opacity, colorLine = link.color;
                const twinkleRgb = twinkle?.enable && getRandom() < twinkle.frequency
                    ? rangeColorToRgb(this.#pluginManager, twinkle.color)
                    : undefined;
                if (twinkle && twinkleRgb) {
                    colorLine = twinkleRgb;
                    opacity = getRangeValue(twinkle.opacity);
                }
                if (!colorLine) {
                    const linkColor = linkOpts.id !== undefined
                        ? this.#container.particles.linksColors.get(linkOpts.id)
                        : this.#container.particles.linksColor;
                    colorLine = getLinkColor(particle, link.destination, linkColor);
                }
                if (!colorLine) {
                    continue;
                }
                const colorStyle = this.#getCachedStyle(colorLine);
                if (colorStyle !== currentColorStyle || width !== currentWidth || opacity !== currentAlpha) {
                    flushLines();
                    context.strokeStyle = colorStyle;
                    context.lineWidth = width;
                    context.globalAlpha = opacity;
                    currentColorStyle = colorStyle;
                    currentWidth = width;
                    currentAlpha = opacity;
                    context.beginPath();
                    pathOpen = true;
                }
                if (link.isWarped) {
                    const canvasSize = this.#container.canvas.size, dx = pos2.x - pos1.x, dy = pos2.y - pos1.y;
                    let sx = originPoint.x, sy = originPoint.y;
                    if (Math.abs(dx) > canvasSize.width * half$2) {
                        sx = dx > minDistance ? -canvasSize.width : canvasSize.width;
                    }
                    if (Math.abs(dy) > canvasSize.height * half$2) {
                        sy = dy > minDistance ? -canvasSize.height : canvasSize.height;
                    }
                    context.moveTo(pos1.x, pos1.y);
                    context.lineTo(pos2.x + sx, pos2.y + sy);
                    context.moveTo(pos1.x - sx, pos1.y - sy);
                    context.lineTo(pos2.x, pos2.y);
                }
                else {
                    context.moveTo(pos1.x, pos1.y);
                    context.lineTo(pos2.x, pos2.y);
                }
            }
            flushLines();
            context.globalAlpha = originalAlpha;
        }
        init() {
            this.#freqs.links.clear();
            this.#freqs.triangles.clear();
            this.#colorCache.clear();
            return Promise.resolve();
        }
        particleCreated(particle) {
            particle.links = [];
            if (!particle.options.links) {
                return;
            }
            particle.linksDistance = particle.options.links.distance;
            particle.linksWidth = particle.options.links.width;
            const ratio = this.#container.retina.pixelRatio;
            particle.retina.linksDistance = particle.linksDistance * ratio;
            particle.retina.linksWidth = particle.linksWidth * ratio;
        }
        particleDestroyed(particle) {
            particle.links = [];
        }
        #drawTriangles(options, p1, link, p1Destinations, pos1, pos2, context) {
            const p2 = link.destination, triangleOptions = options.links?.triangles;
            if (!triangleOptions?.enable || !p2.options.links?.triangles.enable) {
                return;
            }
            const p2Links = p2.links;
            if (!p2Links?.length) {
                return;
            }
            for (const vertex of p2Links) {
                if (vertex.isWarped ||
                    this.#getLinkFrequency(p2, vertex.destination) > p2.options.links.frequency ||
                    !p1Destinations.has(vertex.destination.id)) {
                    continue;
                }
                const p3 = vertex.destination;
                if (this.#getTriangleFrequency(p1, p2, p3) > (options.links?.triangles.frequency ?? defaultFrequency)) {
                    continue;
                }
                const opacityTriangle = triangleOptions.opacity ?? (link.opacity + vertex.opacity) * half$2, colorTriangle = rangeColorToRgb(this.#pluginManager, triangleOptions.color) ?? link.color;
                if (!colorTriangle || opacityTriangle <= minOpacity) {
                    continue;
                }
                const pos3 = p3.getPosition();
                context.save();
                context.fillStyle = this.#getCachedStyle(colorTriangle);
                context.globalAlpha = opacityTriangle;
                context.beginPath();
                context.moveTo(pos1.x, pos1.y);
                context.lineTo(pos2.x, pos2.y);
                context.lineTo(pos3.x, pos3.y);
                context.closePath();
                context.fill();
                context.restore();
            }
        }
        #getCachedStyle(rgb) {
            const key = `${rgb.r},${rgb.g},${rgb.b}-${this.#container.hdr}-${this.#container.peakNits}-${this.#container.hdrMode}`;
            let style = this.#colorCache.get(key);
            if (!style) {
                style = getStyleFromRgb(rgb, this.#container.hdr, undefined, this.#container.peakNits, this.#container.hdrMode);
                this.#colorCache.set(key, style);
            }
            return style;
        }
        #getLinkFrequency(p1, p2) {
            return setLinkFrequency([p1, p2], this.#freqs.links);
        }
        #getTriangleFrequency(p1, p2, p3) {
            return setLinkFrequency([p1, p2, p3], this.#freqs.triangles);
        }
    }

    var LinkInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        LinkInstance: LinkInstance
    });

    const minStage$1 = 0, minDuration = 0;
    class Infecter {
        #container;
        constructor(container) {
            this.#container = container;
        }
        startInfection(particle, stage) {
            const infectionOptions = this.#container.actualOptions.infection, { infection } = particle;
            if (!infectionOptions || !infection) {
                return;
            }
            const stages = infectionOptions.stages, stagesCount = stages.length;
            if (stage > stagesCount || stage < minStage$1) {
                return;
            }
            infection.delay = 0;
            infection.delayStage = stage;
        }
        updateInfection(particle, delta) {
            const infectionOptions = this.#container.actualOptions.infection, { infection } = particle;
            if (!infectionOptions || !infection) {
                return;
            }
            const stages = infectionOptions.stages, stagesCount = stages.length;
            if (infection.delay !== undefined && infection.delayStage !== undefined) {
                const stage = infection.delayStage;
                if (stage > stagesCount || stage < minStage$1) {
                    return;
                }
                if (infection.delay >= infectionOptions.delay * millisecondsToSeconds$1) {
                    infection.stage = stage;
                    infection.time = 0;
                    delete infection.delay;
                    delete infection.delayStage;
                }
                else {
                    infection.delay += delta;
                }
            }
            else {
                delete infection.delay;
                delete infection.delayStage;
            }
            if (infection.stage !== undefined && infection.time !== undefined) {
                const infectionStage = stages[infection.stage];
                if (infectionStage?.duration !== undefined && infectionStage.duration >= minDuration) {
                    if (infection.time > infectionStage.duration * millisecondsToSeconds$1) {
                        this.#nextInfectionStage(particle);
                    }
                    else {
                        infection.time += delta;
                    }
                }
                else {
                    infection.time += delta;
                }
            }
            else {
                delete infection.stage;
                delete infection.time;
            }
        }
        updateInfectionStage(particle, stage) {
            const options = this.#container.actualOptions, { infection } = particle;
            if (!options.infection || !infection) {
                return;
            }
            const stagesCount = options.infection.stages.length;
            if (stage > stagesCount || stage < minStage$1 || (infection.stage !== undefined && infection.stage > stage)) {
                return;
            }
            infection.stage = stage;
            infection.time = 0;
        }
        #nextInfectionStage(particle) {
            const infectionOptions = this.#container.actualOptions.infection, { infection } = particle;
            if (!infectionOptions || !infection) {
                return;
            }
            const stagesCount = infectionOptions.stages.length;
            if (stagesCount <= minStage$1 || infection.stage === undefined) {
                return;
            }
            infection.time = 0;
            if (stagesCount <= ++infection.stage) {
                if (infectionOptions.cure) {
                    delete infection.stage;
                    delete infection.time;
                }
                else {
                    infection.stage = 0;
                    infection.time = 0;
                }
            }
        }
    }

    const minStage = 0;
    class InfectionPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
            this.#container.infecter = new Infecter(this.#container);
        }
        particleFillColor(particle) {
            const options = this.#container.actualOptions;
            if (!particle.infection || !options.infection) {
                return;
            }
            const infectionStage = particle.infection.stage, infection = options.infection, infectionStages = infection.stages;
            return infectionStage === undefined ? undefined : infectionStages[infectionStage]?.color;
        }
        particleStrokeColor(particle) {
            return this.particleFillColor(particle);
        }
        particlesSetup() {
            const options = this.#container.actualOptions;
            if (!options.infection) {
                return;
            }
            for (let i = 0; i < options.infection.infections; i++) {
                const notInfected = this.#container.particles.filter(p => {
                    const infP = p;
                    infP.infection ??= {};
                    return infP.infection.stage === undefined;
                }), infected = itemFromArray(notInfected);
                if (!infected) {
                    continue;
                }
                this.#container.infecter?.startInfection(infected, minStage);
            }
        }
    }

    var InfectionPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        InfectionPluginInstance: InfectionPluginInstance
    });

    const noParticles = 0;
    class ManualParticlesPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        particlesDensityCount() {
            return this.#container.actualOptions.manualParticles?.length ?? noParticles;
        }
        particlesInitialization() {
            const container = this.#container, options = container.actualOptions;
            options.manualParticles?.forEach(p => container.particles.addParticle(p.position ? getPosition(p.position, container.canvas.size) : undefined, p.options));
            return false;
        }
    }

    var ManualParticlesPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ManualParticlesPluginInstance: ManualParticlesPluginInstance
    });

    const defaultFactor = 1, defaultReduce = 1, disableReduce = 0, identity = 1;
    class MotionPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        async init() {
            const container = this.#container, options = container.actualOptions.motion;
            if (!(options && (options.disable || options.reduce.value))) {
                container.retina.reduceFactor = 1;
                return;
            }
            const mediaQuery = safeMatchMedia("(prefers-reduced-motion: reduce)");
            if (!mediaQuery) {
                container.retina.reduceFactor = defaultFactor;
                return;
            }
            this.#handleMotionChange(mediaQuery);
            const handleChange = () => {
                void (async () => {
                    this.#handleMotionChange(mediaQuery);
                    try {
                        await container.refresh();
                    }
                    catch {
                    }
                })();
            };
            mediaQuery.addEventListener("change", handleChange);
            await Promise.resolve();
        }
        #handleMotionChange(mediaQuery) {
            const container = this.#container, motion = container.actualOptions.motion;
            if (!motion) {
                return;
            }
            if (mediaQuery.matches) {
                if (motion.disable) {
                    container.retina.reduceFactor = disableReduce;
                }
                else {
                    container.retina.reduceFactor = motion.reduce.value ? identity / motion.reduce.factor : defaultFactor;
                }
            }
            else {
                container.retina.reduceFactor = defaultReduce;
            }
        }
    }

    var MotionPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        MotionPluginInstance: MotionPluginInstance
    });

    const defaultSize = 1;
    class PoissonDiscPluginInstance {
        poissonDisc;
        redrawTimeout;
        #container;
        #currentIndex;
        constructor(container) {
            this.#container = container;
            this.#currentIndex = 0;
        }
        async init() {
            await this.#initData();
        }
        particlePosition(position) {
            const container = this.#container, options = container.actualOptions.poisson;
            if (!this.poissonDisc || !(options?.enable ?? false) || this.#currentIndex >= this.poissonDisc.points.length) {
                return;
            }
            return position ?? this.poissonDisc.points[this.#currentIndex++]?.position;
        }
        resize() {
            const container = this.#container, options = container.actualOptions.poisson;
            if (!(options?.enable ?? false)) {
                return;
            }
            if (this.redrawTimeout) {
                clearTimeout(this.redrawTimeout);
            }
            const timeout = 250;
            this.redrawTimeout = setTimeout(() => {
                void (async () => {
                    if (this.#container.destroyed) {
                        return;
                    }
                    await this.#initData();
                    await container.particles.redraw();
                })();
            }, timeout);
        }
        stop() {
            delete this.poissonDisc;
        }
        async #initData() {
            const container = this.#container, poissonOptions = container.actualOptions.poisson, particlesOptions = container.actualOptions.particles, canvasSize = container.canvas.size, pixelRatio = container.retina.pixelRatio;
            if (!poissonOptions?.enable) {
                return;
            }
            this.#currentIndex = 0;
            const { PoissonDisc } = await Promise.resolve().then(function () { return PoissonDisc$1; });
            this.poissonDisc = new PoissonDisc(canvasSize, poissonOptions.radius
                ? poissonOptions.radius * pixelRatio
                : Math.max(getRangeMax(particlesOptions["size.value"] ?? defaultSize) * pixelRatio, Math.sqrt((canvasSize.width * canvasSize.height) / particlesOptions.number.value)), poissonOptions.retries, poissonOptions.dimensions);
            const noSteps = 0;
            if (poissonOptions.steps > noSteps) {
                this.poissonDisc.steps(poissonOptions.steps);
            }
            else {
                await this.poissonDisc.run();
            }
        }
    }

    var PoissonDiscPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        PoissonDiscPluginInstance: PoissonDiscPluginInstance
    });

    (function () {
        try {
            if (typeof window === "undefined")
                return;
            if (!("SVGPathSeg" in window)) {
                window.SVGPathSeg = function (type, typeAsLetter, owningPathSegList) {
                    this.pathSegType = type;
                    this.pathSegTypeAsLetter = typeAsLetter;
                    this._owningPathSegList = owningPathSegList;
                };
                window.SVGPathSeg.prototype.classname = "SVGPathSeg";
                window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
                window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
                window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
                window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
                window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
                window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
                window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
                window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
                window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
                window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
                window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
                window.SVGPathSeg.PATHSEG_ARC_REL = 11;
                window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
                window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
                window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
                window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
                window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
                window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
                window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
                window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
                window.SVGPathSeg.prototype._segmentChanged = function () {
                    if (this._owningPathSegList)
                        this._owningPathSegList.segmentChanged(this);
                };
                window.SVGPathSegClosePath = function (owningPathSegList) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
                };
                window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegClosePath.prototype.toString = function () {
                    return "[object SVGPathSegClosePath]";
                };
                window.SVGPathSegClosePath.prototype._asPathString = function () {
                    return this.pathSegTypeAsLetter;
                };
                window.SVGPathSegClosePath.prototype.clone = function () {
                    return new window.SVGPathSegClosePath(undefined);
                };
                window.SVGPathSegMovetoAbs = function (owningPathSegList, x, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
                    this._x = x;
                    this._y = y;
                };
                window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegMovetoAbs.prototype.toString = function () {
                    return "[object SVGPathSegMovetoAbs]";
                };
                window.SVGPathSegMovetoAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x} ${this._y}`;
                };
                window.SVGPathSegMovetoAbs.prototype.clone = function () {
                    return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y);
                };
                Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegMovetoRel = function (owningPathSegList, x, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
                    this._x = x;
                    this._y = y;
                };
                window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegMovetoRel.prototype.toString = function () {
                    return "[object SVGPathSegMovetoRel]";
                };
                window.SVGPathSegMovetoRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x} ${this._y}`;
                };
                window.SVGPathSegMovetoRel.prototype.clone = function () {
                    return new window.SVGPathSegMovetoRel(undefined, this._x, this._y);
                };
                Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegLinetoAbs = function (owningPathSegList, x, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
                    this._x = x;
                    this._y = y;
                };
                window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegLinetoAbs.prototype.toString = function () {
                    return "[object SVGPathSegLinetoAbs]";
                };
                window.SVGPathSegLinetoAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x} ${this._y}`;
                };
                window.SVGPathSegLinetoAbs.prototype.clone = function () {
                    return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y);
                };
                Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegLinetoRel = function (owningPathSegList, x, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
                    this._x = x;
                    this._y = y;
                };
                window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegLinetoRel.prototype.toString = function () {
                    return "[object SVGPathSegLinetoRel]";
                };
                window.SVGPathSegLinetoRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x} ${this._y}`;
                };
                window.SVGPathSegLinetoRel.prototype.clone = function () {
                    return new window.SVGPathSegLinetoRel(undefined, this._x, this._y);
                };
                Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoCubicAbs = function (owningPathSegList, x, y, x1, y1, x2, y2) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._x1 = x1;
                    this._y1 = y1;
                    this._x2 = x2;
                    this._y2 = y2;
                };
                window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoCubicAbs.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoCubicAbs]";
                };
                window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter}  ${this._x1} ${this._y1} ${this._x2} ${this._y2} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoCubicAbs.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
                };
                Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x1", {
                    get: function () {
                        return this._x1;
                    },
                    set: function (x1) {
                        this._x1 = x1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y1", {
                    get: function () {
                        return this._y1;
                    },
                    set: function (y1) {
                        this._y1 = y1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x2", {
                    get: function () {
                        return this._x2;
                    },
                    set: function (x2) {
                        this._x2 = x2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y2", {
                    get: function () {
                        return this._y2;
                    },
                    set: function (y2) {
                        this._y2 = y2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoCubicRel = function (owningPathSegList, x, y, x1, y1, x2, y2) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._x1 = x1;
                    this._y1 = y1;
                    this._x2 = x2;
                    this._y2 = y2;
                };
                window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoCubicRel.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoCubicRel]";
                };
                window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x1} ${this._y1} ${this._x2} ${this._y2} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoCubicRel.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
                };
                Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x1", {
                    get: function () {
                        return this._x1;
                    },
                    set: function (x1) {
                        this._x1 = x1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y1", {
                    get: function () {
                        return this._y1;
                    },
                    set: function (y1) {
                        this._y1 = y1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x2", {
                    get: function () {
                        return this._x2;
                    },
                    set: function (x2) {
                        this._x2 = x2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y2", {
                    get: function () {
                        return this._y2;
                    },
                    set: function (y2) {
                        this._y2 = y2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoQuadraticAbs = function (owningPathSegList, x, y, x1, y1) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._x1 = x1;
                    this._y1 = y1;
                };
                window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoQuadraticAbs]";
                };
                window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x1} ${this._y1} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1);
                };
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x1", {
                    get: function () {
                        return this._x1;
                    },
                    set: function (x1) {
                        this._x1 = x1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y1", {
                    get: function () {
                        return this._y1;
                    },
                    set: function (y1) {
                        this._y1 = y1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoQuadraticRel = function (owningPathSegList, x, y, x1, y1) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._x1 = x1;
                    this._y1 = y1;
                };
                window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoQuadraticRel]";
                };
                window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x1} ${this._y1} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1);
                };
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x1", {
                    get: function () {
                        return this._x1;
                    },
                    set: function (x1) {
                        this._x1 = x1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y1", {
                    get: function () {
                        return this._y1;
                    },
                    set: function (y1) {
                        this._y1 = y1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegArcAbs = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._r1 = r1;
                    this._r2 = r2;
                    this._angle = angle;
                    this._largeArcFlag = largeArcFlag;
                    this._sweepFlag = sweepFlag;
                };
                window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegArcAbs.prototype.toString = function () {
                    return "[object SVGPathSegArcAbs]";
                };
                window.SVGPathSegArcAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._r1} ${this._r2} ${this._angle} ${this._largeArcFlag ? "1" : "0"} ${this._sweepFlag ? "1" : "0"} ${this._x} ${this._y}`;
                };
                window.SVGPathSegArcAbs.prototype.clone = function () {
                    return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
                };
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r1", {
                    get: function () {
                        return this._r1;
                    },
                    set: function (r1) {
                        this._r1 = r1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r2", {
                    get: function () {
                        return this._r2;
                    },
                    set: function (r2) {
                        this._r2 = r2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "angle", {
                    get: function () {
                        return this._angle;
                    },
                    set: function (angle) {
                        this._angle = angle;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "largeArcFlag", {
                    get: function () {
                        return this._largeArcFlag;
                    },
                    set: function (largeArcFlag) {
                        this._largeArcFlag = largeArcFlag;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcAbs.prototype, "sweepFlag", {
                    get: function () {
                        return this._sweepFlag;
                    },
                    set: function (sweepFlag) {
                        this._sweepFlag = sweepFlag;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegArcRel = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._r1 = r1;
                    this._r2 = r2;
                    this._angle = angle;
                    this._largeArcFlag = largeArcFlag;
                    this._sweepFlag = sweepFlag;
                };
                window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegArcRel.prototype.toString = function () {
                    return "[object SVGPathSegArcRel]";
                };
                window.SVGPathSegArcRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._r1} ${this._r2} ${this._angle} ${this._largeArcFlag ? "1" : "0"} ${this._sweepFlag ? "1" : "0"} ${this._x} ${this._y}`;
                };
                window.SVGPathSegArcRel.prototype.clone = function () {
                    return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
                };
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "r1", {
                    get: function () {
                        return this._r1;
                    },
                    set: function (r1) {
                        this._r1 = r1;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "r2", {
                    get: function () {
                        return this._r2;
                    },
                    set: function (r2) {
                        this._r2 = r2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "angle", {
                    get: function () {
                        return this._angle;
                    },
                    set: function (angle) {
                        this._angle = angle;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "largeArcFlag", {
                    get: function () {
                        return this._largeArcFlag;
                    },
                    set: function (largeArcFlag) {
                        this._largeArcFlag = largeArcFlag;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegArcRel.prototype, "sweepFlag", {
                    get: function () {
                        return this._sweepFlag;
                    },
                    set: function (sweepFlag) {
                        this._sweepFlag = sweepFlag;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegLinetoHorizontalAbs = function (owningPathSegList, x) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
                    this._x = x;
                };
                window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function () {
                    return "[object SVGPathSegLinetoHorizontalAbs]";
                };
                window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x}`;
                };
                window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function () {
                    return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x);
                };
                Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegLinetoHorizontalRel = function (owningPathSegList, x) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
                    this._x = x;
                };
                window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegLinetoHorizontalRel.prototype.toString = function () {
                    return "[object SVGPathSegLinetoHorizontalRel]";
                };
                window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x}`;
                };
                window.SVGPathSegLinetoHorizontalRel.prototype.clone = function () {
                    return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x);
                };
                Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegLinetoVerticalAbs = function (owningPathSegList, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
                    this._y = y;
                };
                window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegLinetoVerticalAbs.prototype.toString = function () {
                    return "[object SVGPathSegLinetoVerticalAbs]";
                };
                window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._y}`;
                };
                window.SVGPathSegLinetoVerticalAbs.prototype.clone = function () {
                    return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y);
                };
                Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegLinetoVerticalRel = function (owningPathSegList, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
                    this._y = y;
                };
                window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegLinetoVerticalRel.prototype.toString = function () {
                    return "[object SVGPathSegLinetoVerticalRel]";
                };
                window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._y}`;
                };
                window.SVGPathSegLinetoVerticalRel.prototype.clone = function () {
                    return new window.SVGPathSegLinetoVerticalRel(undefined, this._y);
                };
                Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoCubicSmoothAbs = function (owningPathSegList, x, y, x2, y2) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._x2 = x2;
                    this._y2 = y2;
                };
                window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoCubicSmoothAbs]";
                };
                window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x2} ${this._y2} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2);
                };
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", {
                    get: function () {
                        return this._x2;
                    },
                    set: function (x2) {
                        this._x2 = x2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", {
                    get: function () {
                        return this._y2;
                    },
                    set: function (y2) {
                        this._y2 = y2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoCubicSmoothRel = function (owningPathSegList, x, y, x2, y2) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
                    this._x = x;
                    this._y = y;
                    this._x2 = x2;
                    this._y2 = y2;
                };
                window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoCubicSmoothRel]";
                };
                window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x2} ${this._y2} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2);
                };
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", {
                    get: function () {
                        return this._x2;
                    },
                    set: function (x2) {
                        this._x2 = x2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", {
                    get: function () {
                        return this._y2;
                    },
                    set: function (y2) {
                        this._y2 = y2;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoQuadraticSmoothAbs = function (owningPathSegList, x, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
                    this._x = x;
                    this._y = y;
                };
                window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoQuadraticSmoothAbs]";
                };
                window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y);
                };
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathSegCurvetoQuadraticSmoothRel = function (owningPathSegList, x, y) {
                    window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
                    this._x = x;
                    this._y = y;
                };
                window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
                window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function () {
                    return "[object SVGPathSegCurvetoQuadraticSmoothRel]";
                };
                window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function () {
                    return `${this.pathSegTypeAsLetter} ${this._x} ${this._y}`;
                };
                window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function () {
                    return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y);
                };
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", {
                    get: function () {
                        return this._x;
                    },
                    set: function (x) {
                        this._x = x;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", {
                    get: function () {
                        return this._y;
                    },
                    set: function (y) {
                        this._y = y;
                        this._segmentChanged();
                    },
                    enumerable: true,
                });
                window.SVGPathElement.prototype.createSVGPathSegClosePath = function () {
                    return new window.SVGPathSegClosePath(undefined);
                };
                window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) {
                    return new window.SVGPathSegMovetoAbs(undefined, x, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) {
                    return new window.SVGPathSegMovetoRel(undefined, x, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) {
                    return new window.SVGPathSegLinetoAbs(undefined, x, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) {
                    return new window.SVGPathSegLinetoRel(undefined, x, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) {
                    return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) {
                    return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) {
                    return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) {
                    return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1);
                };
                window.SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
                    return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
                };
                window.SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
                    return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
                };
                window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) {
                    return new window.SVGPathSegLinetoHorizontalAbs(undefined, x);
                };
                window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) {
                    return new window.SVGPathSegLinetoHorizontalRel(undefined, x);
                };
                window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) {
                    return new window.SVGPathSegLinetoVerticalAbs(undefined, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) {
                    return new window.SVGPathSegLinetoVerticalRel(undefined, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) {
                    return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) {
                    return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) {
                    return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y);
                };
                window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) {
                    return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y);
                };
                if (!("getPathSegAtLength" in window.SVGPathElement.prototype)) {
                    window.SVGPathElement.prototype.getPathSegAtLength = function (distance) {
                        if (distance === undefined || !isFinite(distance))
                            throw "Invalid arguments.";
                        const measurementElement = document.createElementNS("http://www.w3.org/2000/svg", "path");
                        measurementElement.setAttribute("d", this.getAttribute("d"));
                        let lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
                        if (lastPathSegment <= 0)
                            return 0;
                        do {
                            measurementElement.pathSegList.removeItem(lastPathSegment);
                            if (distance > measurementElement.getTotalLength())
                                break;
                            lastPathSegment--;
                        } while (lastPathSegment > 0);
                        return lastPathSegment;
                    };
                }
            }
            if (!("SVGPathSegList" in window) || !("appendItem" in window.SVGPathSegList.prototype)) {
                window.SVGPathSegList = function (pathElement) {
                    this._pathElement = pathElement;
                    this._list = this._parsePath(this._pathElement.getAttribute("d"));
                    this._mutationObserverConfig = { attributes: true, attributeFilter: ["d"] };
                    this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
                    this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
                };
                window.SVGPathSegList.prototype.classname = "SVGPathSegList";
                Object.defineProperty(window.SVGPathSegList.prototype, "numberOfItems", {
                    get: function () {
                        this._checkPathSynchronizedToList();
                        return this._list.length;
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathSegList.prototype, "length", {
                    get: function () {
                        this._checkPathSynchronizedToList();
                        return this._list.length;
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathElement.prototype, "pathSegList", {
                    get: function () {
                        if (!this._pathSegList)
                            this._pathSegList = new window.SVGPathSegList(this);
                        return this._pathSegList;
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathElement.prototype, "normalizedPathSegList", {
                    get: function () {
                        return this.pathSegList;
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathElement.prototype, "animatedPathSegList", {
                    get: function () {
                        return this.pathSegList;
                    },
                    enumerable: true,
                });
                Object.defineProperty(window.SVGPathElement.prototype, "animatedNormalizedPathSegList", {
                    get: function () {
                        return this.pathSegList;
                    },
                    enumerable: true,
                });
                window.SVGPathSegList.prototype._checkPathSynchronizedToList = function () {
                    this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
                };
                window.SVGPathSegList.prototype._updateListFromPathMutations = function (mutationRecords) {
                    if (!this._pathElement)
                        return;
                    let hasPathMutations = false;
                    mutationRecords.forEach(function (record) {
                        if (record.attributeName == "d")
                            hasPathMutations = true;
                    });
                    if (hasPathMutations)
                        this._list = this._parsePath(this._pathElement.getAttribute("d"));
                };
                window.SVGPathSegList.prototype._writeListToPath = function () {
                    this._pathElementMutationObserver.disconnect();
                    this._pathElement.setAttribute("d", window.SVGPathSegList._pathSegArrayAsString(this._list));
                    this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
                };
                window.SVGPathSegList.prototype.segmentChanged = function () {
                    this._writeListToPath();
                };
                window.SVGPathSegList.prototype.clear = function () {
                    this._checkPathSynchronizedToList();
                    this._list.forEach(function (pathSeg) {
                        pathSeg._owningPathSegList = null;
                    });
                    this._list = [];
                    this._writeListToPath();
                };
                window.SVGPathSegList.prototype.initialize = function (newItem) {
                    this._checkPathSynchronizedToList();
                    this._list = [newItem];
                    newItem._owningPathSegList = this;
                    this._writeListToPath();
                    return newItem;
                };
                window.SVGPathSegList.prototype._checkValidIndex = function (index) {
                    if (isNaN(index) || index < 0 || index >= this.numberOfItems)
                        throw "INDEX_SIZE_ERR";
                };
                window.SVGPathSegList.prototype.getItem = function (index) {
                    this._checkPathSynchronizedToList();
                    this._checkValidIndex(index);
                    return this._list[index];
                };
                window.SVGPathSegList.prototype.insertItemBefore = function (newItem, index) {
                    this._checkPathSynchronizedToList();
                    if (index > this.numberOfItems)
                        index = this.numberOfItems;
                    if (newItem._owningPathSegList) {
                        newItem = newItem.clone();
                    }
                    this._list.splice(index, 0, newItem);
                    newItem._owningPathSegList = this;
                    this._writeListToPath();
                    return newItem;
                };
                window.SVGPathSegList.prototype.replaceItem = function (newItem, index) {
                    this._checkPathSynchronizedToList();
                    if (newItem._owningPathSegList) {
                        newItem = newItem.clone();
                    }
                    this._checkValidIndex(index);
                    this._list[index] = newItem;
                    newItem._owningPathSegList = this;
                    this._writeListToPath();
                    return newItem;
                };
                window.SVGPathSegList.prototype.removeItem = function (index) {
                    this._checkPathSynchronizedToList();
                    this._checkValidIndex(index);
                    const item = this._list[index];
                    this._list.splice(index, 1);
                    this._writeListToPath();
                    return item;
                };
                window.SVGPathSegList.prototype.appendItem = function (newItem) {
                    this._checkPathSynchronizedToList();
                    if (newItem._owningPathSegList) {
                        newItem = newItem.clone();
                    }
                    this._list.push(newItem);
                    newItem._owningPathSegList = this;
                    this._writeListToPath();
                    return newItem;
                };
                window.SVGPathSegList._pathSegArrayAsString = function (pathSegArray) {
                    let string = "";
                    let first = true;
                    pathSegArray.forEach(function (pathSeg) {
                        if (first) {
                            first = false;
                            string += pathSeg._asPathString();
                        }
                        else {
                            string += ` ${pathSeg._asPathString()}`;
                        }
                    });
                    return string;
                };
                window.SVGPathSegList.prototype._parsePath = function (string) {
                    if (!string?.length)
                        return [];
                    const owningPathSegList = this;
                    const Builder = function () {
                        this.pathSegList = [];
                    };
                    Builder.prototype.appendSegment = function (pathSeg) {
                        this.pathSegList.push(pathSeg);
                    };
                    const Source = function (string) {
                        this._string = string;
                        this._currentIndex = 0;
                        this._endIndex = this._string.length;
                        this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
                        this._skipOptionalSpaces();
                    };
                    Source.prototype._isCurrentSpace = function () {
                        const character = this._string[this._currentIndex];
                        return (character <= " " &&
                            (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f"));
                    };
                    Source.prototype._skipOptionalSpaces = function () {
                        while (this._currentIndex < this._endIndex && this._isCurrentSpace())
                            this._currentIndex++;
                        return this._currentIndex < this._endIndex;
                    };
                    Source.prototype._skipOptionalSpacesOrDelimiter = function () {
                        if (this._currentIndex < this._endIndex &&
                            !this._isCurrentSpace() &&
                            this._string.charAt(this._currentIndex) != ",")
                            return false;
                        if (this._skipOptionalSpaces()) {
                            if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
                                this._currentIndex++;
                                this._skipOptionalSpaces();
                            }
                        }
                        return this._currentIndex < this._endIndex;
                    };
                    Source.prototype.hasMoreData = function () {
                        return this._currentIndex < this._endIndex;
                    };
                    Source.prototype.peekSegmentType = function () {
                        const lookahead = this._string[this._currentIndex];
                        return this._pathSegTypeFromChar(lookahead);
                    };
                    Source.prototype._pathSegTypeFromChar = function (lookahead) {
                        switch (lookahead) {
                            case "Z":
                            case "z":
                                return window.SVGPathSeg.PATHSEG_CLOSEPATH;
                            case "M":
                                return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
                            case "m":
                                return window.SVGPathSeg.PATHSEG_MOVETO_REL;
                            case "L":
                                return window.SVGPathSeg.PATHSEG_LINETO_ABS;
                            case "l":
                                return window.SVGPathSeg.PATHSEG_LINETO_REL;
                            case "C":
                                return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
                            case "c":
                                return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
                            case "Q":
                                return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
                            case "q":
                                return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
                            case "A":
                                return window.SVGPathSeg.PATHSEG_ARC_ABS;
                            case "a":
                                return window.SVGPathSeg.PATHSEG_ARC_REL;
                            case "H":
                                return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
                            case "h":
                                return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
                            case "V":
                                return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
                            case "v":
                                return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
                            case "S":
                                return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
                            case "s":
                                return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
                            case "T":
                                return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
                            case "t":
                                return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
                            default:
                                return window.SVGPathSeg.PATHSEG_UNKNOWN;
                        }
                    };
                    Source.prototype._nextCommandHelper = function (lookahead, previousCommand) {
                        if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) &&
                            previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
                            if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
                                return window.SVGPathSeg.PATHSEG_LINETO_ABS;
                            if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
                                return window.SVGPathSeg.PATHSEG_LINETO_REL;
                            return previousCommand;
                        }
                        return window.SVGPathSeg.PATHSEG_UNKNOWN;
                    };
                    Source.prototype.initialCommandIsMoveTo = function () {
                        if (!this.hasMoreData())
                            return true;
                        const command = this.peekSegmentType();
                        return command == window.SVGPathSeg.PATHSEG_MOVETO_ABS || command == window.SVGPathSeg.PATHSEG_MOVETO_REL;
                    };
                    Source.prototype._parseNumber = function () {
                        let exponent = 0;
                        let integer = 0;
                        let frac = 1;
                        let decimal = 0;
                        let sign = 1;
                        let expsign = 1;
                        const startIndex = this._currentIndex;
                        this._skipOptionalSpaces();
                        if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+")
                            this._currentIndex++;
                        else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
                            this._currentIndex++;
                            sign = -1;
                        }
                        if (this._currentIndex == this._endIndex ||
                            ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") &&
                                this._string.charAt(this._currentIndex) != "."))
                            return undefined;
                        const startIntPartIndex = this._currentIndex;
                        while (this._currentIndex < this._endIndex &&
                            this._string.charAt(this._currentIndex) >= "0" &&
                            this._string.charAt(this._currentIndex) <= "9")
                            this._currentIndex++;
                        if (this._currentIndex != startIntPartIndex) {
                            let scanIntPartIndex = this._currentIndex - 1;
                            let multiplier = 1;
                            while (scanIntPartIndex >= startIntPartIndex) {
                                integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
                                multiplier *= 10;
                            }
                        }
                        if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
                            this._currentIndex++;
                            if (this._currentIndex >= this._endIndex ||
                                this._string.charAt(this._currentIndex) < "0" ||
                                this._string.charAt(this._currentIndex) > "9")
                                return undefined;
                            while (this._currentIndex < this._endIndex &&
                                this._string.charAt(this._currentIndex) >= "0" &&
                                this._string.charAt(this._currentIndex) <= "9") {
                                frac *= 10;
                                decimal += (this._string.charAt(this._currentIndex) - "0") / frac;
                                this._currentIndex += 1;
                            }
                        }
                        if (this._currentIndex != startIndex &&
                            this._currentIndex + 1 < this._endIndex &&
                            (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") &&
                            this._string.charAt(this._currentIndex + 1) != "x" &&
                            this._string.charAt(this._currentIndex + 1) != "m") {
                            this._currentIndex++;
                            if (this._string.charAt(this._currentIndex) == "+") {
                                this._currentIndex++;
                            }
                            else if (this._string.charAt(this._currentIndex) == "-") {
                                this._currentIndex++;
                                expsign = -1;
                            }
                            if (this._currentIndex >= this._endIndex ||
                                this._string.charAt(this._currentIndex) < "0" ||
                                this._string.charAt(this._currentIndex) > "9")
                                return undefined;
                            while (this._currentIndex < this._endIndex &&
                                this._string.charAt(this._currentIndex) >= "0" &&
                                this._string.charAt(this._currentIndex) <= "9") {
                                exponent *= 10;
                                exponent += this._string.charAt(this._currentIndex) - "0";
                                this._currentIndex++;
                            }
                        }
                        let number = integer + decimal;
                        number *= sign;
                        if (exponent)
                            number *= Math.pow(10, expsign * exponent);
                        if (startIndex == this._currentIndex)
                            return undefined;
                        this._skipOptionalSpacesOrDelimiter();
                        return number;
                    };
                    Source.prototype._parseArcFlag = function () {
                        if (this._currentIndex >= this._endIndex)
                            return undefined;
                        let flag = false;
                        const flagChar = this._string.charAt(this._currentIndex++);
                        if (flagChar == "0")
                            flag = false;
                        else if (flagChar == "1")
                            flag = true;
                        else
                            return undefined;
                        this._skipOptionalSpacesOrDelimiter();
                        return flag;
                    };
                    Source.prototype.parseSegment = function () {
                        const lookahead = this._string[this._currentIndex];
                        let command = this._pathSegTypeFromChar(lookahead);
                        if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
                            if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
                                return null;
                            command = this._nextCommandHelper(lookahead, this._previousCommand);
                            if (command == window.SVGPathSeg.PATHSEG_UNKNOWN)
                                return null;
                        }
                        else {
                            this._currentIndex++;
                        }
                        this._previousCommand = command;
                        let points;
                        switch (command) {
                            case window.SVGPathSeg.PATHSEG_MOVETO_REL:
                                return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
                                return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_LINETO_REL:
                                return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_LINETO_ABS:
                                return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
                                return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
                                return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
                                return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
                                return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_CLOSEPATH:
                                this._skipOptionalSpaces();
                                return new window.SVGPathSegClosePath(owningPathSegList);
                            case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
                                points = {
                                    x1: this._parseNumber(),
                                    y1: this._parseNumber(),
                                    x2: this._parseNumber(),
                                    y2: this._parseNumber(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
                            case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
                                points = {
                                    x1: this._parseNumber(),
                                    y1: this._parseNumber(),
                                    x2: this._parseNumber(),
                                    y2: this._parseNumber(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
                            case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
                                points = {
                                    x2: this._parseNumber(),
                                    y2: this._parseNumber(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
                            case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
                                points = {
                                    x2: this._parseNumber(),
                                    y2: this._parseNumber(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
                            case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
                                points = {
                                    x1: this._parseNumber(),
                                    y1: this._parseNumber(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
                            case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
                                points = {
                                    x1: this._parseNumber(),
                                    y1: this._parseNumber(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
                            case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
                                return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
                                return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
                            case window.SVGPathSeg.PATHSEG_ARC_REL:
                                points = {
                                    x1: this._parseNumber(),
                                    y1: this._parseNumber(),
                                    arcAngle: this._parseNumber(),
                                    arcLarge: this._parseArcFlag(),
                                    arcSweep: this._parseArcFlag(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
                            case window.SVGPathSeg.PATHSEG_ARC_ABS:
                                points = {
                                    x1: this._parseNumber(),
                                    y1: this._parseNumber(),
                                    arcAngle: this._parseNumber(),
                                    arcLarge: this._parseArcFlag(),
                                    arcSweep: this._parseArcFlag(),
                                    x: this._parseNumber(),
                                    y: this._parseNumber(),
                                };
                                return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
                            default:
                                throw "Unknown path seg type.";
                        }
                    };
                    const builder = new Builder();
                    const source = new Source(string);
                    if (!source.initialCommandIsMoveTo())
                        return [];
                    while (source.hasMoreData()) {
                        const pathSeg = source.parseSegment();
                        if (!pathSeg)
                            return [];
                        builder.appendSegment(pathSeg);
                    }
                    return builder.pathSegList;
                };
            }
        }
        catch (e) {
            console.warn("An error occurred in tsParticles pathseg polyfill. If the Polygon Mask is not working, please open an issue here: https://github.com/tsparticles/tsparticles", e);
        }
    })();

    const inSegmentRange = {
        min: 0,
        max: 1,
    };
    function drawPolygonMask(pluginManager, context, rawData, stroke, hdr = false, peakNits, mode) {
        const color = rangeColorToRgb(pluginManager, stroke.color);
        if (!color) {
            return;
        }
        const firstIndex = 0, firstItem = rawData[firstIndex];
        if (!firstItem) {
            return;
        }
        context.beginPath();
        context.moveTo(firstItem.x, firstItem.y);
        for (const item of rawData) {
            context.lineTo(item.x, item.y);
        }
        context.closePath();
        context.strokeStyle = getStyleFromRgb(color, hdr, undefined, peakNits, mode);
        context.lineWidth = stroke.width;
        context.stroke();
    }
    function drawPolygonMaskPath(pluginManager, context, path, stroke, position, hdr = false, peakNits, mode) {
        const defaultTransform = {
            a: 1,
            b: 0,
            c: 0,
            d: 1,
        };
        context.setTransform(defaultTransform.a, defaultTransform.b, defaultTransform.c, defaultTransform.d, position.x, position.y);
        const color = rangeColorToRgb(pluginManager, stroke.color);
        if (!color) {
            return;
        }
        context.strokeStyle = getStyleFromRgb(color, hdr, stroke.opacity, peakNits, mode);
        context.lineWidth = stroke.width;
        context.stroke(path);
        context.resetTransform();
    }
    function parsePaths(paths, scale, offset) {
        const res = [], defaultCount = 0;
        for (const path of paths) {
            const segments = path.element.pathSegList, len = segments?.numberOfItems ?? defaultCount, p = {
                x: 0,
                y: 0,
            };
            for (let i = 0; i < len; i++) {
                const segment = segments?.getItem(i), svgPathSeg = globalThis.SVGPathSeg;
                switch (segment?.pathSegType) {
                    case svgPathSeg.PATHSEG_MOVETO_ABS:
                    case svgPathSeg.PATHSEG_LINETO_ABS:
                    case svgPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
                    case svgPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
                    case svgPathSeg.PATHSEG_ARC_ABS:
                    case svgPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
                    case svgPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: {
                        const absSeg = segment;
                        p.x = absSeg.x;
                        p.y = absSeg.y;
                        break;
                    }
                    case svgPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
                        p.x = segment.x;
                        break;
                    case svgPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
                        p.y = segment.y;
                        break;
                    case svgPathSeg.PATHSEG_LINETO_REL:
                    case svgPathSeg.PATHSEG_MOVETO_REL:
                    case svgPathSeg.PATHSEG_CURVETO_CUBIC_REL:
                    case svgPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
                    case svgPathSeg.PATHSEG_ARC_REL:
                    case svgPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
                    case svgPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: {
                        const relSeg = segment;
                        p.x += relSeg.x;
                        p.y += relSeg.y;
                        break;
                    }
                    case svgPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
                        p.x += segment.x;
                        break;
                    case svgPathSeg.PATHSEG_LINETO_VERTICAL_REL:
                        p.y += segment.y;
                        break;
                    case svgPathSeg.PATHSEG_UNKNOWN:
                    case svgPathSeg.PATHSEG_CLOSEPATH:
                        continue;
                    default:
                        continue;
                }
                res.push({
                    x: p.x * scale + offset.x,
                    y: p.y * scale + offset.y,
                });
            }
        }
        return res;
    }
    function calcClosestPointOnSegment(s1, s2, pos) {
        const { dx: dx1, dy: dy1 } = getDistances(pos, s1), { dx: dx2, dy: dy2 } = getDistances(s2, s1), t = (dx1 * dx2 + dy1 * dy2) / (dx2 ** squareExp + dy2 ** squareExp), res = {
            x: s1.x + dx2 * t,
            y: s1.y + dy2 * t,
            isOnSegment: t >= inSegmentRange.min && t <= inSegmentRange.max,
        };
        if (t < inSegmentRange.min) {
            res.x = s1.x;
            res.y = s1.y;
        }
        else if (t > inSegmentRange.max) {
            res.x = s2.x;
            res.y = s2.y;
        }
        return res;
    }
    function segmentBounce(start, stop, velocity) {
        const { dx, dy } = getDistances(start, stop), wallAngle = Math.atan2(dy, dx), wallNormal = Vector.create(Math.sin(wallAngle), -Math.cos(wallAngle)), d = double * (velocity.x * wallNormal.x + velocity.y * wallNormal.y);
        wallNormal.multTo(d);
        velocity.subFrom(wallNormal);
    }

    const noPolygonDataLoaded = `No polygon data loaded.`, noPolygonFound = `No polygon found, you need to specify SVG url in config.`;
    class PolygonMaskInstance {
        dimension;
        offset;
        paths;
        raw;
        redrawTimeout;
        #container;
        #moveRadius;
        #pluginManager;
        #scale;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
            this.dimension = {
                height: 0,
                width: 0,
            };
            this.#moveRadius = 0;
            this.#scale = 1;
        }
        clickPositionValid(position) {
            const options = this.#container.actualOptions.polygon;
            return (!!options?.enable &&
                options.type !== PolygonMaskType.none &&
                options.type !== PolygonMaskType.inline &&
                this.#checkInsidePolygon(position));
        }
        draw(context) {
            if (!this.paths?.length) {
                return;
            }
            const options = this.#container.actualOptions.polygon;
            if (!options?.enable) {
                return;
            }
            const polygonDraw = options.draw;
            if (!polygonDraw.enable) {
                return;
            }
            const rawData = this.raw;
            for (const path of this.paths) {
                const path2d = path.path2d;
                if (path2d && this.offset) {
                    drawPolygonMaskPath(this.#pluginManager, context, path2d, polygonDraw.stroke, this.offset, this.#container.hdr, this.#container.peakNits, this.#container.hdrMode);
                }
                else if (rawData) {
                    drawPolygonMask(this.#pluginManager, context, rawData, polygonDraw.stroke, this.#container.hdr, this.#container.peakNits, this.#container.hdrMode);
                }
            }
        }
        async init() {
            const container = this.#container, polygonMaskOptions = container.actualOptions.polygon, pxRatio = container.retina.pixelRatio;
            if (!polygonMaskOptions) {
                return;
            }
            this.#moveRadius = polygonMaskOptions.move.radius * pxRatio;
            this.#scale = polygonMaskOptions.scale * pxRatio;
            if (polygonMaskOptions.enable) {
                await this.#initRawData();
            }
        }
        particleBounce(particle, delta, direction) {
            return this.#polygonBounce(particle, delta, direction);
        }
        particlePosition(position) {
            const options = this.#container.actualOptions.polygon, defaultLength = 0;
            if (!(options?.enable && (this.raw?.length ?? defaultLength) > defaultLength)) {
                return;
            }
            return deepExtend({}, position ?? this.#randomPoint());
        }
        particlesInitialization() {
            const options = this.#container.actualOptions.polygon;
            if (options?.enable &&
                options.type === PolygonMaskType.inline &&
                (options.inline.arrangement === PolygonMaskInlineArrangement.onePerPoint ||
                    options.inline.arrangement === PolygonMaskInlineArrangement.perPoint)) {
                this.#drawPoints();
                return true;
            }
            return false;
        }
        resize() {
            const container = this.#container, options = container.actualOptions.polygon;
            if (!(options?.enable && options.type !== PolygonMaskType.none)) {
                return;
            }
            if (this.redrawTimeout) {
                clearTimeout(this.redrawTimeout);
            }
            const timeout = 250;
            this.redrawTimeout = setTimeout(() => {
                void (async () => {
                    await this.#initRawData(true);
                    await container.particles.redraw();
                })();
            }, timeout);
        }
        stop() {
            delete this.raw;
            delete this.paths;
        }
        #checkInsidePolygon(position) {
            const container = this.#container, options = container.actualOptions.polygon;
            if (!options?.enable || options.type === PolygonMaskType.none || options.type === PolygonMaskType.inline) {
                return true;
            }
            if (!this.raw) {
                throw new Error(noPolygonFound);
            }
            const canvasSize = container.canvas.size, x = position?.x ?? getRandom() * canvasSize.width, y = position?.y ?? getRandom() * canvasSize.height, indexOffset = 1;
            let inside = false;
            for (let i = 0, j = this.raw.length - indexOffset; i < this.raw.length; j = i++) {
                const pi = this.raw[i], pj = this.raw[j];
                if (!pi || !pj) {
                    continue;
                }
                const intersect = pi.y > y !== pj.y > y && x < ((pj.x - pi.x) * (y - pi.y)) / (pj.y - pi.y) + pi.x;
                if (intersect) {
                    inside = !inside;
                }
            }
            if (options.type === PolygonMaskType.inside) {
                return inside;
            }
            else {
                return !inside;
            }
        }
        #createPath2D() {
            const container = this.#container, options = container.actualOptions.polygon;
            if (!options || !this.paths?.length) {
                return;
            }
            for (const path of this.paths) {
                const pathData = path.element.getAttribute("d");
                if (pathData) {
                    const path2d = new Path2D(pathData), matrix = safeDocument().createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(), finalPath = new Path2D(), transform = matrix.scale(this.#scale);
                    finalPath.addPath(path2d, transform);
                    path.path2d = finalPath;
                }
                else {
                    delete path.path2d;
                }
                if (path.path2d ?? !this.raw) {
                    continue;
                }
                path.path2d = new Path2D();
                const firstIndex = 0, firstPoint = this.raw[firstIndex];
                if (!firstPoint) {
                    continue;
                }
                path.path2d.moveTo(firstPoint.x, firstPoint.y);
                this.raw.forEach((pos, i) => {
                    if (i > firstIndex) {
                        path.path2d?.lineTo(pos.x, pos.y);
                    }
                });
                path.path2d.closePath();
            }
        }
        async #downloadSvgPath(svgUrl, force) {
            const options = this.#container.actualOptions.polygon;
            if (!options) {
                return;
            }
            const url = svgUrl ?? options.url, forceDownload = force ?? false;
            if (!url || (this.paths !== undefined && !forceDownload)) {
                return this.raw;
            }
            const req = await fetch(url);
            if (!req.ok) {
                throw new Error(`Error occurred during polygon mask download`);
            }
            return this.#parseSvgPath(await req.text(), force);
        }
        #drawPoints() {
            if (!this.raw) {
                return;
            }
            for (const item of this.raw) {
                this.#container.particles.addParticle({
                    x: item.x,
                    y: item.y,
                });
            }
        }
        #getEquidistantPointByIndex(index) {
            const container = this.#container, options = container.actualOptions, polygonMaskOptions = options.polygon;
            if (!polygonMaskOptions) {
                return;
            }
            if (!this.raw?.length || !this.paths?.length) {
                throw new Error(noPolygonDataLoaded);
            }
            let offset = 0, point;
            const baseAccumulator = 0, totalLength = this.paths.reduce((tot, path) => tot + path.length, baseAccumulator), distance = totalLength / options.particles.number.value;
            for (const path of this.paths) {
                const pathDistance = distance * index - offset;
                if (pathDistance <= path.length) {
                    point = path.element.getPointAtLength(pathDistance);
                    break;
                }
                else {
                    offset += path.length;
                }
            }
            const scale = this.#scale;
            return {
                x: (point?.x ?? originPoint.x) * scale + (this.offset?.x ?? originPoint.x),
                y: (point?.y ?? originPoint.y) * scale + (this.offset?.y ?? originPoint.y),
            };
        }
        #getPointByIndex(index) {
            if (!this.raw?.length) {
                throw new Error(noPolygonDataLoaded);
            }
            const coords = this.raw[index % this.raw.length];
            if (!coords) {
                return;
            }
            return {
                x: coords.x,
                y: coords.y,
            };
        }
        #getRandomPoint() {
            if (!this.raw?.length) {
                throw new Error(noPolygonDataLoaded);
            }
            const coords = itemFromArray(this.raw);
            if (!coords) {
                return;
            }
            return {
                x: coords.x,
                y: coords.y,
            };
        }
        #getRandomPointByLength() {
            const container = this.#container, options = container.actualOptions.polygon;
            if (!options) {
                return;
            }
            if (!this.raw?.length || !this.paths?.length) {
                throw new Error(noPolygonDataLoaded);
            }
            const path = itemFromArray(this.paths);
            if (!path) {
                return;
            }
            const offset = 1, distance = Math.floor(getRandom() * path.length) + offset, point = path.element.getPointAtLength(distance), scale = this.#scale;
            return {
                x: point.x * scale + (this.offset?.x ?? originPoint.x),
                y: point.y * scale + (this.offset?.y ?? originPoint.y),
            };
        }
        async #initRawData(force) {
            const options = this.#container.actualOptions.polygon;
            if (!options) {
                return;
            }
            if (options.url) {
                this.raw = await this.#downloadSvgPath(options.url, force);
            }
            else if (options.data) {
                const data = options.data;
                let svg;
                if (isString(data)) {
                    svg = data;
                }
                else {
                    const getPath = (p) => `<path d="${p}" />`, path = isArray(data.path) ? data.path.map(getPath).join("") : getPath(data.path), namespaces = 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"';
                    svg = `<svg ${namespaces} width="${data.size.width.toString()}" height="${data.size.height.toString()}">${path}</svg>`;
                }
                this.raw = this.#parseSvgPath(svg, force);
            }
            this.#createPath2D();
            this.#container.dispatchEvent("polygonMaskLoaded");
        }
        #parseSvgPath(xml, force) {
            const forceDownload = force ?? false;
            if (this.paths !== undefined && !forceDownload) {
                return this.raw;
            }
            const container = this.#container, options = container.actualOptions.polygon;
            if (!options) {
                return;
            }
            const parser = new DOMParser(), doc = parser.parseFromString(xml, "image/svg+xml"), firstIndex = 0, svg = doc.getElementsByTagName("svg")[firstIndex];
            if (!svg) {
                return;
            }
            let svgPaths = svg.getElementsByTagName("path");
            if (!svgPaths.length) {
                svgPaths = doc.getElementsByTagName("path");
            }
            this.paths = [];
            for (let i = 0; i < svgPaths.length; i++) {
                const path = svgPaths.item(i);
                if (path) {
                    this.paths.push({
                        element: path,
                        length: path.getTotalLength(),
                    });
                }
            }
            const scale = this.#scale;
            this.dimension.width = parseFloat(svg.getAttribute("width") ?? "0") * scale;
            this.dimension.height = parseFloat(svg.getAttribute("height") ?? "0") * scale;
            const position = options.position ?? {
                x: 50,
                y: 50,
            }, canvasSize = container.canvas.size;
            this.offset = {
                x: (canvasSize.width * position.x) / percentDenominator - this.dimension.width * half$2,
                y: (canvasSize.height * position.y) / percentDenominator - this.dimension.height * half$2,
            };
            return parsePaths(this.paths, scale, this.offset);
        }
        #polygonBounce(particle, _delta, direction) {
            const options = this.#container.actualOptions.polygon;
            if (!this.raw || !options?.enable || direction !== exports.OutModeDirection.top) {
                return false;
            }
            if (options.type === PolygonMaskType.inside || options.type === PolygonMaskType.outside) {
                let closest, dx, dy;
                const pos = particle.getPosition(), radius = particle.getRadius(), offset = 1;
                for (let i = 0, j = this.raw.length - offset; i < this.raw.length; j = i++) {
                    const pi = this.raw[i], pj = this.raw[j];
                    if (!pi || !pj) {
                        continue;
                    }
                    closest = calcClosestPointOnSegment(pi, pj, pos);
                    const dist = getDistances(pos, closest);
                    [dx, dy] = [dist.dx, dist.dy];
                    if (dist.distance < radius) {
                        segmentBounce(pi, pj, particle.velocity);
                        return true;
                    }
                }
                if (closest && dx !== undefined && dy !== undefined && !this.#checkInsidePolygon(pos)) {
                    const factor = { x: 1, y: 1 }, diameter = radius * double, inverse = -1;
                    if (pos.x >= closest.x) {
                        factor.x = -1;
                    }
                    if (pos.y >= closest.y) {
                        factor.y = -1;
                    }
                    particle.position.x = closest.x + diameter * factor.x;
                    particle.position.y = closest.y + diameter * factor.y;
                    particle.velocity.mult(inverse);
                    return true;
                }
            }
            else if (options.type === PolygonMaskType.inline) {
                const dist = getDistance(particle.initialPosition, particle.getPosition()), { velocity } = particle;
                if (dist > this.#moveRadius) {
                    velocity.x = velocity.y * half$2 - velocity.x;
                    velocity.y = velocity.x * half$2 - velocity.y;
                    return true;
                }
            }
            return false;
        }
        #randomPoint() {
            const container = this.#container, options = container.actualOptions.polygon;
            if (!options) {
                return;
            }
            let position;
            if (options.type === PolygonMaskType.inline) {
                switch (options.inline.arrangement) {
                    case PolygonMaskInlineArrangement.randomPoint:
                        position = this.#getRandomPoint();
                        break;
                    case PolygonMaskInlineArrangement.randomLength:
                        position = this.#getRandomPointByLength();
                        break;
                    case PolygonMaskInlineArrangement.equidistant:
                        position = this.#getEquidistantPointByIndex(container.particles.count);
                        break;
                    case PolygonMaskInlineArrangement.onePerPoint:
                    case PolygonMaskInlineArrangement.perPoint:
                    default:
                        position = this.#getPointByIndex(container.particles.count);
                }
            }
            else {
                const canvasSize = container.canvas.size;
                position = {
                    x: getRandom() * canvasSize.width,
                    y: getRandom() * canvasSize.height,
                };
            }
            if (this.#checkInsidePolygon(position)) {
                return position;
            }
            else {
                return this.#randomPoint();
            }
        }
    }

    var PolygonMaskInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        PolygonMaskInstance: PolygonMaskInstance
    });

    class ResponsivePluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        updateActualOptions() {
            const container = this.#container;
            container.actualOptions.responsive = [];
            const newMaxWidth = container.actualOptions.setResponsive?.(container.canvas.size.width, container.retina.pixelRatio, container.options);
            if (container.responsiveMaxWidth === newMaxWidth) {
                return false;
            }
            container.responsiveMaxWidth = newMaxWidth;
            return true;
        }
    }

    var ResponsivePluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ResponsivePluginInstance: ResponsivePluginInstance
    });

    var SoundsEventType;
    (function (SoundsEventType) {
        SoundsEventType["mute"] = "soundsMuted";
        SoundsEventType["unmute"] = "soundsUnmuted";
    })(SoundsEventType || (SoundsEventType = {}));
    var ImageDisplay;
    (function (ImageDisplay) {
        ImageDisplay["Block"] = "block";
        ImageDisplay["None"] = "none";
    })(ImageDisplay || (ImageDisplay = {}));

    const zIndexOffset = 1, rightOffset = 1, minVolume = 0;
    function initImage(data) {
        const img = safeDocument().createElement("img"), { clickCb, container, display, iconOptions, margin, options, pos, rightOffsets } = data, { width, path, style, svg } = iconOptions, defaultAccumulator = 0;
        setIconStyle(img, pos.top + margin, pos.right -
            (margin * (rightOffsets.length + rightOffset) + width + rightOffsets.reduce((a, b) => a + b, defaultAccumulator)), display, options.fullScreen.zIndex + zIndexOffset, width, margin, style);
        img.src = path ?? (svg ? `data:image/svg+xml;base64,${btoa(svg)}` : "");
        const parent = container.canvas.domElement?.parentNode ?? safeDocument().body;
        parent.append(img);
        img.addEventListener("click", () => {
            void clickCb();
        });
        return img;
    }
    function removeImage(image) {
        if (!image) {
            return;
        }
        image.remove();
    }
    function setIconStyle(icon, top, left, display, zIndex, width, margin, style) {
        icon.style.userSelect = "none";
        icon.style.position = "absolute";
        icon.style.top = `${(top + margin).toString()}px`;
        icon.style.left = `${(left - margin - width).toString()}px`;
        icon.style.display = display;
        icon.style.zIndex = (zIndex + zIndexOffset).toString();
        icon.style.cssText += style;
    }
    class SoundsPluginInstance {
        #audioMap;
        #audioSources;
        #container;
        #engine;
        #gain;
        #muteImg;
        #unmuteImg;
        #volume;
        #volumeDownImg;
        #volumeUpImg;
        constructor(container, engine) {
            this.#container = container;
            this.#engine = engine;
            this.#volume = 0;
            this.#audioSources = [];
            this.#audioMap = new Map();
        }
        async init() {
            const container = this.#container, options = container.actualOptions, soundsOptions = options.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            if (soundsOptions.autoPlay && isWindowMuted()) {
                const firstClickHandler = () => {
                    removeEventListener(mouseDownEvent, firstClickHandler);
                    removeEventListener(touchStartEvent, firstClickHandler);
                    unmuteWindow();
                    void this.unmute();
                }, listenerOptions = {
                    capture: true,
                    once: true,
                };
                addEventListener(mouseDownEvent, firstClickHandler, listenerOptions);
                addEventListener(touchStartEvent, firstClickHandler, listenerOptions);
            }
            this.#volume = soundsOptions.volume.value;
            const events = soundsOptions.events;
            this.#audioMap = new Map();
            for (const event of events) {
                if (!event.audio) {
                    continue;
                }
                const promises = executeOnSingleOrMultiple(event.audio, async (audio) => {
                    const response = await fetch(audio.source);
                    if (!response.ok) {
                        return;
                    }
                    const arrayBuffer = await response.arrayBuffer(), audioContext = this.#getAudioContext(), audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
                    this.#audioMap.set(audio.source, audioBuffer);
                });
                if (promises instanceof Promise) {
                    await promises;
                }
                else {
                    await Promise.allSettled(promises);
                }
            }
        }
        async mute() {
            if (!this.#container.muted) {
                await this.toggleMute();
            }
        }
        async start() {
            const container = this.#container, options = container.actualOptions, soundsOptions = options.sounds;
            if (!soundsOptions?.enable || !container.canvas.domElement) {
                return;
            }
            container.muted = true;
            const canvas = container.canvas.domElement, pos = {
                top: canvas.offsetTop,
                right: canvas.offsetLeft + canvas.offsetWidth,
            }, { mute, unmute, volumeDown, volumeUp } = soundsOptions.icons, margin = 10, toggleMute = async () => {
                await this.toggleMute();
            }, enableIcons = soundsOptions.icons.enable, display = enableIcons ? ImageDisplay.Block : ImageDisplay.None;
            this.#muteImg = initImage({
                container,
                options,
                pos,
                display,
                iconOptions: mute,
                margin,
                rightOffsets: [volumeDown.width, volumeUp.width],
                clickCb: toggleMute,
            });
            this.#unmuteImg = initImage({
                container,
                options,
                pos,
                display: ImageDisplay.None,
                iconOptions: unmute,
                margin,
                rightOffsets: [volumeDown.width, volumeUp.width],
                clickCb: toggleMute,
            });
            this.#volumeDownImg = initImage({
                container,
                options,
                pos,
                display,
                iconOptions: volumeDown,
                margin,
                rightOffsets: [volumeUp.width],
                clickCb: async () => {
                    await this.volumeDown();
                },
            });
            this.#volumeUpImg = initImage({
                container,
                options,
                pos,
                display,
                iconOptions: volumeUp,
                margin,
                rightOffsets: [],
                clickCb: async () => {
                    await this.volumeUp();
                },
            });
            if (!isWindowMuted() && soundsOptions.autoPlay) {
                await this.unmute();
            }
        }
        stop() {
            this.#container.muted = true;
            void (async () => {
                await this.#mute();
                removeImage(this.#muteImg);
                removeImage(this.#unmuteImg);
                removeImage(this.#volumeDownImg);
                removeImage(this.#volumeUpImg);
            })();
        }
        async toggleMute() {
            const container = this.#container;
            container.muted = !container.muted;
            this.#updateMuteIcons();
            await this.#updateMuteStatus();
        }
        async unmute() {
            if (this.#container.muted) {
                await this.toggleMute();
            }
        }
        async volumeDown() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            if (container.muted) {
                this.#volume = 0;
            }
            this.#volume -= soundsOptions.volume.step;
            await this.#updateVolume();
        }
        async volumeUp() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            this.#volume += soundsOptions.volume.step;
            await this.#updateVolume();
        }
        #addBuffer(audioCtx) {
            const buffer = audioCtx.createBufferSource();
            this.#audioSources.push(buffer);
            return buffer;
        }
        #addOscillator(audioCtx) {
            const oscillator = audioCtx.createOscillator();
            this.#audioSources.push(oscillator);
            return oscillator;
        }
        #getAudioContext() {
            const container = this.#container;
            container.audioContext ??= new AudioContext();
            return container.audioContext;
        }
        #initEvents() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable || !container.canvas.domElement) {
                return;
            }
            for (const event of soundsOptions.events) {
                const cb = (args) => {
                    if (!args) {
                        return;
                    }
                    void (async () => {
                        const filterNotValid = event.filter && !event.filter(args);
                        if (this.#container !== args.container) {
                            return;
                        }
                        if (!!this.#container.muted || this.#container.destroyed) {
                            executeOnSingleOrMultiple(event.event, item => {
                                this.#engine.removeEventListener(item, cb);
                            });
                            return;
                        }
                        if (filterNotValid) {
                            return;
                        }
                        const defaultNoteIndex = 0;
                        if (event.audio) {
                            const audio = itemFromSingleOrMultiple(event.audio);
                            if (!audio) {
                                return;
                            }
                            this.#playBuffer(audio);
                        }
                        else if (event.melodies) {
                            const melody = itemFromArray(event.melodies);
                            if (!melody) {
                                return;
                            }
                            if (melody.melodies.length) {
                                await Promise.allSettled(melody.melodies.map(m => this.#playNote(m.notes, defaultNoteIndex, melody.loop)));
                            }
                            else {
                                await this.#playNote(melody.notes, defaultNoteIndex, melody.loop);
                            }
                        }
                        else if (event.notes) {
                            const note = itemFromArray(event.notes);
                            if (!note) {
                                return;
                            }
                            await this.#playNote([note], defaultNoteIndex, false);
                        }
                    })();
                };
                executeOnSingleOrMultiple(event.event, item => {
                    this.#engine.addEventListener(item, cb);
                });
            }
        }
        async #mute() {
            const container = this.#container, audioContext = this.#getAudioContext();
            for (const source of this.#audioSources) {
                this.#removeAudioSource(source);
            }
            if (this.#gain) {
                this.#gain.disconnect();
            }
            await audioContext.close();
            container.audioContext = undefined;
            this.#container.dispatchEvent(SoundsEventType.mute);
        }
        #playBuffer(audio) {
            const audioBuffer = this.#audioMap.get(audio.source);
            if (!audioBuffer) {
                return;
            }
            const audioCtx = this.#container.audioContext;
            if (!audioCtx) {
                return;
            }
            const source = this.#addBuffer(audioCtx);
            source.loop = audio.loop;
            source.buffer = audioBuffer;
            source.connect(this.#gain ?? audioCtx.destination);
            source.start();
        }
        async #playFrequency(frequency, duration) {
            if (!this.#gain || this.#container.muted) {
                return;
            }
            const audioContext = this.#getAudioContext(), oscillator = this.#addOscillator(audioContext);
            oscillator.connect(this.#gain);
            oscillator.type = "sine";
            oscillator.frequency.value = frequency;
            oscillator.start();
            return new Promise(resolve => {
                setTimeout(() => {
                    this.#removeAudioSource(oscillator);
                    resolve();
                }, duration);
            });
        }
        #playMuteSound() {
            if (this.#container.muted) {
                return;
            }
            const audioContext = this.#getAudioContext(), gain = audioContext.createGain();
            gain.connect(audioContext.destination);
            gain.gain.value = 0;
            const oscillator = audioContext.createOscillator();
            oscillator.connect(gain);
            oscillator.type = "sine";
            oscillator.frequency.value = 1;
            oscillator.start();
            setTimeout(() => {
                oscillator.stop();
                oscillator.disconnect();
                gain.disconnect();
            });
        }
        async #playNote(notes, noteIdx, loop) {
            if (this.#container.muted) {
                return;
            }
            const note = notes[noteIdx];
            if (!note) {
                return;
            }
            const value = note.value, promises = executeOnSingleOrMultiple(value, async (_, idx) => {
                return this.#playNoteValue(notes, noteIdx, idx);
            });
            await (isArray(promises) ? Promise.allSettled(promises) : promises);
            const indexOffset = 1;
            let nextNoteIdx = noteIdx + indexOffset;
            if (loop && nextNoteIdx >= notes.length) {
                nextNoteIdx = nextNoteIdx % notes.length;
            }
            await this.#playNote(notes, nextNoteIdx, loop);
        }
        async #playNoteValue(notes, noteIdx, valueIdx) {
            const note = notes[noteIdx];
            if (!note) {
                return;
            }
            const value = itemFromSingleOrMultiple(note.value, valueIdx, true);
            if (!value) {
                return;
            }
            try {
                const freq = getNoteFrequency(value);
                if (!isNumber(freq)) {
                    return;
                }
                await this.#playFrequency(freq, note.duration);
            }
            catch (e) {
                getLogger().error(e);
            }
        }
        #removeAudioSource(source) {
            source.stop();
            source.disconnect();
            const deleteCount = 1;
            this.#audioSources.splice(this.#audioSources.indexOf(source), deleteCount);
        }
        #unmute() {
            const container = this.#container, options = container.actualOptions, soundsOptions = options.sounds;
            if (!soundsOptions) {
                return;
            }
            const audioContext = this.#getAudioContext(), gain = audioContext.createGain();
            gain.connect(audioContext.destination);
            gain.gain.value = soundsOptions.volume.value / percentDenominator;
            this.#gain = gain;
            this.#initEvents();
            this.#container.dispatchEvent(SoundsEventType.unmute);
        }
        #updateMuteIcons() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable || !soundsOptions.icons.enable) {
                return;
            }
            const muteImg = this.#muteImg, unmuteImg = this.#unmuteImg;
            if (muteImg) {
                muteImg.style.display = container.muted ? "block" : "none";
            }
            if (unmuteImg) {
                unmuteImg.style.display = container.muted ? "none" : "block";
            }
        }
        async #updateMuteStatus() {
            const container = this.#container, audioContext = this.#getAudioContext();
            if (container.muted) {
                await audioContext.suspend();
                await this.#mute();
            }
            else {
                await audioContext.resume();
                this.#unmute();
                this.#playMuteSound();
            }
        }
        async #updateVolume() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            clamp(this.#volume, soundsOptions.volume.min, soundsOptions.volume.max);
            let stateChanged = false;
            if (this.#volume <= minVolume && !container.muted) {
                this.#volume = 0;
                container.muted = true;
                stateChanged = true;
            }
            else if (this.#volume > minVolume && container.muted) {
                container.muted = false;
                stateChanged = true;
            }
            if (stateChanged) {
                this.#updateMuteIcons();
                await this.#updateMuteStatus();
            }
            if (this.#gain?.gain) {
                this.#gain.gain.value = this.#volume / percentDenominator;
            }
        }
    }

    var SoundsPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        SoundsPluginInstance: SoundsPluginInstance
    });

    class ThemesPluginInstance {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init() {
            const container = this.#container;
            container.themeMatchMedia = safeMatchMedia("(prefers-color-scheme: dark)");
            const loadTheme = async (name) => {
                if (container.destroyed) {
                    return;
                }
                container.currentTheme = name;
                await container.refresh();
            };
            container.themeHandlers = {
                themeChange: (e) => {
                    this.#handleThemeChange(e);
                },
                oldThemeChange: (e) => {
                    this.#handleThemeChange(e);
                },
            };
            container.manageMediaMatch = (add) => {
                const handlers = container.themeHandlers;
                if (!handlers) {
                    return;
                }
                if (!container.themeMatchMedia) {
                    return;
                }
                manageListener(container.themeMatchMedia, "change", handlers.themeChange, add);
            };
            container.loadTheme = loadTheme;
            return Promise.resolve();
        }
        manageListeners(add) {
            const container = this.#container;
            container.manageMediaMatch?.(add);
        }
        async start() {
            this.manageListeners(true);
            return Promise.resolve();
        }
        stop() {
            this.manageListeners(false);
        }
        updateActualOptions() {
            const container = this.#container;
            container.actualOptions.setTheme?.(container.currentTheme);
            return false;
        }
        #handleThemeChange(e) {
            const mediaEvent = e, container = this.#container, options = container.options, defaultThemes = options.defaultThemes, themeName = mediaEvent.matches ? defaultThemes.dark : defaultThemes.light, theme = options.themes?.find(theme => theme.name === themeName);
            if (theme?.default.auto) {
                void container.loadTheme?.(themeName);
            }
        }
    }

    var ThemesPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ThemesPluginInstance: ThemesPluginInstance
    });

    const minimumLength = 0;
    class TrailPluginInstance {
        layer = exports.DrawLayer.PluginContent;
        #container;
        #pluginManager;
        #trailFill;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
        }
        canvasClear() {
            const container = this.#container, trail = container.actualOptions.trail, trailFill = this.#trailFill;
            if (!trail?.enable || !trailFill || trail.length <= minimumLength) {
                return false;
            }
            let handled = false;
            const canvas = container.canvas;
            if (trailFill.color) {
                canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity, container.peakNits, container.hdrMode));
                handled = true;
            }
            else if (trailFill.image) {
                canvas.render.paintImage(trailFill.image, trailFill.opacity);
                handled = true;
            }
            return handled;
        }
        async init() {
            try {
                await this.#initTrail();
            }
            catch (e) {
                getLogger().error(e);
            }
        }
        async #initTrail() {
            const options = this.#container.actualOptions, trail = options.trail;
            if (!trail?.enable) {
                return;
            }
            const trailFill = trail.fill, opacity = inverseFactorNumerator / trail.length;
            if (trailFill.color) {
                const fillColor = rangeColorToRgb(this.#pluginManager, trailFill.color);
                if (!fillColor) {
                    return;
                }
                this.#trailFill = {
                    color: {
                        ...fillColor,
                    },
                    opacity,
                };
            }
            else {
                await new Promise((resolve, reject) => {
                    if (!trailFill.image) {
                        return;
                    }
                    const img = safeDocument().createElement("img");
                    img.addEventListener("load", () => {
                        this.#trailFill = {
                            image: img,
                            opacity,
                        };
                        resolve();
                    });
                    img.addEventListener("error", evt => {
                        getLogger().error(evt);
                        reject(new Error("Error loading image"));
                    });
                    img.src = trailFill.image;
                });
            }
        }
    }

    var TrailPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        TrailPluginInstance: TrailPluginInstance
    });

    class ZoomEventListeners {
        #container;
        #gestureScale;
        #handlers;
        #touchDistance;
        constructor(container) {
            this.#container = container;
            this.#gestureScale = defaultZoom;
            this.#touchDistance = initialTouchDistance;
            this.#handlers = {
                gestureStart: (e) => {
                    this.#handleGestureStart(e);
                },
                gestureChange: (e) => {
                    this.#handleGestureChange(e);
                },
                gestureEnd: (e) => {
                    this.#handleGestureEnd(e);
                },
                wheel: (e) => {
                    this.#handleMouseWheel(e);
                },
                touchMove: (e) => {
                    this.#handleTouchZoom(e);
                },
                touchEnd: () => {
                    this.#handleTouchEnd();
                },
            };
        }
        addListeners() {
            this.#manageListeners(true);
        }
        removeListeners() {
            this.#manageListeners(false);
        }
        #handleGestureChange(event) {
            const container = this.#container, canvas = container.canvas, canvasEl = canvas.domElement;
            if (!canvasEl) {
                return;
            }
            const zoomOptions = container.actualOptions.zoom;
            if (!zoomOptions?.enable) {
                return;
            }
            if (!this.#isEventInsideCanvas(event, canvasEl)) {
                return;
            }
            event.preventDefault();
            const gestureEvent = event, baseZoom = defaultZoom, gestureFactor = zoomGestureFactor, scale = gestureEvent.scale ?? baseZoom;
            if (scale === this.#gestureScale) {
                return;
            }
            const scaleDelta = scale / this.#gestureScale, adjustedScale = baseZoom + (scaleDelta - baseZoom) * gestureFactor, currentZoom = canvas.zoom, newZoom = Math.max(zoomOptions.min, Math.min(currentZoom * adjustedScale, zoomOptions.max)), rect = canvasEl.getBoundingClientRect(), clientX = gestureEvent.clientX ?? rect.left + rect.width / touchCenterDivisor, clientY = gestureEvent.clientY ?? rect.top + rect.height / touchCenterDivisor, pixelRatio = this.#container.retina.pixelRatio, centerX = (clientX - rect.left) * pixelRatio, centerY = (clientY - rect.top) * pixelRatio;
            canvas.setZoom(newZoom, { x: centerX, y: centerY });
            this.#gestureScale = scale;
        }
        #handleGestureEnd(event) {
            const container = this.#container, canvas = container.canvas, canvasEl = canvas.domElement;
            if (!canvasEl) {
                return;
            }
            const zoomOptions = container.actualOptions.zoom;
            if (!zoomOptions?.enable) {
                return;
            }
            if (!this.#isEventInsideCanvas(event, canvasEl)) {
                return;
            }
            event.preventDefault();
            this.#gestureScale = defaultZoom;
        }
        #handleGestureStart(event) {
            const container = this.#container, canvas = container.canvas, canvasEl = canvas.domElement;
            if (!canvasEl) {
                return;
            }
            const zoomOptions = container.actualOptions.zoom;
            if (!zoomOptions?.enable) {
                return;
            }
            if (!this.#isEventInsideCanvas(event, canvasEl)) {
                return;
            }
            event.preventDefault();
            this.#gestureScale = defaultZoom;
        }
        #handleMouseWheel(event) {
            if (!event.ctrlKey && !event.metaKey) {
                return;
            }
            const container = this.#container, zoomOptions = container.actualOptions.zoom, canvas = container.canvas, canvasEl = canvas.domElement;
            if (!canvasEl) {
                return;
            }
            if (!zoomOptions?.enable) {
                return;
            }
            if (!this.#isEventInsideCanvas(event, canvasEl)) {
                return;
            }
            event.preventDefault();
            const zoomFactor = event.deltaY > initialTouchDistance ? zoomOutFactor : zoomInFactor, currentZoom = canvas.zoom, newZoom = Math.max(zoomOptions.min, Math.min(currentZoom * zoomFactor, zoomOptions.max)), rect = canvasEl.getBoundingClientRect(), pixelRatio = this.#container.retina.pixelRatio, mouseX = (event.clientX - rect.left) * pixelRatio, mouseY = (event.clientY - rect.top) * pixelRatio;
            canvas.setZoom(newZoom, { x: mouseX, y: mouseY });
        }
        #handleTouchEnd() {
            this.#touchDistance = initialTouchDistance;
        }
        #handleTouchZoom(event) {
            if (event.touches.length !== touchPointsCount) {
                return;
            }
            event.preventDefault();
            const touch1 = event.touches[touchPointIndexFirst], touch2 = event.touches[touchPointIndexSecond];
            if (!touch1 || !touch2) {
                return;
            }
            const distance = Math.hypot(touch1.clientX - touch2.clientX, touch1.clientY - touch2.clientY);
            if (this.#touchDistance === initialTouchDistance) {
                this.#touchDistance = distance;
                return;
            }
            const container = this.#container, zoomOptions = container.actualOptions.zoom, canvas = container.canvas, canvasEl = canvas.domElement;
            if (!canvasEl) {
                return;
            }
            if (!zoomOptions?.enable) {
                return;
            }
            if (!this.#isEventInsideCanvas(event, canvasEl)) {
                return;
            }
            const scale = distance / this.#touchDistance, baseZoom = defaultZoom, gestureFactor = zoomGestureFactor, adjustedScale = baseZoom + (scale - baseZoom) * gestureFactor, currentZoom = canvas.zoom, newZoom = Math.max(zoomOptions.min, Math.min(currentZoom * adjustedScale, zoomOptions.max)), rect = canvasEl.getBoundingClientRect(), pixelRatio = this.#container.retina.pixelRatio, centerX = ((touch1.clientX + touch2.clientX) / touchCenterDivisor - rect.left) * pixelRatio, centerY = ((touch1.clientY + touch2.clientY) / touchCenterDivisor - rect.top) * pixelRatio;
            canvas.setZoom(newZoom, { x: centerX, y: centerY });
            this.#touchDistance = distance;
        }
        #isEventInsideCanvas(event, canvasEl) {
            if (event.target === canvasEl) {
                return true;
            }
            const eventWithPath = event, path = eventWithPath.composedPath();
            if (path.includes(canvasEl)) {
                return true;
            }
            const { clientX, clientY } = eventWithPath;
            if (typeof clientX === "number" && typeof clientY === "number") {
                const rect = canvasEl.getBoundingClientRect();
                return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
            }
            return false;
        }
        #manageListeners(add) {
            const handlers = this.#handlers, canvas = this.#container.canvas.domElement, options = this.#container.actualOptions, doc = safeDocument();
            if (!canvas) {
                return;
            }
            if (add && !options.zoom?.enable) {
                return;
            }
            const listenerOptions = { passive: false }, captureOptions = { capture: true, passive: false };
            manageListener(doc, "gesturestart", handlers.gestureStart, add, captureOptions);
            manageListener(doc, "gesturechange", handlers.gestureChange, add, captureOptions);
            manageListener(doc, "gestureend", handlers.gestureEnd, add, captureOptions);
            manageListener(doc, "wheel", handlers.wheel, add, captureOptions);
            manageListener(canvas, "gesturestart", handlers.gestureStart, add, listenerOptions);
            manageListener(canvas, "gesturechange", handlers.gestureChange, add, listenerOptions);
            manageListener(canvas, "gestureend", handlers.gestureEnd, add, listenerOptions);
            manageListener(canvas, "wheel", handlers.wheel, add, listenerOptions);
            manageListener(canvas, "touchmove", handlers.touchMove, add, listenerOptions);
            manageListener(canvas, "touchend", handlers.touchEnd, add, listenerOptions);
            manageListener(canvas, "touchcancel", handlers.touchEnd, add, listenerOptions);
        }
    }

    class ZoomPluginInstance {
        layer = exports.DrawLayer.CanvasSetup;
        #container;
        #listeners;
        constructor(container) {
            this.#container = container;
            this.#listeners = new ZoomEventListeners(container);
        }
        destroy() {
            this.#listeners.removeListeners();
        }
        drawParticleTransform(data) {
            const container = this.#container, canvas = container.canvas, zoom = canvas.zoom;
            if (zoom === defaultZoom) {
                return;
            }
            const center = canvas.getZoomCenter(), { context, position, transformData } = data, zoomedX = center.x + (position.x - center.x) * zoom, zoomedY = center.y + (position.y - center.y) * zoom;
            data.drawScale = zoom;
            data.drawRadius = data.radius * zoom;
            data.drawPosition = { x: zoomedX, y: zoomedY };
            context.setTransform(transformData.a * zoom, transformData.b * zoom, transformData.c * zoom, transformData.d * zoom, zoomedX, zoomedY);
        }
        drawSettingsCleanup(context) {
            const zoom = this.#container.canvas.zoom;
            if (zoom === defaultZoom) {
                return;
            }
            context.restore();
        }
        drawSettingsSetup(context) {
            const zoom = this.#container.canvas.zoom;
            if (zoom === defaultZoom) {
                return;
            }
            context.save();
            const { x: centerX, y: centerY } = this.#container.canvas.getZoomCenter();
            context.translate(centerX, centerY);
            context.scale(zoom, zoom);
            context.translate(-centerX, -centerY);
        }
        start() {
            this.#listeners.addListeners();
            return Promise.resolve();
        }
        stop() {
            this.#listeners.removeListeners();
        }
    }

    var ZoomPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ZoomPluginInstance: ZoomPluginInstance
    });

    const defaultLifeDelay$1 = 0, minLifeCount$1 = 0, defaultSpawnDelay$1 = 0, defaultEmitDelay = 0, defaultLifeCount$1 = -1, defaultColorAnimationFactor = 1, colorFactor = 3.6, defaultStrokeWidth = 1;
    function setParticlesOptionsFillColor(particlesOptions, color, opacity, enable) {
        const paint = (particlesOptions.paint ??= new Paint());
        paint.fill = {
            color: AnimatableColor.create(undefined, { value: color }),
            enable,
            opacity,
        };
    }
    function setParticlesOptionsStrokeColor(particlesOptions, color, opacity, width) {
        const paint = (particlesOptions.paint ??= new Paint());
        paint.stroke = {
            color: AnimatableColor.create(undefined, { value: color }),
            opacity,
            width,
        };
    }
    class EmitterInstance {
        fill;
        name;
        options;
        position;
        size;
        spawnFillColor;
        spawnFillEnabled;
        spawnFillOpacity;
        spawnStrokeColor;
        spawnStrokeOpacity;
        spawnStrokeWidth;
        #container;
        #currentDuration;
        #currentEmitDelay;
        #currentSpawnDelay;
        #duration;
        #emitDelay;
        #firstSpawn;
        #immortal;
        #initialPosition;
        #lifeCount;
        #mutationObserver;
        #particlesOptions;
        #paused;
        #pluginManager;
        #removeCallback;
        #resizeObserver;
        #shape;
        #size;
        #spawnDelay;
        #startParticlesAdded;
        constructor(pluginManager, container, removeCallback, options, position) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#removeCallback = removeCallback;
            this.#currentDuration = 0;
            this.#currentEmitDelay = 0;
            this.#currentSpawnDelay = 0;
            this.#initialPosition = position;
            if (options instanceof Emitter) {
                this.options = options;
            }
            else {
                this.options = new Emitter();
                this.options.load(options);
            }
            this.#spawnDelay = container.retina.reduceFactor
                ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay$1) * millisecondsToSeconds$1) /
                    container.retina.reduceFactor
                : Infinity;
            this.position = this.#initialPosition ?? this.#calcPosition();
            this.name = this.options.name;
            this.fill = this.options.fill;
            this.#firstSpawn = !this.options.life.wait;
            this.#startParticlesAdded = false;
            const particlesOptions = deepExtend({}, this.options.particles);
            particlesOptions.move ??= {};
            particlesOptions.move.direction ??= this.options.direction;
            if (this.options.spawn.fill?.color) {
                this.spawnFillColor = rangeColorToHsl(this.#pluginManager, this.options.spawn.fill.color);
            }
            if (this.options.spawn.stroke?.color) {
                this.spawnStrokeColor = rangeColorToHsl(this.#pluginManager, this.options.spawn.stroke.color);
            }
            this.#paused = !this.options.autoPlay;
            this.#particlesOptions = particlesOptions;
            this.#size = this.#calcSize();
            this.size =
                this.#size.mode === exports.PixelMode.percent
                    ? {
                        width: (this.#size.width / percentDenominator) * this.#container.canvas.size.width,
                        height: (this.#size.height / percentDenominator) * this.#container.canvas.size.height,
                    }
                    : { width: this.#size.width, height: this.#size.height };
            this.#lifeCount = this.options.life.count ?? defaultLifeCount$1;
            this.#immortal = this.#lifeCount <= minLifeCount$1;
            if (this.options.domId) {
                const element = safeDocument().getElementById(this.options.domId);
                if (element) {
                    this.#mutationObserver = new MutationObserver(() => {
                        this.resize();
                    });
                    this.#resizeObserver = new ResizeObserver(() => {
                        this.resize();
                    });
                    this.#mutationObserver.observe(element, {
                        attributes: true,
                        attributeFilter: ["style", "width", "height"],
                    });
                    this.#resizeObserver.observe(element);
                }
            }
            const shapeOptions = this.options.shape, shapeGenerator = this.#pluginManager.emitterShapeManager?.getShapeGenerator(shapeOptions.type);
            if (shapeGenerator) {
                this.#shape = shapeGenerator.generate(this.#container, this.position, this.size, this.fill, shapeOptions.options);
            }
            this.#container.dispatchEvent("emitterCreated", {
                emitter: this,
            });
            this.play();
        }
        externalPause() {
            this.#paused = true;
            this.pause();
        }
        externalPlay() {
            this.#paused = false;
            this.play();
        }
        async init() {
            await this.#shape?.init();
        }
        pause() {
            if (this.#paused) {
                return;
            }
            this.#emitDelay = undefined;
        }
        play() {
            if (this.#paused) {
                return;
            }
            if (!((this.#lifeCount > minLifeCount$1 || this.#immortal || !this.options.life.count) &&
                (this.#firstSpawn || this.#currentSpawnDelay >= (this.#spawnDelay ?? defaultSpawnDelay$1)))) {
                return;
            }
            const container = this.#container;
            if (this.#emitDelay === undefined) {
                const delay = getRangeValue(this.options.rate.delay);
                this.#emitDelay = container.retina.reduceFactor
                    ? (delay * millisecondsToSeconds$1) / container.retina.reduceFactor
                    : Infinity;
            }
            if (this.#lifeCount > minLifeCount$1 || this.#immortal) {
                this.#prepareToDie();
            }
        }
        resize() {
            const initialPosition = this.#initialPosition, container = this.#container;
            this.position =
                initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
                    ? initialPosition
                    : this.#calcPosition();
            this.#size = this.#calcSize();
            this.size =
                this.#size.mode === exports.PixelMode.percent
                    ? {
                        width: (this.#size.width / percentDenominator) * container.canvas.size.width,
                        height: (this.#size.height / percentDenominator) * container.canvas.size.height,
                    }
                    : { width: this.#size.width, height: this.#size.height };
            this.#shape?.resize(this.position, this.size);
        }
        update(delta) {
            if (this.#paused) {
                return;
            }
            const container = this.#container;
            if (this.#firstSpawn) {
                this.#firstSpawn = false;
                this.#currentSpawnDelay = this.#spawnDelay ?? defaultSpawnDelay$1;
                this.#currentEmitDelay = this.#emitDelay ?? defaultEmitDelay;
            }
            if (!this.#startParticlesAdded) {
                this.#startParticlesAdded = true;
                this.#emitParticles(this.options.startCount);
            }
            if (this.#duration !== undefined) {
                this.#currentDuration += delta.value;
                if (this.#currentDuration >= this.#duration) {
                    this.pause();
                    if (this.#spawnDelay !== undefined) {
                        this.#spawnDelay = undefined;
                    }
                    if (!this.#immortal) {
                        this.#lifeCount--;
                    }
                    if (this.#lifeCount > minLifeCount$1 || this.#immortal) {
                        this.position = this.#calcPosition();
                        this.#shape?.resize(this.position, this.size);
                        this.#spawnDelay = container.retina.reduceFactor
                            ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay$1) * millisecondsToSeconds$1) /
                                container.retina.reduceFactor
                            : Infinity;
                    }
                    else {
                        this.#destroy();
                    }
                    this.#currentDuration -= this.#duration;
                    this.#duration = undefined;
                }
            }
            if (this.#spawnDelay !== undefined) {
                this.#currentSpawnDelay += delta.value;
                if (this.#currentSpawnDelay >= this.#spawnDelay) {
                    this.#container.dispatchEvent("emitterPlay");
                    this.play();
                    this.#currentSpawnDelay -= this.#spawnDelay;
                    this.#spawnDelay = undefined;
                }
            }
            if (this.#emitDelay !== undefined) {
                this.#currentEmitDelay += delta.value;
                if (this.#currentEmitDelay >= this.#emitDelay) {
                    this.#emit();
                    this.#currentEmitDelay -= this.#emitDelay;
                }
            }
        }
        #calcPosition() {
            const container = this.#container;
            if (this.options.domId) {
                const element = safeDocument().getElementById(this.options.domId);
                if (element) {
                    const elRect = element.getBoundingClientRect(), pxRatio = container.retina.pixelRatio;
                    return {
                        x: (elRect.x + elRect.width * half$2) * pxRatio,
                        y: (elRect.y + elRect.height * half$2) * pxRatio,
                    };
                }
            }
            return calcPositionOrRandomFromSizeRanged({
                size: container.canvas.size,
                position: this.options.position,
            });
        }
        #calcSize() {
            const container = this.#container;
            if (this.options.domId) {
                const element = safeDocument().getElementById(this.options.domId);
                if (element) {
                    const elRect = element.getBoundingClientRect();
                    return {
                        width: elRect.width * container.retina.pixelRatio,
                        height: elRect.height * container.retina.pixelRatio,
                        mode: exports.PixelMode.precise,
                    };
                }
            }
            return (this.options.size ??
                (() => {
                    const size = new EmitterSize();
                    size.load({
                        height: 0,
                        mode: exports.PixelMode.percent,
                        width: 0,
                    });
                    return size;
                })());
        }
        #destroy() {
            this.#mutationObserver?.disconnect();
            this.#mutationObserver = undefined;
            this.#resizeObserver?.disconnect();
            this.#resizeObserver = undefined;
            this.#removeCallback(this);
            this.#container.dispatchEvent("emitterDestroyed", {
                emitter: this,
            });
        }
        #emit() {
            if (this.#paused) {
                return;
            }
            const quantity = getRangeValue(this.options.rate.quantity);
            this.#emitParticles(quantity);
        }
        #emitParticles(quantity) {
            const singleParticlesOptions = (itemFromSingleOrMultiple(this.#particlesOptions) ??
                {}), fillHslAnimation = this.options.spawn.fill?.color?.animation, fillEnabled = this.options.spawn.fill?.enable ?? !!this.options.spawn.fill?.color, fillOpacity = this.options.spawn.fill?.opacity === undefined
                ? defaultOpacity$3
                : getRangeValue(this.options.spawn.fill.opacity), strokeHslAnimation = this.options.spawn.stroke?.color?.animation, strokeOpacity = this.options.spawn.stroke?.opacity === undefined
                ? defaultOpacity$3
                : getRangeValue(this.options.spawn.stroke.opacity), strokeWidth = this.options.spawn.stroke?.width === undefined
                ? defaultStrokeWidth
                : getRangeValue(this.options.spawn.stroke.width), reduceFactor = this.#container.retina.reduceFactor, needsFillColorAnimation = !!fillHslAnimation, needsStrokeColorAnimation = !!strokeHslAnimation, needsShapeData = !!this.#shape, needsColorAnimation = needsFillColorAnimation || needsStrokeColorAnimation, needsCopy = needsColorAnimation || needsShapeData, maxValues = needsColorAnimation ? { h: hMax, s: sMax, l: lMax } : null, shapeOptions = this.options.shape;
            for (let i = 0; i < quantity * reduceFactor; i++) {
                const particlesOptions = needsCopy
                    ? deepExtend({}, singleParticlesOptions)
                    : singleParticlesOptions;
                this.spawnFillOpacity = fillOpacity;
                this.spawnFillEnabled = fillEnabled;
                this.spawnStrokeOpacity = strokeOpacity;
                this.spawnStrokeWidth = strokeWidth;
                if (this.spawnFillColor) {
                    if (fillHslAnimation && maxValues) {
                        this.spawnFillColor.h = this.#setColorAnimation(fillHslAnimation.h, this.spawnFillColor.h, maxValues.h, colorFactor);
                        this.spawnFillColor.s = this.#setColorAnimation(fillHslAnimation.s, this.spawnFillColor.s, maxValues.s);
                        this.spawnFillColor.l = this.#setColorAnimation(fillHslAnimation.l, this.spawnFillColor.l, maxValues.l);
                    }
                    setParticlesOptionsFillColor(particlesOptions, this.spawnFillColor, this.spawnFillOpacity, this.spawnFillEnabled);
                }
                if (this.spawnStrokeColor) {
                    if (strokeHslAnimation && maxValues) {
                        this.spawnStrokeColor.h = this.#setColorAnimation(strokeHslAnimation.h, this.spawnStrokeColor.h, maxValues.h, colorFactor);
                        this.spawnStrokeColor.s = this.#setColorAnimation(strokeHslAnimation.s, this.spawnStrokeColor.s, maxValues.s);
                        this.spawnStrokeColor.l = this.#setColorAnimation(strokeHslAnimation.l, this.spawnStrokeColor.l, maxValues.l);
                    }
                    setParticlesOptionsStrokeColor(particlesOptions, this.spawnStrokeColor, this.spawnStrokeOpacity, this.spawnStrokeWidth);
                }
                let position = this.position;
                if (this.#shape) {
                    const shapePosData = this.#shape.randomPosition();
                    if (shapePosData) {
                        position = shapePosData.position;
                        const replaceData = shapeOptions.replace;
                        if (replaceData.color && shapePosData.color) {
                            setParticlesOptionsFillColor(particlesOptions, shapePosData.color, replaceData.opacity ? (shapePosData.opacity ?? defaultOpacity$3) : defaultOpacity$3, true);
                        }
                    }
                    else {
                        position = null;
                    }
                }
                if (position) {
                    this.#container.particles.addParticle(position, particlesOptions);
                }
            }
        }
        #prepareToDie() {
            if (this.#paused) {
                return;
            }
            const duration = this.options.life.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
            if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
                this.#duration = duration * millisecondsToSeconds$1;
            }
        }
        #setColorAnimation(animation, initValue, maxValue, factor = defaultColorAnimationFactor) {
            const container = this.#container;
            if (!animation.enable) {
                return initValue;
            }
            const colorOffset = randomInRangeValue(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = container.retina.reduceFactor
                ? (delay * millisecondsToSeconds$1) / container.retina.reduceFactor
                : Infinity, colorSpeed = getRangeValue(animation.speed);
            return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
        }
    }

    var EmitterInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        EmitterInstance: EmitterInstance
    });

    const absorbFactor = 0.033, minOrbitLength = 0, minRadius = 0, minMass = 0, minAngle = 0, maxAngle = doublePI, maxDegreeAngle = 360, angleIncrementFactor = identity$3 / maxDegreeAngle, defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultLifeCount = -1;
    class AbsorberInstance {
        color;
        limit;
        mass;
        name;
        opacity;
        options;
        position;
        size;
        #container;
        #currentDuration;
        #currentSpawnDelay;
        #duration;
        #firstSpawn;
        #immortal;
        #initialPosition;
        #lifeCount;
        #pluginManager;
        #spawnDelay;
        constructor(pluginManager, container, options, position) {
            this.#container = container;
            this.#pluginManager = pluginManager;
            this.#currentDuration = 0;
            this.#currentSpawnDelay = 0;
            this.#initialPosition = position ? Vector.create(position.x, position.y) : undefined;
            if (options instanceof Absorber) {
                this.options = options;
            }
            else {
                this.options = new Absorber();
                this.options.load(options);
            }
            this.name = this.options.name;
            this.opacity = this.options.opacity;
            this.size = getRangeValue(this.options.size.value) * container.retina.pixelRatio;
            this.mass = this.size * this.options.size.density * container.retina.reduceFactor;
            const limit = this.options.size.limit;
            this.limit = {
                radius: limit.radius * container.retina.pixelRatio * container.retina.reduceFactor,
                mass: limit.mass,
            };
            this.color = rangeColorToRgb(this.#pluginManager, this.options.color) ?? {
                b: 0,
                g: 0,
                r: 0,
            };
            this.position = this.#initialPosition?.copy() ?? this.#calcPosition();
            this.#firstSpawn = !this.options.life.wait;
            this.#lifeCount = this.options.life.count ?? defaultLifeCount;
            this.#immortal = this.#lifeCount <= minLifeCount;
            this.#spawnDelay = container.retina.reduceFactor
                ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds$1) /
                    container.retina.reduceFactor
                : Infinity;
        }
        attract(particle, delta) {
            const container = this.#container, options = this.options, pos = particle.getPosition(), { dx, dy, distance } = getDistances(this.position, pos), v = Vector.create(dx, dy);
            v.length = (this.mass / Math.pow(distance, squareExp)) * container.retina.reduceFactor;
            if (distance < this.size + particle.getRadius()) {
                const sizeFactor = particle.getRadius() * absorbFactor * container.retina.pixelRatio * delta.factor;
                if ((this.size > particle.getRadius() && distance < this.size - particle.getRadius()) ||
                    (particle.absorberOrbit !== undefined && particle.absorberOrbit.length < minOrbitLength)) {
                    if (options.destroy) {
                        particle.destroy();
                    }
                    else {
                        particle.needsNewPosition = true;
                        this.#updateParticlePosition(particle, delta, v);
                    }
                }
                else {
                    if (options.destroy) {
                        particle.size.value -= sizeFactor;
                    }
                    this.#updateParticlePosition(particle, delta, v);
                }
                if (this.limit.radius <= minRadius || this.size < this.limit.radius) {
                    this.size += sizeFactor;
                }
                if (this.limit.mass <= minMass || this.mass < this.limit.mass) {
                    this.mass += sizeFactor * this.options.size.density * container.retina.reduceFactor;
                }
            }
            else {
                this.#updateParticlePosition(particle, delta, v);
            }
        }
        draw(context) {
            context.translate(this.position.x, this.position.y);
            context.beginPath();
            context.arc(originPoint.x, originPoint.y, this.size, minAngle, maxAngle, false);
            context.closePath();
            context.fillStyle = getStyleFromRgb(this.color, this.#container.hdr, this.opacity, this.#container.peakNits, this.#container.hdrMode);
            context.fill();
        }
        resize() {
            const initialPosition = this.#initialPosition;
            this.position =
                initialPosition && isPointInside(initialPosition, this.#container.canvas.size, Vector.origin)
                    ? initialPosition
                    : this.#calcPosition();
        }
        update(delta) {
            if (this.#firstSpawn) {
                this.#firstSpawn = false;
                this.#currentSpawnDelay = this.#spawnDelay ?? defaultSpawnDelay;
            }
            if (this.#duration !== undefined) {
                this.#currentDuration += delta.value;
                if (this.#currentDuration >= this.#duration) {
                    if (!this.#immortal) {
                        this.#lifeCount--;
                    }
                    if (this.#lifeCount > minLifeCount || this.#immortal) {
                        this.position = this.#calcPosition();
                        this.#spawnDelay = this.#container.retina.reduceFactor
                            ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds$1) /
                                this.#container.retina.reduceFactor
                            : Infinity;
                    }
                    this.#currentDuration -= this.#duration;
                    this.#duration = undefined;
                }
            }
            if (this.#spawnDelay !== undefined) {
                this.#currentSpawnDelay += delta.value;
                if (this.#currentSpawnDelay >= this.#spawnDelay) {
                    this.#play();
                    this.#currentSpawnDelay -= this.#spawnDelay;
                    this.#spawnDelay = undefined;
                }
            }
        }
        #calcPosition() {
            const exactPosition = calcPositionOrRandomFromSizeRanged({
                size: this.#container.canvas.size,
                position: this.options.position,
            });
            return Vector.create(exactPosition.x, exactPosition.y);
        }
        #play() {
            if (!((this.#lifeCount > minLifeCount || this.#immortal || !this.options.life.count) &&
                (this.#firstSpawn || this.#currentSpawnDelay >= (this.#spawnDelay ?? defaultSpawnDelay)))) {
                return;
            }
            if (this.#lifeCount > minLifeCount || this.#immortal) {
                this.#prepareToDie();
            }
        }
        #prepareToDie() {
            const duration = this.options.life.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined, minDuration = 0;
            if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
                this.#duration = duration * millisecondsToSeconds$1;
            }
        }
        #updateParticlePosition(particle, delta, v) {
            if (particle.destroyed) {
                return;
            }
            const container = this.#container, canvasSize = container.canvas.size;
            if (particle.needsNewPosition) {
                const newPosition = calcPositionOrRandomFromSize({ size: canvasSize });
                particle.position.setTo(newPosition);
                particle.velocity.setTo(particle.initialVelocity);
                particle.absorberOrbit = undefined;
                particle.needsNewPosition = false;
            }
            if (this.options.orbits) {
                if (particle.absorberOrbit === undefined) {
                    particle.absorberOrbit = Vector.origin;
                    particle.absorberOrbit.length = getDistance(particle.getPosition(), this.position);
                    particle.absorberOrbit.angle = getRandom() * maxAngle;
                }
                if (particle.absorberOrbit.length <= this.size && !this.options.destroy) {
                    const minSize = Math.min(canvasSize.width, canvasSize.height), offset = 1, randomOffset = 0.1, randomFactor = 0.2;
                    particle.absorberOrbit.length = minSize * (offset + (getRandom() * randomFactor - randomOffset));
                }
                particle.absorberOrbitDirection ??=
                    particle.velocity.x >= minVelocity ? exports.RotateDirection.clockwise : exports.RotateDirection.counterClockwise;
                const orbitRadius = particle.absorberOrbit.length, orbitAngle = particle.absorberOrbit.angle, orbitDirection = particle.absorberOrbitDirection;
                particle.velocity.setTo(Vector.origin);
                const maxSize = particle.size.max, sizeFactor = particle.options.move.size ? particle.getRadius() / maxSize : identity$3, deltaFactor = delta.factor || identity$3, baseSpeed = particle.retina.moveSpeed, moveSpeed = baseSpeed * sizeFactor * deltaFactor * half$2;
                particle.position.x = this.position.x + orbitRadius * Math.cos(orbitAngle);
                particle.position.y =
                    this.position.y +
                        orbitRadius * (orbitDirection === exports.RotateDirection.clockwise ? identity$3 : -identity$3) * Math.sin(orbitAngle);
                particle.absorberOrbit.length = Math.max(minOrbitLength, particle.absorberOrbit.length - v.length);
                particle.absorberOrbit.angle += moveSpeed * angleIncrementFactor * container.retina.reduceFactor;
            }
            else {
                particle.velocity.addTo(v);
            }
        }
    }

    var AbsorberInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        AbsorberInstance: AbsorberInstance
    });

    class PoissonDisc {
        active;
        cellSize;
        cols;
        dimensions;
        firstPoint;
        grid;
        points;
        radius;
        retries;
        rows;
        size;
        constructor(size, radius, retries, dimensions, firstPoint) {
            this.size = { ...size };
            this.radius = radius;
            this.retries = retries;
            this.dimensions = dimensions;
            this.cellSize = Math.floor(this.radius / Math.sqrt(this.dimensions));
            this.cols = Math.floor(this.size.width / this.cellSize);
            this.rows = Math.floor(this.size.height / this.cellSize);
            this.points = [];
            this.active = [];
            this.grid = [];
            this.firstPoint = firstPoint ? { ...firstPoint } : undefined;
            this.reset();
        }
        addPoint(inputPoint) {
            const point = {
                position: { ...inputPoint },
                gridPosition: {
                    x: Math.floor(inputPoint.x / this.cellSize),
                    y: Math.floor(inputPoint.y / this.cellSize),
                },
            }, pointIndex = this.points.length, row = this.grid[point.gridPosition.y];
            if (!row) {
                return;
            }
            this.points.push(point);
            row[point.gridPosition.x] = pointIndex;
            this.active.push(pointIndex);
        }
        getRandom(min, max) {
            return Math.floor(getRandom() * (max - min)) + min;
        }
        initialiseGrid() {
            for (let y = 0; y <= this.rows; y++) {
                this.grid[y] = [];
                const row = this.grid[y];
                if (!row) {
                    continue;
                }
                for (let x = 0; x <= this.cols; x++) {
                    row[x] = -1;
                }
            }
        }
        reset() {
            this.points = [];
            this.active = [];
            this.grid = [];
            this.initialiseGrid();
            if (this.firstPoint) {
                this.addPoint(this.firstPoint);
            }
            else {
                const minCoordinate = 0;
                this.addPoint({
                    x: this.getRandom(minCoordinate, this.size.width),
                    y: this.getRandom(minCoordinate, this.size.height),
                });
            }
        }
        async run() {
            this.reset();
            const minCount = 0, step = 1, yieldEvery = 100, yieldStepModule = 0;
            let iterations = 0;
            while (this.active.length > minCount) {
                this.steps(step);
                if (++iterations % yieldEvery === yieldStepModule) {
                    await new Promise(resolve => setTimeout(resolve));
                }
            }
        }
        steps(steps) {
            const minCount = 0;
            for (let i = 0; i < steps; i++) {
                if (this.active.length <= minCount) {
                    continue;
                }
                this.#step();
            }
        }
        #getNewPoint(currentPoint, tries) {
            const minCoordinate = 0, gridMinValue = 0, maxNeighbourIndex = 1, newAngle = tries * (doublePI / this.retries), newDist = this.getRandom(this.radius, this.radius * double), offset = {
                x: Math.cos(newAngle) * newDist,
                y: Math.sin(newAngle) * newDist,
            }, newPoint = {
                x: Math.floor(currentPoint.position.x + offset.x),
                y: Math.floor(currentPoint.position.y + offset.y),
            }, newGridCoords = {
                x: Math.floor(newPoint.x / this.cellSize),
                y: Math.floor(newPoint.y / this.cellSize),
            };
            if (newPoint.x <= minCoordinate ||
                newPoint.x >= this.size.width ||
                newPoint.y <= minCoordinate ||
                newPoint.y >= this.size.height) {
                return;
            }
            const row = this.grid[newGridCoords.y];
            if (!row) {
                return;
            }
            const cellValue = row[newGridCoords.x];
            if (cellValue === undefined) {
                return;
            }
            if (cellValue >= gridMinValue) {
                return;
            }
            for (let i = -1; i <= maxNeighbourIndex; i++) {
                for (let j = -1; j <= maxNeighbourIndex; j++) {
                    if (!i && !j) {
                        continue;
                    }
                    const neighbourGrid = {
                        x: newGridCoords.x + j,
                        y: newGridCoords.y + i,
                    };
                    if (neighbourGrid.x < minCoordinate ||
                        neighbourGrid.y < minCoordinate ||
                        neighbourGrid.x >= this.cols ||
                        neighbourGrid.y >= this.rows) {
                        continue;
                    }
                    const neighbourCellValue = this.grid[neighbourGrid.y]?.[neighbourGrid.x];
                    if (neighbourCellValue === undefined || neighbourCellValue < gridMinValue) {
                        continue;
                    }
                    const neighbour = this.points[neighbourCellValue];
                    if (!neighbour) {
                        continue;
                    }
                    if (getDistance(newPoint, neighbour.position) < this.radius) {
                        return;
                    }
                }
            }
            return newPoint;
        }
        #step() {
            const minCount = 0, randomActive = this.getRandom(minCount, this.active.length);
            let foundNewPoint = false;
            for (let tries = 0; tries < this.retries; tries++) {
                const randomActivePointIndex = this.active[randomActive];
                if (randomActivePointIndex === undefined) {
                    continue;
                }
                const point = this.points[randomActivePointIndex];
                if (!point) {
                    continue;
                }
                const newPoint = this.#getNewPoint(point, tries);
                if (newPoint) {
                    foundNewPoint = true;
                    this.addPoint(newPoint);
                    break;
                }
            }
            if (!foundNewPoint) {
                const deleteCount = 1;
                this.active.splice(randomActive, deleteCount);
            }
        }
    }

    var PoissonDisc$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        PoissonDisc: PoissonDisc
    });

    exports.AnimatableColor = AnimatableColor;
    exports.AnimationOptions = AnimationOptions;
    exports.AnimationValueWithRandom = AnimationValueWithRandom;
    exports.Background = Background;
    exports.BaseRange = BaseRange;
    exports.Circle = Circle;
    exports.ColorAnimation = ColorAnimation;
    exports.Fill = Fill;
    exports.FullScreen = FullScreen;
    exports.HDROptions = HDROptions;
    exports.HslAnimation = HslAnimation;
    exports.Move = Move;
    exports.MoveAngle = MoveAngle;
    exports.MoveCenter = MoveCenter;
    exports.MoveGravity = MoveGravity;
    exports.MovePath = MovePath;
    exports.OptionLoader = OptionLoader;
    exports.Options = Options;
    exports.OptionsColor = OptionsColor;
    exports.OutModes = OutModes;
    exports.Paint = Paint;
    exports.ParticlesBounce = ParticlesBounce;
    exports.ParticlesBounceFactor = ParticlesBounceFactor;
    exports.ParticlesDensity = ParticlesDensity;
    exports.ParticlesNumber = ParticlesNumber;
    exports.ParticlesNumberLimit = ParticlesNumberLimit;
    exports.ParticlesOptions = ParticlesOptions;
    exports.RangedAnimationOptions = RangedAnimationOptions;
    exports.RangedAnimationValueWithRandom = RangedAnimationValueWithRandom;
    exports.Rectangle = Rectangle;
    exports.ResizeEvent = ResizeEvent;
    exports.Shape = Shape;
    exports.Spin = Spin;
    exports.Stroke = Stroke;
    exports.ValueWithRandom = ValueWithRandom;
    exports.Vector = Vector;
    exports.Vector3d = Vector3d;
    exports.ZIndex = ZIndex;
    exports.alterHsl = alterHsl;
    exports.animate = animate;
    exports.areBoundsInside = areBoundsInside;
    exports.calcExactPositionOrRandomFromSize = calcExactPositionOrRandomFromSize;
    exports.calcPositionFromSize = calcPositionFromSize;
    exports.calcPositionOrRandomFromSize = calcPositionOrRandomFromSize;
    exports.calcPositionOrRandomFromSizeRanged = calcPositionOrRandomFromSizeRanged;
    exports.calculateBounds = calculateBounds;
    exports.cancelAnimation = cancelAnimation;
    exports.canvasFirstIndex = canvasFirstIndex;
    exports.canvasTag = canvasTag;
    exports.checkDistance = checkDistance;
    exports.circleBounce = circleBounce;
    exports.circleBounceDataFromParticle = circleBounceDataFromParticle;
    exports.clamp = clamp;
    exports.cloneStyle = cloneStyle;
    exports.collisionVelocity = collisionVelocity;
    exports.colorMix = colorMix;
    exports.colorToRgb = colorToRgb;
    exports.countOffset = countOffset;
    exports.decayOffset = decayOffset;
    exports.deepExtend = deepExtend;
    exports.defaultAlpha = defaultAlpha$1;
    exports.defaultAngle = defaultAngle$1;
    exports.defaultCompositeValue = defaultCompositeValue;
    exports.defaultDensityFactor = defaultDensityFactor;
    exports.defaultFps = defaultFps;
    exports.defaultFpsLimit = defaultFpsLimit;
    exports.defaultLoops = defaultLoops;
    exports.defaultOpacity = defaultOpacity$3;
    exports.defaultRatio = defaultRatio$1;
    exports.defaultReduceFactor = defaultReduceFactor;
    exports.defaultRemoveQuantity = defaultRemoveQuantity;
    exports.defaultRetryCount = defaultRetryCount;
    exports.defaultRgbMin = defaultRgbMin;
    exports.defaultTime = defaultTime;
    exports.defaultTransform = defaultTransform$1;
    exports.defaultTransformValue = defaultTransformValue;
    exports.defaultVelocity = defaultVelocity;
    exports.defaultZoom = defaultZoom;
    exports.degToRad = degToRad;
    exports.deleteCount = deleteCount;
    exports.double = double;
    exports.doublePI = doublePI;
    exports.empty = empty$1;
    exports.executeOnSingleOrMultiple = executeOnSingleOrMultiple;
    exports.generatedAttribute = generatedAttribute;
    exports.generatedFalse = generatedFalse;
    exports.generatedTrue = generatedTrue;
    exports.getDistance = getDistance;
    exports.getDistanceSq = getDistanceSq;
    exports.getDistances = getDistances;
    exports.getFullScreenStyle = getFullScreenStyle;
    exports.getHslAnimationFromHsl = getHslAnimationFromHsl;
    exports.getHslFromAnimation = getHslFromAnimation;
    exports.getItemMapFromInitializer = getItemMapFromInitializer;
    exports.getItemsFromInitializer = getItemsFromInitializer;
    exports.getLinkColor = getLinkColor;
    exports.getLinkRandomColor = getLinkRandomColor;
    exports.getLogger = getLogger;
    exports.getParticleBaseVelocity = getParticleBaseVelocity;
    exports.getParticleDirectionAngle = getParticleDirectionAngle;
    exports.getPosition = getPosition;
    exports.getRandom = getRandom;
    exports.getRandomFn = getRandomFn;
    exports.getRandomInRange = getRandomInRange;
    exports.getRandomRgbColor = getRandomRgbColor;
    exports.getRangeMax = getRangeMax;
    exports.getRangeMin = getRangeMin;
    exports.getRangeValue = getRangeValue;
    exports.getStyleFromHsl = getStyleFromHsl;
    exports.getStyleFromRgb = getStyleFromRgb;
    exports.hMax = hMax;
    exports.hMin = hMin;
    exports.hPhase = hPhase;
    exports.half = half$2;
    exports.hslToRgb = hslToRgb;
    exports.hslToRgbFloat = hslToRgbFloat;
    exports.hslaToRgba = hslaToRgba;
    exports.identity = identity$3;
    exports.inverseFactorNumerator = inverseFactorNumerator;
    exports.isArray = isArray;
    exports.isBoolean = isBoolean;
    exports.isFunction = isFunction;
    exports.isInArray = isInArray;
    exports.isNull = isNull;
    exports.isNumber = isNumber;
    exports.isObject = isObject;
    exports.isPointInside = isPointInside;
    exports.isString = isString;
    exports.itemFromArray = itemFromArray;
    exports.itemFromSingleOrMultiple = itemFromSingleOrMultiple;
    exports.lFactor = lFactor;
    exports.lMax = lMax;
    exports.lMin = lMin;
    exports.lengthOffset = lengthOffset;
    exports.loadAll = loadAll;
    exports.loadExtendProperty = loadExtendProperty;
    exports.loadLazyProperty = loadLazyProperty;
    exports.loadMinIndex = loadMinIndex;
    exports.loadNestedProperty = loadNestedProperty;
    exports.loadOptionProperty = loadOptionProperty;
    exports.loadOptions = loadOptions;
    exports.loadParticlesOptions = loadParticlesOptions;
    exports.loadProperty = loadProperty;
    exports.loadRandomFactor = loadRandomFactor;
    exports.loadRangeProperty = loadRangeProperty;
    exports.manageListener = manageListener;
    exports.maxNits = maxNits;
    exports.midColorValue = midColorValue;
    exports.millisecondsToSeconds = millisecondsToSeconds$1;
    exports.minCount = minCount;
    exports.minDistance = minDistance$7;
    exports.minFpsLimit = minFpsLimit;
    exports.minIndex = minIndex$1;
    exports.minLimit = minLimit;
    exports.minRadius = minRadius$8;
    exports.minStrokeWidth = minStrokeWidth;
    exports.minVelocity = minVelocity;
    exports.minZ = minZ;
    exports.minimumSize = minimumSize;
    exports.mix = mix;
    exports.none = none;
    exports.one = one;
    exports.originPoint = originPoint;
    exports.parseAlpha = parseAlpha;
    exports.percentDenominator = percentDenominator;
    exports.phaseNumerator = phaseNumerator;
    exports.quarter = quarter$2;
    exports.randomColorValue = randomColorValue;
    exports.randomInRangeValue = randomInRangeValue;
    exports.rangeColorToHsl = rangeColorToHsl;
    exports.rangeColorToRgb = rangeColorToRgb;
    exports.removeDeleteCount = removeDeleteCount;
    exports.removeMinIndex = removeMinIndex;
    exports.resizeEvent = resizeEvent;
    exports.rgbMax = rgbMax;
    exports.rgbToHsl = rgbToHsl;
    exports.sMax = sMax;
    exports.sMin = sMin;
    exports.sNormalizedOffset = sNormalizedOffset;
    exports.safeDocument = safeDocument;
    exports.safeMatchMedia = safeMatchMedia;
    exports.safeMutationObserver = safeMutationObserver;
    exports.setAnimationFunctions = setAnimationFunctions;
    exports.setLogger = setLogger;
    exports.setRandom = setRandom;
    exports.setRangeValue = setRangeValue;
    exports.sextuple = sextuple;
    exports.spatialHashGridCellSize = spatialHashGridCellSize;
    exports.squareExp = squareExp;
    exports.stringToAlpha = stringToAlpha;
    exports.stringToRgb = stringToRgb;
    exports.threeQuarter = threeQuarter;
    exports.triple = triple;
    exports.tryCountIncrement = tryCountIncrement;
    exports.tsParticles = tsParticles;
    exports.updateColor = updateColor;
    exports.updateColorValue = updateColorValue;
    exports.visibilityChangeEvent = visibilityChangeEvent;
    exports.zIndexFactorOffset = zIndexFactorOffset;

}));
Object.assign(globalThis.window || globalThis, { loadAll: (globalThis.__tsParticlesInternals.bundles.all || {}).loadAll, loadExtendProperty: (globalThis.__tsParticlesInternals.bundles.all || {}).loadExtendProperty, loadLazyProperty: (globalThis.__tsParticlesInternals.bundles.all || {}).loadLazyProperty, loadMinIndex: (globalThis.__tsParticlesInternals.bundles.all || {}).loadMinIndex, loadNestedProperty: (globalThis.__tsParticlesInternals.bundles.all || {}).loadNestedProperty, loadOptionProperty: (globalThis.__tsParticlesInternals.bundles.all || {}).loadOptionProperty, loadOptions: (globalThis.__tsParticlesInternals.bundles.all || {}).loadOptions, loadParticlesOptions: (globalThis.__tsParticlesInternals.bundles.all || {}).loadParticlesOptions, loadProperty: (globalThis.__tsParticlesInternals.bundles.all || {}).loadProperty, loadRandomFactor: (globalThis.__tsParticlesInternals.bundles.all || {}).loadRandomFactor, loadRangeProperty: (globalThis.__tsParticlesInternals.bundles.all || {}).loadRangeProperty, tsParticles: (globalThis.__tsParticlesInternals.bundles.all || {}).tsParticles });
globalThis.__tsParticlesInternals = globalThis.__tsParticlesInternals || {};
if (!globalThis.__tsParticlesInternals.engine || !globalThis.__tsParticlesInternals.engine.tsParticles) {
  globalThis.__tsParticlesInternals.engine = globalThis.__tsParticlesInternals.bundles.all || {};
}
delete (globalThis.window || globalThis).tsparticlesInternalExports;