UNPKG

@tsparticles/engine

Version:

Easily create highly customizable particle, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.

4,995 lines 200 kB
(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 Engine 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.engine = global.__tsParticlesInternals.engine || {})));
})(this, (function (exports) { 'use strict';

    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;
    }

    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 = {}));

    const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
        x: 0,
        y: 0,
        z: 0,
    }, defaultTransform = {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
    }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius$1 = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity = 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 = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity = 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;

    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 = 180, degToRadFactor = Math.PI / piDeg;
    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;
            case exports.MoveDirection.topRight:
                return -Math.PI * quarter;
            case exports.MoveDirection.right:
                return empty;
            case exports.MoveDirection.bottomRight:
                return Math.PI * quarter;
            case exports.MoveDirection.bottom:
                return Math.PI * half;
            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 = 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), 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) {
                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 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,
            s: sMin,
        };
        if (max !== min) {
            res.s = res.l < half ? (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
            ? 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
            ? 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, 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, 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).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).toString()})`;
    }
    function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
        const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity, 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;
            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 globalObject = globalThis;
    globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
    globalObject.tsParticles = tsParticles;
    globalObject.getParticlesLogger = getLogger;
    globalObject.setParticlesLogger = setLogger;
    globalObject.getParticlesRandom = getRandom;
    globalObject.getParticlesRandomFn = getRandomFn;
    globalObject.setParticlesRandom = setRandom;

    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) / pxRatio,
                y: (height * half) / 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);
        }
        #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 ? 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,
            opacity: defaultOpacity,
            strokeOpacity: defaultOpacity,
        };
        #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);
        }
        getFillColor() {
            return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
        }
        getMass() {
            return this.getRadius() ** squareExp * Math.PI * half;
        }
        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), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity, strokeOpacity = this.strokeOpacity ?? defaultOpacity;
            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.a);
            this.#cachedTransform.b = rotating
                ? rotateData.sin * (externalTransform.b ?? identity)
                : (externalTransform.b ?? defaultTransform.b);
            this.#cachedTransform.c = rotating
                ? -rotateData.sin * (externalTransform.c ?? identity)
                : (externalTransform.c ?? defaultTransform.c);
            this.#cachedTransform.d = rotateData.cos * (externalTransform.d ?? defaultTransform.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 && adjustedAngle < Math.PI * triple * half;
            }
            if (this.roll.horizontal) {
                const adjustedAngle = normalizeAngle(angle + Math.PI * half, 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) {
                this.#modifiers.splice(idx, identity);
            }
        }
        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,
                right: radOffset + rad * half,
            };
            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 : position.x + radius > defaultAngle,
                    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 : position.y + radius > defaultAngle,
                    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, effectResult.margin ?? defaultAngle);
                return {
                    inside: shapeResult.inside && effectResult.inside,
                    margin: margin > defaultAngle ? 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; 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 || 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, 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) {
                return minIndex;
            }
            return Math.min(Math.max(Math.floor(zIndex), minIndex), 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) {
                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;
            }
        }
        #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) {
                    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;
            this.reduceFactor = defaultReduceFactor;
        }
        init() {
            const container = this.#container, options = container.actualOptions;
            this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
            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;
    }
    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;
            this.#delay = getRangeValue(delay) * millisecondsToSeconds;
            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 / 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) {
                    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
    });

    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;
    exports.defaultAngle = defaultAngle;
    exports.defaultCompositeValue = defaultCompositeValue;
    exports.defaultDensityFactor = defaultDensityFactor;
    exports.defaultFps = defaultFps;
    exports.defaultFpsLimit = defaultFpsLimit;
    exports.defaultLoops = defaultLoops;
    exports.defaultOpacity = defaultOpacity;
    exports.defaultRatio = defaultRatio;
    exports.defaultReduceFactor = defaultReduceFactor;
    exports.defaultRemoveQuantity = defaultRemoveQuantity;
    exports.defaultRetryCount = defaultRetryCount;
    exports.defaultRgbMin = defaultRgbMin;
    exports.defaultTime = defaultTime;
    exports.defaultTransform = defaultTransform;
    exports.defaultTransformValue = defaultTransformValue;
    exports.defaultVelocity = defaultVelocity;
    exports.defaultZoom = defaultZoom;
    exports.degToRad = degToRad;
    exports.deleteCount = deleteCount;
    exports.double = double;
    exports.doublePI = doublePI;
    exports.empty = empty;
    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;
    exports.hslToRgb = hslToRgb;
    exports.hslToRgbFloat = hslToRgbFloat;
    exports.hslaToRgba = hslaToRgba;
    exports.identity = identity;
    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.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;
    exports.minCount = minCount;
    exports.minDistance = minDistance;
    exports.minFpsLimit = minFpsLimit;
    exports.minIndex = minIndex;
    exports.minLimit = minLimit;
    exports.minRadius = minRadius$1;
    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;
    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, { tsParticles: (globalThis.__tsParticlesInternals.engine || {}).tsParticles });
delete (globalThis.window || globalThis).tsparticlesInternalExports;