UNPKG

wave-roll

Version:

JavaScript Library for Comparative MIDI Piano-Roll Visualization

48,702 lines 1.67 MB
var dt = /* @__PURE__ */ ((n) => (n.Application = "application", n.WebGLPipes = "webgl-pipes", n.WebGLPipesAdaptor = "webgl-pipes-adaptor", n.WebGLSystem = "webgl-system", n.WebGPUPipes = "webgpu-pipes", n.WebGPUPipesAdaptor = "webgpu-pipes-adaptor", n.WebGPUSystem = "webgpu-system", n.CanvasSystem = "canvas-system", n.CanvasPipesAdaptor = "canvas-pipes-adaptor", n.CanvasPipes = "canvas-pipes", n.Asset = "asset", n.LoadParser = "load-parser", n.ResolveParser = "resolve-parser", n.CacheParser = "cache-parser", n.DetectionParser = "detection-parser", n.MaskEffect = "mask-effect", n.BlendMode = "blend-mode", n.TextureSource = "texture-source", n.Environment = "environment", n.ShapeBuilder = "shape-builder", n.Batcher = "batcher", n))(dt || {});
const il = (n) => {
  if (typeof n == "function" || typeof n == "object" && n.extension) {
    if (!n.extension)
      throw new Error("Extension class must have an extension object");
    n = { ...typeof n.extension != "object" ? { type: n.extension } : n.extension, ref: n };
  }
  if (typeof n == "object")
    n = { ...n };
  else
    throw new Error("Invalid extension type");
  return typeof n.type == "string" && (n.type = [n.type]), n;
}, Nr = (n, t) => il(n).priority ?? t, ze = {
  /** @ignore */
  _addHandlers: {},
  /** @ignore */
  _removeHandlers: {},
  /** @ignore */
  _queue: {},
  /**
   * Remove extensions from PixiJS.
   * @param extensions - Extensions to be removed. Can be:
   * - Extension class with static `extension` property
   * - Extension format object with `type` and `ref`
   * - Multiple extensions as separate arguments
   * @returns {extensions} this for chaining
   * @example
   * ```ts
   * // Remove a single extension
   * extensions.remove(MyRendererPlugin);
   *
   * // Remove multiple extensions
   * extensions.remove(
   *     MyRendererPlugin,
   *     MySystemPlugin
   * );
   * ```
   * @see {@link ExtensionType} For available extension types
   * @see {@link ExtensionFormat} For extension format details
   */
  remove(...n) {
    return n.map(il).forEach((t) => {
      t.type.forEach((e) => this._removeHandlers[e]?.(t));
    }), this;
  },
  /**
   * Register new extensions with PixiJS. Extensions can be registered in multiple formats:
   * - As a class with a static `extension` property
   * - As an extension format object
   * - As multiple extensions passed as separate arguments
   * @param extensions - Extensions to add to PixiJS. Each can be:
   * - A class with static `extension` property
   * - An extension format object with `type` and `ref`
   * - Multiple extensions as separate arguments
   * @returns This extensions instance for chaining
   * @example
   * ```ts
   * // Register a simple extension
   * extensions.add(MyRendererPlugin);
   *
   * // Register multiple extensions
   * extensions.add(
   *     MyRendererPlugin,
   *     MySystemPlugin,
   * });
   * ```
   * @see {@link ExtensionType} For available extension types
   * @see {@link ExtensionFormat} For extension format details
   * @see {@link extensions.remove} For removing registered extensions
   */
  add(...n) {
    return n.map(il).forEach((t) => {
      t.type.forEach((e) => {
        const s = this._addHandlers, i = this._queue;
        s[e] ? s[e]?.(t) : (i[e] = i[e] || [], i[e]?.push(t));
      });
    }), this;
  },
  /**
   * Internal method to handle extensions by name.
   * @param type - The extension type.
   * @param onAdd  - Function handler when extensions are added/registered {@link StrictExtensionFormat}.
   * @param onRemove  - Function handler when extensions are removed/unregistered {@link StrictExtensionFormat}.
   * @returns this for chaining.
   * @internal
   * @ignore
   */
  handle(n, t, e) {
    const s = this._addHandlers, i = this._removeHandlers;
    if (s[n] || i[n])
      throw new Error(`Extension type ${n} already has a handler`);
    s[n] = t, i[n] = e;
    const r = this._queue;
    return r[n] && (r[n]?.forEach((o) => t(o)), delete r[n]), this;
  },
  /**
   * Handle a type, but using a map by `name` property.
   * @param type - Type of extension to handle.
   * @param map - The object map of named extensions.
   * @returns this for chaining.
   * @ignore
   */
  handleByMap(n, t) {
    return this.handle(
      n,
      (e) => {
        e.name && (t[e.name] = e.ref);
      },
      (e) => {
        e.name && delete t[e.name];
      }
    );
  },
  /**
   * Handle a type, but using a list of extensions with a `name` property.
   * @param type - Type of extension to handle.
   * @param map - The array of named extensions.
   * @param defaultPriority - Fallback priority if none is defined.
   * @returns this for chaining.
   * @ignore
   */
  handleByNamedList(n, t, e = -1) {
    return this.handle(
      n,
      (s) => {
        t.findIndex((r) => r.name === s.name) >= 0 || (t.push({ name: s.name, value: s.ref }), t.sort((r, o) => Nr(o.value, e) - Nr(r.value, e)));
      },
      (s) => {
        const i = t.findIndex((r) => r.name === s.name);
        i !== -1 && t.splice(i, 1);
      }
    );
  },
  /**
   * Handle a type, but using a list of extensions.
   * @param type - Type of extension to handle.
   * @param list - The list of extensions.
   * @param defaultPriority - The default priority to use if none is specified.
   * @returns this for chaining.
   * @ignore
   */
  handleByList(n, t, e = -1) {
    return this.handle(
      n,
      (s) => {
        t.includes(s.ref) || (t.push(s.ref), t.sort((i, r) => Nr(r, e) - Nr(i, e)));
      },
      (s) => {
        const i = t.indexOf(s.ref);
        i !== -1 && t.splice(i, 1);
      }
    );
  },
  /**
   * Mixin the source object(s) properties into the target class's prototype.
   * Copies all property descriptors from source objects to the target's prototype.
   * @param Target - The target class to mix properties into
   * @param sources - One or more source objects containing properties to mix in
   * @example
   * ```ts
   * // Create a mixin with shared properties
   * const moveable = {
   *     x: 0,
   *     y: 0,
   *     move(x: number, y: number) {
   *         this.x += x;
   *         this.y += y;
   *     }
   * };
   *
   * // Create a mixin with computed properties
   * const scalable = {
   *     scale: 1,
   *     get scaled() {
   *         return this.scale > 1;
   *     }
   * };
   *
   * // Apply mixins to a class
   * extensions.mixin(Sprite, moveable, scalable);
   *
   * // Use mixed-in properties
   * const sprite = new Sprite();
   * sprite.move(10, 20);
   * console.log(sprite.x, sprite.y); // 10, 20
   * ```
   * @remarks
   * - Copies all properties including getters/setters
   * - Does not modify source objects
   * - Preserves property descriptors
   * @see {@link Object.defineProperties} For details on property descriptors
   * @see {@link Object.getOwnPropertyDescriptors} For details on property copying
   */
  mixin(n, ...t) {
    for (const e of t)
      Object.defineProperties(n.prototype, Object.getOwnPropertyDescriptors(e));
  }
}, $g = {
  extension: {
    type: dt.Environment,
    name: "browser",
    priority: -1
  },
  test: () => !0,
  load: async () => {
    await import("./browserAll-BKWnA4I2.js");
  }
}, Hg = {
  extension: {
    type: dt.Environment,
    name: "webworker",
    priority: 0
  },
  test: () => typeof self < "u" && self.WorkerGlobalScope !== void 0,
  load: async () => {
    await import("./webworkerAll-DZS3CPgm.js");
  }
};
class Pt {
  /**
   * Creates a new `ObservablePoint`
   * @param observer - Observer to pass to listen for change events.
   * @param {number} [x=0] - position of the point on the x axis
   * @param {number} [y=0] - position of the point on the y axis
   */
  constructor(t, e, s) {
    this._x = e || 0, this._y = s || 0, this._observer = t;
  }
  /**
   * Creates a clone of this point.
   * @example
   * ```ts
   * // Basic cloning
   * const point = new ObservablePoint(observer, 100, 200);
   * const copy = point.clone();
   *
   * // Clone with new observer
   * const newObserver = {
   *     _onUpdate: (p) => console.log(`Clone updated: (${p.x}, ${p.y})`)
   * };
   * const watched = point.clone(newObserver);
   *
   * // Verify independence
   * watched.set(300, 400); // Only triggers new observer
   * ```
   * @param observer - Optional observer to pass to the new observable point
   * @returns A copy of this observable point
   * @see {@link ObservablePoint.copyFrom} For copying into existing point
   * @see {@link Observer} For observer interface details
   */
  clone(t) {
    return new Pt(t ?? this._observer, this._x, this._y);
  }
  /**
   * Sets the point to a new x and y position.
   *
   * If y is omitted, both x and y will be set to x.
   * @example
   * ```ts
   * // Basic position setting
   * const point = new ObservablePoint(observer);
   * point.set(100, 200);
   *
   * // Set both x and y to same value
   * point.set(50); // x=50, y=50
   * ```
   * @param x - Position on the x axis
   * @param y - Position on the y axis, defaults to x
   * @returns The point instance itself
   * @see {@link ObservablePoint.copyFrom} For copying from another point
   * @see {@link ObservablePoint.equals} For comparing positions
   */
  set(t = 0, e = t) {
    return (this._x !== t || this._y !== e) && (this._x = t, this._y = e, this._observer._onUpdate(this)), this;
  }
  /**
   * Copies x and y from the given point into this point.
   * @example
   * ```ts
   * // Basic copying
   * const source = new ObservablePoint(observer, 100, 200);
   * const target = new ObservablePoint();
   * target.copyFrom(source);
   *
   * // Copy and chain operations
   * const point = new ObservablePoint()
   *     .copyFrom(source)
   *     .set(x + 50, y + 50);
   *
   * // Copy from any PointData
   * const data = { x: 10, y: 20 };
   * point.copyFrom(data);
   * ```
   * @param p - The point to copy from
   * @returns The point instance itself
   * @see {@link ObservablePoint.copyTo} For copying to another point
   * @see {@link ObservablePoint.clone} For creating new point copy
   */
  copyFrom(t) {
    return (this._x !== t.x || this._y !== t.y) && (this._x = t.x, this._y = t.y, this._observer._onUpdate(this)), this;
  }
  /**
   * Copies this point's x and y into the given point.
   * @example
   * ```ts
   * // Basic copying
   * const source = new ObservablePoint(100, 200);
   * const target = new ObservablePoint();
   * source.copyTo(target);
   * ```
   * @param p - The point to copy to. Can be any type that is or extends `PointLike`
   * @returns The point (`p`) with values updated
   * @see {@link ObservablePoint.copyFrom} For copying from another point
   * @see {@link ObservablePoint.clone} For creating new point copy
   */
  copyTo(t) {
    return t.set(this._x, this._y), t;
  }
  /**
   * Checks if another point is equal to this point.
   *
   * Compares x and y values using strict equality.
   * @example
   * ```ts
   * // Basic equality check
   * const p1 = new ObservablePoint(100, 200);
   * const p2 = new ObservablePoint(100, 200);
   * console.log(p1.equals(p2)); // true
   *
   * // Compare with PointData
   * const data = { x: 100, y: 200 };
   * console.log(p1.equals(data)); // true
   *
   * // Check different points
   * const p3 = new ObservablePoint(200, 300);
   * console.log(p1.equals(p3)); // false
   * ```
   * @param p - The point to check
   * @returns `true` if both `x` and `y` are equal
   * @see {@link ObservablePoint.copyFrom} For making points equal
   * @see {@link PointData} For point data interface
   */
  equals(t) {
    return t.x === this._x && t.y === this._y;
  }
  toString() {
    return `[pixi.js/math:ObservablePoint x=${this._x} y=${this._y} scope=${this._observer}]`;
  }
  /**
   * Position of the observable point on the x axis.
   * Triggers observer callback when value changes.
   * @example
   * ```ts
   * // Basic x position
   * const point = new ObservablePoint(observer);
   * point.x = 100; // Triggers observer
   *
   * // Use in calculations
   * const width = rightPoint.x - leftPoint.x;
   * ```
   * @default 0
   */
  get x() {
    return this._x;
  }
  set x(t) {
    this._x !== t && (this._x = t, this._observer._onUpdate(this));
  }
  /**
   * Position of the observable point on the y axis.
   * Triggers observer callback when value changes.
   * @example
   * ```ts
   * // Basic y position
   * const point = new ObservablePoint(observer);
   * point.y = 200; // Triggers observer
   *
   * // Use in calculations
   * const height = bottomPoint.y - topPoint.y;
   * ```
   * @default 0
   */
  get y() {
    return this._y;
  }
  set y(t) {
    this._y !== t && (this._y = t, this._observer._onUpdate(this));
  }
}
function Af(n) {
  return n && n.__esModule && Object.prototype.hasOwnProperty.call(n, "default") ? n.default : n;
}
function jg(n) {
  if (Object.prototype.hasOwnProperty.call(n, "__esModule")) return n;
  var t = n.default;
  if (typeof t == "function") {
    var e = function s() {
      var i = !1;
      try {
        i = this instanceof s;
      } catch {
      }
      return i ? Reflect.construct(t, arguments, this.constructor) : t.apply(this, arguments);
    };
    e.prototype = t.prototype;
  } else e = {};
  return Object.defineProperty(e, "__esModule", { value: !0 }), Object.keys(n).forEach(function(s) {
    var i = Object.getOwnPropertyDescriptor(n, s);
    Object.defineProperty(e, s, i.get ? i : {
      enumerable: !0,
      get: function() {
        return n[s];
      }
    });
  }), e;
}
var xa = { exports: {} }, Lh;
function Xg() {
  return Lh || (Lh = 1, function(n) {
    var t = Object.prototype.hasOwnProperty, e = "~";
    function s() {
    }
    Object.create && (s.prototype = /* @__PURE__ */ Object.create(null), new s().__proto__ || (e = !1));
    function i(l, c, h) {
      this.fn = l, this.context = c, this.once = h || !1;
    }
    function r(l, c, h, u, d) {
      if (typeof h != "function")
        throw new TypeError("The listener must be a function");
      var f = new i(h, u || l, d), p = e ? e + c : c;
      return l._events[p] ? l._events[p].fn ? l._events[p] = [l._events[p], f] : l._events[p].push(f) : (l._events[p] = f, l._eventsCount++), l;
    }
    function o(l, c) {
      --l._eventsCount === 0 ? l._events = new s() : delete l._events[c];
    }
    function a() {
      this._events = new s(), this._eventsCount = 0;
    }
    a.prototype.eventNames = function() {
      var c = [], h, u;
      if (this._eventsCount === 0) return c;
      for (u in h = this._events)
        t.call(h, u) && c.push(e ? u.slice(1) : u);
      return Object.getOwnPropertySymbols ? c.concat(Object.getOwnPropertySymbols(h)) : c;
    }, a.prototype.listeners = function(c) {
      var h = e ? e + c : c, u = this._events[h];
      if (!u) return [];
      if (u.fn) return [u.fn];
      for (var d = 0, f = u.length, p = new Array(f); d < f; d++)
        p[d] = u[d].fn;
      return p;
    }, a.prototype.listenerCount = function(c) {
      var h = e ? e + c : c, u = this._events[h];
      return u ? u.fn ? 1 : u.length : 0;
    }, a.prototype.emit = function(c, h, u, d, f, p) {
      var g = e ? e + c : c;
      if (!this._events[g]) return !1;
      var m = this._events[g], y = arguments.length, x, v;
      if (m.fn) {
        switch (m.once && this.removeListener(c, m.fn, void 0, !0), y) {
          case 1:
            return m.fn.call(m.context), !0;
          case 2:
            return m.fn.call(m.context, h), !0;
          case 3:
            return m.fn.call(m.context, h, u), !0;
          case 4:
            return m.fn.call(m.context, h, u, d), !0;
          case 5:
            return m.fn.call(m.context, h, u, d, f), !0;
          case 6:
            return m.fn.call(m.context, h, u, d, f, p), !0;
        }
        for (v = 1, x = new Array(y - 1); v < y; v++)
          x[v - 1] = arguments[v];
        m.fn.apply(m.context, x);
      } else {
        var _ = m.length, b;
        for (v = 0; v < _; v++)
          switch (m[v].once && this.removeListener(c, m[v].fn, void 0, !0), y) {
            case 1:
              m[v].fn.call(m[v].context);
              break;
            case 2:
              m[v].fn.call(m[v].context, h);
              break;
            case 3:
              m[v].fn.call(m[v].context, h, u);
              break;
            case 4:
              m[v].fn.call(m[v].context, h, u, d);
              break;
            default:
              if (!x) for (b = 1, x = new Array(y - 1); b < y; b++)
                x[b - 1] = arguments[b];
              m[v].fn.apply(m[v].context, x);
          }
      }
      return !0;
    }, a.prototype.on = function(c, h, u) {
      return r(this, c, h, u, !1);
    }, a.prototype.once = function(c, h, u) {
      return r(this, c, h, u, !0);
    }, a.prototype.removeListener = function(c, h, u, d) {
      var f = e ? e + c : c;
      if (!this._events[f]) return this;
      if (!h)
        return o(this, f), this;
      var p = this._events[f];
      if (p.fn)
        p.fn === h && (!d || p.once) && (!u || p.context === u) && o(this, f);
      else {
        for (var g = 0, m = [], y = p.length; g < y; g++)
          (p[g].fn !== h || d && !p[g].once || u && p[g].context !== u) && m.push(p[g]);
        m.length ? this._events[f] = m.length === 1 ? m[0] : m : o(this, f);
      }
      return this;
    }, a.prototype.removeAllListeners = function(c) {
      var h;
      return c ? (h = e ? e + c : c, this._events[h] && o(this, h)) : (this._events = new s(), this._eventsCount = 0), this;
    }, a.prototype.off = a.prototype.removeListener, a.prototype.addListener = a.prototype.on, a.prefixed = e, a.EventEmitter = a, n.exports = a;
  }(xa)), xa.exports;
}
var Yg = Xg();
const ps = /* @__PURE__ */ Af(Yg), Zg = Math.PI * 2, Kg = 180 / Math.PI, Qg = Math.PI / 180;
class se {
  /**
   * Creates a new `Point`
   * @param {number} [x=0] - position of the point on the x axis
   * @param {number} [y=0] - position of the point on the y axis
   */
  constructor(t = 0, e = 0) {
    this.x = 0, this.y = 0, this.x = t, this.y = e;
  }
  /**
   * Creates a clone of this point, which is a new instance with the same `x` and `y` values.
   * @example
   * ```ts
   * // Basic point cloning
   * const original = new Point(100, 200);
   * const copy = original.clone();
   *
   * // Clone and modify
   * const modified = original.clone();
   * modified.set(300, 400);
   *
   * // Verify independence
   * console.log(original); // Point(100, 200)
   * console.log(modified); // Point(300, 400)
   * ```
   * @remarks
   * - Creates new Point instance
   * - Deep copies x and y values
   * - Independent from original
   * - Useful for preserving values
   * @returns A clone of this point
   * @see {@link Point.copyFrom} For copying into existing point
   * @see {@link Point.copyTo} For copying to existing point
   */
  clone() {
    return new se(this.x, this.y);
  }
  /**
   * Copies x and y from the given point into this point.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Point(100, 200);
   * const target = new Point();
   * target.copyFrom(source);
   *
   * // Copy and chain operations
   * const point = new Point()
   *     .copyFrom(source)
   *     .set(x + 50, y + 50);
   *
   * // Copy from any PointData
   * const data = { x: 10, y: 20 };
   * point.copyFrom(data);
   * ```
   * @param p - The point to copy from
   * @returns The point instance itself
   * @see {@link Point.copyTo} For copying to another point
   * @see {@link Point.clone} For creating new point copy
   */
  copyFrom(t) {
    return this.set(t.x, t.y), this;
  }
  /**
   * Copies this point's x and y into the given point.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Point(100, 200);
   * const target = new Point();
   * source.copyTo(target);
   * ```
   * @param p - The point to copy to. Can be any type that is or extends `PointLike`
   * @returns The point (`p`) with values updated
   * @see {@link Point.copyFrom} For copying from another point
   * @see {@link Point.clone} For creating new point copy
   */
  copyTo(t) {
    return t.set(this.x, this.y), t;
  }
  /**
   * Checks if another point is equal to this point.
   *
   * Compares x and y values using strict equality.
   * @example
   * ```ts
   * // Basic equality check
   * const p1 = new Point(100, 200);
   * const p2 = new Point(100, 200);
   * console.log(p1.equals(p2)); // true
   *
   * // Compare with PointData
   * const data = { x: 100, y: 200 };
   * console.log(p1.equals(data)); // true
   *
   * // Check different points
   * const p3 = new Point(200, 300);
   * console.log(p1.equals(p3)); // false
   * ```
   * @param p - The point to check
   * @returns `true` if both `x` and `y` are equal
   * @see {@link Point.copyFrom} For making points equal
   * @see {@link PointData} For point data interface
   */
  equals(t) {
    return t.x === this.x && t.y === this.y;
  }
  /**
   * Sets the point to a new x and y position.
   *
   * If y is omitted, both x and y will be set to x.
   * @example
   * ```ts
   * // Basic position setting
   * const point = new Point();
   * point.set(100, 200);
   *
   * // Set both x and y to same value
   * point.set(50); // x=50, y=50
   *
   * // Chain with other operations
   * point
   *     .set(10, 20)
   *     .copyTo(otherPoint);
   * ```
   * @param x - Position on the x axis
   * @param y - Position on the y axis, defaults to x
   * @returns The point instance itself
   * @see {@link Point.copyFrom} For copying from another point
   * @see {@link Point.equals} For comparing positions
   */
  set(t = 0, e = t) {
    return this.x = t, this.y = e, this;
  }
  toString() {
    return `[pixi.js/math:Point x=${this.x} y=${this.y}]`;
  }
  /**
   * A static Point object with `x` and `y` values of `0`.
   *
   * This shared instance is reset to zero values when accessed.
   *
   * > [!IMPORTANT] This point is shared and temporary. Do not store references to it.
   * @example
   * ```ts
   * // Use for temporary calculations
   * const tempPoint = Point.shared;
   * tempPoint.set(100, 200);
   * matrix.apply(tempPoint);
   *
   * // Will be reset to (0,0) on next access
   * const fresh = Point.shared; // x=0, y=0
   * ```
   * @readonly
   * @returns A fresh zeroed point for temporary use
   * @see {@link Point.constructor} For creating new points
   * @see {@link PointData} For basic point interface
   */
  static get shared() {
    return _a.x = 0, _a.y = 0, _a;
  }
}
const _a = new se();
class nt {
  /**
   * @param a - x scale
   * @param b - y skew
   * @param c - x skew
   * @param d - y scale
   * @param tx - x translation
   * @param ty - y translation
   */
  constructor(t = 1, e = 0, s = 0, i = 1, r = 0, o = 0) {
    this.array = null, this.a = t, this.b = e, this.c = s, this.d = i, this.tx = r, this.ty = o;
  }
  /**
   * Creates a Matrix object based on the given array.
   * Populates matrix components from a flat array in column-major order.
   *
   * > [!NOTE] Array mapping order:
   * > ```
   * > array[0] = a  (x scale)
   * > array[1] = b  (y skew)
   * > array[2] = tx (x translation)
   * > array[3] = c  (x skew)
   * > array[4] = d  (y scale)
   * > array[5] = ty (y translation)
   * > ```
   * @example
   * ```ts
   * // Create matrix from array
   * const matrix = new Matrix();
   * matrix.fromArray([
   *     2, 0,  100,  // a, b, tx
   *     0, 2,  100   // c, d, ty
   * ]);
   *
   * // Create matrix from typed array
   * const float32Array = new Float32Array([
   *     1, 0, 0,     // Scale x1, no skew
   *     0, 1, 0      // No skew, scale x1
   * ]);
   * matrix.fromArray(float32Array);
   * ```
   * @param array - The array to populate the matrix from
   * @see {@link Matrix.toArray} For converting matrix to array
   * @see {@link Matrix.set} For setting values directly
   */
  fromArray(t) {
    this.a = t[0], this.b = t[1], this.c = t[3], this.d = t[4], this.tx = t[2], this.ty = t[5];
  }
  /**
   * Sets the matrix properties directly.
   * All matrix components can be set in one call.
   * @example
   * ```ts
   * // Set to identity matrix
   * matrix.set(1, 0, 0, 1, 0, 0);
   *
   * // Set to scale matrix
   * matrix.set(2, 0, 0, 2, 0, 0); // Scale 2x
   *
   * // Set to translation matrix
   * matrix.set(1, 0, 0, 1, 100, 50); // Move 100,50
   * ```
   * @param a - Scale on x axis
   * @param b - Shear on y axis
   * @param c - Shear on x axis
   * @param d - Scale on y axis
   * @param tx - Translation on x axis
   * @param ty - Translation on y axis
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.identity} For resetting to identity
   * @see {@link Matrix.fromArray} For setting from array
   */
  set(t, e, s, i, r, o) {
    return this.a = t, this.b = e, this.c = s, this.d = i, this.tx = r, this.ty = o, this;
  }
  /**
   * Creates an array from the current Matrix object.
   *
   * > [!NOTE] The array format is:
   * > ```
   * > Non-transposed:
   * > [a, c, tx,
   * > b, d, ty,
   * > 0, 0, 1]
   * >
   * > Transposed:
   * > [a, b, 0,
   * > c, d, 0,
   * > tx,ty,1]
   * > ```
   * @example
   * ```ts
   * // Basic array conversion
   * const matrix = new Matrix(2, 0, 0, 2, 100, 100);
   * const array = matrix.toArray();
   *
   * // Using existing array
   * const float32Array = new Float32Array(9);
   * matrix.toArray(false, float32Array);
   *
   * // Get transposed array
   * const transposed = matrix.toArray(true);
   * ```
   * @param transpose - Whether to transpose the matrix
   * @param out - Optional Float32Array to store the result
   * @returns The array containing the matrix values
   * @see {@link Matrix.fromArray} For creating matrix from array
   * @see {@link Matrix.array} For cached array storage
   */
  toArray(t, e) {
    this.array || (this.array = new Float32Array(9));
    const s = e || this.array;
    return t ? (s[0] = this.a, s[1] = this.b, s[2] = 0, s[3] = this.c, s[4] = this.d, s[5] = 0, s[6] = this.tx, s[7] = this.ty, s[8] = 1) : (s[0] = this.a, s[1] = this.c, s[2] = this.tx, s[3] = this.b, s[4] = this.d, s[5] = this.ty, s[6] = 0, s[7] = 0, s[8] = 1), s;
  }
  /**
   * Get a new position with the current transformation applied.
   *
   * Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering)
   * @example
   * ```ts
   * // Basic point transformation
   * const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4);
   * const point = new Point(10, 20);
   * const transformed = matrix.apply(point);
   *
   * // Reuse existing point
   * const output = new Point();
   * matrix.apply(point, output);
   * ```
   * @param pos - The origin point to transform
   * @param newPos - Optional point to store the result
   * @returns The transformed point
   * @see {@link Matrix.applyInverse} For inverse transformation
   * @see {@link Point} For point operations
   */
  apply(t, e) {
    e = e || new se();
    const s = t.x, i = t.y;
    return e.x = this.a * s + this.c * i + this.tx, e.y = this.b * s + this.d * i + this.ty, e;
  }
  /**
   * Get a new position with the inverse of the current transformation applied.
   *
   * Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input)
   * @example
   * ```ts
   * // Basic inverse transformation
   * const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4);
   * const worldPoint = new Point(150, 100);
   * const localPoint = matrix.applyInverse(worldPoint);
   *
   * // Reuse existing point
   * const output = new Point();
   * matrix.applyInverse(worldPoint, output);
   *
   * // Convert mouse position to local space
   * const mousePoint = new Point(mouseX, mouseY);
   * const localMouse = matrix.applyInverse(mousePoint);
   * ```
   * @param pos - The origin point to inverse-transform
   * @param newPos - Optional point to store the result
   * @returns The inverse-transformed point
   * @see {@link Matrix.apply} For forward transformation
   * @see {@link Matrix.invert} For getting inverse matrix
   */
  applyInverse(t, e) {
    e = e || new se();
    const s = this.a, i = this.b, r = this.c, o = this.d, a = this.tx, l = this.ty, c = 1 / (s * o + r * -i), h = t.x, u = t.y;
    return e.x = o * c * h + -r * c * u + (l * r - a * o) * c, e.y = s * c * u + -i * c * h + (-l * s + a * i) * c, e;
  }
  /**
   * Translates the matrix on the x and y axes.
   * Adds to the position values while preserving scale, rotation and skew.
   * @example
   * ```ts
   * // Basic translation
   * const matrix = new Matrix();
   * matrix.translate(100, 50); // Move right 100, down 50
   *
   * // Chain with other transformations
   * matrix
   *     .scale(2, 2)
   *     .translate(100, 0)
   *     .rotate(Math.PI / 4);
   * ```
   * @param x - How much to translate on the x axis
   * @param y - How much to translate on the y axis
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.set} For setting position directly
   * @see {@link Matrix.setTransform} For complete transform setup
   */
  translate(t, e) {
    return this.tx += t, this.ty += e, this;
  }
  /**
   * Applies a scale transformation to the matrix.
   * Multiplies the scale values with existing matrix components.
   * @example
   * ```ts
   * // Basic scaling
   * const matrix = new Matrix();
   * matrix.scale(2, 3); // Scale 2x horizontally, 3x vertically
   *
   * // Chain with other transformations
   * matrix
   *     .translate(100, 100)
   *     .scale(2, 2)     // Scales after translation
   *     .rotate(Math.PI / 4);
   * ```
   * @param x - The amount to scale horizontally
   * @param y - The amount to scale vertically
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.setTransform} For setting scale directly
   * @see {@link Matrix.append} For combining transformations
   */
  scale(t, e) {
    return this.a *= t, this.d *= e, this.c *= t, this.b *= e, this.tx *= t, this.ty *= e, this;
  }
  /**
   * Applies a rotation transformation to the matrix.
   *
   * Rotates around the origin (0,0) by the given angle in radians.
   * @example
   * ```ts
   * // Basic rotation
   * const matrix = new Matrix();
   * matrix.rotate(Math.PI / 4); // Rotate 45 degrees
   *
   * // Chain with other transformations
   * matrix
   *     .translate(100, 100) // Move to rotation center
   *     .rotate(Math.PI)     // Rotate 180 degrees
   *     .scale(2, 2);        // Scale after rotation
   *
   * // Common angles
   * matrix.rotate(Math.PI / 2);  // 90 degrees
   * matrix.rotate(Math.PI);      // 180 degrees
   * matrix.rotate(Math.PI * 2);  // 360 degrees
   * ```
   * @remarks
   * - Rotates around origin point (0,0)
   * - Affects position if translation was set
   * - Uses counter-clockwise rotation
   * - Order of operations matters when chaining
   * @param angle - The angle in radians
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.setTransform} For setting rotation directly
   * @see {@link Matrix.append} For combining transformations
   */
  rotate(t) {
    const e = Math.cos(t), s = Math.sin(t), i = this.a, r = this.c, o = this.tx;
    return this.a = i * e - this.b * s, this.b = i * s + this.b * e, this.c = r * e - this.d * s, this.d = r * s + this.d * e, this.tx = o * e - this.ty * s, this.ty = o * s + this.ty * e, this;
  }
  /**
   * Appends the given Matrix to this Matrix.
   * Combines two matrices by multiplying them together: this = this * matrix
   * @example
   * ```ts
   * // Basic matrix combination
   * const matrix = new Matrix();
   * const other = new Matrix().translate(100, 0).rotate(Math.PI / 4);
   * matrix.append(other);
   * ```
   * @remarks
   * - Order matters: A.append(B) !== B.append(A)
   * - Modifies current matrix
   * - Preserves transformation order
   * - Commonly used for combining transforms
   * @param matrix - The matrix to append
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.prepend} For prepending transformations
   * @see {@link Matrix.appendFrom} For appending two external matrices
   */
  append(t) {
    const e = this.a, s = this.b, i = this.c, r = this.d;
    return this.a = t.a * e + t.b * i, this.b = t.a * s + t.b * r, this.c = t.c * e + t.d * i, this.d = t.c * s + t.d * r, this.tx = t.tx * e + t.ty * i + this.tx, this.ty = t.tx * s + t.ty * r + this.ty, this;
  }
  /**
   * Appends two matrices and sets the result to this matrix.
   * Performs matrix multiplication: this = A * B
   * @example
   * ```ts
   * // Basic matrix multiplication
   * const result = new Matrix();
   * const matrixA = new Matrix().scale(2, 2);
   * const matrixB = new Matrix().rotate(Math.PI / 4);
   * result.appendFrom(matrixA, matrixB);
   * ```
   * @remarks
   * - Order matters: A * B !== B * A
   * - Creates a new transformation from two others
   * - More efficient than append() for multiple operations
   * - Does not modify input matrices
   * @param a - The first matrix to multiply
   * @param b - The second matrix to multiply
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.append} For single matrix combination
   * @see {@link Matrix.prepend} For reverse order multiplication
   */
  appendFrom(t, e) {
    const s = t.a, i = t.b, r = t.c, o = t.d, a = t.tx, l = t.ty, c = e.a, h = e.b, u = e.c, d = e.d;
    return this.a = s * c + i * u, this.b = s * h + i * d, this.c = r * c + o * u, this.d = r * h + o * d, this.tx = a * c + l * u + e.tx, this.ty = a * h + l * d + e.ty, this;
  }
  /**
   * Sets the matrix based on all the available properties.
   * Combines position, scale, rotation, skew and pivot in a single operation.
   * @example
   * ```ts
   * // Basic transform setup
   * const matrix = new Matrix();
   * matrix.setTransform(
   *     100, 100,    // position
   *     0, 0,        // pivot
   *     2, 2,        // scale
   *     Math.PI / 4, // rotation (45 degrees)
   *     0, 0         // skew
   * );
   * ```
   * @remarks
   * - Updates all matrix components at once
   * - More efficient than separate transform calls
   * - Uses radians for rotation and skew
   * - Pivot affects rotation center
   * @param x - Position on the x axis
   * @param y - Position on the y axis
   * @param pivotX - Pivot on the x axis
   * @param pivotY - Pivot on the y axis
   * @param scaleX - Scale on the x axis
   * @param scaleY - Scale on the y axis
   * @param rotation - Rotation in radians
   * @param skewX - Skew on the x axis
   * @param skewY - Skew on the y axis
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.decompose} For extracting transform properties
   * @see {@link TransformableObject} For transform data structure
   */
  setTransform(t, e, s, i, r, o, a, l, c) {
    return this.a = Math.cos(a + c) * r, this.b = Math.sin(a + c) * r, this.c = -Math.sin(a - l) * o, this.d = Math.cos(a - l) * o, this.tx = t - (s * this.a + i * this.c), this.ty = e - (s * this.b + i * this.d), this;
  }
  /**
   * Prepends the given Matrix to this Matrix.
   * Combines two matrices by multiplying them together: this = matrix * this
   * @example
   * ```ts
   * // Basic matrix prepend
   * const matrix = new Matrix().scale(2, 2);
   * const other = new Matrix().translate(100, 0);
   * matrix.prepend(other); // Translation happens before scaling
   * ```
   * @remarks
   * - Order matters: A.prepend(B) !== B.prepend(A)
   * - Modifies current matrix
   * - Reverses transformation order compared to append()
   * @param matrix - The matrix to prepend
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.append} For appending transformations
   * @see {@link Matrix.appendFrom} For combining external matrices
   */
  prepend(t) {
    const e = this.tx;
    if (t.a !== 1 || t.b !== 0 || t.c !== 0 || t.d !== 1) {
      const s = this.a, i = this.c;
      this.a = s * t.a + this.b * t.c, this.b = s * t.b + this.b * t.d, this.c = i * t.a + this.d * t.c, this.d = i * t.b + this.d * t.d;
    }
    return this.tx = e * t.a + this.ty * t.c + t.tx, this.ty = e * t.b + this.ty * t.d + t.ty, this;
  }
  /**
   * Decomposes the matrix into its individual transform components.
   * Extracts position, scale, rotation and skew values from the matrix.
   * @example
   * ```ts
   * // Basic decomposition
   * const matrix = new Matrix()
   *     .translate(100, 100)
   *     .rotate(Math.PI / 4)
   *     .scale(2, 2);
   *
   * const transform = {
   *     position: new Point(),
   *     scale: new Point(),
   *     pivot: new Point(),
   *     skew: new Point(),
   *     rotation: 0
   * };
   *
   * matrix.decompose(transform);
   * console.log(transform.position); // Point(100, 100)
   * console.log(transform.rotation); // ~0.785 (PI/4)
   * console.log(transform.scale); // Point(2, 2)
   * ```
   * @remarks
   * - Handles combined transformations
   * - Accounts for pivot points
   * - Chooses between rotation/skew based on transform type
   * - Uses radians for rotation and skew
   * @param transform - The transform object to store the decomposed values
   * @returns The transform with the newly applied properties
   * @see {@link Matrix.setTransform} For composing from components
   * @see {@link TransformableObject} For transform structure
   */
  decompose(t) {
    const e = this.a, s = this.b, i = this.c, r = this.d, o = t.pivot, a = -Math.atan2(-i, r), l = Math.atan2(s, e), c = Math.abs(a + l);
    return c < 1e-5 || Math.abs(Zg - c) < 1e-5 ? (t.rotation = l, t.skew.x = t.skew.y = 0) : (t.rotation = 0, t.skew.x = a, t.skew.y = l), t.scale.x = Math.sqrt(e * e + s * s), t.scale.y = Math.sqrt(i * i + r * r), t.position.x = this.tx + (o.x * e + o.y * i), t.position.y = this.ty + (o.x * s + o.y * r), t;
  }
  /**
   * Inverts this matrix.
   * Creates the matrix that when multiplied with this matrix results in an identity matrix.
   * @example
   * ```ts
   * // Basic matrix inversion
   * const matrix = new Matrix()
   *     .translate(100, 50)
   *     .scale(2, 2);
   *
   * matrix.invert(); // Now transforms in opposite direction
   *
   * // Verify inversion
   * const point = new Point(50, 50);
   * const transformed = matrix.apply(point);
   * const original = matrix.invert().apply(transformed);
   * // original ≈ point
   * ```
   * @remarks
   * - Modifies the current matrix
   * - Useful for reversing transformations
   * - Cannot invert matrices with zero determinant
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.identity} For resetting to identity
   * @see {@link Matrix.applyInverse} For inverse transformations
   */
  invert() {
    const t = this.a, e = this.b, s = this.c, i = this.d, r = this.tx, o = t * i - e * s;
    return this.a = i / o, this.b = -e / o, this.c = -s / o, this.d = t / o, this.tx = (s * this.ty - i * r) / o, this.ty = -(t * this.ty - e * r) / o, this;
  }
  /**
   * Checks if this matrix is an identity matrix.
   *
   * An identity matrix has no transformations applied (default state).
   * @example
   * ```ts
   * // Check if matrix is identity
   * const matrix = new Matrix();
   * console.log(matrix.isIdentity()); // true
   *
   * // Check after transformations
   * matrix.translate(100, 0);
   * console.log(matrix.isIdentity()); // false
   *
   * // Reset and verify
   * matrix.identity();
   * console.log(matrix.isIdentity()); // true
   * ```
   * @remarks
   * - Verifies a = 1, d = 1 (no scale)
   * - Verifies b = 0, c = 0 (no skew)
   * - Verifies tx = 0, ty = 0 (no translation)
   * @returns True if matrix has no transformations
   * @see {@link Matrix.identity} For resetting to identity
   * @see {@link Matrix.IDENTITY} For constant identity matrix
   */
  isIdentity() {
    return this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1 && this.tx === 0 && this.ty === 0;
  }
  /**
   * Resets this Matrix to an identity (default) matrix.
   * Sets all components to their default values: scale=1, no skew, no translation.
   * @example
   * ```ts
   * // Reset transformed matrix
   * const matrix = new Matrix()
   *     .scale(2, 2)
   *     .rotate(Math.PI / 4);
   * matrix.identity(); // Back to default state
   *
   * // Chain after reset
   * matrix
   *     .identity()
   *     .translate(100, 100)
   *     .scale(2, 2);
   *
   * // Compare with identity constant
   * const isDefault = matrix.equals(Matrix.IDENTITY);
   * ```
   * @remarks
   * - Sets a=1, d=1 (default scale)
   * - Sets b=0, c=0 (no skew)
   * - Sets tx=0, ty=0 (no translation)
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.IDENTITY} For constant identity matrix
   * @see {@link Matrix.isIdentity} For checking identity state
   */
  identity() {
    return this.a = 1, this.b = 0, this.c = 0, this.d = 1, this.tx = 0, this.ty = 0, this;
  }
  /**
   * Creates a new Matrix object with the same values as this one.
   * @returns A copy of this matrix. Good for chaining method calls.
   */
  clone() {
    const t = new nt();
    return t.a = this.a, t.b = this.b, t.c = this.c, t.d = this.d, t.tx = this.tx, t.ty = this.ty, t;
  }
  /**
   * Creates a new Matrix object with the same values as this one.
   * @param matrix
   * @example
   * ```ts
   * // Basic matrix cloning
   * const matrix = new Matrix()
   *     .translate(100, 100)
   *     .rotate(Math.PI / 4);
   * const copy = matrix.clone();
   *
   * // Clone and modify
   * const modified = matrix.clone()
   *     .scale(2, 2);
   *
   * // Compare matrices
   * console.log(matrix.equals(copy));     // true
   * console.log(matrix.equals(modified)); // false
   * ```
   * @returns A copy of this matrix. Good for chaining method calls.
   * @see {@link Matrix.copyTo} For copying to existing matrix
   * @see {@link Matrix.copyFrom} For copying from another matrix
   */
  copyTo(t) {
    return t.a = this.a, t.b = this.b, t.c = this.c, t.d = this.d, t.tx = this.tx, t.ty = this.ty, t;
  }
  /**
   * Changes the values of the matrix to be the same as the ones in given matrix.
   * @example
   * ```ts
   * // Basic matrix copying
   * const source = new Matrix()
   *     .translate(100, 100)
   *     .rotate(Math.PI / 4);
   * const target = new Matrix();
   * target.copyFrom(source);
   * ```
   * @param matrix - The matrix to copy from
   * @returns This matrix. Good for chaining method calls.
   * @see {@link Matrix.clone} For creating new matrix copy
   * @see {@link Matrix.copyTo} For copying to another matrix
   */
  copyFrom(t) {
    return this.a = t.a, this.b = t.b, this.c = t.c, this.d = t.d, this.tx = t.tx, this.ty = t.ty, this;
  }
  /**
   * Checks if this matrix equals another matrix.
   * Compares all components for exact equality.
   * @example
   * ```ts
   * // Basic equality check
   * const m1 = new Matrix();
   * const m2 = new Matrix();
   * console.log(m1.equals(m2)); // true
   *
   * // Compare transformed matrices
   * const transform = new Matrix()
   *     .translate(100, 100)
   * const clone = new Matrix()
   *     .scale(2, 2);
   * console.log(transform.equals(clone)); // false
   * ```
   * @param matrix - The matrix to compare to
   * @returns True if matrices are identical
   * @see {@link Matrix.copyFrom} For copying matrix values
   * @see {@link Matrix.isIdentity} For identity comparison
   */
  equals(t) {
    return t.a === this.a && t.b === this.b && t.c === this.c && t.d === this.d && t.tx === this.tx && t.ty === this.ty;
  }
  toString() {
    return `[pixi.js:Matrix a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`;
  }
  /**
   * A default (identity) matrix with no transformations applied.
   *
   * > [!IMPORTANT] This is a shared read-only object. Create a new Matrix if you need to modify it.
   * @example
   * ```ts
   * // Get identity matrix reference
   * const identity = Matrix.IDENTITY;
   * console.log(identity.isIdentity()); // true
   *
   * // Compare with identity
   * const matrix = new Matrix();
   * console.log(matrix.equals(Matrix.IDENTITY)); // true
   *
   * // Create new matrix instead of modifying IDENTITY
   * const transform = new Matrix()
   *     .copyFrom(Matrix.IDENTITY)
   *     .translate(100, 100);
   * ```
   * @readonly
   * @returns A read-only identity matrix
   * @see {@link Matrix.shared} For temporary calculations
   * @see {@link Matrix.identity} For resetting matrices
   */
  static get IDENTITY() {
    return ty.identity();
  }
  /**
   * A static Matrix that can be used to avoid creating new objects.
   * Will always ensure the matrix is reset to identity when requested.
   *
   * > [!IMPORTANT] This matrix is shared and temporary. Do not store references to it.
   * @example
   * ```ts
   * // Use for temporary calculations
   * const tempMatrix = Matrix.shared;
   * tempMatrix.translate(100, 100).rotate(Math.PI / 4);
   * const point = tempMatrix.apply({ x: 10, y: 20 });
   *
   * // Will be reset to identity on next access
   * const fresh = Matrix.shared; // Back to identity
   * ```
   * @remarks
   * - Always returns identity matrix
   * - Safe to modify temporarily
   * - Not safe to store references
   * - Useful for one-off calculations
   * @readonly
   * @returns A fresh identity matrix for temporary use
   * @see {@link Matrix.IDENTITY} For immutable identity matrix
   * @see {@link Matrix.identity} For resetting matrices
   */
  static get shared() {
    return Jg.identity();
  }
}
const Jg = new nt(), ty = new nt(), hn = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1], un = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1], dn = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1], fn = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1], rl = [], Ef = [], Lr = Math.sign;
function ey() {
  for (let n = 0; n < 16; n++) {
    const t = [];
    rl.push(t);
    for (let e = 0; e < 16; e++) {
      const s = Lr(hn[n] * hn[e] + dn[n] * un[e]), i = Lr(un[n] * hn[e] + fn[n] * un[e]), r = Lr(hn[n] * dn[e] + dn[n] * fn[e]), o = Lr(un[n] * dn[e] + fn[n] * fn[e]);
      for (let a = 0; a < 16; a++)
        if (hn[a] === s && un[a] === i && dn[a] === r && fn[a] === o) {
          t.push(a);
          break;
        }
    }
  }
  for (let n = 0; n < 16; n++) {
    const t = new nt();
    t.set(hn[n], un[n], dn[n], fn[n], 0, 0), Ef.push(t);
  }
}
ey();
const gt = {
  /**
   * | Rotation | Direction |
   * |----------|-----------|
   * | 0°       | East      |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  E: 0,
  /**
   * | Rotation | Direction |
   * |----------|-----------|
   * | 45°↻     | Southeast |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  SE: 1,
  /**
   * | Rotation | Direction |
   * |----------|-----------|
   * | 90°↻     | South     |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  S: 2,
  /**
   * | Rotation | Direction |
   * |----------|-----------|
   * | 135°↻    | Southwest |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  SW: 3,
  /**
   * | Rotation | Direction |
   * |----------|-----------|
   * | 180°     | West      |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  W: 4,
  /**
   * | Rotation    | Direction    |
   * |-------------|--------------|
   * | -135°/225°↻ | Northwest    |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  NW: 5,
  /**
   * | Rotation    | Direction    |
   * |-------------|--------------|
   * | -90°/270°↻  | North        |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  N: 6,
  /**
   * | Rotation    | Direction    |
   * |-------------|--------------|
   * | -45°/315°↻  | Northeast    |
   * @group groupD8
   * @type {GD8Symmetry}
   */
  NE: 7,
  /**
   * Reflection about Y-axis.
   * @group groupD8
   * @type {GD8Symmetry}
   */
  MIRROR_VERTICAL: 8,
  /**
   * Reflection about the main diagonal.
   * @group groupD8
   * @type {GD8Symmetry}
   */
  MAIN_DIAGONAL: 10,
  /**
   * Reflection about X-axis.
   * @group groupD8
   * @type {GD8Symmetry}
   */
  MIRROR_HORIZONTAL: 12,
  /**
   * Reflection about reverse diagonal.
   * @group groupD8
   * @type {GD8Symmetry}
   */
  REVERSE_DIAGONAL: 14,
  /**
   * @group groupD8
   * @param {GD8Symmetry} ind - sprite rotation angle.
   * @returns {GD8Symmetry} The X-component of the U-axis
   *    after rotating the axes.
   */
  uX: (n) => hn[n],
  /**
   * @group groupD8
   * @param {GD8Symmetry} ind - sprite rotation angle.
   * @returns {GD8Symmetry} The Y-component of the U-axis
   *    after rotating the axes.
   */
  uY: (n) => un[n],
  /**
   * @group groupD8
   * @param {GD8Symmetry} ind - sprite rotation angle.
   * @returns {GD8Symmetry} The X-component of the V-axis
   *    after rotating the axes.
   */
  vX: (n) => dn[n],
  /**
   * @group groupD8
   * @param {GD8Symmetry} ind - sprite rotation angle.
   * @returns {GD8Symmetry} The Y-component of the V-axis
   *    after rotating the axes.
   */
  vY: (n) => fn[n],
  /**
   * @group groupD8
   * @param {GD8Symmetry} rotation - symmetry whose opposite
   *   is needed. Only rotations have opposite symmetries while
   *   reflections don't.
   * @returns {GD8Symmetry} The opposite symmetry of `rotation`
   */
  inv: (n) => n & 8 ? n & 15 : -n & 7,
  /**
   * Composes the two D8 operations.
   *
   * Taking `^` as reflection:
   *
   * |       | E=0 | S=2 | W=4 | N=6 | E^=8 | S^=10 | W^=12 | N^=14 |
   * |-------|-----|-----|-----|-----|------|-------|-------|-------|
   * | E=0   | E   | S   | W   | N   | E^   | S^    | W^    | N^    |
   * | S=2   | S   | W   | N   | E   | S^   | W^    | N^    | E^    |
   * | W=4   | W   | N   | E   | S   | W^   | N^    | E^    | S^    |
   * | N=6   | N   | E   | S   | W   | N^   | E^    | S^    | W^    |
   * | E^=8  | E^  | N^  | W^  | S^  | E    | N     | W     | S     |
   * | S^=10 | S^  | E^  | N^  | W^  | S    | E     | N     | W     |
   * | W^=12 | W^  | S^  | E^  | N^  | W    | S     | E     | N     |
   * | N^=14 | N^  | W^  | S^  | E^  | N    | W     | S     | E     |
   *
   * [This is a Cayley table]{@link https://en.wikipedia.org/wiki/Cayley_table}
   * @group groupD8
   * @param {GD8Symmetry} rotationSecond - Second operation, which
   *   is the row in the above cayley table.
   * @param {GD8Symmetry} rotationFirst - First operation, which
   *   is the column in the above cayley table.
   * @returns {GD8Symmetry} Composed operation
   */
  add: (n, t) => rl[n][t],
  /**
   * Reverse of `add`.
   * @group groupD8
   * @param {GD8Symmetry} rotationSecond - Second operation
   * @param {GD8Symmetry} rotationFirst - First operation
   * @returns {GD8Symmetry} Result
   */
  sub: (n, t) => rl[n][gt.inv(t)],
  /**
   * Adds 180 degrees to rotation, which is a commutative
   * operation.
   * @group groupD8
   * @param {number} rotation - The number to rotate.
   * @returns {number} Rotated number
   */
  rotate180: (n) => n ^ 4,
  /**
   * Checks if the rotation angle is vertical, i.e. south
   * or north. It doesn't work for reflections.
   * @group groupD8
   * @param {GD8Symmetry} rotation - The number to check.
   * @returns {boolean} Whether or not the direction is vertical
   */
  isVertical: (n) => (n & 3) === 2,
  // rotation % 4 === 2
  /**
   * Approximates the vector `V(dx,dy)` into one of the
   * eight directions provided by `groupD8`.
   * @group groupD8
   * @param {number} dx - X-component of the vector
   * @param {number} dy - Y-component of the vector
   * @returns {GD8Symmetry} Approximation of the vector into
   *  one of the eight symmetries.
   */
  byDirection: (n, t) => Math.abs(n) * 2 <= Math.abs(t) ? t >= 0 ? gt.S : gt.N : Math.abs(t) * 2 <= Math.abs(n) ? n > 0 ? gt.E : gt.W : t > 0 ? n > 0 ? gt.SE : gt.SW : n > 0 ? gt.NE : gt.NW,
  /**
   * Helps sprite to compensate texture packer rotation.
   * @group groupD8
   * @param {Matrix} matrix - sprite world matrix
   * @param {GD8Symmetry} rotation - The rotation factor to use.
   * @param {number} tx - sprite anchoring
   * @param {number} ty - sprite anchoring
   */
  matrixAppendRotationInv: (n, t, e = 0, s = 0) => {
    const i = Ef[gt.inv(t)];
    i.tx = e, i.ty = s, n.append(i);
  },
  /**
   * Transforms rectangle coordinates based on texture packer rotation.
   * Used when texture atlas pages are rotated and coordinates need to be adjusted.
   * @group groupD8
   * @param {RectangleLike} rect - Rectangle with original coordinates to transform
   * @param {RectangleLike} sourceFrame - Source texture frame (includes offset and dimensions)
   * @param {GD8Symmetry} rotation - The groupD8 rotation value
   * @param {Rectangle} out - Rectangle to store the result
   * @returns {Rectangle} Transformed coordinates (includes source frame offset)
   */
  transformRectCoords: (n, t, e, s) => {
    const { x: i, y: r, width: o, height: a } = n, { x: l, y: c, width: h, height: u } = t;
    return e === gt.E ? (s.set(i + l, r + c, o, a), s) : e === gt.S ? s.set(
      h - r - a + l,
      i + c,
      a,
      o
    ) : e === gt.W ? s.set(
      h - i - o + l,
      u - r - a + c,
      o,
      a
    ) : e === gt.N ? s.set(
      r + l,
      u - i - o + c,
      a,
      o
    ) : s.set(i + l, r + c, o, a);
  }
}, Vr = [new se(), new se(), new se(), new se()];
class Dt {
  /**
   * @param x - The X coordinate of the upper-left corner of the rectangle
   * @param y - The Y coordinate of the upper-left corner of the rectangle
   * @param width - The overall width of the rectangle
   * @param height - The overall height of the rectangle
   */
  constructor(t = 0, e = 0, s = 0, i = 0) {
    this.type = "rectangle", this.x = Number(t), this.y = Number(e), this.width = Number(s), this.height = Number(i);
  }
  /**
   * Returns the left edge (x-coordinate) of the rectangle.
   * @example
   * ```ts
   * // Get left edge position
   * const rect = new Rectangle(100, 100, 200, 150);
   * console.log(rect.left); // 100
   *
   * // Use in alignment calculations
   * sprite.x = rect.left + padding;
   *
   * // Compare positions
   * if (point.x > rect.left) {
   *     console.log('Point is right of rectangle');
   * }
   * ```
   * @readonly
   * @returns The x-coordinate of the left edge
   * @see {@link Rectangle.right} For right edge position
   * @see {@link Rectangle.x} For direct x-coordinate access
   */
  get left() {
    return this.x;
  }
  /**
   * Returns the right edge (x + width) of the rectangle.
   * @example
   * ```ts
   * // Get right edge position
   * const rect = new Rectangle(100, 100, 200, 150);
   * console.log(rect.right); // 300
   *
   * // Align to right edge
   * sprite.x = rect.right - sprite.width;
   *
   * // Check boundaries
   * if (point.x < rect.right) {
   *     console.log('Point is inside right bound');
   * }
   * ```
   * @readonly
   * @returns The x-coordinate of the right edge
   * @see {@link Rectangle.left} For left edge position
   * @see {@link Rectangle.width} For width value
   */
  get right() {
    return this.x + this.width;
  }
  /**
   * Returns the top edge (y-coordinate) of the rectangle.
   * @example
   * ```ts
   * // Get top edge position
   * const rect = new Rectangle(100, 100, 200, 150);
   * console.log(rect.top); // 100
   *
   * // Position above rectangle
   * sprite.y = rect.top - sprite.height;
   *
   * // Check vertical position
   * if (point.y > rect.top) {
   *     console.log('Point is below top edge');
   * }
   * ```
   * @readonly
   * @returns The y-coordinate of the top edge
   * @see {@link Rectangle.bottom} For bottom edge position
   * @see {@link Rectangle.y} For direct y-coordinate access
   */
  get top() {
    return this.y;
  }
  /**
   * Returns the bottom edge (y + height) of the rectangle.
   * @example
   * ```ts
   * // Get bottom edge position
   * const rect = new Rectangle(100, 100, 200, 150);
   * console.log(rect.bottom); // 250
   *
   * // Stack below rectangle
   * sprite.y = rect.bottom + margin;
   *
   * // Check vertical bounds
   * if (point.y < rect.bottom) {
   *     console.log('Point is above bottom edge');
   * }
   * ```
   * @readonly
   * @returns The y-coordinate of the bottom edge
   * @see {@link Rectangle.top} For top edge position
   * @see {@link Rectangle.height} For height value
   */
  get bottom() {
    return this.y + this.height;
  }
  /**
   * Determines whether the Rectangle is empty (has no area).
   * @example
   * ```ts
   * // Check zero dimensions
   * const rect = new Rectangle(100, 100, 0, 50);
   * console.log(rect.isEmpty()); // true
   * ```
   * @returns True if the rectangle has no area
   * @see {@link Rectangle.width} For width value
   * @see {@link Rectangle.height} For height value
   */
  isEmpty() {
    return this.left === this.right || this.top === this.bottom;
  }
  /**
   * A constant empty rectangle. This is a new object every time the property is accessed.
   * @example
   * ```ts
   * // Get fresh empty rectangle
   * const empty = Rectangle.EMPTY;
   * console.log(empty.isEmpty()); // true
   * ```
   * @returns A new empty rectangle instance
   * @see {@link Rectangle.isEmpty} For empty state testing
   */
  static get EMPTY() {
    return new Dt(0, 0, 0, 0);
  }
  /**
   * Creates a clone of this Rectangle
   * @example
   * ```ts
   * // Basic cloning
   * const original = new Rectangle(100, 100, 200, 150);
   * const copy = original.clone();
   *
   * // Clone and modify
   * const modified = original.clone();
   * modified.width *= 2;
   * modified.height += 50;
   *
   * // Verify independence
   * console.log(original.width);  // 200
   * console.log(modified.width);  // 400
   * ```
   * @returns A copy of the rectangle
   * @see {@link Rectangle.copyFrom} For copying into existing rectangle
   * @see {@link Rectangle.copyTo} For copying to another rectangle
   */
  clone() {
    return new Dt(this.x, this.y, this.width, this.height);
  }
  /**
   * Converts a Bounds object to a Rectangle object.
   * @example
   * ```ts
   * // Convert bounds to rectangle
   * const bounds = container.getBounds();
   * const rect = new Rectangle().copyFromBounds(bounds);
   * ```
   * @param bounds - The bounds to copy and convert to a rectangle
   * @returns Returns itself
   * @see {@link Bounds} For bounds object structure
   * @see {@link Rectangle.getBounds} For getting rectangle bounds
   */
  copyFromBounds(t) {
    return this.x = t.minX, this.y = t.minY, this.width = t.maxX - t.minX, this.height = t.maxY - t.minY, this;
  }
  /**
   * Copies another rectangle to this one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Rectangle(100, 100, 200, 150);
   * const target = new Rectangle();
   * target.copyFrom(source);
   *
   * // Chain with other operations
   * const rect = new Rectangle()
   *     .copyFrom(source)
   *     .pad(10);
   * ```
   * @param rectangle - The rectangle to copy from
   * @returns Returns itself
   * @see {@link Rectangle.copyTo} For copying to another rectangle
   * @see {@link Rectangle.clone} For creating new rectangle copy
   */
  copyFrom(t) {
    return this.x = t.x, this.y = t.y, this.width = t.width, this.height = t.height, this;
  }
  /**
   * Copies this rectangle to another one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Rectangle(100, 100, 200, 150);
   * const target = new Rectangle();
   * source.copyTo(target);
   *
   * // Chain with other operations
   * const result = source
   *     .copyTo(new Rectangle())
   *     .getBounds();
   * ```
   * @param rectangle - The rectangle to copy to
   * @returns Returns given parameter
   * @see {@link Rectangle.copyFrom} For copying from another rectangle
   * @see {@link Rectangle.clone} For creating new rectangle copy
   */
  copyTo(t) {
    return t.copyFrom(this), t;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this Rectangle
   * @example
   * ```ts
   * // Basic containment check
   * const rect = new Rectangle(100, 100, 200, 150);
   * const isInside = rect.contains(150, 125); // true
   * // Check edge cases
   * console.log(rect.contains(100, 100)); // true (on edge)
   * console.log(rect.contains(300, 250)); // false (outside)
   * ```
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @returns Whether the x/y coordinates are within this Rectangle
   * @see {@link Rectangle.containsRect} For rectangle containment
   * @see {@link Rectangle.strokeContains} For checking stroke intersection
   */
  contains(t, e) {
    return this.width <= 0 || this.height <= 0 ? !1 : t >= this.x && t < this.x + this.width && e >= this.y && e < this.y + this.height;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
   * @example
   * ```ts
   * // Basic stroke check
   * const rect = new Rectangle(100, 100, 200, 150);
   * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width
   *
   * // Check with different alignments
   * const innerStroke = rect.strokeContains(150, 100, 4, 1);   // Inside
   * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered
   * const outerStroke = rect.strokeContains(150, 100, 4, 0);   // Outside
   * ```
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @param strokeWidth - The width of the line to check
   * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
   * @returns Whether the x/y coordinates are within this rectangle's stroke
   * @see {@link Rectangle.contains} For checking fill containment
   * @see {@link Rectangle.getBounds} For getting stroke bounds
   */
  strokeContains(t, e, s, i = 0.5) {
    const { width: r, height: o } = this;
    if (r <= 0 || o <= 0)
      return !1;
    const a = this.x, l = this.y, c = s * (1 - i), h = s - c, u = a - c, d = a + r + c, f = l - c, p = l + o + c, g = a + h, m = a + r - h, y = l + h, x = l + o - h;
    return t >= u && t <= d && e >= f && e <= p && !(t > g && t < m && e > y && e < x);
  }
  /**
   * Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object.
   * Returns true only if the area of the intersection is >0, this means that Rectangles
   * sharing a side are not overlapping. Another side effect is that an arealess rectangle
   * (width or height equal to zero) can't intersect any other rectangle.
   * @param {Rectangle} other - The Rectangle to intersect with `this`.
   * @param {Matrix} transform - The transformation matrix of `other`.
   * @returns {boolean} A value of `true` if the transformed `other` Rectangle intersects with `this`; otherwise `false`.
   */
  /**
   * Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object.
   *
   * Returns true only if the area of the intersection is greater than 0.
   * This means that rectangles sharing only a side are not considered intersecting.
   * @example
   * ```ts
   * // Basic intersection check
   * const rect1 = new Rectangle(0, 0, 100, 100);
   * const rect2 = new Rectangle(50, 50, 100, 100);
   * console.log(rect1.intersects(rect2)); // true
   *
   * // With transformation matrix
   * const matrix = new Matrix();
   * matrix.rotate(Math.PI / 4); // 45 degrees
   * console.log(rect1.intersects(rect2, matrix)); // Checks with rotation
   *
   * // Edge cases
   * const zeroWidth = new Rectangle(0, 0, 0, 100);
   * console.log(rect1.intersects(zeroWidth)); // false (no area)
   * ```
   * @remarks
   * - Returns true only if intersection area is > 0
   * - Rectangles sharing only a side are not intersecting
   * - Zero-area rectangles cannot intersect anything
   * - Supports optional transformation matrix
   * @param other - The Rectangle to intersect with `this`
   * @param transform - Optional transformation matrix of `other`
   * @returns True if the transformed `other` Rectangle intersects with `this`
   * @see {@link Rectangle.containsRect} For containment testing
   * @see {@link Rectangle.contains} For point testing
   */
  intersects(t, e) {
    if (!e) {
      const T = this.x < t.x ? t.x : this.x;
      if ((this.right > t.right ? t.right : this.right) <= T)
        return !1;
      const C = this.y < t.y ? t.y : this.y;
      return (this.bottom > t.bottom ? t.bottom : this.bottom) > C;
    }
    const s = this.left, i = this.right, r = this.top, o = this.bottom;
    if (i <= s || o <= r)
      return !1;
    const a = Vr[0].set(t.left, t.top), l = Vr[1].set(t.left, t.bottom), c = Vr[2].set(t.right, t.top), h = Vr[3].set(t.right, t.bottom);
    if (c.x <= a.x || l.y <= a.y)
      return !1;
    const u = Math.sign(e.a * e.d - e.b * e.c);
    if (u === 0 || (e.apply(a, a), e.apply(l, l), e.apply(c, c), e.apply(h, h), Math.max(a.x, l.x, c.x, h.x) <= s || Math.min(a.x, l.x, c.x, h.x) >= i || Math.max(a.y, l.y, c.y, h.y) <= r || Math.min(a.y, l.y, c.y, h.y) >= o))
      return !1;
    const d = u * (l.y - a.y), f = u * (a.x - l.x), p = d * s + f * r, g = d * i + f * r, m = d * s + f * o, y = d * i + f * o;
    if (Math.max(p, g, m, y) <= d * a.x + f * a.y || Math.min(p, g, m, y) >= d * h.x + f * h.y)
      return !1;
    const x = u * (a.y - c.y), v = u * (c.x - a.x), _ = x * s + v * r, b = x * i + v * r, w = x * s + v * o, S = x * i + v * o;
    return !(Math.max(_, b, w, S) <= x * a.x + v * a.y || Math.min(_, b, w, S) >= x * h.x + v * h.y);
  }
  /**
   * Pads the rectangle making it grow in all directions.
   *
   * If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
   * @example
   * ```ts
   * // Basic padding
   * const rect = new Rectangle(100, 100, 200, 150);
   * rect.pad(10); // Adds 10px padding on all sides
   *
   * // Different horizontal and vertical padding
   * const uiRect = new Rectangle(0, 0, 100, 50);
   * uiRect.pad(20, 10); // 20px horizontal, 10px vertical
   * ```
   * @remarks
   * - Adjusts x/y by subtracting padding
   * - Increases width/height by padding * 2
   * - Common in UI layout calculations
   * - Chainable with other methods
   * @param paddingX - The horizontal padding amount
   * @param paddingY - The vertical padding amount
   * @returns Returns itself
   * @see {@link Rectangle.enlarge} For growing to include another rectangle
   * @see {@link Rectangle.fit} For shrinking to fit within another rectangle
   */
  pad(t = 0, e = t) {
    return this.x -= t, this.y -= e, this.width += t * 2, this.height += e * 2, this;
  }
  /**
   * Fits this rectangle around the passed one.
   * @example
   * ```ts
   * // Basic fitting
   * const container = new Rectangle(0, 0, 100, 100);
   * const content = new Rectangle(25, 25, 200, 200);
   * content.fit(container); // Clips to container bounds
   * ```
   * @param rectangle - The rectangle to fit around
   * @returns Returns itself
   * @see {@link Rectangle.enlarge} For growing to include another rectangle
   * @see {@link Rectangle.pad} For adding padding around the rectangle
   */
  fit(t) {
    const e = Math.max(this.x, t.x), s = Math.min(this.x + this.width, t.x + t.width), i = Math.max(this.y, t.y), r = Math.min(this.y + this.height, t.y + t.height);
    return this.x = e, this.width = Math.max(s - e, 0), this.y = i, this.height = Math.max(r - i, 0), this;
  }
  /**
   * Enlarges rectangle so that its corners lie on a grid defined by resolution.
   * @example
   * ```ts
   * // Basic grid alignment
   * const rect = new Rectangle(10.2, 10.6, 100.8, 100.4);
   * rect.ceil(); // Aligns to whole pixels
   *
   * // Custom resolution grid
   * const uiRect = new Rectangle(5.3, 5.7, 50.2, 50.8);
   * uiRect.ceil(0.5); // Aligns to half pixels
   *
   * // Use with precision value
   * const preciseRect = new Rectangle(20.001, 20.999, 100.001, 100.999);
   * preciseRect.ceil(1, 0.01); // Handles small decimal variations
   * ```
   * @param resolution - The grid size to align to (1 = whole pixels)
   * @param eps - Small number to prevent floating point errors
   * @returns Returns itself
   * @see {@link Rectangle.fit} For constraining to bounds
   * @see {@link Rectangle.enlarge} For growing dimensions
   */
  ceil(t = 1, e = 1e-3) {
    const s = Math.ceil((this.x + this.width - e) * t) / t, i = Math.ceil((this.y + this.height - e) * t) / t;
    return this.x = Math.floor((this.x + e) * t) / t, this.y = Math.floor((this.y + e) * t) / t, this.width = s - this.x, this.height = i - this.y, this;
  }
  /**
   * Scales the rectangle's dimensions and position by the specified factors.
   * @example
   * ```ts
   * const rect = new Rectangle(50, 50, 100, 100);
   *
   * // Scale uniformly
   * rect.scale(0.5, 0.5);
   * // rect is now: x=25, y=25, width=50, height=50
   *
   * // non-uniformly
   * rect.scale(0.5, 1);
   * // rect is now: x=25, y=50, width=50, height=100
   * ```
   * @param x - The factor by which to scale the horizontal properties (x, width).
   * @param y - The factor by which to scale the vertical properties (y, height).
   * @returns Returns itself
   */
  scale(t, e = t) {
    return this.x *= t, this.y *= e, this.width *= t, this.height *= e, this;
  }
  /**
   * Enlarges this rectangle to include the passed rectangle.
   * @example
   * ```ts
   * // Basic enlargement
   * const rect = new Rectangle(50, 50, 100, 100);
   * const other = new Rectangle(0, 0, 200, 75);
   * rect.enlarge(other);
   * // rect is now: x=0, y=0, width=200, height=150
   *
   * // Use for bounding box calculation
   * const bounds = new Rectangle();
   * objects.forEach((obj) => {
   *     bounds.enlarge(obj.getBounds());
   * });
   * ```
   * @param rectangle - The rectangle to include
   * @returns Returns itself
   * @see {@link Rectangle.fit} For shrinking to fit within another rectangle
   * @see {@link Rectangle.pad} For adding padding around the rectangle
   */
  enlarge(t) {
    const e = Math.min(this.x, t.x), s = Math.max(this.x + this.width, t.x + t.width), i = Math.min(this.y, t.y), r = Math.max(this.y + this.height, t.y + t.height);
    return this.x = e, this.width = s - e, this.y = i, this.height = r - i, this;
  }
  /**
   * Returns the framing rectangle of the rectangle as a Rectangle object
   * @example
   * ```ts
   * // Basic bounds retrieval
   * const rect = new Rectangle(100, 100, 200, 150);
   * const bounds = rect.getBounds();
   *
   * // Reuse existing rectangle
   * const out = new Rectangle();
   * rect.getBounds(out);
   * ```
   * @param out - Optional rectangle to store the result
   * @returns The framing rectangle
   * @see {@link Rectangle.copyFrom} For direct copying
   * @see {@link Rectangle.clone} For creating new copy
   */
  getBounds(t) {
    return t || (t = new Dt()), t.copyFrom(this), t;
  }
  /**
   * Determines whether another Rectangle is fully contained within this Rectangle.
   *
   * Rectangles that occupy the same space are considered to be containing each other.
   *
   * Rectangles without area (width or height equal to zero) can't contain anything,
   * not even other arealess rectangles.
   * @example
   * ```ts
   * // Check if one rectangle contains another
   * const container = new Rectangle(0, 0, 100, 100);
   * const inner = new Rectangle(25, 25, 50, 50);
   *
   * console.log(container.containsRect(inner)); // true
   *
   * // Check overlapping rectangles
   * const partial = new Rectangle(75, 75, 50, 50);
   * console.log(container.containsRect(partial)); // false
   *
   * // Zero-area rectangles
   * const empty = new Rectangle(0, 0, 0, 100);
   * console.log(container.containsRect(empty)); // false
   * ```
   * @param other - The Rectangle to check for containment
   * @returns True if other is fully contained within this Rectangle
   * @see {@link Rectangle.contains} For point containment
   * @see {@link Rectangle.intersects} For overlap testing
   */
  containsRect(t) {
    if (this.width <= 0 || this.height <= 0)
      return !1;
    const e = t.x, s = t.y, i = t.x + t.width, r = t.y + t.height;
    return e >= this.x && e < this.x + this.width && s >= this.y && s < this.y + this.height && i >= this.x && i < this.x + this.width && r >= this.y && r < this.y + this.height;
  }
  /**
   * Sets the position and dimensions of the rectangle.
   * @example
   * ```ts
   * // Basic usage
   * const rect = new Rectangle();
   * rect.set(100, 100, 200, 150);
   *
   * // Chain with other operations
   * const bounds = new Rectangle()
   *     .set(0, 0, 100, 100)
   *     .pad(10);
   * ```
   * @param x - The X coordinate of the upper-left corner of the rectangle
   * @param y - The Y coordinate of the upper-left corner of the rectangle
   * @param width - The overall width of the rectangle
   * @param height - The overall height of the rectangle
   * @returns Returns itself for method chaining
   * @see {@link Rectangle.copyFrom} For copying from another rectangle
   * @see {@link Rectangle.clone} For creating a new copy
   */
  set(t, e, s, i) {
    return this.x = t, this.y = e, this.width = s, this.height = i, this;
  }
  toString() {
    return `[pixi.js/math:Rectangle x=${this.x} y=${this.y} width=${this.width} height=${this.height}]`;
  }
}
const va = {
  default: -1
};
function Ot(n = "default") {
  return va[n] === void 0 && (va[n] = -1), ++va[n];
}
const Vh = {}, kt = "8.0.0", sy = "8.3.4";
function ct(n, t, e = 3) {
  if (Vh[t])
    return;
  let s = new Error().stack;
  typeof s > "u" ? console.warn("PixiJS Deprecation Warning: ", `${t}
Deprecated since v${n}`) : (s = s.split(`
`).splice(e).join(`
`), console.groupCollapsed ? (console.groupCollapsed(
    "%cPixiJS Deprecation Warning: %c%s",
    "color:#614108;background:#fffbe6",
    "font-weight:normal;color:#614108;background:#fffbe6",
    `${t}
Deprecated since v${n}`
  ), console.warn(s), console.groupEnd()) : (console.warn("PixiJS Deprecation Warning: ", `${t}
Deprecated since v${n}`), console.warn(s))), Vh[t] = !0;
}
const Pf = () => {
};
function Xn(n) {
  return n += n === 0 ? 1 : 0, --n, n |= n >>> 1, n |= n >>> 2, n |= n >>> 4, n |= n >>> 8, n |= n >>> 16, n + 1;
}
function Bh(n) {
  return !(n & n - 1) && !!n;
}
function If(n) {
  const t = {};
  for (const e in n)
    n[e] !== void 0 && (t[e] = n[e]);
  return t;
}
const zh = /* @__PURE__ */ Object.create(null);
function ny(n) {
  const t = zh[n];
  return t === void 0 && (zh[n] = Ot("resource")), t;
}
const Ff = class Rf extends ps {
  /**
   * @param options - options for the style
   */
  constructor(t = {}) {
    super(), this._resourceType = "textureSampler", this._touched = 0, this._maxAnisotropy = 1, this.destroyed = !1, t = { ...Rf.defaultOptions, ...t }, this.addressMode = t.addressMode, this.addressModeU = t.addressModeU ?? this.addressModeU, this.addressModeV = t.addressModeV ?? this.addressModeV, this.addressModeW = t.addressModeW ?? this.addressModeW, this.scaleMode = t.scaleMode, this.magFilter = t.magFilter ?? this.magFilter, this.minFilter = t.minFilter ?? this.minFilter, this.mipmapFilter = t.mipmapFilter ?? this.mipmapFilter, this.lodMinClamp = t.lodMinClamp, this.lodMaxClamp = t.lodMaxClamp, this.compare = t.compare, this.maxAnisotropy = t.maxAnisotropy ?? 1;
  }
  set addressMode(t) {
    this.addressModeU = t, this.addressModeV = t, this.addressModeW = t;
  }
  /** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */
  get addressMode() {
    return this.addressModeU;
  }
  set wrapMode(t) {
    ct(kt, "TextureStyle.wrapMode is now TextureStyle.addressMode"), this.addressMode = t;
  }
  get wrapMode() {
    return this.addressMode;
  }
  set scaleMode(t) {
    this.magFilter = t, this.minFilter = t, this.mipmapFilter = t;
  }
  /** setting this will set magFilter,minFilter and mipmapFilter all at once!  */
  get scaleMode() {
    return this.magFilter;
  }
  /** Specifies the maximum anisotropy value clamp used by the sampler. */
  set maxAnisotropy(t) {
    this._maxAnisotropy = Math.min(t, 16), this._maxAnisotropy > 1 && (this.scaleMode = "linear");
  }
  get maxAnisotropy() {
    return this._maxAnisotropy;
  }
  // TODO - move this to WebGL?
  get _resourceId() {
    return this._sharedResourceId || this._generateResourceId();
  }
  update() {
    this.emit("change", this), this._sharedResourceId = null;
  }
  _generateResourceId() {
    const t = `${this.addressModeU}-${this.addressModeV}-${this.addressModeW}-${this.magFilter}-${this.minFilter}-${this.mipmapFilter}-${this.lodMinClamp}-${this.lodMaxClamp}-${this.compare}-${this._maxAnisotropy}`;
    return this._sharedResourceId = ny(t), this._resourceId;
  }
  /** Destroys the style */
  destroy() {
    this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this.removeAllListeners();
  }
};
Ff.defaultOptions = {
  addressMode: "clamp-to-edge",
  scaleMode: "linear"
};
let mo = Ff;
const Df = class Of extends ps {
  /**
   * @param options - options for creating a new TextureSource
   */
  constructor(t = {}) {
    super(), this.options = t, this.uid = Ot("textureSource"), this._resourceType = "textureSource", this._resourceId = Ot("resource"), this.uploadMethodId = "unknown", this._resolution = 1, this.pixelWidth = 1, this.pixelHeight = 1, this.width = 1, this.height = 1, this.sampleCount = 1, this.mipLevelCount = 1, this.autoGenerateMipmaps = !1, this.format = "rgba8unorm", this.dimension = "2d", this.antialias = !1, this._touched = 0, this._batchTick = -1, this._textureBindLocation = -1, t = { ...Of.defaultOptions, ...t }, this.label = t.label ?? "", this.resource = t.resource, this.autoGarbageCollect = t.autoGarbageCollect, this._resolution = t.resolution, t.width ? this.pixelWidth = t.width * this._resolution : this.pixelWidth = this.resource ? this.resourceWidth ?? 1 : 1, t.height ? this.pixelHeight = t.height * this._resolution : this.pixelHeight = this.resource ? this.resourceHeight ?? 1 : 1, this.width = this.pixelWidth / this._resolution, this.height = this.pixelHeight / this._resolution, this.format = t.format, this.dimension = t.dimensions, this.mipLevelCount = t.mipLevelCount, this.autoGenerateMipmaps = t.autoGenerateMipmaps, this.sampleCount = t.sampleCount, this.antialias = t.antialias, this.alphaMode = t.alphaMode, this.style = new mo(If(t)), this.destroyed = !1, this._refreshPOT();
  }
  /** returns itself */
  get source() {
    return this;
  }
  /** the style of the texture */
  get style() {
    return this._style;
  }
  set style(t) {
    this.style !== t && (this._style?.off("change", this._onStyleChange, this), this._style = t, this._style?.on("change", this._onStyleChange, this), this._onStyleChange());
  }
  /** Specifies the maximum anisotropy value clamp used by the sampler. */
  set maxAnisotropy(t) {
    this._style.maxAnisotropy = t;
  }
  get maxAnisotropy() {
    return this._style.maxAnisotropy;
  }
  /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */
  get addressMode() {
    return this._style.addressMode;
  }
  set addressMode(t) {
    this._style.addressMode = t;
  }
  /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */
  get repeatMode() {
    return this._style.addressMode;
  }
  set repeatMode(t) {
    this._style.addressMode = t;
  }
  /** Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel. */
  get magFilter() {
    return this._style.magFilter;
  }
  set magFilter(t) {
    this._style.magFilter = t;
  }
  /** Specifies the sampling behavior when the sample footprint is larger than one texel. */
  get minFilter() {
    return this._style.minFilter;
  }
  set minFilter(t) {
    this._style.minFilter = t;
  }
  /** Specifies behavior for sampling between mipmap levels. */
  get mipmapFilter() {
    return this._style.mipmapFilter;
  }
  set mipmapFilter(t) {
    this._style.mipmapFilter = t;
  }
  /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */
  get lodMinClamp() {
    return this._style.lodMinClamp;
  }
  set lodMinClamp(t) {
    this._style.lodMinClamp = t;
  }
  /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */
  get lodMaxClamp() {
    return this._style.lodMaxClamp;
  }
  set lodMaxClamp(t) {
    this._style.lodMaxClamp = t;
  }
  _onStyleChange() {
    this.emit("styleChange", this);
  }
  /** call this if you have modified the texture outside of the constructor */
  update() {
    if (this.resource) {
      const t = this._resolution;
      if (this.resize(this.resourceWidth / t, this.resourceHeight / t))
        return;
    }
    this.emit("update", this);
  }
  /** Destroys this texture source */
  destroy() {
    this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this._style && (this._style.destroy(), this._style = null), this.uploadMethodId = null, this.resource = null, this.removeAllListeners();
  }
  /**
   * This will unload the Texture source from the GPU. This will free up the GPU memory
   * As soon as it is required fore rendering, it will be re-uploaded.
   */
  unload() {
    this._resourceId = Ot("resource"), this.emit("change", this), this.emit("unload", this);
  }
  /** the width of the resource. This is the REAL pure number, not accounting resolution   */
  get resourceWidth() {
    const { resource: t } = this;
    return t.naturalWidth || t.videoWidth || t.displayWidth || t.width;
  }
  /** the height of the resource. This is the REAL pure number, not accounting resolution */
  get resourceHeight() {
    const { resource: t } = this;
    return t.naturalHeight || t.videoHeight || t.displayHeight || t.height;
  }
  /**
   * the resolution of the texture. Changing this number, will not change the number of pixels in the actual texture
   * but will the size of the texture when rendered.
   *
   * changing the resolution of this texture to 2 for example will make it appear twice as small when rendered (as pixel
   * density will have increased)
   */
  get resolution() {
    return this._resolution;
  }
  set resolution(t) {
    this._resolution !== t && (this._resolution = t, this.width = this.pixelWidth / t, this.height = this.pixelHeight / t);
  }
  /**
   * Resize the texture, this is handy if you want to use the texture as a render texture
   * @param width - the new width of the texture
   * @param height - the new height of the texture
   * @param resolution - the new resolution of the texture
   * @returns - if the texture was resized
   */
  resize(t, e, s) {
    s || (s = this._resolution), t || (t = this.width), e || (e = this.height);
    const i = Math.round(t * s), r = Math.round(e * s);
    return this.width = i / s, this.height = r / s, this._resolution = s, this.pixelWidth === i && this.pixelHeight === r ? !1 : (this._refreshPOT(), this.pixelWidth = i, this.pixelHeight = r, this.emit("resize", this), this._resourceId = Ot("resource"), this.emit("change", this), !0);
  }
  /**
   * Lets the renderer know that this texture has been updated and its mipmaps should be re-generated.
   * This is only important for RenderTexture instances, as standard Texture instances will have their
   * mipmaps generated on upload. You should call this method after you make any change to the texture
   *
   * The reason for this is is can be quite expensive to update mipmaps for a texture. So by default,
   * We want you, the developer to specify when this action should happen.
   *
   * Generally you don't want to have mipmaps generated on Render targets that are changed every frame,
   */
  updateMipmaps() {
    this.autoGenerateMipmaps && this.mipLevelCount > 1 && this.emit("updateMipmaps", this);
  }
  set wrapMode(t) {
    this._style.wrapMode = t;
  }
  get wrapMode() {
    return this._style.wrapMode;
  }
  set scaleMode(t) {
    this._style.scaleMode = t;
  }
  /** setting this will set magFilter,minFilter and mipmapFilter all at once!  */
  get scaleMode() {
    return this._style.scaleMode;
  }
  /**
   * Refresh check for isPowerOfTwo texture based on size
   * @private
   */
  _refreshPOT() {
    this.isPowerOfTwo = Bh(this.pixelWidth) && Bh(this.pixelHeight);
  }
  static test(t) {
    throw new Error("Unimplemented");
  }
};
Df.defaultOptions = {
  resolution: 1,
  format: "bgra8unorm",
  alphaMode: "premultiply-alpha-on-upload",
  dimensions: "2d",
  mipLevelCount: 1,
  autoGenerateMipmaps: !1,
  sampleCount: 1,
  antialias: !1,
  autoGarbageCollect: !1
};
let Je = Df;
class jl extends Je {
  constructor(t) {
    const e = t.resource || new Float32Array(t.width * t.height * 4);
    let s = t.format;
    s || (e instanceof Float32Array ? s = "rgba32float" : e instanceof Int32Array || e instanceof Uint32Array ? s = "rgba32uint" : e instanceof Int16Array || e instanceof Uint16Array ? s = "rgba16uint" : (e instanceof Int8Array, s = "bgra8unorm")), super({
      ...t,
      resource: e,
      format: s
    }), this.uploadMethodId = "buffer";
  }
  static test(t) {
    return t instanceof Int8Array || t instanceof Uint8Array || t instanceof Uint8ClampedArray || t instanceof Int16Array || t instanceof Uint16Array || t instanceof Int32Array || t instanceof Uint32Array || t instanceof Float32Array;
  }
}
jl.extension = dt.TextureSource;
const qh = new nt();
class iy {
  /**
   * @param texture - observed texture
   * @param clampMargin - Changes frame clamping, 0.5 by default. Use -0.5 for extra border.
   */
  constructor(t, e) {
    this.mapCoord = new nt(), this.uClampFrame = new Float32Array(4), this.uClampOffset = new Float32Array(2), this._textureID = -1, this._updateID = 0, this.clampOffset = 0, typeof e > "u" ? this.clampMargin = t.width < 10 ? 0 : 0.5 : this.clampMargin = e, this.isSimple = !1, this.texture = t;
  }
  /** Texture property. */
  get texture() {
    return this._texture;
  }
  set texture(t) {
    this.texture !== t && (this._texture?.removeListener("update", this.update, this), this._texture = t, this._texture.addListener("update", this.update, this), this.update());
  }
  /**
   * Multiplies uvs array to transform
   * @param uvs - mesh uvs
   * @param [out=uvs] - output
   * @returns - output
   */
  multiplyUvs(t, e) {
    e === void 0 && (e = t);
    const s = this.mapCoord;
    for (let i = 0; i < t.length; i += 2) {
      const r = t[i], o = t[i + 1];
      e[i] = r * s.a + o * s.c + s.tx, e[i + 1] = r * s.b + o * s.d + s.ty;
    }
    return e;
  }
  /**
   * Updates matrices if texture was changed
   * @returns - whether or not it was updated
   */
  update() {
    const t = this._texture;
    this._updateID++;
    const e = t.uvs;
    this.mapCoord.set(e.x1 - e.x0, e.y1 - e.y0, e.x3 - e.x0, e.y3 - e.y0, e.x0, e.y0);
    const s = t.orig, i = t.trim;
    i && (qh.set(
      s.width / i.width,
      0,
      0,
      s.height / i.height,
      -i.x / i.width,
      -i.y / i.height
    ), this.mapCoord.append(qh));
    const r = t.source, o = this.uClampFrame, a = this.clampMargin / r._resolution, l = this.clampOffset / r._resolution;
    return o[0] = (t.frame.x + a + l) / r.width, o[1] = (t.frame.y + a + l) / r.height, o[2] = (t.frame.x + t.frame.width - a + l) / r.width, o[3] = (t.frame.y + t.frame.height - a + l) / r.height, this.uClampOffset[0] = this.clampOffset / r.pixelWidth, this.uClampOffset[1] = this.clampOffset / r.pixelHeight, this.isSimple = t.frame.width === r.width && t.frame.height === r.height && t.rotate === 0, !0;
  }
}
class rt extends ps {
  /**
   * @param {TextureOptions} options - Options for the texture
   */
  constructor({
    source: t,
    label: e,
    frame: s,
    orig: i,
    trim: r,
    defaultAnchor: o,
    defaultBorders: a,
    rotate: l,
    dynamic: c
  } = {}) {
    if (super(), this.uid = Ot("texture"), this.uvs = { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 }, this.frame = new Dt(), this.noFrame = !1, this.dynamic = !1, this.isTexture = !0, this.label = e, this.source = t?.source ?? new Je(), this.noFrame = !s, s)
      this.frame.copyFrom(s);
    else {
      const { width: h, height: u } = this._source;
      this.frame.width = h, this.frame.height = u;
    }
    this.orig = i || this.frame, this.trim = r, this.rotate = l ?? 0, this.defaultAnchor = o, this.defaultBorders = a, this.destroyed = !1, this.dynamic = c || !1, this.updateUvs();
  }
  set source(t) {
    this._source && this._source.off("resize", this.update, this), this._source = t, t.on("resize", this.update, this), this.emit("update", this);
  }
  /** the underlying source of the texture (equivalent of baseTexture in v7) */
  get source() {
    return this._source;
  }
  /** returns a TextureMatrix instance for this texture. By default, that object is not created because its heavy. */
  get textureMatrix() {
    return this._textureMatrix || (this._textureMatrix = new iy(this)), this._textureMatrix;
  }
  /** The width of the Texture in pixels. */
  get width() {
    return this.orig.width;
  }
  /** The height of the Texture in pixels. */
  get height() {
    return this.orig.height;
  }
  /** Call this function when you have modified the frame of this texture. */
  updateUvs() {
    const { uvs: t, frame: e } = this, { width: s, height: i } = this._source, r = e.x / s, o = e.y / i, a = e.width / s, l = e.height / i;
    let c = this.rotate;
    if (c) {
      const h = a / 2, u = l / 2, d = r + h, f = o + u;
      c = gt.add(c, gt.NW), t.x0 = d + h * gt.uX(c), t.y0 = f + u * gt.uY(c), c = gt.add(c, 2), t.x1 = d + h * gt.uX(c), t.y1 = f + u * gt.uY(c), c = gt.add(c, 2), t.x2 = d + h * gt.uX(c), t.y2 = f + u * gt.uY(c), c = gt.add(c, 2), t.x3 = d + h * gt.uX(c), t.y3 = f + u * gt.uY(c);
    } else
      t.x0 = r, t.y0 = o, t.x1 = r + a, t.y1 = o, t.x2 = r + a, t.y2 = o + l, t.x3 = r, t.y3 = o + l;
  }
  /**
   * Destroys this texture
   * @param destroySource - Destroy the source when the texture is destroyed.
   */
  destroy(t = !1) {
    this._source && t && (this._source.destroy(), this._source = null), this._textureMatrix = null, this.destroyed = !0, this.emit("destroy", this), this.removeAllListeners();
  }
  /**
   * Call this if you have modified the `texture outside` of the constructor.
   *
   * If you have modified this texture's source, you must separately call `texture.source.update()` to see those changes.
   */
  update() {
    this.noFrame && (this.frame.width = this._source.width, this.frame.height = this._source.height), this.updateUvs(), this.emit("update", this);
  }
  /** @deprecated since 8.0.0 */
  get baseTexture() {
    return ct(kt, "Texture.baseTexture is now Texture.source"), this._source;
  }
}
rt.EMPTY = new rt({
  label: "EMPTY",
  source: new Je({
    label: "EMPTY"
  })
});
rt.EMPTY.destroy = Pf;
rt.WHITE = new rt({
  source: new jl({
    resource: new Uint8Array([255, 255, 255, 255]),
    width: 1,
    height: 1,
    alphaMode: "premultiply-alpha-on-upload",
    label: "WHITE"
  }),
  label: "WHITE"
});
rt.WHITE.destroy = Pf;
function ry(n, t, e) {
  const { width: s, height: i } = e.orig, r = e.trim;
  if (r) {
    const o = r.width, a = r.height;
    n.minX = r.x - t._x * s, n.maxX = n.minX + o, n.minY = r.y - t._y * i, n.maxY = n.minY + a;
  } else
    n.minX = -t._x * s, n.maxX = n.minX + s, n.minY = -t._y * i, n.maxY = n.minY + i;
}
const Uh = new nt();
class Ye {
  /**
   * Creates a new Bounds object.
   * @param minX - The minimum X coordinate of the bounds.
   * @param minY - The minimum Y coordinate of the bounds.
   * @param maxX - The maximum X coordinate of the bounds.
   * @param maxY - The maximum Y coordinate of the bounds.
   */
  constructor(t = 1 / 0, e = 1 / 0, s = -1 / 0, i = -1 / 0) {
    this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = Uh, this.minX = t, this.minY = e, this.maxX = s, this.maxY = i;
  }
  /**
   * Checks if bounds are empty, meaning either width or height is zero or negative.
   * Empty bounds occur when min values exceed max values on either axis.
   * @example
   * ```ts
   * const bounds = new Bounds();
   *
   * // Check if newly created bounds are empty
   * console.log(bounds.isEmpty()); // true, default bounds are empty
   *
   * // Add frame and check again
   * bounds.addFrame(0, 0, 100, 100);
   * console.log(bounds.isEmpty()); // false, bounds now have area
   *
   * // Clear bounds
   * bounds.clear();
   * console.log(bounds.isEmpty()); // true, bounds are empty again
   * ```
   * @returns True if bounds are empty (have no area)
   * @see {@link Bounds#clear} For resetting bounds
   * @see {@link Bounds#isValid} For checking validity
   */
  isEmpty() {
    return this.minX > this.maxX || this.minY > this.maxY;
  }
  /**
   * The bounding rectangle representation of these bounds.
   * Lazily creates and updates a Rectangle instance based on the current bounds.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   *
   * // Get rectangle representation
   * const rect = bounds.rectangle;
   * console.log(rect.x, rect.y, rect.width, rect.height);
   *
   * // Use for hit testing
   * if (bounds.rectangle.contains(mouseX, mouseY)) {
   *     console.log('Mouse is inside bounds!');
   * }
   * ```
   * @see {@link Rectangle} For rectangle methods
   * @see {@link Bounds.isEmpty} For bounds validation
   */
  get rectangle() {
    this._rectangle || (this._rectangle = new Dt());
    const t = this._rectangle;
    return this.minX > this.maxX || this.minY > this.maxY ? (t.x = 0, t.y = 0, t.width = 0, t.height = 0) : t.copyFromBounds(this), t;
  }
  /**
   * Clears the bounds and resets all coordinates to their default values.
   * Resets the transformation matrix back to identity.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * console.log(bounds.isEmpty()); // false
   * // Clear the bounds
   * bounds.clear();
   * console.log(bounds.isEmpty()); // true
   * ```
   * @returns This bounds object for chaining
   */
  clear() {
    return this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = Uh, this;
  }
  /**
   * Sets the bounds directly using coordinate values.
   * Provides a way to set all bounds values at once.
   * @example
   * ```ts
   * const bounds = new Bounds();
   * bounds.set(0, 0, 100, 100);
   * ```
   * @param x0 - Left X coordinate of frame
   * @param y0 - Top Y coordinate of frame
   * @param x1 - Right X coordinate of frame
   * @param y1 - Bottom Y coordinate of frame
   * @see {@link Bounds#addFrame} For matrix-aware bounds setting
   * @see {@link Bounds#clear} For resetting bounds
   */
  set(t, e, s, i) {
    this.minX = t, this.minY = e, this.maxX = s, this.maxY = i;
  }
  /**
   * Adds a rectangular frame to the bounds, optionally transformed by a matrix.
   * Updates the bounds to encompass the new frame coordinates.
   * @example
   * ```ts
   * const bounds = new Bounds();
   * bounds.addFrame(0, 0, 100, 100);
   *
   * // Add transformed frame
   * const matrix = new Matrix()
   *     .translate(50, 50)
   *     .rotate(Math.PI / 4);
   * bounds.addFrame(0, 0, 100, 100, matrix);
   * ```
   * @param x0 - Left X coordinate of frame
   * @param y0 - Top Y coordinate of frame
   * @param x1 - Right X coordinate of frame
   * @param y1 - Bottom Y coordinate of frame
   * @param matrix - Optional transformation matrix
   * @see {@link Bounds#addRect} For adding Rectangle objects
   * @see {@link Bounds#addBounds} For adding other Bounds
   */
  addFrame(t, e, s, i, r) {
    r || (r = this.matrix);
    const o = r.a, a = r.b, l = r.c, c = r.d, h = r.tx, u = r.ty;
    let d = this.minX, f = this.minY, p = this.maxX, g = this.maxY, m = o * t + l * e + h, y = a * t + c * e + u;
    m < d && (d = m), y < f && (f = y), m > p && (p = m), y > g && (g = y), m = o * s + l * e + h, y = a * s + c * e + u, m < d && (d = m), y < f && (f = y), m > p && (p = m), y > g && (g = y), m = o * t + l * i + h, y = a * t + c * i + u, m < d && (d = m), y < f && (f = y), m > p && (p = m), y > g && (g = y), m = o * s + l * i + h, y = a * s + c * i + u, m < d && (d = m), y < f && (f = y), m > p && (p = m), y > g && (g = y), this.minX = d, this.minY = f, this.maxX = p, this.maxY = g;
  }
  /**
   * Adds a rectangle to the bounds, optionally transformed by a matrix.
   * Updates the bounds to encompass the given rectangle.
   * @example
   * ```ts
   * const bounds = new Bounds();
   * // Add simple rectangle
   * const rect = new Rectangle(0, 0, 100, 100);
   * bounds.addRect(rect);
   *
   * // Add transformed rectangle
   * const matrix = new Matrix()
   *     .translate(50, 50)
   *     .rotate(Math.PI / 4);
   * bounds.addRect(rect, matrix);
   * ```
   * @param rect - The rectangle to be added
   * @param matrix - Optional transformation matrix
   * @see {@link Bounds#addFrame} For adding raw coordinates
   * @see {@link Bounds#addBounds} For adding other bounds
   */
  addRect(t, e) {
    this.addFrame(t.x, t.y, t.x + t.width, t.y + t.height, e);
  }
  /**
   * Adds another bounds object to this one, optionally transformed by a matrix.
   * Expands the bounds to include the given bounds' area.
   * @example
   * ```ts
   * const bounds = new Bounds();
   *
   * // Add child bounds
   * const childBounds = sprite.getBounds();
   * bounds.addBounds(childBounds);
   *
   * // Add transformed bounds
   * const matrix = new Matrix()
   *     .scale(2, 2);
   * bounds.addBounds(childBounds, matrix);
   * ```
   * @param bounds - The bounds to be added
   * @param matrix - Optional transformation matrix
   * @see {@link Bounds#addFrame} For adding raw coordinates
   * @see {@link Bounds#addRect} For adding rectangles
   */
  addBounds(t, e) {
    this.addFrame(t.minX, t.minY, t.maxX, t.maxY, e);
  }
  /**
   * Adds other Bounds as a mask, creating an intersection of the two bounds.
   * Only keeps the overlapping region between current bounds and mask bounds.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Create mask bounds
   * const mask = new Bounds();
   * mask.addFrame(50, 50, 150, 150);
   * // Apply mask - results in bounds of (50,50,100,100)
   * bounds.addBoundsMask(mask);
   * ```
   * @param mask - The Bounds to use as a mask
   * @see {@link Bounds#addBounds} For union operation
   * @see {@link Bounds#fit} For fitting to rectangle
   */
  addBoundsMask(t) {
    this.minX = this.minX > t.minX ? this.minX : t.minX, this.minY = this.minY > t.minY ? this.minY : t.minY, this.maxX = this.maxX < t.maxX ? this.maxX : t.maxX, this.maxY = this.maxY < t.maxY ? this.maxY : t.maxY;
  }
  /**
   * Applies a transformation matrix to the bounds, updating its coordinates.
   * Transforms all corners of the bounds using the given matrix.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Apply translation
   * const translateMatrix = new Matrix()
   *     .translate(50, 50);
   * bounds.applyMatrix(translateMatrix);
   * ```
   * @param matrix - The matrix to apply to the bounds
   * @see {@link Matrix} For matrix operations
   * @see {@link Bounds#addFrame} For adding transformed frames
   */
  applyMatrix(t) {
    const e = this.minX, s = this.minY, i = this.maxX, r = this.maxY, { a: o, b: a, c: l, d: c, tx: h, ty: u } = t;
    let d = o * e + l * s + h, f = a * e + c * s + u;
    this.minX = d, this.minY = f, this.maxX = d, this.maxY = f, d = o * i + l * s + h, f = a * i + c * s + u, this.minX = d < this.minX ? d : this.minX, this.minY = f < this.minY ? f : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = f > this.maxY ? f : this.maxY, d = o * e + l * r + h, f = a * e + c * r + u, this.minX = d < this.minX ? d : this.minX, this.minY = f < this.minY ? f : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = f > this.maxY ? f : this.maxY, d = o * i + l * r + h, f = a * i + c * r + u, this.minX = d < this.minX ? d : this.minX, this.minY = f < this.minY ? f : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = f > this.maxY ? f : this.maxY;
  }
  /**
   * Resizes the bounds object to fit within the given rectangle.
   * Clips the bounds if they extend beyond the rectangle's edges.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 200, 200);
   * // Fit within viewport
   * const viewport = new Rectangle(50, 50, 100, 100);
   * bounds.fit(viewport);
   * // bounds are now (50, 50, 150, 150)
   * ```
   * @param rect - The rectangle to fit within
   * @returns This bounds object for chaining
   * @see {@link Bounds#addBoundsMask} For intersection
   * @see {@link Bounds#pad} For expanding bounds
   */
  fit(t) {
    return this.minX < t.left && (this.minX = t.left), this.maxX > t.right && (this.maxX = t.right), this.minY < t.top && (this.minY = t.top), this.maxY > t.bottom && (this.maxY = t.bottom), this;
  }
  /**
   * Resizes the bounds object to include the given bounds.
   * Similar to fit() but works with raw coordinate values instead of a Rectangle.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 200, 200);
   * // Fit to specific coordinates
   * bounds.fitBounds(50, 150, 50, 150);
   * // bounds are now (50, 50, 150, 150)
   * ```
   * @param left - The left value of the bounds
   * @param right - The right value of the bounds
   * @param top - The top value of the bounds
   * @param bottom - The bottom value of the bounds
   * @returns This bounds object for chaining
   * @see {@link Bounds#fit} For fitting to Rectangle
   * @see {@link Bounds#addBoundsMask} For intersection
   */
  fitBounds(t, e, s, i) {
    return this.minX < t && (this.minX = t), this.maxX > e && (this.maxX = e), this.minY < s && (this.minY = s), this.maxY > i && (this.maxY = i), this;
  }
  /**
   * Pads bounds object, making it grow in all directions.
   * If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   *
   * // Add equal padding
   * bounds.pad(10);
   * // bounds are now (-10, -10, 110, 110)
   *
   * // Add different padding for x and y
   * bounds.pad(20, 10);
   * // bounds are now (-30, -20, 130, 120)
   * ```
   * @param paddingX - The horizontal padding amount
   * @param paddingY - The vertical padding amount
   * @returns This bounds object for chaining
   * @see {@link Bounds#fit} For constraining bounds
   * @see {@link Bounds#scale} For uniform scaling
   */
  pad(t, e = t) {
    return this.minX -= t, this.maxX += t, this.minY -= e, this.maxY += e, this;
  }
  /**
   * Ceils the bounds by rounding up max values and rounding down min values.
   * Useful for pixel-perfect calculations and avoiding fractional pixels.
   * @example
   * ```ts
   * const bounds = new Bounds();
   * bounds.set(10.2, 10.9, 50.1, 50.8);
   *
   * // Round to whole pixels
   * bounds.ceil();
   * // bounds are now (10, 10, 51, 51)
   * ```
   * @returns This bounds object for chaining
   * @see {@link Bounds#scale} For size adjustments
   * @see {@link Bounds#fit} For constraining bounds
   */
  ceil() {
    return this.minX = Math.floor(this.minX), this.minY = Math.floor(this.minY), this.maxX = Math.ceil(this.maxX), this.maxY = Math.ceil(this.maxY), this;
  }
  /**
   * Creates a new Bounds instance with the same values.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   *
   * // Create a copy
   * const copy = bounds.clone();
   *
   * // Original and copy are independent
   * bounds.pad(10);
   * console.log(copy.width === bounds.width); // false
   * ```
   * @returns A new Bounds instance with the same values
   * @see {@link Bounds#copyFrom} For reusing existing bounds
   */
  clone() {
    return new Ye(this.minX, this.minY, this.maxX, this.maxY);
  }
  /**
   * Scales the bounds by the given values, adjusting all edges proportionally.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   *
   * // Scale uniformly
   * bounds.scale(2);
   * // bounds are now (0, 0, 200, 200)
   *
   * // Scale non-uniformly
   * bounds.scale(0.5, 2);
   * // bounds are now (0, 0, 100, 400)
   * ```
   * @param x - The X value to scale by
   * @param y - The Y value to scale by (defaults to x)
   * @returns This bounds object for chaining
   * @see {@link Bounds#pad} For adding padding
   * @see {@link Bounds#fit} For constraining size
   */
  scale(t, e = t) {
    return this.minX *= t, this.minY *= e, this.maxX *= t, this.maxY *= e, this;
  }
  /**
   * The x position of the bounds in local space.
   * Setting this value will move the bounds while maintaining its width.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Get x position
   * console.log(bounds.x); // 0
   *
   * // Move bounds horizontally
   * bounds.x = 50;
   * console.log(bounds.minX, bounds.maxX); // 50, 150
   *
   * // Width stays the same
   * console.log(bounds.width); // Still 100
   * ```
   */
  get x() {
    return this.minX;
  }
  set x(t) {
    const e = this.maxX - this.minX;
    this.minX = t, this.maxX = t + e;
  }
  /**
   * The y position of the bounds in local space.
   * Setting this value will move the bounds while maintaining its height.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Get y position
   * console.log(bounds.y); // 0
   *
   * // Move bounds vertically
   * bounds.y = 50;
   * console.log(bounds.minY, bounds.maxY); // 50, 150
   *
   * // Height stays the same
   * console.log(bounds.height); // Still 100
   * ```
   */
  get y() {
    return this.minY;
  }
  set y(t) {
    const e = this.maxY - this.minY;
    this.minY = t, this.maxY = t + e;
  }
  /**
   * The width value of the bounds.
   * Represents the distance between minX and maxX coordinates.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Get width
   * console.log(bounds.width); // 100
   * // Resize width
   * bounds.width = 200;
   * console.log(bounds.maxX - bounds.minX); // 200
   * ```
   */
  get width() {
    return this.maxX - this.minX;
  }
  set width(t) {
    this.maxX = this.minX + t;
  }
  /**
   * The height value of the bounds.
   * Represents the distance between minY and maxY coordinates.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Get height
   * console.log(bounds.height); // 100
   * // Resize height
   * bounds.height = 150;
   * console.log(bounds.maxY - bounds.minY); // 150
   * ```
   */
  get height() {
    return this.maxY - this.minY;
  }
  set height(t) {
    this.maxY = this.minY + t;
  }
  /**
   * The left edge coordinate of the bounds.
   * Alias for minX.
   * @example
   * ```ts
   * const bounds = new Bounds(50, 0, 150, 100);
   * console.log(bounds.left); // 50
   * console.log(bounds.left === bounds.minX); // true
   * ```
   * @readonly
   */
  get left() {
    return this.minX;
  }
  /**
   * The right edge coordinate of the bounds.
   * Alias for maxX.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * console.log(bounds.right); // 100
   * console.log(bounds.right === bounds.maxX); // true
   * ```
   * @readonly
   */
  get right() {
    return this.maxX;
  }
  /**
   * The top edge coordinate of the bounds.
   * Alias for minY.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 25, 100, 125);
   * console.log(bounds.top); // 25
   * console.log(bounds.top === bounds.minY); // true
   * ```
   * @readonly
   */
  get top() {
    return this.minY;
  }
  /**
   * The bottom edge coordinate of the bounds.
   * Alias for maxY.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 200);
   * console.log(bounds.bottom); // 200
   * console.log(bounds.bottom === bounds.maxY); // true
   * ```
   * @readonly
   */
  get bottom() {
    return this.maxY;
  }
  /**
   * Whether the bounds has positive width and height.
   * Checks if both dimensions are greater than zero.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Check if bounds are positive
   * console.log(bounds.isPositive); // true
   *
   * // Negative bounds
   * bounds.maxX = bounds.minX;
   * console.log(bounds.isPositive); // false, width is 0
   * ```
   * @readonly
   * @see {@link Bounds#isEmpty} For checking empty state
   * @see {@link Bounds#isValid} For checking validity
   */
  get isPositive() {
    return this.maxX - this.minX > 0 && this.maxY - this.minY > 0;
  }
  /**
   * Whether the bounds has valid coordinates.
   * Checks if the bounds has been initialized with real values.
   * @example
   * ```ts
   * const bounds = new Bounds();
   * console.log(bounds.isValid); // false, default state
   *
   * // Set valid bounds
   * bounds.addFrame(0, 0, 100, 100);
   * console.log(bounds.isValid); // true
   * ```
   * @readonly
   * @see {@link Bounds#isEmpty} For checking empty state
   * @see {@link Bounds#isPositive} For checking dimensions
   */
  get isValid() {
    return this.minX + this.minY !== 1 / 0;
  }
  /**
   * Adds vertices from a Float32Array to the bounds, optionally transformed by a matrix.
   * Used for efficiently updating bounds from raw vertex data.
   * @example
   * ```ts
   * const bounds = new Bounds();
   *
   * // Add vertices from geometry
   * const vertices = new Float32Array([
   *     0, 0,    // Vertex 1
   *     100, 0,  // Vertex 2
   *     100, 100 // Vertex 3
   * ]);
   * bounds.addVertexData(vertices, 0, 6);
   *
   * // Add transformed vertices
   * const matrix = new Matrix()
   *     .translate(50, 50)
   *     .rotate(Math.PI / 4);
   * bounds.addVertexData(vertices, 0, 6, matrix);
   *
   * // Add subset of vertices
   * bounds.addVertexData(vertices, 2, 4); // Only second vertex
   * ```
   * @param vertexData - The array of vertices to add
   * @param beginOffset - Starting index in the vertex array
   * @param endOffset - Ending index in the vertex array (excluded)
   * @param matrix - Optional transformation matrix
   * @see {@link Bounds#addFrame} For adding rectangular frames
   * @see {@link Matrix} For transformation details
   */
  addVertexData(t, e, s, i) {
    let r = this.minX, o = this.minY, a = this.maxX, l = this.maxY;
    i || (i = this.matrix);
    const c = i.a, h = i.b, u = i.c, d = i.d, f = i.tx, p = i.ty;
    for (let g = e; g < s; g += 2) {
      const m = t[g], y = t[g + 1], x = c * m + u * y + f, v = h * m + d * y + p;
      r = x < r ? x : r, o = v < o ? v : o, a = x > a ? x : a, l = v > l ? v : l;
    }
    this.minX = r, this.minY = o, this.maxX = a, this.maxY = l;
  }
  /**
   * Checks if a point is contained within the bounds.
   * Returns true if the point's coordinates fall within the bounds' area.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * // Basic point check
   * console.log(bounds.containsPoint(50, 50)); // true
   * console.log(bounds.containsPoint(150, 150)); // false
   *
   * // Check edges
   * console.log(bounds.containsPoint(0, 0));   // true, includes edges
   * console.log(bounds.containsPoint(100, 100)); // true, includes edges
   * ```
   * @param x - x coordinate to check
   * @param y - y coordinate to check
   * @returns True if the point is inside the bounds
   * @see {@link Bounds#isPositive} For valid bounds check
   * @see {@link Bounds#rectangle} For Rectangle representation
   */
  containsPoint(t, e) {
    return this.minX <= t && this.minY <= e && this.maxX >= t && this.maxY >= e;
  }
  /**
   * Returns a string representation of the bounds.
   * Useful for debugging and logging bounds information.
   * @example
   * ```ts
   * const bounds = new Bounds(0, 0, 100, 100);
   * console.log(bounds.toString()); // "[pixi.js:Bounds minX=0 minY=0 maxX=100 maxY=100 width=100 height=100]"
   * ```
   * @returns A string describing the bounds
   * @see {@link Bounds#copyFrom} For copying bounds
   * @see {@link Bounds#clone} For creating a new instance
   */
  toString() {
    return `[pixi.js:Bounds minX=${this.minX} minY=${this.minY} maxX=${this.maxX} maxY=${this.maxY} width=${this.width} height=${this.height}]`;
  }
  /**
   * Copies the bounds from another bounds object.
   * Useful for reusing bounds objects and avoiding allocations.
   * @example
   * ```ts
   * const sourceBounds = new Bounds(0, 0, 100, 100);
   * // Copy bounds
   * const targetBounds = new Bounds();
   * targetBounds.copyFrom(sourceBounds);
   * ```
   * @param bounds - The bounds to copy from
   * @returns This bounds object for chaining
   * @see {@link Bounds#clone} For creating new instances
   */
  copyFrom(t) {
    return this.minX = t.minX, this.minY = t.minY, this.maxX = t.maxX, this.maxY = t.maxY, this;
  }
}
var oy = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, vs = function(n) {
  return typeof n == "string" ? n.length > 0 : typeof n == "number";
}, $t = function(n, t, e) {
  return t === void 0 && (t = 0), e === void 0 && (e = Math.pow(10, t)), Math.round(e * n) / e + 0;
}, Oe = function(n, t, e) {
  return t === void 0 && (t = 0), e === void 0 && (e = 1), n > e ? e : n > t ? n : t;
}, Nf = function(n) {
  return (n = isFinite(n) ? n % 360 : 0) > 0 ? n : n + 360;
}, Gh = function(n) {
  return { r: Oe(n.r, 0, 255), g: Oe(n.g, 0, 255), b: Oe(n.b, 0, 255), a: Oe(n.a) };
}, ba = function(n) {
  return { r: $t(n.r), g: $t(n.g), b: $t(n.b), a: $t(n.a, 3) };
}, ay = /^#([0-9a-f]{3,8})$/i, Br = function(n) {
  var t = n.toString(16);
  return t.length < 2 ? "0" + t : t;
}, Lf = function(n) {
  var t = n.r, e = n.g, s = n.b, i = n.a, r = Math.max(t, e, s), o = r - Math.min(t, e, s), a = o ? r === t ? (e - s) / o : r === e ? 2 + (s - t) / o : 4 + (t - e) / o : 0;
  return { h: 60 * (a < 0 ? a + 6 : a), s: r ? o / r * 100 : 0, v: r / 255 * 100, a: i };
}, Vf = function(n) {
  var t = n.h, e = n.s, s = n.v, i = n.a;
  t = t / 360 * 6, e /= 100, s /= 100;
  var r = Math.floor(t), o = s * (1 - e), a = s * (1 - (t - r) * e), l = s * (1 - (1 - t + r) * e), c = r % 6;
  return { r: 255 * [s, a, o, o, l, s][c], g: 255 * [l, s, s, a, o, o][c], b: 255 * [o, o, l, s, s, a][c], a: i };
}, Wh = function(n) {
  return { h: Nf(n.h), s: Oe(n.s, 0, 100), l: Oe(n.l, 0, 100), a: Oe(n.a) };
}, $h = function(n) {
  return { h: $t(n.h), s: $t(n.s), l: $t(n.l), a: $t(n.a, 3) };
}, Hh = function(n) {
  return Vf((e = (t = n).s, { h: t.h, s: (e *= ((s = t.l) < 50 ? s : 100 - s) / 100) > 0 ? 2 * e / (s + e) * 100 : 0, v: s + e, a: t.a }));
  var t, e, s;
}, Wi = function(n) {
  return { h: (t = Lf(n)).h, s: (i = (200 - (e = t.s)) * (s = t.v) / 100) > 0 && i < 200 ? e * s / 100 / (i <= 100 ? i : 200 - i) * 100 : 0, l: i / 2, a: t.a };
  var t, e, s, i;
}, ly = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, cy = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, hy = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, uy = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, ol = { string: [[function(n) {
  var t = ay.exec(n);
  return t ? (n = t[1]).length <= 4 ? { r: parseInt(n[0] + n[0], 16), g: parseInt(n[1] + n[1], 16), b: parseInt(n[2] + n[2], 16), a: n.length === 4 ? $t(parseInt(n[3] + n[3], 16) / 255, 2) : 1 } : n.length === 6 || n.length === 8 ? { r: parseInt(n.substr(0, 2), 16), g: parseInt(n.substr(2, 2), 16), b: parseInt(n.substr(4, 2), 16), a: n.length === 8 ? $t(parseInt(n.substr(6, 2), 16) / 255, 2) : 1 } : null : null;
}, "hex"], [function(n) {
  var t = hy.exec(n) || uy.exec(n);
  return t ? t[2] !== t[4] || t[4] !== t[6] ? null : Gh({ r: Number(t[1]) / (t[2] ? 100 / 255 : 1), g: Number(t[3]) / (t[4] ? 100 / 255 : 1), b: Number(t[5]) / (t[6] ? 100 / 255 : 1), a: t[7] === void 0 ? 1 : Number(t[7]) / (t[8] ? 100 : 1) }) : null;
}, "rgb"], [function(n) {
  var t = ly.exec(n) || cy.exec(n);
  if (!t) return null;
  var e, s, i = Wh({ h: (e = t[1], s = t[2], s === void 0 && (s = "deg"), Number(e) * (oy[s] || 1)), s: Number(t[3]), l: Number(t[4]), a: t[5] === void 0 ? 1 : Number(t[5]) / (t[6] ? 100 : 1) });
  return Hh(i);
}, "hsl"]], object: [[function(n) {
  var t = n.r, e = n.g, s = n.b, i = n.a, r = i === void 0 ? 1 : i;
  return vs(t) && vs(e) && vs(s) ? Gh({ r: Number(t), g: Number(e), b: Number(s), a: Number(r) }) : null;
}, "rgb"], [function(n) {
  var t = n.h, e = n.s, s = n.l, i = n.a, r = i === void 0 ? 1 : i;
  if (!vs(t) || !vs(e) || !vs(s)) return null;
  var o = Wh({ h: Number(t), s: Number(e), l: Number(s), a: Number(r) });
  return Hh(o);
}, "hsl"], [function(n) {
  var t = n.h, e = n.s, s = n.v, i = n.a, r = i === void 0 ? 1 : i;
  if (!vs(t) || !vs(e) || !vs(s)) return null;
  var o = function(a) {
    return { h: Nf(a.h), s: Oe(a.s, 0, 100), v: Oe(a.v, 0, 100), a: Oe(a.a) };
  }({ h: Number(t), s: Number(e), v: Number(s), a: Number(r) });
  return Vf(o);
}, "hsv"]] }, jh = function(n, t) {
  for (var e = 0; e < t.length; e++) {
    var s = t[e][0](n);
    if (s) return [s, t[e][1]];
  }
  return [null, void 0];
}, dy = function(n) {
  return typeof n == "string" ? jh(n.trim(), ol.string) : typeof n == "object" && n !== null ? jh(n, ol.object) : [null, void 0];
}, wa = function(n, t) {
  var e = Wi(n);
  return { h: e.h, s: Oe(e.s + 100 * t, 0, 100), l: e.l, a: e.a };
}, Sa = function(n) {
  return (299 * n.r + 587 * n.g + 114 * n.b) / 1e3 / 255;
}, Xh = function(n, t) {
  var e = Wi(n);
  return { h: e.h, s: e.s, l: Oe(e.l + 100 * t, 0, 100), a: e.a };
}, al = function() {
  function n(t) {
    this.parsed = dy(t)[0], this.rgba = this.parsed || { r: 0, g: 0, b: 0, a: 1 };
  }
  return n.prototype.isValid = function() {
    return this.parsed !== null;
  }, n.prototype.brightness = function() {
    return $t(Sa(this.rgba), 2);
  }, n.prototype.isDark = function() {
    return Sa(this.rgba) < 0.5;
  }, n.prototype.isLight = function() {
    return Sa(this.rgba) >= 0.5;
  }, n.prototype.toHex = function() {
    return t = ba(this.rgba), e = t.r, s = t.g, i = t.b, o = (r = t.a) < 1 ? Br($t(255 * r)) : "", "#" + Br(e) + Br(s) + Br(i) + o;
    var t, e, s, i, r, o;
  }, n.prototype.toRgb = function() {
    return ba(this.rgba);
  }, n.prototype.toRgbString = function() {
    return t = ba(this.rgba), e = t.r, s = t.g, i = t.b, (r = t.a) < 1 ? "rgba(" + e + ", " + s + ", " + i + ", " + r + ")" : "rgb(" + e + ", " + s + ", " + i + ")";
    var t, e, s, i, r;
  }, n.prototype.toHsl = function() {
    return $h(Wi(this.rgba));
  }, n.prototype.toHslString = function() {
    return t = $h(Wi(this.rgba)), e = t.h, s = t.s, i = t.l, (r = t.a) < 1 ? "hsla(" + e + ", " + s + "%, " + i + "%, " + r + ")" : "hsl(" + e + ", " + s + "%, " + i + "%)";
    var t, e, s, i, r;
  }, n.prototype.toHsv = function() {
    return t = Lf(this.rgba), { h: $t(t.h), s: $t(t.s), v: $t(t.v), a: $t(t.a, 3) };
    var t;
  }, n.prototype.invert = function() {
    return rs({ r: 255 - (t = this.rgba).r, g: 255 - t.g, b: 255 - t.b, a: t.a });
    var t;
  }, n.prototype.saturate = function(t) {
    return t === void 0 && (t = 0.1), rs(wa(this.rgba, t));
  }, n.prototype.desaturate = function(t) {
    return t === void 0 && (t = 0.1), rs(wa(this.rgba, -t));
  }, n.prototype.grayscale = function() {
    return rs(wa(this.rgba, -1));
  }, n.prototype.lighten = function(t) {
    return t === void 0 && (t = 0.1), rs(Xh(this.rgba, t));
  }, n.prototype.darken = function(t) {
    return t === void 0 && (t = 0.1), rs(Xh(this.rgba, -t));
  }, n.prototype.rotate = function(t) {
    return t === void 0 && (t = 15), this.hue(this.hue() + t);
  }, n.prototype.alpha = function(t) {
    return typeof t == "number" ? rs({ r: (e = this.rgba).r, g: e.g, b: e.b, a: t }) : $t(this.rgba.a, 3);
    var e;
  }, n.prototype.hue = function(t) {
    var e = Wi(this.rgba);
    return typeof t == "number" ? rs({ h: t, s: e.s, l: e.l, a: e.a }) : $t(e.h);
  }, n.prototype.isEqual = function(t) {
    return this.toHex() === rs(t).toHex();
  }, n;
}(), rs = function(n) {
  return n instanceof al ? n : new al(n);
}, Yh = [], fy = function(n) {
  n.forEach(function(t) {
    Yh.indexOf(t) < 0 && (t(al, ol), Yh.push(t));
  });
};
function py(n, t) {
  var e = { white: "#ffffff", bisque: "#ffe4c4", blue: "#0000ff", cadetblue: "#5f9ea0", chartreuse: "#7fff00", chocolate: "#d2691e", coral: "#ff7f50", antiquewhite: "#faebd7", aqua: "#00ffff", azure: "#f0ffff", whitesmoke: "#f5f5f5", papayawhip: "#ffefd5", plum: "#dda0dd", blanchedalmond: "#ffebcd", black: "#000000", gold: "#ffd700", goldenrod: "#daa520", gainsboro: "#dcdcdc", cornsilk: "#fff8dc", cornflowerblue: "#6495ed", burlywood: "#deb887", aquamarine: "#7fffd4", beige: "#f5f5dc", crimson: "#dc143c", cyan: "#00ffff", darkblue: "#00008b", darkcyan: "#008b8b", darkgoldenrod: "#b8860b", darkkhaki: "#bdb76b", darkgray: "#a9a9a9", darkgreen: "#006400", darkgrey: "#a9a9a9", peachpuff: "#ffdab9", darkmagenta: "#8b008b", darkred: "#8b0000", darkorchid: "#9932cc", darkorange: "#ff8c00", darkslateblue: "#483d8b", gray: "#808080", darkslategray: "#2f4f4f", darkslategrey: "#2f4f4f", deeppink: "#ff1493", deepskyblue: "#00bfff", wheat: "#f5deb3", firebrick: "#b22222", floralwhite: "#fffaf0", ghostwhite: "#f8f8ff", darkviolet: "#9400d3", magenta: "#ff00ff", green: "#008000", dodgerblue: "#1e90ff", grey: "#808080", honeydew: "#f0fff0", hotpink: "#ff69b4", blueviolet: "#8a2be2", forestgreen: "#228b22", lawngreen: "#7cfc00", indianred: "#cd5c5c", indigo: "#4b0082", fuchsia: "#ff00ff", brown: "#a52a2a", maroon: "#800000", mediumblue: "#0000cd", lightcoral: "#f08080", darkturquoise: "#00ced1", lightcyan: "#e0ffff", ivory: "#fffff0", lightyellow: "#ffffe0", lightsalmon: "#ffa07a", lightseagreen: "#20b2aa", linen: "#faf0e6", mediumaquamarine: "#66cdaa", lemonchiffon: "#fffacd", lime: "#00ff00", khaki: "#f0e68c", mediumseagreen: "#3cb371", limegreen: "#32cd32", mediumspringgreen: "#00fa9a", lightskyblue: "#87cefa", lightblue: "#add8e6", midnightblue: "#191970", lightpink: "#ffb6c1", mistyrose: "#ffe4e1", moccasin: "#ffe4b5", mintcream: "#f5fffa", lightslategray: "#778899", lightslategrey: "#778899", navajowhite: "#ffdead", navy: "#000080", mediumvioletred: "#c71585", powderblue: "#b0e0e6", palegoldenrod: "#eee8aa", oldlace: "#fdf5e6", paleturquoise: "#afeeee", mediumturquoise: "#48d1cc", mediumorchid: "#ba55d3", rebeccapurple: "#663399", lightsteelblue: "#b0c4de", mediumslateblue: "#7b68ee", thistle: "#d8bfd8", tan: "#d2b48c", orchid: "#da70d6", mediumpurple: "#9370db", purple: "#800080", pink: "#ffc0cb", skyblue: "#87ceeb", springgreen: "#00ff7f", palegreen: "#98fb98", red: "#ff0000", yellow: "#ffff00", slateblue: "#6a5acd", lavenderblush: "#fff0f5", peru: "#cd853f", palevioletred: "#db7093", violet: "#ee82ee", teal: "#008080", slategray: "#708090", slategrey: "#708090", aliceblue: "#f0f8ff", darkseagreen: "#8fbc8f", darkolivegreen: "#556b2f", greenyellow: "#adff2f", seagreen: "#2e8b57", seashell: "#fff5ee", tomato: "#ff6347", silver: "#c0c0c0", sienna: "#a0522d", lavender: "#e6e6fa", lightgreen: "#90ee90", orange: "#ffa500", orangered: "#ff4500", steelblue: "#4682b4", royalblue: "#4169e1", turquoise: "#40e0d0", yellowgreen: "#9acd32", salmon: "#fa8072", saddlebrown: "#8b4513", sandybrown: "#f4a460", rosybrown: "#bc8f8f", darksalmon: "#e9967a", lightgoldenrodyellow: "#fafad2", snow: "#fffafa", lightgrey: "#d3d3d3", lightgray: "#d3d3d3", dimgray: "#696969", dimgrey: "#696969", olivedrab: "#6b8e23", olive: "#808000" }, s = {};
  for (var i in e) s[e[i]] = i;
  var r = {};
  n.prototype.toName = function(o) {
    if (!(this.rgba.a || this.rgba.r || this.rgba.g || this.rgba.b)) return "transparent";
    var a, l, c = s[this.toHex()];
    if (c) return c;
    if (o?.closest) {
      var h = this.toRgb(), u = 1 / 0, d = "black";
      if (!r.length) for (var f in e) r[f] = new n(e[f]).toRgb();
      for (var p in e) {
        var g = (a = h, l = r[p], Math.pow(a.r - l.r, 2) + Math.pow(a.g - l.g, 2) + Math.pow(a.b - l.b, 2));
        g < u && (u = g, d = p);
      }
      return d;
    }
  }, t.string.push([function(o) {
    var a = o.toLowerCase(), l = a === "transparent" ? "#0000" : e[a];
    return l ? new n(l).toRgb() : null;
  }, "name"]);
}
fy([py]);
const Yn = class Vi {
  /**
   * @param {ColorSource} value - Optional value to use, if not provided, white is used.
   */
  constructor(t = 16777215) {
    this._value = null, this._components = new Float32Array(4), this._components.fill(1), this._int = 16777215, this.value = t;
  }
  /**
   * Get the red component of the color, normalized between 0 and 1.
   * @example
   * ```ts
   * const color = new Color('red');
   * console.log(color.red); // 1
   *
   * const green = new Color('#00ff00');
   * console.log(green.red); // 0
   * ```
   */
  get red() {
    return this._components[0];
  }
  /**
   * Get the green component of the color, normalized between 0 and 1.
   * @example
   * ```ts
   * const color = new Color('lime');
   * console.log(color.green); // 1
   *
   * const red = new Color('#ff0000');
   * console.log(red.green); // 0
   * ```
   */
  get green() {
    return this._components[1];
  }
  /**
   * Get the blue component of the color, normalized between 0 and 1.
   * @example
   * ```ts
   * const color = new Color('blue');
   * console.log(color.blue); // 1
   *
   * const yellow = new Color('#ffff00');
   * console.log(yellow.blue); // 0
   * ```
   */
  get blue() {
    return this._components[2];
  }
  /**
   * Get the alpha component of the color, normalized between 0 and 1.
   * @example
   * ```ts
   * const color = new Color('red');
   * console.log(color.alpha); // 1 (fully opaque)
   *
   * const transparent = new Color('rgba(255, 0, 0, 0.5)');
   * console.log(transparent.alpha); // 0.5 (semi-transparent)
   * ```
   */
  get alpha() {
    return this._components[3];
  }
  /**
   * Sets the color value and returns the instance for chaining.
   *
   * This is a chainable version of setting the `value` property.
   * @param value - The color to set. Accepts various formats:
   * - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
   * - RGB/RGBA values (arrays, objects)
   * - CSS color names
   * - HSL/HSLA values
   * - HSV/HSVA values
   * @returns The Color instance for chaining
   * @example
   * ```ts
   * // Basic usage
   * const color = new Color();
   * color.setValue('#ff0000')
   *     .setAlpha(0.5)
   *     .premultiply(0.8);
   *
   * // Different formats
   * color.setValue(0xff0000);          // Hex number
   * color.setValue('#ff0000');         // Hex string
   * color.setValue([1, 0, 0]);         // RGB array
   * color.setValue([1, 0, 0, 0.5]);    // RGBA array
   * color.setValue({ r: 1, g: 0, b: 0 }); // RGB object
   *
   * // Copy from another color
   * const red = new Color('red');
   * color.setValue(red);
   * ```
   * @throws {Error} If the color value is invalid or null
   * @see {@link Color.value} For the underlying value property
   */
  setValue(t) {
    return this.value = t, this;
  }
  /**
   * The current color source. This property allows getting and setting the color value
   * while preserving the original format where possible.
   * @remarks
   * When setting:
   * - Setting to a `Color` instance copies its source and components
   * - Setting to other valid sources normalizes and stores the value
   * - Setting to `null` throws an Error
   * - The color remains unchanged if normalization fails
   *
   * When getting:
   * - Returns `null` if color was modified by {@link Color.multiply} or {@link Color.premultiply}
   * - Otherwise returns the original color source
   * @example
   * ```ts
   * // Setting different color formats
   * const color = new Color();
   *
   * color.value = 0xff0000;         // Hex number
   * color.value = '#ff0000';        // Hex string
   * color.value = [1, 0, 0];        // RGB array
   * color.value = [1, 0, 0, 0.5];   // RGBA array
   * color.value = { r: 1, g: 0, b: 0 }; // RGB object
   *
   * // Copying from another color
   * const red = new Color('red');
   * color.value = red;  // Copies red's components
   *
   * // Getting the value
   * console.log(color.value);  // Returns original format
   *
   * // After modifications
   * color.multiply([0.5, 0.5, 0.5]);
   * console.log(color.value);  // Returns null
   * ```
   * @throws {Error} When attempting to set `null`
   */
  set value(t) {
    if (t instanceof Vi)
      this._value = this._cloneSource(t._value), this._int = t._int, this._components.set(t._components);
    else {
      if (t === null)
        throw new Error("Cannot set Color#value to null");
      (this._value === null || !this._isSourceEqual(this._value, t)) && (this._value = this._cloneSource(t), this._normalize(this._value));
    }
  }
  get value() {
    return this._value;
  }
  /**
   * Copy a color source internally.
   * @param value - Color source
   */
  _cloneSource(t) {
    return typeof t == "string" || typeof t == "number" || t instanceof Number || t === null ? t : Array.isArray(t) || ArrayBuffer.isView(t) ? t.slice(0) : typeof t == "object" && t !== null ? { ...t } : t;
  }
  /**
   * Equality check for color sources.
   * @param value1 - First color source
   * @param value2 - Second color source
   * @returns `true` if the color sources are equal, `false` otherwise.
   */
  _isSourceEqual(t, e) {
    const s = typeof t;
    if (s !== typeof e)
      return !1;
    if (s === "number" || s === "string" || t instanceof Number)
      return t === e;
    if (Array.isArray(t) && Array.isArray(e) || ArrayBuffer.isView(t) && ArrayBuffer.isView(e))
      return t.length !== e.length ? !1 : t.every((r, o) => r === e[o]);
    if (t !== null && e !== null) {
      const r = Object.keys(t), o = Object.keys(e);
      return r.length !== o.length ? !1 : r.every((a) => t[a] === e[a]);
    }
    return t === e;
  }
  /**
   * Convert to a RGBA color object with normalized components (0-1).
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // Convert colors to RGBA objects
   * new Color('white').toRgba();     // returns { r: 1, g: 1, b: 1, a: 1 }
   * new Color('#ff0000').toRgba();   // returns { r: 1, g: 0, b: 0, a: 1 }
   *
   * // With transparency
   * new Color('rgba(255,0,0,0.5)').toRgba(); // returns { r: 1, g: 0, b: 0, a: 0.5 }
   * ```
   * @returns An RGBA object with normalized components
   */
  toRgba() {
    const [t, e, s, i] = this._components;
    return { r: t, g: e, b: s, a: i };
  }
  /**
   * Convert to a RGB color object with normalized components (0-1).
   *
   * Alpha component is omitted in the output.
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // Convert colors to RGB objects
   * new Color('white').toRgb();     // returns { r: 1, g: 1, b: 1 }
   * new Color('#ff0000').toRgb();   // returns { r: 1, g: 0, b: 0 }
   *
   * // Alpha is ignored
   * new Color('rgba(255,0,0,0.5)').toRgb(); // returns { r: 1, g: 0, b: 0 }
   * ```
   * @returns An RGB object with normalized components
   */
  toRgb() {
    const [t, e, s] = this._components;
    return { r: t, g: e, b: s };
  }
  /**
   * Convert to a CSS-style rgba string representation.
   *
   * RGB components are scaled to 0-255 range, alpha remains 0-1.
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // Convert colors to RGBA strings
   * new Color('white').toRgbaString();     // returns "rgba(255,255,255,1)"
   * new Color('#ff0000').toRgbaString();   // returns "rgba(255,0,0,1)"
   *
   * // With transparency
   * new Color([1, 0, 0, 0.5]).toRgbaString(); // returns "rgba(255,0,0,0.5)"
   * ```
   * @returns A CSS-compatible rgba string
   */
  toRgbaString() {
    const [t, e, s] = this.toUint8RgbArray();
    return `rgba(${t},${e},${s},${this.alpha})`;
  }
  /**
   * Convert to an [R, G, B] array of clamped uint8 values (0 to 255).
   * @param {number[]|Uint8Array|Uint8ClampedArray} [out] - Optional output array. If not provided,
   * a cached array will be used and returned.
   * @returns Array containing RGB components as integers between 0-255
   * @example
   * ```ts
   * // Basic usage
   * new Color('white').toUint8RgbArray(); // returns [255, 255, 255]
   * new Color('#ff0000').toUint8RgbArray(); // returns [255, 0, 0]
   *
   * // Using custom output array
   * const rgb = new Uint8Array(3);
   * new Color('blue').toUint8RgbArray(rgb); // rgb is now [0, 0, 255]
   *
   * // Using different array types
   * new Color('red').toUint8RgbArray(new Uint8ClampedArray(3)); // [255, 0, 0]
   * new Color('red').toUint8RgbArray([]); // [255, 0, 0]
   * ```
   * @remarks
   * - Output values are always clamped between 0-255
   * - Alpha component is not included in output
   * - Reuses internal cache array if no output array provided
   */
  toUint8RgbArray(t) {
    const [e, s, i] = this._components;
    return this._arrayRgb || (this._arrayRgb = []), t || (t = this._arrayRgb), t[0] = Math.round(e * 255), t[1] = Math.round(s * 255), t[2] = Math.round(i * 255), t;
  }
  /**
   * Convert to an [R, G, B, A] array of normalized floats (numbers from 0.0 to 1.0).
   * @param {number[]|Float32Array} [out] - Optional output array. If not provided,
   * a cached array will be used and returned.
   * @returns Array containing RGBA components as floats between 0-1
   * @example
   * ```ts
   * // Basic usage
   * new Color('white').toArray();  // returns [1, 1, 1, 1]
   * new Color('red').toArray();    // returns [1, 0, 0, 1]
   *
   * // With alpha
   * new Color('rgba(255,0,0,0.5)').toArray(); // returns [1, 0, 0, 0.5]
   *
   * // Using custom output array
   * const rgba = new Float32Array(4);
   * new Color('blue').toArray(rgba); // rgba is now [0, 0, 1, 1]
   * ```
   * @remarks
   * - Output values are normalized between 0-1
   * - Includes alpha component as the fourth value
   * - Reuses internal cache array if no output array provided
   */
  toArray(t) {
    this._arrayRgba || (this._arrayRgba = []), t || (t = this._arrayRgba);
    const [e, s, i, r] = this._components;
    return t[0] = e, t[1] = s, t[2] = i, t[3] = r, t;
  }
  /**
   * Convert to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0).
   * @param {number[]|Float32Array} [out] - Optional output array. If not provided,
   * a cached array will be used and returned.
   * @returns Array containing RGB components as floats between 0-1
   * @example
   * ```ts
   * // Basic usage
   * new Color('white').toRgbArray(); // returns [1, 1, 1]
   * new Color('red').toRgbArray();   // returns [1, 0, 0]
   *
   * // Using custom output array
   * const rgb = new Float32Array(3);
   * new Color('blue').toRgbArray(rgb); // rgb is now [0, 0, 1]
   * ```
   * @remarks
   * - Output values are normalized between 0-1
   * - Alpha component is omitted from output
   * - Reuses internal cache array if no output array provided
   */
  toRgbArray(t) {
    this._arrayRgb || (this._arrayRgb = []), t || (t = this._arrayRgb);
    const [e, s, i] = this._components;
    return t[0] = e, t[1] = s, t[2] = i, t;
  }
  /**
   * Convert to a hexadecimal number.
   * @returns The color as a 24-bit RGB integer
   * @example
   * ```ts
   * // Basic usage
   * new Color('white').toNumber(); // returns 0xffffff
   * new Color('red').toNumber();   // returns 0xff0000
   *
   * // Store as hex
   * const color = new Color('blue');
   * const hex = color.toNumber(); // 0x0000ff
   * ```
   */
  toNumber() {
    return this._int;
  }
  /**
   * Convert to a BGR number.
   *
   * Useful for platforms that expect colors in BGR format.
   * @returns The color as a 24-bit BGR integer
   * @example
   * ```ts
   * // Convert RGB to BGR
   * new Color(0xffcc99).toBgrNumber(); // returns 0x99ccff
   *
   * // Common use case: platform-specific color format
   * const color = new Color('orange');
   * const bgrColor = color.toBgrNumber(); // Color with swapped R/B channels
   * ```
   * @remarks
   * This swaps the red and blue channels compared to the normal RGB format:
   * - RGB 0xRRGGBB becomes BGR 0xBBGGRR
   */
  toBgrNumber() {
    const [t, e, s] = this.toUint8RgbArray();
    return (s << 16) + (e << 8) + t;
  }
  /**
   * Convert to a hexadecimal number in little endian format (e.g., BBGGRR).
   *
   * Useful for platforms that expect colors in little endian byte order.
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // Convert RGB color to little endian format
   * new Color(0xffcc99).toLittleEndianNumber(); // returns 0x99ccff
   *
   * // Common use cases:
   * const color = new Color('orange');
   * const leColor = color.toLittleEndianNumber(); // Swaps byte order for LE systems
   *
   * // Multiple conversions
   * const colors = {
   *     normal: 0xffcc99,
   *     littleEndian: new Color(0xffcc99).toLittleEndianNumber(), // 0x99ccff
   *     backToNormal: new Color(0x99ccff).toLittleEndianNumber()  // 0xffcc99
   * };
   * ```
   * @remarks
   * - Swaps R and B channels in the color value
   * - RGB 0xRRGGBB becomes 0xBBGGRR
   * - Useful for systems that use little endian byte order
   * - Can be used to convert back and forth between formats
   * @returns The color as a number in little endian format (BBGGRR)
   * @see {@link Color.toBgrNumber} For BGR format without byte swapping
   */
  toLittleEndianNumber() {
    const t = this._int;
    return (t >> 16) + (t & 65280) + ((t & 255) << 16);
  }
  /**
   * Multiply with another color.
   *
   * This action is destructive and modifies the original color.
   * @param {ColorSource} value - The color to multiply by. Accepts any valid color format:
   * - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
   * - RGB/RGBA arrays ([1, 0, 0], [1, 0, 0, 1])
   * - Color objects ({ r: 1, g: 0, b: 0 })
   * - CSS color names ('red', 'blue')
   * @returns this - The Color instance for chaining
   * @example
   * ```ts
   * // Basic multiplication
   * const color = new Color('#ff0000');
   * color.multiply(0x808080); // 50% darker red
   *
   * // With transparency
   * color.multiply([1, 1, 1, 0.5]); // 50% transparent
   *
   * // Chain operations
   * color
   *     .multiply('#808080')
   *     .multiply({ r: 1, g: 1, b: 1, a: 0.5 });
   * ```
   * @remarks
   * - Multiplies each RGB component and alpha separately
   * - Values are clamped between 0-1
   * - Original color format is lost (value becomes null)
   * - Operation cannot be undone
   */
  multiply(t) {
    const [e, s, i, r] = Vi._temp.setValue(t)._components;
    return this._components[0] *= e, this._components[1] *= s, this._components[2] *= i, this._components[3] *= r, this._refreshInt(), this._value = null, this;
  }
  /**
   * Converts color to a premultiplied alpha format.
   *
   * This action is destructive and modifies the original color.
   * @param alpha - The alpha value to multiply by (0-1)
   * @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
   * @returns {Color} The Color instance for chaining
   * @example
   * ```ts
   * // Basic premultiplication
   * const color = new Color('red');
   * color.premultiply(0.5); // 50% transparent red with premultiplied RGB
   *
   * // Alpha only (RGB unchanged)
   * color.premultiply(0.5, false); // 50% transparent, original RGB
   *
   * // Chain with other operations
   * color
   *     .multiply(0x808080)
   *     .premultiply(0.5)
   *     .toNumber();
   * ```
   * @remarks
   * - RGB channels are multiplied by alpha when applyToRGB is true
   * - Alpha is always set to the provided value
   * - Values are clamped between 0-1
   * - Original color format is lost (value becomes null)
   * - Operation cannot be undone
   */
  premultiply(t, e = !0) {
    return e && (this._components[0] *= t, this._components[1] *= t, this._components[2] *= t), this._components[3] = t, this._refreshInt(), this._value = null, this;
  }
  /**
   * Returns the color as a 32-bit premultiplied alpha integer.
   *
   * Format: 0xAARRGGBB
   * @param {number} alpha - The alpha value to multiply by (0-1)
   * @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
   * @returns {number} The premultiplied color as a 32-bit integer
   * @example
   * ```ts
   * // Convert to premultiplied format
   * const color = new Color('red');
   *
   * // Full opacity (0xFFRRGGBB)
   * color.toPremultiplied(1.0); // 0xFFFF0000
   *
   * // 50% transparency with premultiplied RGB
   * color.toPremultiplied(0.5); // 0x7F7F0000
   *
   * // 50% transparency without RGB premultiplication
   * color.toPremultiplied(0.5, false); // 0x7FFF0000
   * ```
   * @remarks
   * - Returns full opacity (0xFF000000) when alpha is 1.0
   * - Returns 0 when alpha is 0.0 and applyToRGB is true
   * - RGB values are rounded during premultiplication
   */
  toPremultiplied(t, e = !0) {
    if (t === 1)
      return (255 << 24) + this._int;
    if (t === 0)
      return e ? 0 : this._int;
    let s = this._int >> 16 & 255, i = this._int >> 8 & 255, r = this._int & 255;
    return e && (s = s * t + 0.5 | 0, i = i * t + 0.5 | 0, r = r * t + 0.5 | 0), (t * 255 << 24) + (s << 16) + (i << 8) + r;
  }
  /**
   * Convert to a hexadecimal string (6 characters).
   * @returns A CSS-compatible hex color string (e.g., "#ff0000")
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // Basic colors
   * new Color('red').toHex();    // returns "#ff0000"
   * new Color('white').toHex();  // returns "#ffffff"
   * new Color('black').toHex();  // returns "#000000"
   *
   * // From different formats
   * new Color(0xff0000).toHex(); // returns "#ff0000"
   * new Color([1, 0, 0]).toHex(); // returns "#ff0000"
   * new Color({ r: 1, g: 0, b: 0 }).toHex(); // returns "#ff0000"
   * ```
   * @remarks
   * - Always returns a 6-character hex string
   * - Includes leading "#" character
   * - Alpha channel is ignored
   * - Values are rounded to nearest hex value
   */
  toHex() {
    const t = this._int.toString(16);
    return `#${"000000".substring(0, 6 - t.length) + t}`;
  }
  /**
   * Convert to a hexadecimal string with alpha (8 characters).
   * @returns A CSS-compatible hex color string with alpha (e.g., "#ff0000ff")
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // Fully opaque colors
   * new Color('red').toHexa();   // returns "#ff0000ff"
   * new Color('white').toHexa(); // returns "#ffffffff"
   *
   * // With transparency
   * new Color('rgba(255, 0, 0, 0.5)').toHexa(); // returns "#ff00007f"
   * new Color([1, 0, 0, 0]).toHexa(); // returns "#ff000000"
   * ```
   * @remarks
   * - Returns an 8-character hex string
   * - Includes leading "#" character
   * - Alpha is encoded in last two characters
   * - Values are rounded to nearest hex value
   */
  toHexa() {
    const e = Math.round(this._components[3] * 255).toString(16);
    return this.toHex() + "00".substring(0, 2 - e.length) + e;
  }
  /**
   * Set alpha (transparency) value while preserving color components.
   *
   * Provides a chainable interface for setting alpha.
   * @param alpha - Alpha value between 0 (fully transparent) and 1 (fully opaque)
   * @returns The Color instance for chaining
   * @example
   * ```ts
   * // Basic alpha setting
   * const color = new Color('red');
   * color.setAlpha(0.5);  // 50% transparent red
   *
   * // Chain with other operations
   * color
   *     .setValue('#ff0000')
   *     .setAlpha(0.8)    // 80% opaque
   *     .premultiply(0.5); // Further modify alpha
   *
   * // Reset to fully opaque
   * color.setAlpha(1);
   * ```
   * @remarks
   * - Alpha value is clamped between 0-1
   * - Can be chained with other color operations
   */
  setAlpha(t) {
    return this._components[3] = this._clamp(t), this;
  }
  /**
   * Normalize the input value into rgba
   * @param value - Input value
   */
  _normalize(t) {
    let e, s, i, r;
    if ((typeof t == "number" || t instanceof Number) && t >= 0 && t <= 16777215) {
      const o = t;
      e = (o >> 16 & 255) / 255, s = (o >> 8 & 255) / 255, i = (o & 255) / 255, r = 1;
    } else if ((Array.isArray(t) || t instanceof Float32Array) && t.length >= 3 && t.length <= 4)
      t = this._clamp(t), [e, s, i, r = 1] = t;
    else if ((t instanceof Uint8Array || t instanceof Uint8ClampedArray) && t.length >= 3 && t.length <= 4)
      t = this._clamp(t, 0, 255), [e, s, i, r = 255] = t, e /= 255, s /= 255, i /= 255, r /= 255;
    else if (typeof t == "string" || typeof t == "object") {
      if (typeof t == "string") {
        const a = Vi.HEX_PATTERN.exec(t);
        a && (t = `#${a[2]}`);
      }
      const o = rs(t);
      o.isValid() && ({ r: e, g: s, b: i, a: r } = o.rgba, e /= 255, s /= 255, i /= 255);
    }
    if (e !== void 0)
      this._components[0] = e, this._components[1] = s, this._components[2] = i, this._components[3] = r, this._refreshInt();
    else
      throw new Error(`Unable to convert color ${t}`);
  }
  /** Refresh the internal color rgb number */
  _refreshInt() {
    this._clamp(this._components);
    const [t, e, s] = this._components;
    this._int = (t * 255 << 16) + (e * 255 << 8) + (s * 255 | 0);
  }
  /**
   * Clamps values to a range. Will override original values
   * @param value - Value(s) to clamp
   * @param min - Minimum value
   * @param max - Maximum value
   */
  _clamp(t, e = 0, s = 1) {
    return typeof t == "number" ? Math.min(Math.max(t, e), s) : (t.forEach((i, r) => {
      t[r] = Math.min(Math.max(i, e), s);
    }), t);
  }
  /**
   * Check if a value can be interpreted as a valid color format.
   * Supports all color formats that can be used with the Color class.
   * @param value - Value to check
   * @returns True if the value can be used as a color
   * @example
   * ```ts
   * import { Color } from 'pixi.js';
   *
   * // CSS colors and hex values
   * Color.isColorLike('red');          // true
   * Color.isColorLike('#ff0000');      // true
   * Color.isColorLike(0xff0000);       // true
   *
   * // Arrays (RGB/RGBA)
   * Color.isColorLike([1, 0, 0]);      // true
   * Color.isColorLike([1, 0, 0, 0.5]); // true
   *
   * // TypedArrays
   * Color.isColorLike(new Float32Array([1, 0, 0]));          // true
   * Color.isColorLike(new Uint8Array([255, 0, 0]));          // true
   * Color.isColorLike(new Uint8ClampedArray([255, 0, 0]));   // true
   *
   * // Object formats
   * Color.isColorLike({ r: 1, g: 0, b: 0 });            // true (RGB)
   * Color.isColorLike({ r: 1, g: 0, b: 0, a: 0.5 });    // true (RGBA)
   * Color.isColorLike({ h: 0, s: 100, l: 50 });         // true (HSL)
   * Color.isColorLike({ h: 0, s: 100, l: 50, a: 0.5 }); // true (HSLA)
   * Color.isColorLike({ h: 0, s: 100, v: 100 });        // true (HSV)
   * Color.isColorLike({ h: 0, s: 100, v: 100, a: 0.5 });// true (HSVA)
   *
   * // Color instances
   * Color.isColorLike(new Color('red')); // true
   *
   * // Invalid values
   * Color.isColorLike(null);           // false
   * Color.isColorLike(undefined);      // false
   * Color.isColorLike({});             // false
   * Color.isColorLike([]);             // false
   * Color.isColorLike('not-a-color');  // false
   * ```
   * @remarks
   * Checks for the following formats:
   * - Numbers (0x000000 to 0xffffff)
   * - CSS color strings
   * - RGB/RGBA arrays and objects
   * - HSL/HSLA objects
   * - HSV/HSVA objects
   * - TypedArrays (Float32Array, Uint8Array, Uint8ClampedArray)
   * - Color instances
   * @see {@link ColorSource} For supported color format types
   * @see {@link Color.setValue} For setting color values
   * @category utility
   */
  static isColorLike(t) {
    return typeof t == "number" || typeof t == "string" || t instanceof Number || t instanceof Vi || Array.isArray(t) || t instanceof Uint8Array || t instanceof Uint8ClampedArray || t instanceof Float32Array || t.r !== void 0 && t.g !== void 0 && t.b !== void 0 || t.r !== void 0 && t.g !== void 0 && t.b !== void 0 && t.a !== void 0 || t.h !== void 0 && t.s !== void 0 && t.l !== void 0 || t.h !== void 0 && t.s !== void 0 && t.l !== void 0 && t.a !== void 0 || t.h !== void 0 && t.s !== void 0 && t.v !== void 0 || t.h !== void 0 && t.s !== void 0 && t.v !== void 0 && t.a !== void 0;
  }
};
Yn.shared = new Yn();
Yn._temp = new Yn();
Yn.HEX_PATTERN = /^(#|0x)?(([a-f0-9]{3}){1,2}([a-f0-9]{2})?)$/i;
let Bt = Yn;
const my = {
  cullArea: null,
  cullable: !1,
  cullableChildren: !0
};
let Ta = 0;
const Zh = 500;
function Ht(...n) {
  Ta !== Zh && (Ta++, Ta === Zh ? console.warn("PixiJS Warning: too many warnings, no more warnings will be reported to the console by PixiJS.") : console.warn("PixiJS Warning: ", ...n));
}
class Xl {
  /**
   * Constructs a new Pool.
   * @param ClassType - The constructor of the items in the pool.
   * @param {number} [initialSize] - The initial size of the pool.
   */
  constructor(t, e) {
    this._pool = [], this._count = 0, this._index = 0, this._classType = t, e && this.prepopulate(e);
  }
  /**
   * Prepopulates the pool with a given number of items.
   * @param total - The number of items to add to the pool.
   */
  prepopulate(t) {
    for (let e = 0; e < t; e++)
      this._pool[this._index++] = new this._classType();
    this._count += t;
  }
  /**
   * Gets an item from the pool. Calls the item's `init` method if it exists.
   * If there are no items left in the pool, a new one will be created.
   * @param {unknown} [data] - Optional data to pass to the item's constructor.
   * @returns {T} The item from the pool.
   */
  get(t) {
    let e;
    return this._index > 0 ? e = this._pool[--this._index] : e = new this._classType(), e.init?.(t), e;
  }
  /**
   * Returns an item to the pool. Calls the item's `reset` method if it exists.
   * @param {T} item - The item to return to the pool.
   */
  return(t) {
    t.reset?.(), this._pool[this._index++] = t;
  }
  /**
   * Gets the number of items in the pool.
   * @readonly
   */
  get totalSize() {
    return this._count;
  }
  /**
   * Gets the number of items in the pool that are free to use without needing to create more.
   * @readonly
   */
  get totalFree() {
    return this._index;
  }
  /**
   * Gets the number of items in the pool that are currently in use.
   * @readonly
   */
  get totalUsed() {
    return this._count - this._index;
  }
  /** clears the pool - mainly used for debugging! */
  clear() {
    this._pool.length = 0, this._index = 0;
  }
}
class gy {
  constructor() {
    this._poolsByClass = /* @__PURE__ */ new Map();
  }
  /**
   * Prepopulates a specific pool with a given number of items.
   * @template T The type of items in the pool. Must extend PoolItem.
   * @param {PoolItemConstructor<T>} Class - The constructor of the items in the pool.
   * @param {number} total - The number of items to add to the pool.
   */
  prepopulate(t, e) {
    this.getPool(t).prepopulate(e);
  }
  /**
   * Gets an item from a specific pool.
   * @template T The type of items in the pool. Must extend PoolItem.
   * @param {PoolItemConstructor<T>} Class - The constructor of the items in the pool.
   * @param {unknown} [data] - Optional data to pass to the item's constructor.
   * @returns {T} The item from the pool.
   */
  get(t, e) {
    return this.getPool(t).get(e);
  }
  /**
   * Returns an item to its respective pool.
   * @param {PoolItem} item - The item to return to the pool.
   */
  return(t) {
    this.getPool(t.constructor).return(t);
  }
  /**
   * Gets a specific pool based on the class type.
   * @template T The type of items in the pool. Must extend PoolItem.
   * @param {PoolItemConstructor<T>} ClassType - The constructor of the items in the pool.
   * @returns {Pool<T>} The pool of the given class type.
   */
  getPool(t) {
    return this._poolsByClass.has(t) || this._poolsByClass.set(t, new Xl(t)), this._poolsByClass.get(t);
  }
  /** gets the usage stats of each pool in the system */
  stats() {
    const t = {};
    return this._poolsByClass.forEach((e) => {
      const s = t[e._classType.name] ? e._classType.name + e._classType.ID : e._classType.name;
      t[s] = {
        free: e.totalFree,
        used: e.totalUsed,
        size: e.totalSize
      };
    }), t;
  }
}
const Ms = new gy(), yy = {
  get isCachedAsTexture() {
    return !!this.renderGroup?.isCachedAsTexture;
  },
  cacheAsTexture(n) {
    typeof n == "boolean" && n === !1 ? this.disableRenderGroup() : (this.enableRenderGroup(), this.renderGroup.enableCacheAsTexture(n === !0 ? {} : n));
  },
  updateCacheTexture() {
    this.renderGroup?.updateCacheTexture();
  },
  get cacheAsBitmap() {
    return this.isCachedAsTexture;
  },
  set cacheAsBitmap(n) {
    ct("v8.6.0", "cacheAsBitmap is deprecated, use cacheAsTexture instead."), this.cacheAsTexture(n);
  }
};
function xy(n, t, e) {
  const s = n.length;
  let i;
  if (t >= s || e === 0)
    return;
  e = t + e > s ? s - t : e;
  const r = s - e;
  for (i = t; i < r; ++i)
    n[i] = n[i + e];
  n.length = r;
}
const _y = {
  allowChildren: !0,
  removeChildren(n = 0, t) {
    const e = t ?? this.children.length, s = e - n, i = [];
    if (s > 0 && s <= e) {
      for (let o = e - 1; o >= n; o--) {
        const a = this.children[o];
        a && (i.push(a), a.parent = null);
      }
      xy(this.children, n, e);
      const r = this.renderGroup || this.parentRenderGroup;
      r && r.removeChildren(i);
      for (let o = 0; o < i.length; ++o) {
        const a = i[o];
        a.parentRenderLayer?.detach(a), this.emit("childRemoved", a, this, o), i[o].emit("removed", this);
      }
      return i.length > 0 && this._didViewChangeTick++, i;
    } else if (s === 0 && this.children.length === 0)
      return i;
    throw new RangeError("removeChildren: numeric values are outside the acceptable range.");
  },
  removeChildAt(n) {
    const t = this.getChildAt(n);
    return this.removeChild(t);
  },
  getChildAt(n) {
    if (n < 0 || n >= this.children.length)
      throw new Error(`getChildAt: Index (${n}) does not exist.`);
    return this.children[n];
  },
  setChildIndex(n, t) {
    if (t < 0 || t >= this.children.length)
      throw new Error(`The index ${t} supplied is out of bounds ${this.children.length}`);
    this.getChildIndex(n), this.addChildAt(n, t);
  },
  getChildIndex(n) {
    const t = this.children.indexOf(n);
    if (t === -1)
      throw new Error("The supplied Container must be a child of the caller");
    return t;
  },
  addChildAt(n, t) {
    this.allowChildren || ct(kt, "addChildAt: Only Containers will be allowed to add children in v8.0.0");
    const { children: e } = this;
    if (t < 0 || t > e.length)
      throw new Error(`${n}addChildAt: The index ${t} supplied is out of bounds ${e.length}`);
    if (n.parent) {
      const i = n.parent.children.indexOf(n);
      if (n.parent === this && i === t)
        return n;
      i !== -1 && n.parent.children.splice(i, 1);
    }
    t === e.length ? e.push(n) : e.splice(t, 0, n), n.parent = this, n.didChange = !0, n._updateFlags = 15;
    const s = this.renderGroup || this.parentRenderGroup;
    return s && s.addChild(n), this.sortableChildren && (this.sortDirty = !0), this.emit("childAdded", n, this, t), n.emit("added", this), n;
  },
  swapChildren(n, t) {
    if (n === t)
      return;
    const e = this.getChildIndex(n), s = this.getChildIndex(t);
    this.children[e] = t, this.children[s] = n;
    const i = this.renderGroup || this.parentRenderGroup;
    i && (i.structureDidChange = !0), this._didContainerChangeTick++;
  },
  removeFromParent() {
    this.parent?.removeChild(this);
  },
  reparentChild(...n) {
    return n.length === 1 ? this.reparentChildAt(n[0], this.children.length) : (n.forEach((t) => this.reparentChildAt(t, this.children.length)), n[0]);
  },
  reparentChildAt(n, t) {
    if (n.parent === this)
      return this.setChildIndex(n, t), n;
    const e = n.worldTransform.clone();
    n.removeFromParent(), this.addChildAt(n, t);
    const s = this.worldTransform.clone();
    return s.invert(), e.prepend(s), n.setFromMatrix(e), n;
  },
  replaceChild(n, t) {
    n.updateLocalTransform(), this.addChildAt(t, this.getChildIndex(n)), t.setFromMatrix(n.localTransform), t.updateLocalTransform(), this.removeChild(n);
  }
}, vy = {
  collectRenderables(n, t, e) {
    this.parentRenderLayer && this.parentRenderLayer !== e || this.globalDisplayStatus < 7 || !this.includeInBuild || (this.sortableChildren && this.sortChildren(), this.isSimple ? this.collectRenderablesSimple(n, t, e) : this.renderGroup ? t.renderPipes.renderGroup.addRenderGroup(this.renderGroup, n) : this.collectRenderablesWithEffects(n, t, e));
  },
  collectRenderablesSimple(n, t, e) {
    const s = this.children, i = s.length;
    for (let r = 0; r < i; r++)
      s[r].collectRenderables(n, t, e);
  },
  collectRenderablesWithEffects(n, t, e) {
    const { renderPipes: s } = t;
    for (let i = 0; i < this.effects.length; i++) {
      const r = this.effects[i];
      s[r.pipe].push(r, this, n);
    }
    this.collectRenderablesSimple(n, t, e);
    for (let i = this.effects.length - 1; i >= 0; i--) {
      const r = this.effects[i];
      s[r.pipe].pop(r, this, n);
    }
  }
};
class Kh {
  constructor() {
    this.pipe = "filter", this.priority = 1;
  }
  destroy() {
    for (let t = 0; t < this.filters.length; t++)
      this.filters[t].destroy();
    this.filters = null, this.filterArea = null;
  }
}
class by {
  constructor() {
    this._effectClasses = [], this._tests = [], this._initialized = !1;
  }
  init() {
    this._initialized || (this._initialized = !0, this._effectClasses.forEach((t) => {
      this.add({
        test: t.test,
        maskClass: t
      });
    }));
  }
  add(t) {
    this._tests.push(t);
  }
  getMaskEffect(t) {
    this._initialized || this.init();
    for (let e = 0; e < this._tests.length; e++) {
      const s = this._tests[e];
      if (s.test(t))
        return Ms.get(s.maskClass, t);
    }
    return t;
  }
  returnMaskEffect(t) {
    Ms.return(t);
  }
}
const ll = new by();
ze.handleByList(dt.MaskEffect, ll._effectClasses);
const wy = {
  _maskEffect: null,
  _maskOptions: {
    inverse: !1
  },
  _filterEffect: null,
  effects: [],
  _markStructureAsChanged() {
    const n = this.renderGroup || this.parentRenderGroup;
    n && (n.structureDidChange = !0);
  },
  addEffect(n) {
    this.effects.indexOf(n) === -1 && (this.effects.push(n), this.effects.sort((e, s) => e.priority - s.priority), this._markStructureAsChanged(), this._updateIsSimple());
  },
  removeEffect(n) {
    const t = this.effects.indexOf(n);
    t !== -1 && (this.effects.splice(t, 1), this._markStructureAsChanged(), this._updateIsSimple());
  },
  set mask(n) {
    const t = this._maskEffect;
    t?.mask !== n && (t && (this.removeEffect(t), ll.returnMaskEffect(t), this._maskEffect = null), n != null && (this._maskEffect = ll.getMaskEffect(n), this.addEffect(this._maskEffect)));
  },
  get mask() {
    return this._maskEffect?.mask;
  },
  setMask(n) {
    this._maskOptions = {
      ...this._maskOptions,
      ...n
    }, n.mask && (this.mask = n.mask), this._markStructureAsChanged();
  },
  set filters(n) {
    !Array.isArray(n) && n && (n = [n]);
    const t = this._filterEffect || (this._filterEffect = new Kh());
    n = n;
    const e = n?.length > 0, s = t.filters?.length > 0, i = e !== s;
    n = Array.isArray(n) ? n.slice(0) : n, t.filters = Object.freeze(n), i && (e ? this.addEffect(t) : (this.removeEffect(t), t.filters = n ?? null));
  },
  get filters() {
    return this._filterEffect?.filters;
  },
  set filterArea(n) {
    this._filterEffect || (this._filterEffect = new Kh()), this._filterEffect.filterArea = n;
  },
  get filterArea() {
    return this._filterEffect?.filterArea;
  }
}, Sy = {
  label: null,
  get name() {
    return ct(kt, "Container.name property has been removed, use Container.label instead"), this.label;
  },
  set name(n) {
    ct(kt, "Container.name property has been removed, use Container.label instead"), this.label = n;
  },
  getChildByName(n, t = !1) {
    return this.getChildByLabel(n, t);
  },
  getChildByLabel(n, t = !1) {
    const e = this.children;
    for (let s = 0; s < e.length; s++) {
      const i = e[s];
      if (i.label === n || n instanceof RegExp && n.test(i.label))
        return i;
    }
    if (t)
      for (let s = 0; s < e.length; s++) {
        const r = e[s].getChildByLabel(n, !0);
        if (r)
          return r;
      }
    return null;
  },
  getChildrenByLabel(n, t = !1, e = []) {
    const s = this.children;
    for (let i = 0; i < s.length; i++) {
      const r = s[i];
      (r.label === n || n instanceof RegExp && n.test(r.label)) && e.push(r);
    }
    if (t)
      for (let i = 0; i < s.length; i++)
        s[i].getChildrenByLabel(n, !0, e);
    return e;
  }
}, ae = new Xl(nt), ks = new Xl(Ye), Ty = new nt(), My = {
  getFastGlobalBounds(n, t) {
    t || (t = new Ye()), t.clear(), this._getGlobalBoundsRecursive(!!n, t, this.parentRenderLayer), t.isValid || t.set(0, 0, 0, 0);
    const e = this.renderGroup || this.parentRenderGroup;
    return t.applyMatrix(e.worldTransform), t;
  },
  _getGlobalBoundsRecursive(n, t, e) {
    let s = t;
    if (n && this.parentRenderLayer && this.parentRenderLayer !== e || this.localDisplayStatus !== 7 || !this.measurable)
      return;
    const i = !!this.effects.length;
    if ((this.renderGroup || i) && (s = ks.get().clear()), this.boundsArea)
      t.addRect(this.boundsArea, this.worldTransform);
    else {
      if (this.renderPipeId) {
        const o = this.bounds;
        s.addFrame(
          o.minX,
          o.minY,
          o.maxX,
          o.maxY,
          this.groupTransform
        );
      }
      const r = this.children;
      for (let o = 0; o < r.length; o++)
        r[o]._getGlobalBoundsRecursive(n, s, e);
    }
    if (i) {
      let r = !1;
      const o = this.renderGroup || this.parentRenderGroup;
      for (let a = 0; a < this.effects.length; a++)
        this.effects[a].addBounds && (r || (r = !0, s.applyMatrix(o.worldTransform)), this.effects[a].addBounds(s, !0));
      r && s.applyMatrix(o.worldTransform.copyTo(Ty).invert()), t.addBounds(s), ks.return(s);
    } else this.renderGroup && (t.addBounds(s, this.relativeGroupTransform), ks.return(s));
  }
};
function Bf(n, t, e) {
  e.clear();
  let s, i;
  return n.parent ? t ? s = n.parent.worldTransform : (i = ae.get().identity(), s = Yl(n, i)) : s = nt.IDENTITY, zf(n, e, s, t), i && ae.return(i), e.isValid || e.set(0, 0, 0, 0), e;
}
function zf(n, t, e, s) {
  if (!n.visible || !n.measurable)
    return;
  let i;
  s ? i = n.worldTransform : (n.updateLocalTransform(), i = ae.get(), i.appendFrom(n.localTransform, e));
  const r = t, o = !!n.effects.length;
  if (o && (t = ks.get().clear()), n.boundsArea)
    t.addRect(n.boundsArea, i);
  else {
    n.bounds && (t.matrix = i, t.addBounds(n.bounds));
    for (let a = 0; a < n.children.length; a++)
      zf(n.children[a], t, i, s);
  }
  if (o) {
    for (let a = 0; a < n.effects.length; a++)
      n.effects[a].addBounds?.(t);
    r.addBounds(t, nt.IDENTITY), ks.return(t);
  }
  s || ae.return(i);
}
function Yl(n, t) {
  const e = n.parent;
  return e && (Yl(e, t), e.updateLocalTransform(), t.append(e.localTransform)), t;
}
function qf(n, t) {
  if (n === 16777215 || !t)
    return t;
  if (t === 16777215 || !n)
    return n;
  const e = n >> 16 & 255, s = n >> 8 & 255, i = n & 255, r = t >> 16 & 255, o = t >> 8 & 255, a = t & 255, l = e * r / 255 | 0, c = s * o / 255 | 0, h = i * a / 255 | 0;
  return (l << 16) + (c << 8) + h;
}
const Qh = 16777215;
function Jh(n, t) {
  return n === Qh ? t : t === Qh ? n : qf(n, t);
}
function oo(n) {
  return ((n & 255) << 16) + (n & 65280) + (n >> 16 & 255);
}
const ky = {
  getGlobalAlpha(n) {
    if (n)
      return this.renderGroup ? this.renderGroup.worldAlpha : this.parentRenderGroup ? this.parentRenderGroup.worldAlpha * this.alpha : this.alpha;
    let t = this.alpha, e = this.parent;
    for (; e; )
      t *= e.alpha, e = e.parent;
    return t;
  },
  getGlobalTransform(n = new nt(), t) {
    if (t)
      return n.copyFrom(this.worldTransform);
    this.updateLocalTransform();
    const e = Yl(this, ae.get().identity());
    return n.appendFrom(this.localTransform, e), ae.return(e), n;
  },
  getGlobalTint(n) {
    if (n)
      return this.renderGroup ? oo(this.renderGroup.worldColor) : this.parentRenderGroup ? oo(
        Jh(this.localColor, this.parentRenderGroup.worldColor)
      ) : this.tint;
    let t = this.localColor, e = this.parent;
    for (; e; )
      t = Jh(t, e.localColor), e = e.parent;
    return oo(t);
  }
};
function Uf(n, t, e) {
  return t.clear(), e || (e = nt.IDENTITY), Gf(n, t, e, n, !0), t.isValid || t.set(0, 0, 0, 0), t;
}
function Gf(n, t, e, s, i) {
  let r;
  if (i)
    r = ae.get(), r = e.copyTo(r);
  else {
    if (!n.visible || !n.measurable)
      return;
    n.updateLocalTransform();
    const l = n.localTransform;
    r = ae.get(), r.appendFrom(l, e);
  }
  const o = t, a = !!n.effects.length;
  if (a && (t = ks.get().clear()), n.boundsArea)
    t.addRect(n.boundsArea, r);
  else {
    n.renderPipeId && (t.matrix = r, t.addBounds(n.bounds));
    const l = n.children;
    for (let c = 0; c < l.length; c++)
      Gf(l[c], t, r, s, !1);
  }
  if (a) {
    for (let l = 0; l < n.effects.length; l++)
      n.effects[l].addLocalBounds?.(t, s);
    o.addBounds(t, nt.IDENTITY), ks.return(t);
  }
  ae.return(r);
}
function Wf(n, t) {
  const e = n.children;
  for (let s = 0; s < e.length; s++) {
    const i = e[s], r = i.uid, o = (i._didViewChangeTick & 65535) << 16 | i._didContainerChangeTick & 65535, a = t.index;
    (t.data[a] !== r || t.data[a + 1] !== o) && (t.data[t.index] = r, t.data[t.index + 1] = o, t.didChange = !0), t.index = a + 2, i.children.length && Wf(i, t);
  }
  return t.didChange;
}
const Cy = new nt(), Ay = {
  _localBoundsCacheId: -1,
  _localBoundsCacheData: null,
  _setWidth(n, t) {
    const e = Math.sign(this.scale.x) || 1;
    t !== 0 ? this.scale.x = n / t * e : this.scale.x = e;
  },
  _setHeight(n, t) {
    const e = Math.sign(this.scale.y) || 1;
    t !== 0 ? this.scale.y = n / t * e : this.scale.y = e;
  },
  getLocalBounds() {
    this._localBoundsCacheData || (this._localBoundsCacheData = {
      data: [],
      index: 1,
      didChange: !1,
      localBounds: new Ye()
    });
    const n = this._localBoundsCacheData;
    return n.index = 1, n.didChange = !1, n.data[0] !== this._didViewChangeTick && (n.didChange = !0, n.data[0] = this._didViewChangeTick), Wf(this, n), n.didChange && Uf(this, n.localBounds, Cy), n.localBounds;
  },
  getBounds(n, t) {
    return Bf(this, n, t || new Ye());
  }
}, Ey = {
  _onRender: null,
  set onRender(n) {
    const t = this.renderGroup || this.parentRenderGroup;
    if (!n) {
      this._onRender && t?.removeOnRender(this), this._onRender = null;
      return;
    }
    this._onRender || t?.addOnRender(this), this._onRender = n;
  },
  get onRender() {
    return this._onRender;
  }
}, Py = {
  _zIndex: 0,
  sortDirty: !1,
  sortableChildren: !1,
  get zIndex() {
    return this._zIndex;
  },
  set zIndex(n) {
    this._zIndex !== n && (this._zIndex = n, this.depthOfChildModified());
  },
  depthOfChildModified() {
    this.parent && (this.parent.sortableChildren = !0, this.parent.sortDirty = !0), this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0);
  },
  sortChildren() {
    this.sortDirty && (this.sortDirty = !1, this.children.sort(Iy));
  }
};
function Iy(n, t) {
  return n._zIndex - t._zIndex;
}
const Fy = {
  getGlobalPosition(n = new se(), t = !1) {
    return this.parent ? this.parent.toGlobal(this._position, n, t) : (n.x = this._position.x, n.y = this._position.y), n;
  },
  toGlobal(n, t, e = !1) {
    const s = this.getGlobalTransform(ae.get(), e);
    return t = s.apply(n, t), ae.return(s), t;
  },
  toLocal(n, t, e, s) {
    t && (n = t.toGlobal(n, e, s));
    const i = this.getGlobalTransform(ae.get(), s);
    return e = i.applyInverse(n, e), ae.return(i), e;
  }
};
class $f {
  constructor() {
    this.uid = Ot("instructionSet"), this.instructions = [], this.instructionSize = 0, this.renderables = [], this.gcTick = 0;
  }
  /** reset the instruction set so it can be reused set size back to 0 */
  reset() {
    this.instructionSize = 0;
  }
  /**
   * Add an instruction to the set
   * @param instruction - add an instruction to the set
   */
  add(t) {
    this.instructions[this.instructionSize++] = t;
  }
  /**
   * Log the instructions to the console (for debugging)
   * @internal
   */
  log() {
    this.instructions.length = this.instructionSize, console.table(this.instructions, ["type", "action"]);
  }
}
let Ry = 0;
class Dy {
  /**
   * @param textureOptions - options that will be passed to BaseRenderTexture constructor
   * @param {SCALE_MODE} [textureOptions.scaleMode] - See {@link SCALE_MODE} for possible values.
   */
  constructor(t) {
    this._poolKeyHash = /* @__PURE__ */ Object.create(null), this._texturePool = {}, this.textureOptions = t || {}, this.enableFullScreen = !1, this.textureStyle = new mo(this.textureOptions);
  }
  /**
   * Creates texture with params that were specified in pool constructor.
   * @param pixelWidth - Width of texture in pixels.
   * @param pixelHeight - Height of texture in pixels.
   * @param antialias
   */
  createTexture(t, e, s) {
    const i = new Je({
      ...this.textureOptions,
      width: t,
      height: e,
      resolution: 1,
      antialias: s,
      autoGarbageCollect: !1
    });
    return new rt({
      source: i,
      label: `texturePool_${Ry++}`
    });
  }
  /**
   * Gets a Power-of-Two render texture or fullScreen texture
   * @param frameWidth - The minimum width of the render texture.
   * @param frameHeight - The minimum height of the render texture.
   * @param resolution - The resolution of the render texture.
   * @param antialias
   * @returns The new render texture.
   */
  getOptimalTexture(t, e, s = 1, i) {
    let r = Math.ceil(t * s - 1e-6), o = Math.ceil(e * s - 1e-6);
    r = Xn(r), o = Xn(o);
    const a = (r << 17) + (o << 1) + (i ? 1 : 0);
    this._texturePool[a] || (this._texturePool[a] = []);
    let l = this._texturePool[a].pop();
    return l || (l = this.createTexture(r, o, i)), l.source._resolution = s, l.source.width = r / s, l.source.height = o / s, l.source.pixelWidth = r, l.source.pixelHeight = o, l.frame.x = 0, l.frame.y = 0, l.frame.width = t, l.frame.height = e, l.updateUvs(), this._poolKeyHash[l.uid] = a, l;
  }
  /**
   * Gets extra texture of the same size as input renderTexture
   * @param texture - The texture to check what size it is.
   * @param antialias - Whether to use antialias.
   * @returns A texture that is a power of two
   */
  getSameSizeTexture(t, e = !1) {
    const s = t.source;
    return this.getOptimalTexture(t.width, t.height, s._resolution, e);
  }
  /**
   * Place a render texture back into the pool. Optionally reset the style of the texture to the default texture style.
   * useful if you modified the style of the texture after getting it from the pool.
   * @param renderTexture - The renderTexture to free
   * @param resetStyle - Whether to reset the style of the texture to the default texture style
   */
  returnTexture(t, e = !1) {
    const s = this._poolKeyHash[t.uid];
    e && (t.source.style = this.textureStyle), this._texturePool[s].push(t);
  }
  /**
   * Clears the pool.
   * @param destroyTextures - Destroy all stored textures.
   */
  clear(t) {
    if (t = t !== !1, t)
      for (const e in this._texturePool) {
        const s = this._texturePool[e];
        if (s)
          for (let i = 0; i < s.length; i++)
            s[i].destroy(!0);
      }
    this._texturePool = {};
  }
}
const Oy = new Dy();
class Ny {
  constructor() {
    this.renderPipeId = "renderGroup", this.root = null, this.canBundle = !1, this.renderGroupParent = null, this.renderGroupChildren = [], this.worldTransform = new nt(), this.worldColorAlpha = 4294967295, this.worldColor = 16777215, this.worldAlpha = 1, this.childrenToUpdate = /* @__PURE__ */ Object.create(null), this.updateTick = 0, this.gcTick = 0, this.childrenRenderablesToUpdate = { list: [], index: 0 }, this.structureDidChange = !0, this.instructionSet = new $f(), this._onRenderContainers = [], this.textureNeedsUpdate = !0, this.isCachedAsTexture = !1, this._matrixDirty = 7;
  }
  init(t) {
    this.root = t, t._onRender && this.addOnRender(t), t.didChange = !0;
    const e = t.children;
    for (let s = 0; s < e.length; s++) {
      const i = e[s];
      i._updateFlags = 15, this.addChild(i);
    }
  }
  enableCacheAsTexture(t = {}) {
    this.textureOptions = t, this.isCachedAsTexture = !0, this.textureNeedsUpdate = !0;
  }
  disableCacheAsTexture() {
    this.isCachedAsTexture = !1, this.texture && (Oy.returnTexture(this.texture, !0), this.texture = null);
  }
  updateCacheTexture() {
    this.textureNeedsUpdate = !0;
  }
  reset() {
    this.renderGroupChildren.length = 0;
    for (const t in this.childrenToUpdate) {
      const e = this.childrenToUpdate[t];
      e.list.fill(null), e.index = 0;
    }
    this.childrenRenderablesToUpdate.index = 0, this.childrenRenderablesToUpdate.list.fill(null), this.root = null, this.updateTick = 0, this.structureDidChange = !0, this._onRenderContainers.length = 0, this.renderGroupParent = null, this.disableCacheAsTexture();
  }
  get localTransform() {
    return this.root.localTransform;
  }
  addRenderGroupChild(t) {
    t.renderGroupParent && t.renderGroupParent._removeRenderGroupChild(t), t.renderGroupParent = this, this.renderGroupChildren.push(t);
  }
  _removeRenderGroupChild(t) {
    const e = this.renderGroupChildren.indexOf(t);
    e > -1 && this.renderGroupChildren.splice(e, 1), t.renderGroupParent = null;
  }
  addChild(t) {
    if (this.structureDidChange = !0, t.parentRenderGroup = this, t.updateTick = -1, t.parent === this.root ? t.relativeRenderGroupDepth = 1 : t.relativeRenderGroupDepth = t.parent.relativeRenderGroupDepth + 1, t.didChange = !0, this.onChildUpdate(t), t.renderGroup) {
      this.addRenderGroupChild(t.renderGroup);
      return;
    }
    t._onRender && this.addOnRender(t);
    const e = t.children;
    for (let s = 0; s < e.length; s++)
      this.addChild(e[s]);
  }
  removeChild(t) {
    if (this.structureDidChange = !0, t._onRender && (t.renderGroup || this.removeOnRender(t)), t.parentRenderGroup = null, t.renderGroup) {
      this._removeRenderGroupChild(t.renderGroup);
      return;
    }
    const e = t.children;
    for (let s = 0; s < e.length; s++)
      this.removeChild(e[s]);
  }
  removeChildren(t) {
    for (let e = 0; e < t.length; e++)
      this.removeChild(t[e]);
  }
  onChildUpdate(t) {
    let e = this.childrenToUpdate[t.relativeRenderGroupDepth];
    e || (e = this.childrenToUpdate[t.relativeRenderGroupDepth] = {
      index: 0,
      list: []
    }), e.list[e.index++] = t;
  }
  updateRenderable(t) {
    t.globalDisplayStatus < 7 || (this.instructionSet.renderPipes[t.renderPipeId].updateRenderable(t), t.didViewUpdate = !1);
  }
  onChildViewUpdate(t) {
    this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = t;
  }
  get isRenderable() {
    return this.root.localDisplayStatus === 7 && this.worldAlpha > 0;
  }
  /**
   * adding a container to the onRender list will make sure the user function
   * passed in to the user defined 'onRender` callBack
   * @param container - the container to add to the onRender list
   */
  addOnRender(t) {
    this._onRenderContainers.push(t);
  }
  removeOnRender(t) {
    this._onRenderContainers.splice(this._onRenderContainers.indexOf(t), 1);
  }
  runOnRender(t) {
    for (let e = 0; e < this._onRenderContainers.length; e++)
      this._onRenderContainers[e]._onRender(t);
  }
  destroy() {
    this.disableCacheAsTexture(), this.renderGroupParent = null, this.root = null, this.childrenRenderablesToUpdate = null, this.childrenToUpdate = null, this.renderGroupChildren = null, this._onRenderContainers = null, this.instructionSet = null;
  }
  getChildren(t = []) {
    const e = this.root.children;
    for (let s = 0; s < e.length; s++)
      this._getChildren(e[s], t);
    return t;
  }
  _getChildren(t, e = []) {
    if (e.push(t), t.renderGroup)
      return e;
    const s = t.children;
    for (let i = 0; i < s.length; i++)
      this._getChildren(s[i], e);
    return e;
  }
  invalidateMatrices() {
    this._matrixDirty = 7;
  }
  /**
   * Returns the inverse of the world transform matrix.
   * @returns {Matrix} The inverse of the world transform matrix.
   */
  get inverseWorldTransform() {
    return (this._matrixDirty & 1) === 0 ? this._inverseWorldTransform : (this._matrixDirty &= -2, this._inverseWorldTransform || (this._inverseWorldTransform = new nt()), this._inverseWorldTransform.copyFrom(this.worldTransform).invert());
  }
  /**
   * Returns the inverse of the texture offset transform matrix.
   * @returns {Matrix} The inverse of the texture offset transform matrix.
   */
  get textureOffsetInverseTransform() {
    return (this._matrixDirty & 2) === 0 ? this._textureOffsetInverseTransform : (this._matrixDirty &= -3, this._textureOffsetInverseTransform || (this._textureOffsetInverseTransform = new nt()), this._textureOffsetInverseTransform.copyFrom(this.inverseWorldTransform).translate(
      -this._textureBounds.x,
      -this._textureBounds.y
    ));
  }
  /**
   * Returns the inverse of the parent texture transform matrix.
   * This is used to properly transform coordinates when rendering into cached textures.
   * @returns {Matrix} The inverse of the parent texture transform matrix.
   */
  get inverseParentTextureTransform() {
    if ((this._matrixDirty & 4) === 0)
      return this._inverseParentTextureTransform;
    this._matrixDirty &= -5;
    const t = this._parentCacheAsTextureRenderGroup;
    return t ? (this._inverseParentTextureTransform || (this._inverseParentTextureTransform = new nt()), this._inverseParentTextureTransform.copyFrom(this.worldTransform).prepend(t.inverseWorldTransform).translate(
      -t._textureBounds.x,
      -t._textureBounds.y
    )) : this.worldTransform;
  }
  /**
   * Returns a matrix that transforms coordinates to the correct coordinate space of the texture being rendered to.
   * This is the texture offset inverse transform of the closest parent RenderGroup that is cached as a texture.
   * @returns {Matrix | null} The transform matrix for the cached texture coordinate space,
   * or null if no parent is cached as texture.
   */
  get cacheToLocalTransform() {
    return this._parentCacheAsTextureRenderGroup ? this._parentCacheAsTextureRenderGroup.textureOffsetInverseTransform : null;
  }
}
function Ly(n, t, e = {}) {
  for (const s in t)
    !e[s] && t[s] !== void 0 && (n[s] = t[s]);
}
const Ma = new Pt(null), zr = new Pt(null), ka = new Pt(null, 1, 1), qr = new Pt(null), tu = 1, Vy = 2, Ca = 4;
class Te extends ps {
  constructor(t = {}) {
    super(), this.uid = Ot("renderable"), this._updateFlags = 15, this.renderGroup = null, this.parentRenderGroup = null, this.parentRenderGroupIndex = 0, this.didChange = !1, this.didViewUpdate = !1, this.relativeRenderGroupDepth = 0, this.children = [], this.parent = null, this.includeInBuild = !0, this.measurable = !0, this.isSimple = !0, this.updateTick = -1, this.localTransform = new nt(), this.relativeGroupTransform = new nt(), this.groupTransform = this.relativeGroupTransform, this.destroyed = !1, this._position = new Pt(this, 0, 0), this._scale = ka, this._pivot = zr, this._origin = qr, this._skew = Ma, this._cx = 1, this._sx = 0, this._cy = 0, this._sy = 1, this._rotation = 0, this.localColor = 16777215, this.localAlpha = 1, this.groupAlpha = 1, this.groupColor = 16777215, this.groupColorAlpha = 4294967295, this.localBlendMode = "inherit", this.groupBlendMode = "normal", this.localDisplayStatus = 7, this.globalDisplayStatus = 7, this._didContainerChangeTick = 0, this._didViewChangeTick = 0, this._didLocalTransformChangeId = -1, this.effects = [], Ly(this, t, {
      children: !0,
      parent: !0,
      effects: !0
    }), t.children?.forEach((e) => this.addChild(e)), t.parent?.addChild(this);
  }
  /**
   * Mixes all enumerable properties and methods from a source object to Container.
   * @param source - The source of properties and methods to mix in.
   * @deprecated since 8.8.0
   */
  static mixin(t) {
    ct("8.8.0", "Container.mixin is deprecated, please use extensions.mixin instead."), ze.mixin(Te, t);
  }
  // = 'default';
  /**
   * We now use the _didContainerChangeTick and _didViewChangeTick to track changes
   * @deprecated since 8.2.6
   * @ignore
   */
  set _didChangeId(t) {
    this._didViewChangeTick = t >> 12 & 4095, this._didContainerChangeTick = t & 4095;
  }
  /** @ignore */
  get _didChangeId() {
    return this._didContainerChangeTick & 4095 | (this._didViewChangeTick & 4095) << 12;
  }
  /**
   * Adds one or more children to the container.
   * The children will be rendered as part of this container's display list.
   * @example
   * ```ts
   * // Add a single child
   * container.addChild(sprite);
   *
   * // Add multiple children
   * container.addChild(background, player, foreground);
   *
   * // Add with type checking
   * const sprite = container.addChild<Sprite>(new Sprite(texture));
   * sprite.tint = 'red';
   * ```
   * @param children - The Container(s) to add to the container
   * @returns The first child that was added
   * @see {@link Container#removeChild} For removing children
   * @see {@link Container#addChildAt} For adding at specific index
   */
  addChild(...t) {
    if (this.allowChildren || ct(kt, "addChild: Only Containers will be allowed to add children in v8.0.0"), t.length > 1) {
      for (let i = 0; i < t.length; i++)
        this.addChild(t[i]);
      return t[0];
    }
    const e = t[0], s = this.renderGroup || this.parentRenderGroup;
    return e.parent === this ? (this.children.splice(this.children.indexOf(e), 1), this.children.push(e), s && (s.structureDidChange = !0), e) : (e.parent && e.parent.removeChild(e), this.children.push(e), this.sortableChildren && (this.sortDirty = !0), e.parent = this, e.didChange = !0, e._updateFlags = 15, s && s.addChild(e), this.emit("childAdded", e, this, this.children.length - 1), e.emit("added", this), this._didViewChangeTick++, e._zIndex !== 0 && e.depthOfChildModified(), e);
  }
  /**
   * Removes one or more children from the container.
   * When removing multiple children, events will be triggered for each child in sequence.
   * @example
   * ```ts
   * // Remove a single child
   * const removed = container.removeChild(sprite);
   *
   * // Remove multiple children
   * const bg = container.removeChild(background, player, userInterface);
   *
   * // Remove with type checking
   * const sprite = container.removeChild<Sprite>(childSprite);
   * sprite.texture = newTexture;
   * ```
   * @param children - The Container(s) to remove
   * @returns The first child that was removed
   * @see {@link Container#addChild} For adding children
   * @see {@link Container#removeChildren} For removing multiple children
   */
  removeChild(...t) {
    if (t.length > 1) {
      for (let i = 0; i < t.length; i++)
        this.removeChild(t[i]);
      return t[0];
    }
    const e = t[0], s = this.children.indexOf(e);
    return s > -1 && (this._didViewChangeTick++, this.children.splice(s, 1), this.renderGroup ? this.renderGroup.removeChild(e) : this.parentRenderGroup && this.parentRenderGroup.removeChild(e), e.parentRenderLayer && e.parentRenderLayer.detach(e), e.parent = null, this.emit("childRemoved", e, this, s), e.emit("removed", this)), e;
  }
  /** @ignore */
  _onUpdate(t) {
    t && t === this._skew && this._updateSkew(), this._didContainerChangeTick++, !this.didChange && (this.didChange = !0, this.parentRenderGroup && this.parentRenderGroup.onChildUpdate(this));
  }
  set isRenderGroup(t) {
    !!this.renderGroup !== t && (t ? this.enableRenderGroup() : this.disableRenderGroup());
  }
  /**
   * Returns true if this container is a render group.
   * This means that it will be rendered as a separate pass, with its own set of instructions
   * @advanced
   */
  get isRenderGroup() {
    return !!this.renderGroup;
  }
  /**
   * Calling this enables a render group for this container.
   * This means it will be rendered as a separate set of instructions.
   * The transform of the container will also be handled on the GPU rather than the CPU.
   * @advanced
   */
  enableRenderGroup() {
    if (this.renderGroup)
      return;
    const t = this.parentRenderGroup;
    t?.removeChild(this), this.renderGroup = Ms.get(Ny, this), this.groupTransform = nt.IDENTITY, t?.addChild(this), this._updateIsSimple();
  }
  /**
   * This will disable the render group for this container.
   * @advanced
   */
  disableRenderGroup() {
    if (!this.renderGroup)
      return;
    const t = this.parentRenderGroup;
    t?.removeChild(this), Ms.return(this.renderGroup), this.renderGroup = null, this.groupTransform = this.relativeGroupTransform, t?.addChild(this), this._updateIsSimple();
  }
  /** @ignore */
  _updateIsSimple() {
    this.isSimple = !this.renderGroup && this.effects.length === 0;
  }
  /**
   * Current transform of the object based on world (parent) factors.
   *
   * This matrix represents the absolute transformation in the scene graph.
   * @example
   * ```ts
   * // Get world position
   * const worldPos = container.worldTransform;
   * console.log(`World position: (${worldPos.tx}, ${worldPos.ty})`);
   * ```
   * @readonly
   * @see {@link Container#localTransform} For local space transform
   */
  get worldTransform() {
    return this._worldTransform || (this._worldTransform = new nt()), this.renderGroup ? this._worldTransform.copyFrom(this.renderGroup.worldTransform) : this.parentRenderGroup && this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform), this._worldTransform;
  }
  /**
   * The position of the container on the x axis relative to the local coordinates of the parent.
   *
   * An alias to position.x
   * @example
   * ```ts
   * // Basic position
   * container.x = 100;
   * ```
   */
  get x() {
    return this._position.x;
  }
  set x(t) {
    this._position.x = t;
  }
  /**
   * The position of the container on the y axis relative to the local coordinates of the parent.
   *
   * An alias to position.y
   * @example
   * ```ts
   * // Basic position
   * container.y = 200;
   * ```
   */
  get y() {
    return this._position.y;
  }
  set y(t) {
    this._position.y = t;
  }
  /**
   * The coordinate of the object relative to the local coordinates of the parent.
   * @example
   * ```ts
   * // Basic position setting
   * container.position.set(100, 200);
   * container.position.set(100); // Sets both x and y to 100
   * // Using point data
   * container.position = { x: 50, y: 75 };
   * ```
   * @since 4.0.0
   */
  get position() {
    return this._position;
  }
  set position(t) {
    this._position.copyFrom(t);
  }
  /**
   * The rotation of the object in radians.
   *
   * > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
   * > rotation is in radians, angle is in degrees.
   * @example
   * ```ts
   * // Basic rotation
   * container.rotation = Math.PI / 4; // 45 degrees
   *
   * // Convert from degrees
   * const degrees = 45;
   * container.rotation = degrees * Math.PI / 180;
   *
   * // Rotate around center
   * container.pivot.set(container.width / 2, container.height / 2);
   * container.rotation = Math.PI; // 180 degrees
   *
   * // Rotate around center with origin
   * container.origin.set(container.width / 2, container.height / 2);
   * container.rotation = Math.PI; // 180 degrees
   * ```
   */
  get rotation() {
    return this._rotation;
  }
  set rotation(t) {
    this._rotation !== t && (this._rotation = t, this._onUpdate(this._skew));
  }
  /**
   * The angle of the object in degrees.
   *
   * > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
   * > rotation is in radians, angle is in degrees.
   * @example
   * ```ts
   * // Basic angle rotation
   * sprite.angle = 45; // 45 degrees
   *
   * // Rotate around center
   * sprite.pivot.set(sprite.width / 2, sprite.height / 2);
   * sprite.angle = 180; // Half rotation
   *
   * // Rotate around center with origin
   * sprite.origin.set(sprite.width / 2, sprite.height / 2);
   * sprite.angle = 180; // Half rotation
   *
   * // Reset rotation
   * sprite.angle = 0;
   * ```
   */
  get angle() {
    return this.rotation * Kg;
  }
  set angle(t) {
    this.rotation = t * Qg;
  }
  /**
   * The center of rotation, scaling, and skewing for this display object in its local space.
   * The `position` is the projection of `pivot` in the parent's local space.
   *
   * By default, the pivot is the origin (0, 0).
   * @example
   * ```ts
   * // Rotate around center
   * container.pivot.set(container.width / 2, container.height / 2);
   * container.rotation = Math.PI; // Rotates around center
   * ```
   * @since 4.0.0
   */
  get pivot() {
    return this._pivot === zr && (this._pivot = new Pt(this, 0, 0)), this._pivot;
  }
  set pivot(t) {
    this._pivot === zr && (this._pivot = new Pt(this, 0, 0), this._origin !== qr && Ht("Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.")), typeof t == "number" ? this._pivot.set(t) : this._pivot.copyFrom(t);
  }
  /**
   * The skew factor for the object in radians. Skewing is a transformation that distorts
   * the object by rotating it differently at each point, creating a non-uniform shape.
   * @example
   * ```ts
   * // Basic skewing
   * container.skew.set(0.5, 0); // Skew horizontally
   * container.skew.set(0, 0.5); // Skew vertically
   *
   * // Skew with point data
   * container.skew = { x: 0.3, y: 0.3 }; // Diagonal skew
   *
   * // Reset skew
   * container.skew.set(0, 0);
   *
   * // Animate skew
   * app.ticker.add(() => {
   *     // Create wave effect
   *     container.skew.x = Math.sin(Date.now() / 1000) * 0.3;
   * });
   *
   * // Combine with rotation
   * container.rotation = Math.PI / 4; // 45 degrees
   * container.skew.set(0.2, 0.2); // Skew the rotated object
   * ```
   * @since 4.0.0
   * @type {ObservablePoint} Point-like object with x/y properties in radians
   * @default {x: 0, y: 0}
   */
  get skew() {
    return this._skew === Ma && (this._skew = new Pt(this, 0, 0)), this._skew;
  }
  set skew(t) {
    this._skew === Ma && (this._skew = new Pt(this, 0, 0)), this._skew.copyFrom(t);
  }
  /**
   * The scale factors of this object along the local coordinate axes.
   *
   * The default scale is (1, 1).
   * @example
   * ```ts
   * // Basic scaling
   * container.scale.set(2, 2); // Scales to double size
   * container.scale.set(2); // Scales uniformly to double size
   * container.scale = 2; // Scales uniformly to double size
   * // Scale to a specific width and height
   * container.setSize(200, 100); // Sets width to 200 and height to 100
   * ```
   * @since 4.0.0
   */
  get scale() {
    return this._scale === ka && (this._scale = new Pt(this, 1, 1)), this._scale;
  }
  set scale(t) {
    this._scale === ka && (this._scale = new Pt(this, 0, 0)), typeof t == "string" && (t = parseFloat(t)), typeof t == "number" ? this._scale.set(t) : this._scale.copyFrom(t);
  }
  /**
   * @experimental
   * The origin point around which the container rotates and scales without affecting its position.
   * Unlike pivot, changing the origin will not move the container's position.
   * @example
   * ```ts
   * // Rotate around center point
   * container.origin.set(container.width / 2, container.height / 2);
   * container.rotation = Math.PI; // Rotates around center
   *
   * // Reset origin
   * container.origin.set(0, 0);
   * ```
   */
  get origin() {
    return this._origin === qr && (this._origin = new Pt(this, 0, 0)), this._origin;
  }
  set origin(t) {
    this._origin === qr && (this._origin = new Pt(this, 0, 0), this._pivot !== zr && Ht("Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.")), typeof t == "number" ? this._origin.set(t) : this._origin.copyFrom(t);
  }
  /**
   * The width of the Container, setting this will actually modify the scale to achieve the value set.
   * > [!NOTE] Changing the width will adjust the scale.x property of the container while maintaining its aspect ratio.
   * > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize}
   * as it is more optimized by not recalculating the local bounds twice.
   * @example
   * ```ts
   * // Basic width setting
   * container.width = 100;
   * // Optimized width setting
   * container.setSize(100, 100);
   * ```
   */
  get width() {
    return Math.abs(this.scale.x * this.getLocalBounds().width);
  }
  set width(t) {
    const e = this.getLocalBounds().width;
    this._setWidth(t, e);
  }
  /**
   * The height of the Container,
   * > [!NOTE] Changing the height will adjust the scale.y property of the container while maintaining its aspect ratio.
   * > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize}
   * as it is more optimized by not recalculating the local bounds twice.
   * @example
   * ```ts
   * // Basic height setting
   * container.height = 200;
   * // Optimized height setting
   * container.setSize(100, 200);
   * ```
   */
  get height() {
    return Math.abs(this.scale.y * this.getLocalBounds().height);
  }
  set height(t) {
    const e = this.getLocalBounds().height;
    this._setHeight(t, e);
  }
  /**
   * Retrieves the size of the container as a [Size]{@link Size} object.
   *
   * This is faster than get the width and height separately.
   * @example
   * ```ts
   * // Basic size retrieval
   * const size = container.getSize();
   * console.log(`Size: ${size.width}x${size.height}`);
   *
   * // Reuse existing size object
   * const reuseSize = { width: 0, height: 0 };
   * container.getSize(reuseSize);
   * ```
   * @param out - Optional object to store the size in.
   * @returns The size of the container.
   */
  getSize(t) {
    t || (t = {});
    const e = this.getLocalBounds();
    return t.width = Math.abs(this.scale.x * e.width), t.height = Math.abs(this.scale.y * e.height), t;
  }
  /**
   * Sets the size of the container to the specified width and height.
   * This is more efficient than setting width and height separately as it only recalculates bounds once.
   * @example
   * ```ts
   * // Basic size setting
   * container.setSize(100, 200);
   *
   * // Set uniform size
   * container.setSize(100); // Sets both width and height to 100
   * ```
   * @param value - This can be either a number or a [Size]{@link Size} object.
   * @param height - The height to set. Defaults to the value of `width` if not provided.
   */
  setSize(t, e) {
    const s = this.getLocalBounds();
    typeof t == "object" ? (e = t.height ?? t.width, t = t.width) : e ?? (e = t), t !== void 0 && this._setWidth(t, s.width), e !== void 0 && this._setHeight(e, s.height);
  }
  /** Called when the skew or the rotation changes. */
  _updateSkew() {
    const t = this._rotation, e = this._skew;
    this._cx = Math.cos(t + e._y), this._sx = Math.sin(t + e._y), this._cy = -Math.sin(t - e._x), this._sy = Math.cos(t - e._x);
  }
  /**
   * Updates the transform properties of the container.
   * Allows partial updates of transform properties for optimized manipulation.
   * @example
   * ```ts
   * // Basic transform update
   * container.updateTransform({
   *     x: 100,
   *     y: 200,
   *     rotation: Math.PI / 4
   * });
   *
   * // Scale and rotate around center
   * sprite.updateTransform({
   *     pivotX: sprite.width / 2,
   *     pivotY: sprite.height / 2,
   *     scaleX: 2,
   *     scaleY: 2,
   *     rotation: Math.PI
   * });
   *
   * // Update position only
   * button.updateTransform({
   *     x: button.x + 10, // Move right
   *     y: button.y      // Keep same y
   * });
   * ```
   * @param opts - Transform options to update
   * @param opts.x - The x position
   * @param opts.y - The y position
   * @param opts.scaleX - The x-axis scale factor
   * @param opts.scaleY - The y-axis scale factor
   * @param opts.rotation - The rotation in radians
   * @param opts.skewX - The x-axis skew factor
   * @param opts.skewY - The y-axis skew factor
   * @param opts.pivotX - The x-axis pivot point
   * @param opts.pivotY - The y-axis pivot point
   * @returns This container, for chaining
   * @see {@link Container#setFromMatrix} For matrix-based transforms
   * @see {@link Container#position} For direct position access
   */
  updateTransform(t) {
    return this.position.set(
      typeof t.x == "number" ? t.x : this.position.x,
      typeof t.y == "number" ? t.y : this.position.y
    ), this.scale.set(
      typeof t.scaleX == "number" ? t.scaleX || 1 : this.scale.x,
      typeof t.scaleY == "number" ? t.scaleY || 1 : this.scale.y
    ), this.rotation = typeof t.rotation == "number" ? t.rotation : this.rotation, this.skew.set(
      typeof t.skewX == "number" ? t.skewX : this.skew.x,
      typeof t.skewY == "number" ? t.skewY : this.skew.y
    ), this.pivot.set(
      typeof t.pivotX == "number" ? t.pivotX : this.pivot.x,
      typeof t.pivotY == "number" ? t.pivotY : this.pivot.y
    ), this.origin.set(
      typeof t.originX == "number" ? t.originX : this.origin.x,
      typeof t.originY == "number" ? t.originY : this.origin.y
    ), this;
  }
  /**
   * Updates the local transform properties by decomposing the given matrix.
   * Extracts position, scale, rotation, and skew from a transformation matrix.
   * @example
   * ```ts
   * // Basic matrix transform
   * const matrix = new Matrix()
   *     .translate(100, 100)
   *     .rotate(Math.PI / 4)
   *     .scale(2, 2);
   *
   * container.setFromMatrix(matrix);
   *
   * // Copy transform from another container
   * const source = new Container();
   * source.position.set(100, 100);
   * source.rotation = Math.PI / 2;
   *
   * target.setFromMatrix(source.localTransform);
   *
   * // Reset transform
   * container.setFromMatrix(Matrix.IDENTITY);
   * ```
   * @param matrix - The matrix to use for updating the transform
   * @see {@link Container#updateTransform} For property-based updates
   * @see {@link Matrix#decompose} For matrix decomposition details
   */
  setFromMatrix(t) {
    t.decompose(this);
  }
  /** Updates the local transform. */
  updateLocalTransform() {
    const t = this._didContainerChangeTick;
    if (this._didLocalTransformChangeId === t)
      return;
    this._didLocalTransformChangeId = t;
    const e = this.localTransform, s = this._scale, i = this._pivot, r = this._origin, o = this._position, a = s._x, l = s._y, c = i._x, h = i._y, u = -r._x, d = -r._y;
    e.a = this._cx * a, e.b = this._sx * a, e.c = this._cy * l, e.d = this._sy * l, e.tx = o._x - (c * e.a + h * e.c) + (u * e.a + d * e.c) - u, e.ty = o._y - (c * e.b + h * e.d) + (u * e.b + d * e.d) - d;
  }
  // / ///// color related stuff
  set alpha(t) {
    t !== this.localAlpha && (this.localAlpha = t, this._updateFlags |= tu, this._onUpdate());
  }
  /**
   * The opacity of the object relative to its parent's opacity.
   * Value ranges from 0 (fully transparent) to 1 (fully opaque).
   * @example
   * ```ts
   * // Basic transparency
   * sprite.alpha = 0.5; // 50% opacity
   *
   * // Inherited opacity
   * container.alpha = 0.5;
   * const child = new Sprite(texture);
   * child.alpha = 0.5;
   * container.addChild(child);
   * // child's effective opacity is 0.25 (0.5 * 0.5)
   * ```
   * @default 1
   * @see {@link Container#visible} For toggling visibility
   * @see {@link Container#renderable} For render control
   */
  get alpha() {
    return this.localAlpha;
  }
  set tint(t) {
    const s = Bt.shared.setValue(t ?? 16777215).toBgrNumber();
    s !== this.localColor && (this.localColor = s, this._updateFlags |= tu, this._onUpdate());
  }
  /**
   * The tint applied to the sprite.
   *
   * This can be any valid {@link ColorSource}.
   * @example
   * ```ts
   * // Basic color tinting
   * container.tint = 0xff0000; // Red tint
   * container.tint = 'red';    // Same as above
   * container.tint = '#00ff00'; // Green
   * container.tint = 'rgb(0,0,255)'; // Blue
   *
   * // Remove tint
   * container.tint = 0xffffff; // White = no tint
   * container.tint = null;     // Also removes tint
   * ```
   * @default 0xFFFFFF
   * @see {@link Container#alpha} For transparency
   * @see {@link Container#visible} For visibility control
   */
  get tint() {
    return oo(this.localColor);
  }
  // / //////////////// blend related stuff
  set blendMode(t) {
    this.localBlendMode !== t && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= Vy, this.localBlendMode = t, this._onUpdate());
  }
  /**
   * The blend mode to be applied to the sprite. Controls how pixels are blended when rendering.
   *
   * Setting to 'normal' will reset to default blending.
   * > [!NOTE] More blend modes are available after importing the `pixi.js/advanced-blend-modes` sub-export.
   * @example
   * ```ts
   * // Basic blend modes
   * sprite.blendMode = 'add';        // Additive blending
   * sprite.blendMode = 'multiply';   // Multiply colors
   * sprite.blendMode = 'screen';     // Screen blend
   *
   * // Reset blend mode
   * sprite.blendMode = 'normal';     // Normal blending
   * ```
   * @default 'normal'
   * @see {@link Container#alpha} For transparency
   * @see {@link Container#tint} For color adjustments
   */
  get blendMode() {
    return this.localBlendMode;
  }
  // / ///////// VISIBILITY / RENDERABLE /////////////////
  /**
   * The visibility of the object. If false the object will not be drawn,
   * and the transform will not be updated.
   * @example
   * ```ts
   * // Basic visibility toggle
   * sprite.visible = false; // Hide sprite
   * sprite.visible = true;  // Show sprite
   * ```
   * @default true
   * @see {@link Container#renderable} For render-only control
   * @see {@link Container#alpha} For transparency
   */
  get visible() {
    return !!(this.localDisplayStatus & 2);
  }
  set visible(t) {
    const e = t ? 2 : 0;
    (this.localDisplayStatus & 2) !== e && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= Ca, this.localDisplayStatus ^= 2, this._onUpdate());
  }
  /** @ignore */
  get culled() {
    return !(this.localDisplayStatus & 4);
  }
  /** @ignore */
  set culled(t) {
    const e = t ? 0 : 4;
    (this.localDisplayStatus & 4) !== e && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= Ca, this.localDisplayStatus ^= 4, this._onUpdate());
  }
  /**
   * Controls whether this object can be rendered. If false the object will not be drawn,
   * but the transform will still be updated. This is different from visible, which skips
   * transform updates.
   * @example
   * ```ts
   * // Basic render control
   * sprite.renderable = false; // Skip rendering
   * sprite.renderable = true;  // Enable rendering
   * ```
   * @default true
   * @see {@link Container#visible} For skipping transform updates
   * @see {@link Container#alpha} For transparency
   */
  get renderable() {
    return !!(this.localDisplayStatus & 1);
  }
  set renderable(t) {
    const e = t ? 1 : 0;
    (this.localDisplayStatus & 1) !== e && (this._updateFlags |= Ca, this.localDisplayStatus ^= 1, this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._onUpdate());
  }
  /**
   * Whether or not the object should be rendered.
   * @advanced
   */
  get isRenderable() {
    return this.localDisplayStatus === 7 && this.groupAlpha > 0;
  }
  /**
   * Removes all internal references and listeners as well as removes children from the display list.
   * Do not use a Container after calling `destroy`.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @example
   * ```ts
   * container.destroy();
   * container.destroy(true);
   * container.destroy({ children: true });
   * container.destroy({ children: true, texture: true, textureSource: true });
   * ```
   */
  destroy(t = !1) {
    if (this.destroyed)
      return;
    this.destroyed = !0;
    let e;
    if (this.children.length && (e = this.removeChildren(0, this.children.length)), this.removeFromParent(), this.parent = null, this._maskEffect = null, this._filterEffect = null, this.effects = null, this._position = null, this._scale = null, this._pivot = null, this._origin = null, this._skew = null, this.emit("destroyed", this), this.removeAllListeners(), (typeof t == "boolean" ? t : t?.children) && e)
      for (let i = 0; i < e.length; ++i)
        e[i].destroy(t);
    this.renderGroup?.destroy(), this.renderGroup = null;
  }
}
ze.mixin(
  Te,
  _y,
  My,
  Fy,
  Ey,
  Ay,
  wy,
  Sy,
  Py,
  my,
  yy,
  ky,
  vy
);
class jo extends Te {
  // eslint-disable-next-line @typescript-eslint/no-useless-constructor
  constructor(t) {
    super(t), this.canBundle = !0, this.allowChildren = !1, this._roundPixels = 0, this._lastUsed = -1, this._gpuData = /* @__PURE__ */ Object.create(null), this._bounds = new Ye(0, 1, 0, 0), this._boundsDirty = !0;
  }
  /**
   * The local bounds of the view in its own coordinate space.
   * Bounds are automatically updated when the view's content changes.
   * @example
   * ```ts
   * // Get bounds dimensions
   * const bounds = view.bounds;
   * console.log(`Width: ${bounds.maxX - bounds.minX}`);
   * console.log(`Height: ${bounds.maxY - bounds.minY}`);
   * ```
   * @returns The rectangular bounds of the view
   * @see {@link Bounds} For bounds operations
   */
  get bounds() {
    return this._boundsDirty ? (this.updateBounds(), this._boundsDirty = !1, this._bounds) : this._bounds;
  }
  /**
   * Whether or not to round the x/y position of the sprite.
   * @example
   * ```ts
   * // Enable pixel rounding for crisp rendering
   * view.roundPixels = true;
   * ```
   * @default false
   */
  get roundPixels() {
    return !!this._roundPixels;
  }
  set roundPixels(t) {
    this._roundPixels = t ? 1 : 0;
  }
  /**
   * Checks if the object contains the given point in local coordinates.
   * Uses the view's bounds for hit testing.
   * @example
   * ```ts
   * // Basic point check
   * const localPoint = { x: 50, y: 25 };
   * const contains = view.containsPoint(localPoint);
   * console.log('Point is inside:', contains);
   * ```
   * @param point - The point to check in local coordinates
   * @returns True if the point is within the view's bounds
   * @see {@link ViewContainer#bounds} For the bounds used in hit testing
   * @see {@link Container#toLocal} For converting global coordinates to local
   */
  containsPoint(t) {
    const e = this.bounds, { x: s, y: i } = t;
    return s >= e.minX && s <= e.maxX && i >= e.minY && i <= e.maxY;
  }
  /** @private */
  onViewUpdate() {
    if (this._didViewChangeTick++, this._boundsDirty = !0, this.didViewUpdate)
      return;
    this.didViewUpdate = !0;
    const t = this.renderGroup || this.parentRenderGroup;
    t && t.onChildViewUpdate(this);
  }
  destroy(t) {
    super.destroy(t), this._bounds = null;
    for (const e in this._gpuData)
      this._gpuData[e].destroy?.();
    this._gpuData = null;
  }
  /**
   * Collects renderables for the view container.
   * @param instructionSet - The instruction set to collect renderables for.
   * @param renderer - The renderer to collect renderables for.
   * @param currentLayer - The current render layer.
   * @internal
   */
  collectRenderablesSimple(t, e, s) {
    const { renderPipes: i } = e;
    i.blendMode.setBlendMode(this, this.groupBlendMode, t), i[this.renderPipeId].addRenderable(this, t), this.didViewUpdate = !1;
    const o = this.children, a = o.length;
    for (let l = 0; l < a; l++)
      o[l].collectRenderables(t, e, s);
  }
}
class wn extends jo {
  /**
   * @param options - The options for creating the sprite.
   */
  constructor(t = rt.EMPTY) {
    t instanceof rt && (t = { texture: t });
    const { texture: e = rt.EMPTY, anchor: s, roundPixels: i, width: r, height: o, ...a } = t;
    super({
      label: "Sprite",
      ...a
    }), this.renderPipeId = "sprite", this.batched = !0, this._visualBounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 }, this._anchor = new Pt(
      {
        _onUpdate: () => {
          this.onViewUpdate();
        }
      }
    ), s ? this.anchor = s : e.defaultAnchor && (this.anchor = e.defaultAnchor), this.texture = e, this.allowChildren = !1, this.roundPixels = i ?? !1, r !== void 0 && (this.width = r), o !== void 0 && (this.height = o);
  }
  /**
   * Creates a new sprite based on a source texture, image, video, or canvas element.
   * This is a convenience method that automatically creates and manages textures.
   * @example
   * ```ts
   * // Create from path or URL
   * const sprite = Sprite.from('assets/image.png');
   *
   * // Create from existing texture
   * const sprite = Sprite.from(texture);
   *
   * // Create from canvas
   * const canvas = document.createElement('canvas');
   * const sprite = Sprite.from(canvas, true); // Skip caching new texture
   * ```
   * @param source - The source to create the sprite from. Can be a path to an image, a texture,
   * or any valid texture source (canvas, video, etc.)
   * @param skipCache - Whether to skip adding to the texture cache when creating a new texture
   * @returns A new sprite based on the source
   * @see {@link Texture.from} For texture creation details
   * @see {@link Assets} For asset loading and management
   */
  static from(t, e = !1) {
    return t instanceof rt ? new wn(t) : new wn(rt.from(t, e));
  }
  set texture(t) {
    t || (t = rt.EMPTY);
    const e = this._texture;
    e !== t && (e && e.dynamic && e.off("update", this.onViewUpdate, this), t.dynamic && t.on("update", this.onViewUpdate, this), this._texture = t, this._width && this._setWidth(this._width, this._texture.orig.width), this._height && this._setHeight(this._height, this._texture.orig.height), this.onViewUpdate());
  }
  /**
   * The texture that is displayed by the sprite. When changed, automatically updates
   * the sprite dimensions and manages texture event listeners.
   * @example
   * ```ts
   * // Create sprite with texture
   * const sprite = new Sprite({
   *     texture: Texture.from('sprite.png')
   * });
   *
   * // Update texture
   * sprite.texture = Texture.from('newSprite.png');
   *
   * // Use texture from spritesheet
   * const sheet = await Assets.load('spritesheet.json');
   * sprite.texture = sheet.textures['frame1.png'];
   *
   * // Reset to empty texture
   * sprite.texture = Texture.EMPTY;
   * ```
   * @see {@link Texture} For texture creation and management
   * @see {@link Assets} For asset loading
   */
  get texture() {
    return this._texture;
  }
  /**
   * The bounds of the sprite, taking into account the texture's trim area.
   * @example
   * ```ts
   * const texture = new Texture({
   *     source: new TextureSource({ width: 300, height: 300 }),
   *     frame: new Rectangle(196, 66, 58, 56),
   *     trim: new Rectangle(4, 4, 58, 56),
   *     orig: new Rectangle(0, 0, 64, 64),
   *     rotate: 2,
   * });
   * const sprite = new Sprite(texture);
   * const visualBounds = sprite.visualBounds;
   * // console.log(visualBounds); // { minX: -4, maxX: 62, minY: -4, maxY: 60 }
   */
  get visualBounds() {
    return ry(this._visualBounds, this._anchor, this._texture), this._visualBounds;
  }
  /**
   * @deprecated
   * @ignore
   */
  get sourceBounds() {
    return ct("8.6.1", "Sprite.sourceBounds is deprecated, use visualBounds instead."), this.visualBounds;
  }
  /** @private */
  updateBounds() {
    const t = this._anchor, e = this._texture, s = this._bounds, { width: i, height: r } = e.orig;
    s.minX = -t._x * i, s.maxX = s.minX + i, s.minY = -t._y * r, s.maxY = s.minY + r;
  }
  /**
   * Destroys this sprite renderable and optionally its texture.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @example
   * sprite.destroy();
   * sprite.destroy(true);
   * sprite.destroy({ texture: true, textureSource: true });
   */
  destroy(t = !1) {
    if (super.destroy(t), typeof t == "boolean" ? t : t?.texture) {
      const s = typeof t == "boolean" ? t : t?.textureSource;
      this._texture.destroy(s);
    }
    this._texture = null, this._visualBounds = null, this._bounds = null, this._anchor = null, this._gpuData = null;
  }
  /**
   * The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
   * and passed to the constructor.
   *
   * - The default is `(0,0)`, this means the sprite's origin is the top left.
   * - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
   * - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
   *
   * If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
   * @example
   * ```ts
   * // Center the anchor point
   * sprite.anchor = 0.5; // Sets both x and y to 0.5
   * sprite.position.set(400, 300); // Sprite will be centered at this position
   *
   * // Set specific x/y anchor points
   * sprite.anchor = {
   *     x: 1, // Right edge
   *     y: 0  // Top edge
   * };
   *
   * // Using individual coordinates
   * sprite.anchor.set(0.5, 1); // Center-bottom
   *
   * // For rotation around center
   * sprite.anchor.set(0.5);
   * sprite.rotation = Math.PI / 4; // 45 degrees around center
   *
   * // For scaling from center
   * sprite.anchor.set(0.5);
   * sprite.scale.set(2); // Scales from center point
   * ```
   */
  get anchor() {
    return this._anchor;
  }
  set anchor(t) {
    typeof t == "number" ? this._anchor.set(t) : this._anchor.copyFrom(t);
  }
  /**
   * The width of the sprite, setting this will actually modify the scale to achieve the value set.
   * @example
   * ```ts
   * // Set width directly
   * sprite.width = 200;
   * console.log(sprite.scale.x); // Scale adjusted to match width
   *
   * // Set width while preserving aspect ratio
   * const ratio = sprite.height / sprite.width;
   * sprite.width = 300;
   * sprite.height = 300 * ratio;
   *
   * // For better performance when setting both width and height
   * sprite.setSize(300, 400); // Avoids recalculating bounds twice
   *
   * // Reset to original texture size
   * sprite.width = sprite.texture.orig.width;
   * ```
   */
  get width() {
    return Math.abs(this.scale.x) * this._texture.orig.width;
  }
  set width(t) {
    this._setWidth(t, this._texture.orig.width), this._width = t;
  }
  /**
   * The height of the sprite, setting this will actually modify the scale to achieve the value set.
   * @example
   * ```ts
   * // Set height directly
   * sprite.height = 150;
   * console.log(sprite.scale.y); // Scale adjusted to match height
   *
   * // Set height while preserving aspect ratio
   * const ratio = sprite.width / sprite.height;
   * sprite.height = 200;
   * sprite.width = 200 * ratio;
   *
   * // For better performance when setting both width and height
   * sprite.setSize(300, 400); // Avoids recalculating bounds twice
   *
   * // Reset to original texture size
   * sprite.height = sprite.texture.orig.height;
   * ```
   */
  get height() {
    return Math.abs(this.scale.y) * this._texture.orig.height;
  }
  set height(t) {
    this._setHeight(t, this._texture.orig.height), this._height = t;
  }
  /**
   * Retrieves the size of the Sprite as a [Size]{@link Size} object based on the texture dimensions and scale.
   * This is faster than getting width and height separately as it only calculates the bounds once.
   * @example
   * ```ts
   * // Basic size retrieval
   * const sprite = new Sprite(Texture.from('sprite.png'));
   * const size = sprite.getSize();
   * console.log(`Size: ${size.width}x${size.height}`);
   *
   * // Reuse existing size object
   * const reuseSize = { width: 0, height: 0 };
   * sprite.getSize(reuseSize);
   * ```
   * @param out - Optional object to store the size in, to avoid allocating a new object
   * @returns The size of the Sprite
   * @see {@link Sprite#width} For getting just the width
   * @see {@link Sprite#height} For getting just the height
   * @see {@link Sprite#setSize} For setting both width and height
   */
  getSize(t) {
    return t || (t = {}), t.width = Math.abs(this.scale.x) * this._texture.orig.width, t.height = Math.abs(this.scale.y) * this._texture.orig.height, t;
  }
  /**
   * Sets the size of the Sprite to the specified width and height.
   * This is faster than setting width and height separately as it only recalculates bounds once.
   * @example
   * ```ts
   * // Basic size setting
   * const sprite = new Sprite(Texture.from('sprite.png'));
   * sprite.setSize(100, 200); // Width: 100, Height: 200
   *
   * // Set uniform size
   * sprite.setSize(100); // Sets both width and height to 100
   *
   * // Set size with object
   * sprite.setSize({
   *     width: 200,
   *     height: 300
   * });
   *
   * // Reset to texture size
   * sprite.setSize(
   *     sprite.texture.orig.width,
   *     sprite.texture.orig.height
   * );
   * ```
   * @param value - This can be either a number or a {@link Size} object
   * @param height - The height to set. Defaults to the value of `width` if not provided
   * @see {@link Sprite#width} For setting width only
   * @see {@link Sprite#height} For setting height only
   * @see {@link Sprite#texture} For the source dimensions
   */
  setSize(t, e) {
    typeof t == "object" ? (e = t.height ?? t.width, t = t.width) : e ?? (e = t), t !== void 0 && this._setWidth(t, this._texture.orig.width), e !== void 0 && this._setHeight(e, this._texture.orig.height);
  }
}
const By = new Ye();
function Hf(n, t, e) {
  const s = By;
  n.measurable = !0, Bf(n, e, s), t.addBoundsMask(s), n.measurable = !1;
}
function jf(n, t, e) {
  const s = ks.get();
  n.measurable = !0;
  const i = ae.get().identity(), r = Xf(n, e, i);
  Uf(n, s, r), n.measurable = !1, t.addBoundsMask(s), ae.return(i), ks.return(s);
}
function Xf(n, t, e) {
  return n ? (n !== t && (Xf(n.parent, t, e), n.updateLocalTransform(), e.append(n.localTransform)), e) : (Ht("Mask bounds, renderable is not inside the root container"), e);
}
class Yf {
  constructor(t) {
    this.priority = 0, this.inverse = !1, this.pipe = "alphaMask", t?.mask && this.init(t.mask);
  }
  init(t) {
    this.mask = t, this.renderMaskToTexture = !(t instanceof wn), this.mask.renderable = this.renderMaskToTexture, this.mask.includeInBuild = !this.renderMaskToTexture, this.mask.measurable = !1;
  }
  reset() {
    this.mask.measurable = !0, this.mask = null;
  }
  addBounds(t, e) {
    this.inverse || Hf(this.mask, t, e);
  }
  addLocalBounds(t, e) {
    jf(this.mask, t, e);
  }
  containsPoint(t, e) {
    const s = this.mask;
    return e(s, t);
  }
  destroy() {
    this.reset();
  }
  static test(t) {
    return t instanceof wn;
  }
}
Yf.extension = dt.MaskEffect;
class Zf {
  constructor(t) {
    this.priority = 0, this.pipe = "colorMask", t?.mask && this.init(t.mask);
  }
  init(t) {
    this.mask = t;
  }
  destroy() {
  }
  static test(t) {
    return typeof t == "number";
  }
}
Zf.extension = dt.MaskEffect;
class Kf {
  constructor(t) {
    this.priority = 0, this.pipe = "stencilMask", t?.mask && this.init(t.mask);
  }
  init(t) {
    this.mask = t, this.mask.includeInBuild = !1, this.mask.measurable = !1;
  }
  reset() {
    this.mask.measurable = !0, this.mask.includeInBuild = !0, this.mask = null;
  }
  addBounds(t, e) {
    Hf(this.mask, t, e);
  }
  addLocalBounds(t, e) {
    jf(this.mask, t, e);
  }
  containsPoint(t, e) {
    const s = this.mask;
    return e(s, t);
  }
  destroy() {
    this.reset();
  }
  static test(t) {
    return t instanceof Te;
  }
}
Kf.extension = dt.MaskEffect;
const zy = {
  createCanvas: (n, t) => {
    const e = document.createElement("canvas");
    return e.width = n, e.height = t, e;
  },
  createImage: () => new Image(),
  getCanvasRenderingContext2D: () => CanvasRenderingContext2D,
  getWebGLRenderingContext: () => WebGLRenderingContext,
  getNavigator: () => navigator,
  getBaseUrl: () => document.baseURI ?? window.location.href,
  getFontFaceSet: () => document.fonts,
  fetch: (n, t) => fetch(n, t),
  parseXML: (n) => new DOMParser().parseFromString(n, "text/xml")
};
let eu = zy;
const Ae = {
  /**
   * Returns the current adapter.
   * @returns {environment.Adapter} The current adapter.
   */
  get() {
    return eu;
  },
  /**
   * Sets the current adapter.
   * @param adapter - The new adapter.
   */
  set(n) {
    eu = n;
  }
};
class Qf extends Je {
  constructor(t) {
    t.resource || (t.resource = Ae.get().createCanvas()), t.width || (t.width = t.resource.width, t.autoDensity || (t.width /= t.resolution)), t.height || (t.height = t.resource.height, t.autoDensity || (t.height /= t.resolution)), super(t), this.uploadMethodId = "image", this.autoDensity = t.autoDensity, this.resizeCanvas(), this.transparent = !!t.transparent;
  }
  resizeCanvas() {
    this.autoDensity && "style" in this.resource && (this.resource.style.width = `${this.width}px`, this.resource.style.height = `${this.height}px`), (this.resource.width !== this.pixelWidth || this.resource.height !== this.pixelHeight) && (this.resource.width = this.pixelWidth, this.resource.height = this.pixelHeight);
  }
  resize(t = this.width, e = this.height, s = this._resolution) {
    const i = super.resize(t, e, s);
    return i && this.resizeCanvas(), i;
  }
  static test(t) {
    return globalThis.HTMLCanvasElement && t instanceof HTMLCanvasElement || globalThis.OffscreenCanvas && t instanceof OffscreenCanvas;
  }
  /**
   * Returns the 2D rendering context for the canvas.
   * Caches the context after creating it.
   * @returns The 2D rendering context of the canvas.
   */
  get context2D() {
    return this._context2D || (this._context2D = this.resource.getContext("2d"));
  }
}
Qf.extension = dt.TextureSource;
class go extends Je {
  constructor(t) {
    super(t), this.uploadMethodId = "image", this.autoGarbageCollect = !0;
  }
  static test(t) {
    return globalThis.HTMLImageElement && t instanceof HTMLImageElement || typeof ImageBitmap < "u" && t instanceof ImageBitmap || globalThis.VideoFrame && t instanceof VideoFrame;
  }
}
go.extension = dt.TextureSource;
var cl = /* @__PURE__ */ ((n) => (n[n.INTERACTION = 50] = "INTERACTION", n[n.HIGH = 25] = "HIGH", n[n.NORMAL = 0] = "NORMAL", n[n.LOW = -25] = "LOW", n[n.UTILITY = -50] = "UTILITY", n))(cl || {});
class Aa {
  /**
   * Constructor
   * @private
   * @param fn - The listener function to be added for one update
   * @param context - The listener context
   * @param priority - The priority for emitting
   * @param once - If the handler should fire once
   */
  constructor(t, e = null, s = 0, i = !1) {
    this.next = null, this.previous = null, this._destroyed = !1, this._fn = t, this._context = e, this.priority = s, this._once = i;
  }
  /**
   * Simple compare function to figure out if a function and context match.
   * @param fn - The listener function to be added for one update
   * @param context - The listener context
   * @returns `true` if the listener match the arguments
   */
  match(t, e = null) {
    return this._fn === t && this._context === e;
  }
  /**
   * Emit by calling the current function.
   * @param ticker - The ticker emitting.
   * @returns Next ticker
   */
  emit(t) {
    this._fn && (this._context ? this._fn.call(this._context, t) : this._fn(t));
    const e = this.next;
    return this._once && this.destroy(!0), this._destroyed && (this.next = null), e;
  }
  /**
   * Connect to the list.
   * @param previous - Input node, previous listener
   */
  connect(t) {
    this.previous = t, t.next && (t.next.previous = this), this.next = t.next, t.next = this;
  }
  /**
   * Destroy and don't use after this.
   * @param hard - `true` to remove the `next` reference, this
   *        is considered a hard destroy. Soft destroy maintains the next reference.
   * @returns The listener to redirect while emitting or removing.
   */
  destroy(t = !1) {
    this._destroyed = !0, this._fn = null, this._context = null, this.previous && (this.previous.next = this.next), this.next && (this.next.previous = this.previous);
    const e = this.next;
    return this.next = t ? null : e, this.previous = null, e;
  }
}
const Jf = class Se {
  constructor() {
    this.autoStart = !1, this.deltaTime = 1, this.lastTime = -1, this.speed = 1, this.started = !1, this._requestId = null, this._maxElapsedMS = 100, this._minElapsedMS = 0, this._protected = !1, this._lastFrame = -1, this._head = new Aa(null, null, 1 / 0), this.deltaMS = 1 / Se.targetFPMS, this.elapsedMS = 1 / Se.targetFPMS, this._tick = (t) => {
      this._requestId = null, this.started && (this.update(t), this.started && this._requestId === null && this._head.next && (this._requestId = requestAnimationFrame(this._tick)));
    };
  }
  /**
   * Conditionally requests a new animation frame.
   * If a frame has not already been requested, and if the internal
   * emitter has listeners, a new frame is requested.
   */
  _requestIfNeeded() {
    this._requestId === null && this._head.next && (this.lastTime = performance.now(), this._lastFrame = this.lastTime, this._requestId = requestAnimationFrame(this._tick));
  }
  /** Conditionally cancels a pending animation frame. */
  _cancelIfNeeded() {
    this._requestId !== null && (cancelAnimationFrame(this._requestId), this._requestId = null);
  }
  /**
   * Conditionally requests a new animation frame.
   * If the ticker has been started it checks if a frame has not already
   * been requested, and if the internal emitter has listeners. If these
   * conditions are met, a new frame is requested. If the ticker has not
   * been started, but autoStart is `true`, then the ticker starts now,
   * and continues with the previous conditions to request a new frame.
   */
  _startIfPossible() {
    this.started ? this._requestIfNeeded() : this.autoStart && this.start();
  }
  /**
   * Register a handler for tick events. Calls continuously unless
   * it is removed or the ticker is stopped.
   * @example
   * ```ts
   * // Basic update handler
   * ticker.add((ticker) => {
   *     // Update every frame
   *     sprite.rotation += 0.1 * ticker.deltaTime;
   * });
   *
   * // With specific context
   * const game = {
   *     update(ticker) {
   *         this.physics.update(ticker.deltaTime);
   *     }
   * };
   * ticker.add(game.update, game);
   *
   * // With priority
   * ticker.add(
   *     (ticker) => {
   *         // Runs before normal priority updates
   *         physics.update(ticker.deltaTime);
   *     },
   *     undefined,
   *     UPDATE_PRIORITY.HIGH
   * );
   * ```
   * @param fn - The listener function to be added for updates
   * @param context - The listener context
   * @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL)
   * @returns This instance of a ticker
   * @see {@link Ticker#addOnce} For one-time handlers
   * @see {@link Ticker#remove} For removing handlers
   */
  add(t, e, s = cl.NORMAL) {
    return this._addListener(new Aa(t, e, s));
  }
  /**
   * Add a handler for the tick event which is only executed once on the next frame.
   * @example
   * ```ts
   * // Basic one-time update
   * ticker.addOnce(() => {
   *     console.log('Runs next frame only');
   * });
   *
   * // With specific context
   * const game = {
   *     init(ticker) {
   *         this.loadResources();
   *         console.log('Game initialized');
   *     }
   * };
   * ticker.addOnce(game.init, game);
   *
   * // With priority
   * ticker.addOnce(
   *     () => {
   *         // High priority one-time setup
   *         physics.init();
   *     },
   *     undefined,
   *     UPDATE_PRIORITY.HIGH
   * );
   * ```
   * @param fn - The listener function to be added for one update
   * @param context - The listener context
   * @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL)
   * @returns This instance of a ticker
   * @see {@link Ticker#add} For continuous updates
   * @see {@link Ticker#remove} For removing handlers
   */
  addOnce(t, e, s = cl.NORMAL) {
    return this._addListener(new Aa(t, e, s, !0));
  }
  /**
   * Internally adds the event handler so that it can be sorted by priority.
   * Priority allows certain handler (user, AnimatedSprite, Interaction) to be run
   * before the rendering.
   * @private
   * @param listener - Current listener being added.
   * @returns This instance of a ticker
   */
  _addListener(t) {
    let e = this._head.next, s = this._head;
    if (!e)
      t.connect(s);
    else {
      for (; e; ) {
        if (t.priority > e.priority) {
          t.connect(s);
          break;
        }
        s = e, e = e.next;
      }
      t.previous || t.connect(s);
    }
    return this._startIfPossible(), this;
  }
  /**
   * Removes any handlers matching the function and context parameters.
   * If no handlers are left after removing, then it cancels the animation frame.
   * @example
   * ```ts
   * // Basic removal
   * const onTick = () => {
   *     sprite.rotation += 0.1;
   * };
   * ticker.add(onTick);
   * ticker.remove(onTick);
   *
   * // Remove with context
   * const game = {
   *     update(ticker) {
   *         this.physics.update(ticker.deltaTime);
   *     }
   * };
   * ticker.add(game.update, game);
   * ticker.remove(game.update, game);
   *
   * // Remove all matching handlers
   * // (if same function was added multiple times)
   * ticker.add(onTick);
   * ticker.add(onTick);
   * ticker.remove(onTick); // Removes all instances
   * ```
   * @param fn - The listener function to be removed
   * @param context - The listener context to be removed
   * @returns This instance of a ticker
   * @see {@link Ticker#add} For adding handlers
   * @see {@link Ticker#addOnce} For one-time handlers
   */
  remove(t, e) {
    let s = this._head.next;
    for (; s; )
      s.match(t, e) ? s = s.destroy() : s = s.next;
    return this._head.next || this._cancelIfNeeded(), this;
  }
  /**
   * The number of listeners on this ticker, calculated by walking through linked list.
   * @example
   * ```ts
   * // Check number of active listeners
   * const ticker = new Ticker();
   * console.log(ticker.count); // 0
   *
   * // Add some listeners
   * ticker.add(() => {});
   * ticker.add(() => {});
   * console.log(ticker.count); // 2
   *
   * // Check after cleanup
   * ticker.destroy();
   * console.log(ticker.count); // 0
   * ```
   * @readonly
   * @see {@link Ticker#add} For adding listeners
   * @see {@link Ticker#remove} For removing listeners
   */
  get count() {
    if (!this._head)
      return 0;
    let t = 0, e = this._head;
    for (; e = e.next; )
      t++;
    return t;
  }
  /**
   * Starts the ticker. If the ticker has listeners a new animation frame is requested at this point.
   * @example
   * ```ts
   * // Basic manual start
   * const ticker = new Ticker();
   * ticker.add(() => {
   *     // Animation code here
   * });
   * ticker.start();
   * ```
   * @see {@link Ticker#stop} For stopping the ticker
   * @see {@link Ticker#autoStart} For automatic starting
   * @see {@link Ticker#started} For checking ticker state
   */
  start() {
    this.started || (this.started = !0, this._requestIfNeeded());
  }
  /**
   * Stops the ticker. If the ticker has requested an animation frame it is canceled at this point.
   * @example
   * ```ts
   * // Basic stop
   * const ticker = new Ticker();
   * ticker.stop();
   * ```
   * @see {@link Ticker#start} For starting the ticker
   * @see {@link Ticker#started} For checking ticker state
   * @see {@link Ticker#destroy} For cleaning up the ticker
   */
  stop() {
    this.started && (this.started = !1, this._cancelIfNeeded());
  }
  /**
   * Destroy the ticker and don't use after this. Calling this method removes all references to internal events.
   * @example
   * ```ts
   * // Clean up with active listeners
   * const ticker = new Ticker();
   * ticker.add(() => {});
   * ticker.destroy(); // Removes all listeners
   * ```
   * @see {@link Ticker#stop} For stopping without destroying
   * @see {@link Ticker#remove} For removing specific listeners
   */
  destroy() {
    if (!this._protected) {
      this.stop();
      let t = this._head.next;
      for (; t; )
        t = t.destroy(!0);
      this._head.destroy(), this._head = null;
    }
  }
  /**
   * Triggers an update.
   *
   * An update entails setting the
   * current {@link Ticker#elapsedMS|elapsedMS},
   * the current {@link Ticker#deltaTime|deltaTime},
   * invoking all listeners with current deltaTime,
   * and then finally setting {@link Ticker#lastTime|lastTime}
   * with the value of currentTime that was provided.
   *
   * This method will be called automatically by animation
   * frame callbacks if the ticker instance has been started
   * and listeners are added.
   * @example
   * ```ts
   * // Basic manual update
   * const ticker = new Ticker();
   * ticker.update(performance.now());
   * ```
   * @param currentTime - The current time of execution (defaults to performance.now())
   * @see {@link Ticker#deltaTime} For frame delta value
   * @see {@link Ticker#elapsedMS} For raw elapsed time
   */
  update(t = performance.now()) {
    let e;
    if (t > this.lastTime) {
      if (e = this.elapsedMS = t - this.lastTime, e > this._maxElapsedMS && (e = this._maxElapsedMS), e *= this.speed, this._minElapsedMS) {
        const r = t - this._lastFrame | 0;
        if (r < this._minElapsedMS)
          return;
        this._lastFrame = t - r % this._minElapsedMS;
      }
      this.deltaMS = e, this.deltaTime = this.deltaMS * Se.targetFPMS;
      const s = this._head;
      let i = s.next;
      for (; i; )
        i = i.emit(this);
      s.next || this._cancelIfNeeded();
    } else
      this.deltaTime = this.deltaMS = this.elapsedMS = 0;
    this.lastTime = t;
  }
  /**
   * The frames per second at which this ticker is running.
   * The default is approximately 60 in most modern browsers.
   * > [!NOTE] This does not factor in the value of
   * > {@link Ticker#speed|speed}, which is specific
   * > to scaling {@link Ticker#deltaTime|deltaTime}.
   * @example
   * ```ts
   * // Basic FPS monitoring
   * ticker.add(() => {
   *     console.log(`Current FPS: ${Math.round(ticker.FPS)}`);
   * });
   * ```
   * @readonly
   */
  get FPS() {
    return 1e3 / this.elapsedMS;
  }
  /**
   * Manages the maximum amount of milliseconds allowed to
   * elapse between invoking {@link Ticker#update|update}.
   *
   * This value is used to cap {@link Ticker#deltaTime|deltaTime},
   * but does not effect the measured value of {@link Ticker#FPS|FPS}.
   *
   * When setting this property it is clamped to a value between
   * `0` and `Ticker.targetFPMS * 1000`.
   * @example
   * ```ts
   * // Set minimum acceptable frame rate
   * const ticker = new Ticker();
   * ticker.minFPS = 30; // Never go below 30 FPS
   *
   * // Use with maxFPS for frame rate clamping
   * ticker.minFPS = 30;
   * ticker.maxFPS = 60;
   *
   * // Monitor delta capping
   * ticker.add(() => {
   *     // Delta time will be capped based on minFPS
   *     console.log(`Delta time: ${ticker.deltaTime}`);
   * });
   * ```
   * @default 10
   */
  get minFPS() {
    return 1e3 / this._maxElapsedMS;
  }
  set minFPS(t) {
    const e = Math.min(this.maxFPS, t), s = Math.min(Math.max(0, e) / 1e3, Se.targetFPMS);
    this._maxElapsedMS = 1 / s;
  }
  /**
   * Manages the minimum amount of milliseconds required to
   * elapse between invoking {@link Ticker#update|update}.
   *
   * This will effect the measured value of {@link Ticker#FPS|FPS}.
   *
   * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can.
   * Otherwise it will be at least `minFPS`
   * @example
   * ```ts
   * // Set minimum acceptable frame rate
   * const ticker = new Ticker();
   * ticker.maxFPS = 60; // Never go above 60 FPS
   *
   * // Use with maxFPS for frame rate clamping
   * ticker.minFPS = 30;
   * ticker.maxFPS = 60;
   *
   * // Monitor delta capping
   * ticker.add(() => {
   *     // Delta time will be capped based on maxFPS
   *     console.log(`Delta time: ${ticker.deltaTime}`);
   * });
   * ```
   * @default 0
   */
  get maxFPS() {
    return this._minElapsedMS ? Math.round(1e3 / this._minElapsedMS) : 0;
  }
  set maxFPS(t) {
    if (t === 0)
      this._minElapsedMS = 0;
    else {
      const e = Math.max(this.minFPS, t);
      this._minElapsedMS = 1 / (e / 1e3);
    }
  }
  /**
   * The shared ticker instance used by {@link AnimatedSprite} and by
   * {@link VideoSource} to update animation frames / video textures.
   *
   * It may also be used by {@link Application} if created with the `sharedTicker` option property set to true.
   *
   * The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance.
   * Please follow the examples for usage, including how to opt-out of auto-starting the shared ticker.
   * @example
   * import { Ticker } from 'pixi.js';
   *
   * const ticker = Ticker.shared;
   * // Set this to prevent starting this ticker when listeners are added.
   * // By default this is true only for the Ticker.shared instance.
   * ticker.autoStart = false;
   *
   * // FYI, call this to ensure the ticker is stopped. It should be stopped
   * // if you have not attempted to render anything yet.
   * ticker.stop();
   *
   * // Call this when you are ready for a running shared ticker.
   * ticker.start();
   * @example
   * import { autoDetectRenderer, Container } from 'pixi.js';
   *
   * // You may use the shared ticker to render...
   * const renderer = autoDetectRenderer();
   * const stage = new Container();
   * document.body.appendChild(renderer.view);
   * ticker.add((time) => renderer.render(stage));
   *
   * // Or you can just update it manually.
   * ticker.autoStart = false;
   * ticker.stop();
   * const animate = (time) => {
   *     ticker.update(time);
   *     renderer.render(stage);
   *     requestAnimationFrame(animate);
   * };
   * animate(performance.now());
   * @type {Ticker}
   * @readonly
   */
  static get shared() {
    if (!Se._shared) {
      const t = Se._shared = new Se();
      t.autoStart = !0, t._protected = !0;
    }
    return Se._shared;
  }
  /**
   * The system ticker instance used by {@link PrepareBase} for core timing
   * functionality that shouldn't usually need to be paused, unlike the `shared`
   * ticker which drives visual animations and rendering which may want to be paused.
   *
   * The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance.
   * @type {Ticker}
   * @readonly
   * @advanced
   */
  static get system() {
    if (!Se._system) {
      const t = Se._system = new Se();
      t.autoStart = !0, t._protected = !0;
    }
    return Se._system;
  }
};
Jf.targetFPMS = 0.06;
let Ur = Jf, Ea;
async function qy() {
  return Ea ?? (Ea = (async () => {
    const t = Ae.get().createCanvas(1, 1).getContext("webgl");
    if (!t)
      return "premultiply-alpha-on-upload";
    const e = await new Promise((o) => {
      const a = document.createElement("video");
      a.onloadeddata = () => o(a), a.onerror = () => o(null), a.autoplay = !1, a.crossOrigin = "anonymous", a.preload = "auto", a.src = "data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHTEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggEXTbuMU6uEHFO7a1OsggG97AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQkBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua8yuAQAAAAAAAEPXgQFzxYgAAAAAAAAAAZyBACK1nIN1bmSIgQCGhVZfVlA5g4EBI+ODhAJiWgDglLCBArqBApqBAlPAgQFVsIRVuYEBElTDZ9Vzc9JjwItjxYgAAAAAAAAAAWfInEWjh0VOQ09ERVJEh49MYXZjIGxpYnZweC12cDlnyKJFo4hEVVJBVElPTkSHlDAwOjAwOjAwLjA0MDAwMDAwMAAAH0O2dcfngQCgwqGggQAAAIJJg0IAABAAFgA4JBwYSgAAICAAEb///4r+AAB1oZ2mm+6BAaWWgkmDQgAAEAAWADgkHBhKAAAgIABIQBxTu2uRu4+zgQC3iveBAfGCAXHwgQM=", a.load();
    });
    if (!e)
      return "premultiply-alpha-on-upload";
    const s = t.createTexture();
    t.bindTexture(t.TEXTURE_2D, s);
    const i = t.createFramebuffer();
    t.bindFramebuffer(t.FRAMEBUFFER, i), t.framebufferTexture2D(
      t.FRAMEBUFFER,
      t.COLOR_ATTACHMENT0,
      t.TEXTURE_2D,
      s,
      0
    ), t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !1), t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL, t.NONE), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, e);
    const r = new Uint8Array(4);
    return t.readPixels(0, 0, 1, 1, t.RGBA, t.UNSIGNED_BYTE, r), t.deleteFramebuffer(i), t.deleteTexture(s), t.getExtension("WEBGL_lose_context")?.loseContext(), r[0] <= r[3] ? "premultiplied-alpha" : "premultiply-alpha-on-upload";
  })()), Ea;
}
const Xo = class tp extends Je {
  constructor(t) {
    super(t), this.isReady = !1, this.uploadMethodId = "video", t = {
      ...tp.defaultOptions,
      ...t
    }, this._autoUpdate = !0, this._isConnectedToTicker = !1, this._updateFPS = t.updateFPS || 0, this._msToNextUpdate = 0, this.autoPlay = t.autoPlay !== !1, this.alphaMode = t.alphaMode ?? "premultiply-alpha-on-upload", this._videoFrameRequestCallback = this._videoFrameRequestCallback.bind(this), this._videoFrameRequestCallbackHandle = null, this._load = null, this._resolve = null, this._reject = null, this._onCanPlay = this._onCanPlay.bind(this), this._onCanPlayThrough = this._onCanPlayThrough.bind(this), this._onError = this._onError.bind(this), this._onPlayStart = this._onPlayStart.bind(this), this._onPlayStop = this._onPlayStop.bind(this), this._onSeeked = this._onSeeked.bind(this), t.autoLoad !== !1 && this.load();
  }
  /** Update the video frame if the source is not destroyed and meets certain conditions. */
  updateFrame() {
    if (!this.destroyed) {
      if (this._updateFPS) {
        const t = Ur.shared.elapsedMS * this.resource.playbackRate;
        this._msToNextUpdate = Math.floor(this._msToNextUpdate - t);
      }
      (!this._updateFPS || this._msToNextUpdate <= 0) && (this._msToNextUpdate = this._updateFPS ? Math.floor(1e3 / this._updateFPS) : 0), this.isValid && this.update();
    }
  }
  /** Callback to update the video frame and potentially request the next frame update. */
  _videoFrameRequestCallback() {
    this.updateFrame(), this.destroyed ? this._videoFrameRequestCallbackHandle = null : this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback(
      this._videoFrameRequestCallback
    );
  }
  /**
   * Checks if the resource has valid dimensions.
   * @returns {boolean} True if width and height are set, otherwise false.
   */
  get isValid() {
    return !!this.resource.videoWidth && !!this.resource.videoHeight;
  }
  /**
   * Start preloading the video resource.
   * @returns {Promise<this>} Handle the validate event
   */
  async load() {
    if (this._load)
      return this._load;
    const t = this.resource, e = this.options;
    return (t.readyState === t.HAVE_ENOUGH_DATA || t.readyState === t.HAVE_FUTURE_DATA) && t.width && t.height && (t.complete = !0), t.addEventListener("play", this._onPlayStart), t.addEventListener("pause", this._onPlayStop), t.addEventListener("seeked", this._onSeeked), this._isSourceReady() ? this._mediaReady() : (e.preload || t.addEventListener("canplay", this._onCanPlay), t.addEventListener("canplaythrough", this._onCanPlayThrough), t.addEventListener("error", this._onError, !0)), this.alphaMode = await qy(), this._load = new Promise((s, i) => {
      this.isValid ? s(this) : (this._resolve = s, this._reject = i, e.preloadTimeoutMs !== void 0 && (this._preloadTimeout = setTimeout(() => {
        this._onError(new ErrorEvent(`Preload exceeded timeout of ${e.preloadTimeoutMs}ms`));
      })), t.load());
    }), this._load;
  }
  /**
   * Handle video error events.
   * @param event - The error event
   */
  _onError(t) {
    this.resource.removeEventListener("error", this._onError, !0), this.emit("error", t), this._reject && (this._reject(t), this._reject = null, this._resolve = null);
  }
  /**
   * Checks if the underlying source is playing.
   * @returns True if playing.
   */
  _isSourcePlaying() {
    const t = this.resource;
    return !t.paused && !t.ended;
  }
  /**
   * Checks if the underlying source is ready for playing.
   * @returns True if ready.
   */
  _isSourceReady() {
    return this.resource.readyState > 2;
  }
  /** Runs the update loop when the video is ready to play. */
  _onPlayStart() {
    this.isValid || this._mediaReady(), this._configureAutoUpdate();
  }
  /** Stops the update loop when a pause event is triggered. */
  _onPlayStop() {
    this._configureAutoUpdate();
  }
  /** Handles behavior when the video completes seeking to the current playback position. */
  _onSeeked() {
    this._autoUpdate && !this._isSourcePlaying() && (this._msToNextUpdate = 0, this.updateFrame(), this._msToNextUpdate = 0);
  }
  _onCanPlay() {
    this.resource.removeEventListener("canplay", this._onCanPlay), this._mediaReady();
  }
  _onCanPlayThrough() {
    this.resource.removeEventListener("canplaythrough", this._onCanPlay), this._preloadTimeout && (clearTimeout(this._preloadTimeout), this._preloadTimeout = void 0), this._mediaReady();
  }
  /** Fired when the video is loaded and ready to play. */
  _mediaReady() {
    const t = this.resource;
    this.isValid && (this.isReady = !0, this.resize(t.videoWidth, t.videoHeight)), this._msToNextUpdate = 0, this.updateFrame(), this._msToNextUpdate = 0, this._resolve && (this._resolve(this), this._resolve = null, this._reject = null), this._isSourcePlaying() ? this._onPlayStart() : this.autoPlay && this.resource.play();
  }
  /** Cleans up resources and event listeners associated with this texture. */
  destroy() {
    this._configureAutoUpdate();
    const t = this.resource;
    t && (t.removeEventListener("play", this._onPlayStart), t.removeEventListener("pause", this._onPlayStop), t.removeEventListener("seeked", this._onSeeked), t.removeEventListener("canplay", this._onCanPlay), t.removeEventListener("canplaythrough", this._onCanPlayThrough), t.removeEventListener("error", this._onError, !0), t.pause(), t.src = "", t.load()), super.destroy();
  }
  /** Should the base texture automatically update itself, set to true by default. */
  get autoUpdate() {
    return this._autoUpdate;
  }
  set autoUpdate(t) {
    t !== this._autoUpdate && (this._autoUpdate = t, this._configureAutoUpdate());
  }
  /**
   * How many times a second to update the texture from the video.
   * Leave at 0 to update at every render.
   * A lower fps can help performance, as updating the texture at 60fps on a 30ps video may not be efficient.
   */
  get updateFPS() {
    return this._updateFPS;
  }
  set updateFPS(t) {
    t !== this._updateFPS && (this._updateFPS = t, this._configureAutoUpdate());
  }
  /**
   * Configures the updating mechanism based on the current state and settings.
   *
   * This method decides between using the browser's native video frame callback or a custom ticker
   * for updating the video frame. It ensures optimal performance and responsiveness
   * based on the video's state, playback status, and the desired frames-per-second setting.
   *
   * - If `_autoUpdate` is enabled and the video source is playing:
   *   - It will prefer the native video frame callback if available and no specific FPS is set.
   *   - Otherwise, it will use a custom ticker for manual updates.
   * - If `_autoUpdate` is disabled or the video isn't playing, any active update mechanisms are halted.
   */
  _configureAutoUpdate() {
    this._autoUpdate && this._isSourcePlaying() ? !this._updateFPS && this.resource.requestVideoFrameCallback ? (this._isConnectedToTicker && (Ur.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0), this._videoFrameRequestCallbackHandle === null && (this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback(
      this._videoFrameRequestCallback
    ))) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker || (Ur.shared.add(this.updateFrame, this), this._isConnectedToTicker = !0, this._msToNextUpdate = 0)) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker && (Ur.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0));
  }
  static test(t) {
    return globalThis.HTMLVideoElement && t instanceof HTMLVideoElement;
  }
};
Xo.extension = dt.TextureSource;
Xo.defaultOptions = {
  ...Je.defaultOptions,
  /** If true, the video will start loading immediately. */
  autoLoad: !0,
  /** If true, the video will start playing as soon as it is loaded. */
  autoPlay: !0,
  /** The number of times a second to update the texture from the video. Leave at 0 to update at every render. */
  updateFPS: 0,
  /** If true, the video will be loaded with the `crossorigin` attribute. */
  crossorigin: !0,
  /** If true, the video will loop when it ends. */
  loop: !1,
  /** If true, the video will be muted. */
  muted: !0,
  /** If true, the video will play inline. */
  playsinline: !0,
  /** If true, the video will be preloaded. */
  preload: !1
};
Xo.MIME_TYPES = {
  ogv: "video/ogg",
  mov: "video/quicktime",
  m4v: "video/mp4"
};
let Uy = Xo;
const Vn = (n, t, e = !1) => (Array.isArray(n) || (n = [n]), t ? n.map((s) => typeof s == "string" || e ? t(s) : s) : n);
class Gy {
  constructor() {
    this._parsers = [], this._cache = /* @__PURE__ */ new Map(), this._cacheMap = /* @__PURE__ */ new Map();
  }
  /** Clear all entries. */
  reset() {
    this._cacheMap.clear(), this._cache.clear();
  }
  /**
   * Check if the key exists
   * @param key - The key to check
   */
  has(t) {
    return this._cache.has(t);
  }
  /**
   * Fetch entry by key
   * @param key - The key of the entry to get
   */
  get(t) {
    const e = this._cache.get(t);
    return e || Ht(`[Assets] Asset id ${t} was not found in the Cache`), e;
  }
  /**
   * Set a value by key or keys name
   * @param key - The key or keys to set
   * @param value - The value to store in the cache or from which cacheable assets will be derived.
   */
  set(t, e) {
    const s = Vn(t);
    let i;
    for (let l = 0; l < this.parsers.length; l++) {
      const c = this.parsers[l];
      if (c.test(e)) {
        i = c.getCacheableAssets(s, e);
        break;
      }
    }
    const r = new Map(Object.entries(i || {}));
    i || s.forEach((l) => {
      r.set(l, e);
    });
    const o = [...r.keys()], a = {
      cacheKeys: o,
      keys: s
    };
    s.forEach((l) => {
      this._cacheMap.set(l, a);
    }), o.forEach((l) => {
      const c = i ? i[l] : e;
      this._cache.has(l) && this._cache.get(l) !== c && Ht("[Cache] already has key:", l), this._cache.set(l, r.get(l));
    });
  }
  /**
   * Remove entry by key
   *
   * This function will also remove any associated alias from the cache also.
   * @param key - The key of the entry to remove
   */
  remove(t) {
    if (!this._cacheMap.has(t)) {
      Ht(`[Assets] Asset id ${t} was not found in the Cache`);
      return;
    }
    const e = this._cacheMap.get(t);
    e.cacheKeys.forEach((i) => {
      this._cache.delete(i);
    }), e.keys.forEach((i) => {
      this._cacheMap.delete(i);
    });
  }
  /**
   * All loader parsers registered
   * @advanced
   */
  get parsers() {
    return this._parsers;
  }
}
const pn = new Gy(), hl = [];
ze.handleByList(dt.TextureSource, hl);
function ep(n = {}) {
  const t = n && n.resource, e = t ? n.resource : n, s = t ? n : { resource: n };
  for (let i = 0; i < hl.length; i++) {
    const r = hl[i];
    if (r.test(e))
      return new r(s);
  }
  throw new Error(`Could not find a source type for resource: ${s.resource}`);
}
function Wy(n = {}, t = !1) {
  const e = n && n.resource, s = e ? n.resource : n, i = e ? n : { resource: n };
  if (!t && pn.has(s))
    return pn.get(s);
  const r = new rt({ source: ep(i) });
  return r.on("destroy", () => {
    pn.has(s) && pn.remove(s);
  }), t || pn.set(s, r), r;
}
function $y(n, t = !1) {
  return typeof n == "string" ? pn.get(n) : n instanceof Je ? new rt({ source: n }) : Wy(n, t);
}
rt.from = $y;
Je.from = ep;
ze.add(Yf, Zf, Kf, Uy, go, Qf, jl);
var sp = /* @__PURE__ */ ((n) => (n[n.Low = 0] = "Low", n[n.Normal = 1] = "Normal", n[n.High = 2] = "High", n))(sp || {});
function Ge(n) {
  if (typeof n != "string")
    throw new TypeError(`Path must be a string. Received ${JSON.stringify(n)}`);
}
function Ai(n) {
  return n.split("?")[0].split("#")[0];
}
function Hy(n) {
  return n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function jy(n, t, e) {
  return n.replace(new RegExp(Hy(t), "g"), e);
}
function Xy(n, t) {
  let e = "", s = 0, i = -1, r = 0, o = -1;
  for (let a = 0; a <= n.length; ++a) {
    if (a < n.length)
      o = n.charCodeAt(a);
    else {
      if (o === 47)
        break;
      o = 47;
    }
    if (o === 47) {
      if (!(i === a - 1 || r === 1)) if (i !== a - 1 && r === 2) {
        if (e.length < 2 || s !== 2 || e.charCodeAt(e.length - 1) !== 46 || e.charCodeAt(e.length - 2) !== 46) {
          if (e.length > 2) {
            const l = e.lastIndexOf("/");
            if (l !== e.length - 1) {
              l === -1 ? (e = "", s = 0) : (e = e.slice(0, l), s = e.length - 1 - e.lastIndexOf("/")), i = a, r = 0;
              continue;
            }
          } else if (e.length === 2 || e.length === 1) {
            e = "", s = 0, i = a, r = 0;
            continue;
          }
        }
      } else
        e.length > 0 ? e += `/${n.slice(i + 1, a)}` : e = n.slice(i + 1, a), s = a - i - 1;
      i = a, r = 0;
    } else o === 46 && r !== -1 ? ++r : r = -1;
  }
  return e;
}
const Yi = {
  /**
   * Converts a path to posix format.
   * @param path - The path to convert to posix
   * @example
   * ```ts
   * // Convert a Windows path to POSIX format
   * path.toPosix('C:\\Users\\User\\Documents\\file.txt');
   * // -> 'C:/Users/User/Documents/file.txt'
   * ```
   */
  toPosix(n) {
    return jy(n, "\\", "/");
  },
  /**
   * Checks if the path is a URL e.g. http://, https://
   * @param path - The path to check
   * @example
   * ```ts
   * // Check if a path is a URL
   * path.isUrl('http://www.example.com');
   * // -> true
   * path.isUrl('C:/Users/User/Documents/file.txt');
   * // -> false
   * ```
   */
  isUrl(n) {
    return /^https?:/.test(this.toPosix(n));
  },
  /**
   * Checks if the path is a data URL
   * @param path - The path to check
   * @example
   * ```ts
   * // Check if a path is a data URL
   * path.isDataUrl('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...');
   * // -> true
   * ```
   */
  isDataUrl(n) {
    return /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i.test(n);
  },
  /**
   * Checks if the path is a blob URL
   * @param path - The path to check
   * @example
   * ```ts
   * // Check if a path is a blob URL
   * path.isBlobUrl('blob:http://www.example.com/12345678-1234-1234-1234-123456789012');
   * // -> true
   * ```
   */
  isBlobUrl(n) {
    return n.startsWith("blob:");
  },
  /**
   * Checks if the path has a protocol e.g. http://, https://, file:///, data:, blob:, C:/
   * This will return true for windows file paths
   * @param path - The path to check
   * @example
   * ```ts
   * // Check if a path has a protocol
   * path.hasProtocol('http://www.example.com');
   * // -> true
   * path.hasProtocol('C:/Users/User/Documents/file.txt');
   * // -> true
   * ```
   */
  hasProtocol(n) {
    return /^[^/:]+:/.test(this.toPosix(n));
  },
  /**
   * Returns the protocol of the path e.g. http://, https://, file:///, data:, blob:, C:/
   * @param path - The path to get the protocol from
   * @example
   * ```ts
   * // Get the protocol from a URL
   * path.getProtocol('http://www.example.com/path/to/resource');
   * // -> 'http://'
   * // Get the protocol from a file path
   * path.getProtocol('C:/Users/User/Documents/file.txt');
   * // -> 'C:/'
   * ```
   */
  getProtocol(n) {
    Ge(n), n = this.toPosix(n);
    const t = /^file:\/\/\//.exec(n);
    if (t)
      return t[0];
    const e = /^[^/:]+:\/{0,2}/.exec(n);
    return e ? e[0] : "";
  },
  /**
   * Converts URL to an absolute path.
   * When loading from a Web Worker, we must use absolute paths.
   * If the URL is already absolute we return it as is
   * If it's not, we convert it
   * @param url - The URL to test
   * @param customBaseUrl - The base URL to use
   * @param customRootUrl - The root URL to use
   * @example
   * ```ts
   * // Convert a relative URL to an absolute path
   * path.toAbsolute('images/texture.png', 'http://example.com/assets/');
   * // -> 'http://example.com/assets/images/texture.png'
   * ```
   */
  toAbsolute(n, t, e) {
    if (Ge(n), this.isDataUrl(n) || this.isBlobUrl(n))
      return n;
    const s = Ai(this.toPosix(t ?? Ae.get().getBaseUrl())), i = Ai(this.toPosix(e ?? this.rootname(s)));
    return n = this.toPosix(n), n.startsWith("/") ? Yi.join(i, n.slice(1)) : this.isAbsolute(n) ? n : this.join(s, n);
  },
  /**
   * Normalizes the given path, resolving '..' and '.' segments
   * @param path - The path to normalize
   * @example
   * ```ts
   * // Normalize a path with relative segments
   * path.normalize('http://www.example.com/foo/bar/../baz');
   * // -> 'http://www.example.com/foo/baz'
   * // Normalize a file path with relative segments
   * path.normalize('C:\\Users\\User\\Documents\\..\\file.txt');
   * // -> 'C:/Users/User/file.txt'
   * ```
   */
  normalize(n) {
    if (Ge(n), n.length === 0)
      return ".";
    if (this.isDataUrl(n) || this.isBlobUrl(n))
      return n;
    n = this.toPosix(n);
    let t = "";
    const e = n.startsWith("/");
    this.hasProtocol(n) && (t = this.rootname(n), n = n.slice(t.length));
    const s = n.endsWith("/");
    return n = Xy(n), n.length > 0 && s && (n += "/"), e ? `/${n}` : t + n;
  },
  /**
   * Determines if path is an absolute path.
   * Absolute paths can be urls, data urls, or paths on disk
   * @param path - The path to test
   * @example
   * ```ts
   * // Check if a path is absolute
   * path.isAbsolute('http://www.example.com/foo/bar');
   * // -> true
   * path.isAbsolute('C:/Users/User/Documents/file.txt');
   * // -> true
   * ```
   */
  isAbsolute(n) {
    return Ge(n), n = this.toPosix(n), this.hasProtocol(n) ? !0 : n.startsWith("/");
  },
  /**
   * Joins all given path segments together using the platform-specific separator as a delimiter,
   * then normalizes the resulting path
   * @param segments - The segments of the path to join
   * @example
   * ```ts
   * // Join multiple path segments
   * path.join('assets', 'images', 'sprite.png');
   * // -> 'assets/images/sprite.png'
   * // Join with relative segments
   * path.join('assets', 'images', '../textures', 'sprite.png');
   * // -> 'assets/textures/sprite.png'
   * ```
   */
  join(...n) {
    if (n.length === 0)
      return ".";
    let t;
    for (let e = 0; e < n.length; ++e) {
      const s = n[e];
      if (Ge(s), s.length > 0)
        if (t === void 0)
          t = s;
        else {
          const i = n[e - 1] ?? "";
          this.joinExtensions.includes(this.extname(i).toLowerCase()) ? t += `/../${s}` : t += `/${s}`;
        }
    }
    return t === void 0 ? "." : this.normalize(t);
  },
  /**
   * Returns the directory name of a path
   * @param path - The path to parse
   * @example
   * ```ts
   * // Get the directory name of a path
   * path.dirname('http://www.example.com/foo/bar/baz.png');
   * // -> 'http://www.example.com/foo/bar'
   * // Get the directory name of a file path
   * path.dirname('C:/Users/User/Documents/file.txt');
   * // -> 'C:/Users/User/Documents'
   * ```
   */
  dirname(n) {
    if (Ge(n), n.length === 0)
      return ".";
    n = this.toPosix(n);
    let t = n.charCodeAt(0);
    const e = t === 47;
    let s = -1, i = !0;
    const r = this.getProtocol(n), o = n;
    n = n.slice(r.length);
    for (let a = n.length - 1; a >= 1; --a)
      if (t = n.charCodeAt(a), t === 47) {
        if (!i) {
          s = a;
          break;
        }
      } else
        i = !1;
    return s === -1 ? e ? "/" : this.isUrl(o) ? r + n : r : e && s === 1 ? "//" : r + n.slice(0, s);
  },
  /**
   * Returns the root of the path e.g. /, C:/, file:///, http://domain.com/
   * @param path - The path to parse
   * @example
   * ```ts
   * // Get the root of a URL
   * path.rootname('http://www.example.com/foo/bar/baz.png');
   * // -> 'http://www.example.com/'
   * // Get the root of a file path
   * path.rootname('C:/Users/User/Documents/file.txt');
   * // -> 'C:/'
   * ```
   */
  rootname(n) {
    Ge(n), n = this.toPosix(n);
    let t = "";
    if (n.startsWith("/") ? t = "/" : t = this.getProtocol(n), this.isUrl(n)) {
      const e = n.indexOf("/", t.length);
      e !== -1 ? t = n.slice(0, e) : t = n, t.endsWith("/") || (t += "/");
    }
    return t;
  },
  /**
   * Returns the last portion of a path
   * @param path - The path to test
   * @param ext - Optional extension to remove
   * @example
   * ```ts
   * // Get the basename of a URL
   * path.basename('http://www.example.com/foo/bar/baz.png');
   * // -> 'baz.png'
   * // Get the basename of a file path
   * path.basename('C:/Users/User/Documents/file.txt');
   * // -> 'file.txt'
   * ```
   */
  basename(n, t) {
    Ge(n), t && Ge(t), n = Ai(this.toPosix(n));
    let e = 0, s = -1, i = !0, r;
    if (t !== void 0 && t.length > 0 && t.length <= n.length) {
      if (t.length === n.length && t === n)
        return "";
      let o = t.length - 1, a = -1;
      for (r = n.length - 1; r >= 0; --r) {
        const l = n.charCodeAt(r);
        if (l === 47) {
          if (!i) {
            e = r + 1;
            break;
          }
        } else
          a === -1 && (i = !1, a = r + 1), o >= 0 && (l === t.charCodeAt(o) ? --o === -1 && (s = r) : (o = -1, s = a));
      }
      return e === s ? s = a : s === -1 && (s = n.length), n.slice(e, s);
    }
    for (r = n.length - 1; r >= 0; --r)
      if (n.charCodeAt(r) === 47) {
        if (!i) {
          e = r + 1;
          break;
        }
      } else s === -1 && (i = !1, s = r + 1);
    return s === -1 ? "" : n.slice(e, s);
  },
  /**
   * Returns the extension of the path, from the last occurrence of the . (period) character to end of string in the last
   * portion of the path. If there is no . in the last portion of the path, or if there are no . characters other than
   * the first character of the basename of path, an empty string is returned.
   * @param path - The path to parse
   * @example
   * ```ts
   * // Get the extension of a URL
   * path.extname('http://www.example.com/foo/bar/baz.png');
   * // -> '.png'
   * // Get the extension of a file path
   * path.extname('C:/Users/User/Documents/file.txt');
   * // -> '.txt'
   * ```
   */
  extname(n) {
    Ge(n), n = Ai(this.toPosix(n));
    let t = -1, e = 0, s = -1, i = !0, r = 0;
    for (let o = n.length - 1; o >= 0; --o) {
      const a = n.charCodeAt(o);
      if (a === 47) {
        if (!i) {
          e = o + 1;
          break;
        }
        continue;
      }
      s === -1 && (i = !1, s = o + 1), a === 46 ? t === -1 ? t = o : r !== 1 && (r = 1) : t !== -1 && (r = -1);
    }
    return t === -1 || s === -1 || r === 0 || r === 1 && t === s - 1 && t === e + 1 ? "" : n.slice(t, s);
  },
  /**
   * Parses a path into an object containing the 'root', `dir`, `base`, `ext`, and `name` properties.
   * @param path - The path to parse
   * @example
   * ```ts
   * // Parse a URL
   * const parsed = path.parse('http://www.example.com/foo/bar/baz.png');
   * // -> {
   * //   root: 'http://www.example.com/',
   * //   dir: 'http://www.example.com/foo/bar',
   * //   base: 'baz.png',
   * //   ext: '.png',
   * //   name: 'baz'
   * // }
   * // Parse a file path
   * const parsedFile = path.parse('C:/Users/User/Documents/file.txt');
   * // -> {
   * //   root: 'C:/',
   * //   dir: 'C:/Users/User/Documents',
   * //   base: 'file.txt',
   * //   ext: '.txt',
   * //   name: 'file'
   * // }
   * ```
   */
  parse(n) {
    Ge(n);
    const t = { root: "", dir: "", base: "", ext: "", name: "" };
    if (n.length === 0)
      return t;
    n = Ai(this.toPosix(n));
    let e = n.charCodeAt(0);
    const s = this.isAbsolute(n);
    let i;
    t.root = this.rootname(n), s || this.hasProtocol(n) ? i = 1 : i = 0;
    let r = -1, o = 0, a = -1, l = !0, c = n.length - 1, h = 0;
    for (; c >= i; --c) {
      if (e = n.charCodeAt(c), e === 47) {
        if (!l) {
          o = c + 1;
          break;
        }
        continue;
      }
      a === -1 && (l = !1, a = c + 1), e === 46 ? r === -1 ? r = c : h !== 1 && (h = 1) : r !== -1 && (h = -1);
    }
    return r === -1 || a === -1 || h === 0 || h === 1 && r === a - 1 && r === o + 1 ? a !== -1 && (o === 0 && s ? t.base = t.name = n.slice(1, a) : t.base = t.name = n.slice(o, a)) : (o === 0 && s ? (t.name = n.slice(1, r), t.base = n.slice(1, a)) : (t.name = n.slice(o, r), t.base = n.slice(o, a)), t.ext = n.slice(r, a)), t.dir = this.dirname(n), t;
  },
  sep: "/",
  delimiter: ":",
  joinExtensions: [".html"]
};
function np(n, t, e, s, i) {
  const r = t[e];
  for (let o = 0; o < r.length; o++) {
    const a = r[o];
    e < t.length - 1 ? np(n.replace(s[e], a), t, e + 1, s, i) : i.push(n.replace(s[e], a));
  }
}
function Yy(n) {
  const t = /\{(.*?)\}/g, e = n.match(t), s = [];
  if (e) {
    const i = [];
    e.forEach((r) => {
      const o = r.substring(1, r.length - 1).split(",");
      i.push(o);
    }), np(n, i, 0, e, s);
  } else
    s.push(n);
  return s;
}
const su = (n) => !Array.isArray(n);
class ip {
  constructor() {
    this._defaultBundleIdentifierOptions = {
      connector: "-",
      createBundleAssetId: (t, e) => `${t}${this._bundleIdConnector}${e}`,
      extractAssetIdFromBundle: (t, e) => e.replace(`${t}${this._bundleIdConnector}`, "")
    }, this._bundleIdConnector = this._defaultBundleIdentifierOptions.connector, this._createBundleAssetId = this._defaultBundleIdentifierOptions.createBundleAssetId, this._extractAssetIdFromBundle = this._defaultBundleIdentifierOptions.extractAssetIdFromBundle, this._assetMap = {}, this._preferredOrder = [], this._parsers = [], this._resolverHash = {}, this._bundles = {};
  }
  /**
   * Override how the resolver deals with generating bundle ids.
   * must be called before any bundles are added
   * @param bundleIdentifier - the bundle identifier options
   */
  setBundleIdentifier(t) {
    if (this._bundleIdConnector = t.connector ?? this._bundleIdConnector, this._createBundleAssetId = t.createBundleAssetId ?? this._createBundleAssetId, this._extractAssetIdFromBundle = t.extractAssetIdFromBundle ?? this._extractAssetIdFromBundle, this._extractAssetIdFromBundle("foo", this._createBundleAssetId("foo", "bar")) !== "bar")
      throw new Error("[Resolver] GenerateBundleAssetId are not working correctly");
  }
  /**
   * Let the resolver know which assets you prefer to use when resolving assets.
   * Multiple prefer user defined rules can be added.
   * @example
   * resolver.prefer({
   *     // first look for something with the correct format, and then then correct resolution
   *     priority: ['format', 'resolution'],
   *     params:{
   *         format:'webp', // prefer webp images
   *         resolution: 2, // prefer a resolution of 2
   *     }
   * })
   * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']);
   * resolver.resolveUrl('foo') // => 'bar@2x.webp'
   * @param preferOrders - the prefer options
   */
  prefer(...t) {
    t.forEach((e) => {
      this._preferredOrder.push(e), e.priority || (e.priority = Object.keys(e.params));
    }), this._resolverHash = {};
  }
  /**
   * Set the base path to prepend to all urls when resolving
   * @example
   * resolver.basePath = 'https://home.com/';
   * resolver.add('foo', 'bar.ong');
   * resolver.resolveUrl('foo', 'bar.png'); // => 'https://home.com/bar.png'
   * @param basePath - the base path to use
   */
  set basePath(t) {
    this._basePath = t;
  }
  get basePath() {
    return this._basePath;
  }
  /**
   * Set the root path for root-relative URLs. By default the `basePath`'s root is used. If no `basePath` is set, then the
   * default value for browsers is `window.location.origin`
   * @example
   * // Application hosted on https://home.com/some-path/index.html
   * resolver.basePath = 'https://home.com/some-path/';
   * resolver.rootPath = 'https://home.com/';
   * resolver.add('foo', '/bar.png');
   * resolver.resolveUrl('foo', '/bar.png'); // => 'https://home.com/bar.png'
   * @param rootPath - the root path to use
   */
  set rootPath(t) {
    this._rootPath = t;
  }
  get rootPath() {
    return this._rootPath;
  }
  /**
   * All the active URL parsers that help the parser to extract information and create
   * an asset object-based on parsing the URL itself.
   *
   * Can be added using the extensions API
   * @example
   * resolver.add('foo', [
   *     {
   *         resolution: 2,
   *         format: 'png',
   *         src: 'image@2x.png',
   *     },
   *     {
   *         resolution:1,
   *         format:'png',
   *         src: 'image.png',
   *     },
   * ]);
   *
   * // With a url parser the information such as resolution and file format could extracted from the url itself:
   * extensions.add({
   *     extension: ExtensionType.ResolveParser,
   *     test: loadTextures.test, // test if url ends in an image
   *     parse: (value: string) =>
   *     ({
   *         resolution: parseFloat(Resolver.RETINA_PREFIX.exec(value)?.[1] ?? '1'),
   *         format: value.split('.').pop(),
   *         src: value,
   *     }),
   * });
   *
   * // Now resolution and format can be extracted from the url
   * resolver.add('foo', [
   *     'image@2x.png',
   *     'image.png',
   * ]);
   */
  get parsers() {
    return this._parsers;
  }
  /** Used for testing, this resets the resolver to its initial state */
  reset() {
    this.setBundleIdentifier(this._defaultBundleIdentifierOptions), this._assetMap = {}, this._preferredOrder = [], this._resolverHash = {}, this._rootPath = null, this._basePath = null, this._manifest = null, this._bundles = {}, this._defaultSearchParams = null;
  }
  /**
   * Sets the default URL search parameters for the URL resolver. The urls can be specified as a string or an object.
   * @param searchParams - the default url parameters to append when resolving urls
   */
  setDefaultSearchParams(t) {
    if (typeof t == "string")
      this._defaultSearchParams = t;
    else {
      const e = t;
      this._defaultSearchParams = Object.keys(e).map((s) => `${encodeURIComponent(s)}=${encodeURIComponent(e[s])}`).join("&");
    }
  }
  /**
   * Returns the aliases for a given asset
   * @param asset - the asset to get the aliases for
   */
  getAlias(t) {
    const { alias: e, src: s } = t;
    return Vn(
      e || s,
      (r) => typeof r == "string" ? r : Array.isArray(r) ? r.map((o) => o?.src ?? o) : r?.src ? r.src : r,
      !0
    );
  }
  /**
   * Add a manifest to the asset resolver. This is a nice way to add all the asset information in one go.
   * generally a manifest would be built using a tool.
   * @param manifest - the manifest to add to the resolver
   */
  addManifest(t) {
    this._manifest && Ht("[Resolver] Manifest already exists, this will be overwritten"), this._manifest = t, t.bundles.forEach((e) => {
      this.addBundle(e.name, e.assets);
    });
  }
  /**
   * This adds a bundle of assets in one go so that you can resolve them as a group.
   * For example you could add a bundle for each screen in you pixi app
   * @example
   * resolver.addBundle('animals', [
   *  { alias: 'bunny', src: 'bunny.png' },
   *  { alias: 'chicken', src: 'chicken.png' },
   *  { alias: 'thumper', src: 'thumper.png' },
   * ]);
   * // or
   * resolver.addBundle('animals', {
   *     bunny: 'bunny.png',
   *     chicken: 'chicken.png',
   *     thumper: 'thumper.png',
   * });
   *
   * const resolvedAssets = await resolver.resolveBundle('animals');
   * @param bundleId - The id of the bundle to add
   * @param assets - A record of the asset or assets that will be chosen from when loading via the specified key
   */
  addBundle(t, e) {
    const s = [];
    let i = e;
    Array.isArray(e) || (i = Object.entries(e).map(([r, o]) => typeof o == "string" || Array.isArray(o) ? { alias: r, src: o } : { alias: r, ...o })), i.forEach((r) => {
      const o = r.src, a = r.alias;
      let l;
      if (typeof a == "string") {
        const c = this._createBundleAssetId(t, a);
        s.push(c), l = [a, c];
      } else {
        const c = a.map((h) => this._createBundleAssetId(t, h));
        s.push(...c), l = [...a, ...c];
      }
      this.add({
        ...r,
        alias: l,
        src: o
      });
    }), this._bundles[t] = s;
  }
  /**
   * Tells the resolver what keys are associated with witch asset.
   * The most important thing the resolver does
   * @example
   * // Single key, single asset:
   * resolver.add({alias: 'foo', src: 'bar.png');
   * resolver.resolveUrl('foo') // => 'bar.png'
   *
   * // Multiple keys, single asset:
   * resolver.add({alias: ['foo', 'boo'], src: 'bar.png'});
   * resolver.resolveUrl('foo') // => 'bar.png'
   * resolver.resolveUrl('boo') // => 'bar.png'
   *
   * // Multiple keys, multiple assets:
   * resolver.add({alias: ['foo', 'boo'], src: ['bar.png', 'bar.webp']});
   * resolver.resolveUrl('foo') // => 'bar.png'
   *
   * // Add custom data attached to the resolver
   * Resolver.add({
   *     alias: 'bunnyBooBooSmooth',
   *     src: 'bunny{png,webp}',
   *     data: { scaleMode:SCALE_MODES.NEAREST }, // Base texture options
   * });
   *
   * resolver.resolve('bunnyBooBooSmooth') // => { src: 'bunny.png', data: { scaleMode: SCALE_MODES.NEAREST } }
   * @param aliases - the UnresolvedAsset or array of UnresolvedAssets to add to the resolver
   */
  add(t) {
    const e = [];
    Array.isArray(t) ? e.push(...t) : e.push(t);
    let s;
    s = (r) => {
      this.hasKey(r) && Ht(`[Resolver] already has key: ${r} overwriting`);
    }, Vn(e).forEach((r) => {
      const { src: o } = r;
      let { data: a, format: l, loadParser: c, parser: h } = r;
      const u = Vn(o).map((p) => typeof p == "string" ? Yy(p) : Array.isArray(p) ? p : [p]), d = this.getAlias(r);
      Array.isArray(d) ? d.forEach(s) : s(d);
      const f = [];
      u.forEach((p) => {
        p.forEach((g) => {
          let m = {};
          if (typeof g != "object") {
            m.src = g;
            for (let y = 0; y < this._parsers.length; y++) {
              const x = this._parsers[y];
              if (x.test(g)) {
                m = x.parse(g);
                break;
              }
            }
          } else
            a = g.data ?? a, l = g.format ?? l, (g.loadParser || g.parser) && (c = g.loadParser ?? c, h = g.parser ?? h), m = {
              ...m,
              ...g
            };
          if (!d)
            throw new Error(`[Resolver] alias is undefined for this asset: ${m.src}`);
          m = this._buildResolvedAsset(m, {
            aliases: d,
            data: a,
            format: l,
            loadParser: c,
            parser: h
          }), f.push(m);
        });
      }), d.forEach((p) => {
        this._assetMap[p] = f;
      });
    });
  }
  // TODO: this needs an overload like load did in Assets
  /**
   * If the resolver has had a manifest set via setManifest, this will return the assets urls for
   * a given bundleId or bundleIds.
   * @example
   * // Manifest Example
   * const manifest = {
   *     bundles: [
   *         {
   *             name: 'load-screen',
   *             assets: [
   *                 {
   *                     alias: 'background',
   *                     src: 'sunset.png',
   *                 },
   *                 {
   *                     alias: 'bar',
   *                     src: 'load-bar.{png,webp}',
   *                 },
   *             ],
   *         },
   *         {
   *             name: 'game-screen',
   *             assets: [
   *                 {
   *                     alias: 'character',
   *                     src: 'robot.png',
   *                 },
   *                 {
   *                     alias: 'enemy',
   *                     src: 'bad-guy.png',
   *                 },
   *             ],
   *         },
   *     ]
   * };
   *
   * resolver.setManifest(manifest);
   * const resolved = resolver.resolveBundle('load-screen');
   * @param bundleIds - The bundle ids to resolve
   * @returns All the bundles assets or a hash of assets for each bundle specified
   */
  resolveBundle(t) {
    const e = su(t);
    t = Vn(t);
    const s = {};
    return t.forEach((i) => {
      const r = this._bundles[i];
      if (r) {
        const o = this.resolve(r), a = {};
        for (const l in o) {
          const c = o[l];
          a[this._extractAssetIdFromBundle(i, l)] = c;
        }
        s[i] = a;
      }
    }), e ? s[t[0]] : s;
  }
  /**
   * Does exactly what resolve does, but returns just the URL rather than the whole asset object
   * @param key - The key or keys to resolve
   * @returns - The URLs associated with the key(s)
   */
  resolveUrl(t) {
    const e = this.resolve(t);
    if (typeof t != "string") {
      const s = {};
      for (const i in e)
        s[i] = e[i].src;
      return s;
    }
    return e.src;
  }
  resolve(t) {
    const e = su(t);
    t = Vn(t);
    const s = {};
    return t.forEach((i) => {
      if (!this._resolverHash[i])
        if (this._assetMap[i]) {
          let r = this._assetMap[i];
          const o = this._getPreferredOrder(r);
          o?.priority.forEach((a) => {
            o.params[a].forEach((l) => {
              const c = r.filter((h) => h[a] ? h[a] === l : !1);
              c.length && (r = c);
            });
          }), this._resolverHash[i] = r[0];
        } else
          this._resolverHash[i] = this._buildResolvedAsset({
            alias: [i],
            src: i
          }, {});
      s[i] = this._resolverHash[i];
    }), e ? s[t[0]] : s;
  }
  /**
   * Checks if an asset with a given key exists in the resolver
   * @param key - The key of the asset
   */
  hasKey(t) {
    return !!this._assetMap[t];
  }
  /**
   * Checks if a bundle with the given key exists in the resolver
   * @param key - The key of the bundle
   */
  hasBundle(t) {
    return !!this._bundles[t];
  }
  /**
   * Internal function for figuring out what prefer criteria an asset should use.
   * @param assets
   */
  _getPreferredOrder(t) {
    for (let e = 0; e < t.length; e++) {
      const s = t[e], i = this._preferredOrder.find((r) => r.params.format.includes(s.format));
      if (i)
        return i;
    }
    return this._preferredOrder[0];
  }
  /**
   * Appends the default url parameters to the url
   * @param url - The url to append the default parameters to
   * @returns - The url with the default parameters appended
   */
  _appendDefaultSearchParams(t) {
    if (!this._defaultSearchParams)
      return t;
    const e = /\?/.test(t) ? "&" : "?";
    return `${t}${e}${this._defaultSearchParams}`;
  }
  _buildResolvedAsset(t, e) {
    const { aliases: s, data: i, loadParser: r, parser: o, format: a } = e;
    return (this._basePath || this._rootPath) && (t.src = Yi.toAbsolute(t.src, this._basePath, this._rootPath)), t.alias = s ?? t.alias ?? [t.src], t.src = this._appendDefaultSearchParams(t.src), t.data = { ...i || {}, ...t.data }, t.loadParser = r ?? t.loadParser, t.parser = o ?? t.parser, t.format = a ?? t.format ?? Zy(t.src), t;
  }
}
ip.RETINA_PREFIX = /@([0-9\.]+)x/;
function Zy(n) {
  return n.split(".").pop().split("?").shift().split("#").shift();
}
const nu = (n, t) => {
  const e = t.split("?")[1];
  return e && (n += `?${e}`), n;
}, rp = class Bi {
  constructor(t, e) {
    this.linkedSheets = [];
    let s = t;
    t?.source instanceof Je && (s = {
      texture: t,
      data: e
    });
    const { texture: i, data: r, cachePrefix: o = "" } = s;
    this.cachePrefix = o, this._texture = i instanceof rt ? i : null, this.textureSource = i.source, this.textures = {}, this.animations = {}, this.data = r;
    const a = parseFloat(r.meta.scale);
    a ? (this.resolution = a, i.source.resolution = this.resolution) : this.resolution = i.source._resolution, this._frames = this.data.frames, this._frameKeys = Object.keys(this._frames), this._batchIndex = 0, this._callback = null;
  }
  /**
   * Parser spritesheet from loaded data. This is done asynchronously
   * to prevent creating too many Texture within a single process.
   */
  parse() {
    return new Promise((t) => {
      this._callback = t, this._batchIndex = 0, this._frameKeys.length <= Bi.BATCH_SIZE ? (this._processFrames(0), this._processAnimations(), this._parseComplete()) : this._nextBatch();
    });
  }
  /**
   * Process a batch of frames
   * @param initialFrameIndex - The index of frame to start.
   */
  _processFrames(t) {
    let e = t;
    const s = Bi.BATCH_SIZE;
    for (; e - t < s && e < this._frameKeys.length; ) {
      const i = this._frameKeys[e], r = this._frames[i], o = r.frame;
      if (o) {
        let a = null, l = null;
        const c = r.trimmed !== !1 && r.sourceSize ? r.sourceSize : r.frame, h = new Dt(
          0,
          0,
          Math.floor(c.w) / this.resolution,
          Math.floor(c.h) / this.resolution
        );
        r.rotated ? a = new Dt(
          Math.floor(o.x) / this.resolution,
          Math.floor(o.y) / this.resolution,
          Math.floor(o.h) / this.resolution,
          Math.floor(o.w) / this.resolution
        ) : a = new Dt(
          Math.floor(o.x) / this.resolution,
          Math.floor(o.y) / this.resolution,
          Math.floor(o.w) / this.resolution,
          Math.floor(o.h) / this.resolution
        ), r.trimmed !== !1 && r.spriteSourceSize && (l = new Dt(
          Math.floor(r.spriteSourceSize.x) / this.resolution,
          Math.floor(r.spriteSourceSize.y) / this.resolution,
          Math.floor(o.w) / this.resolution,
          Math.floor(o.h) / this.resolution
        )), this.textures[i] = new rt({
          source: this.textureSource,
          frame: a,
          orig: h,
          trim: l,
          rotate: r.rotated ? 2 : 0,
          defaultAnchor: r.anchor,
          defaultBorders: r.borders,
          label: i.toString()
        });
      }
      e++;
    }
  }
  /** Parse animations config. */
  _processAnimations() {
    const t = this.data.animations || {};
    for (const e in t) {
      this.animations[e] = [];
      for (let s = 0; s < t[e].length; s++) {
        const i = t[e][s];
        this.animations[e].push(this.textures[i]);
      }
    }
  }
  /** The parse has completed. */
  _parseComplete() {
    const t = this._callback;
    this._callback = null, this._batchIndex = 0, t.call(this, this.textures);
  }
  /** Begin the next batch of textures. */
  _nextBatch() {
    this._processFrames(this._batchIndex * Bi.BATCH_SIZE), this._batchIndex++, setTimeout(() => {
      this._batchIndex * Bi.BATCH_SIZE < this._frameKeys.length ? this._nextBatch() : (this._processAnimations(), this._parseComplete());
    }, 0);
  }
  /**
   * Destroy Spritesheet and don't use after this.
   * @param {boolean} [destroyBase=false] - Whether to destroy the base texture as well
   */
  destroy(t = !1) {
    for (const e in this.textures)
      this.textures[e].destroy();
    this._frames = null, this._frameKeys = null, this.data = null, this.textures = null, t && (this._texture?.destroy(), this.textureSource.destroy()), this._texture = null, this.textureSource = null, this.linkedSheets = [];
  }
};
rp.BATCH_SIZE = 1e3;
let iu = rp;
const Ky = [
  "jpg",
  "png",
  "jpeg",
  "avif",
  "webp",
  "basis",
  "etc2",
  "bc7",
  "bc6h",
  "bc5",
  "bc4",
  "bc3",
  "bc2",
  "bc1",
  "eac",
  "astc"
];
function op(n, t, e) {
  const s = {};
  if (n.forEach((i) => {
    s[i] = t;
  }), Object.keys(t.textures).forEach((i) => {
    s[`${t.cachePrefix}${i}`] = t.textures[i];
  }), !e) {
    const i = Yi.dirname(n[0]);
    t.linkedSheets.forEach((r, o) => {
      const a = op([`${i}/${t.data.meta.related_multi_packs[o]}`], r, !0);
      Object.assign(s, a);
    });
  }
  return s;
}
const Qy = {
  extension: dt.Asset,
  /** Handle the caching of the related Spritesheet Textures */
  cache: {
    test: (n) => n instanceof iu,
    getCacheableAssets: (n, t) => op(n, t, !1)
  },
  /** Resolve the resolution of the asset. */
  resolver: {
    extension: {
      type: dt.ResolveParser,
      name: "resolveSpritesheet"
    },
    test: (n) => {
      const e = n.split("?")[0].split("."), s = e.pop(), i = e.pop();
      return s === "json" && Ky.includes(i);
    },
    parse: (n) => {
      const t = n.split(".");
      return {
        resolution: parseFloat(ip.RETINA_PREFIX.exec(n)?.[1] ?? "1"),
        format: t[t.length - 2],
        src: n
      };
    }
  },
  /**
   * Loader plugin that parses sprite sheets!
   * once the JSON has been loaded this checks to see if the JSON is spritesheet data.
   * If it is, we load the spritesheets image and parse the data into Spritesheet
   * All textures in the sprite sheet are then added to the cache
   */
  loader: {
    /** used for deprecation purposes */
    name: "spritesheetLoader",
    id: "spritesheet",
    extension: {
      type: dt.LoadParser,
      priority: sp.Normal,
      name: "spritesheetLoader"
    },
    async testParse(n, t) {
      return Yi.extname(t.src).toLowerCase() === ".json" && !!n.frames;
    },
    async parse(n, t, e) {
      const {
        texture: s,
        // if user need to use preloaded texture
        imageFilename: i,
        // if user need to use custom filename (not from jsonFile.meta.image)
        textureOptions: r,
        // if user need to set texture options on texture
        cachePrefix: o
        // if user need to use custom cache prefix
      } = t?.data ?? {};
      let a = Yi.dirname(t.src);
      a && a.lastIndexOf("/") !== a.length - 1 && (a += "/");
      let l;
      if (s instanceof rt)
        l = s;
      else {
        const u = nu(a + (i ?? n.meta.image), t.src);
        l = (await e.load([{ src: u, data: r }]))[u];
      }
      const c = new iu({
        texture: l.source,
        data: n,
        cachePrefix: o
      });
      await c.parse();
      const h = n?.meta?.related_multi_packs;
      if (Array.isArray(h)) {
        const u = [];
        for (const f of h) {
          if (typeof f != "string")
            continue;
          let p = a + f;
          t.data?.ignoreMultiPack || (p = nu(p, t.src), u.push(e.load({
            src: p,
            data: {
              textureOptions: r,
              ignoreMultiPack: !0
            }
          })));
        }
        const d = await Promise.all(u);
        c.linkedSheets = d, d.forEach((f) => {
          f.linkedSheets = [c].concat(c.linkedSheets.filter((p) => p !== f));
        });
      }
      return c;
    },
    async unload(n, t, e) {
      await e.unload(n.textureSource._sourceOrigin), n.destroy(!1);
    }
  }
};
ze.add(Qy);
const Pa = /* @__PURE__ */ Object.create(null), ru = /* @__PURE__ */ Object.create(null);
function Zl(n, t) {
  let e = ru[n];
  return e === void 0 && (Pa[t] === void 0 && (Pa[t] = 1), ru[n] = e = Pa[t]++), e;
}
let Gr;
function ap() {
  return (!Gr || Gr?.isContextLost()) && (Gr = Ae.get().createCanvas().getContext("webgl", {})), Gr;
}
let Wr;
function Jy() {
  if (!Wr) {
    Wr = "mediump";
    const n = ap();
    n && n.getShaderPrecisionFormat && (Wr = n.getShaderPrecisionFormat(n.FRAGMENT_SHADER, n.HIGH_FLOAT).precision ? "highp" : "mediump");
  }
  return Wr;
}
function t0(n, t, e) {
  return t ? n : e ? (n = n.replace("out vec4 finalColor;", ""), `

        #ifdef GL_ES // This checks if it is WebGL1
        #define in varying
        #define finalColor gl_FragColor
        #define texture texture2D
        #endif
        ${n}
        `) : `

        #ifdef GL_ES // This checks if it is WebGL1
        #define in attribute
        #define out varying
        #endif
        ${n}
        `;
}
function e0(n, t, e) {
  const s = e ? t.maxSupportedFragmentPrecision : t.maxSupportedVertexPrecision;
  if (n.substring(0, 9) !== "precision") {
    let i = e ? t.requestedFragmentPrecision : t.requestedVertexPrecision;
    return i === "highp" && s !== "highp" && (i = "mediump"), `precision ${i} float;
${n}`;
  } else if (s !== "highp" && n.substring(0, 15) === "precision highp")
    return n.replace("precision highp", "precision mediump");
  return n;
}
function s0(n, t) {
  return t ? `#version 300 es
${n}` : n;
}
const n0 = {}, i0 = {};
function r0(n, { name: t = "pixi-program" }, e = !0) {
  t = t.replace(/\s+/g, "-"), t += e ? "-fragment" : "-vertex";
  const s = e ? n0 : i0;
  return s[t] ? (s[t]++, t += `-${s[t]}`) : s[t] = 1, n.indexOf("#define SHADER_NAME") !== -1 ? n : `${`#define SHADER_NAME ${t}`}
${n}`;
}
function o0(n, t) {
  return t ? n.replace("#version 300 es", "") : n;
}
const Ia = {
  // strips any version headers..
  stripVersion: o0,
  // adds precision string if not already present
  ensurePrecision: e0,
  // add some defines if WebGL1 to make it more compatible with WebGL2 shaders
  addProgramDefines: t0,
  // add the program name to the shader
  setProgramName: r0,
  // add the version string to the shader header
  insertVersion: s0
}, Fa = /* @__PURE__ */ Object.create(null), lp = class ul {
  /**
   * Creates a shiny new GlProgram. Used by WebGL renderer.
   * @param options - The options for the program.
   */
  constructor(t) {
    t = { ...ul.defaultOptions, ...t };
    const e = t.fragment.indexOf("#version 300 es") !== -1, s = {
      stripVersion: e,
      ensurePrecision: {
        requestedFragmentPrecision: t.preferredFragmentPrecision,
        requestedVertexPrecision: t.preferredVertexPrecision,
        maxSupportedVertexPrecision: "highp",
        maxSupportedFragmentPrecision: Jy()
      },
      setProgramName: {
        name: t.name
      },
      addProgramDefines: e,
      insertVersion: e
    };
    let i = t.fragment, r = t.vertex;
    Object.keys(Ia).forEach((o) => {
      const a = s[o];
      i = Ia[o](i, a, !0), r = Ia[o](r, a, !1);
    }), this.fragment = i, this.vertex = r, this.transformFeedbackVaryings = t.transformFeedbackVaryings, this._key = Zl(`${this.vertex}:${this.fragment}`, "gl-program");
  }
  /** destroys the program */
  destroy() {
    this.fragment = null, this.vertex = null, this._attributeData = null, this._uniformData = null, this._uniformBlockData = null, this.transformFeedbackVaryings = null;
  }
  /**
   * Helper function that creates a program for a given source.
   * It will check the program cache if the program has already been created.
   * If it has that one will be returned, if not a new one will be created and cached.
   * @param options - The options for the program.
   * @returns A program using the same source
   */
  static from(t) {
    const e = `${t.vertex}:${t.fragment}`;
    return Fa[e] || (Fa[e] = new ul(t)), Fa[e];
  }
};
lp.defaultOptions = {
  preferredVertexPrecision: "highp",
  preferredFragmentPrecision: "mediump"
};
let cp = lp;
const ou = {
  uint8x2: { size: 2, stride: 2, normalised: !1 },
  uint8x4: { size: 4, stride: 4, normalised: !1 },
  sint8x2: { size: 2, stride: 2, normalised: !1 },
  sint8x4: { size: 4, stride: 4, normalised: !1 },
  unorm8x2: { size: 2, stride: 2, normalised: !0 },
  unorm8x4: { size: 4, stride: 4, normalised: !0 },
  snorm8x2: { size: 2, stride: 2, normalised: !0 },
  snorm8x4: { size: 4, stride: 4, normalised: !0 },
  uint16x2: { size: 2, stride: 4, normalised: !1 },
  uint16x4: { size: 4, stride: 8, normalised: !1 },
  sint16x2: { size: 2, stride: 4, normalised: !1 },
  sint16x4: { size: 4, stride: 8, normalised: !1 },
  unorm16x2: { size: 2, stride: 4, normalised: !0 },
  unorm16x4: { size: 4, stride: 8, normalised: !0 },
  snorm16x2: { size: 2, stride: 4, normalised: !0 },
  snorm16x4: { size: 4, stride: 8, normalised: !0 },
  float16x2: { size: 2, stride: 4, normalised: !1 },
  float16x4: { size: 4, stride: 8, normalised: !1 },
  float32: { size: 1, stride: 4, normalised: !1 },
  float32x2: { size: 2, stride: 8, normalised: !1 },
  float32x3: { size: 3, stride: 12, normalised: !1 },
  float32x4: { size: 4, stride: 16, normalised: !1 },
  uint32: { size: 1, stride: 4, normalised: !1 },
  uint32x2: { size: 2, stride: 8, normalised: !1 },
  uint32x3: { size: 3, stride: 12, normalised: !1 },
  uint32x4: { size: 4, stride: 16, normalised: !1 },
  sint32: { size: 1, stride: 4, normalised: !1 },
  sint32x2: { size: 2, stride: 8, normalised: !1 },
  sint32x3: { size: 3, stride: 12, normalised: !1 },
  sint32x4: { size: 4, stride: 16, normalised: !1 }
};
function a0(n) {
  return ou[n] ?? ou.float32;
}
const l0 = {
  f32: "float32",
  "vec2<f32>": "float32x2",
  "vec3<f32>": "float32x3",
  "vec4<f32>": "float32x4",
  vec2f: "float32x2",
  vec3f: "float32x3",
  vec4f: "float32x4",
  i32: "sint32",
  "vec2<i32>": "sint32x2",
  "vec3<i32>": "sint32x3",
  "vec4<i32>": "sint32x4",
  u32: "uint32",
  "vec2<u32>": "uint32x2",
  "vec3<u32>": "uint32x3",
  "vec4<u32>": "uint32x4",
  bool: "uint32",
  "vec2<bool>": "uint32x2",
  "vec3<bool>": "uint32x3",
  "vec4<bool>": "uint32x4"
};
function c0({ source: n, entryPoint: t }) {
  const e = {}, s = n.indexOf(`fn ${t}`);
  if (s !== -1) {
    const i = n.indexOf("->", s);
    if (i !== -1) {
      const r = n.substring(s, i), o = /@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g;
      let a;
      for (; (a = o.exec(r)) !== null; ) {
        const l = l0[a[3]] ?? "float32";
        e[a[2]] = {
          location: parseInt(a[1], 10),
          format: l,
          stride: a0(l).stride,
          offset: 0,
          instance: !1,
          start: 0
        };
      }
    }
  }
  return e;
}
function Ra(n) {
  const t = /(^|[^/])@(group|binding)\(\d+\)[^;]+;/g, e = /@group\((\d+)\)/, s = /@binding\((\d+)\)/, i = /var(<[^>]+>)? (\w+)/, r = /:\s*(\w+)/, o = /struct\s+(\w+)\s*{([^}]+)}/g, a = /(\w+)\s*:\s*([\w\<\>]+)/g, l = /struct\s+(\w+)/, c = n.match(t)?.map((u) => ({
    group: parseInt(u.match(e)[1], 10),
    binding: parseInt(u.match(s)[1], 10),
    name: u.match(i)[2],
    isUniform: u.match(i)[1] === "<uniform>",
    type: u.match(r)[1]
  }));
  if (!c)
    return {
      groups: [],
      structs: []
    };
  const h = n.match(o)?.map((u) => {
    const d = u.match(l)[1], f = u.match(a).reduce((p, g) => {
      const [m, y] = g.split(":");
      return p[m.trim()] = y.trim(), p;
    }, {});
    return f ? { name: d, members: f } : null;
  }).filter(({ name: u }) => c.some((d) => d.type === u)) ?? [];
  return {
    groups: c,
    structs: h
  };
}
var zi = /* @__PURE__ */ ((n) => (n[n.VERTEX = 1] = "VERTEX", n[n.FRAGMENT = 2] = "FRAGMENT", n[n.COMPUTE = 4] = "COMPUTE", n))(zi || {});
function h0({ groups: n }) {
  const t = [];
  for (let e = 0; e < n.length; e++) {
    const s = n[e];
    t[s.group] || (t[s.group] = []), s.isUniform ? t[s.group].push({
      binding: s.binding,
      visibility: zi.VERTEX | zi.FRAGMENT,
      buffer: {
        type: "uniform"
      }
    }) : s.type === "sampler" ? t[s.group].push({
      binding: s.binding,
      visibility: zi.FRAGMENT,
      sampler: {
        type: "filtering"
      }
    }) : s.type === "texture_2d" && t[s.group].push({
      binding: s.binding,
      visibility: zi.FRAGMENT,
      texture: {
        sampleType: "float",
        viewDimension: "2d",
        multisampled: !1
      }
    });
  }
  return t;
}
function u0({ groups: n }) {
  const t = [];
  for (let e = 0; e < n.length; e++) {
    const s = n[e];
    t[s.group] || (t[s.group] = {}), t[s.group][s.name] = s.binding;
  }
  return t;
}
function d0(n, t) {
  const e = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), i = [...n.structs, ...t.structs].filter((o) => e.has(o.name) ? !1 : (e.add(o.name), !0)), r = [...n.groups, ...t.groups].filter((o) => {
    const a = `${o.name}-${o.binding}`;
    return s.has(a) ? !1 : (s.add(a), !0);
  });
  return { structs: i, groups: r };
}
const Da = /* @__PURE__ */ Object.create(null);
class Yo {
  /**
   * Create a new GpuProgram
   * @param options - The options for the gpu program
   */
  constructor(t) {
    this._layoutKey = 0, this._attributeLocationsKey = 0;
    const { fragment: e, vertex: s, layout: i, gpuLayout: r, name: o } = t;
    if (this.name = o, this.fragment = e, this.vertex = s, e.source === s.source) {
      const a = Ra(e.source);
      this.structsAndGroups = a;
    } else {
      const a = Ra(s.source), l = Ra(e.source);
      this.structsAndGroups = d0(a, l);
    }
    this.layout = i ?? u0(this.structsAndGroups), this.gpuLayout = r ?? h0(this.structsAndGroups), this.autoAssignGlobalUniforms = this.layout[0]?.globalUniforms !== void 0, this.autoAssignLocalUniforms = this.layout[1]?.localUniforms !== void 0, this._generateProgramKey();
  }
  // TODO maker this pure
  _generateProgramKey() {
    const { vertex: t, fragment: e } = this, s = t.source + e.source + t.entryPoint + e.entryPoint;
    this._layoutKey = Zl(s, "program");
  }
  get attributeData() {
    return this._attributeData ?? (this._attributeData = c0(this.vertex)), this._attributeData;
  }
  /** destroys the program */
  destroy() {
    this.gpuLayout = null, this.layout = null, this.structsAndGroups = null, this.fragment = null, this.vertex = null;
  }
  /**
   * Helper function that creates a program for a given source.
   * It will check the program cache if the program has already been created.
   * If it has that one will be returned, if not a new one will be created and cached.
   * @param options - The options for the program.
   * @returns A program using the same source
   */
  static from(t) {
    const e = `${t.vertex.source}:${t.fragment.source}:${t.fragment.entryPoint}:${t.vertex.entryPoint}`;
    return Da[e] || (Da[e] = new Yo(t)), Da[e];
  }
}
const hp = [
  "f32",
  "i32",
  "vec2<f32>",
  "vec3<f32>",
  "vec4<f32>",
  "mat2x2<f32>",
  "mat3x3<f32>",
  "mat4x4<f32>",
  "mat3x2<f32>",
  "mat4x2<f32>",
  "mat2x3<f32>",
  "mat4x3<f32>",
  "mat2x4<f32>",
  "mat3x4<f32>",
  "vec2<i32>",
  "vec3<i32>",
  "vec4<i32>"
], f0 = hp.reduce((n, t) => (n[t] = !0, n), {});
function p0(n, t) {
  switch (n) {
    case "f32":
      return 0;
    case "vec2<f32>":
      return new Float32Array(2 * t);
    case "vec3<f32>":
      return new Float32Array(3 * t);
    case "vec4<f32>":
      return new Float32Array(4 * t);
    case "mat2x2<f32>":
      return new Float32Array([
        1,
        0,
        0,
        1
      ]);
    case "mat3x3<f32>":
      return new Float32Array([
        1,
        0,
        0,
        0,
        1,
        0,
        0,
        0,
        1
      ]);
    case "mat4x4<f32>":
      return new Float32Array([
        1,
        0,
        0,
        0,
        0,
        1,
        0,
        0,
        0,
        0,
        1,
        0,
        0,
        0,
        0,
        1
      ]);
  }
  return null;
}
const up = class dp {
  /**
   * Create a new Uniform group
   * @param uniformStructures - The structures of the uniform group
   * @param options - The optional parameters of this uniform group
   */
  constructor(t, e) {
    this._touched = 0, this.uid = Ot("uniform"), this._resourceType = "uniformGroup", this._resourceId = Ot("resource"), this.isUniformGroup = !0, this._dirtyId = 0, this.destroyed = !1, e = { ...dp.defaultOptions, ...e }, this.uniformStructures = t;
    const s = {};
    for (const i in t) {
      const r = t[i];
      if (r.name = i, r.size = r.size ?? 1, !f0[r.type])
        throw new Error(`Uniform type ${r.type} is not supported. Supported uniform types are: ${hp.join(", ")}`);
      r.value ?? (r.value = p0(r.type, r.size)), s[i] = r.value;
    }
    this.uniforms = s, this._dirtyId = 1, this.ubo = e.ubo, this.isStatic = e.isStatic, this._signature = Zl(Object.keys(s).map(
      (i) => `${i}-${t[i].type}`
    ).join("-"), "uniform-group");
  }
  /** Call this if you want the uniform groups data to be uploaded to the GPU only useful if `isStatic` is true. */
  update() {
    this._dirtyId++;
  }
};
up.defaultOptions = {
  /** if true the UniformGroup is handled as an Uniform buffer object. */
  ubo: !1,
  /** if true, then you are responsible for when the data is uploaded to the GPU by calling `update()` */
  isStatic: !1
};
let fp = up;
class ao {
  /**
   * Create a new instance eof the Bind Group.
   * @param resources - The resources that are bound together for use by a shader.
   */
  constructor(t) {
    this.resources = /* @__PURE__ */ Object.create(null), this._dirty = !0;
    let e = 0;
    for (const s in t) {
      const i = t[s];
      this.setResource(i, e++);
    }
    this._updateKey();
  }
  /**
   * Updates the key if its flagged as dirty. This is used internally to
   * match this bind group to a WebGPU BindGroup.
   * @internal
   */
  _updateKey() {
    if (!this._dirty)
      return;
    this._dirty = !1;
    const t = [];
    let e = 0;
    for (const s in this.resources)
      t[e++] = this.resources[s]._resourceId;
    this._key = t.join("|");
  }
  /**
   * Set a resource at a given index. this function will
   * ensure that listeners will be removed from the current resource
   * and added to the new resource.
   * @param resource - The resource to set.
   * @param index - The index to set the resource at.
   */
  setResource(t, e) {
    const s = this.resources[e];
    t !== s && (s && t.off?.("change", this.onResourceChange, this), t.on?.("change", this.onResourceChange, this), this.resources[e] = t, this._dirty = !0);
  }
  /**
   * Returns the resource at the current specified index.
   * @param index - The index of the resource to get.
   * @returns - The resource at the specified index.
   */
  getResource(t) {
    return this.resources[t];
  }
  /**
   * Used internally to 'touch' each resource, to ensure that the GC
   * knows that all resources in this bind group are still being used.
   * @param tick - The current tick.
   * @internal
   */
  _touch(t) {
    const e = this.resources;
    for (const s in e)
      e[s]._touched = t;
  }
  /** Destroys this bind group and removes all listeners. */
  destroy() {
    const t = this.resources;
    for (const e in t)
      t[e].off?.("change", this.onResourceChange, this);
    this.resources = null;
  }
  onResourceChange(t) {
    if (this._dirty = !0, t.destroyed) {
      const e = this.resources;
      for (const s in e)
        e[s] === t && (e[s] = null);
    } else
      this._updateKey();
  }
}
var dl = /* @__PURE__ */ ((n) => (n[n.WEBGL = 1] = "WEBGL", n[n.WEBGPU = 2] = "WEBGPU", n[n.BOTH = 3] = "BOTH", n))(dl || {});
class Kl extends ps {
  constructor(t) {
    super(), this.uid = Ot("shader"), this._uniformBindMap = /* @__PURE__ */ Object.create(null), this._ownedBindGroups = [];
    let {
      gpuProgram: e,
      glProgram: s,
      groups: i,
      resources: r,
      compatibleRenderers: o,
      groupMap: a
    } = t;
    this.gpuProgram = e, this.glProgram = s, o === void 0 && (o = 0, e && (o |= dl.WEBGPU), s && (o |= dl.WEBGL)), this.compatibleRenderers = o;
    const l = {};
    if (!r && !i && (r = {}), r && i)
      throw new Error("[Shader] Cannot have both resources and groups");
    if (!e && i && !a)
      throw new Error("[Shader] No group map or WebGPU shader provided - consider using resources instead.");
    if (!e && i && a)
      for (const c in a)
        for (const h in a[c]) {
          const u = a[c][h];
          l[u] = {
            group: c,
            binding: h,
            name: u
          };
        }
    else if (e && i && !a) {
      const c = e.structsAndGroups.groups;
      a = {}, c.forEach((h) => {
        a[h.group] = a[h.group] || {}, a[h.group][h.binding] = h.name, l[h.name] = h;
      });
    } else if (r) {
      i = {}, a = {}, e && e.structsAndGroups.groups.forEach((u) => {
        a[u.group] = a[u.group] || {}, a[u.group][u.binding] = u.name, l[u.name] = u;
      });
      let c = 0;
      for (const h in r)
        l[h] || (i[99] || (i[99] = new ao(), this._ownedBindGroups.push(i[99])), l[h] = { group: 99, binding: c, name: h }, a[99] = a[99] || {}, a[99][c] = h, c++);
      for (const h in r) {
        const u = h;
        let d = r[h];
        !d.source && !d._resourceType && (d = new fp(d));
        const f = l[u];
        f && (i[f.group] || (i[f.group] = new ao(), this._ownedBindGroups.push(i[f.group])), i[f.group].setResource(d, f.binding));
      }
    }
    this.groups = i, this._uniformBindMap = a, this.resources = this._buildResourceAccessor(i, l);
  }
  /**
   * Sometimes a resource group will be provided later (for example global uniforms)
   * In such cases, this method can be used to let the shader know about the group.
   * @param name - the name of the resource group
   * @param groupIndex - the index of the group (should match the webGPU shader group location)
   * @param bindIndex - the index of the bind point (should match the webGPU shader bind point)
   */
  addResource(t, e, s) {
    var i, r;
    (i = this._uniformBindMap)[e] || (i[e] = {}), (r = this._uniformBindMap[e])[s] || (r[s] = t), this.groups[e] || (this.groups[e] = new ao(), this._ownedBindGroups.push(this.groups[e]));
  }
  _buildResourceAccessor(t, e) {
    const s = {};
    for (const i in e) {
      const r = e[i];
      Object.defineProperty(s, r.name, {
        get() {
          return t[r.group].getResource(r.binding);
        },
        set(o) {
          t[r.group].setResource(o, r.binding);
        }
      });
    }
    return s;
  }
  /**
   * Use to destroy the shader when its not longer needed.
   * It will destroy the resources and remove listeners.
   * @param destroyPrograms - if the programs should be destroyed as well.
   * Make sure its not being used by other shaders!
   */
  destroy(t = !1) {
    this.emit("destroy", this), t && (this.gpuProgram?.destroy(), this.glProgram?.destroy()), this.gpuProgram = null, this.glProgram = null, this.removeAllListeners(), this._uniformBindMap = null, this._ownedBindGroups.forEach((e) => {
      e.destroy();
    }), this._ownedBindGroups = null, this.resources = null, this.groups = null;
  }
  static from(t) {
    const { gpu: e, gl: s, ...i } = t;
    let r, o;
    return e && (r = Yo.from(e)), s && (o = cp.from(s)), new Kl({
      gpuProgram: r,
      glProgram: o,
      ...i
    });
  }
}
const fl = [];
ze.handleByNamedList(dt.Environment, fl);
async function m0(n) {
  if (!n)
    for (let t = 0; t < fl.length; t++) {
      const e = fl[t];
      if (e.value.test()) {
        await e.value.load();
        return;
      }
    }
}
let Ei;
function g0() {
  if (typeof Ei == "boolean")
    return Ei;
  try {
    Ei = new Function("param1", "param2", "param3", "return param1[param2] === param3;")({ a: "b" }, "a", "b") === !0;
  } catch {
    Ei = !1;
  }
  return Ei;
}
function au(n, t, e = 2) {
  const s = t && t.length, i = s ? t[0] * e : n.length;
  let r = pp(n, 0, i, e, !0);
  const o = [];
  if (!r || r.next === r.prev) return o;
  let a, l, c;
  if (s && (r = b0(n, t, r, e)), n.length > 80 * e) {
    a = n[0], l = n[1];
    let h = a, u = l;
    for (let d = e; d < i; d += e) {
      const f = n[d], p = n[d + 1];
      f < a && (a = f), p < l && (l = p), f > h && (h = f), p > u && (u = p);
    }
    c = Math.max(h - a, u - l), c = c !== 0 ? 32767 / c : 0;
  }
  return Zi(r, o, e, a, l, c, 0), o;
}
function pp(n, t, e, s, i) {
  let r;
  if (i === F0(n, t, e, s) > 0)
    for (let o = t; o < e; o += s) r = lu(o / s | 0, n[o], n[o + 1], r);
  else
    for (let o = e - s; o >= t; o -= s) r = lu(o / s | 0, n[o], n[o + 1], r);
  return r && Zn(r, r.next) && (Qi(r), r = r.next), r;
}
function Sn(n, t) {
  if (!n) return n;
  t || (t = n);
  let e = n, s;
  do
    if (s = !1, !e.steiner && (Zn(e, e.next) || Ct(e.prev, e, e.next) === 0)) {
      if (Qi(e), e = t = e.prev, e === e.next) break;
      s = !0;
    } else
      e = e.next;
  while (s || e !== t);
  return t;
}
function Zi(n, t, e, s, i, r, o) {
  if (!n) return;
  !o && r && k0(n, s, i, r);
  let a = n;
  for (; n.prev !== n.next; ) {
    const l = n.prev, c = n.next;
    if (r ? x0(n, s, i, r) : y0(n)) {
      t.push(l.i, n.i, c.i), Qi(n), n = c.next, a = c.next;
      continue;
    }
    if (n = c, n === a) {
      o ? o === 1 ? (n = _0(Sn(n), t), Zi(n, t, e, s, i, r, 2)) : o === 2 && v0(n, t, e, s, i, r) : Zi(Sn(n), t, e, s, i, r, 1);
      break;
    }
  }
}
function y0(n) {
  const t = n.prev, e = n, s = n.next;
  if (Ct(t, e, s) >= 0) return !1;
  const i = t.x, r = e.x, o = s.x, a = t.y, l = e.y, c = s.y, h = Math.min(i, r, o), u = Math.min(a, l, c), d = Math.max(i, r, o), f = Math.max(a, l, c);
  let p = s.next;
  for (; p !== t; ) {
    if (p.x >= h && p.x <= d && p.y >= u && p.y <= f && qi(i, a, r, l, o, c, p.x, p.y) && Ct(p.prev, p, p.next) >= 0) return !1;
    p = p.next;
  }
  return !0;
}
function x0(n, t, e, s) {
  const i = n.prev, r = n, o = n.next;
  if (Ct(i, r, o) >= 0) return !1;
  const a = i.x, l = r.x, c = o.x, h = i.y, u = r.y, d = o.y, f = Math.min(a, l, c), p = Math.min(h, u, d), g = Math.max(a, l, c), m = Math.max(h, u, d), y = pl(f, p, t, e, s), x = pl(g, m, t, e, s);
  let v = n.prevZ, _ = n.nextZ;
  for (; v && v.z >= y && _ && _.z <= x; ) {
    if (v.x >= f && v.x <= g && v.y >= p && v.y <= m && v !== i && v !== o && qi(a, h, l, u, c, d, v.x, v.y) && Ct(v.prev, v, v.next) >= 0 || (v = v.prevZ, _.x >= f && _.x <= g && _.y >= p && _.y <= m && _ !== i && _ !== o && qi(a, h, l, u, c, d, _.x, _.y) && Ct(_.prev, _, _.next) >= 0)) return !1;
    _ = _.nextZ;
  }
  for (; v && v.z >= y; ) {
    if (v.x >= f && v.x <= g && v.y >= p && v.y <= m && v !== i && v !== o && qi(a, h, l, u, c, d, v.x, v.y) && Ct(v.prev, v, v.next) >= 0) return !1;
    v = v.prevZ;
  }
  for (; _ && _.z <= x; ) {
    if (_.x >= f && _.x <= g && _.y >= p && _.y <= m && _ !== i && _ !== o && qi(a, h, l, u, c, d, _.x, _.y) && Ct(_.prev, _, _.next) >= 0) return !1;
    _ = _.nextZ;
  }
  return !0;
}
function _0(n, t) {
  let e = n;
  do {
    const s = e.prev, i = e.next.next;
    !Zn(s, i) && gp(s, e, e.next, i) && Ki(s, i) && Ki(i, s) && (t.push(s.i, e.i, i.i), Qi(e), Qi(e.next), e = n = i), e = e.next;
  } while (e !== n);
  return Sn(e);
}
function v0(n, t, e, s, i, r) {
  let o = n;
  do {
    let a = o.next.next;
    for (; a !== o.prev; ) {
      if (o.i !== a.i && E0(o, a)) {
        let l = yp(o, a);
        o = Sn(o, o.next), l = Sn(l, l.next), Zi(o, t, e, s, i, r, 0), Zi(l, t, e, s, i, r, 0);
        return;
      }
      a = a.next;
    }
    o = o.next;
  } while (o !== n);
}
function b0(n, t, e, s) {
  const i = [];
  for (let r = 0, o = t.length; r < o; r++) {
    const a = t[r] * s, l = r < o - 1 ? t[r + 1] * s : n.length, c = pp(n, a, l, s, !1);
    c === c.next && (c.steiner = !0), i.push(A0(c));
  }
  i.sort(w0);
  for (let r = 0; r < i.length; r++)
    e = S0(i[r], e);
  return e;
}
function w0(n, t) {
  let e = n.x - t.x;
  if (e === 0 && (e = n.y - t.y, e === 0)) {
    const s = (n.next.y - n.y) / (n.next.x - n.x), i = (t.next.y - t.y) / (t.next.x - t.x);
    e = s - i;
  }
  return e;
}
function S0(n, t) {
  const e = T0(n, t);
  if (!e)
    return t;
  const s = yp(e, n);
  return Sn(s, s.next), Sn(e, e.next);
}
function T0(n, t) {
  let e = t;
  const s = n.x, i = n.y;
  let r = -1 / 0, o;
  if (Zn(n, e)) return e;
  do {
    if (Zn(n, e.next)) return e.next;
    if (i <= e.y && i >= e.next.y && e.next.y !== e.y) {
      const u = e.x + (i - e.y) * (e.next.x - e.x) / (e.next.y - e.y);
      if (u <= s && u > r && (r = u, o = e.x < e.next.x ? e : e.next, u === s))
        return o;
    }
    e = e.next;
  } while (e !== t);
  if (!o) return null;
  const a = o, l = o.x, c = o.y;
  let h = 1 / 0;
  e = o;
  do {
    if (s >= e.x && e.x >= l && s !== e.x && mp(i < c ? s : r, i, l, c, i < c ? r : s, i, e.x, e.y)) {
      const u = Math.abs(i - e.y) / (s - e.x);
      Ki(e, n) && (u < h || u === h && (e.x > o.x || e.x === o.x && M0(o, e))) && (o = e, h = u);
    }
    e = e.next;
  } while (e !== a);
  return o;
}
function M0(n, t) {
  return Ct(n.prev, n, t.prev) < 0 && Ct(t.next, n, n.next) < 0;
}
function k0(n, t, e, s) {
  let i = n;
  do
    i.z === 0 && (i.z = pl(i.x, i.y, t, e, s)), i.prevZ = i.prev, i.nextZ = i.next, i = i.next;
  while (i !== n);
  i.prevZ.nextZ = null, i.prevZ = null, C0(i);
}
function C0(n) {
  let t, e = 1;
  do {
    let s = n, i;
    n = null;
    let r = null;
    for (t = 0; s; ) {
      t++;
      let o = s, a = 0;
      for (let c = 0; c < e && (a++, o = o.nextZ, !!o); c++)
        ;
      let l = e;
      for (; a > 0 || l > 0 && o; )
        a !== 0 && (l === 0 || !o || s.z <= o.z) ? (i = s, s = s.nextZ, a--) : (i = o, o = o.nextZ, l--), r ? r.nextZ = i : n = i, i.prevZ = r, r = i;
      s = o;
    }
    r.nextZ = null, e *= 2;
  } while (t > 1);
  return n;
}
function pl(n, t, e, s, i) {
  return n = (n - e) * i | 0, t = (t - s) * i | 0, n = (n | n << 8) & 16711935, n = (n | n << 4) & 252645135, n = (n | n << 2) & 858993459, n = (n | n << 1) & 1431655765, t = (t | t << 8) & 16711935, t = (t | t << 4) & 252645135, t = (t | t << 2) & 858993459, t = (t | t << 1) & 1431655765, n | t << 1;
}
function A0(n) {
  let t = n, e = n;
  do
    (t.x < e.x || t.x === e.x && t.y < e.y) && (e = t), t = t.next;
  while (t !== n);
  return e;
}
function mp(n, t, e, s, i, r, o, a) {
  return (i - o) * (t - a) >= (n - o) * (r - a) && (n - o) * (s - a) >= (e - o) * (t - a) && (e - o) * (r - a) >= (i - o) * (s - a);
}
function qi(n, t, e, s, i, r, o, a) {
  return !(n === o && t === a) && mp(n, t, e, s, i, r, o, a);
}
function E0(n, t) {
  return n.next.i !== t.i && n.prev.i !== t.i && !P0(n, t) && // doesn't intersect other edges
  (Ki(n, t) && Ki(t, n) && I0(n, t) && // locally visible
  (Ct(n.prev, n, t.prev) || Ct(n, t.prev, t)) || // does not create opposite-facing sectors
  Zn(n, t) && Ct(n.prev, n, n.next) > 0 && Ct(t.prev, t, t.next) > 0);
}
function Ct(n, t, e) {
  return (t.y - n.y) * (e.x - t.x) - (t.x - n.x) * (e.y - t.y);
}
function Zn(n, t) {
  return n.x === t.x && n.y === t.y;
}
function gp(n, t, e, s) {
  const i = Hr(Ct(n, t, e)), r = Hr(Ct(n, t, s)), o = Hr(Ct(e, s, n)), a = Hr(Ct(e, s, t));
  return !!(i !== r && o !== a || i === 0 && $r(n, e, t) || r === 0 && $r(n, s, t) || o === 0 && $r(e, n, s) || a === 0 && $r(e, t, s));
}
function $r(n, t, e) {
  return t.x <= Math.max(n.x, e.x) && t.x >= Math.min(n.x, e.x) && t.y <= Math.max(n.y, e.y) && t.y >= Math.min(n.y, e.y);
}
function Hr(n) {
  return n > 0 ? 1 : n < 0 ? -1 : 0;
}
function P0(n, t) {
  let e = n;
  do {
    if (e.i !== n.i && e.next.i !== n.i && e.i !== t.i && e.next.i !== t.i && gp(e, e.next, n, t)) return !0;
    e = e.next;
  } while (e !== n);
  return !1;
}
function Ki(n, t) {
  return Ct(n.prev, n, n.next) < 0 ? Ct(n, t, n.next) >= 0 && Ct(n, n.prev, t) >= 0 : Ct(n, t, n.prev) < 0 || Ct(n, n.next, t) < 0;
}
function I0(n, t) {
  let e = n, s = !1;
  const i = (n.x + t.x) / 2, r = (n.y + t.y) / 2;
  do
    e.y > r != e.next.y > r && e.next.y !== e.y && i < (e.next.x - e.x) * (r - e.y) / (e.next.y - e.y) + e.x && (s = !s), e = e.next;
  while (e !== n);
  return s;
}
function yp(n, t) {
  const e = ml(n.i, n.x, n.y), s = ml(t.i, t.x, t.y), i = n.next, r = t.prev;
  return n.next = t, t.prev = n, e.next = i, i.prev = e, s.next = e, e.prev = s, r.next = s, s.prev = r, s;
}
function lu(n, t, e, s) {
  const i = ml(n, t, e);
  return s ? (i.next = s.next, i.prev = s, s.next.prev = i, s.next = i) : (i.prev = i, i.next = i), i;
}
function Qi(n) {
  n.next.prev = n.prev, n.prev.next = n.next, n.prevZ && (n.prevZ.nextZ = n.nextZ), n.nextZ && (n.nextZ.prevZ = n.prevZ);
}
function ml(n, t, e) {
  return {
    i: n,
    // vertex index in coordinates array
    x: t,
    y: e,
    // vertex coordinates
    prev: null,
    // previous and next vertex nodes in a polygon ring
    next: null,
    z: 0,
    // z-order curve value
    prevZ: null,
    // previous and next nodes in z-order
    nextZ: null,
    steiner: !1
    // indicates whether this is a steiner point
  };
}
function F0(n, t, e, s) {
  let i = 0;
  for (let r = t, o = e - s; r < e; r += s)
    i += (n[o] - n[r]) * (n[r + 1] + n[o + 1]), o = r;
  return i;
}
const R0 = au.default || au;
var xp = /* @__PURE__ */ ((n) => (n[n.NONE = 0] = "NONE", n[n.COLOR = 16384] = "COLOR", n[n.STENCIL = 1024] = "STENCIL", n[n.DEPTH = 256] = "DEPTH", n[n.COLOR_DEPTH = 16640] = "COLOR_DEPTH", n[n.COLOR_STENCIL = 17408] = "COLOR_STENCIL", n[n.DEPTH_STENCIL = 1280] = "DEPTH_STENCIL", n[n.ALL = 17664] = "ALL", n))(xp || {});
class D0 {
  /**
   * @param name - The function name that will be executed on the listeners added to this Runner.
   */
  constructor(t) {
    this.items = [], this._name = t;
  }
  /* jsdoc/check-param-names */
  /**
   * Dispatch/Broadcast Runner to all listeners added to the queue.
   * @param {...any} params - (optional) parameters to pass to each listener
   */
  /* jsdoc/check-param-names */
  emit(t, e, s, i, r, o, a, l) {
    const { name: c, items: h } = this;
    for (let u = 0, d = h.length; u < d; u++)
      h[u][c](t, e, s, i, r, o, a, l);
    return this;
  }
  /**
   * Add a listener to the Runner
   *
   * Runners do not need to have scope or functions passed to them.
   * All that is required is to pass the listening object and ensure that it has contains a function that has the same name
   * as the name provided to the Runner when it was created.
   *
   * Eg A listener passed to this Runner will require a 'complete' function.
   *
   * ```ts
   * import { Runner } from 'pixi.js';
   *
   * const complete = new Runner('complete');
   * ```
   *
   * The scope used will be the object itself.
   * @param {any} item - The object that will be listening.
   */
  add(t) {
    return t[this._name] && (this.remove(t), this.items.push(t)), this;
  }
  /**
   * Remove a single listener from the dispatch queue.
   * @param {any} item - The listener that you would like to remove.
   */
  remove(t) {
    const e = this.items.indexOf(t);
    return e !== -1 && this.items.splice(e, 1), this;
  }
  /**
   * Check to see if the listener is already in the Runner
   * @param {any} item - The listener that you would like to check.
   */
  contains(t) {
    return this.items.indexOf(t) !== -1;
  }
  /** Remove all listeners from the Runner */
  removeAll() {
    return this.items.length = 0, this;
  }
  /** Remove all references, don't use after this. */
  destroy() {
    this.removeAll(), this.items = null, this._name = null;
  }
  /**
   * `true` if there are no this Runner contains no listeners
   * @readonly
   */
  get empty() {
    return this.items.length === 0;
  }
  /**
   * The name of the runner.
   * @readonly
   */
  get name() {
    return this._name;
  }
}
const O0 = [
  "init",
  "destroy",
  "contextChange",
  "resolutionChange",
  "resetState",
  "renderEnd",
  "renderStart",
  "render",
  "update",
  "postrender",
  "prerender"
], _p = class vp extends ps {
  /**
   * Set up a system with a collection of SystemClasses and runners.
   * Systems are attached dynamically to this class when added.
   * @param config - the config for the system manager
   */
  constructor(t) {
    super(), this.uid = Ot("renderer"), this.runners = /* @__PURE__ */ Object.create(null), this.renderPipes = /* @__PURE__ */ Object.create(null), this._initOptions = {}, this._systemsHash = /* @__PURE__ */ Object.create(null), this.type = t.type, this.name = t.name, this.config = t;
    const e = [...O0, ...this.config.runners ?? []];
    this._addRunners(...e), this._unsafeEvalCheck();
  }
  /**
   * Initialize the renderer.
   * @param options - The options to use to create the renderer.
   */
  async init(t = {}) {
    const e = t.skipExtensionImports === !0 ? !0 : t.manageImports === !1;
    await m0(e), this._addSystems(this.config.systems), this._addPipes(this.config.renderPipes, this.config.renderPipeAdaptors);
    for (const s in this._systemsHash)
      t = { ...this._systemsHash[s].constructor.defaultOptions, ...t };
    t = { ...vp.defaultOptions, ...t }, this._roundPixels = t.roundPixels ? 1 : 0;
    for (let s = 0; s < this.runners.init.items.length; s++)
      await this.runners.init.items[s].init(t);
    this._initOptions = t;
  }
  render(t, e) {
    let s = t;
    if (s instanceof Te && (s = { container: s }, e && (ct(kt, "passing a second argument is deprecated, please use render options instead"), s.target = e.renderTexture)), s.target || (s.target = this.view.renderTarget), s.target === this.view.renderTarget && (this._lastObjectRendered = s.container, s.clearColor ?? (s.clearColor = this.background.colorRgba), s.clear ?? (s.clear = this.background.clearBeforeRender)), s.clearColor) {
      const i = Array.isArray(s.clearColor) && s.clearColor.length === 4;
      s.clearColor = i ? s.clearColor : Bt.shared.setValue(s.clearColor).toArray();
    }
    s.transform || (s.container.updateLocalTransform(), s.transform = s.container.localTransform), s.container.enableRenderGroup(), this.runners.prerender.emit(s), this.runners.renderStart.emit(s), this.runners.render.emit(s), this.runners.renderEnd.emit(s), this.runners.postrender.emit(s);
  }
  /**
   * Resizes the WebGL view to the specified width and height.
   * @param desiredScreenWidth - The desired width of the screen.
   * @param desiredScreenHeight - The desired height of the screen.
   * @param resolution - The resolution / device pixel ratio of the renderer.
   */
  resize(t, e, s) {
    const i = this.view.resolution;
    this.view.resize(t, e, s), this.emit("resize", this.view.screen.width, this.view.screen.height, this.view.resolution), s !== void 0 && s !== i && this.runners.resolutionChange.emit(s);
  }
  /**
   * Clears the render target.
   * @param options - The options to use when clearing the render target.
   * @param options.target - The render target to clear.
   * @param options.clearColor - The color to clear with.
   * @param options.clear - The clear mode to use.
   * @advanced
   */
  clear(t = {}) {
    const e = this;
    t.target || (t.target = e.renderTarget.renderTarget), t.clearColor || (t.clearColor = this.background.colorRgba), t.clear ?? (t.clear = xp.ALL);
    const { clear: s, clearColor: i, target: r } = t;
    Bt.shared.setValue(i ?? this.background.colorRgba), e.renderTarget.clear(r, s, Bt.shared.toArray());
  }
  /** The resolution / device pixel ratio of the renderer. */
  get resolution() {
    return this.view.resolution;
  }
  set resolution(t) {
    this.view.resolution = t, this.runners.resolutionChange.emit(t);
  }
  /**
   * Same as view.width, actual number of pixels in the canvas by horizontal.
   * @type {number}
   * @readonly
   * @default 800
   */
  get width() {
    return this.view.texture.frame.width;
  }
  /**
   * Same as view.height, actual number of pixels in the canvas by vertical.
   * @default 600
   */
  get height() {
    return this.view.texture.frame.height;
  }
  // NOTE: this was `view` in v7
  /**
   * The canvas element that everything is drawn to.
   * @type {environment.ICanvas}
   */
  get canvas() {
    return this.view.canvas;
  }
  /**
   * the last object rendered by the renderer. Useful for other plugins like interaction managers
   * @readonly
   */
  get lastObjectRendered() {
    return this._lastObjectRendered;
  }
  /**
   * Flag if we are rendering to the screen vs renderTexture
   * @readonly
   * @default true
   */
  get renderingToScreen() {
    return this.renderTarget.renderingToScreen;
  }
  /**
   * Measurements of the screen. (0, 0, screenWidth, screenHeight).
   *
   * Its safe to use as filterArea or hitArea for the whole stage.
   */
  get screen() {
    return this.view.screen;
  }
  /**
   * Create a bunch of runners based of a collection of ids
   * @param runnerIds - the runner ids to add
   */
  _addRunners(...t) {
    t.forEach((e) => {
      this.runners[e] = new D0(e);
    });
  }
  _addSystems(t) {
    let e;
    for (e in t) {
      const s = t[e];
      this._addSystem(s.value, s.name);
    }
  }
  /**
   * Add a new system to the renderer.
   * @param ClassRef - Class reference
   * @param name - Property name for system, if not specified
   *        will use a static `name` property on the class itself. This
   *        name will be assigned as s property on the Renderer so make
   *        sure it doesn't collide with properties on Renderer.
   * @returns Return instance of renderer
   */
  _addSystem(t, e) {
    const s = new t(this);
    if (this[e])
      throw new Error(`Whoops! The name "${e}" is already in use`);
    this[e] = s, this._systemsHash[e] = s;
    for (const i in this.runners)
      this.runners[i].add(s);
    return this;
  }
  _addPipes(t, e) {
    const s = e.reduce((i, r) => (i[r.name] = r.value, i), {});
    t.forEach((i) => {
      const r = i.value, o = i.name, a = s[o];
      this.renderPipes[o] = new r(
        this,
        a ? new a() : null
      );
    });
  }
  destroy(t = !1) {
    this.runners.destroy.items.reverse(), this.runners.destroy.emit(t), Object.values(this.runners).forEach((e) => {
      e.destroy();
    }), this._systemsHash = null, this.renderPipes = null;
  }
  /**
   * Generate a texture from a container.
   * @param options - options or container target to use when generating the texture
   * @returns a texture
   */
  generateTexture(t) {
    return this.textureGenerator.generateTexture(t);
  }
  /**
   * Whether the renderer will round coordinates to whole pixels when rendering.
   * Can be overridden on a per scene item basis.
   */
  get roundPixels() {
    return !!this._roundPixels;
  }
  /**
   * Overridable function by `pixi.js/unsafe-eval` to silence
   * throwing an error if platform doesn't support unsafe-evals.
   * @private
   * @ignore
   */
  _unsafeEvalCheck() {
    if (!g0())
      throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.");
  }
  /**
   * Resets the rendering state of the renderer.
   * This is useful when you want to use the WebGL context directly and need to ensure PixiJS's internal state
   * stays synchronized. When modifying the WebGL context state externally, calling this method before the next Pixi
   * render will reset all internal caches and ensure it executes correctly.
   *
   * This is particularly useful when combining PixiJS with other rendering engines like Three.js:
   * ```js
   * // Reset Three.js state
   * threeRenderer.resetState();
   *
   * // Render a Three.js scene
   * threeRenderer.render(threeScene, threeCamera);
   *
   * // Reset PixiJS state since Three.js modified the WebGL context
   * pixiRenderer.resetState();
   *
   * // Now render Pixi content
   * pixiRenderer.render(pixiScene);
   * ```
   * @advanced
   */
  resetState() {
    this.runners.resetState.emit();
  }
};
_p.defaultOptions = {
  /**
   * Default resolution / device pixel ratio of the renderer.
   * @default 1
   */
  resolution: 1,
  /**
   * Should the `failIfMajorPerformanceCaveat` flag be enabled as a context option used in the `isWebGLSupported`
   * function. If set to true, a WebGL renderer can fail to be created if the browser thinks there could be
   * performance issues when using WebGL.
   *
   * In PixiJS v6 this has changed from true to false by default, to allow WebGL to work in as many
   * scenarios as possible. However, some users may have a poor experience, for example, if a user has a gpu or
   * driver version blacklisted by the
   * browser.
   *
   * If your application requires high performance rendering, you may wish to set this to false.
   * We recommend one of two options if you decide to set this flag to false:
   *
   * 1: Use the Canvas renderer as a fallback in case high performance WebGL is
   *    not supported.
   *
   * 2: Call `isWebGLSupported` (which if found in the utils package) in your code before attempting to create a
   *    PixiJS renderer, and show an error message to the user if the function returns false, explaining that their
   *    device & browser combination does not support high performance WebGL.
   *    This is a much better strategy than trying to create a PixiJS renderer and finding it then fails.
   * @default false
   */
  failIfMajorPerformanceCaveat: !1,
  /**
   * Should round pixels be forced when rendering?
   * @default false
   */
  roundPixels: !1
};
let bp = _p, jr;
function N0(n) {
  return jr !== void 0 || (jr = (() => {
    const t = {
      stencil: !0,
      failIfMajorPerformanceCaveat: n ?? bp.defaultOptions.failIfMajorPerformanceCaveat
    };
    try {
      if (!Ae.get().getWebGLRenderingContext())
        return !1;
      let s = Ae.get().createCanvas().getContext("webgl", t);
      const i = !!s?.getContextAttributes()?.stencil;
      if (s) {
        const r = s.getExtension("WEBGL_lose_context");
        r && r.loseContext();
      }
      return s = null, i;
    } catch {
      return !1;
    }
  })()), jr;
}
let Xr;
async function L0(n = {}) {
  return Xr !== void 0 || (Xr = await (async () => {
    const t = Ae.get().getNavigator().gpu;
    if (!t)
      return !1;
    try {
      return await (await t.requestAdapter(n)).requestDevice(), !0;
    } catch {
      return !1;
    }
  })()), Xr;
}
const cu = ["webgl", "webgpu", "canvas"];
async function V0(n) {
  let t = [];
  n.preference ? (t.push(n.preference), cu.forEach((r) => {
    r !== n.preference && t.push(r);
  })) : t = cu.slice();
  let e, s = {};
  for (let r = 0; r < t.length; r++) {
    const o = t[r];
    if (o === "webgpu" && await L0()) {
      const { WebGPURenderer: a } = await import("./WebGPURenderer-Do4eogWs.js");
      e = a, s = { ...n, ...n.webgpu };
      break;
    } else if (o === "webgl" && N0(
      n.failIfMajorPerformanceCaveat ?? bp.defaultOptions.failIfMajorPerformanceCaveat
    )) {
      const { WebGLRenderer: a } = await import("./WebGLRenderer-71VIucIP.js");
      e = a, s = { ...n, ...n.webgl };
      break;
    } else if (o === "canvas")
      throw s = { ...n }, new Error("CanvasRenderer is not yet implemented");
  }
  if (delete s.webgpu, delete s.webgl, !e)
    throw new Error("No available renderer for the current environment");
  const i = new e();
  return await i.init(s), i;
}
const wp = "8.12.0";
class Sp {
  static init() {
    globalThis.__PIXI_APP_INIT__?.(this, wp);
  }
  static destroy() {
  }
}
Sp.extension = dt.Application;
class B0 {
  constructor(t) {
    this._renderer = t;
  }
  init() {
    globalThis.__PIXI_RENDERER_INIT__?.(this._renderer, wp);
  }
  destroy() {
    this._renderer = null;
  }
}
B0.extension = {
  type: [
    dt.WebGLSystem,
    dt.WebGPUSystem
  ],
  name: "initHook",
  priority: -10
};
const Tp = class gl {
  constructor(...t) {
    this.stage = new Te(), t[0] !== void 0 && ct(kt, "Application constructor options are deprecated, please use Application.init() instead.");
  }
  /**
   * Initializes the PixiJS application with the specified options.
   *
   * This method must be called after creating a new Application instance.
   * @param options - Configuration options for the application and renderer
   * @returns A promise that resolves when initialization is complete
   * @example
   * ```js
   * const app = new Application();
   *
   * // Initialize with custom options
   * await app.init({
   *     width: 800,
   *     height: 600,
   *     backgroundColor: 0x1099bb,
   *     preference: 'webgl', // or 'webgpu'
   * });
   * ```
   */
  async init(t) {
    t = { ...t }, this.renderer = await V0(t), gl._plugins.forEach((e) => {
      e.init.call(this, t);
    });
  }
  /**
   * Renders the current stage to the screen.
   *
   * When using the default setup with {@link TickerPlugin} (enabled by default), you typically don't need to call
   * this method directly as rendering is handled automatically.
   *
   * Only use this method if you've disabled the {@link TickerPlugin} or need custom
   * render timing control.
   * @example
   * ```js
   * // Example 1: Default setup (TickerPlugin handles rendering)
   * const app = new Application();
   * await app.init();
   * // No need to call render() - TickerPlugin handles it
   *
   * // Example 2: Custom rendering loop (if TickerPlugin is disabled)
   * const app = new Application();
   * await app.init({ autoStart: false }); // Disable automatic rendering
   *
   * function animate() {
   *     app.render();
   *     requestAnimationFrame(animate);
   * }
   * animate();
   * ```
   */
  render() {
    this.renderer.render({ container: this.stage });
  }
  /**
   * Reference to the renderer's canvas element. This is the HTML element
   * that displays your application's graphics.
   * @readonly
   * @type {HTMLCanvasElement}
   * @example
   * ```js
   * // Create a new application
   * const app = new Application();
   * // Initialize the application
   * await app.init({...});
   * // Add canvas to the page
   * document.body.appendChild(app.canvas);
   *
   * // Access the canvas directly
   * console.log(app.canvas); // HTMLCanvasElement
   * ```
   */
  get canvas() {
    return this.renderer.canvas;
  }
  /**
   * Reference to the renderer's canvas element.
   * @type {HTMLCanvasElement}
   * @deprecated since 8.0.0
   * @see {@link Application#canvas}
   */
  get view() {
    return ct(kt, "Application.view is deprecated, please use Application.canvas instead."), this.renderer.canvas;
  }
  /**
   * Reference to the renderer's screen rectangle. This represents the visible area of your application.
   *
   * It's commonly used for:
   * - Setting filter areas for full-screen effects
   * - Defining hit areas for screen-wide interaction
   * - Determining the visible bounds of your application
   * @readonly
   * @example
   * ```js
   * // Use as filter area for a full-screen effect
   * const blurFilter = new BlurFilter();
   * sprite.filterArea = app.screen;
   *
   * // Use as hit area for screen-wide interaction
   * const screenSprite = new Sprite();
   * screenSprite.hitArea = app.screen;
   *
   * // Get screen dimensions
   * console.log(app.screen.width, app.screen.height);
   * ```
   * @see {@link Rectangle} For all available properties and methods
   */
  get screen() {
    return this.renderer.screen;
  }
  /**
   * Destroys the application and all of its resources.
   *
   * This method should be called when you want to completely
   * clean up the application and free all associated memory.
   * @param rendererDestroyOptions - Options for destroying the renderer:
   *  - `false` or `undefined`: Preserves the canvas element (default)
   *  - `true`: Removes the canvas element
   *  - `{ removeView: boolean }`: Object with removeView property to control canvas removal
   * @param options - Options for destroying the application:
   *  - `false` or `undefined`: Basic cleanup (default)
   *  - `true`: Complete cleanup including children
   *  - Detailed options object:
   *    - `children`: Remove children
   *    - `texture`: Destroy textures
   *    - `textureSource`: Destroy texture sources
   *    - `context`: Destroy WebGL context
   * @example
   * ```js
   * // Basic cleanup
   * app.destroy();
   *
   * // Remove canvas and do complete cleanup
   * app.destroy(true, true);
   *
   * // Remove canvas with explicit options
   * app.destroy({ removeView: true }, true);
   *
   * // Detailed cleanup with specific options
   * app.destroy(
   *     { removeView: true },
   *     {
   *         children: true,
   *         texture: true,
   *         textureSource: true,
   *         context: true
   *     }
   * );
   * ```
   * > [!WARNING] After calling destroy, the application instance should no longer be used.
   * > All properties will be null and further operations will throw errors.
   */
  destroy(t = !1, e = !1) {
    const s = gl._plugins.slice(0);
    s.reverse(), s.forEach((i) => {
      i.destroy.call(this);
    }), this.stage.destroy(e), this.stage = null, this.renderer.destroy(t), this.renderer = null;
  }
};
Tp._plugins = [];
let Mp = Tp;
ze.handleByList(dt.Application, Mp._plugins);
ze.add(Sp);
const z0 = [
  "serif",
  "sans-serif",
  "monospace",
  "cursive",
  "fantasy",
  "system-ui"
];
function kp(n) {
  const t = typeof n.fontSize == "number" ? `${n.fontSize}px` : n.fontSize;
  let e = n.fontFamily;
  Array.isArray(n.fontFamily) || (e = n.fontFamily.split(","));
  for (let s = e.length - 1; s >= 0; s--) {
    let i = e[s].trim();
    !/([\"\'])[^\'\"]+\1/.test(i) && !z0.includes(i) && (i = `"${i}"`), e[s] = i;
  }
  return `${n.fontStyle} ${n.fontVariant} ${n.fontWeight} ${t} ${e.join(",")}`;
}
const Oa = {
  // TextMetrics requires getImageData readback for measuring fonts.
  willReadFrequently: !0
}, ms = class Y {
  /**
   * Checking that we can use modern canvas 2D API.
   *
   * Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
   * @see TextMetrics.experimentalLetterSpacing
   * @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
   * @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
   */
  static get experimentalLetterSpacingSupported() {
    let t = Y._experimentalLetterSpacingSupported;
    if (t === void 0) {
      const e = Ae.get().getCanvasRenderingContext2D().prototype;
      t = Y._experimentalLetterSpacingSupported = "letterSpacing" in e || "textLetterSpacing" in e;
    }
    return t;
  }
  /**
   * @param text - the text that was measured
   * @param style - the style that was measured
   * @param width - the measured width of the text
   * @param height - the measured height of the text
   * @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
   * @param lineWidths - an array of the line widths for each line matched to `lines`
   * @param lineHeight - the measured line height for this style
   * @param maxLineWidth - the maximum line width for all measured lines
   * @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
   */
  constructor(t, e, s, i, r, o, a, l, c) {
    this.text = t, this.style = e, this.width = s, this.height = i, this.lines = r, this.lineWidths = o, this.lineHeight = a, this.maxLineWidth = l, this.fontProperties = c;
  }
  /**
   * Measures the supplied string of text and returns a Rectangle.
   * @param text - The text to measure.
   * @param style - The text style to use for measuring
   * @param canvas - optional specification of the canvas to use for measuring.
   * @param wordWrap
   * @returns Measured width and height of the text.
   */
  static measureText(t = " ", e, s = Y._canvas, i = e.wordWrap) {
    const r = kp(e), o = Y.measureFont(r);
    o.fontSize === 0 && (o.fontSize = e.fontSize, o.ascent = e.fontSize);
    const a = Y.__context;
    a.font = r;
    const c = (i ? Y._wordWrap(t, e, s) : t).split(/(?:\r\n|\r|\n)/), h = new Array(c.length);
    let u = 0;
    for (let y = 0; y < c.length; y++) {
      const x = Y._measureText(c[y], e.letterSpacing, a);
      h[y] = x, u = Math.max(u, x);
    }
    const d = e._stroke?.width || 0;
    let f = u + d;
    e.dropShadow && (f += e.dropShadow.distance);
    const p = e.lineHeight || o.fontSize;
    let g = Math.max(p, o.fontSize + d) + (c.length - 1) * (p + e.leading);
    return e.dropShadow && (g += e.dropShadow.distance), new Y(
      t,
      e,
      f,
      g,
      c,
      h,
      p + e.leading,
      u,
      o
    );
  }
  static _measureText(t, e, s) {
    let i = !1;
    Y.experimentalLetterSpacingSupported && (Y.experimentalLetterSpacing ? (s.letterSpacing = `${e}px`, s.textLetterSpacing = `${e}px`, i = !0) : (s.letterSpacing = "0px", s.textLetterSpacing = "0px"));
    const r = s.measureText(t);
    let o = r.width;
    const a = -r.actualBoundingBoxLeft;
    let c = r.actualBoundingBoxRight - a;
    if (o > 0)
      if (i)
        o -= e, c -= e;
      else {
        const h = (Y.graphemeSegmenter(t).length - 1) * e;
        o += h, c += h;
      }
    return Math.max(o, c);
  }
  /**
   * Applies newlines to a string to have it optimally fit into the horizontal
   * bounds set by the Text object's wordWrapWidth property.
   * @param text - String to apply word wrapping to
   * @param style - the style to use when wrapping
   * @param canvas - optional specification of the canvas to use for measuring.
   * @returns New string with new lines applied where required
   */
  static _wordWrap(t, e, s = Y._canvas) {
    const i = s.getContext("2d", Oa);
    let r = 0, o = "", a = "";
    const l = /* @__PURE__ */ Object.create(null), { letterSpacing: c, whiteSpace: h } = e, u = Y._collapseSpaces(h), d = Y._collapseNewlines(h);
    let f = !u;
    const p = e.wordWrapWidth + c, g = Y._tokenize(t);
    for (let m = 0; m < g.length; m++) {
      let y = g[m];
      if (Y._isNewline(y)) {
        if (!d) {
          a += Y._addLine(o), f = !u, o = "", r = 0;
          continue;
        }
        y = " ";
      }
      if (u) {
        const v = Y.isBreakingSpace(y), _ = Y.isBreakingSpace(o[o.length - 1]);
        if (v && _)
          continue;
      }
      const x = Y._getFromCache(y, c, l, i);
      if (x > p)
        if (o !== "" && (a += Y._addLine(o), o = "", r = 0), Y.canBreakWords(y, e.breakWords)) {
          const v = Y.wordWrapSplit(y);
          for (let _ = 0; _ < v.length; _++) {
            let b = v[_], w = b, S = 1;
            for (; v[_ + S]; ) {
              const k = v[_ + S];
              if (!Y.canBreakChars(w, k, y, _, e.breakWords))
                b += k;
              else
                break;
              w = k, S++;
            }
            _ += S - 1;
            const T = Y._getFromCache(b, c, l, i);
            T + r > p && (a += Y._addLine(o), f = !1, o = "", r = 0), o += b, r += T;
          }
        } else {
          o.length > 0 && (a += Y._addLine(o), o = "", r = 0);
          const v = m === g.length - 1;
          a += Y._addLine(y, !v), f = !1, o = "", r = 0;
        }
      else
        x + r > p && (f = !1, a += Y._addLine(o), o = "", r = 0), (o.length > 0 || !Y.isBreakingSpace(y) || f) && (o += y, r += x);
    }
    return a += Y._addLine(o, !1), a;
  }
  /**
   * Convenience function for logging each line added during the wordWrap method.
   * @param line    - The line of text to add
   * @param newLine - Add new line character to end
   * @returns A formatted line
   */
  static _addLine(t, e = !0) {
    return t = Y._trimRight(t), t = e ? `${t}
` : t, t;
  }
  /**
   * Gets & sets the widths of calculated characters in a cache object
   * @param key            - The key
   * @param letterSpacing  - The letter spacing
   * @param cache          - The cache
   * @param context        - The canvas context
   * @returns The from cache.
   */
  static _getFromCache(t, e, s, i) {
    let r = s[t];
    return typeof r != "number" && (r = Y._measureText(t, e, i) + e, s[t] = r), r;
  }
  /**
   * Determines whether we should collapse breaking spaces.
   * @param whiteSpace - The TextStyle property whiteSpace
   * @returns Should collapse
   */
  static _collapseSpaces(t) {
    return t === "normal" || t === "pre-line";
  }
  /**
   * Determines whether we should collapse newLine chars.
   * @param whiteSpace - The white space
   * @returns should collapse
   */
  static _collapseNewlines(t) {
    return t === "normal";
  }
  /**
   * Trims breaking whitespaces from string.
   * @param text - The text
   * @returns Trimmed string
   */
  static _trimRight(t) {
    if (typeof t != "string")
      return "";
    for (let e = t.length - 1; e >= 0; e--) {
      const s = t[e];
      if (!Y.isBreakingSpace(s))
        break;
      t = t.slice(0, -1);
    }
    return t;
  }
  /**
   * Determines if char is a newline.
   * @param char - The character
   * @returns True if newline, False otherwise.
   */
  static _isNewline(t) {
    return typeof t != "string" ? !1 : Y._newlines.includes(t.charCodeAt(0));
  }
  /**
   * Determines if char is a breaking whitespace.
   *
   * It allows one to determine whether char should be a breaking whitespace
   * For example certain characters in CJK langs or numbers.
   * It must return a boolean.
   * @param char - The character
   * @param [_nextChar] - The next character
   * @returns True if whitespace, False otherwise.
   */
  static isBreakingSpace(t, e) {
    return typeof t != "string" ? !1 : Y._breakingSpaces.includes(t.charCodeAt(0));
  }
  /**
   * Splits a string into words, breaking-spaces and newLine characters
   * @param text - The text
   * @returns A tokenized array
   */
  static _tokenize(t) {
    const e = [];
    let s = "";
    if (typeof t != "string")
      return e;
    for (let i = 0; i < t.length; i++) {
      const r = t[i], o = t[i + 1];
      if (Y.isBreakingSpace(r, o) || Y._isNewline(r)) {
        s !== "" && (e.push(s), s = ""), r === "\r" && o === `
` ? (e.push(`\r
`), i++) : e.push(r);
        continue;
      }
      s += r;
    }
    return s !== "" && e.push(s), e;
  }
  /**
   * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
   *
   * It allows one to customise which words should break
   * Examples are if the token is CJK or numbers.
   * It must return a boolean.
   * @param _token - The token
   * @param breakWords - The style attr break words
   * @returns Whether to break word or not
   */
  static canBreakWords(t, e) {
    return e;
  }
  /**
   * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
   *
   * It allows one to determine whether a pair of characters
   * should be broken by newlines
   * For example certain characters in CJK langs or numbers.
   * It must return a boolean.
   * @param _char - The character
   * @param _nextChar - The next character
   * @param _token - The token/word the characters are from
   * @param _index - The index in the token of the char
   * @param _breakWords - The style attr break words
   * @returns whether to break word or not
   */
  static canBreakChars(t, e, s, i, r) {
    return !0;
  }
  /**
   * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
   *
   * It is called when a token (usually a word) has to be split into separate pieces
   * in order to determine the point to break a word.
   * It must return an array of characters.
   * @param token - The token to split
   * @returns The characters of the token
   * @see CanvasTextMetrics.graphemeSegmenter
   */
  static wordWrapSplit(t) {
    return Y.graphemeSegmenter(t);
  }
  /**
   * Calculates the ascent, descent and fontSize of a given font-style
   * @param font - String representing the style of the font
   * @returns Font properties object
   */
  static measureFont(t) {
    if (Y._fonts[t])
      return Y._fonts[t];
    const e = Y._context;
    e.font = t;
    const s = e.measureText(Y.METRICS_STRING + Y.BASELINE_SYMBOL), i = {
      ascent: s.actualBoundingBoxAscent,
      descent: s.actualBoundingBoxDescent,
      fontSize: s.actualBoundingBoxAscent + s.actualBoundingBoxDescent
    };
    return Y._fonts[t] = i, i;
  }
  /**
   * Clear font metrics in metrics cache.
   * @param {string} [font] - font name. If font name not set then clear cache for all fonts.
   */
  static clearMetrics(t = "") {
    t ? delete Y._fonts[t] : Y._fonts = {};
  }
  /**
   * Cached canvas element for measuring text
   * TODO: this should be private, but isn't because of backward compat, will fix later.
   * @ignore
   */
  static get _canvas() {
    if (!Y.__canvas) {
      let t;
      try {
        const e = new OffscreenCanvas(0, 0);
        if (e.getContext("2d", Oa)?.measureText)
          return Y.__canvas = e, e;
        t = Ae.get().createCanvas();
      } catch {
        t = Ae.get().createCanvas();
      }
      t.width = t.height = 10, Y.__canvas = t;
    }
    return Y.__canvas;
  }
  /**
   * TODO: this should be private, but isn't because of backward compat, will fix later.
   * @ignore
   */
  static get _context() {
    return Y.__context || (Y.__context = Y._canvas.getContext("2d", Oa)), Y.__context;
  }
};
ms.METRICS_STRING = "|ÉqÅ";
ms.BASELINE_SYMBOL = "M";
ms.BASELINE_MULTIPLIER = 1.4;
ms.HEIGHT_MULTIPLIER = 2;
ms.graphemeSegmenter = (() => {
  if (typeof Intl?.Segmenter == "function") {
    const n = new Intl.Segmenter();
    return (t) => {
      const e = n.segment(t), s = [];
      let i = 0;
      for (const r of e)
        s[i++] = r.segment;
      return s;
    };
  }
  return (n) => [...n];
})();
ms.experimentalLetterSpacing = !1;
ms._fonts = {};
ms._newlines = [
  10,
  // line feed
  13
  // carriage return
];
ms._breakingSpaces = [
  9,
  // character tabulation
  32,
  // space
  8192,
  // en quad
  8193,
  // em quad
  8194,
  // en space
  8195,
  // em space
  8196,
  // three-per-em space
  8197,
  // four-per-em space
  8198,
  // six-per-em space
  8200,
  // punctuation space
  8201,
  // thin space
  8202,
  // hair space
  8287,
  // medium mathematical space
  12288
  // ideographic space
];
let Bn = ms;
const hu = [{ offset: 0, color: "white" }, { offset: 1, color: "black" }], Ql = class yl {
  constructor(...t) {
    this.uid = Ot("fillGradient"), this.type = "linear", this.colorStops = [];
    let e = q0(t);
    e = { ...e.type === "radial" ? yl.defaultRadialOptions : yl.defaultLinearOptions, ...If(e) }, this._textureSize = e.textureSize, this._wrapMode = e.wrapMode, e.type === "radial" ? (this.center = e.center, this.outerCenter = e.outerCenter ?? this.center, this.innerRadius = e.innerRadius, this.outerRadius = e.outerRadius, this.scale = e.scale, this.rotation = e.rotation) : (this.start = e.start, this.end = e.end), this.textureSpace = e.textureSpace, this.type = e.type, e.colorStops.forEach((i) => {
      this.addColorStop(i.offset, i.color);
    });
  }
  /**
   * Adds a color stop to the gradient
   * @param offset - Position of the stop (0-1)
   * @param color - Color of the stop
   * @returns This gradient instance for chaining
   */
  addColorStop(t, e) {
    return this.colorStops.push({ offset: t, color: Bt.shared.setValue(e).toHexa() }), this;
  }
  /**
   * Builds the internal texture and transform for the gradient.
   * Called automatically when the gradient is first used.
   * @internal
   */
  buildLinearGradient() {
    if (this.texture)
      return;
    let { x: t, y: e } = this.start, { x: s, y: i } = this.end, r = s - t, o = i - e;
    const a = r < 0 || o < 0;
    if (this._wrapMode === "clamp-to-edge") {
      if (r < 0) {
        const m = t;
        t = s, s = m, r *= -1;
      }
      if (o < 0) {
        const m = e;
        e = i, i = m, o *= -1;
      }
    }
    const l = this.colorStops.length ? this.colorStops : hu, c = this._textureSize, { canvas: h, context: u } = du(c, 1), d = a ? u.createLinearGradient(this._textureSize, 0, 0, 0) : u.createLinearGradient(0, 0, this._textureSize, 0);
    uu(d, l), u.fillStyle = d, u.fillRect(0, 0, c, 1), this.texture = new rt({
      source: new go({
        resource: h,
        addressMode: this._wrapMode
      })
    });
    const f = Math.sqrt(r * r + o * o), p = Math.atan2(o, r), g = new nt();
    g.scale(f / c, 1), g.rotate(p), g.translate(t, e), this.textureSpace === "local" && g.scale(c, c), this.transform = g;
  }
  /**
   * Builds the internal texture and transform for the gradient.
   * Called automatically when the gradient is first used.
   * @internal
   */
  buildGradient() {
    this.type === "linear" ? this.buildLinearGradient() : this.buildRadialGradient();
  }
  /**
   * Builds the internal texture and transform for the radial gradient.
   * Called automatically when the gradient is first used.
   * @internal
   */
  buildRadialGradient() {
    if (this.texture)
      return;
    const t = this.colorStops.length ? this.colorStops : hu, e = this._textureSize, { canvas: s, context: i } = du(e, e), { x: r, y: o } = this.center, { x: a, y: l } = this.outerCenter, c = this.innerRadius, h = this.outerRadius, u = a - h, d = l - h, f = e / (h * 2), p = (r - u) * f, g = (o - d) * f, m = i.createRadialGradient(
      p,
      g,
      c * f,
      (a - u) * f,
      (l - d) * f,
      h * f
    );
    uu(m, t), i.fillStyle = t[t.length - 1].color, i.fillRect(0, 0, e, e), i.fillStyle = m, i.translate(p, g), i.rotate(this.rotation), i.scale(1, this.scale), i.translate(-p, -g), i.fillRect(0, 0, e, e), this.texture = new rt({
      source: new go({
        resource: s,
        addressMode: this._wrapMode
      })
    });
    const y = new nt();
    y.scale(1 / f, 1 / f), y.translate(u, d), this.textureSpace === "local" && y.scale(e, e), this.transform = y;
  }
  /**
   * Gets a unique key representing the current state of the gradient.
   * Used internally for caching.
   * @returns Unique string key
   */
  get styleKey() {
    return this.uid;
  }
  /** Destroys the gradient, releasing resources. This will also destroy the internal texture. */
  destroy() {
    this.texture?.destroy(!0), this.texture = null, this.transform = null, this.colorStops = [], this.start = null, this.end = null, this.center = null, this.outerCenter = null;
  }
};
Ql.defaultLinearOptions = {
  start: { x: 0, y: 0 },
  end: { x: 0, y: 1 },
  colorStops: [],
  textureSpace: "local",
  type: "linear",
  textureSize: 256,
  wrapMode: "clamp-to-edge"
};
Ql.defaultRadialOptions = {
  center: { x: 0.5, y: 0.5 },
  innerRadius: 0,
  outerRadius: 0.5,
  colorStops: [],
  scale: 1,
  textureSpace: "local",
  type: "radial",
  textureSize: 256,
  wrapMode: "clamp-to-edge"
};
let Is = Ql;
function uu(n, t) {
  for (let e = 0; e < t.length; e++) {
    const s = t[e];
    n.addColorStop(s.offset, s.color);
  }
}
function du(n, t) {
  const e = Ae.get().createCanvas(n, t), s = e.getContext("2d");
  return { canvas: e, context: s };
}
function q0(n) {
  let t = n[0] ?? {};
  return (typeof t == "number" || n[1]) && (ct("8.5.2", "use options object instead"), t = {
    type: "linear",
    start: { x: n[0], y: n[1] },
    end: { x: n[2], y: n[3] },
    textureSpace: n[4],
    textureSize: n[5] ?? Is.defaultLinearOptions.textureSize
  }), t;
}
const fu = {
  repeat: {
    addressModeU: "repeat",
    addressModeV: "repeat"
  },
  "repeat-x": {
    addressModeU: "repeat",
    addressModeV: "clamp-to-edge"
  },
  "repeat-y": {
    addressModeU: "clamp-to-edge",
    addressModeV: "repeat"
  },
  "no-repeat": {
    addressModeU: "clamp-to-edge",
    addressModeV: "clamp-to-edge"
  }
};
class Zo {
  constructor(t, e) {
    this.uid = Ot("fillPattern"), this.transform = new nt(), this._styleKey = null, this.texture = t, this.transform.scale(
      1 / t.frame.width,
      1 / t.frame.height
    ), e && (t.source.style.addressModeU = fu[e].addressModeU, t.source.style.addressModeV = fu[e].addressModeV);
  }
  /**
   * Sets the transform for the pattern
   * @param transform - The transform matrix to apply to the pattern.
   * If not provided, the pattern will use the default transform.
   */
  setTransform(t) {
    const e = this.texture;
    this.transform.copyFrom(t), this.transform.invert(), this.transform.scale(
      1 / e.frame.width,
      1 / e.frame.height
    ), this._styleKey = null;
  }
  /**
   * Gets a unique key representing the current state of the pattern.
   * Used internally for caching.
   * @returns Unique string key
   */
  get styleKey() {
    return this._styleKey ? this._styleKey : (this._styleKey = `fill-pattern-${this.uid}-${this.texture.uid}-${this.transform.toArray().join("-")}`, this._styleKey);
  }
  /** Destroys the fill pattern, releasing resources. This will also destroy the internal texture. */
  destroy() {
    this.texture.destroy(!0), this.texture = null, this._styleKey = null;
  }
}
var Na, pu;
function U0() {
  if (pu) return Na;
  pu = 1, Na = e;
  var n = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 }, t = /([astvzqmhlc])([^astvzqmhlc]*)/ig;
  function e(r) {
    var o = [];
    return r.replace(t, function(a, l, c) {
      var h = l.toLowerCase();
      for (c = i(c), h == "m" && c.length > 2 && (o.push([l].concat(c.splice(0, 2))), h = "l", l = l == "m" ? "l" : "L"); ; ) {
        if (c.length == n[h])
          return c.unshift(l), o.push(c);
        if (c.length < n[h]) throw new Error("malformed path data");
        o.push([l].concat(c.splice(0, n[h])));
      }
    }), o;
  }
  var s = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig;
  function i(r) {
    var o = r.match(s);
    return o ? o.map(Number) : [];
  }
  return Na;
}
var G0 = U0();
const W0 = /* @__PURE__ */ Af(G0);
function $0(n, t) {
  const e = W0(n), s = [];
  let i = null, r = 0, o = 0;
  for (let a = 0; a < e.length; a++) {
    const l = e[a], c = l[0], h = l;
    switch (c) {
      case "M":
        r = h[1], o = h[2], t.moveTo(r, o);
        break;
      case "m":
        r += h[1], o += h[2], t.moveTo(r, o);
        break;
      case "H":
        r = h[1], t.lineTo(r, o);
        break;
      case "h":
        r += h[1], t.lineTo(r, o);
        break;
      case "V":
        o = h[1], t.lineTo(r, o);
        break;
      case "v":
        o += h[1], t.lineTo(r, o);
        break;
      case "L":
        r = h[1], o = h[2], t.lineTo(r, o);
        break;
      case "l":
        r += h[1], o += h[2], t.lineTo(r, o);
        break;
      case "C":
        r = h[5], o = h[6], t.bezierCurveTo(
          h[1],
          h[2],
          // First control point
          h[3],
          h[4],
          // Second control point
          r,
          o
          // End point
        );
        break;
      case "c":
        t.bezierCurveTo(
          r + h[1],
          o + h[2],
          // First control point
          r + h[3],
          o + h[4],
          // Second control point
          r + h[5],
          o + h[6]
          // End point
        ), r += h[5], o += h[6];
        break;
      case "S":
        r = h[3], o = h[4], t.bezierCurveToShort(
          h[1],
          h[2],
          // Control point
          r,
          o
          // End point
        );
        break;
      case "s":
        t.bezierCurveToShort(
          r + h[1],
          o + h[2],
          // Control point
          r + h[3],
          o + h[4]
          // End point
        ), r += h[3], o += h[4];
        break;
      case "Q":
        r = h[3], o = h[4], t.quadraticCurveTo(
          h[1],
          h[2],
          // Control point
          r,
          o
          // End point
        );
        break;
      case "q":
        t.quadraticCurveTo(
          r + h[1],
          o + h[2],
          // Control point
          r + h[3],
          o + h[4]
          // End point
        ), r += h[3], o += h[4];
        break;
      case "T":
        r = h[1], o = h[2], t.quadraticCurveToShort(
          r,
          o
          // End point
        );
        break;
      case "t":
        r += h[1], o += h[2], t.quadraticCurveToShort(
          r,
          o
          // End point
        );
        break;
      case "A":
        r = h[6], o = h[7], t.arcToSvg(
          h[1],
          // rx
          h[2],
          // ry
          h[3],
          // x-axis-rotation
          h[4],
          // large-arc-flag
          h[5],
          // sweep-flag
          r,
          o
          // End point
        );
        break;
      case "a":
        r += h[6], o += h[7], t.arcToSvg(
          h[1],
          // rx
          h[2],
          // ry
          h[3],
          // x-axis-rotation
          h[4],
          // large-arc-flag
          h[5],
          // sweep-flag
          r,
          o
          // End point
        );
        break;
      case "Z":
      case "z":
        t.closePath(), s.length > 0 && (i = s.pop(), i ? (r = i.startX, o = i.startY) : (r = 0, o = 0)), i = null;
        break;
      default:
        Ht(`Unknown SVG path command: ${c}`);
    }
    c !== "Z" && c !== "z" && i === null && (i = { startX: r, startY: o }, s.push(i));
  }
  return t;
}
class Jl {
  /**
   * @param x - The X coordinate of the center of this circle
   * @param y - The Y coordinate of the center of this circle
   * @param radius - The radius of the circle
   */
  constructor(t = 0, e = 0, s = 0) {
    this.type = "circle", this.x = t, this.y = e, this.radius = s;
  }
  /**
   * Creates a clone of this Circle instance.
   * @example
   * ```ts
   * // Basic circle cloning
   * const original = new Circle(100, 100, 50);
   * const copy = original.clone();
   *
   * // Clone and modify
   * const modified = original.clone();
   * modified.radius = 75;
   *
   * // Verify independence
   * console.log(original.radius); // 50
   * console.log(modified.radius); // 75
   * ```
   * @returns A copy of the Circle
   * @see {@link Circle.copyFrom} For copying into existing circle
   * @see {@link Circle.copyTo} For copying to another circle
   */
  clone() {
    return new Jl(this.x, this.y, this.radius);
  }
  /**
   * Checks whether the x and y coordinates given are contained within this circle.
   *
   * Uses the distance formula to determine if a point is inside the circle's radius.
   *
   * Commonly used for hit testing in PixiJS events and graphics.
   * @example
   * ```ts
   * // Basic containment check
   * const circle = new Circle(100, 100, 50);
   * const isInside = circle.contains(120, 120);
   *
   * // Check mouse position
   * const circle = new Circle(0, 0, 100);
   * container.hitArea = circle;
   * container.on('pointermove', (e) => {
   *     // only called if pointer is within circle
   * });
   * ```
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @returns Whether the x/y coordinates are within this Circle
   * @see {@link Circle.strokeContains} For checking stroke intersection
   * @see {@link Circle.getBounds} For getting bounding box
   */
  contains(t, e) {
    if (this.radius <= 0)
      return !1;
    const s = this.radius * this.radius;
    let i = this.x - t, r = this.y - e;
    return i *= i, r *= r, i + r <= s;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this circle including the stroke.
   * @example
   * ```ts
   * // Basic stroke check
   * const circle = new Circle(100, 100, 50);
   * const isOnStroke = circle.strokeContains(150, 100, 4); // 4px line width
   *
   * // Check with different alignments
   * const innerStroke = circle.strokeContains(150, 100, 4, 1);   // Inside
   * const centerStroke = circle.strokeContains(150, 100, 4, 0.5); // Centered
   * const outerStroke = circle.strokeContains(150, 100, 4, 0);   // Outside
   * ```
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @param width - The width of the line to check
   * @param alignment - The alignment of the stroke, 0.5 by default
   * @returns Whether the x/y coordinates are within this Circle's stroke
   * @see {@link Circle.contains} For checking fill containment
   * @see {@link Circle.getBounds} For getting stroke bounds
   */
  strokeContains(t, e, s, i = 0.5) {
    if (this.radius === 0)
      return !1;
    const r = this.x - t, o = this.y - e, a = this.radius, l = (1 - i) * s, c = Math.sqrt(r * r + o * o);
    return c <= a + l && c > a - (s - l);
  }
  /**
   * Returns the framing rectangle of the circle as a Rectangle object.
   * @example
   * ```ts
   * // Basic bounds calculation
   * const circle = new Circle(100, 100, 50);
   * const bounds = circle.getBounds();
   * // bounds: x=50, y=50, width=100, height=100
   *
   * // Reuse existing rectangle
   * const rect = new Rectangle();
   * circle.getBounds(rect);
   * ```
   * @param out - Optional Rectangle object to store the result
   * @returns The framing rectangle
   * @see {@link Rectangle} For rectangle properties
   * @see {@link Circle.contains} For point containment
   */
  getBounds(t) {
    return t || (t = new Dt()), t.x = this.x - this.radius, t.y = this.y - this.radius, t.width = this.radius * 2, t.height = this.radius * 2, t;
  }
  /**
   * Copies another circle to this one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Circle(100, 100, 50);
   * const target = new Circle();
   * target.copyFrom(source);
   * ```
   * @param circle - The circle to copy from
   * @returns Returns itself
   * @see {@link Circle.copyTo} For copying to another circle
   * @see {@link Circle.clone} For creating new circle copy
   */
  copyFrom(t) {
    return this.x = t.x, this.y = t.y, this.radius = t.radius, this;
  }
  /**
   * Copies this circle to another one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Circle(100, 100, 50);
   * const target = new Circle();
   * source.copyTo(target);
   * ```
   * @param circle - The circle to copy to
   * @returns Returns given parameter
   * @see {@link Circle.copyFrom} For copying from another circle
   * @see {@link Circle.clone} For creating new circle copy
   */
  copyTo(t) {
    return t.copyFrom(this), t;
  }
  toString() {
    return `[pixi.js/math:Circle x=${this.x} y=${this.y} radius=${this.radius}]`;
  }
}
class tc {
  /**
   * @param x - The X coordinate of the center of this ellipse
   * @param y - The Y coordinate of the center of this ellipse
   * @param halfWidth - The half width of this ellipse
   * @param halfHeight - The half height of this ellipse
   */
  constructor(t = 0, e = 0, s = 0, i = 0) {
    this.type = "ellipse", this.x = t, this.y = e, this.halfWidth = s, this.halfHeight = i;
  }
  /**
   * Creates a clone of this Ellipse instance.
   * @example
   * ```ts
   * // Basic cloning
   * const original = new Ellipse(100, 100, 50, 25);
   * const copy = original.clone();
   *
   * // Clone and modify
   * const modified = original.clone();
   * modified.halfWidth *= 2;
   * modified.halfHeight *= 2;
   *
   * // Verify independence
   * console.log(original.halfWidth);  // 50
   * console.log(modified.halfWidth);  // 100
   * ```
   * @returns A copy of the ellipse
   * @see {@link Ellipse.copyFrom} For copying into existing ellipse
   * @see {@link Ellipse.copyTo} For copying to another ellipse
   */
  clone() {
    return new tc(this.x, this.y, this.halfWidth, this.halfHeight);
  }
  /**
   * Checks whether the x and y coordinates given are contained within this ellipse.
   * Uses normalized coordinates and the ellipse equation to determine containment.
   * @example
   * ```ts
   * // Basic containment check
   * const ellipse = new Ellipse(100, 100, 50, 25);
   * const isInside = ellipse.contains(120, 110);
   * ```
   * @remarks
   * - Uses ellipse equation (x²/a² + y²/b² ≤ 1)
   * - Returns false if dimensions are 0 or negative
   * - Normalized to center (0,0) for calculation
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @returns Whether the x/y coords are within this ellipse
   * @see {@link Ellipse.strokeContains} For checking stroke intersection
   * @see {@link Ellipse.getBounds} For getting containing rectangle
   */
  contains(t, e) {
    if (this.halfWidth <= 0 || this.halfHeight <= 0)
      return !1;
    let s = (t - this.x) / this.halfWidth, i = (e - this.y) / this.halfHeight;
    return s *= s, i *= i, s + i <= 1;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this ellipse including stroke.
   * @example
   * ```ts
   * // Basic stroke check
   * const ellipse = new Ellipse(100, 100, 50, 25);
   * const isOnStroke = ellipse.strokeContains(150, 100, 4); // 4px line width
   *
   * // Check with different alignments
   * const innerStroke = ellipse.strokeContains(150, 100, 4, 1);   // Inside
   * const centerStroke = ellipse.strokeContains(150, 100, 4, 0.5); // Centered
   * const outerStroke = ellipse.strokeContains(150, 100, 4, 0);   // Outside
   * ```
   * @remarks
   * - Uses normalized ellipse equations
   * - Considers stroke alignment
   * - Returns false if dimensions are 0
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @param strokeWidth - The width of the line to check
   * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
   * @returns Whether the x/y coords are within this ellipse's stroke
   * @see {@link Ellipse.contains} For checking fill containment
   * @see {@link Ellipse.getBounds} For getting stroke bounds
   */
  strokeContains(t, e, s, i = 0.5) {
    const { halfWidth: r, halfHeight: o } = this;
    if (r <= 0 || o <= 0)
      return !1;
    const a = s * (1 - i), l = s - a, c = r - l, h = o - l, u = r + a, d = o + a, f = t - this.x, p = e - this.y, g = f * f / (c * c) + p * p / (h * h), m = f * f / (u * u) + p * p / (d * d);
    return g > 1 && m <= 1;
  }
  /**
   * Returns the framing rectangle of the ellipse as a Rectangle object.
   * @example
   * ```ts
   * // Basic bounds calculation
   * const ellipse = new Ellipse(100, 100, 50, 25);
   * const bounds = ellipse.getBounds();
   * // bounds: x=50, y=75, width=100, height=50
   *
   * // Reuse existing rectangle
   * const rect = new Rectangle();
   * ellipse.getBounds(rect);
   * ```
   * @remarks
   * - Creates Rectangle if none provided
   * - Top-left is (x-halfWidth, y-halfHeight)
   * - Width is halfWidth * 2
   * - Height is halfHeight * 2
   * @param out - Optional Rectangle object to store the result
   * @returns The framing rectangle
   * @see {@link Rectangle} For rectangle properties
   * @see {@link Ellipse.contains} For checking if a point is inside
   */
  getBounds(t) {
    return t || (t = new Dt()), t.x = this.x - this.halfWidth, t.y = this.y - this.halfHeight, t.width = this.halfWidth * 2, t.height = this.halfHeight * 2, t;
  }
  /**
   * Copies another ellipse to this one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Ellipse(100, 100, 50, 25);
   * const target = new Ellipse();
   * target.copyFrom(source);
   * ```
   * @param ellipse - The ellipse to copy from
   * @returns Returns itself
   * @see {@link Ellipse.copyTo} For copying to another ellipse
   * @see {@link Ellipse.clone} For creating new ellipse copy
   */
  copyFrom(t) {
    return this.x = t.x, this.y = t.y, this.halfWidth = t.halfWidth, this.halfHeight = t.halfHeight, this;
  }
  /**
   * Copies this ellipse to another one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Ellipse(100, 100, 50, 25);
   * const target = new Ellipse();
   * source.copyTo(target);
   * ```
   * @param ellipse - The ellipse to copy to
   * @returns Returns given parameter
   * @see {@link Ellipse.copyFrom} For copying from another ellipse
   * @see {@link Ellipse.clone} For creating new ellipse copy
   */
  copyTo(t) {
    return t.copyFrom(this), t;
  }
  toString() {
    return `[pixi.js/math:Ellipse x=${this.x} y=${this.y} halfWidth=${this.halfWidth} halfHeight=${this.halfHeight}]`;
  }
}
function H0(n, t, e, s, i, r) {
  const o = n - e, a = t - s, l = i - e, c = r - s, h = o * l + a * c, u = l * l + c * c;
  let d = -1;
  u !== 0 && (d = h / u);
  let f, p;
  d < 0 ? (f = e, p = s) : d > 1 ? (f = i, p = r) : (f = e + d * l, p = s + d * c);
  const g = n - f, m = t - p;
  return g * g + m * m;
}
let j0, X0;
class $i {
  /**
   * @param points - This can be an array of Points
   *  that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...], or
   *  the arguments passed can be all the points of the polygon e.g.
   *  `new Polygon(new Point(), new Point(), ...)`, or the arguments passed can be flat
   *  x,y values e.g. `new Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are Numbers.
   */
  constructor(...t) {
    this.type = "polygon";
    let e = Array.isArray(t[0]) ? t[0] : t;
    if (typeof e[0] != "number") {
      const s = [];
      for (let i = 0, r = e.length; i < r; i++)
        s.push(e[i].x, e[i].y);
      e = s;
    }
    this.points = e, this.closePath = !0;
  }
  /**
   * Determines whether the polygon's points are arranged in a clockwise direction.
   * Uses the shoelace formula (surveyor's formula) to calculate the signed area.
   *
   * A positive area indicates clockwise winding, while negative indicates counter-clockwise.
   *
   * The formula sums up the cross products of adjacent vertices:
   * For each pair of adjacent points (x1,y1) and (x2,y2), we calculate (x1*y2 - x2*y1)
   * The final sum divided by 2 gives the signed area - positive for clockwise.
   * @example
   * ```ts
   * // Check polygon winding
   * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
   * console.log(polygon.isClockwise()); // Check direction
   *
   * // Use in path construction
   * const hole = new Polygon([25, 25, 75, 25, 75, 75, 25, 75]);
   * if (hole.isClockwise() === shape.isClockwise()) {
   *     hole.points.reverse(); // Reverse for proper hole winding
   * }
   * ```
   * @returns `true` if the polygon's points are arranged clockwise, `false` if counter-clockwise
   */
  isClockwise() {
    let t = 0;
    const e = this.points, s = e.length;
    for (let i = 0; i < s; i += 2) {
      const r = e[i], o = e[i + 1], a = e[(i + 2) % s], l = e[(i + 3) % s];
      t += (a - r) * (l + o);
    }
    return t < 0;
  }
  /**
   * Checks if this polygon completely contains another polygon.
   * Used for detecting holes in shapes, like when parsing SVG paths.
   * @example
   * ```ts
   * // Basic containment check
   * const outerSquare = new Polygon([0,0, 100,0, 100,100, 0,100]); // A square
   * const innerSquare = new Polygon([25,25, 75,25, 75,75, 25,75]); // A smaller square inside
   *
   * outerSquare.containsPolygon(innerSquare); // Returns true
   * innerSquare.containsPolygon(outerSquare); // Returns false
   * ```
   * @remarks
   * - Uses bounds check for quick rejection
   * - Tests all points for containment
   * @param polygon - The polygon to test for containment
   * @returns True if this polygon completely contains the other polygon
   * @see {@link Polygon.contains} For single point testing
   * @see {@link Polygon.getBounds} For bounds calculation
   */
  containsPolygon(t) {
    const e = this.getBounds(j0), s = t.getBounds(X0);
    if (!e.containsRect(s))
      return !1;
    const i = t.points;
    for (let r = 0; r < i.length; r += 2) {
      const o = i[r], a = i[r + 1];
      if (!this.contains(o, a))
        return !1;
    }
    return !0;
  }
  /**
   * Creates a clone of this polygon.
   * @example
   * ```ts
   * // Basic cloning
   * const original = new Polygon([0, 0, 100, 0, 50, 100]);
   * const copy = original.clone();
   *
   * // Clone and modify
   * const modified = original.clone();
   * modified.points[0] = 10; // Modify first x coordinate
   * ```
   * @returns A copy of the polygon
   * @see {@link Polygon.copyFrom} For copying into existing polygon
   * @see {@link Polygon.copyTo} For copying to another polygon
   */
  clone() {
    const t = this.points.slice(), e = new $i(t);
    return e.closePath = this.closePath, e;
  }
  /**
   * Checks whether the x and y coordinates passed to this function are contained within this polygon.
   * Uses raycasting algorithm for point-in-polygon testing.
   * @example
   * ```ts
   * // Basic containment check
   * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
   * const isInside = polygon.contains(25, 25); // true
   * ```
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @returns Whether the x/y coordinates are within this polygon
   * @see {@link Polygon.strokeContains} For checking stroke intersection
   * @see {@link Polygon.containsPolygon} For polygon-in-polygon testing
   */
  contains(t, e) {
    let s = !1;
    const i = this.points.length / 2;
    for (let r = 0, o = i - 1; r < i; o = r++) {
      const a = this.points[r * 2], l = this.points[r * 2 + 1], c = this.points[o * 2], h = this.points[o * 2 + 1];
      l > e != h > e && t < (c - a) * ((e - l) / (h - l)) + a && (s = !s);
    }
    return s;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this polygon including the stroke.
   * @example
   * ```ts
   * // Basic stroke check
   * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
   * const isOnStroke = polygon.strokeContains(25, 25, 4); // 4px line width
   *
   * // Check with different alignments
   * const innerStroke = polygon.strokeContains(25, 25, 4, 1);   // Inside
   * const centerStroke = polygon.strokeContains(25, 25, 4, 0.5); // Centered
   * const outerStroke = polygon.strokeContains(25, 25, 4, 0);   // Outside
   * ```
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @param strokeWidth - The width of the line to check
   * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
   * @returns Whether the x/y coordinates are within this polygon's stroke
   * @see {@link Polygon.contains} For checking fill containment
   * @see {@link Polygon.getBounds} For getting stroke bounds
   */
  strokeContains(t, e, s, i = 0.5) {
    const r = s * s, o = r * (1 - i), a = r - o, { points: l } = this, c = l.length - (this.closePath ? 0 : 2);
    for (let h = 0; h < c; h += 2) {
      const u = l[h], d = l[h + 1], f = l[(h + 2) % l.length], p = l[(h + 3) % l.length], g = H0(t, e, u, d, f, p), m = Math.sign((f - u) * (e - d) - (p - d) * (t - u));
      if (g <= (m < 0 ? a : o))
        return !0;
    }
    return !1;
  }
  /**
   * Returns the framing rectangle of the polygon as a Rectangle object.
   * @example
   * ```ts
   * // Basic bounds calculation
   * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
   * const bounds = polygon.getBounds();
   * // bounds: x=0, y=0, width=100, height=100
   *
   * // Reuse existing rectangle
   * const rect = new Rectangle();
   * polygon.getBounds(rect);
   * ```
   * @param out - Optional rectangle to store the result
   * @returns The framing rectangle
   * @see {@link Rectangle} For rectangle properties
   * @see {@link Polygon.contains} For checking if a point is inside
   */
  getBounds(t) {
    t || (t = new Dt());
    const e = this.points;
    let s = 1 / 0, i = -1 / 0, r = 1 / 0, o = -1 / 0;
    for (let a = 0, l = e.length; a < l; a += 2) {
      const c = e[a], h = e[a + 1];
      s = c < s ? c : s, i = c > i ? c : i, r = h < r ? h : r, o = h > o ? h : o;
    }
    return t.x = s, t.width = i - s, t.y = r, t.height = o - r, t;
  }
  /**
   * Copies another polygon to this one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Polygon([0, 0, 100, 0, 50, 100]);
   * const target = new Polygon();
   * target.copyFrom(source);
   * ```
   * @param polygon - The polygon to copy from
   * @returns Returns itself
   * @see {@link Polygon.copyTo} For copying to another polygon
   * @see {@link Polygon.clone} For creating new polygon copy
   */
  copyFrom(t) {
    return this.points = t.points.slice(), this.closePath = t.closePath, this;
  }
  /**
   * Copies this polygon to another one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new Polygon([0, 0, 100, 0, 50, 100]);
   * const target = new Polygon();
   * source.copyTo(target);
   * ```
   * @param polygon - The polygon to copy to
   * @returns Returns given parameter
   * @see {@link Polygon.copyFrom} For copying from another polygon
   * @see {@link Polygon.clone} For creating new polygon copy
   */
  copyTo(t) {
    return t.copyFrom(this), t;
  }
  toString() {
    return `[pixi.js/math:PolygoncloseStroke=${this.closePath}points=${this.points.reduce((t, e) => `${t}, ${e}`, "")}]`;
  }
  /**
   * Get the last X coordinate of the polygon.
   * @example
   * ```ts
   * // Basic coordinate access
   * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
   * console.log(polygon.lastX); // 300
   * ```
   * @readonly
   * @returns The x-coordinate of the last vertex
   * @see {@link Polygon.lastY} For last Y coordinate
   * @see {@link Polygon.points} For raw points array
   */
  get lastX() {
    return this.points[this.points.length - 2];
  }
  /**
   * Get the last Y coordinate of the polygon.
   * @example
   * ```ts
   * // Basic coordinate access
   * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
   * console.log(polygon.lastY); // 400
   * ```
   * @readonly
   * @returns The y-coordinate of the last vertex
   * @see {@link Polygon.lastX} For last X coordinate
   * @see {@link Polygon.points} For raw points array
   */
  get lastY() {
    return this.points[this.points.length - 1];
  }
  /**
   * Get the last X coordinate of the polygon.
   * @readonly
   * @deprecated since 8.11.0, use {@link Polygon.lastX} instead.
   */
  get x() {
    return ct("8.11.0", "Polygon.lastX is deprecated, please use Polygon.lastX instead."), this.points[this.points.length - 2];
  }
  /**
   * Get the last Y coordinate of the polygon.
   * @readonly
   * @deprecated since 8.11.0, use {@link Polygon.lastY} instead.
   */
  get y() {
    return ct("8.11.0", "Polygon.y is deprecated, please use Polygon.lastY instead."), this.points[this.points.length - 1];
  }
  /**
   * Get the first X coordinate of the polygon.
   * @example
   * ```ts
   * // Basic coordinate access
   * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
   * console.log(polygon.x); // 0
   * ```
   * @readonly
   * @returns The x-coordinate of the first vertex
   * @see {@link Polygon.startY} For first Y coordinate
   * @see {@link Polygon.points} For raw points array
   */
  get startX() {
    return this.points[0];
  }
  /**
   * Get the first Y coordinate of the polygon.
   * @example
   * ```ts
   * // Basic coordinate access
   * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
   * console.log(polygon.y); // 0
   * ```
   * @readonly
   * @returns The y-coordinate of the first vertex
   * @see {@link Polygon.startX} For first X coordinate
   * @see {@link Polygon.points} For raw points array
   */
  get startY() {
    return this.points[1];
  }
}
const Yr = (n, t, e, s, i, r, o) => {
  const a = n - e, l = t - s, c = Math.sqrt(a * a + l * l);
  return c >= i - r && c <= i + o;
};
class ec {
  /**
   * @param x - The X coordinate of the upper-left corner of the rounded rectangle
   * @param y - The Y coordinate of the upper-left corner of the rounded rectangle
   * @param width - The overall width of this rounded rectangle
   * @param height - The overall height of this rounded rectangle
   * @param radius - Controls the radius of the rounded corners
   */
  constructor(t = 0, e = 0, s = 0, i = 0, r = 20) {
    this.type = "roundedRectangle", this.x = t, this.y = e, this.width = s, this.height = i, this.radius = r;
  }
  /**
   * Returns the framing rectangle of the rounded rectangle as a Rectangle object
   * @example
   * ```ts
   * // Basic bounds calculation
   * const rect = new RoundedRectangle(100, 100, 200, 150, 20);
   * const bounds = rect.getBounds();
   * // bounds: x=100, y=100, width=200, height=150
   *
   * // Reuse existing rectangle
   * const out = new Rectangle();
   * rect.getBounds(out);
   * ```
   * @remarks
   * - Rectangle matches outer dimensions
   * - Ignores corner radius
   * @param out - Optional rectangle to store the result
   * @returns The framing rectangle
   * @see {@link Rectangle} For rectangle properties
   * @see {@link RoundedRectangle.contains} For checking if a point is inside
   */
  getBounds(t) {
    return t || (t = new Dt()), t.x = this.x, t.y = this.y, t.width = this.width, t.height = this.height, t;
  }
  /**
   * Creates a clone of this Rounded Rectangle.
   * @example
   * ```ts
   * // Basic cloning
   * const original = new RoundedRectangle(100, 100, 200, 150, 20);
   * const copy = original.clone();
   *
   * // Clone and modify
   * const modified = original.clone();
   * modified.radius = 30;
   * modified.width *= 2;
   *
   * // Verify independence
   * console.log(original.radius);  // 20
   * console.log(modified.radius);  // 30
   * ```
   * @returns A copy of the rounded rectangle
   * @see {@link RoundedRectangle.copyFrom} For copying into existing rectangle
   * @see {@link RoundedRectangle.copyTo} For copying to another rectangle
   */
  clone() {
    return new ec(this.x, this.y, this.width, this.height, this.radius);
  }
  /**
   * Copies another rectangle to this one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new RoundedRectangle(100, 100, 200, 150, 20);
   * const target = new RoundedRectangle();
   * target.copyFrom(source);
   *
   * // Chain with other operations
   * const rect = new RoundedRectangle()
   *     .copyFrom(source)
   *     .getBounds(rect);
   * ```
   * @param rectangle - The rectangle to copy from
   * @returns Returns itself
   * @see {@link RoundedRectangle.copyTo} For copying to another rectangle
   * @see {@link RoundedRectangle.clone} For creating new rectangle copy
   */
  copyFrom(t) {
    return this.x = t.x, this.y = t.y, this.width = t.width, this.height = t.height, this;
  }
  /**
   * Copies this rectangle to another one.
   * @example
   * ```ts
   * // Basic copying
   * const source = new RoundedRectangle(100, 100, 200, 150, 20);
   * const target = new RoundedRectangle();
   * source.copyTo(target);
   *
   * // Chain with other operations
   * const result = source
   *     .copyTo(new RoundedRectangle())
   *     .getBounds();
   * ```
   * @param rectangle - The rectangle to copy to
   * @returns Returns given parameter
   * @see {@link RoundedRectangle.copyFrom} For copying from another rectangle
   * @see {@link RoundedRectangle.clone} For creating new rectangle copy
   */
  copyTo(t) {
    return t.copyFrom(this), t;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this Rounded Rectangle
   * @example
   * ```ts
   * // Basic containment check
   * const rect = new RoundedRectangle(100, 100, 200, 150, 20);
   * const isInside = rect.contains(150, 125); // true
   * // Check corner radius
   * const corner = rect.contains(100, 100); // false if within corner curve
   * ```
   * @remarks
   * - Returns false if width/height is 0 or negative
   * - Handles rounded corners with radius check
   * @param x - The X coordinate of the point to test
   * @param y - The Y coordinate of the point to test
   * @returns Whether the x/y coordinates are within this Rounded Rectangle
   * @see {@link RoundedRectangle.strokeContains} For checking stroke intersection
   * @see {@link RoundedRectangle.getBounds} For getting containing rectangle
   */
  contains(t, e) {
    if (this.width <= 0 || this.height <= 0)
      return !1;
    if (t >= this.x && t <= this.x + this.width && e >= this.y && e <= this.y + this.height) {
      const s = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2));
      if (e >= this.y + s && e <= this.y + this.height - s || t >= this.x + s && t <= this.x + this.width - s)
        return !0;
      let i = t - (this.x + s), r = e - (this.y + s);
      const o = s * s;
      if (i * i + r * r <= o || (i = t - (this.x + this.width - s), i * i + r * r <= o) || (r = e - (this.y + this.height - s), i * i + r * r <= o) || (i = t - (this.x + s), i * i + r * r <= o))
        return !0;
    }
    return !1;
  }
  /**
   * Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
   * @example
   * ```ts
   * // Basic stroke check
   * const rect = new RoundedRectangle(100, 100, 200, 150, 20);
   * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width
   *
   * // Check with different alignments
   * const innerStroke = rect.strokeContains(150, 100, 4, 1);   // Inside
   * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered
   * const outerStroke = rect.strokeContains(150, 100, 4, 0);   // Outside
   * ```
   * @param pX - The X coordinate of the point to test
   * @param pY - The Y coordinate of the point to test
   * @param strokeWidth - The width of the line to check
   * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
   * @returns Whether the x/y coordinates are within this rectangle's stroke
   * @see {@link RoundedRectangle.contains} For checking fill containment
   * @see {@link RoundedRectangle.getBounds} For getting stroke bounds
   */
  strokeContains(t, e, s, i = 0.5) {
    const { x: r, y: o, width: a, height: l, radius: c } = this, h = s * (1 - i), u = s - h, d = r + c, f = o + c, p = a - c * 2, g = l - c * 2, m = r + a, y = o + l;
    return (t >= r - h && t <= r + u || t >= m - u && t <= m + h) && e >= f && e <= f + g || (e >= o - h && e <= o + u || e >= y - u && e <= y + h) && t >= d && t <= d + p ? !0 : (
      // Top-left
      t < d && e < f && Yr(
        t,
        e,
        d,
        f,
        c,
        u,
        h
      ) || t > m - c && e < f && Yr(
        t,
        e,
        m - c,
        f,
        c,
        u,
        h
      ) || t > m - c && e > y - c && Yr(
        t,
        e,
        m - c,
        y - c,
        c,
        u,
        h
      ) || t < d && e > y - c && Yr(
        t,
        e,
        d,
        y - c,
        c,
        u,
        h
      )
    );
  }
  toString() {
    return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}width=${this.width} height=${this.height} radius=${this.radius}]`;
  }
}
const Cp = {};
function Y0(n, t, e) {
  let s = 2166136261;
  for (let i = 0; i < t; i++)
    s ^= n[i].uid, s = Math.imul(s, 16777619), s >>>= 0;
  return Cp[s] || Z0(n, t, s, e);
}
function Z0(n, t, e, s) {
  const i = {};
  let r = 0;
  for (let a = 0; a < s; a++) {
    const l = a < t ? n[a] : rt.EMPTY.source;
    i[r++] = l.source, i[r++] = l.style;
  }
  const o = new ao(i);
  return Cp[e] = o, o;
}
class mu {
  constructor(t) {
    typeof t == "number" ? this.rawBinaryData = new ArrayBuffer(t) : t instanceof Uint8Array ? this.rawBinaryData = t.buffer : this.rawBinaryData = t, this.uint32View = new Uint32Array(this.rawBinaryData), this.float32View = new Float32Array(this.rawBinaryData), this.size = this.rawBinaryData.byteLength;
  }
  /** View on the raw binary data as a `Int8Array`. */
  get int8View() {
    return this._int8View || (this._int8View = new Int8Array(this.rawBinaryData)), this._int8View;
  }
  /** View on the raw binary data as a `Uint8Array`. */
  get uint8View() {
    return this._uint8View || (this._uint8View = new Uint8Array(this.rawBinaryData)), this._uint8View;
  }
  /**  View on the raw binary data as a `Int16Array`. */
  get int16View() {
    return this._int16View || (this._int16View = new Int16Array(this.rawBinaryData)), this._int16View;
  }
  /** View on the raw binary data as a `Int32Array`. */
  get int32View() {
    return this._int32View || (this._int32View = new Int32Array(this.rawBinaryData)), this._int32View;
  }
  /** View on the raw binary data as a `Float64Array`. */
  get float64View() {
    return this._float64Array || (this._float64Array = new Float64Array(this.rawBinaryData)), this._float64Array;
  }
  /** View on the raw binary data as a `BigUint64Array`. */
  get bigUint64View() {
    return this._bigUint64Array || (this._bigUint64Array = new BigUint64Array(this.rawBinaryData)), this._bigUint64Array;
  }
  /**
   * Returns the view of the given type.
   * @param type - One of `int8`, `uint8`, `int16`,
   *    `uint16`, `int32`, `uint32`, and `float32`.
   * @returns - typed array of given type
   */
  view(t) {
    return this[`${t}View`];
  }
  /** Destroys all buffer references. Do not use after calling this. */
  destroy() {
    this.rawBinaryData = null, this._int8View = null, this._uint8View = null, this._int16View = null, this.uint16View = null, this._int32View = null, this.uint32View = null, this.float32View = null;
  }
  /**
   * Returns the size of the given type in bytes.
   * @param type - One of `int8`, `uint8`, `int16`,
   *   `uint16`, `int32`, `uint32`, and `float32`.
   * @returns - size of the type in bytes
   */
  static sizeOf(t) {
    switch (t) {
      case "int8":
      case "uint8":
        return 1;
      case "int16":
      case "uint16":
        return 2;
      case "int32":
      case "uint32":
      case "float32":
        return 4;
      default:
        throw new Error(`${t} isn't a valid view type`);
    }
  }
}
function gu(n, t) {
  const e = n.byteLength / 8 | 0, s = new Float64Array(n, 0, e);
  new Float64Array(t, 0, e).set(s);
  const r = n.byteLength - e * 8;
  if (r > 0) {
    const o = new Uint8Array(n, e * 8, r);
    new Uint8Array(t, e * 8, r).set(o);
  }
}
const K0 = {
  normal: "normal-npm",
  add: "add-npm",
  screen: "screen-npm"
};
var Q0 = /* @__PURE__ */ ((n) => (n[n.DISABLED = 0] = "DISABLED", n[n.RENDERING_MASK_ADD = 1] = "RENDERING_MASK_ADD", n[n.MASK_ACTIVE = 2] = "MASK_ACTIVE", n[n.INVERSE_MASK_ACTIVE = 3] = "INVERSE_MASK_ACTIVE", n[n.RENDERING_MASK_REMOVE = 4] = "RENDERING_MASK_REMOVE", n[n.NONE = 5] = "NONE", n))(Q0 || {});
function yu(n, t) {
  return t.alphaMode === "no-premultiply-alpha" && K0[n] || n;
}
const J0 = [
  "precision mediump float;",
  "void main(void){",
  "float test = 0.1;",
  "%forloop%",
  "gl_FragColor = vec4(0.0);",
  "}"
].join(`
`);
function tx(n) {
  let t = "";
  for (let e = 0; e < n; ++e)
    e > 0 && (t += `
else `), e < n - 1 && (t += `if(test == ${e}.0){}`);
  return t;
}
function ex(n, t) {
  if (n === 0)
    throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`");
  const e = t.createShader(t.FRAGMENT_SHADER);
  try {
    for (; ; ) {
      const s = J0.replace(/%forloop%/gi, tx(n));
      if (t.shaderSource(e, s), t.compileShader(e), !t.getShaderParameter(e, t.COMPILE_STATUS))
        n = n / 2 | 0;
      else
        break;
    }
  } finally {
    t.deleteShader(e);
  }
  return n;
}
let Nn = null;
function sx() {
  if (Nn)
    return Nn;
  const n = ap();
  return Nn = n.getParameter(n.MAX_TEXTURE_IMAGE_UNITS), Nn = ex(
    Nn,
    n
  ), n.getExtension("WEBGL_lose_context")?.loseContext(), Nn;
}
class nx {
  constructor() {
    this.ids = /* @__PURE__ */ Object.create(null), this.textures = [], this.count = 0;
  }
  /** Clear the textures and their locations. */
  clear() {
    for (let t = 0; t < this.count; t++) {
      const e = this.textures[t];
      this.textures[t] = null, this.ids[e.uid] = null;
    }
    this.count = 0;
  }
}
class ix {
  constructor() {
    this.renderPipeId = "batch", this.action = "startBatch", this.start = 0, this.size = 0, this.textures = new nx(), this.blendMode = "normal", this.topology = "triangle-strip", this.canBundle = !0;
  }
  destroy() {
    this.textures = null, this.gpuBindGroup = null, this.bindGroup = null, this.batcher = null;
  }
}
const Ap = [];
let xl = 0;
function xu() {
  return xl > 0 ? Ap[--xl] : new ix();
}
function _u(n) {
  Ap[xl++] = n;
}
let Pi = 0;
const Ep = class Pp {
  constructor(t) {
    this.uid = Ot("batcher"), this.dirty = !0, this.batchIndex = 0, this.batches = [], this._elements = [], t = { ...Pp.defaultOptions, ...t }, t.maxTextures || (ct("v8.8.0", "maxTextures is a required option for Batcher now, please pass it in the options"), t.maxTextures = sx());
    const { maxTextures: e, attributesInitialSize: s, indicesInitialSize: i } = t;
    this.attributeBuffer = new mu(s * 4), this.indexBuffer = new Uint16Array(i), this.maxTextures = e;
  }
  begin() {
    this.elementSize = 0, this.elementStart = 0, this.indexSize = 0, this.attributeSize = 0;
    for (let t = 0; t < this.batchIndex; t++)
      _u(this.batches[t]);
    this.batchIndex = 0, this._batchIndexStart = 0, this._batchIndexSize = 0, this.dirty = !0;
  }
  add(t) {
    this._elements[this.elementSize++] = t, t._indexStart = this.indexSize, t._attributeStart = this.attributeSize, t._batcher = this, this.indexSize += t.indexSize, this.attributeSize += t.attributeSize * this.vertexSize;
  }
  checkAndUpdateTexture(t, e) {
    const s = t._batch.textures.ids[e._source.uid];
    return !s && s !== 0 ? !1 : (t._textureId = s, t.texture = e, !0);
  }
  updateElement(t) {
    this.dirty = !0;
    const e = this.attributeBuffer;
    t.packAsQuad ? this.packQuadAttributes(
      t,
      e.float32View,
      e.uint32View,
      t._attributeStart,
      t._textureId
    ) : this.packAttributes(
      t,
      e.float32View,
      e.uint32View,
      t._attributeStart,
      t._textureId
    );
  }
  /**
   * breaks the batcher. This happens when a batch gets too big,
   * or we need to switch to a different type of rendering (a filter for example)
   * @param instructionSet
   */
  break(t) {
    const e = this._elements;
    if (!e[this.elementStart])
      return;
    let s = xu(), i = s.textures;
    i.clear();
    const r = e[this.elementStart];
    let o = yu(r.blendMode, r.texture._source), a = r.topology;
    this.attributeSize * 4 > this.attributeBuffer.size && this._resizeAttributeBuffer(this.attributeSize * 4), this.indexSize > this.indexBuffer.length && this._resizeIndexBuffer(this.indexSize);
    const l = this.attributeBuffer.float32View, c = this.attributeBuffer.uint32View, h = this.indexBuffer;
    let u = this._batchIndexSize, d = this._batchIndexStart, f = "startBatch";
    const p = this.maxTextures;
    for (let g = this.elementStart; g < this.elementSize; ++g) {
      const m = e[g];
      e[g] = null;
      const x = m.texture._source, v = yu(m.blendMode, x), _ = o !== v || a !== m.topology;
      if (x._batchTick === Pi && !_) {
        m._textureId = x._textureBindLocation, u += m.indexSize, m.packAsQuad ? (this.packQuadAttributes(
          m,
          l,
          c,
          m._attributeStart,
          m._textureId
        ), this.packQuadIndex(
          h,
          m._indexStart,
          m._attributeStart / this.vertexSize
        )) : (this.packAttributes(
          m,
          l,
          c,
          m._attributeStart,
          m._textureId
        ), this.packIndex(
          m,
          h,
          m._indexStart,
          m._attributeStart / this.vertexSize
        )), m._batch = s;
        continue;
      }
      x._batchTick = Pi, (i.count >= p || _) && (this._finishBatch(
        s,
        d,
        u - d,
        i,
        o,
        a,
        t,
        f
      ), f = "renderBatch", d = u, o = v, a = m.topology, s = xu(), i = s.textures, i.clear(), ++Pi), m._textureId = x._textureBindLocation = i.count, i.ids[x.uid] = i.count, i.textures[i.count++] = x, m._batch = s, u += m.indexSize, m.packAsQuad ? (this.packQuadAttributes(
        m,
        l,
        c,
        m._attributeStart,
        m._textureId
      ), this.packQuadIndex(
        h,
        m._indexStart,
        m._attributeStart / this.vertexSize
      )) : (this.packAttributes(
        m,
        l,
        c,
        m._attributeStart,
        m._textureId
      ), this.packIndex(
        m,
        h,
        m._indexStart,
        m._attributeStart / this.vertexSize
      ));
    }
    i.count > 0 && (this._finishBatch(
      s,
      d,
      u - d,
      i,
      o,
      a,
      t,
      f
    ), d = u, ++Pi), this.elementStart = this.elementSize, this._batchIndexStart = d, this._batchIndexSize = u;
  }
  _finishBatch(t, e, s, i, r, o, a, l) {
    t.gpuBindGroup = null, t.bindGroup = null, t.action = l, t.batcher = this, t.textures = i, t.blendMode = r, t.topology = o, t.start = e, t.size = s, ++Pi, this.batches[this.batchIndex++] = t, a.add(t);
  }
  finish(t) {
    this.break(t);
  }
  /**
   * Resizes the attribute buffer to the given size (1 = 1 float32)
   * @param size - the size in vertices to ensure (not bytes!)
   */
  ensureAttributeBuffer(t) {
    t * 4 <= this.attributeBuffer.size || this._resizeAttributeBuffer(t * 4);
  }
  /**
   * Resizes the index buffer to the given size (1 = 1 float32)
   * @param size - the size in vertices to ensure (not bytes!)
   */
  ensureIndexBuffer(t) {
    t <= this.indexBuffer.length || this._resizeIndexBuffer(t);
  }
  _resizeAttributeBuffer(t) {
    const e = Math.max(t, this.attributeBuffer.size * 2), s = new mu(e);
    gu(this.attributeBuffer.rawBinaryData, s.rawBinaryData), this.attributeBuffer = s;
  }
  _resizeIndexBuffer(t) {
    const e = this.indexBuffer;
    let s = Math.max(t, e.length * 1.5);
    s += s % 2;
    const i = s > 65535 ? new Uint32Array(s) : new Uint16Array(s);
    if (i.BYTES_PER_ELEMENT !== e.BYTES_PER_ELEMENT)
      for (let r = 0; r < e.length; r++)
        i[r] = e[r];
    else
      gu(e.buffer, i.buffer);
    this.indexBuffer = i;
  }
  packQuadIndex(t, e, s) {
    t[e] = s + 0, t[e + 1] = s + 1, t[e + 2] = s + 2, t[e + 3] = s + 0, t[e + 4] = s + 2, t[e + 5] = s + 3;
  }
  packIndex(t, e, s, i) {
    const r = t.indices, o = t.indexSize, a = t.indexOffset, l = t.attributeOffset;
    for (let c = 0; c < o; c++)
      e[s++] = i + r[c + a] - l;
  }
  destroy() {
    for (let t = 0; t < this.batches.length; t++)
      _u(this.batches[t]);
    this.batches = null;
    for (let t = 0; t < this._elements.length; t++)
      this._elements[t]._batch = null;
    this._elements = null, this.indexBuffer = null, this.attributeBuffer.destroy(), this.attributeBuffer = null;
  }
};
Ep.defaultOptions = {
  maxTextures: null,
  attributesInitialSize: 4,
  indicesInitialSize: 6
};
let rx = Ep;
var ge = /* @__PURE__ */ ((n) => (n[n.MAP_READ = 1] = "MAP_READ", n[n.MAP_WRITE = 2] = "MAP_WRITE", n[n.COPY_SRC = 4] = "COPY_SRC", n[n.COPY_DST = 8] = "COPY_DST", n[n.INDEX = 16] = "INDEX", n[n.VERTEX = 32] = "VERTEX", n[n.UNIFORM = 64] = "UNIFORM", n[n.STORAGE = 128] = "STORAGE", n[n.INDIRECT = 256] = "INDIRECT", n[n.QUERY_RESOLVE = 512] = "QUERY_RESOLVE", n[n.STATIC = 1024] = "STATIC", n))(ge || {});
let Ji = class extends ps {
  /**
   * Creates a new Buffer with the given options
   * @param options - the options for the buffer
   */
  constructor(t) {
    let { data: e, size: s } = t;
    const { usage: i, label: r, shrinkToFit: o } = t;
    super(), this.uid = Ot("buffer"), this._resourceType = "buffer", this._resourceId = Ot("resource"), this._touched = 0, this._updateID = 1, this._dataInt32 = null, this.shrinkToFit = !0, this.destroyed = !1, e instanceof Array && (e = new Float32Array(e)), this._data = e, s ?? (s = e?.byteLength);
    const a = !!e;
    this.descriptor = {
      size: s,
      usage: i,
      mappedAtCreation: a,
      label: r
    }, this.shrinkToFit = o ?? !0;
  }
  /** the data in the buffer */
  get data() {
    return this._data;
  }
  set data(t) {
    this.setDataWithSize(t, t.length, !0);
  }
  get dataInt32() {
    return this._dataInt32 || (this._dataInt32 = new Int32Array(this.data.buffer)), this._dataInt32;
  }
  /** whether the buffer is static or not */
  get static() {
    return !!(this.descriptor.usage & ge.STATIC);
  }
  set static(t) {
    t ? this.descriptor.usage |= ge.STATIC : this.descriptor.usage &= ~ge.STATIC;
  }
  /**
   * Sets the data in the buffer to the given value. This will immediately update the buffer on the GPU.
   * If you only want to update a subset of the buffer, you can pass in the size of the data.
   * @param value - the data to set
   * @param size - the size of the data in bytes
   * @param syncGPU - should the buffer be updated on the GPU immediately?
   */
  setDataWithSize(t, e, s) {
    if (this._updateID++, this._updateSize = e * t.BYTES_PER_ELEMENT, this._data === t) {
      s && this.emit("update", this);
      return;
    }
    const i = this._data;
    if (this._data = t, this._dataInt32 = null, !i || i.length !== t.length) {
      !this.shrinkToFit && i && t.byteLength < i.byteLength ? s && this.emit("update", this) : (this.descriptor.size = t.byteLength, this._resourceId = Ot("resource"), this.emit("change", this));
      return;
    }
    s && this.emit("update", this);
  }
  /**
   * updates the buffer on the GPU to reflect the data in the buffer.
   * By default it will update the entire buffer. If you only want to update a subset of the buffer,
   * you can pass in the size of the buffer to update.
   * @param sizeInBytes - the new size of the buffer in bytes
   */
  update(t) {
    this._updateSize = t ?? this._updateSize, this._updateID++, this.emit("update", this);
  }
  /** Destroys the buffer */
  destroy() {
    this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this._data = null, this.descriptor = null, this.removeAllListeners();
  }
};
function Ip(n, t) {
  if (!(n instanceof Ji)) {
    let e = t ? ge.INDEX : ge.VERTEX;
    n instanceof Array && (t ? (n = new Uint32Array(n), e = ge.INDEX | ge.COPY_DST) : (n = new Float32Array(n), e = ge.VERTEX | ge.COPY_DST)), n = new Ji({
      data: n,
      label: t ? "index-mesh-buffer" : "vertex-mesh-buffer",
      usage: e
    });
  }
  return n;
}
function ox(n, t, e) {
  const s = n.getAttribute(t);
  if (!s)
    return e.minX = 0, e.minY = 0, e.maxX = 0, e.maxY = 0, e;
  const i = s.buffer.data;
  let r = 1 / 0, o = 1 / 0, a = -1 / 0, l = -1 / 0;
  const c = i.BYTES_PER_ELEMENT, h = (s.offset || 0) / c, u = (s.stride || 8) / c;
  for (let d = h; d < i.length; d += u) {
    const f = i[d], p = i[d + 1];
    f > a && (a = f), p > l && (l = p), f < r && (r = f), p < o && (o = p);
  }
  return e.minX = r, e.minY = o, e.maxX = a, e.maxY = l, e;
}
function ax(n) {
  return (n instanceof Ji || Array.isArray(n) || n.BYTES_PER_ELEMENT) && (n = {
    buffer: n
  }), n.buffer = Ip(n.buffer, !1), n;
}
class lx extends ps {
  /**
   * Create a new instance of a geometry
   * @param options - The options for the geometry.
   */
  constructor(t = {}) {
    super(), this.uid = Ot("geometry"), this._layoutKey = 0, this.instanceCount = 1, this._bounds = new Ye(), this._boundsDirty = !0;
    const { attributes: e, indexBuffer: s, topology: i } = t;
    if (this.buffers = [], this.attributes = {}, e)
      for (const r in e)
        this.addAttribute(r, e[r]);
    this.instanceCount = t.instanceCount ?? 1, s && this.addIndex(s), this.topology = i || "triangle-list";
  }
  onBufferUpdate() {
    this._boundsDirty = !0, this.emit("update", this);
  }
  /**
   * Returns the requested attribute.
   * @param id - The name of the attribute required
   * @returns - The attribute requested.
   */
  getAttribute(t) {
    return this.attributes[t];
  }
  /**
   * Returns the index buffer
   * @returns - The index buffer.
   */
  getIndex() {
    return this.indexBuffer;
  }
  /**
   * Returns the requested buffer.
   * @param id - The name of the buffer required.
   * @returns - The buffer requested.
   */
  getBuffer(t) {
    return this.getAttribute(t).buffer;
  }
  /**
   * Used to figure out how many vertices there are in this geometry
   * @returns the number of vertices in the geometry
   */
  getSize() {
    for (const t in this.attributes) {
      const e = this.attributes[t];
      return e.buffer.data.length / (e.stride / 4 || e.size);
    }
    return 0;
  }
  /**
   * Adds an attribute to the geometry.
   * @param name - The name of the attribute to add.
   * @param attributeOption - The attribute option to add.
   */
  addAttribute(t, e) {
    const s = ax(e);
    this.buffers.indexOf(s.buffer) === -1 && (this.buffers.push(s.buffer), s.buffer.on("update", this.onBufferUpdate, this), s.buffer.on("change", this.onBufferUpdate, this)), this.attributes[t] = s;
  }
  /**
   * Adds an index buffer to the geometry.
   * @param indexBuffer - The index buffer to add. Can be a Buffer, TypedArray, or an array of numbers.
   */
  addIndex(t) {
    this.indexBuffer = Ip(t, !0), this.buffers.push(this.indexBuffer);
  }
  /** Returns the bounds of the geometry. */
  get bounds() {
    return this._boundsDirty ? (this._boundsDirty = !1, ox(this, "aPosition", this._bounds)) : this._bounds;
  }
  /**
   * destroys the geometry.
   * @param destroyBuffers - destroy the buffers associated with this geometry
   */
  destroy(t = !1) {
    this.emit("destroy", this), this.removeAllListeners(), t && this.buffers.forEach((e) => e.destroy()), this.attributes = null, this.buffers = null, this.indexBuffer = null, this._bounds = null;
  }
}
const cx = new Float32Array(1), hx = new Uint32Array(1);
class ux extends lx {
  constructor() {
    const e = new Ji({
      data: cx,
      label: "attribute-batch-buffer",
      usage: ge.VERTEX | ge.COPY_DST,
      shrinkToFit: !1
    }), s = new Ji({
      data: hx,
      label: "index-batch-buffer",
      usage: ge.INDEX | ge.COPY_DST,
      // | BufferUsage.STATIC,
      shrinkToFit: !1
    }), i = 24;
    super({
      attributes: {
        aPosition: {
          buffer: e,
          format: "float32x2",
          stride: i,
          offset: 0
        },
        aUV: {
          buffer: e,
          format: "float32x2",
          stride: i,
          offset: 8
        },
        aColor: {
          buffer: e,
          format: "unorm8x4",
          stride: i,
          offset: 16
        },
        aTextureIdAndRound: {
          buffer: e,
          format: "uint16x2",
          stride: i,
          offset: 20
        }
      },
      indexBuffer: s
    });
  }
}
function vu(n, t, e) {
  if (n)
    for (const s in n) {
      const i = s.toLocaleLowerCase(), r = t[i];
      if (r) {
        let o = n[s];
        s === "header" && (o = o.replace(/@in\s+[^;]+;\s*/g, "").replace(/@out\s+[^;]+;\s*/g, "")), e && r.push(`//----${e}----//`), r.push(o);
      } else
        Ht(`${s} placement hook does not exist in shader`);
    }
}
const dx = /\{\{(.*?)\}\}/g;
function bu(n) {
  const t = {};
  return (n.match(dx)?.map((s) => s.replace(/[{()}]/g, "")) ?? []).forEach((s) => {
    t[s] = [];
  }), t;
}
function wu(n, t) {
  let e;
  const s = /@in\s+([^;]+);/g;
  for (; (e = s.exec(n)) !== null; )
    t.push(e[1]);
}
function Su(n, t, e = !1) {
  const s = [];
  wu(t, s), n.forEach((a) => {
    a.header && wu(a.header, s);
  });
  const i = s;
  e && i.sort();
  const r = i.map((a, l) => `       @location(${l}) ${a},`).join(`
`);
  let o = t.replace(/@in\s+[^;]+;\s*/g, "");
  return o = o.replace("{{in}}", `
${r}
`), o;
}
function Tu(n, t) {
  let e;
  const s = /@out\s+([^;]+);/g;
  for (; (e = s.exec(n)) !== null; )
    t.push(e[1]);
}
function fx(n) {
  const e = /\b(\w+)\s*:/g.exec(n);
  return e ? e[1] : "";
}
function px(n) {
  const t = /@.*?\s+/g;
  return n.replace(t, "");
}
function mx(n, t) {
  const e = [];
  Tu(t, e), n.forEach((l) => {
    l.header && Tu(l.header, e);
  });
  let s = 0;
  const i = e.sort().map((l) => l.indexOf("builtin") > -1 ? l : `@location(${s++}) ${l}`).join(`,
`), r = e.sort().map((l) => `       var ${px(l)};`).join(`
`), o = `return VSOutput(
            ${e.sort().map((l) => ` ${fx(l)}`).join(`,
`)});`;
  let a = t.replace(/@out\s+[^;]+;\s*/g, "");
  return a = a.replace("{{struct}}", `
${i}
`), a = a.replace("{{start}}", `
${r}
`), a = a.replace("{{return}}", `
${o}
`), a;
}
function Mu(n, t) {
  let e = n;
  for (const s in t) {
    const i = t[s];
    i.join(`
`).length ? e = e.replace(`{{${s}}}`, `//-----${s} START-----//
${i.join(`
`)}
//----${s} FINISH----//`) : e = e.replace(`{{${s}}}`, "");
  }
  return e;
}
const qs = /* @__PURE__ */ Object.create(null), La = /* @__PURE__ */ new Map();
let gx = 0;
function yx({
  template: n,
  bits: t
}) {
  const e = Fp(n, t);
  if (qs[e])
    return qs[e];
  const { vertex: s, fragment: i } = _x(n, t);
  return qs[e] = Rp(s, i, t), qs[e];
}
function xx({
  template: n,
  bits: t
}) {
  const e = Fp(n, t);
  return qs[e] || (qs[e] = Rp(n.vertex, n.fragment, t)), qs[e];
}
function _x(n, t) {
  const e = t.map((o) => o.vertex).filter((o) => !!o), s = t.map((o) => o.fragment).filter((o) => !!o);
  let i = Su(e, n.vertex, !0);
  i = mx(e, i);
  const r = Su(s, n.fragment, !0);
  return {
    vertex: i,
    fragment: r
  };
}
function Fp(n, t) {
  return t.map((e) => (La.has(e) || La.set(e, gx++), La.get(e))).sort((e, s) => e - s).join("-") + n.vertex + n.fragment;
}
function Rp(n, t, e) {
  const s = bu(n), i = bu(t);
  return e.forEach((r) => {
    vu(r.vertex, s, r.name), vu(r.fragment, i, r.name);
  }), {
    vertex: Mu(n, s),
    fragment: Mu(t, i)
  };
}
const vx = (
  /* wgsl */
  `
    @in aPosition: vec2<f32>;
    @in aUV: vec2<f32>;

    @out @builtin(position) vPosition: vec4<f32>;
    @out vUV : vec2<f32>;
    @out vColor : vec4<f32>;

    {{header}}

    struct VSOutput {
        {{struct}}
    };

    @vertex
    fn main( {{in}} ) -> VSOutput {

        var worldTransformMatrix = globalUniforms.uWorldTransformMatrix;
        var modelMatrix = mat3x3<f32>(
            1.0, 0.0, 0.0,
            0.0, 1.0, 0.0,
            0.0, 0.0, 1.0
          );
        var position = aPosition;
        var uv = aUV;

        {{start}}

        vColor = vec4<f32>(1., 1., 1., 1.);

        {{main}}

        vUV = uv;

        var modelViewProjectionMatrix = globalUniforms.uProjectionMatrix * worldTransformMatrix * modelMatrix;

        vPosition =  vec4<f32>((modelViewProjectionMatrix *  vec3<f32>(position, 1.0)).xy, 0.0, 1.0);

        vColor *= globalUniforms.uWorldColorAlpha;

        {{end}}

        {{return}}
    };
`
), bx = (
  /* wgsl */
  `
    @in vUV : vec2<f32>;
    @in vColor : vec4<f32>;

    {{header}}

    @fragment
    fn main(
        {{in}}
      ) -> @location(0) vec4<f32> {

        {{start}}

        var outColor:vec4<f32>;

        {{main}}

        var finalColor:vec4<f32> = outColor * vColor;

        {{end}}

        return finalColor;
      };
`
), wx = (
  /* glsl */
  `
    in vec2 aPosition;
    in vec2 aUV;

    out vec4 vColor;
    out vec2 vUV;

    {{header}}

    void main(void){

        mat3 worldTransformMatrix = uWorldTransformMatrix;
        mat3 modelMatrix = mat3(
            1.0, 0.0, 0.0,
            0.0, 1.0, 0.0,
            0.0, 0.0, 1.0
          );
        vec2 position = aPosition;
        vec2 uv = aUV;

        {{start}}

        vColor = vec4(1.);

        {{main}}

        vUV = uv;

        mat3 modelViewProjectionMatrix = uProjectionMatrix * worldTransformMatrix * modelMatrix;

        gl_Position = vec4((modelViewProjectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);

        vColor *= uWorldColorAlpha;

        {{end}}
    }
`
), Sx = (
  /* glsl */
  `

    in vec4 vColor;
    in vec2 vUV;

    out vec4 finalColor;

    {{header}}

    void main(void) {

        {{start}}

        vec4 outColor;

        {{main}}

        finalColor = outColor * vColor;

        {{end}}
    }
`
), Tx = {
  name: "global-uniforms-bit",
  vertex: {
    header: (
      /* wgsl */
      `
        struct GlobalUniforms {
            uProjectionMatrix:mat3x3<f32>,
            uWorldTransformMatrix:mat3x3<f32>,
            uWorldColorAlpha: vec4<f32>,
            uResolution: vec2<f32>,
        }

        @group(0) @binding(0) var<uniform> globalUniforms : GlobalUniforms;
        `
    )
  }
}, Mx = {
  name: "global-uniforms-bit",
  vertex: {
    header: (
      /* glsl */
      `
          uniform mat3 uProjectionMatrix;
          uniform mat3 uWorldTransformMatrix;
          uniform vec4 uWorldColorAlpha;
          uniform vec2 uResolution;
        `
    )
  }
};
function kx({ bits: n, name: t }) {
  const e = yx({
    template: {
      fragment: bx,
      vertex: vx
    },
    bits: [
      Tx,
      ...n
    ]
  });
  return Yo.from({
    name: t,
    vertex: {
      source: e.vertex,
      entryPoint: "main"
    },
    fragment: {
      source: e.fragment,
      entryPoint: "main"
    }
  });
}
function Cx({ bits: n, name: t }) {
  return new cp({
    name: t,
    ...xx({
      template: {
        vertex: wx,
        fragment: Sx
      },
      bits: [
        Mx,
        ...n
      ]
    })
  });
}
const Ax = {
  name: "color-bit",
  vertex: {
    header: (
      /* wgsl */
      `
            @in aColor: vec4<f32>;
        `
    ),
    main: (
      /* wgsl */
      `
            vColor *= vec4<f32>(aColor.rgb * aColor.a, aColor.a);
        `
    )
  }
}, Ex = {
  name: "color-bit",
  vertex: {
    header: (
      /* glsl */
      `
            in vec4 aColor;
        `
    ),
    main: (
      /* glsl */
      `
            vColor *= vec4(aColor.rgb * aColor.a, aColor.a);
        `
    )
  }
}, Va = {};
function Px(n) {
  const t = [];
  if (n === 1)
    t.push("@group(1) @binding(0) var textureSource1: texture_2d<f32>;"), t.push("@group(1) @binding(1) var textureSampler1: sampler;");
  else {
    let e = 0;
    for (let s = 0; s < n; s++)
      t.push(`@group(1) @binding(${e++}) var textureSource${s + 1}: texture_2d<f32>;`), t.push(`@group(1) @binding(${e++}) var textureSampler${s + 1}: sampler;`);
  }
  return t.join(`
`);
}
function Ix(n) {
  const t = [];
  if (n === 1)
    t.push("outColor = textureSampleGrad(textureSource1, textureSampler1, vUV, uvDx, uvDy);");
  else {
    t.push("switch vTextureId {");
    for (let e = 0; e < n; e++)
      e === n - 1 ? t.push("  default:{") : t.push(`  case ${e}:{`), t.push(`      outColor = textureSampleGrad(textureSource${e + 1}, textureSampler${e + 1}, vUV, uvDx, uvDy);`), t.push("      break;}");
    t.push("}");
  }
  return t.join(`
`);
}
function Fx(n) {
  return Va[n] || (Va[n] = {
    name: "texture-batch-bit",
    vertex: {
      header: `
                @in aTextureIdAndRound: vec2<u32>;
                @out @interpolate(flat) vTextureId : u32;
            `,
      main: `
                vTextureId = aTextureIdAndRound.y;
            `,
      end: `
                if(aTextureIdAndRound.x == 1)
                {
                    vPosition = vec4<f32>(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
                }
            `
    },
    fragment: {
      header: `
                @in @interpolate(flat) vTextureId: u32;

                ${Px(n)}
            `,
      main: `
                var uvDx = dpdx(vUV);
                var uvDy = dpdy(vUV);

                ${Ix(n)}
            `
    }
  }), Va[n];
}
const Ba = {};
function Rx(n) {
  const t = [];
  for (let e = 0; e < n; e++)
    e > 0 && t.push("else"), e < n - 1 && t.push(`if(vTextureId < ${e}.5)`), t.push("{"), t.push(`	outColor = texture(uTextures[${e}], vUV);`), t.push("}");
  return t.join(`
`);
}
function Dx(n) {
  return Ba[n] || (Ba[n] = {
    name: "texture-batch-bit",
    vertex: {
      header: `
                in vec2 aTextureIdAndRound;
                out float vTextureId;

            `,
      main: `
                vTextureId = aTextureIdAndRound.y;
            `,
      end: `
                if(aTextureIdAndRound.x == 1.)
                {
                    gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
                }
            `
    },
    fragment: {
      header: `
                in float vTextureId;

                uniform sampler2D uTextures[${n}];

            `,
      main: `

                ${Rx(n)}
            `
    }
  }), Ba[n];
}
const Ox = {
  name: "round-pixels-bit",
  vertex: {
    header: (
      /* wgsl */
      `
            fn roundPixels(position: vec2<f32>, targetSize: vec2<f32>) -> vec2<f32>
            {
                return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
            }
        `
    )
  }
}, Nx = {
  name: "round-pixels-bit",
  vertex: {
    header: (
      /* glsl */
      `
            vec2 roundPixels(vec2 position, vec2 targetSize)
            {
                return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
            }
        `
    )
  }
}, ku = {};
function Lx(n) {
  let t = ku[n];
  if (t)
    return t;
  const e = new Int32Array(n);
  for (let s = 0; s < n; s++)
    e[s] = s;
  return t = ku[n] = new fp({
    uTextures: { value: e, type: "i32", size: n }
  }, { isStatic: !0 }), t;
}
class Vx extends Kl {
  constructor(t) {
    const e = Cx({
      name: "batch",
      bits: [
        Ex,
        Dx(t),
        Nx
      ]
    }), s = kx({
      name: "batch",
      bits: [
        Ax,
        Fx(t),
        Ox
      ]
    });
    super({
      glProgram: e,
      gpuProgram: s,
      resources: {
        batchSamplers: Lx(t)
      }
    });
  }
}
let za = null;
const Dp = class Op extends rx {
  constructor(t) {
    super(t), this.geometry = new ux(), this.name = Op.extension.name, this.vertexSize = 6, za ?? (za = new Vx(t.maxTextures)), this.shader = za;
  }
  /**
   * Packs the attributes of a DefaultBatchableMeshElement into the provided views.
   * @param element - The DefaultBatchableMeshElement to pack.
   * @param float32View - The Float32Array view to pack into.
   * @param uint32View - The Uint32Array view to pack into.
   * @param index - The starting index in the views.
   * @param textureId - The texture ID to use.
   */
  packAttributes(t, e, s, i, r) {
    const o = r << 16 | t.roundPixels & 65535, a = t.transform, l = a.a, c = a.b, h = a.c, u = a.d, d = a.tx, f = a.ty, { positions: p, uvs: g } = t, m = t.color, y = t.attributeOffset, x = y + t.attributeSize;
    for (let v = y; v < x; v++) {
      const _ = v * 2, b = p[_], w = p[_ + 1];
      e[i++] = l * b + h * w + d, e[i++] = u * w + c * b + f, e[i++] = g[_], e[i++] = g[_ + 1], s[i++] = m, s[i++] = o;
    }
  }
  /**
   * Packs the attributes of a DefaultBatchableQuadElement into the provided views.
   * @param element - The DefaultBatchableQuadElement to pack.
   * @param float32View - The Float32Array view to pack into.
   * @param uint32View - The Uint32Array view to pack into.
   * @param index - The starting index in the views.
   * @param textureId - The texture ID to use.
   */
  packQuadAttributes(t, e, s, i, r) {
    const o = t.texture, a = t.transform, l = a.a, c = a.b, h = a.c, u = a.d, d = a.tx, f = a.ty, p = t.bounds, g = p.maxX, m = p.minX, y = p.maxY, x = p.minY, v = o.uvs, _ = t.color, b = r << 16 | t.roundPixels & 65535;
    e[i + 0] = l * m + h * x + d, e[i + 1] = u * x + c * m + f, e[i + 2] = v.x0, e[i + 3] = v.y0, s[i + 4] = _, s[i + 5] = b, e[i + 6] = l * g + h * x + d, e[i + 7] = u * x + c * g + f, e[i + 8] = v.x1, e[i + 9] = v.y1, s[i + 10] = _, s[i + 11] = b, e[i + 12] = l * g + h * y + d, e[i + 13] = u * y + c * g + f, e[i + 14] = v.x2, e[i + 15] = v.y2, s[i + 16] = _, s[i + 17] = b, e[i + 18] = l * m + h * y + d, e[i + 19] = u * y + c * m + f, e[i + 20] = v.x3, e[i + 21] = v.y3, s[i + 22] = _, s[i + 23] = b;
  }
};
Dp.extension = {
  type: [
    dt.Batcher
  ],
  name: "default"
};
let Bx = Dp;
function zx(n, t, e, s, i, r, o, a = null) {
  let l = 0;
  e *= t, i *= r;
  const c = a.a, h = a.b, u = a.c, d = a.d, f = a.tx, p = a.ty;
  for (; l < o; ) {
    const g = n[e], m = n[e + 1];
    s[i] = c * g + u * m + f, s[i + 1] = h * g + d * m + p, i += r, e += t, l++;
  }
}
function qx(n, t, e, s) {
  let i = 0;
  for (t *= e; i < s; )
    n[t] = 0, n[t + 1] = 0, t += e, i++;
}
function Np(n, t, e, s, i) {
  const r = t.a, o = t.b, a = t.c, l = t.d, c = t.tx, h = t.ty;
  e || (e = 0), s || (s = 2), i || (i = n.length / s - e);
  let u = e * s;
  for (let d = 0; d < i; d++) {
    const f = n[u], p = n[u + 1];
    n[u] = r * f + a * p + c, n[u + 1] = o * f + l * p + h, u += s;
  }
}
const Ux = new nt();
class Lp {
  constructor() {
    this.packAsQuad = !1, this.batcherName = "default", this.topology = "triangle-list", this.applyTransform = !0, this.roundPixels = 0, this._batcher = null, this._batch = null;
  }
  get uvs() {
    return this.geometryData.uvs;
  }
  get positions() {
    return this.geometryData.vertices;
  }
  get indices() {
    return this.geometryData.indices;
  }
  get blendMode() {
    return this.renderable && this.applyTransform ? this.renderable.groupBlendMode : "normal";
  }
  get color() {
    const t = this.baseColor, e = t >> 16 | t & 65280 | (t & 255) << 16, s = this.renderable;
    return s ? qf(e, s.groupColor) + (this.alpha * s.groupAlpha * 255 << 24) : e + (this.alpha * 255 << 24);
  }
  get transform() {
    return this.renderable?.groupTransform || Ux;
  }
  copyTo(t) {
    t.indexOffset = this.indexOffset, t.indexSize = this.indexSize, t.attributeOffset = this.attributeOffset, t.attributeSize = this.attributeSize, t.baseColor = this.baseColor, t.alpha = this.alpha, t.texture = this.texture, t.geometryData = this.geometryData, t.topology = this.topology;
  }
  reset() {
    this.applyTransform = !0, this.renderable = null, this.topology = "triangle-list";
  }
}
const tr = {
  extension: {
    type: dt.ShapeBuilder,
    name: "circle"
  },
  build(n, t) {
    let e, s, i, r, o, a;
    if (n.type === "circle") {
      const _ = n;
      if (o = a = _.radius, o <= 0)
        return !1;
      e = _.x, s = _.y, i = r = 0;
    } else if (n.type === "ellipse") {
      const _ = n;
      if (o = _.halfWidth, a = _.halfHeight, o <= 0 || a <= 0)
        return !1;
      e = _.x, s = _.y, i = r = 0;
    } else {
      const _ = n, b = _.width / 2, w = _.height / 2;
      e = _.x + b, s = _.y + w, o = a = Math.max(0, Math.min(_.radius, Math.min(b, w))), i = b - o, r = w - a;
    }
    if (i < 0 || r < 0)
      return !1;
    const l = Math.ceil(2.3 * Math.sqrt(o + a)), c = l * 8 + (i ? 4 : 0) + (r ? 4 : 0);
    if (c === 0)
      return !1;
    if (l === 0)
      return t[0] = t[6] = e + i, t[1] = t[3] = s + r, t[2] = t[4] = e - i, t[5] = t[7] = s - r, !0;
    let h = 0, u = l * 4 + (i ? 2 : 0) + 2, d = u, f = c, p = i + o, g = r, m = e + p, y = e - p, x = s + g;
    if (t[h++] = m, t[h++] = x, t[--u] = x, t[--u] = y, r) {
      const _ = s - g;
      t[d++] = y, t[d++] = _, t[--f] = _, t[--f] = m;
    }
    for (let _ = 1; _ < l; _++) {
      const b = Math.PI / 2 * (_ / l), w = i + Math.cos(b) * o, S = r + Math.sin(b) * a, T = e + w, k = e - w, C = s + S, M = s - S;
      t[h++] = T, t[h++] = C, t[--u] = C, t[--u] = k, t[d++] = k, t[d++] = M, t[--f] = M, t[--f] = T;
    }
    p = i, g = r + a, m = e + p, y = e - p, x = s + g;
    const v = s - g;
    return t[h++] = m, t[h++] = x, t[--f] = v, t[--f] = m, i && (t[h++] = y, t[h++] = x, t[--f] = v, t[--f] = y), !0;
  },
  triangulate(n, t, e, s, i, r) {
    if (n.length === 0)
      return;
    let o = 0, a = 0;
    for (let h = 0; h < n.length; h += 2)
      o += n[h], a += n[h + 1];
    o /= n.length / 2, a /= n.length / 2;
    let l = s;
    t[l * e] = o, t[l * e + 1] = a;
    const c = l++;
    for (let h = 0; h < n.length; h += 2)
      t[l * e] = n[h], t[l * e + 1] = n[h + 1], h > 0 && (i[r++] = l, i[r++] = c, i[r++] = l - 1), l++;
    i[r++] = c + 1, i[r++] = c, i[r++] = l - 1;
  }
}, Gx = { ...tr, extension: { ...tr.extension, name: "ellipse" } }, Wx = { ...tr, extension: { ...tr.extension, name: "roundedRectangle" } }, Vp = 1e-4, Cu = 1e-4;
function $x(n) {
  const t = n.length;
  if (t < 6)
    return 1;
  let e = 0;
  for (let s = 0, i = n[t - 2], r = n[t - 1]; s < t; s += 2) {
    const o = n[s], a = n[s + 1];
    e += (o - i) * (a + r), i = o, r = a;
  }
  return e < 0 ? -1 : 1;
}
function Au(n, t, e, s, i, r, o, a) {
  const l = n - e * i, c = t - s * i, h = n + e * r, u = t + s * r;
  let d, f;
  o ? (d = s, f = -e) : (d = -s, f = e);
  const p = l + d, g = c + f, m = h + d, y = u + f;
  return a.push(p, g), a.push(m, y), 2;
}
function rn(n, t, e, s, i, r, o, a) {
  const l = e - n, c = s - t;
  let h = Math.atan2(l, c), u = Math.atan2(i - n, r - t);
  a && h < u ? h += Math.PI * 2 : !a && h > u && (u += Math.PI * 2);
  let d = h;
  const f = u - h, p = Math.abs(f), g = Math.sqrt(l * l + c * c), m = (15 * p * Math.sqrt(g) / Math.PI >> 0) + 1, y = f / m;
  if (d += y, a) {
    o.push(n, t), o.push(e, s);
    for (let x = 1, v = d; x < m; x++, v += y)
      o.push(n, t), o.push(
        n + Math.sin(v) * g,
        t + Math.cos(v) * g
      );
    o.push(n, t), o.push(i, r);
  } else {
    o.push(e, s), o.push(n, t);
    for (let x = 1, v = d; x < m; x++, v += y)
      o.push(
        n + Math.sin(v) * g,
        t + Math.cos(v) * g
      ), o.push(n, t);
    o.push(i, r), o.push(n, t);
  }
  return m * 2;
}
function Hx(n, t, e, s, i, r) {
  const o = Vp;
  if (n.length === 0)
    return;
  const a = t;
  let l = a.alignment;
  if (t.alignment !== 0.5) {
    let D = $x(n);
    l = (l - 0.5) * D + 0.5;
  }
  const c = new se(n[0], n[1]), h = new se(n[n.length - 2], n[n.length - 1]), u = s, d = Math.abs(c.x - h.x) < o && Math.abs(c.y - h.y) < o;
  if (u) {
    n = n.slice(), d && (n.pop(), n.pop(), h.set(n[n.length - 2], n[n.length - 1]));
    const D = (c.x + h.x) * 0.5, z = (h.y + c.y) * 0.5;
    n.unshift(D, z), n.push(D, z);
  }
  const f = i, p = n.length / 2;
  let g = n.length;
  const m = f.length / 2, y = a.width / 2, x = y * y, v = a.miterLimit * a.miterLimit;
  let _ = n[0], b = n[1], w = n[2], S = n[3], T = 0, k = 0, C = -(b - S), M = _ - w, A = 0, I = 0, F = Math.sqrt(C * C + M * M);
  C /= F, M /= F, C *= y, M *= y;
  const R = l, E = (1 - R) * 2, P = R * 2;
  u || (a.cap === "round" ? g += rn(
    _ - C * (E - P) * 0.5,
    b - M * (E - P) * 0.5,
    _ - C * E,
    b - M * E,
    _ + C * P,
    b + M * P,
    f,
    !0
  ) + 2 : a.cap === "square" && (g += Au(_, b, C, M, E, P, !0, f))), f.push(
    _ - C * E,
    b - M * E
  ), f.push(
    _ + C * P,
    b + M * P
  );
  for (let D = 1; D < p - 1; ++D) {
    _ = n[(D - 1) * 2], b = n[(D - 1) * 2 + 1], w = n[D * 2], S = n[D * 2 + 1], T = n[(D + 1) * 2], k = n[(D + 1) * 2 + 1], C = -(b - S), M = _ - w, F = Math.sqrt(C * C + M * M), C /= F, M /= F, C *= y, M *= y, A = -(S - k), I = w - T, F = Math.sqrt(A * A + I * I), A /= F, I /= F, A *= y, I *= y;
    const z = w - _, O = b - S, V = w - T, G = k - S, H = z * V + O * G, q = O * V - G * z, W = q < 0;
    if (Math.abs(q) < 1e-3 * Math.abs(H)) {
      f.push(
        w - C * E,
        S - M * E
      ), f.push(
        w + C * P,
        S + M * P
      ), H >= 0 && (a.join === "round" ? g += rn(
        w,
        S,
        w - C * E,
        S - M * E,
        w - A * E,
        S - I * E,
        f,
        !1
      ) + 4 : g += 2, f.push(
        w - A * P,
        S - I * P
      ), f.push(
        w + A * E,
        S + I * E
      ));
      continue;
    }
    const K = (-C + _) * (-M + S) - (-C + w) * (-M + b), U = (-A + T) * (-I + S) - (-A + w) * (-I + k), at = (z * U - V * K) / q, At = (G * K - O * U) / q, te = (at - w) * (at - w) + (At - S) * (At - S), ee = w + (at - w) * E, Ue = S + (At - S) * E, we = w - (at - w) * P, $ = S - (At - S) * P, J = Math.min(z * z + O * O, V * V + G * G), bt = W ? E : P, pt = J + bt * bt * x;
    te <= pt ? a.join === "bevel" || te / x > v ? (W ? (f.push(ee, Ue), f.push(w + C * P, S + M * P), f.push(ee, Ue), f.push(w + A * P, S + I * P)) : (f.push(w - C * E, S - M * E), f.push(we, $), f.push(w - A * E, S - I * E), f.push(we, $)), g += 2) : a.join === "round" ? W ? (f.push(ee, Ue), f.push(w + C * P, S + M * P), g += rn(
      w,
      S,
      w + C * P,
      S + M * P,
      w + A * P,
      S + I * P,
      f,
      !0
    ) + 4, f.push(ee, Ue), f.push(w + A * P, S + I * P)) : (f.push(w - C * E, S - M * E), f.push(we, $), g += rn(
      w,
      S,
      w - C * E,
      S - M * E,
      w - A * E,
      S - I * E,
      f,
      !1
    ) + 4, f.push(w - A * E, S - I * E), f.push(we, $)) : (f.push(ee, Ue), f.push(we, $)) : (f.push(w - C * E, S - M * E), f.push(w + C * P, S + M * P), a.join === "round" ? W ? g += rn(
      w,
      S,
      w + C * P,
      S + M * P,
      w + A * P,
      S + I * P,
      f,
      !0
    ) + 2 : g += rn(
      w,
      S,
      w - C * E,
      S - M * E,
      w - A * E,
      S - I * E,
      f,
      !1
    ) + 2 : a.join === "miter" && te / x <= v && (W ? (f.push(we, $), f.push(we, $)) : (f.push(ee, Ue), f.push(ee, Ue)), g += 2), f.push(w - A * E, S - I * E), f.push(w + A * P, S + I * P), g += 2);
  }
  _ = n[(p - 2) * 2], b = n[(p - 2) * 2 + 1], w = n[(p - 1) * 2], S = n[(p - 1) * 2 + 1], C = -(b - S), M = _ - w, F = Math.sqrt(C * C + M * M), C /= F, M /= F, C *= y, M *= y, f.push(w - C * E, S - M * E), f.push(w + C * P, S + M * P), u || (a.cap === "round" ? g += rn(
    w - C * (E - P) * 0.5,
    S - M * (E - P) * 0.5,
    w - C * E,
    S - M * E,
    w + C * P,
    S + M * P,
    f,
    !1
  ) + 2 : a.cap === "square" && (g += Au(w, S, C, M, E, P, !1, f)));
  const N = Cu * Cu;
  for (let D = m; D < g + m - 2; ++D)
    _ = f[D * 2], b = f[D * 2 + 1], w = f[(D + 1) * 2], S = f[(D + 1) * 2 + 1], T = f[(D + 2) * 2], k = f[(D + 2) * 2 + 1], !(Math.abs(_ * (S - k) + w * (k - b) + T * (b - S)) < N) && r.push(D, D + 1, D + 2);
}
function jx(n, t, e, s) {
  const i = Vp;
  if (n.length === 0)
    return;
  const r = n[0], o = n[1], a = n[n.length - 2], l = n[n.length - 1], c = t || Math.abs(r - a) < i && Math.abs(o - l) < i, h = e, u = n.length / 2, d = h.length / 2;
  for (let f = 0; f < u; f++)
    h.push(n[f * 2]), h.push(n[f * 2 + 1]);
  for (let f = 0; f < u - 1; f++)
    s.push(d + f, d + f + 1);
  c && s.push(d + u - 1, d);
}
function Bp(n, t, e, s, i, r, o) {
  const a = R0(n, t, 2);
  if (!a)
    return;
  for (let c = 0; c < a.length; c += 3)
    r[o++] = a[c] + i, r[o++] = a[c + 1] + i, r[o++] = a[c + 2] + i;
  let l = i * s;
  for (let c = 0; c < n.length; c += 2)
    e[l] = n[c], e[l + 1] = n[c + 1], l += s;
}
const Xx = [], Yx = {
  extension: {
    type: dt.ShapeBuilder,
    name: "polygon"
  },
  build(n, t) {
    for (let e = 0; e < n.points.length; e++)
      t[e] = n.points[e];
    return !0;
  },
  triangulate(n, t, e, s, i, r) {
    Bp(n, Xx, t, e, s, i, r);
  }
}, Zx = {
  extension: {
    type: dt.ShapeBuilder,
    name: "rectangle"
  },
  build(n, t) {
    const e = n, s = e.x, i = e.y, r = e.width, o = e.height;
    return r > 0 && o > 0 ? (t[0] = s, t[1] = i, t[2] = s + r, t[3] = i, t[4] = s + r, t[5] = i + o, t[6] = s, t[7] = i + o, !0) : !1;
  },
  triangulate(n, t, e, s, i, r) {
    let o = 0;
    s *= e, t[s + o] = n[0], t[s + o + 1] = n[1], o += e, t[s + o] = n[2], t[s + o + 1] = n[3], o += e, t[s + o] = n[6], t[s + o + 1] = n[7], o += e, t[s + o] = n[4], t[s + o + 1] = n[5], o += e;
    const a = s / e;
    i[r++] = a, i[r++] = a + 1, i[r++] = a + 2, i[r++] = a + 1, i[r++] = a + 3, i[r++] = a + 2;
  }
}, Kx = {
  extension: {
    type: dt.ShapeBuilder,
    name: "triangle"
  },
  build(n, t) {
    return t[0] = n.x, t[1] = n.y, t[2] = n.x2, t[3] = n.y2, t[4] = n.x3, t[5] = n.y3, !0;
  },
  triangulate(n, t, e, s, i, r) {
    let o = 0;
    s *= e, t[s + o] = n[0], t[s + o + 1] = n[1], o += e, t[s + o] = n[2], t[s + o + 1] = n[3], o += e, t[s + o] = n[4], t[s + o + 1] = n[5];
    const a = s / e;
    i[r++] = a, i[r++] = a + 1, i[r++] = a + 2;
  }
}, Qx = new nt(), Jx = new Dt();
function t_(n, t, e, s) {
  const i = t.matrix ? n.copyFrom(t.matrix).invert() : n.identity();
  if (t.textureSpace === "local") {
    const o = e.getBounds(Jx);
    t.width && o.pad(t.width);
    const { x: a, y: l } = o, c = 1 / o.width, h = 1 / o.height, u = -a * c, d = -l * h, f = i.a, p = i.b, g = i.c, m = i.d;
    i.a *= c, i.b *= c, i.c *= h, i.d *= h, i.tx = u * f + d * g + i.tx, i.ty = u * p + d * m + i.ty;
  } else
    i.translate(t.texture.frame.x, t.texture.frame.y), i.scale(1 / t.texture.source.width, 1 / t.texture.source.height);
  const r = t.texture.source.style;
  return !(t.fill instanceof Is) && r.addressMode === "clamp-to-edge" && (r.addressMode = "repeat", r.update()), s && i.append(Qx.copyFrom(s).invert()), i;
}
const Ko = {};
ze.handleByMap(dt.ShapeBuilder, Ko);
ze.add(Zx, Yx, Kx, tr, Gx, Wx);
const e_ = new Dt(), s_ = new nt();
function n_(n, t) {
  const { geometryData: e, batches: s } = t;
  s.length = 0, e.indices.length = 0, e.vertices.length = 0, e.uvs.length = 0;
  for (let i = 0; i < n.instructions.length; i++) {
    const r = n.instructions[i];
    if (r.action === "texture")
      i_(r.data, s, e);
    else if (r.action === "fill" || r.action === "stroke") {
      const o = r.action === "stroke", a = r.data.path.shapePath, l = r.data.style, c = r.data.hole;
      o && c && Eu(c.shapePath, l, !0, s, e), c && (a.shapePrimitives[a.shapePrimitives.length - 1].holes = c.shapePath.shapePrimitives), Eu(a, l, o, s, e);
    }
  }
}
function i_(n, t, e) {
  const s = [], i = Ko.rectangle, r = e_;
  r.x = n.dx, r.y = n.dy, r.width = n.dw, r.height = n.dh;
  const o = n.transform;
  if (!i.build(r, s))
    return;
  const { vertices: a, uvs: l, indices: c } = e, h = c.length, u = a.length / 2;
  o && Np(s, o), i.triangulate(s, a, 2, u, c, h);
  const d = n.image, f = d.uvs;
  l.push(
    f.x0,
    f.y0,
    f.x1,
    f.y1,
    f.x3,
    f.y3,
    f.x2,
    f.y2
  );
  const p = Ms.get(Lp);
  p.indexOffset = h, p.indexSize = c.length - h, p.attributeOffset = u, p.attributeSize = a.length / 2 - u, p.baseColor = n.style, p.alpha = n.alpha, p.texture = d, p.geometryData = e, t.push(p);
}
function Eu(n, t, e, s, i) {
  const { vertices: r, uvs: o, indices: a } = i;
  n.shapePrimitives.forEach(({ shape: l, transform: c, holes: h }) => {
    const u = [], d = Ko[l.type];
    if (!d.build(l, u))
      return;
    const f = a.length, p = r.length / 2;
    let g = "triangle-list";
    if (c && Np(u, c), e) {
      const v = l.closePath ?? !0, _ = t;
      _.pixelLine ? (jx(u, v, r, a), g = "line-list") : Hx(u, _, !1, v, r, a);
    } else if (h) {
      const v = [], _ = u.slice();
      r_(h).forEach((w) => {
        v.push(_.length / 2), _.push(...w);
      }), Bp(_, v, r, 2, p, a, f);
    } else
      d.triangulate(u, r, 2, p, a, f);
    const m = o.length / 2, y = t.texture;
    if (y !== rt.WHITE) {
      const v = t_(s_, t, l, c);
      zx(r, 2, p, o, m, 2, r.length / 2 - p, v);
    } else
      qx(o, m, 2, r.length / 2 - p);
    const x = Ms.get(Lp);
    x.indexOffset = f, x.indexSize = a.length - f, x.attributeOffset = p, x.attributeSize = r.length / 2 - p, x.baseColor = t.color, x.alpha = t.alpha, x.texture = y, x.geometryData = i, x.topology = g, s.push(x);
  });
}
function r_(n) {
  const t = [];
  for (let e = 0; e < n.length; e++) {
    const s = n[e].shape, i = [];
    Ko[s.type].build(s, i) && t.push(i);
  }
  return t;
}
class o_ {
  constructor() {
    this.batches = [], this.geometryData = {
      vertices: [],
      uvs: [],
      indices: []
    };
  }
}
class a_ {
  constructor() {
    this.instructions = new $f();
  }
  init(t) {
    this.batcher = new Bx({
      maxTextures: t
    }), this.instructions.reset();
  }
  /**
   * @deprecated since version 8.0.0
   * Use `batcher.geometry` instead.
   * @see {Batcher#geometry}
   */
  get geometry() {
    return ct(sy, "GraphicsContextRenderData#geometry is deprecated, please use batcher.geometry instead."), this.batcher.geometry;
  }
}
const sc = class _l {
  constructor(t) {
    this._gpuContextHash = {}, this._graphicsDataContextHash = /* @__PURE__ */ Object.create(null), this._renderer = t, t.renderableGC.addManagedHash(this, "_gpuContextHash"), t.renderableGC.addManagedHash(this, "_graphicsDataContextHash");
  }
  /**
   * Runner init called, update the default options
   * @ignore
   */
  init(t) {
    _l.defaultOptions.bezierSmoothness = t?.bezierSmoothness ?? _l.defaultOptions.bezierSmoothness;
  }
  /**
   * Returns the render data for a given GraphicsContext.
   * @param context - The GraphicsContext to get the render data for.
   * @internal
   */
  getContextRenderData(t) {
    return this._graphicsDataContextHash[t.uid] || this._initContextRenderData(t);
  }
  /**
   * Updates the GPU context for a given GraphicsContext.
   * If the context is dirty, it will rebuild the batches and geometry data.
   * @param context - The GraphicsContext to update.
   * @returns The updated GpuGraphicsContext.
   * @internal
   */
  updateGpuContext(t) {
    let e = this._gpuContextHash[t.uid] || this._initContext(t);
    if (t.dirty) {
      e ? this._cleanGraphicsContextData(t) : e = this._initContext(t), n_(t, e);
      const s = t.batchMode;
      t.customShader || s === "no-batch" ? e.isBatchable = !1 : s === "auto" ? e.isBatchable = e.geometryData.vertices.length < 400 : e.isBatchable = !0, t.dirty = !1;
    }
    return e;
  }
  /**
   * Returns the GpuGraphicsContext for a given GraphicsContext.
   * If it does not exist, it will initialize a new one.
   * @param context - The GraphicsContext to get the GpuGraphicsContext for.
   * @returns The GpuGraphicsContext for the given GraphicsContext.
   * @internal
   */
  getGpuContext(t) {
    return this._gpuContextHash[t.uid] || this._initContext(t);
  }
  _initContextRenderData(t) {
    const e = Ms.get(a_, {
      maxTextures: this._renderer.limits.maxBatchableTextures
    }), { batches: s, geometryData: i } = this._gpuContextHash[t.uid], r = i.vertices.length, o = i.indices.length;
    for (let h = 0; h < s.length; h++)
      s[h].applyTransform = !1;
    const a = e.batcher;
    a.ensureAttributeBuffer(r), a.ensureIndexBuffer(o), a.begin();
    for (let h = 0; h < s.length; h++) {
      const u = s[h];
      a.add(u);
    }
    a.finish(e.instructions);
    const l = a.geometry;
    l.indexBuffer.setDataWithSize(a.indexBuffer, a.indexSize, !0), l.buffers[0].setDataWithSize(a.attributeBuffer.float32View, a.attributeSize, !0);
    const c = a.batches;
    for (let h = 0; h < c.length; h++) {
      const u = c[h];
      u.bindGroup = Y0(
        u.textures.textures,
        u.textures.count,
        this._renderer.limits.maxBatchableTextures
      );
    }
    return this._graphicsDataContextHash[t.uid] = e, e;
  }
  _initContext(t) {
    const e = new o_();
    return e.context = t, this._gpuContextHash[t.uid] = e, t.on("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[t.uid];
  }
  onGraphicsContextDestroy(t) {
    this._cleanGraphicsContextData(t), t.off("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[t.uid] = null;
  }
  _cleanGraphicsContextData(t) {
    const e = this._gpuContextHash[t.uid];
    e.isBatchable || this._graphicsDataContextHash[t.uid] && (Ms.return(this.getContextRenderData(t)), this._graphicsDataContextHash[t.uid] = null), e.batches && e.batches.forEach((s) => {
      Ms.return(s);
    });
  }
  destroy() {
    for (const t in this._gpuContextHash)
      this._gpuContextHash[t] && this.onGraphicsContextDestroy(this._gpuContextHash[t].context);
  }
};
sc.extension = {
  type: [
    dt.WebGLSystem,
    dt.WebGPUSystem,
    dt.CanvasSystem
  ],
  name: "graphicsContext"
};
sc.defaultOptions = {
  /**
   * A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother)
   * @default 0.5
   */
  bezierSmoothness: 0.5
};
let zp = sc;
const l_ = 8, Zr = 11920929e-14, c_ = 1;
function qp(n, t, e, s, i, r, o, a, l, c) {
  const u = Math.min(
    0.99,
    // a value of 1.0 actually inverts smoothing, so we cap it at 0.99
    Math.max(0, c ?? zp.defaultOptions.bezierSmoothness)
  );
  let d = (c_ - u) / 1;
  return d *= d, h_(t, e, s, i, r, o, a, l, n, d), n;
}
function h_(n, t, e, s, i, r, o, a, l, c) {
  vl(n, t, e, s, i, r, o, a, l, c, 0), l.push(o, a);
}
function vl(n, t, e, s, i, r, o, a, l, c, h) {
  if (h > l_)
    return;
  const u = (n + e) / 2, d = (t + s) / 2, f = (e + i) / 2, p = (s + r) / 2, g = (i + o) / 2, m = (r + a) / 2, y = (u + f) / 2, x = (d + p) / 2, v = (f + g) / 2, _ = (p + m) / 2, b = (y + v) / 2, w = (x + _) / 2;
  if (h > 0) {
    let S = o - n, T = a - t;
    const k = Math.abs((e - o) * T - (s - a) * S), C = Math.abs((i - o) * T - (r - a) * S);
    if (k > Zr && C > Zr) {
      if ((k + C) * (k + C) <= c * (S * S + T * T)) {
        l.push(b, w);
        return;
      }
    } else if (k > Zr) {
      if (k * k <= c * (S * S + T * T)) {
        l.push(b, w);
        return;
      }
    } else if (C > Zr) {
      if (C * C <= c * (S * S + T * T)) {
        l.push(b, w);
        return;
      }
    } else if (S = b - (n + o) / 2, T = w - (t + a) / 2, S * S + T * T <= c) {
      l.push(b, w);
      return;
    }
  }
  vl(n, t, u, d, y, x, b, w, l, c, h + 1), vl(b, w, v, _, g, m, o, a, l, c, h + 1);
}
const u_ = 8, d_ = 11920929e-14, f_ = 1;
function p_(n, t, e, s, i, r, o, a) {
  const c = Math.min(
    0.99,
    // a value of 1.0 actually inverts smoothing, so we cap it at 0.99
    Math.max(0, a ?? zp.defaultOptions.bezierSmoothness)
  );
  let h = (f_ - c) / 1;
  return h *= h, m_(t, e, s, i, r, o, n, h), n;
}
function m_(n, t, e, s, i, r, o, a) {
  bl(o, n, t, e, s, i, r, a, 0), o.push(i, r);
}
function bl(n, t, e, s, i, r, o, a, l) {
  if (l > u_)
    return;
  const c = (t + s) / 2, h = (e + i) / 2, u = (s + r) / 2, d = (i + o) / 2, f = (c + u) / 2, p = (h + d) / 2;
  let g = r - t, m = o - e;
  const y = Math.abs((s - r) * m - (i - o) * g);
  if (y > d_) {
    if (y * y <= a * (g * g + m * m)) {
      n.push(f, p);
      return;
    }
  } else if (g = f - (t + r) / 2, m = p - (e + o) / 2, g * g + m * m <= a) {
    n.push(f, p);
    return;
  }
  bl(n, t, e, c, h, f, p, a, l + 1), bl(n, f, p, u, d, r, o, a, l + 1);
}
function Up(n, t, e, s, i, r, o, a) {
  let l = Math.abs(i - r);
  (!o && i > r || o && r > i) && (l = 2 * Math.PI - l), a || (a = Math.max(6, Math.floor(6 * Math.pow(s, 1 / 3) * (l / Math.PI)))), a = Math.max(a, 3);
  let c = l / a, h = i;
  c *= o ? -1 : 1;
  for (let u = 0; u < a + 1; u++) {
    const d = Math.cos(h), f = Math.sin(h), p = t + d * s, g = e + f * s;
    n.push(p, g), h += c;
  }
}
function g_(n, t, e, s, i, r) {
  const o = n[n.length - 2], l = n[n.length - 1] - e, c = o - t, h = i - e, u = s - t, d = Math.abs(l * u - c * h);
  if (d < 1e-8 || r === 0) {
    (n[n.length - 2] !== t || n[n.length - 1] !== e) && n.push(t, e);
    return;
  }
  const f = l * l + c * c, p = h * h + u * u, g = l * h + c * u, m = r * Math.sqrt(f) / d, y = r * Math.sqrt(p) / d, x = m * g / f, v = y * g / p, _ = m * u + y * c, b = m * h + y * l, w = c * (y + x), S = l * (y + x), T = u * (m + v), k = h * (m + v), C = Math.atan2(S - b, w - _), M = Math.atan2(k - b, T - _);
  Up(
    n,
    _ + t,
    b + e,
    r,
    C,
    M,
    c * h > u * l
  );
}
const Hi = Math.PI * 2, qa = {
  centerX: 0,
  centerY: 0,
  ang1: 0,
  ang2: 0
}, Ua = ({ x: n, y: t }, e, s, i, r, o, a, l) => {
  n *= e, t *= s;
  const c = i * n - r * t, h = r * n + i * t;
  return l.x = c + o, l.y = h + a, l;
};
function y_(n, t) {
  const e = t === -1.5707963267948966 ? -0.551915024494 : 1.3333333333333333 * Math.tan(t / 4), s = t === 1.5707963267948966 ? 0.551915024494 : e, i = Math.cos(n), r = Math.sin(n), o = Math.cos(n + t), a = Math.sin(n + t);
  return [
    {
      x: i - r * s,
      y: r + i * s
    },
    {
      x: o + a * s,
      y: a - o * s
    },
    {
      x: o,
      y: a
    }
  ];
}
const Pu = (n, t, e, s) => {
  const i = n * s - t * e < 0 ? -1 : 1;
  let r = n * e + t * s;
  return r > 1 && (r = 1), r < -1 && (r = -1), i * Math.acos(r);
}, x_ = (n, t, e, s, i, r, o, a, l, c, h, u, d) => {
  const f = Math.pow(i, 2), p = Math.pow(r, 2), g = Math.pow(h, 2), m = Math.pow(u, 2);
  let y = f * p - f * m - p * g;
  y < 0 && (y = 0), y /= f * m + p * g, y = Math.sqrt(y) * (o === a ? -1 : 1);
  const x = y * i / r * u, v = y * -r / i * h, _ = c * x - l * v + (n + e) / 2, b = l * x + c * v + (t + s) / 2, w = (h - x) / i, S = (u - v) / r, T = (-h - x) / i, k = (-u - v) / r, C = Pu(1, 0, w, S);
  let M = Pu(w, S, T, k);
  a === 0 && M > 0 && (M -= Hi), a === 1 && M < 0 && (M += Hi), d.centerX = _, d.centerY = b, d.ang1 = C, d.ang2 = M;
};
function __(n, t, e, s, i, r, o, a = 0, l = 0, c = 0) {
  if (r === 0 || o === 0)
    return;
  const h = Math.sin(a * Hi / 360), u = Math.cos(a * Hi / 360), d = u * (t - s) / 2 + h * (e - i) / 2, f = -h * (t - s) / 2 + u * (e - i) / 2;
  if (d === 0 && f === 0)
    return;
  r = Math.abs(r), o = Math.abs(o);
  const p = Math.pow(d, 2) / Math.pow(r, 2) + Math.pow(f, 2) / Math.pow(o, 2);
  p > 1 && (r *= Math.sqrt(p), o *= Math.sqrt(p)), x_(
    t,
    e,
    s,
    i,
    r,
    o,
    l,
    c,
    h,
    u,
    d,
    f,
    qa
  );
  let { ang1: g, ang2: m } = qa;
  const { centerX: y, centerY: x } = qa;
  let v = Math.abs(m) / (Hi / 4);
  Math.abs(1 - v) < 1e-7 && (v = 1);
  const _ = Math.max(Math.ceil(v), 1);
  m /= _;
  let b = n[n.length - 2], w = n[n.length - 1];
  const S = { x: 0, y: 0 };
  for (let T = 0; T < _; T++) {
    const k = y_(g, m), { x: C, y: M } = Ua(k[0], r, o, u, h, y, x, S), { x: A, y: I } = Ua(k[1], r, o, u, h, y, x, S), { x: F, y: R } = Ua(k[2], r, o, u, h, y, x, S);
    qp(
      n,
      b,
      w,
      C,
      M,
      A,
      I,
      F,
      R
    ), b = F, w = R, g += m;
  }
}
function v_(n, t, e) {
  const s = (o, a) => {
    const l = a.x - o.x, c = a.y - o.y, h = Math.sqrt(l * l + c * c), u = l / h, d = c / h;
    return { len: h, nx: u, ny: d };
  }, i = (o, a) => {
    o === 0 ? n.moveTo(a.x, a.y) : n.lineTo(a.x, a.y);
  };
  let r = t[t.length - 1];
  for (let o = 0; o < t.length; o++) {
    const a = t[o % t.length], l = a.radius ?? e;
    if (l <= 0) {
      i(o, a), r = a;
      continue;
    }
    const c = t[(o + 1) % t.length], h = s(a, r), u = s(a, c);
    if (h.len < 1e-4 || u.len < 1e-4) {
      i(o, a), r = a;
      continue;
    }
    let d = Math.asin(h.nx * u.ny - h.ny * u.nx), f = 1, p = !1;
    h.nx * u.nx - h.ny * -u.ny < 0 ? d < 0 ? d = Math.PI + d : (d = Math.PI - d, f = -1, p = !0) : d > 0 && (f = -1, p = !0);
    const g = d / 2;
    let m, y = Math.abs(
      Math.cos(g) * l / Math.sin(g)
    );
    y > Math.min(h.len / 2, u.len / 2) ? (y = Math.min(h.len / 2, u.len / 2), m = Math.abs(y * Math.sin(g) / Math.cos(g))) : m = l;
    const x = a.x + u.nx * y + -u.ny * m * f, v = a.y + u.ny * y + u.nx * m * f, _ = Math.atan2(h.ny, h.nx) + Math.PI / 2 * f, b = Math.atan2(u.ny, u.nx) - Math.PI / 2 * f;
    o === 0 && n.moveTo(
      x + Math.cos(_) * m,
      v + Math.sin(_) * m
    ), n.arc(x, v, m, _, b, p), r = a;
  }
}
function b_(n, t, e, s) {
  const i = (a, l) => Math.sqrt((a.x - l.x) ** 2 + (a.y - l.y) ** 2), r = (a, l, c) => ({
    x: a.x + (l.x - a.x) * c,
    y: a.y + (l.y - a.y) * c
  }), o = t.length;
  for (let a = 0; a < o; a++) {
    const l = t[(a + 1) % o], c = l.radius ?? e;
    if (c <= 0) {
      a === 0 ? n.moveTo(l.x, l.y) : n.lineTo(l.x, l.y);
      continue;
    }
    const h = t[a], u = t[(a + 2) % o], d = i(h, l);
    let f;
    if (d < 1e-4)
      f = l;
    else {
      const m = Math.min(d / 2, c);
      f = r(
        l,
        h,
        m / d
      );
    }
    const p = i(u, l);
    let g;
    if (p < 1e-4)
      g = l;
    else {
      const m = Math.min(p / 2, c);
      g = r(
        l,
        u,
        m / p
      );
    }
    a === 0 ? n.moveTo(f.x, f.y) : n.lineTo(f.x, f.y), n.quadraticCurveTo(l.x, l.y, g.x, g.y, s);
  }
}
const w_ = new Dt();
class S_ {
  constructor(t) {
    this.shapePrimitives = [], this._currentPoly = null, this._bounds = new Ye(), this._graphicsPath2D = t, this.signed = t.checkForHoles;
  }
  /**
   * Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
   * @param x - The x-coordinate for the starting point.
   * @param y - The y-coordinate for the starting point.
   * @returns The instance of the current object for chaining.
   */
  moveTo(t, e) {
    return this.startPoly(t, e), this;
  }
  /**
   * Connects the current point to a new point with a straight line. This method updates the current path.
   * @param x - The x-coordinate of the new point to connect to.
   * @param y - The y-coordinate of the new point to connect to.
   * @returns The instance of the current object for chaining.
   */
  lineTo(t, e) {
    this._ensurePoly();
    const s = this._currentPoly.points, i = s[s.length - 2], r = s[s.length - 1];
    return (i !== t || r !== e) && s.push(t, e), this;
  }
  /**
   * Adds an arc to the path. The arc is centered at (x, y)
   *  position with radius `radius` starting at `startAngle` and ending at `endAngle`.
   * @param x - The x-coordinate of the arc's center.
   * @param y - The y-coordinate of the arc's center.
   * @param radius - The radius of the arc.
   * @param startAngle - The starting angle of the arc, in radians.
   * @param endAngle - The ending angle of the arc, in radians.
   * @param counterclockwise - Specifies whether the arc should be drawn in the anticlockwise direction. False by default.
   * @returns The instance of the current object for chaining.
   */
  arc(t, e, s, i, r, o) {
    this._ensurePoly(!1);
    const a = this._currentPoly.points;
    return Up(a, t, e, s, i, r, o), this;
  }
  /**
   * Adds an arc to the path with the arc tangent to the line joining two specified points.
   * The arc radius is specified by `radius`.
   * @param x1 - The x-coordinate of the first point.
   * @param y1 - The y-coordinate of the first point.
   * @param x2 - The x-coordinate of the second point.
   * @param y2 - The y-coordinate of the second point.
   * @param radius - The radius of the arc.
   * @returns The instance of the current object for chaining.
   */
  arcTo(t, e, s, i, r) {
    this._ensurePoly();
    const o = this._currentPoly.points;
    return g_(o, t, e, s, i, r), this;
  }
  /**
   * Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
   * @param rx - The x-radius of the ellipse.
   * @param ry - The y-radius of the ellipse.
   * @param xAxisRotation - The rotation of the ellipse's x-axis relative
   * to the x-axis of the coordinate system, in degrees.
   * @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
   * @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
   * @param x - The x-coordinate of the arc's end point.
   * @param y - The y-coordinate of the arc's end point.
   * @returns The instance of the current object for chaining.
   */
  arcToSvg(t, e, s, i, r, o, a) {
    const l = this._currentPoly.points;
    return __(
      l,
      this._currentPoly.lastX,
      this._currentPoly.lastY,
      o,
      a,
      t,
      e,
      s,
      i,
      r
    ), this;
  }
  /**
   * Adds a cubic Bezier curve to the path.
   * It requires three points: the first two are control points and the third one is the end point.
   * The starting point is the last point in the current path.
   * @param cp1x - The x-coordinate of the first control point.
   * @param cp1y - The y-coordinate of the first control point.
   * @param cp2x - The x-coordinate of the second control point.
   * @param cp2y - The y-coordinate of the second control point.
   * @param x - The x-coordinate of the end point.
   * @param y - The y-coordinate of the end point.
   * @param smoothness - Optional parameter to adjust the smoothness of the curve.
   * @returns The instance of the current object for chaining.
   */
  bezierCurveTo(t, e, s, i, r, o, a) {
    this._ensurePoly();
    const l = this._currentPoly;
    return qp(
      this._currentPoly.points,
      l.lastX,
      l.lastY,
      t,
      e,
      s,
      i,
      r,
      o,
      a
    ), this;
  }
  /**
   * Adds a quadratic curve to the path. It requires two points: the control point and the end point.
   * The starting point is the last point in the current path.
   * @param cp1x - The x-coordinate of the control point.
   * @param cp1y - The y-coordinate of the control point.
   * @param x - The x-coordinate of the end point.
   * @param y - The y-coordinate of the end point.
   * @param smoothing - Optional parameter to adjust the smoothness of the curve.
   * @returns The instance of the current object for chaining.
   */
  quadraticCurveTo(t, e, s, i, r) {
    this._ensurePoly();
    const o = this._currentPoly;
    return p_(
      this._currentPoly.points,
      o.lastX,
      o.lastY,
      t,
      e,
      s,
      i,
      r
    ), this;
  }
  /**
   * Closes the current path by drawing a straight line back to the start.
   * If the shape is already closed or there are no points in the path, this method does nothing.
   * @returns The instance of the current object for chaining.
   */
  closePath() {
    return this.endPoly(!0), this;
  }
  /**
   * Adds another path to the current path. This method allows for the combination of multiple paths into one.
   * @param path - The `GraphicsPath` object representing the path to add.
   * @param transform - An optional `Matrix` object to apply a transformation to the path before adding it.
   * @returns The instance of the current object for chaining.
   */
  addPath(t, e) {
    this.endPoly(), e && !e.isIdentity() && (t = t.clone(!0), t.transform(e));
    const s = this.shapePrimitives, i = s.length;
    for (let r = 0; r < t.instructions.length; r++) {
      const o = t.instructions[r];
      this[o.action](...o.data);
    }
    if (t.checkForHoles && s.length - i > 1) {
      let r = null;
      for (let o = i; o < s.length; o++) {
        const a = s[o];
        if (a.shape.type === "polygon") {
          const l = a.shape, c = r?.shape;
          c && c.containsPolygon(l) ? (r.holes || (r.holes = []), r.holes.push(a), s.copyWithin(o, o + 1), s.length--, o--) : r = a;
        }
      }
    }
    return this;
  }
  /**
   * Finalizes the drawing of the current path. Optionally, it can close the path.
   * @param closePath - A boolean indicating whether to close the path after finishing. False by default.
   */
  finish(t = !1) {
    this.endPoly(t);
  }
  /**
   * Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
   * @param x - The x-coordinate of the top-left corner of the rectangle.
   * @param y - The y-coordinate of the top-left corner of the rectangle.
   * @param w - The width of the rectangle.
   * @param h - The height of the rectangle.
   * @param transform - An optional `Matrix` object to apply a transformation to the rectangle.
   * @returns The instance of the current object for chaining.
   */
  rect(t, e, s, i, r) {
    return this.drawShape(new Dt(t, e, s, i), r), this;
  }
  /**
   * Draws a circle shape. This method adds a new circle path to the current drawing.
   * @param x - The x-coordinate of the center of the circle.
   * @param y - The y-coordinate of the center of the circle.
   * @param radius - The radius of the circle.
   * @param transform - An optional `Matrix` object to apply a transformation to the circle.
   * @returns The instance of the current object for chaining.
   */
  circle(t, e, s, i) {
    return this.drawShape(new Jl(t, e, s), i), this;
  }
  /**
   * Draws a polygon shape. This method allows for the creation of complex polygons by specifying a sequence of points.
   * @param points - An array of numbers, or or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
   * representing the x and y coordinates of the polygon's vertices, in sequence.
   * @param close - A boolean indicating whether to close the polygon path. True by default.
   * @param transform - An optional `Matrix` object to apply a transformation to the polygon.
   * @returns The instance of the current object for chaining.
   */
  poly(t, e, s) {
    const i = new $i(t);
    return i.closePath = e, this.drawShape(i, s), this;
  }
  /**
   * Draws a regular polygon with a specified number of sides. All sides and angles are equal.
   * @param x - The x-coordinate of the center of the polygon.
   * @param y - The y-coordinate of the center of the polygon.
   * @param radius - The radius of the circumscribed circle of the polygon.
   * @param sides - The number of sides of the polygon. Must be 3 or more.
   * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
   * @param transform - An optional `Matrix` object to apply a transformation to the polygon.
   * @returns The instance of the current object for chaining.
   */
  regularPoly(t, e, s, i, r = 0, o) {
    i = Math.max(i | 0, 3);
    const a = -1 * Math.PI / 2 + r, l = Math.PI * 2 / i, c = [];
    for (let h = 0; h < i; h++) {
      const u = a - h * l;
      c.push(
        t + s * Math.cos(u),
        e + s * Math.sin(u)
      );
    }
    return this.poly(c, !0, o), this;
  }
  /**
   * Draws a polygon with rounded corners.
   * Similar to `regularPoly` but with the ability to round the corners of the polygon.
   * @param x - The x-coordinate of the center of the polygon.
   * @param y - The y-coordinate of the center of the polygon.
   * @param radius - The radius of the circumscribed circle of the polygon.
   * @param sides - The number of sides of the polygon. Must be 3 or more.
   * @param corner - The radius of the rounding of the corners.
   * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
   * @param smoothness - Optional parameter to adjust the smoothness of the rounding.
   * @returns The instance of the current object for chaining.
   */
  roundPoly(t, e, s, i, r, o = 0, a) {
    if (i = Math.max(i | 0, 3), r <= 0)
      return this.regularPoly(t, e, s, i, o);
    const l = s * Math.sin(Math.PI / i) - 1e-3;
    r = Math.min(r, l);
    const c = -1 * Math.PI / 2 + o, h = Math.PI * 2 / i, u = (i - 2) * Math.PI / i / 2;
    for (let d = 0; d < i; d++) {
      const f = d * h + c, p = t + s * Math.cos(f), g = e + s * Math.sin(f), m = f + Math.PI + u, y = f - Math.PI - u, x = p + r * Math.cos(m), v = g + r * Math.sin(m), _ = p + r * Math.cos(y), b = g + r * Math.sin(y);
      d === 0 ? this.moveTo(x, v) : this.lineTo(x, v), this.quadraticCurveTo(p, g, _, b, a);
    }
    return this.closePath();
  }
  /**
   * Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
   * Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
   * @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
   * A minimum of 3 points is required.
   * @param radius - The default radius for the corners.
   * This radius is applied to all corners unless overridden in `points`.
   * @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
   *  method instead of an arc method. Defaults to false.
   * @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
   * Higher values make the curve smoother.
   * @returns The instance of the current object for chaining.
   */
  roundShape(t, e, s = !1, i) {
    return t.length < 3 ? this : (s ? b_(this, t, e, i) : v_(this, t, e), this.closePath());
  }
  /**
   * Draw Rectangle with fillet corners. This is much like rounded rectangle
   * however it support negative numbers as well for the corner radius.
   * @param x - Upper left corner of rect
   * @param y - Upper right corner of rect
   * @param width - Width of rect
   * @param height - Height of rect
   * @param fillet - accept negative or positive values
   */
  filletRect(t, e, s, i, r) {
    if (r === 0)
      return this.rect(t, e, s, i);
    const o = Math.min(s, i) / 2, a = Math.min(o, Math.max(-o, r)), l = t + s, c = e + i, h = a < 0 ? -a : 0, u = Math.abs(a);
    return this.moveTo(t, e + u).arcTo(t + h, e + h, t + u, e, u).lineTo(l - u, e).arcTo(l - h, e + h, l, e + u, u).lineTo(l, c - u).arcTo(l - h, c - h, t + s - u, c, u).lineTo(t + u, c).arcTo(t + h, c - h, t, c - u, u).closePath();
  }
  /**
   * Draw Rectangle with chamfer corners. These are angled corners.
   * @param x - Upper left corner of rect
   * @param y - Upper right corner of rect
   * @param width - Width of rect
   * @param height - Height of rect
   * @param chamfer - non-zero real number, size of corner cutout
   * @param transform
   */
  chamferRect(t, e, s, i, r, o) {
    if (r <= 0)
      return this.rect(t, e, s, i);
    const a = Math.min(r, Math.min(s, i) / 2), l = t + s, c = e + i, h = [
      t + a,
      e,
      l - a,
      e,
      l,
      e + a,
      l,
      c - a,
      l - a,
      c,
      t + a,
      c,
      t,
      c - a,
      t,
      e + a
    ];
    for (let u = h.length - 1; u >= 2; u -= 2)
      h[u] === h[u - 2] && h[u - 1] === h[u - 3] && h.splice(u - 1, 2);
    return this.poly(h, !0, o);
  }
  /**
   * Draws an ellipse at the specified location and with the given x and y radii.
   * An optional transformation can be applied, allowing for rotation, scaling, and translation.
   * @param x - The x-coordinate of the center of the ellipse.
   * @param y - The y-coordinate of the center of the ellipse.
   * @param radiusX - The horizontal radius of the ellipse.
   * @param radiusY - The vertical radius of the ellipse.
   * @param transform - An optional `Matrix` object to apply a transformation to the ellipse. This can include rotations.
   * @returns The instance of the current object for chaining.
   */
  ellipse(t, e, s, i, r) {
    return this.drawShape(new tc(t, e, s, i), r), this;
  }
  /**
   * Draws a rectangle with rounded corners.
   * The corner radius can be specified to determine how rounded the corners should be.
   * An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
   * @param x - The x-coordinate of the top-left corner of the rectangle.
   * @param y - The y-coordinate of the top-left corner of the rectangle.
   * @param w - The width of the rectangle.
   * @param h - The height of the rectangle.
   * @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
   * @param transform - An optional `Matrix` object to apply a transformation to the rectangle.
   * @returns The instance of the current object for chaining.
   */
  roundRect(t, e, s, i, r, o) {
    return this.drawShape(new ec(t, e, s, i, r), o), this;
  }
  /**
   * Draws a given shape on the canvas.
   * This is a generic method that can draw any type of shape specified by the `ShapePrimitive` parameter.
   * An optional transformation matrix can be applied to the shape, allowing for complex transformations.
   * @param shape - The shape to draw, defined as a `ShapePrimitive` object.
   * @param matrix - An optional `Matrix` for transforming the shape. This can include rotations,
   * scaling, and translations.
   * @returns The instance of the current object for chaining.
   */
  drawShape(t, e) {
    return this.endPoly(), this.shapePrimitives.push({ shape: t, transform: e }), this;
  }
  /**
   * Starts a new polygon path from the specified starting point.
   * This method initializes a new polygon or ends the current one if it exists.
   * @param x - The x-coordinate of the starting point of the new polygon.
   * @param y - The y-coordinate of the starting point of the new polygon.
   * @returns The instance of the current object for chaining.
   */
  startPoly(t, e) {
    let s = this._currentPoly;
    return s && this.endPoly(), s = new $i(), s.points.push(t, e), this._currentPoly = s, this;
  }
  /**
   * Ends the current polygon path. If `closePath` is set to true,
   * the path is closed by connecting the last point to the first one.
   * This method finalizes the current polygon and prepares it for drawing or adding to the shape primitives.
   * @param closePath - A boolean indicating whether to close the polygon by connecting the last point
   *  back to the starting point. False by default.
   * @returns The instance of the current object for chaining.
   */
  endPoly(t = !1) {
    const e = this._currentPoly;
    return e && e.points.length > 2 && (e.closePath = t, this.shapePrimitives.push({ shape: e })), this._currentPoly = null, this;
  }
  _ensurePoly(t = !0) {
    if (!this._currentPoly && (this._currentPoly = new $i(), t)) {
      const e = this.shapePrimitives[this.shapePrimitives.length - 1];
      if (e) {
        let s = e.shape.x, i = e.shape.y;
        if (e.transform && !e.transform.isIdentity()) {
          const r = e.transform, o = s;
          s = r.a * s + r.c * i + r.tx, i = r.b * o + r.d * i + r.ty;
        }
        this._currentPoly.points.push(s, i);
      } else
        this._currentPoly.points.push(0, 0);
    }
  }
  /** Builds the path. */
  buildPath() {
    const t = this._graphicsPath2D;
    this.shapePrimitives.length = 0, this._currentPoly = null;
    for (let e = 0; e < t.instructions.length; e++) {
      const s = t.instructions[e];
      this[s.action](...s.data);
    }
    this.finish();
  }
  /** Gets the bounds of the path. */
  get bounds() {
    const t = this._bounds;
    t.clear();
    const e = this.shapePrimitives;
    for (let s = 0; s < e.length; s++) {
      const i = e[s], r = i.shape.getBounds(w_);
      i.transform ? t.addRect(r, i.transform) : t.addRect(r);
    }
    return t;
  }
}
class Kn {
  /**
   * Creates a `GraphicsPath` instance optionally from an SVG path string or an array of `PathInstruction`.
   * @param instructions - An SVG path string or an array of `PathInstruction` objects.
   * @param signed
   */
  constructor(t, e = !1) {
    this.instructions = [], this.uid = Ot("graphicsPath"), this._dirty = !0, this.checkForHoles = e, typeof t == "string" ? $0(t, this) : this.instructions = t?.slice() ?? [];
  }
  /**
   * Provides access to the internal shape path, ensuring it is up-to-date with the current instructions.
   * @returns The `ShapePath` instance associated with this `GraphicsPath`.
   */
  get shapePath() {
    return this._shapePath || (this._shapePath = new S_(this)), this._dirty && (this._dirty = !1, this._shapePath.buildPath()), this._shapePath;
  }
  /**
   * Adds another `GraphicsPath` to this path, optionally applying a transformation.
   * @param path - The `GraphicsPath` to add.
   * @param transform - An optional transformation to apply to the added path.
   * @returns The instance of the current object for chaining.
   */
  addPath(t, e) {
    return t = t.clone(), this.instructions.push({ action: "addPath", data: [t, e] }), this._dirty = !0, this;
  }
  arc(...t) {
    return this.instructions.push({ action: "arc", data: t }), this._dirty = !0, this;
  }
  arcTo(...t) {
    return this.instructions.push({ action: "arcTo", data: t }), this._dirty = !0, this;
  }
  arcToSvg(...t) {
    return this.instructions.push({ action: "arcToSvg", data: t }), this._dirty = !0, this;
  }
  bezierCurveTo(...t) {
    return this.instructions.push({ action: "bezierCurveTo", data: t }), this._dirty = !0, this;
  }
  /**
   * Adds a cubic Bezier curve to the path.
   * It requires two points: the second control point and the end point. The first control point is assumed to be
   * The starting point is the last point in the current path.
   * @param cp2x - The x-coordinate of the second control point.
   * @param cp2y - The y-coordinate of the second control point.
   * @param x - The x-coordinate of the end point.
   * @param y - The y-coordinate of the end point.
   * @param smoothness - Optional parameter to adjust the smoothness of the curve.
   * @returns The instance of the current object for chaining.
   */
  bezierCurveToShort(t, e, s, i, r) {
    const o = this.instructions[this.instructions.length - 1], a = this.getLastPoint(se.shared);
    let l = 0, c = 0;
    if (!o || o.action !== "bezierCurveTo")
      l = a.x, c = a.y;
    else {
      l = o.data[2], c = o.data[3];
      const h = a.x, u = a.y;
      l = h + (h - l), c = u + (u - c);
    }
    return this.instructions.push({ action: "bezierCurveTo", data: [l, c, t, e, s, i, r] }), this._dirty = !0, this;
  }
  /**
   * Closes the current path by drawing a straight line back to the start.
   * If the shape is already closed or there are no points in the path, this method does nothing.
   * @returns The instance of the current object for chaining.
   */
  closePath() {
    return this.instructions.push({ action: "closePath", data: [] }), this._dirty = !0, this;
  }
  ellipse(...t) {
    return this.instructions.push({ action: "ellipse", data: t }), this._dirty = !0, this;
  }
  lineTo(...t) {
    return this.instructions.push({ action: "lineTo", data: t }), this._dirty = !0, this;
  }
  moveTo(...t) {
    return this.instructions.push({ action: "moveTo", data: t }), this;
  }
  quadraticCurveTo(...t) {
    return this.instructions.push({ action: "quadraticCurveTo", data: t }), this._dirty = !0, this;
  }
  /**
   * Adds a quadratic curve to the path. It uses the previous point as the control point.
   * @param x - The x-coordinate of the end point.
   * @param y - The y-coordinate of the end point.
   * @param smoothness - Optional parameter to adjust the smoothness of the curve.
   * @returns The instance of the current object for chaining.
   */
  quadraticCurveToShort(t, e, s) {
    const i = this.instructions[this.instructions.length - 1], r = this.getLastPoint(se.shared);
    let o = 0, a = 0;
    if (!i || i.action !== "quadraticCurveTo")
      o = r.x, a = r.y;
    else {
      o = i.data[0], a = i.data[1];
      const l = r.x, c = r.y;
      o = l + (l - o), a = c + (c - a);
    }
    return this.instructions.push({ action: "quadraticCurveTo", data: [o, a, t, e, s] }), this._dirty = !0, this;
  }
  /**
   * Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
   * @param x - The x-coordinate of the top-left corner of the rectangle.
   * @param y - The y-coordinate of the top-left corner of the rectangle.
   * @param w - The width of the rectangle.
   * @param h - The height of the rectangle.
   * @param transform - An optional `Matrix` object to apply a transformation to the rectangle.
   * @returns The instance of the current object for chaining.
   */
  rect(t, e, s, i, r) {
    return this.instructions.push({ action: "rect", data: [t, e, s, i, r] }), this._dirty = !0, this;
  }
  /**
   * Draws a circle shape. This method adds a new circle path to the current drawing.
   * @param x - The x-coordinate of the center of the circle.
   * @param y - The y-coordinate of the center of the circle.
   * @param radius - The radius of the circle.
   * @param transform - An optional `Matrix` object to apply a transformation to the circle.
   * @returns The instance of the current object for chaining.
   */
  circle(t, e, s, i) {
    return this.instructions.push({ action: "circle", data: [t, e, s, i] }), this._dirty = !0, this;
  }
  roundRect(...t) {
    return this.instructions.push({ action: "roundRect", data: t }), this._dirty = !0, this;
  }
  poly(...t) {
    return this.instructions.push({ action: "poly", data: t }), this._dirty = !0, this;
  }
  regularPoly(...t) {
    return this.instructions.push({ action: "regularPoly", data: t }), this._dirty = !0, this;
  }
  roundPoly(...t) {
    return this.instructions.push({ action: "roundPoly", data: t }), this._dirty = !0, this;
  }
  roundShape(...t) {
    return this.instructions.push({ action: "roundShape", data: t }), this._dirty = !0, this;
  }
  filletRect(...t) {
    return this.instructions.push({ action: "filletRect", data: t }), this._dirty = !0, this;
  }
  chamferRect(...t) {
    return this.instructions.push({ action: "chamferRect", data: t }), this._dirty = !0, this;
  }
  /**
   * Draws a star shape centered at a specified location. This method allows for the creation
   *  of stars with a variable number of points, outer radius, optional inner radius, and rotation.
   * The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
   * An optional transformation can be applied to scale, rotate, or translate the star as needed.
   * @param x - The x-coordinate of the center of the star.
   * @param y - The y-coordinate of the center of the star.
   * @param points - The number of points of the star.
   * @param radius - The outer radius of the star (distance from the center to the outer points).
   * @param innerRadius - Optional. The inner radius of the star
   * (distance from the center to the inner points between the outer points).
   * If not provided, defaults to half of the `radius`.
   * @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
   * Defaults to 0, meaning one point is directly upward.
   * @param transform - An optional `Matrix` object to apply a transformation to the star.
   * This can include rotations, scaling, and translations.
   * @returns The instance of the current object for chaining further drawing commands.
   */
  // eslint-disable-next-line max-len
  star(t, e, s, i, r, o, a) {
    r || (r = i / 2);
    const l = -1 * Math.PI / 2 + o, c = s * 2, h = Math.PI * 2 / c, u = [];
    for (let d = 0; d < c; d++) {
      const f = d % 2 ? r : i, p = d * h + l;
      u.push(
        t + f * Math.cos(p),
        e + f * Math.sin(p)
      );
    }
    return this.poly(u, !0, a), this;
  }
  /**
   * Creates a copy of the current `GraphicsPath` instance. This method supports both shallow and deep cloning.
   * A shallow clone copies the reference of the instructions array, while a deep clone creates a new array and
   * copies each instruction individually, ensuring that modifications to the instructions of the cloned `GraphicsPath`
   * do not affect the original `GraphicsPath` and vice versa.
   * @param deep - A boolean flag indicating whether the clone should be deep.
   * @returns A new `GraphicsPath` instance that is a clone of the current instance.
   */
  clone(t = !1) {
    const e = new Kn();
    if (e.checkForHoles = this.checkForHoles, !t)
      e.instructions = this.instructions.slice();
    else
      for (let s = 0; s < this.instructions.length; s++) {
        const i = this.instructions[s];
        e.instructions.push({ action: i.action, data: i.data.slice() });
      }
    return e;
  }
  clear() {
    return this.instructions.length = 0, this._dirty = !0, this;
  }
  /**
   * Applies a transformation matrix to all drawing instructions within the `GraphicsPath`.
   * This method enables the modification of the path's geometry according to the provided
   * transformation matrix, which can include translations, rotations, scaling, and skewing.
   *
   * Each drawing instruction in the path is updated to reflect the transformation,
   * ensuring the visual representation of the path is consistent with the applied matrix.
   *
   * Note: The transformation is applied directly to the coordinates and control points of the drawing instructions,
   * not to the path as a whole. This means the transformation's effects are baked into the individual instructions,
   * allowing for fine-grained control over the path's appearance.
   * @param matrix - A `Matrix` object representing the transformation to apply.
   * @returns The instance of the current object for chaining further operations.
   */
  transform(t) {
    if (t.isIdentity())
      return this;
    const e = t.a, s = t.b, i = t.c, r = t.d, o = t.tx, a = t.ty;
    let l = 0, c = 0, h = 0, u = 0, d = 0, f = 0, p = 0, g = 0;
    for (let m = 0; m < this.instructions.length; m++) {
      const y = this.instructions[m], x = y.data;
      switch (y.action) {
        case "moveTo":
        case "lineTo":
          l = x[0], c = x[1], x[0] = e * l + i * c + o, x[1] = s * l + r * c + a;
          break;
        case "bezierCurveTo":
          h = x[0], u = x[1], d = x[2], f = x[3], l = x[4], c = x[5], x[0] = e * h + i * u + o, x[1] = s * h + r * u + a, x[2] = e * d + i * f + o, x[3] = s * d + r * f + a, x[4] = e * l + i * c + o, x[5] = s * l + r * c + a;
          break;
        case "quadraticCurveTo":
          h = x[0], u = x[1], l = x[2], c = x[3], x[0] = e * h + i * u + o, x[1] = s * h + r * u + a, x[2] = e * l + i * c + o, x[3] = s * l + r * c + a;
          break;
        case "arcToSvg":
          l = x[5], c = x[6], p = x[0], g = x[1], x[0] = e * p + i * g, x[1] = s * p + r * g, x[5] = e * l + i * c + o, x[6] = s * l + r * c + a;
          break;
        case "circle":
          x[4] = Ii(x[3], t);
          break;
        case "rect":
          x[4] = Ii(x[4], t);
          break;
        case "ellipse":
          x[8] = Ii(x[8], t);
          break;
        case "roundRect":
          x[5] = Ii(x[5], t);
          break;
        case "addPath":
          x[0].transform(t);
          break;
        case "poly":
          x[2] = Ii(x[2], t);
          break;
        default:
          Ht("unknown transform action", y.action);
          break;
      }
    }
    return this._dirty = !0, this;
  }
  get bounds() {
    return this.shapePath.bounds;
  }
  /**
   * Retrieves the last point from the current drawing instructions in the `GraphicsPath`.
   * This method is useful for operations that depend on the path's current endpoint,
   * such as connecting subsequent shapes or paths. It supports various drawing instructions,
   * ensuring the last point's position is accurately determined regardless of the path's complexity.
   *
   * If the last instruction is a `closePath`, the method iterates backward through the instructions
   *  until it finds an actionable instruction that defines a point (e.g., `moveTo`, `lineTo`,
   * `quadraticCurveTo`, etc.). For compound paths added via `addPath`, it recursively retrieves
   * the last point from the nested path.
   * @param out - A `Point` object where the last point's coordinates will be stored.
   * This object is modified directly to contain the result.
   * @returns The `Point` object containing the last point's coordinates.
   */
  getLastPoint(t) {
    let e = this.instructions.length - 1, s = this.instructions[e];
    if (!s)
      return t.x = 0, t.y = 0, t;
    for (; s.action === "closePath"; ) {
      if (e--, e < 0)
        return t.x = 0, t.y = 0, t;
      s = this.instructions[e];
    }
    switch (s.action) {
      case "moveTo":
      case "lineTo":
        t.x = s.data[0], t.y = s.data[1];
        break;
      case "quadraticCurveTo":
        t.x = s.data[2], t.y = s.data[3];
        break;
      case "bezierCurveTo":
        t.x = s.data[4], t.y = s.data[5];
        break;
      case "arc":
      case "arcToSvg":
        t.x = s.data[5], t.y = s.data[6];
        break;
      case "addPath":
        s.data[0].getLastPoint(t);
        break;
    }
    return t;
  }
}
function Ii(n, t) {
  return n ? n.prepend(t) : t.clone();
}
function Et(n, t, e) {
  const s = n.getAttribute(t);
  return s ? Number(s) : e;
}
function T_(n, t) {
  const e = n.querySelectorAll("defs");
  for (let s = 0; s < e.length; s++) {
    const i = e[s];
    for (let r = 0; r < i.children.length; r++) {
      const o = i.children[r];
      switch (o.nodeName.toLowerCase()) {
        case "lineargradient":
          t.defs[o.id] = M_(o);
          break;
        case "radialgradient":
          t.defs[o.id] = k_();
          break;
      }
    }
  }
}
function M_(n) {
  const t = Et(n, "x1", 0), e = Et(n, "y1", 0), s = Et(n, "x2", 1), i = Et(n, "y2", 0), r = n.getAttribute("gradientUnits") || "objectBoundingBox", o = new Is(
    t,
    e,
    s,
    i,
    r === "objectBoundingBox" ? "local" : "global"
  );
  for (let a = 0; a < n.children.length; a++) {
    const l = n.children[a], c = Et(l, "offset", 0), h = Bt.shared.setValue(l.getAttribute("stop-color")).toNumber();
    o.addColorStop(c, h);
  }
  return o;
}
function k_(n) {
  return Ht("[SVG Parser] Radial gradients are not yet supported"), new Is(0, 0, 1, 0);
}
function Iu(n) {
  const t = n.match(/url\s*\(\s*['"]?\s*#([^'"\s)]+)\s*['"]?\s*\)/i);
  return t ? t[1] : "";
}
const Fu = {
  // Fill properties
  fill: { type: "paint", default: 0 },
  // Fill color/gradient
  "fill-opacity": { type: "number", default: 1 },
  // Fill transparency
  // Stroke properties
  stroke: { type: "paint", default: 0 },
  // Stroke color/gradient
  "stroke-width": { type: "number", default: 1 },
  // Width of stroke
  "stroke-opacity": { type: "number", default: 1 },
  // Stroke transparency
  "stroke-linecap": { type: "string", default: "butt" },
  // End cap style: butt, round, square
  "stroke-linejoin": { type: "string", default: "miter" },
  // Join style: miter, round, bevel
  "stroke-miterlimit": { type: "number", default: 10 },
  // Limit on miter join sharpness
  "stroke-dasharray": { type: "string", default: "none" },
  // Dash pattern
  "stroke-dashoffset": { type: "number", default: 0 },
  // Offset for dash pattern
  // Global properties
  opacity: { type: "number", default: 1 }
  // Overall opacity
};
function Gp(n, t) {
  const e = n.getAttribute("style"), s = {}, i = {}, r = {
    strokeStyle: s,
    fillStyle: i,
    useFill: !1,
    useStroke: !1
  };
  for (const o in Fu) {
    const a = n.getAttribute(o);
    a && Ru(t, r, o, a.trim());
  }
  if (e) {
    const o = e.split(";");
    for (let a = 0; a < o.length; a++) {
      const l = o[a].trim(), [c, h] = l.split(":");
      Fu[c] && Ru(t, r, c, h.trim());
    }
  }
  return {
    strokeStyle: r.useStroke ? s : null,
    fillStyle: r.useFill ? i : null,
    useFill: r.useFill,
    useStroke: r.useStroke
  };
}
function Ru(n, t, e, s) {
  switch (e) {
    case "stroke":
      if (s !== "none") {
        if (s.startsWith("url(")) {
          const i = Iu(s);
          t.strokeStyle.fill = n.defs[i];
        } else
          t.strokeStyle.color = Bt.shared.setValue(s).toNumber();
        t.useStroke = !0;
      }
      break;
    case "stroke-width":
      t.strokeStyle.width = Number(s);
      break;
    case "fill":
      if (s !== "none") {
        if (s.startsWith("url(")) {
          const i = Iu(s);
          t.fillStyle.fill = n.defs[i];
        } else
          t.fillStyle.color = Bt.shared.setValue(s).toNumber();
        t.useFill = !0;
      }
      break;
    case "fill-opacity":
      t.fillStyle.alpha = Number(s);
      break;
    case "stroke-opacity":
      t.strokeStyle.alpha = Number(s);
      break;
    case "opacity":
      t.fillStyle.alpha = Number(s), t.strokeStyle.alpha = Number(s);
      break;
  }
}
function C_(n, t) {
  if (typeof n == "string") {
    const o = document.createElement("div");
    o.innerHTML = n.trim(), n = o.querySelector("svg");
  }
  const e = {
    context: t,
    defs: {},
    path: new Kn()
  };
  T_(n, e);
  const s = n.children, { fillStyle: i, strokeStyle: r } = Gp(n, e);
  for (let o = 0; o < s.length; o++) {
    const a = s[o];
    a.nodeName.toLowerCase() !== "defs" && Wp(a, e, i, r);
  }
  return t;
}
function Wp(n, t, e, s) {
  const i = n.children, { fillStyle: r, strokeStyle: o } = Gp(n, t);
  r && e ? e = { ...e, ...r } : r && (e = r), o && s ? s = { ...s, ...o } : o && (s = o);
  const a = !e && !s;
  a && (e = { color: 0 });
  let l, c, h, u, d, f, p, g, m, y, x, v, _, b, w, S, T;
  switch (n.nodeName.toLowerCase()) {
    case "path":
      b = n.getAttribute("d"), n.getAttribute("fill-rule") === "evenodd" && Ht("SVG Evenodd fill rule not supported, your svg may render incorrectly"), w = new Kn(b, !0), t.context.path(w), e && t.context.fill(e), s && t.context.stroke(s);
      break;
    case "circle":
      p = Et(n, "cx", 0), g = Et(n, "cy", 0), m = Et(n, "r", 0), t.context.ellipse(p, g, m, m), e && t.context.fill(e), s && t.context.stroke(s);
      break;
    case "rect":
      l = Et(n, "x", 0), c = Et(n, "y", 0), S = Et(n, "width", 0), T = Et(n, "height", 0), y = Et(n, "rx", 0), x = Et(n, "ry", 0), y || x ? t.context.roundRect(l, c, S, T, y || x) : t.context.rect(l, c, S, T), e && t.context.fill(e), s && t.context.stroke(s);
      break;
    case "ellipse":
      p = Et(n, "cx", 0), g = Et(n, "cy", 0), y = Et(n, "rx", 0), x = Et(n, "ry", 0), t.context.beginPath(), t.context.ellipse(p, g, y, x), e && t.context.fill(e), s && t.context.stroke(s);
      break;
    case "line":
      h = Et(n, "x1", 0), u = Et(n, "y1", 0), d = Et(n, "x2", 0), f = Et(n, "y2", 0), t.context.beginPath(), t.context.moveTo(h, u), t.context.lineTo(d, f), s && t.context.stroke(s);
      break;
    case "polygon":
      _ = n.getAttribute("points"), v = _.match(/\d+/g).map((k) => parseInt(k, 10)), t.context.poly(v, !0), e && t.context.fill(e), s && t.context.stroke(s);
      break;
    case "polyline":
      _ = n.getAttribute("points"), v = _.match(/\d+/g).map((k) => parseInt(k, 10)), t.context.poly(v, !1), s && t.context.stroke(s);
      break;
    case "g":
    case "svg":
      break;
    default: {
      Ht(`[SVG parser] <${n.nodeName}> elements unsupported`);
      break;
    }
  }
  a && (e = null);
  for (let k = 0; k < i.length; k++)
    Wp(i[k], t, e, s);
}
function A_(n) {
  return Bt.isColorLike(n);
}
function Du(n) {
  return n instanceof Zo;
}
function Ou(n) {
  return n instanceof Is;
}
function E_(n) {
  return n instanceof rt;
}
function P_(n, t, e) {
  const s = Bt.shared.setValue(t ?? 0);
  return n.color = s.toNumber(), n.alpha = s.alpha === 1 ? e.alpha : s.alpha, n.texture = rt.WHITE, { ...e, ...n };
}
function I_(n, t, e) {
  return n.texture = t, { ...e, ...n };
}
function Nu(n, t, e) {
  return n.fill = t, n.color = 16777215, n.texture = t.texture, n.matrix = t.transform, { ...e, ...n };
}
function Lu(n, t, e) {
  return t.buildGradient(), n.fill = t, n.color = 16777215, n.texture = t.texture, n.matrix = t.transform, n.textureSpace = t.textureSpace, { ...e, ...n };
}
function F_(n, t) {
  const e = { ...t, ...n }, s = Bt.shared.setValue(e.color);
  return e.alpha *= s.alpha, e.color = s.toNumber(), e;
}
function gn(n, t) {
  if (n == null)
    return null;
  const e = {}, s = n;
  return A_(n) ? P_(e, n, t) : E_(n) ? I_(e, n, t) : Du(n) ? Nu(e, n, t) : Ou(n) ? Lu(e, n, t) : s.fill && Du(s.fill) ? Nu(s, s.fill, t) : s.fill && Ou(s.fill) ? Lu(s, s.fill, t) : F_(s, t);
}
function yo(n, t) {
  const { width: e, alignment: s, miterLimit: i, cap: r, join: o, pixelLine: a, ...l } = t, c = gn(n, l);
  return c ? {
    width: e,
    alignment: s,
    miterLimit: i,
    cap: r,
    join: o,
    pixelLine: a,
    ...c
  } : null;
}
const R_ = new se(), Vu = new nt(), nc = class os extends ps {
  constructor() {
    super(...arguments), this.uid = Ot("graphicsContext"), this.dirty = !0, this.batchMode = "auto", this.instructions = [], this._activePath = new Kn(), this._transform = new nt(), this._fillStyle = { ...os.defaultFillStyle }, this._strokeStyle = { ...os.defaultStrokeStyle }, this._stateStack = [], this._tick = 0, this._bounds = new Ye(), this._boundsDirty = !0;
  }
  /**
   * Creates a new GraphicsContext object that is a clone of this instance, copying all properties,
   * including the current drawing state, transformations, styles, and instructions.
   * @returns A new GraphicsContext instance with the same properties and state as this one.
   */
  clone() {
    const t = new os();
    return t.batchMode = this.batchMode, t.instructions = this.instructions.slice(), t._activePath = this._activePath.clone(), t._transform = this._transform.clone(), t._fillStyle = { ...this._fillStyle }, t._strokeStyle = { ...this._strokeStyle }, t._stateStack = this._stateStack.slice(), t._bounds = this._bounds.clone(), t._boundsDirty = !0, t;
  }
  /**
   * The current fill style of the graphics context. This can be a color, gradient, pattern, or a more complex style defined by a FillStyle object.
   */
  get fillStyle() {
    return this._fillStyle;
  }
  set fillStyle(t) {
    this._fillStyle = gn(t, os.defaultFillStyle);
  }
  /**
   * The current stroke style of the graphics context. Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
   */
  get strokeStyle() {
    return this._strokeStyle;
  }
  set strokeStyle(t) {
    this._strokeStyle = yo(t, os.defaultStrokeStyle);
  }
  /**
   * Sets the current fill style of the graphics context. The fill style can be a color, gradient,
   * pattern, or a more complex style defined by a FillStyle object.
   * @param style - The fill style to apply. This can be a simple color, a gradient or pattern object,
   *                or a FillStyle or ConvertedFillStyle object.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  setFillStyle(t) {
    return this._fillStyle = gn(t, os.defaultFillStyle), this;
  }
  /**
   * Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
   * encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
   * @param style - The stroke style to apply. Can be defined as a color, a gradient or pattern,
   *                or a StrokeStyle or ConvertedStrokeStyle object.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  setStrokeStyle(t) {
    return this._strokeStyle = gn(t, os.defaultStrokeStyle), this;
  }
  texture(t, e, s, i, r, o) {
    return this.instructions.push({
      action: "texture",
      data: {
        image: t,
        dx: s || 0,
        dy: i || 0,
        dw: r || t.frame.width,
        dh: o || t.frame.height,
        transform: this._transform.clone(),
        alpha: this._fillStyle.alpha,
        style: e ? Bt.shared.setValue(e).toNumber() : 16777215
      }
    }), this.onUpdate(), this;
  }
  /**
   * Resets the current path. Any previous path and its commands are discarded and a new path is
   * started. This is typically called before beginning a new shape or series of drawing commands.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  beginPath() {
    return this._activePath = new Kn(), this;
  }
  fill(t, e) {
    let s;
    const i = this.instructions[this.instructions.length - 1];
    return this._tick === 0 && i && i.action === "stroke" ? s = i.data.path : s = this._activePath.clone(), s ? (t != null && (e !== void 0 && typeof t == "number" && (ct(kt, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead"), t = { color: t, alpha: e }), this._fillStyle = gn(t, os.defaultFillStyle)), this.instructions.push({
      action: "fill",
      // TODO copy fill style!
      data: { style: this.fillStyle, path: s }
    }), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : this;
  }
  _initNextPathLocation() {
    const { x: t, y: e } = this._activePath.getLastPoint(se.shared);
    this._activePath.clear(), this._activePath.moveTo(t, e);
  }
  /**
   * Strokes the current path with the current stroke style. This method can take an optional
   * FillInput parameter to define the stroke's appearance, including its color, width, and other properties.
   * @param style - (Optional) The stroke style to apply. Can be defined as a simple color or a more complex style object. If omitted, uses the current stroke style.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  stroke(t) {
    let e;
    const s = this.instructions[this.instructions.length - 1];
    return this._tick === 0 && s && s.action === "fill" ? e = s.data.path : e = this._activePath.clone(), e ? (t != null && (this._strokeStyle = yo(t, os.defaultStrokeStyle)), this.instructions.push({
      action: "stroke",
      // TODO copy fill style!
      data: { style: this.strokeStyle, path: e }
    }), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : this;
  }
  /**
   * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
   * subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
   * fail to cut correctly!
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  cut() {
    for (let t = 0; t < 2; t++) {
      const e = this.instructions[this.instructions.length - 1 - t], s = this._activePath.clone();
      if (e && (e.action === "stroke" || e.action === "fill"))
        if (e.data.hole)
          e.data.hole.addPath(s);
        else {
          e.data.hole = s;
          break;
        }
    }
    return this._initNextPathLocation(), this;
  }
  /**
   * Adds an arc to the current path, which is centered at (x, y) with the specified radius,
   * starting and ending angles, and direction.
   * @param x - The x-coordinate of the arc's center.
   * @param y - The y-coordinate of the arc's center.
   * @param radius - The arc's radius.
   * @param startAngle - The starting angle, in radians.
   * @param endAngle - The ending angle, in radians.
   * @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise (false). Defaults to false.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  arc(t, e, s, i, r, o) {
    this._tick++;
    const a = this._transform;
    return this._activePath.arc(
      a.a * t + a.c * e + a.tx,
      a.b * t + a.d * e + a.ty,
      s,
      i,
      r,
      o
    ), this;
  }
  /**
   * Adds an arc to the current path with the given control points and radius, connected to the previous point
   * by a straight line if necessary.
   * @param x1 - The x-coordinate of the first control point.
   * @param y1 - The y-coordinate of the first control point.
   * @param x2 - The x-coordinate of the second control point.
   * @param y2 - The y-coordinate of the second control point.
   * @param radius - The arc's radius.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  arcTo(t, e, s, i, r) {
    this._tick++;
    const o = this._transform;
    return this._activePath.arcTo(
      o.a * t + o.c * e + o.tx,
      o.b * t + o.d * e + o.ty,
      o.a * s + o.c * i + o.tx,
      o.b * s + o.d * i + o.ty,
      r
    ), this;
  }
  /**
   * Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
   * @param rx - The x-radius of the ellipse.
   * @param ry - The y-radius of the ellipse.
   * @param xAxisRotation - The rotation of the ellipse's x-axis relative
   * to the x-axis of the coordinate system, in degrees.
   * @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
   * @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
   * @param x - The x-coordinate of the arc's end point.
   * @param y - The y-coordinate of the arc's end point.
   * @returns The instance of the current object for chaining.
   */
  arcToSvg(t, e, s, i, r, o, a) {
    this._tick++;
    const l = this._transform;
    return this._activePath.arcToSvg(
      t,
      e,
      s,
      // should we rotate this with transform??
      i,
      r,
      l.a * o + l.c * a + l.tx,
      l.b * o + l.d * a + l.ty
    ), this;
  }
  /**
   * Adds a cubic Bezier curve to the path.
   * It requires three points: the first two are control points and the third one is the end point.
   * The starting point is the last point in the current path.
   * @param cp1x - The x-coordinate of the first control point.
   * @param cp1y - The y-coordinate of the first control point.
   * @param cp2x - The x-coordinate of the second control point.
   * @param cp2y - The y-coordinate of the second control point.
   * @param x - The x-coordinate of the end point.
   * @param y - The y-coordinate of the end point.
   * @param smoothness - Optional parameter to adjust the smoothness of the curve.
   * @returns The instance of the current object for chaining.
   */
  bezierCurveTo(t, e, s, i, r, o, a) {
    this._tick++;
    const l = this._transform;
    return this._activePath.bezierCurveTo(
      l.a * t + l.c * e + l.tx,
      l.b * t + l.d * e + l.ty,
      l.a * s + l.c * i + l.tx,
      l.b * s + l.d * i + l.ty,
      l.a * r + l.c * o + l.tx,
      l.b * r + l.d * o + l.ty,
      a
    ), this;
  }
  /**
   * Closes the current path by drawing a straight line back to the start.
   * If the shape is already closed or there are no points in the path, this method does nothing.
   * @returns The instance of the current object for chaining.
   */
  closePath() {
    return this._tick++, this._activePath?.closePath(), this;
  }
  /**
   * Draws an ellipse at the specified location and with the given x and y radii.
   * An optional transformation can be applied, allowing for rotation, scaling, and translation.
   * @param x - The x-coordinate of the center of the ellipse.
   * @param y - The y-coordinate of the center of the ellipse.
   * @param radiusX - The horizontal radius of the ellipse.
   * @param radiusY - The vertical radius of the ellipse.
   * @returns The instance of the current object for chaining.
   */
  ellipse(t, e, s, i) {
    return this._tick++, this._activePath.ellipse(t, e, s, i, this._transform.clone()), this;
  }
  /**
   * Draws a circle shape. This method adds a new circle path to the current drawing.
   * @param x - The x-coordinate of the center of the circle.
   * @param y - The y-coordinate of the center of the circle.
   * @param radius - The radius of the circle.
   * @returns The instance of the current object for chaining.
   */
  circle(t, e, s) {
    return this._tick++, this._activePath.circle(t, e, s, this._transform.clone()), this;
  }
  /**
   * Adds another `GraphicsPath` to this path, optionally applying a transformation.
   * @param path - The `GraphicsPath` to add.
   * @returns The instance of the current object for chaining.
   */
  path(t) {
    return this._tick++, this._activePath.addPath(t, this._transform.clone()), this;
  }
  /**
   * Connects the current point to a new point with a straight line. This method updates the current path.
   * @param x - The x-coordinate of the new point to connect to.
   * @param y - The y-coordinate of the new point to connect to.
   * @returns The instance of the current object for chaining.
   */
  lineTo(t, e) {
    this._tick++;
    const s = this._transform;
    return this._activePath.lineTo(
      s.a * t + s.c * e + s.tx,
      s.b * t + s.d * e + s.ty
    ), this;
  }
  /**
   * Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
   * @param x - The x-coordinate for the starting point.
   * @param y - The y-coordinate for the starting point.
   * @returns The instance of the current object for chaining.
   */
  moveTo(t, e) {
    this._tick++;
    const s = this._transform, i = this._activePath.instructions, r = s.a * t + s.c * e + s.tx, o = s.b * t + s.d * e + s.ty;
    return i.length === 1 && i[0].action === "moveTo" ? (i[0].data[0] = r, i[0].data[1] = o, this) : (this._activePath.moveTo(
      r,
      o
    ), this);
  }
  /**
   * Adds a quadratic curve to the path. It requires two points: the control point and the end point.
   * The starting point is the last point in the current path.
   * @param cpx - The x-coordinate of the control point.
   * @param cpy - The y-coordinate of the control point.
   * @param x - The x-coordinate of the end point.
   * @param y - The y-coordinate of the end point.
   * @param smoothness - Optional parameter to adjust the smoothness of the curve.
   * @returns The instance of the current object for chaining.
   */
  quadraticCurveTo(t, e, s, i, r) {
    this._tick++;
    const o = this._transform;
    return this._activePath.quadraticCurveTo(
      o.a * t + o.c * e + o.tx,
      o.b * t + o.d * e + o.ty,
      o.a * s + o.c * i + o.tx,
      o.b * s + o.d * i + o.ty,
      r
    ), this;
  }
  /**
   * Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
   * @param x - The x-coordinate of the top-left corner of the rectangle.
   * @param y - The y-coordinate of the top-left corner of the rectangle.
   * @param w - The width of the rectangle.
   * @param h - The height of the rectangle.
   * @returns The instance of the current object for chaining.
   */
  rect(t, e, s, i) {
    return this._tick++, this._activePath.rect(t, e, s, i, this._transform.clone()), this;
  }
  /**
   * Draws a rectangle with rounded corners.
   * The corner radius can be specified to determine how rounded the corners should be.
   * An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
   * @param x - The x-coordinate of the top-left corner of the rectangle.
   * @param y - The y-coordinate of the top-left corner of the rectangle.
   * @param w - The width of the rectangle.
   * @param h - The height of the rectangle.
   * @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
   * @returns The instance of the current object for chaining.
   */
  roundRect(t, e, s, i, r) {
    return this._tick++, this._activePath.roundRect(t, e, s, i, r, this._transform.clone()), this;
  }
  /**
   * Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons,
   * which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled,
   * rotated, or translated as needed.
   * @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
   * representing the x and y coordinates, of the polygon's vertices, in sequence.
   * @param close - A boolean indicating whether to close the polygon path. True by default.
   */
  poly(t, e) {
    return this._tick++, this._activePath.poly(t, e, this._transform.clone()), this;
  }
  /**
   * Draws a regular polygon with a specified number of sides. All sides and angles are equal.
   * @param x - The x-coordinate of the center of the polygon.
   * @param y - The y-coordinate of the center of the polygon.
   * @param radius - The radius of the circumscribed circle of the polygon.
   * @param sides - The number of sides of the polygon. Must be 3 or more.
   * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
   * @param transform - An optional `Matrix` object to apply a transformation to the polygon.
   * @returns The instance of the current object for chaining.
   */
  regularPoly(t, e, s, i, r = 0, o) {
    return this._tick++, this._activePath.regularPoly(t, e, s, i, r, o), this;
  }
  /**
   * Draws a polygon with rounded corners.
   * Similar to `regularPoly` but with the ability to round the corners of the polygon.
   * @param x - The x-coordinate of the center of the polygon.
   * @param y - The y-coordinate of the center of the polygon.
   * @param radius - The radius of the circumscribed circle of the polygon.
   * @param sides - The number of sides of the polygon. Must be 3 or more.
   * @param corner - The radius of the rounding of the corners.
   * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
   * @returns The instance of the current object for chaining.
   */
  roundPoly(t, e, s, i, r, o) {
    return this._tick++, this._activePath.roundPoly(t, e, s, i, r, o), this;
  }
  /**
   * Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
   * Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
   * @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
   * A minimum of 3 points is required.
   * @param radius - The default radius for the corners.
   * This radius is applied to all corners unless overridden in `points`.
   * @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
   *  method instead of an arc method. Defaults to false.
   * @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
   * Higher values make the curve smoother.
   * @returns The instance of the current object for chaining.
   */
  roundShape(t, e, s, i) {
    return this._tick++, this._activePath.roundShape(t, e, s, i), this;
  }
  /**
   * Draw Rectangle with fillet corners. This is much like rounded rectangle
   * however it support negative numbers as well for the corner radius.
   * @param x - Upper left corner of rect
   * @param y - Upper right corner of rect
   * @param width - Width of rect
   * @param height - Height of rect
   * @param fillet - accept negative or positive values
   */
  filletRect(t, e, s, i, r) {
    return this._tick++, this._activePath.filletRect(t, e, s, i, r), this;
  }
  /**
   * Draw Rectangle with chamfer corners. These are angled corners.
   * @param x - Upper left corner of rect
   * @param y - Upper right corner of rect
   * @param width - Width of rect
   * @param height - Height of rect
   * @param chamfer - non-zero real number, size of corner cutout
   * @param transform
   */
  chamferRect(t, e, s, i, r, o) {
    return this._tick++, this._activePath.chamferRect(t, e, s, i, r, o), this;
  }
  /**
   * Draws a star shape centered at a specified location. This method allows for the creation
   *  of stars with a variable number of points, outer radius, optional inner radius, and rotation.
   * The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
   * An optional transformation can be applied to scale, rotate, or translate the star as needed.
   * @param x - The x-coordinate of the center of the star.
   * @param y - The y-coordinate of the center of the star.
   * @param points - The number of points of the star.
   * @param radius - The outer radius of the star (distance from the center to the outer points).
   * @param innerRadius - Optional. The inner radius of the star
   * (distance from the center to the inner points between the outer points).
   * If not provided, defaults to half of the `radius`.
   * @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
   * Defaults to 0, meaning one point is directly upward.
   * @returns The instance of the current object for chaining further drawing commands.
   */
  star(t, e, s, i, r = 0, o = 0) {
    return this._tick++, this._activePath.star(t, e, s, i, r, o, this._transform.clone()), this;
  }
  /**
   * Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths
   * defined in SVG format to be drawn within the graphics context.
   * @param svg - The SVG string to be parsed and rendered.
   */
  svg(t) {
    return this._tick++, C_(t, this), this;
  }
  /**
   * Restores the most recently saved graphics state by popping the top of the graphics state stack.
   * This includes transformations, fill styles, and stroke styles.
   */
  restore() {
    const t = this._stateStack.pop();
    return t && (this._transform = t.transform, this._fillStyle = t.fillStyle, this._strokeStyle = t.strokeStyle), this;
  }
  /** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
  save() {
    return this._stateStack.push({
      transform: this._transform.clone(),
      fillStyle: { ...this._fillStyle },
      strokeStyle: { ...this._strokeStyle }
    }), this;
  }
  /**
   * Returns the current transformation matrix of the graphics context.
   * @returns The current transformation matrix.
   */
  getTransform() {
    return this._transform;
  }
  /**
   * Resets the current transformation matrix to the identity matrix, effectively removing any transformations (rotation, scaling, translation) previously applied.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  resetTransform() {
    return this._transform.identity(), this;
  }
  /**
   * Applies a rotation transformation to the graphics context around the current origin.
   * @param angle - The angle of rotation in radians.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  rotate(t) {
    return this._transform.rotate(t), this;
  }
  /**
   * Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically.
   * @param x - The scale factor in the horizontal direction.
   * @param y - (Optional) The scale factor in the vertical direction. If not specified, the x value is used for both directions.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  scale(t, e = t) {
    return this._transform.scale(t, e), this;
  }
  setTransform(t, e, s, i, r, o) {
    return t instanceof nt ? (this._transform.set(t.a, t.b, t.c, t.d, t.tx, t.ty), this) : (this._transform.set(t, e, s, i, r, o), this);
  }
  transform(t, e, s, i, r, o) {
    return t instanceof nt ? (this._transform.append(t), this) : (Vu.set(t, e, s, i, r, o), this._transform.append(Vu), this);
  }
  /**
   * Applies a translation transformation to the graphics context, moving the origin by the specified amounts.
   * @param x - The amount to translate in the horizontal direction.
   * @param y - (Optional) The amount to translate in the vertical direction. If not specified, the x value is used for both directions.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  translate(t, e = t) {
    return this._transform.translate(t, e), this;
  }
  /**
   * Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
   * and optionally resetting transformations to the identity matrix.
   * @returns The instance of the current GraphicsContext for method chaining.
   */
  clear() {
    return this._activePath.clear(), this.instructions.length = 0, this.resetTransform(), this.onUpdate(), this;
  }
  onUpdate() {
    this.dirty || (this.emit("update", this, 16), this.dirty = !0, this._boundsDirty = !0);
  }
  /** The bounds of the graphic shape. */
  get bounds() {
    if (!this._boundsDirty)
      return this._bounds;
    const t = this._bounds;
    t.clear();
    for (let e = 0; e < this.instructions.length; e++) {
      const s = this.instructions[e], i = s.action;
      if (i === "fill") {
        const r = s.data;
        t.addBounds(r.path.bounds);
      } else if (i === "texture") {
        const r = s.data;
        t.addFrame(r.dx, r.dy, r.dx + r.dw, r.dy + r.dh, r.transform);
      }
      if (i === "stroke") {
        const r = s.data, o = r.style.alignment, a = r.style.width * (1 - o), l = r.path.bounds;
        t.addFrame(
          l.minX - a,
          l.minY - a,
          l.maxX + a,
          l.maxY + a
        );
      }
    }
    return t;
  }
  /**
   * Check to see if a point is contained within this geometry.
   * @param point - Point to check if it's contained.
   * @returns {boolean} `true` if the point is contained within geometry.
   */
  containsPoint(t) {
    if (!this.bounds.containsPoint(t.x, t.y))
      return !1;
    const e = this.instructions;
    let s = !1;
    for (let i = 0; i < e.length; i++) {
      const r = e[i], o = r.data, a = o.path;
      if (!r.action || !a)
        continue;
      const l = o.style, c = a.shapePath.shapePrimitives;
      for (let h = 0; h < c.length; h++) {
        const u = c[h].shape;
        if (!l || !u)
          continue;
        const d = c[h].transform, f = d ? d.applyInverse(t, R_) : t;
        if (r.action === "fill")
          s = u.contains(f.x, f.y);
        else {
          const g = l;
          s = u.strokeContains(f.x, f.y, g.width, g.alignment);
        }
        const p = o.hole;
        if (p) {
          const g = p.shapePath?.shapePrimitives;
          if (g)
            for (let m = 0; m < g.length; m++)
              g[m].shape.contains(f.x, f.y) && (s = !1);
        }
        if (s)
          return !0;
      }
    }
    return s;
  }
  /**
   * Destroys the GraphicsData object.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @example
   * context.destroy();
   * context.destroy(true);
   * context.destroy({ texture: true, textureSource: true });
   */
  destroy(t = !1) {
    if (this._stateStack.length = 0, this._transform = null, this.emit("destroy", this), this.removeAllListeners(), typeof t == "boolean" ? t : t?.texture) {
      const s = typeof t == "boolean" ? t : t?.textureSource;
      this._fillStyle.texture && (this._fillStyle.fill && "uid" in this._fillStyle.fill ? this._fillStyle.fill.destroy() : this._fillStyle.texture.destroy(s)), this._strokeStyle.texture && (this._strokeStyle.fill && "uid" in this._strokeStyle.fill ? this._strokeStyle.fill.destroy() : this._strokeStyle.texture.destroy(s));
    }
    this._fillStyle = null, this._strokeStyle = null, this.instructions = null, this._activePath = null, this._bounds = null, this._stateStack = null, this.customShader = null, this._transform = null;
  }
};
nc.defaultFillStyle = {
  /** The color to use for the fill. */
  color: 16777215,
  /** The alpha value to use for the fill. */
  alpha: 1,
  /** The texture to use for the fill. */
  texture: rt.WHITE,
  /** The matrix to apply. */
  matrix: null,
  /** The fill pattern to use. */
  fill: null,
  /** Whether coordinates are 'global' or 'local' */
  textureSpace: "local"
};
nc.defaultStrokeStyle = {
  /** The width of the stroke. */
  width: 1,
  /** The color to use for the stroke. */
  color: 16777215,
  /** The alpha value to use for the stroke. */
  alpha: 1,
  /** The alignment of the stroke. */
  alignment: 0.5,
  /** The miter limit to use. */
  miterLimit: 10,
  /** The line cap style to use. */
  cap: "butt",
  /** The line join style to use. */
  join: "miter",
  /** The texture to use for the fill. */
  texture: rt.WHITE,
  /** The matrix to apply. */
  matrix: null,
  /** The fill pattern to use. */
  fill: null,
  /** Whether coordinates are 'global' or 'local' */
  textureSpace: "local",
  /** If the stroke is a pixel line. */
  pixelLine: !1
};
let We = nc;
const Bu = [
  "align",
  "breakWords",
  "cssOverrides",
  "fontVariant",
  "fontWeight",
  "leading",
  "letterSpacing",
  "lineHeight",
  "padding",
  "textBaseline",
  "trim",
  "whiteSpace",
  "wordWrap",
  "wordWrapWidth",
  "fontFamily",
  "fontStyle",
  "fontSize"
];
function D_(n) {
  const t = [];
  let e = 0;
  for (let s = 0; s < Bu.length; s++) {
    const i = `_${Bu[s]}`;
    t[e++] = n[i];
  }
  return e = $p(n._fill, t, e), e = N_(n._stroke, t, e), e = L_(n.dropShadow, t, e), e = O_(n.filters, t, e), t.join("-");
}
function O_(n, t, e) {
  if (!n)
    return e;
  for (const s of n)
    t[e++] = s.uid;
  return e;
}
function $p(n, t, e) {
  return n && (t[e++] = n.color, t[e++] = n.alpha, t[e++] = n.fill?.styleKey), e;
}
function N_(n, t, e) {
  return n && (e = $p(n, t, e), t[e++] = n.width, t[e++] = n.alignment, t[e++] = n.cap, t[e++] = n.join, t[e++] = n.miterLimit), e;
}
function L_(n, t, e) {
  return n && (t[e++] = n.alpha, t[e++] = n.angle, t[e++] = n.blur, t[e++] = n.distance, t[e++] = Bt.shared.setValue(n.color).toNumber()), e;
}
const ic = class zn extends ps {
  constructor(t = {}) {
    super(), V_(t);
    const e = { ...zn.defaultTextStyle, ...t };
    for (const s in e) {
      const i = s;
      this[i] = e[s];
    }
    this.update();
  }
  /**
   * Alignment for multiline text, does not affect single line text.
   * @type {'left'|'center'|'right'|'justify'}
   */
  get align() {
    return this._align;
  }
  set align(t) {
    this._align = t, this.update();
  }
  /** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */
  get breakWords() {
    return this._breakWords;
  }
  set breakWords(t) {
    this._breakWords = t, this.update();
  }
  /** Set a drop shadow for the text. */
  get dropShadow() {
    return this._dropShadow;
  }
  set dropShadow(t) {
    t !== null && typeof t == "object" ? this._dropShadow = this._createProxy({ ...zn.defaultDropShadow, ...t }) : this._dropShadow = t ? this._createProxy({ ...zn.defaultDropShadow }) : null, this.update();
  }
  /** The font family, can be a single font name, or a list of names where the first is the preferred font. */
  get fontFamily() {
    return this._fontFamily;
  }
  set fontFamily(t) {
    this._fontFamily = t, this.update();
  }
  /** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
  get fontSize() {
    return this._fontSize;
  }
  set fontSize(t) {
    typeof t == "string" ? this._fontSize = parseInt(t, 10) : this._fontSize = t, this.update();
  }
  /**
   * The font style.
   * @type {'normal'|'italic'|'oblique'}
   */
  get fontStyle() {
    return this._fontStyle;
  }
  set fontStyle(t) {
    this._fontStyle = t.toLowerCase(), this.update();
  }
  /**
   * The font variant.
   * @type {'normal'|'small-caps'}
   */
  get fontVariant() {
    return this._fontVariant;
  }
  set fontVariant(t) {
    this._fontVariant = t, this.update();
  }
  /**
   * The font weight.
   * @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
   */
  get fontWeight() {
    return this._fontWeight;
  }
  set fontWeight(t) {
    this._fontWeight = t, this.update();
  }
  /** The space between lines. */
  get leading() {
    return this._leading;
  }
  set leading(t) {
    this._leading = t, this.update();
  }
  /** The amount of spacing between letters, default is 0. */
  get letterSpacing() {
    return this._letterSpacing;
  }
  set letterSpacing(t) {
    this._letterSpacing = t, this.update();
  }
  /** The line height, a number that represents the vertical space that a letter uses. */
  get lineHeight() {
    return this._lineHeight;
  }
  set lineHeight(t) {
    this._lineHeight = t, this.update();
  }
  /**
   * Occasionally some fonts are cropped. Adding some padding will prevent this from happening
   * by adding padding to all sides of the text.
   * > [!NOTE] This will NOT affect the positioning or bounds of the text.
   */
  get padding() {
    return this._padding;
  }
  set padding(t) {
    this._padding = t, this.update();
  }
  /**
   * An optional filter or array of filters to apply to the text, allowing for advanced visual effects.
   * These filters will be applied to the text as it is created, resulting in faster rendering for static text
   * compared to applying the filter directly to the text object (which would be applied at run time).
   * @default null
   */
  get filters() {
    return this._filters;
  }
  set filters(t) {
    this._filters = t, this.update();
  }
  /**
   * Trim transparent borders from the text texture.
   * > [!IMPORTANT] PERFORMANCE WARNING:
   * > This is a costly operation as it requires scanning pixel alpha values.
   * > Avoid using `trim: true` for dynamic text, as it could significantly impact performance.
   */
  get trim() {
    return this._trim;
  }
  set trim(t) {
    this._trim = t, this.update();
  }
  /**
   * The baseline of the text that is rendered.
   * @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
   */
  get textBaseline() {
    return this._textBaseline;
  }
  set textBaseline(t) {
    this._textBaseline = t, this.update();
  }
  /**
   * How newlines and spaces should be handled.
   * Default is 'pre' (preserve, preserve).
   *
   *  value       | New lines     |   Spaces
   *  ---         | ---           |   ---
   * 'normal'     | Collapse      |   Collapse
   * 'pre'        | Preserve      |   Preserve
   * 'pre-line'   | Preserve      |   Collapse
   * @type {'normal'|'pre'|'pre-line'}
   */
  get whiteSpace() {
    return this._whiteSpace;
  }
  set whiteSpace(t) {
    this._whiteSpace = t, this.update();
  }
  /** Indicates if word wrap should be used. */
  get wordWrap() {
    return this._wordWrap;
  }
  set wordWrap(t) {
    this._wordWrap = t, this.update();
  }
  /** The width at which text will wrap, it needs wordWrap to be set to true. */
  get wordWrapWidth() {
    return this._wordWrapWidth;
  }
  set wordWrapWidth(t) {
    this._wordWrapWidth = t, this.update();
  }
  /**
   * The fill style that will be used to color the text.
   * This can be:
   * - A color string like 'red', '#00FF00', or 'rgba(255,0,0,0.5)'
   * - A hex number like 0xff0000 for red
   * - A FillStyle object with properties like { color: 0xff0000, alpha: 0.5 }
   * - A FillGradient for gradient fills
   * - A FillPattern for pattern/texture fills
   *
   * When using a FillGradient, vertical gradients (angle of 90 degrees) are applied per line of text,
   * while gradients at any other angle are spread across the entire text body as a whole.
   * @example
   * // Vertical gradient applied per line
   * const verticalGradient = new FillGradient(0, 0, 0, 1)
   *     .addColorStop(0, 0xff0000)
   *     .addColorStop(1, 0x0000ff);
   *
   * const text = new Text({
   *     text: 'Line 1\nLine 2',
   *     style: { fill: verticalGradient }
   * });
   *
   * To manage the gradient in a global scope, set the textureSpace property of the FillGradient to 'global'.
   * @type {string|number|FillStyle|FillGradient|FillPattern}
   */
  get fill() {
    return this._originalFill;
  }
  set fill(t) {
    t !== this._originalFill && (this._originalFill = t, this._isFillStyle(t) && (this._originalFill = this._createProxy({ ...We.defaultFillStyle, ...t }, () => {
      this._fill = gn(
        { ...this._originalFill },
        We.defaultFillStyle
      );
    })), this._fill = gn(
      t === 0 ? "black" : t,
      We.defaultFillStyle
    ), this.update());
  }
  /** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */
  get stroke() {
    return this._originalStroke;
  }
  set stroke(t) {
    t !== this._originalStroke && (this._originalStroke = t, this._isFillStyle(t) && (this._originalStroke = this._createProxy({ ...We.defaultStrokeStyle, ...t }, () => {
      this._stroke = yo(
        { ...this._originalStroke },
        We.defaultStrokeStyle
      );
    })), this._stroke = yo(t, We.defaultStrokeStyle), this.update());
  }
  _generateKey() {
    return this._styleKey = D_(this), this._styleKey;
  }
  update() {
    this._styleKey = null, this.emit("update", this);
  }
  /** Resets all properties to the default values */
  reset() {
    const t = zn.defaultTextStyle;
    for (const e in t)
      this[e] = t[e];
  }
  /** @internal */
  get styleKey() {
    return this._styleKey || this._generateKey();
  }
  /**
   * Creates a new TextStyle object with the same values as this one.
   * @returns New cloned TextStyle object
   */
  clone() {
    return new zn({
      align: this.align,
      breakWords: this.breakWords,
      dropShadow: this._dropShadow ? { ...this._dropShadow } : null,
      fill: this._fill,
      fontFamily: this.fontFamily,
      fontSize: this.fontSize,
      fontStyle: this.fontStyle,
      fontVariant: this.fontVariant,
      fontWeight: this.fontWeight,
      leading: this.leading,
      letterSpacing: this.letterSpacing,
      lineHeight: this.lineHeight,
      padding: this.padding,
      stroke: this._stroke,
      textBaseline: this.textBaseline,
      whiteSpace: this.whiteSpace,
      wordWrap: this.wordWrap,
      wordWrapWidth: this.wordWrapWidth,
      filters: this._filters ? [...this._filters] : void 0
    });
  }
  /**
   * Returns the final padding for the text style, taking into account any filters applied.
   * Used internally for correct measurements
   * @internal
   * @returns {number} The final padding for the text style.
   */
  _getFinalPadding() {
    let t = 0;
    if (this._filters)
      for (let e = 0; e < this._filters.length; e++)
        t += this._filters[e].padding;
    return Math.max(this._padding, t);
  }
  /**
   * Destroys this text style.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @example
   * // Destroy the text style and its textures
   * textStyle.destroy({ texture: true, textureSource: true });
   * textStyle.destroy(true);
   */
  destroy(t = !1) {
    if (this.removeAllListeners(), typeof t == "boolean" ? t : t?.texture) {
      const s = typeof t == "boolean" ? t : t?.textureSource;
      this._fill?.texture && this._fill.texture.destroy(s), this._originalFill?.texture && this._originalFill.texture.destroy(s), this._stroke?.texture && this._stroke.texture.destroy(s), this._originalStroke?.texture && this._originalStroke.texture.destroy(s);
    }
    this._fill = null, this._stroke = null, this.dropShadow = null, this._originalStroke = null, this._originalFill = null;
  }
  _createProxy(t, e) {
    return new Proxy(t, {
      set: (s, i, r) => (s[i] = r, e?.(i, r), this.update(), !0)
    });
  }
  _isFillStyle(t) {
    return (t ?? null) !== null && !(Bt.isColorLike(t) || t instanceof Is || t instanceof Zo);
  }
};
ic.defaultDropShadow = {
  alpha: 1,
  angle: Math.PI / 6,
  blur: 0,
  color: "black",
  distance: 5
};
ic.defaultTextStyle = {
  align: "left",
  breakWords: !1,
  dropShadow: null,
  fill: "black",
  fontFamily: "Arial",
  fontSize: 26,
  fontStyle: "normal",
  fontVariant: "normal",
  fontWeight: "normal",
  leading: 0,
  letterSpacing: 0,
  lineHeight: 0,
  padding: 0,
  stroke: null,
  textBaseline: "alphabetic",
  trim: !1,
  whiteSpace: "pre",
  wordWrap: !1,
  wordWrapWidth: 100
};
let Hp = ic;
function V_(n) {
  const t = n;
  if (typeof t.dropShadow == "boolean" && t.dropShadow) {
    const e = Hp.defaultDropShadow;
    n.dropShadow = {
      alpha: t.dropShadowAlpha ?? e.alpha,
      angle: t.dropShadowAngle ?? e.angle,
      blur: t.dropShadowBlur ?? e.blur,
      color: t.dropShadowColor ?? e.color,
      distance: t.dropShadowDistance ?? e.distance
    };
  }
  if (t.strokeThickness !== void 0) {
    ct(kt, "strokeThickness is now a part of stroke");
    const e = t.stroke;
    let s = {};
    if (Bt.isColorLike(e))
      s.color = e;
    else if (e instanceof Is || e instanceof Zo)
      s.fill = e;
    else if (Object.hasOwnProperty.call(e, "color") || Object.hasOwnProperty.call(e, "fill"))
      s = e;
    else
      throw new Error("Invalid stroke value.");
    n.stroke = {
      ...s,
      width: t.strokeThickness
    };
  }
  if (Array.isArray(t.fillGradientStops)) {
    if (ct(kt, "gradient fill is now a fill pattern: `new FillGradient(...)`"), !Array.isArray(t.fill) || t.fill.length === 0)
      throw new Error("Invalid fill value. Expected an array of colors for gradient fill.");
    t.fill.length !== t.fillGradientStops.length && Ht("The number of fill colors must match the number of fill gradient stops.");
    const e = new Is({
      start: { x: 0, y: 0 },
      end: { x: 0, y: 1 },
      textureSpace: "local"
    }), s = t.fillGradientStops.slice(), i = t.fill.map((r) => Bt.shared.setValue(r).toNumber());
    s.forEach((r, o) => {
      e.addColorStop(r, i[o]);
    }), n.fill = {
      fill: e
    };
  }
}
class B_ {
  constructor(t) {
    this._canvasPool = /* @__PURE__ */ Object.create(null), this.canvasOptions = t || {}, this.enableFullScreen = !1;
  }
  /**
   * Creates texture with params that were specified in pool constructor.
   * @param pixelWidth - Width of texture in pixels.
   * @param pixelHeight - Height of texture in pixels.
   */
  _createCanvasAndContext(t, e) {
    const s = Ae.get().createCanvas();
    s.width = t, s.height = e;
    const i = s.getContext("2d");
    return { canvas: s, context: i };
  }
  /**
   * Gets a Power-of-Two render texture or fullScreen texture
   * @param minWidth - The minimum width of the render texture.
   * @param minHeight - The minimum height of the render texture.
   * @param resolution - The resolution of the render texture.
   * @returns The new render texture.
   */
  getOptimalCanvasAndContext(t, e, s = 1) {
    t = Math.ceil(t * s - 1e-6), e = Math.ceil(e * s - 1e-6), t = Xn(t), e = Xn(e);
    const i = (t << 17) + (e << 1);
    this._canvasPool[i] || (this._canvasPool[i] = []);
    let r = this._canvasPool[i].pop();
    return r || (r = this._createCanvasAndContext(t, e)), r;
  }
  /**
   * Place a render texture back into the pool.
   * @param canvasAndContext
   */
  returnCanvasAndContext(t) {
    const e = t.canvas, { width: s, height: i } = e, r = (s << 17) + (i << 1);
    t.context.resetTransform(), t.context.clearRect(0, 0, s, i), this._canvasPool[r].push(t);
  }
  clear() {
    this._canvasPool = {};
  }
}
const zu = new B_(), qu = 1e5;
function Uu(n, t, e, s = 0) {
  if (n.texture === rt.WHITE && !n.fill)
    return Bt.shared.setValue(n.color).setAlpha(n.alpha ?? 1).toHexa();
  if (n.fill) {
    if (n.fill instanceof Zo) {
      const i = n.fill, r = t.createPattern(i.texture.source.resource, "repeat"), o = i.transform.copyTo(nt.shared);
      return o.scale(
        i.texture.frame.width,
        i.texture.frame.height
      ), r.setTransform(o), r;
    } else if (n.fill instanceof Is) {
      const i = n.fill, r = i.type === "linear", o = i.textureSpace === "local";
      let a = 1, l = 1;
      o && e && (a = e.width + s, l = e.height + s);
      let c, h = !1;
      if (r) {
        const { start: u, end: d } = i;
        c = t.createLinearGradient(
          u.x * a,
          u.y * l,
          d.x * a,
          d.y * l
        ), h = Math.abs(d.x - u.x) < Math.abs((d.y - u.y) * 0.1);
      } else {
        const { center: u, innerRadius: d, outerCenter: f, outerRadius: p } = i;
        c = t.createRadialGradient(
          u.x * a,
          u.y * l,
          d * a,
          f.x * a,
          f.y * l,
          p * a
        );
      }
      if (h && o && e) {
        const u = e.lineHeight / l;
        for (let d = 0; d < e.lines.length; d++) {
          const f = (d * e.lineHeight + s / 2) / l;
          i.colorStops.forEach((p) => {
            const g = f + p.offset * u;
            c.addColorStop(
              // fix to 5 decimal places to avoid floating point precision issues
              Math.floor(g * qu) / qu,
              Bt.shared.setValue(p.color).toHex()
            );
          });
        }
      } else
        i.colorStops.forEach((u) => {
          c.addColorStop(u.offset, Bt.shared.setValue(u.color).toHex());
        });
      return c;
    }
  } else {
    const i = t.createPattern(n.texture.source.resource, "repeat"), r = n.matrix.copyTo(nt.shared);
    return r.scale(n.texture.frame.width, n.texture.frame.height), i.setTransform(r), i;
  }
  return Ht("FillStyle not recognised", n), "red";
}
class ie extends jo {
  /**
   * Creates a new Graphics object.
   * @param options - Options for the Graphics.
   */
  constructor(t) {
    t instanceof We && (t = { context: t });
    const { context: e, roundPixels: s, ...i } = t || {};
    super({
      label: "Graphics",
      ...i
    }), this.renderPipeId = "graphics", e ? this._context = e : this._context = this._ownedContext = new We(), this._context.on("update", this.onViewUpdate, this), this.didViewUpdate = !0, this.allowChildren = !1, this.roundPixels = s ?? !1;
  }
  set context(t) {
    t !== this._context && (this._context.off("update", this.onViewUpdate, this), this._context = t, this._context.on("update", this.onViewUpdate, this), this.onViewUpdate());
  }
  /**
   * The underlying graphics context used for drawing operations.
   * Controls how shapes and paths are rendered.
   * @example
   * ```ts
   * // Create a shared context
   * const sharedContext = new GraphicsContext();
   *
   * // Create graphics objects sharing the same context
   * const graphics1 = new Graphics();
   * const graphics2 = new Graphics();
   *
   * // Assign shared context
   * graphics1.context = sharedContext;
   * graphics2.context = sharedContext;
   *
   * // Both graphics will show the same shapes
   * sharedContext
   *     .rect(0, 0, 100, 100)
   *     .fill({ color: 0xff0000 });
   * ```
   * @see {@link GraphicsContext} For drawing operations
   * @see {@link GraphicsOptions} For context configuration
   */
  get context() {
    return this._context;
  }
  /**
   * The local bounds of the graphics object.
   * Returns the boundaries after all graphical operations but before any transforms.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Draw a shape
   * graphics
   *     .rect(0, 0, 100, 100)
   *     .fill({ color: 0xff0000 });
   *
   * // Get bounds information
   * const bounds = graphics.bounds;
   * console.log(bounds.width);  // 100
   * console.log(bounds.height); // 100
   * ```
   * @readonly
   * @see {@link Bounds} For bounds operations
   * @see {@link Container#getBounds} For transformed bounds
   */
  get bounds() {
    return this._context.bounds;
  }
  /**
   * Graphics objects do not need to update their bounds as the context handles this.
   * @private
   */
  updateBounds() {
  }
  /**
   * Checks if the object contains the given point.
   * Returns true if the point lies within the Graphics object's rendered area.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Draw a shape
   * graphics
   *     .rect(0, 0, 100, 100)
   *     .fill({ color: 0xff0000 });
   *
   * // Check point intersection
   * if (graphics.containsPoint({ x: 50, y: 50 })) {
   *     console.log('Point is inside rectangle!');
   * }
   * ```
   * @param point - The point to check in local coordinates
   * @returns True if the point is inside the Graphics object
   * @see {@link Graphics#bounds} For bounding box checks
   * @see {@link PointData} For point data structure
   */
  containsPoint(t) {
    return this._context.containsPoint(t);
  }
  /**
   * Destroys this graphics renderable and optionally its context.
   * @param options - Options parameter. A boolean will act as if all options
   *
   * If the context was created by this graphics and `destroy(false)` or `destroy()` is called
   * then the context will still be destroyed.
   *
   * If you want to explicitly not destroy this context that this graphics created,
   * then you should pass destroy({ context: false })
   *
   * If the context was passed in as an argument to the constructor then it will not be destroyed
   * @example
   * ```ts
   * // Destroy the graphics and its context
   * graphics.destroy();
   * graphics.destroy(true);
   * graphics.destroy({ context: true, texture: true, textureSource: true });
   * ```
   */
  destroy(t) {
    this._ownedContext && !t ? this._ownedContext.destroy(t) : (t === !0 || t?.context === !0) && this._context.destroy(t), this._ownedContext = null, this._context = null, super.destroy(t);
  }
  _callContextMethod(t, e) {
    return this.context[t](...e), this;
  }
  // --------------------------------------- GraphicsContext methods ---------------------------------------
  /**
   * Sets the current fill style of the graphics context.
   * The fill style can be a color, gradient, pattern, or a complex style object.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Basic color fill
   * graphics
   *     .setFillStyle({ color: 0xff0000 }) // Red fill
   *     .rect(0, 0, 100, 100)
   *     .fill();
   *
   * // Gradient fill
   * const gradient = new FillGradient({
   *    end: { x: 1, y: 0 },
   *    colorStops: [
   *         { offset: 0, color: 0xff0000 }, // Red at start
   *         { offset: 0.5, color: 0x00ff00 }, // Green at middle
   *         { offset: 1, color: 0x0000ff }, // Blue at end
   *    ],
   * });
   *
   * graphics
   *     .setFillStyle(gradient)
   *     .circle(100, 100, 50)
   *     .fill();
   *
   * // Pattern fill
   * const pattern = new FillPattern(texture);
   * graphics
   *     .setFillStyle({
   *         fill: pattern,
   *         alpha: 0.5
   *     })
   *     .rect(0, 0, 200, 200)
   *     .fill();
   * ```
   * @param {FillInput} args - The fill style to apply
   * @returns The Graphics instance for chaining
   * @see {@link FillStyle} For fill style options
   * @see {@link FillGradient} For gradient fills
   * @see {@link FillPattern} For pattern fills
   */
  setFillStyle(...t) {
    return this._callContextMethod("setFillStyle", t);
  }
  /**
   * Sets the current stroke style of the graphics context.
   * Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Basic color stroke
   * graphics
   *     .setStrokeStyle({
   *         width: 2,
   *         color: 0x000000
   *     })
   *     .rect(0, 0, 100, 100)
   *     .stroke();
   *
   * // Complex stroke style
   * graphics
   *     .setStrokeStyle({
   *         width: 4,
   *         color: 0xff0000,
   *         alpha: 0.5,
   *         join: 'round',
   *         cap: 'round',
   *         alignment: 0.5
   *     })
   *     .circle(100, 100, 50)
   *     .stroke();
   *
   * // Gradient stroke
   * const gradient = new FillGradient({
   *    end: { x: 1, y: 0 },
   *    colorStops: [
   *         { offset: 0, color: 0xff0000 }, // Red at start
   *         { offset: 0.5, color: 0x00ff00 }, // Green at middle
   *         { offset: 1, color: 0x0000ff }, // Blue at end
   *    ],
   * });
   *
   * graphics
   *     .setStrokeStyle({
   *         width: 10,
   *         fill: gradient
   *     })
   *     .poly([0,0, 100,50, 0,100])
   *     .stroke();
   * ```
   * @param {StrokeInput} args - The stroke style to apply
   * @returns The Graphics instance for chaining
   * @see {@link StrokeStyle} For stroke style options
   * @see {@link FillGradient} For gradient strokes
   * @see {@link FillPattern} For pattern strokes
   */
  setStrokeStyle(...t) {
    return this._callContextMethod("setStrokeStyle", t);
  }
  fill(...t) {
    return this._callContextMethod("fill", t);
  }
  /**
   * Strokes the current path with the current stroke style or specified style.
   * Outlines the shape using the stroke settings.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Stroke with direct color
   * graphics
   *     .circle(50, 50, 25)
   *     .stroke({
   *         width: 2,
   *         color: 0xff0000
   *     }); // 2px red stroke
   *
   * // Fill with texture
   * graphics
   *    .rect(0, 0, 100, 100)
   *    .stroke(myTexture); // Fill with texture
   *
   * // Stroke with gradient
   * const gradient = new FillGradient({
   *     end: { x: 1, y: 0 },
   *     colorStops: [
   *         { offset: 0, color: 0xff0000 },
   *         { offset: 0.5, color: 0x00ff00 },
   *         { offset: 1, color: 0x0000ff },
   *     ],
   * });
   *
   * graphics
   *     .rect(0, 0, 100, 100)
   *     .stroke({
   *         width: 4,
   *         fill: gradient,
   *         alignment: 0.5,
   *         join: 'round'
   *     });
   * ```
   * @param {StrokeStyle} args - Optional stroke style to apply. Can be:
   * - A stroke style object with width, color, etc.
   * - A gradient
   * - A pattern
   * If omitted, uses current stroke style.
   * @returns The Graphics instance for chaining
   * @see {@link StrokeStyle} For stroke style options
   * @see {@link FillGradient} For gradient strokes
   * @see {@link setStrokeStyle} For setting default stroke style
   */
  stroke(...t) {
    return this._callContextMethod("stroke", t);
  }
  texture(...t) {
    return this._callContextMethod("texture", t);
  }
  /**
   * Resets the current path. Any previous path and its commands are discarded and a new path is
   * started. This is typically called before beginning a new shape or series of drawing commands.
   * @example
   * ```ts
   * const graphics = new Graphics();
   * graphics
   *     .circle(150, 150, 50)
   *     .fill({ color: 0x00ff00 })
   *     .beginPath() // Starts a new path
   *     .circle(250, 150, 50)
   *     .fill({ color: 0x0000ff });
   * ```
   * @returns The Graphics instance for chaining
   * @see {@link Graphics#moveTo} For starting a new subpath
   * @see {@link Graphics#closePath} For closing the current path
   */
  beginPath() {
    return this._callContextMethod("beginPath", []);
  }
  /**
   * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
   * subtracting a path from the previously drawn path.
   *
   * If a hole is not completely in a shape, it will fail to cut correctly.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Draw outer circle
   * graphics
   *     .circle(100, 100, 50)
   *     .fill({ color: 0xff0000 });
   *     .circle(100, 100, 25) // Inner circle
   *     .cut() // Cuts out the inner circle from the outer circle
   * ```
   */
  cut() {
    return this._callContextMethod("cut", []);
  }
  arc(...t) {
    return this._callContextMethod("arc", t);
  }
  arcTo(...t) {
    return this._callContextMethod("arcTo", t);
  }
  arcToSvg(...t) {
    return this._callContextMethod("arcToSvg", t);
  }
  bezierCurveTo(...t) {
    return this._callContextMethod("bezierCurveTo", t);
  }
  /**
   * Closes the current path by drawing a straight line back to the start point.
   *
   * This is useful for completing shapes and ensuring they are properly closed for fills.
   * @example
   * ```ts
   * // Create a triangle with closed path
   * const graphics = new Graphics();
   * graphics
   *     .moveTo(50, 50)
   *     .lineTo(100, 100)
   *     .lineTo(0, 100)
   *     .closePath()
   * ```
   * @returns The Graphics instance for method chaining
   * @see {@link Graphics#beginPath} For starting a new path
   * @see {@link Graphics#fill} For filling closed paths
   * @see {@link Graphics#stroke} For stroking paths
   */
  closePath() {
    return this._callContextMethod("closePath", []);
  }
  ellipse(...t) {
    return this._callContextMethod("ellipse", t);
  }
  circle(...t) {
    return this._callContextMethod("circle", t);
  }
  path(...t) {
    return this._callContextMethod("path", t);
  }
  lineTo(...t) {
    return this._callContextMethod("lineTo", t);
  }
  moveTo(...t) {
    return this._callContextMethod("moveTo", t);
  }
  quadraticCurveTo(...t) {
    return this._callContextMethod("quadraticCurveTo", t);
  }
  rect(...t) {
    return this._callContextMethod("rect", t);
  }
  roundRect(...t) {
    return this._callContextMethod("roundRect", t);
  }
  poly(...t) {
    return this._callContextMethod("poly", t);
  }
  regularPoly(...t) {
    return this._callContextMethod("regularPoly", t);
  }
  roundPoly(...t) {
    return this._callContextMethod("roundPoly", t);
  }
  roundShape(...t) {
    return this._callContextMethod("roundShape", t);
  }
  filletRect(...t) {
    return this._callContextMethod("filletRect", t);
  }
  chamferRect(...t) {
    return this._callContextMethod("chamferRect", t);
  }
  star(...t) {
    return this._callContextMethod("star", t);
  }
  svg(...t) {
    return this._callContextMethod("svg", t);
  }
  restore(...t) {
    return this._callContextMethod("restore", t);
  }
  /**
   * Saves the current graphics state onto a stack. The state includes:
   * - Current transformation matrix
   * - Current fill style
   * - Current stroke style
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Save state before complex operations
   * graphics.save();
   *
   * // Create transformed and styled shape
   * graphics
   *     .translateTransform(100, 100)
   *     .rotateTransform(Math.PI / 4)
   *     .setFillStyle({
   *         color: 0xff0000,
   *         alpha: 0.5
   *     })
   *     .rect(-25, -25, 50, 50)
   *     .fill();
   *
   * // Restore to original state
   * graphics.restore();
   *
   * // Continue drawing with previous state
   * graphics
   *     .circle(50, 50, 25)
   *     .fill();
   * ```
   * @returns The Graphics instance for method chaining
   * @see {@link Graphics#restore} For restoring the saved state
   * @see {@link Graphics#setTransform} For setting transformations
   */
  save() {
    return this._callContextMethod("save", []);
  }
  /**
   * Returns the current transformation matrix of the graphics context.
   * This matrix represents all accumulated transformations including translate, scale, and rotate.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Apply some transformations
   * graphics
   *     .translateTransform(100, 100)
   *     .rotateTransform(Math.PI / 4);
   *
   * // Get the current transform matrix
   * const matrix = graphics.getTransform();
   * console.log(matrix.tx, matrix.ty); // 100, 100
   *
   * // Use the matrix for other operations
   * graphics
   *     .setTransform(matrix)
   *     .circle(0, 0, 50)
   *     .fill({ color: 0xff0000 });
   * ```
   * @returns The current transformation matrix.
   * @see {@link Graphics#setTransform} For setting the transform matrix
   * @see {@link Matrix} For matrix operations
   */
  getTransform() {
    return this.context.getTransform();
  }
  /**
   * Resets the current transformation matrix to the identity matrix, effectively removing
   * any transformations (rotation, scaling, translation) previously applied.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Apply transformations
   * graphics
   *     .translateTransform(100, 100)
   *     .scaleTransform(2, 2)
   *     .circle(0, 0, 25)
   *     .fill({ color: 0xff0000 });
   * // Reset transform to default state
   * graphics
   *     .resetTransform()
   *     .circle(50, 50, 25) // Will draw at actual coordinates
   *     .fill({ color: 0x00ff00 });
   * ```
   * @returns The Graphics instance for method chaining
   * @see {@link Graphics#getTransform} For getting the current transform
   * @see {@link Graphics#setTransform} For setting a specific transform
   * @see {@link Graphics#save} For saving the current transform state
   * @see {@link Graphics#restore} For restoring a previous transform state
   */
  resetTransform() {
    return this._callContextMethod("resetTransform", []);
  }
  rotateTransform(...t) {
    return this._callContextMethod("rotate", t);
  }
  scaleTransform(...t) {
    return this._callContextMethod("scale", t);
  }
  setTransform(...t) {
    return this._callContextMethod("setTransform", t);
  }
  transform(...t) {
    return this._callContextMethod("transform", t);
  }
  translateTransform(...t) {
    return this._callContextMethod("translate", t);
  }
  /**
   * Clears all drawing commands from the graphics context, effectively resetting it.
   * This includes clearing the current path, fill style, stroke style, and transformations.
   *
   * > [!NOTE] Graphics objects are not designed to be continuously cleared and redrawn.
   * > Instead, they are intended to be used for static or semi-static graphics that
   * > can be redrawn as needed. Frequent clearing and redrawing may lead to performance issues.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Draw some shapes
   * graphics
   *     .circle(100, 100, 50)
   *     .fill({ color: 0xff0000 })
   *     .rect(200, 100, 100, 50)
   *     .fill({ color: 0x00ff00 });
   *
   * // Clear all graphics
   * graphics.clear();
   *
   * // Start fresh with new shapes
   * graphics
   *     .circle(150, 150, 30)
   *     .fill({ color: 0x0000ff });
   * ```
   * @returns The Graphics instance for method chaining
   * @see {@link Graphics#beginPath} For starting a new path without clearing styles
   * @see {@link Graphics#save} For saving the current state
   * @see {@link Graphics#restore} For restoring a previous state
   */
  clear() {
    return this._callContextMethod("clear", []);
  }
  /**
   * Gets or sets the current fill style for the graphics context. The fill style determines
   * how shapes are filled when using the fill() method.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Basic color fill
   * graphics.fillStyle = {
   *     color: 0xff0000,  // Red
   *     alpha: 1
   * };
   *
   * // Using gradients
   * const gradient = new FillGradient({
   *     end: { x: 0, y: 1 }, // Vertical gradient
   *     stops: [
   *         { offset: 0, color: 0xff0000, alpha: 1 }, // Start color
   *         { offset: 1, color: 0x0000ff, alpha: 1 }  // End color
   *     ]
   * });
   *
   * graphics.fillStyle = {
   *     fill: gradient,
   *     alpha: 0.8
   * };
   *
   * // Using patterns
   * graphics.fillStyle = {
   *     texture: myTexture,
   *     alpha: 1,
   *     matrix: new Matrix()
   *         .scale(0.5, 0.5)
   *         .rotate(Math.PI / 4)
   * };
   * ```
   * @type {ConvertedFillStyle}
   * @see {@link FillStyle} For all available fill style options
   * @see {@link FillGradient} For creating gradient fills
   * @see {@link Graphics#fill} For applying the fill to paths
   */
  get fillStyle() {
    return this._context.fillStyle;
  }
  set fillStyle(t) {
    this._context.fillStyle = t;
  }
  /**
   * Gets or sets the current stroke style for the graphics context. The stroke style determines
   * how paths are outlined when using the stroke() method.
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Basic stroke style
   * graphics.strokeStyle = {
   *     width: 2,
   *     color: 0xff0000,
   *     alpha: 1
   * };
   *
   * // Using with gradients
   * const gradient = new FillGradient({
   *   end: { x: 0, y: 1 },
   *   stops: [
   *       { offset: 0, color: 0xff0000, alpha: 1 },
   *       { offset: 1, color: 0x0000ff, alpha: 1 }
   *   ]
   * });
   *
   * graphics.strokeStyle = {
   *     width: 4,
   *     fill: gradient,
   *     alignment: 0.5,
   *     join: 'round',
   *     cap: 'round'
   * };
   *
   * // Complex stroke settings
   * graphics.strokeStyle = {
   *     width: 6,
   *     color: 0x00ff00,
   *     alpha: 0.5,
   *     join: 'miter',
   *     miterLimit: 10,
   * };
   * ```
   * @see {@link StrokeStyle} For all available stroke style options
   * @see {@link Graphics#stroke} For applying the stroke to paths
   */
  get strokeStyle() {
    return this._context.strokeStyle;
  }
  set strokeStyle(t) {
    this._context.strokeStyle = t;
  }
  /**
   * Creates a new Graphics object that copies the current graphics content.
   * The clone can either share the same context (shallow clone) or have its own independent
   * context (deep clone).
   * @example
   * ```ts
   * const graphics = new Graphics();
   *
   * // Create original graphics content
   * graphics
   *     .circle(100, 100, 50)
   *     .fill({ color: 0xff0000 });
   *
   * // Create a shallow clone (shared context)
   * const shallowClone = graphics.clone();
   *
   * // Changes to original affect the clone
   * graphics
   *     .circle(200, 100, 30)
   *     .fill({ color: 0x00ff00 });
   *
   * // Create a deep clone (independent context)
   * const deepClone = graphics.clone(true);
   *
   * // Modify deep clone independently
   * deepClone
   *     .translateTransform(100, 100)
   *     .circle(0, 0, 40)
   *     .fill({ color: 0x0000ff });
   * ```
   * @param deep - Whether to create a deep clone of the graphics object.
   *              If false (default), the context will be shared between objects.
   *              If true, creates an independent copy of the context.
   * @returns A new Graphics instance with either shared or copied context
   * @see {@link Graphics#context} For accessing the underlying graphics context
   * @see {@link GraphicsContext} For understanding the shared context behavior
   */
  clone(t = !1) {
    return t ? new ie(this._context.clone()) : (this._ownedContext = null, new ie(this._context));
  }
  // -------- v7 deprecations ---------
  /**
   * @param width
   * @param color
   * @param alpha
   * @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead
   */
  lineStyle(t, e, s) {
    ct(kt, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style.");
    const i = {};
    return t && (i.width = t), e && (i.color = e), s && (i.alpha = s), this.context.strokeStyle = i, this;
  }
  /**
   * @param color
   * @param alpha
   * @deprecated since 8.0.0 Use {@link Graphics#fill} instead
   */
  beginFill(t, e) {
    ct(kt, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
    const s = {};
    return t !== void 0 && (s.color = t), e !== void 0 && (s.alpha = e), this.context.fillStyle = s, this;
  }
  /**
   * @deprecated since 8.0.0 Use {@link Graphics#fill} instead
   */
  endFill() {
    ct(kt, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."), this.context.fill();
    const t = this.context.strokeStyle;
    return (t.width !== We.defaultStrokeStyle.width || t.color !== We.defaultStrokeStyle.color || t.alpha !== We.defaultStrokeStyle.alpha) && this.context.stroke(), this;
  }
  /**
   * @param {...any} args
   * @deprecated since 8.0.0 Use {@link Graphics#circle} instead
   */
  drawCircle(...t) {
    return ct(kt, "Graphics#drawCircle has been renamed to Graphics#circle"), this._callContextMethod("circle", t);
  }
  /**
   * @param {...any} args
   * @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead
   */
  drawEllipse(...t) {
    return ct(kt, "Graphics#drawEllipse has been renamed to Graphics#ellipse"), this._callContextMethod("ellipse", t);
  }
  /**
   * @param {...any} args
   * @deprecated since 8.0.0 Use {@link Graphics#poly} instead
   */
  drawPolygon(...t) {
    return ct(kt, "Graphics#drawPolygon has been renamed to Graphics#poly"), this._callContextMethod("poly", t);
  }
  /**
   * @param {...any} args
   * @deprecated since 8.0.0 Use {@link Graphics#rect} instead
   */
  drawRect(...t) {
    return ct(kt, "Graphics#drawRect has been renamed to Graphics#rect"), this._callContextMethod("rect", t);
  }
  /**
   * @param {...any} args
   * @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead
   */
  drawRoundedRect(...t) {
    return ct(kt, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect"), this._callContextMethod("roundRect", t);
  }
  /**
   * @param {...any} args
   * @deprecated since 8.0.0 Use {@link Graphics#star} instead
   */
  drawStar(...t) {
    return ct(kt, "Graphics#drawStar has been renamed to Graphics#star"), this._callContextMethod("star", t);
  }
}
class z_ {
  /**
   * @param options - Options for the transform.
   * @param options.matrix - The matrix to use.
   * @param options.observer - The observer to use.
   */
  constructor({ matrix: t, observer: e } = {}) {
    this.dirty = !0, this._matrix = t ?? new nt(), this.observer = e, this.position = new Pt(this, 0, 0), this.scale = new Pt(this, 1, 1), this.pivot = new Pt(this, 0, 0), this.skew = new Pt(this, 0, 0), this._rotation = 0, this._cx = 1, this._sx = 0, this._cy = 0, this._sy = 1;
  }
  /**
   * The transformation matrix computed from the transform's properties.
   * Combines position, scale, rotation, skew, and pivot into a single matrix.
   * @example
   * ```ts
   * // Get current matrix
   * const matrix = transform.matrix;
   * console.log(matrix.toString());
   * ```
   * @readonly
   * @see {@link Matrix} For matrix operations
   * @see {@link Transform.setFromMatrix} For setting transform from matrix
   */
  get matrix() {
    const t = this._matrix;
    return this.dirty && (t.a = this._cx * this.scale.x, t.b = this._sx * this.scale.x, t.c = this._cy * this.scale.y, t.d = this._sy * this.scale.y, t.tx = this.position.x - (this.pivot.x * t.a + this.pivot.y * t.c), t.ty = this.position.y - (this.pivot.x * t.b + this.pivot.y * t.d), this.dirty = !1), t;
  }
  /**
   * Called when a value changes.
   * @param point
   * @internal
   */
  _onUpdate(t) {
    this.dirty = !0, t === this.skew && this.updateSkew(), this.observer?._onUpdate(this);
  }
  /** Called when the skew or the rotation changes. */
  updateSkew() {
    this._cx = Math.cos(this._rotation + this.skew.y), this._sx = Math.sin(this._rotation + this.skew.y), this._cy = -Math.sin(this._rotation - this.skew.x), this._sy = Math.cos(this._rotation - this.skew.x), this.dirty = !0;
  }
  toString() {
    return `[pixi.js/math:Transform position=(${this.position.x}, ${this.position.y}) rotation=${this.rotation} scale=(${this.scale.x}, ${this.scale.y}) skew=(${this.skew.x}, ${this.skew.y}) ]`;
  }
  /**
   * Decomposes a matrix and sets the transforms properties based on it.
   * @example
   * ```ts
   * // Basic matrix decomposition
   * const transform = new Transform();
   * const matrix = new Matrix()
   *     .translate(100, 100)
   *     .rotate(Math.PI / 4)
   *     .scale(2, 2);
   *
   * transform.setFromMatrix(matrix);
   * console.log(transform.position.x); // 100
   * console.log(transform.rotation); // ~0.785 (π/4)
   * ```
   * @param matrix - The matrix to decompose
   * @see {@link Matrix#decompose} For the decomposition logic
   * @see {@link Transform#matrix} For getting the current matrix
   */
  setFromMatrix(t) {
    t.decompose(this), this.dirty = !0;
  }
  /**
   * The rotation of the object in radians.
   * @example
   * ```ts
   * // Basic rotation
   * transform.rotation = Math.PI / 4; // 45 degrees
   *
   * // Rotate around pivot point
   * transform.pivot.set(50, 50);
   * transform.rotation = Math.PI; // 180 degrees around pivot
   *
   * // Animate rotation
   * app.ticker.add(() => {
   *     transform.rotation += 0.1;
   * });
   * ```
   * @see {@link Transform#pivot} For rotation point
   * @see {@link Transform#skew} For skew effects
   */
  get rotation() {
    return this._rotation;
  }
  set rotation(t) {
    this._rotation !== t && (this._rotation = t, this._onUpdate(this.skew));
  }
}
const jp = class lo extends jo {
  constructor(...t) {
    let e = t[0] || {};
    e instanceof rt && (e = { texture: e }), t.length > 1 && (ct(kt, "use new TilingSprite({ texture, width:100, height:100 }) instead"), e.width = t[1], e.height = t[2]), e = { ...lo.defaultOptions, ...e };
    const {
      texture: s,
      anchor: i,
      tilePosition: r,
      tileScale: o,
      tileRotation: a,
      width: l,
      height: c,
      applyAnchorToTexture: h,
      roundPixels: u,
      ...d
    } = e ?? {};
    super({
      label: "TilingSprite",
      ...d
    }), this.renderPipeId = "tilingSprite", this.batched = !0, this.allowChildren = !1, this._anchor = new Pt(
      {
        _onUpdate: () => {
          this.onViewUpdate();
        }
      }
    ), this.applyAnchorToTexture = h, this.texture = s, this._width = l ?? s.width, this._height = c ?? s.height, this._tileTransform = new z_({
      observer: {
        _onUpdate: () => this.onViewUpdate()
      }
    }), i && (this.anchor = i), this.tilePosition = r, this.tileScale = o, this.tileRotation = a, this.roundPixels = u ?? !1;
  }
  /**
   * Creates a new tiling sprite based on a source texture or image path.
   * This is a convenience method that automatically creates and manages textures.
   * @example
   * ```ts
   * // Create a new tiling sprite from an image path
   * const pattern = TilingSprite.from('pattern.png');
   * pattern.width = 300; // Set the width of the tiling area
   * pattern.height = 200; // Set the height of the tiling area
   *
   * // Create from options
   * const texture = Texture.from('pattern.png');
   * const pattern = TilingSprite.from(texture, {
   *     width: 300,
   *     height: 200,
   *     tileScale: { x: 0.5, y: 0.5 }
   * });
   * ```
   * @param source - The source to create the sprite from. Can be a path to an image or a texture
   * @param options - Additional options for the tiling sprite
   * @returns A new tiling sprite based on the source
   * @see {@link Texture.from} For texture creation details
   * @see {@link Assets} For asset loading and management
   */
  static from(t, e = {}) {
    return typeof t == "string" ? new lo({
      texture: pn.get(t),
      ...e
    }) : new lo({
      texture: t,
      ...e
    });
  }
  /**
   * @see {@link TilingSpriteOptions.applyAnchorToTexture}
   * @deprecated since 8.0.0
   * @advanced
   */
  get uvRespectAnchor() {
    return Ht("uvRespectAnchor is deprecated, please use applyAnchorToTexture instead"), this.applyAnchorToTexture;
  }
  /** @advanced */
  set uvRespectAnchor(t) {
    Ht("uvRespectAnchor is deprecated, please use applyAnchorToTexture instead"), this.applyAnchorToTexture = t;
  }
  /**
   * Changes frame clamping in corresponding textureMatrix
   * Change to -0.5 to add a pixel to the edge, recommended for transparent trimmed textures in atlas
   * @default 0.5
   * @type {number}
   * @advanced
   */
  get clampMargin() {
    return this._texture.textureMatrix.clampMargin;
  }
  /** @advanced */
  set clampMargin(t) {
    this._texture.textureMatrix.clampMargin = t;
  }
  /**
   * The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
   * and passed to the constructor.
   *
   * - The default is `(0,0)`, this means the sprite's origin is the top left.
   * - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
   * - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
   *
   * If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
   * @example
   * ```ts
   * // Center the anchor point
   * sprite.anchor = 0.5; // Sets both x and y to 0.5
   * sprite.position.set(400, 300); // Sprite will be centered at this position
   *
   * // Set specific x/y anchor points
   * sprite.anchor = {
   *     x: 1, // Right edge
   *     y: 0  // Top edge
   * };
   *
   * // Using individual coordinates
   * sprite.anchor.set(0.5, 1); // Center-bottom
   *
   * // For rotation around center
   * sprite.anchor.set(0.5);
   * sprite.rotation = Math.PI / 4; // 45 degrees around center
   *
   * // For scaling from center
   * sprite.anchor.set(0.5);
   * sprite.scale.set(2); // Scales from center point
   * ```
   */
  get anchor() {
    return this._anchor;
  }
  set anchor(t) {
    typeof t == "number" ? this._anchor.set(t) : this._anchor.copyFrom(t);
  }
  /**
   * The offset of the tiling texture.
   * Used to scroll or position the repeated pattern.
   * @example
   * ```ts
   * // Offset the tiling pattern by 100 pixels in both x and y directions
   * tilingSprite.tilePosition = { x: 100, y: 100 };
   * ```
   * @default {x: 0, y: 0}
   */
  get tilePosition() {
    return this._tileTransform.position;
  }
  set tilePosition(t) {
    this._tileTransform.position.copyFrom(t);
  }
  /**
   * Scale of the tiling texture.
   * Affects the size of each repeated instance of the texture.
   * @example
   * ```ts
   * // Scale the texture by 1.5 in both x and y directions
   * tilingSprite.tileScale = { x: 1.5, y: 1.5 };
   * ```
   * @default {x: 1, y: 1}
   */
  get tileScale() {
    return this._tileTransform.scale;
  }
  set tileScale(t) {
    typeof t == "number" ? this._tileTransform.scale.set(t) : this._tileTransform.scale.copyFrom(t);
  }
  set tileRotation(t) {
    this._tileTransform.rotation = t;
  }
  /**
   * Rotation of the tiling texture in radians.
   * This controls the rotation applied to the texture before tiling.
   * @example
   * ```ts
   * // Rotate the texture by 45 degrees (in radians)
   * tilingSprite.tileRotation = Math.PI / 4; // 45 degrees
   * ```
   * @default 0
   */
  get tileRotation() {
    return this._tileTransform.rotation;
  }
  /**
   * The transform object that controls the tiling texture's position, scale, and rotation.
   * This transform is independent of the sprite's own transform properties.
   * @example
   * ```ts
   * // Access transform properties directly
   * sprite.tileTransform.position.set(100, 50);
   * sprite.tileTransform.scale.set(2);
   * sprite.tileTransform.rotation = Math.PI / 4;
   *
   * // Create smooth scrolling animation
   * app.ticker.add(() => {
   *     sprite.tileTransform.position.x += 1;
   *     sprite.tileTransform.rotation += 0.01;
   * });
   *
   * // Reset transform
   * sprite.tileTransform.position.set(0);
   * sprite.tileTransform.scale.set(1);
   * sprite.tileTransform.rotation = 0;
   * ```
   * @returns {Transform} The transform object for the tiling texture
   * @see {@link Transform} For transform operations
   * @see {@link TilingSprite#tilePosition} For position control
   * @see {@link TilingSprite#tileScale} For scale control
   * @see {@link TilingSprite#tileRotation} For rotation control
   * @advanced
   */
  get tileTransform() {
    return this._tileTransform;
  }
  set texture(t) {
    t || (t = rt.EMPTY);
    const e = this._texture;
    e !== t && (e && e.dynamic && e.off("update", this.onViewUpdate, this), t.dynamic && t.on("update", this.onViewUpdate, this), this._texture = t, this.onViewUpdate());
  }
  /**
   * The texture to use for tiling.
   * This is the image that will be repeated across the sprite.
   * @example
   * ```ts
   * // Use a texture from the asset cache
   * tilingSprite.texture = Texture.from('assets/pattern.png');
   * ```
   * @default Texture.WHITE
   */
  get texture() {
    return this._texture;
  }
  /**
   * The width of the tiling area. This defines how wide the area is that the texture will be tiled across.
   * @example
   * ```ts
   * // Create a tiling sprite
   * const sprite = new TilingSprite({
   *     texture: Texture.from('pattern.png'),
   *     width: 500,
   *     height: 300
   * });
   *
   * // Adjust width dynamically
   * sprite.width = 800; // Expands tiling area
   *
   * // Update on resize
   * window.addEventListener('resize', () => {
   *     sprite.width = app.screen.width;
   * });
   * ```
   * @see {@link TilingSprite#setSize} For setting both width and height efficiently
   * @see {@link TilingSprite#height} For setting height
   */
  set width(t) {
    this._width = t, this.onViewUpdate();
  }
  get width() {
    return this._width;
  }
  set height(t) {
    this._height = t, this.onViewUpdate();
  }
  /**
   * The height of the tiling area. This defines how tall the area is that the texture will be tiled across.
   * @example
   * ```ts
   * // Create a tiling sprite
   * const sprite = new TilingSprite({
   *     texture: Texture.from('pattern.png'),
   *     width: 500,
   *     height: 300
   * });
   *
   * // Adjust width dynamically
   * sprite.height = 800; // Expands tiling area
   *
   * // Update on resize
   * window.addEventListener('resize', () => {
   *     sprite.height = app.screen.height;
   * });
   * ```
   * @see {@link TilingSprite#setSize} For setting both width and height efficiently
   * @see {@link TilingSprite#width} For setting width
   */
  get height() {
    return this._height;
  }
  /**
   * Sets the size of the TilingSprite to the specified width and height.
   * This is faster than setting width and height separately as it only triggers one update.
   * @example
   * ```ts
   * // Set specific dimensions
   * sprite.setSize(300, 200); // Width: 300, Height: 200
   *
   * // Set uniform size (square)
   * sprite.setSize(400); // Width: 400, Height: 400
   *
   * // Set size using object
   * sprite.setSize({
   *     width: 500,
   *     height: 300
   * });
   * ```
   * @param value - This can be either a number for uniform sizing or a Size object with width/height properties
   * @param height - The height to set. Defaults to the value of `width` if not provided
   * @see {@link TilingSprite#width} For setting width only
   * @see {@link TilingSprite#height} For setting height only
   */
  setSize(t, e) {
    typeof t == "object" && (e = t.height ?? t.width, t = t.width), this._width = t, this._height = e ?? t, this.onViewUpdate();
  }
  /**
   * Retrieves the size of the TilingSprite as a {@link Size} object.
   * This method is more efficient than getting width and height separately as it only allocates one object.
   * @example
   * ```ts
   * // Get basic size
   * const size = sprite.getSize();
   * console.log(`Size: ${size.width}x${size.height}`);
   *
   * // Reuse existing size object
   * const reuseSize = { width: 0, height: 0 };
   * sprite.getSize(reuseSize);
   * ```
   * @param out - Optional object to store the size in, to avoid allocating a new object
   * @returns The size of the TilingSprite
   * @see {@link TilingSprite#width} For getting just the width
   * @see {@link TilingSprite#height} For getting just the height
   * @see {@link TilingSprite#setSize} For setting both width and height efficiently
   */
  getSize(t) {
    return t || (t = {}), t.width = this._width, t.height = this._height, t;
  }
  /** @private */
  updateBounds() {
    const t = this._bounds, e = this._anchor, s = this._width, i = this._height;
    t.minX = -e._x * s, t.maxX = t.minX + s, t.minY = -e._y * i, t.maxY = t.minY + i;
  }
  /**
   * Checks if the object contains the given point in local coordinates.
   * Takes into account the anchor offset when determining boundaries.
   * @example
   * ```ts
   * // Create a tiling sprite
   * const sprite = new TilingSprite({
   *     texture: Texture.from('pattern.png'),
   *     width: 200,
   *     height: 100,
   *     anchor: 0.5 // Center anchor
   * });
   *
   * // Basic point check
   * const contains = sprite.containsPoint({ x: 50, y: 25 });
   * console.log('Point is inside:', contains);
   *
   * // Check with different anchors
   * sprite.anchor.set(0); // Top-left anchor
   * console.log('Contains point:', sprite.containsPoint({ x: 150, y: 75 }));
   * ```
   * @param point - The point to check in local coordinates
   * @returns True if the point is within the sprite's bounds
   * @see {@link TilingSprite#toLocal} For converting global coordinates to local
   * @see {@link TilingSprite#anchor} For understanding boundary calculations
   */
  containsPoint(t) {
    const e = this._width, s = this._height, i = -e * this._anchor._x;
    let r = 0;
    return t.x >= i && t.x <= i + e && (r = -s * this._anchor._y, t.y >= r && t.y <= r + s);
  }
  /**
   * Destroys this sprite renderable and optionally its texture.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @example
   * tilingSprite.destroy();
   * tilingSprite.destroy(true);
   * tilingSprite.destroy({ texture: true, textureSource: true });
   */
  destroy(t = !1) {
    if (super.destroy(t), this._anchor = null, this._tileTransform = null, this._bounds = null, typeof t == "boolean" ? t : t?.texture) {
      const s = typeof t == "boolean" ? t : t?.textureSource;
      this._texture.destroy(s);
    }
    this._texture = null;
  }
};
jp.defaultOptions = {
  /** The texture to use for the sprite. */
  texture: rt.EMPTY,
  /** The anchor point of the sprite */
  anchor: { x: 0, y: 0 },
  /** The offset of the image that is being tiled. */
  tilePosition: { x: 0, y: 0 },
  /** Scaling of the image that is being tiled. */
  tileScale: { x: 1, y: 1 },
  /** The rotation of the image that is being tiled. */
  tileRotation: 0,
  /**
   * Flags whether the tiling pattern should originate from the origin instead of the top-left corner in
   * local space.
   *
   * This will make the texture coordinates assigned to each vertex dependent on the value of the anchor. Without
   * this, the top-left corner always gets the (0, 0) texture coordinate.
   * @default false
   */
  applyAnchorToTexture: !1
};
let Gu = jp;
class q_ extends jo {
  constructor(t, e) {
    const { text: s, resolution: i, style: r, anchor: o, width: a, height: l, roundPixels: c, ...h } = t;
    super({
      ...h
    }), this.batched = !0, this._resolution = null, this._autoResolution = !0, this._didTextUpdate = !0, this._styleClass = e, this.text = s ?? "", this.style = r, this.resolution = i ?? null, this.allowChildren = !1, this._anchor = new Pt(
      {
        _onUpdate: () => {
          this.onViewUpdate();
        }
      }
    ), o && (this.anchor = o), this.roundPixels = c ?? !1, a !== void 0 && (this.width = a), l !== void 0 && (this.height = l);
  }
  /**
   * The anchor point of the text that controls the origin point for positioning and rotation.
   * Can be a number (same value for x/y) or a PointData object.
   * - (0,0) is top-left
   * - (0.5,0.5) is center
   * - (1,1) is bottom-right
   * ```ts
   * // Set anchor to center
   * const text = new Text({
   *     text: 'Hello Pixi!',
   *     anchor: 0.5 // Same as { x: 0.5, y: 0.5 }
   * });
   * // Set anchor to top-left
   * const text2 = new Text({
   *     text: 'Hello Pixi!',
   *     anchor: { x: 0, y: 0 } // Top-left corner
   * });
   * // Set anchor to bottom-right
   * const text3 = new Text({
   *     text: 'Hello Pixi!',
   *     anchor: { x: 1, y: 1 } // Bottom-right corner
   * });
   * ```
   * @default { x: 0, y: 0 }
   */
  get anchor() {
    return this._anchor;
  }
  set anchor(t) {
    typeof t == "number" ? this._anchor.set(t) : this._anchor.copyFrom(t);
  }
  /**
   * The text content to display. Use '\n' for line breaks.
   * Accepts strings, numbers, or objects with toString() method.
   * @example
   * ```ts
   * const text = new Text({
   *     text: 'Hello Pixi!',
   * });
   * const multilineText = new Text({
   *     text: 'Line 1\nLine 2\nLine 3',
   * });
   * const numberText = new Text({
   *     text: 12345, // Will be converted to '12345'
   * });
   * const objectText = new Text({
   *     text: { toString: () => 'Object Text' }, // Custom toString
   * });
   *
   * // Update text dynamically
   * text.text = 'Updated Text'; // Re-renders with new text
   * text.text = 67890; // Updates to '67890'
   * text.text = { toString: () => 'Dynamic Text' }; // Uses custom toString method
   * // Clear text
   * text.text = ''; // Clears the text
   * ```
   * @default ''
   */
  set text(t) {
    t = t.toString(), this._text !== t && (this._text = t, this.onViewUpdate());
  }
  get text() {
    return this._text;
  }
  /**
   * The resolution/device pixel ratio for rendering.
   * Higher values result in sharper text at the cost of performance.
   * Set to null for auto-resolution based on device.
   * @example
   * ```ts
   * const text = new Text({
   *     text: 'Hello Pixi!',
   *     resolution: 2 // High DPI for sharper text
   * });
   * const autoResText = new Text({
   *     text: 'Auto Resolution',
   *     resolution: null // Use device's pixel ratio
   * });
   * ```
   * @default null
   */
  set resolution(t) {
    this._autoResolution = t === null, this._resolution = t, this.onViewUpdate();
  }
  get resolution() {
    return this._resolution;
  }
  get style() {
    return this._style;
  }
  /**
   * The style configuration for the text.
   * Can be a TextStyle instance or a configuration object.
   * Supports canvas text styles, HTML text styles, and bitmap text styles.
   * @example
   * ```ts
   * const text = new Text({
   *     text: 'Styled Text',
   *     style: {
   *         fontSize: 24,
   *         fill: 0xff1010, // Red color
   *         fontFamily: 'Arial',
   *         align: 'center', // Center alignment
   *         stroke: { color: '#4a1850', width: 5 }, // Purple stroke
   *         dropShadow: {
   *             color: '#000000', // Black shadow
   *             blur: 4, // Shadow blur
   *             distance: 6 // Shadow distance
   *         }
   *     }
   * });
   * const htmlText = new HTMLText({
   *     text: 'HTML Styled Text',
   *     style: {
   *         fontSize: '20px',
   *         fill: 'blue',
   *         fontFamily: 'Verdana',
   *     }
   * });
   * const bitmapText = new BitmapText({
   *     text: 'Bitmap Styled Text',
   *     style: {
   *         fontName: 'Arial',
   *         fontSize: 32,
   *     }
   * })
   *
   * // Update style dynamically
   * text.style = {
   *     fontSize: 30, // Change font size
   *     fill: 0x00ff00, // Change color to green
   *     align: 'right', // Change alignment to right
   *     stroke: { color: '#000000', width: 2 }, // Add black stroke
   * }
   */
  set style(t) {
    t || (t = {}), this._style?.off("update", this.onViewUpdate, this), t instanceof this._styleClass ? this._style = t : this._style = new this._styleClass(t), this._style.on("update", this.onViewUpdate, this), this.onViewUpdate();
  }
  /**
   * The width of the sprite, setting this will actually modify the scale to achieve the value set.
   * @example
   * ```ts
   * // Set width directly
   * texture.width = 200;
   * console.log(texture.scale.x); // Scale adjusted to match width
   *
   * // For better performance when setting both width and height
   * texture.setSize(300, 400); // Avoids recalculating bounds twice
   * ```
   */
  get width() {
    return Math.abs(this.scale.x) * this.bounds.width;
  }
  set width(t) {
    this._setWidth(t, this.bounds.width);
  }
  /**
   * The height of the sprite, setting this will actually modify the scale to achieve the value set.
   * @example
   * ```ts
   * // Set height directly
   * texture.height = 200;
   * console.log(texture.scale.y); // Scale adjusted to match height
   *
   * // For better performance when setting both width and height
   * texture.setSize(300, 400); // Avoids recalculating bounds twice
   * ```
   */
  get height() {
    return Math.abs(this.scale.y) * this.bounds.height;
  }
  set height(t) {
    this._setHeight(t, this.bounds.height);
  }
  /**
   * Retrieves the size of the Text as a [Size]{@link Size} object based on the texture dimensions and scale.
   * This is faster than getting width and height separately as it only calculates the bounds once.
   * @example
   * ```ts
   * // Basic size retrieval
   * const text = new Text({
   *     text: 'Hello Pixi!',
   *     style: { fontSize: 24 }
   * });
   * const size = text.getSize();
   * console.log(`Size: ${size.width}x${size.height}`);
   *
   * // Reuse existing size object
   * const reuseSize = { width: 0, height: 0 };
   * text.getSize(reuseSize);
   * ```
   * @param out - Optional object to store the size in, to avoid allocating a new object
   * @returns The size of the Sprite
   * @see {@link Text#width} For getting just the width
   * @see {@link Text#height} For getting just the height
   * @see {@link Text#setSize} For setting both width and height
   */
  getSize(t) {
    return t || (t = {}), t.width = Math.abs(this.scale.x) * this.bounds.width, t.height = Math.abs(this.scale.y) * this.bounds.height, t;
  }
  /**
   * Sets the size of the Text to the specified width and height.
   * This is faster than setting width and height separately as it only recalculates bounds once.
   * @example
   * ```ts
   * // Basic size setting
   * const text = new Text({
   *    text: 'Hello Pixi!',
   *    style: { fontSize: 24 }
   * });
   * text.setSize(100, 200); // Width: 100, Height: 200
   *
   * // Set uniform size
   * text.setSize(100); // Sets both width and height to 100
   *
   * // Set size with object
   * text.setSize({
   *     width: 200,
   *     height: 300
   * });
   * ```
   * @param value - This can be either a number or a {@link Size} object
   * @param height - The height to set. Defaults to the value of `width` if not provided
   * @see {@link Text#width} For setting width only
   * @see {@link Text#height} For setting height only
   */
  setSize(t, e) {
    typeof t == "object" ? (e = t.height ?? t.width, t = t.width) : e ?? (e = t), t !== void 0 && this._setWidth(t, this.bounds.width), e !== void 0 && this._setHeight(e, this.bounds.height);
  }
  /**
   * Checks if the object contains the given point in local coordinates.
   * Uses the text's bounds for hit testing.
   * @example
   * ```ts
   * // Basic point check
   * const localPoint = { x: 50, y: 25 };
   * const contains = text.containsPoint(localPoint);
   * console.log('Point is inside:', contains);
   * ```
   * @param point - The point to check in local coordinates
   * @returns True if the point is within the text's bounds
   * @see {@link Container#toLocal} For converting global coordinates to local
   */
  containsPoint(t) {
    const e = this.bounds.width, s = this.bounds.height, i = -e * this.anchor.x;
    let r = 0;
    return t.x >= i && t.x <= i + e && (r = -s * this.anchor.y, t.y >= r && t.y <= r + s);
  }
  /** @internal */
  onViewUpdate() {
    this.didViewUpdate || (this._didTextUpdate = !0), super.onViewUpdate();
  }
  /**
   * Destroys this text renderable and optionally its style texture.
   * @param options - Options parameter. A boolean will act as if all options
   *  have been set to that value
   * @example
   * // Destroys the text and its style
   * text.destroy({ style: true, texture: true, textureSource: true });
   * text.destroy(true);
   * text.destroy() // Destroys the text, but not its style
   */
  destroy(t = !1) {
    super.destroy(t), this.owner = null, this._bounds = null, this._anchor = null, (typeof t == "boolean" ? t : t?.style) && this._style.destroy(t), this._style = null, this._text = null;
  }
}
function U_(n, t) {
  let e = n[0] ?? {};
  return (typeof e == "string" || n[1]) && (ct(kt, `use new ${t}({ text: "hi!", style }) instead`), e = {
    text: e,
    style: n[1]
  }), e;
}
let on = null, Ts = null;
function G_(n, t) {
  on || (on = Ae.get().createCanvas(256, 128), Ts = on.getContext("2d", { willReadFrequently: !0 }), Ts.globalCompositeOperation = "copy", Ts.globalAlpha = 1), (on.width < n || on.height < t) && (on.width = Xn(n), on.height = Xn(t));
}
function Wu(n, t, e) {
  for (let s = 0, i = 4 * e * t; s < t; ++s, i += 4)
    if (n[i + 3] !== 0)
      return !1;
  return !0;
}
function $u(n, t, e, s, i) {
  const r = 4 * t;
  for (let o = s, a = s * r + 4 * e; o <= i; ++o, a += r)
    if (n[a + 3] !== 0)
      return !1;
  return !0;
}
function W_(...n) {
  let t = n[0];
  t.canvas || (t = { canvas: n[0], resolution: n[1] });
  const { canvas: e } = t, s = Math.min(t.resolution ?? 1, 1), i = t.width ?? e.width, r = t.height ?? e.height;
  let o = t.output;
  if (G_(i, r), !Ts)
    throw new TypeError("Failed to get canvas 2D context");
  Ts.drawImage(
    e,
    0,
    0,
    i,
    r,
    0,
    0,
    i * s,
    r * s
  );
  const l = Ts.getImageData(0, 0, i, r).data;
  let c = 0, h = 0, u = i - 1, d = r - 1;
  for (; h < r && Wu(l, i, h); )
    ++h;
  if (h === r)
    return Dt.EMPTY;
  for (; Wu(l, i, d); )
    --d;
  for (; $u(l, i, c, h, d); )
    ++c;
  for (; $u(l, i, u, h, d); )
    --u;
  return ++u, ++d, Ts.globalCompositeOperation = "source-over", Ts.strokeRect(c, h, u - c, d - h), Ts.globalCompositeOperation = "copy", o ?? (o = new Dt()), o.set(c / s, h / s, (u - c) / s, (d - h) / s), o;
}
const Hu = new Dt();
class $_ {
  /**
   * Creates a canvas with the specified text rendered to it.
   *
   * Generates a canvas of appropriate size, renders the text with the provided style,
   * and returns both the canvas/context and a Rectangle representing the text bounds.
   *
   * When trim is enabled in the style, the frame will represent the bounds of the
   * non-transparent pixels, which can be smaller than the full canvas.
   * @param options - The options for generating the text canvas
   * @param options.text - The text to render
   * @param options.style - The style to apply to the text
   * @param options.resolution - The resolution of the canvas (defaults to 1)
   * @param options.padding
   * @returns An object containing the canvas/context and the frame (bounds) of the text
   */
  getCanvasAndContext(t) {
    const { text: e, style: s, resolution: i = 1 } = t, r = s._getFinalPadding(), o = Bn.measureText(e || " ", s), a = Math.ceil(Math.ceil(Math.max(1, o.width) + r * 2) * i), l = Math.ceil(Math.ceil(Math.max(1, o.height) + r * 2) * i), c = zu.getOptimalCanvasAndContext(a, l);
    this._renderTextToCanvas(e, s, r, i, c);
    const h = s.trim ? W_({ canvas: c.canvas, width: a, height: l, resolution: 1, output: Hu }) : Hu.set(0, 0, a, l);
    return {
      canvasAndContext: c,
      frame: h
    };
  }
  /**
   * Returns a canvas and context to the pool.
   *
   * This should be called when you're done with the canvas to allow reuse
   * and prevent memory leaks.
   * @param canvasAndContext - The canvas and context to return to the pool
   */
  returnCanvasAndContext(t) {
    zu.returnCanvasAndContext(t);
  }
  /**
   * Renders text to its canvas, and updates its texture.
   * @param text - The text to render
   * @param style - The style of the text
   * @param padding - The padding of the text
   * @param resolution - The resolution of the text
   * @param canvasAndContext - The canvas and context to render the text to
   */
  _renderTextToCanvas(t, e, s, i, r) {
    const { canvas: o, context: a } = r, l = kp(e), c = Bn.measureText(t || " ", e), h = c.lines, u = c.lineHeight, d = c.lineWidths, f = c.maxLineWidth, p = c.fontProperties, g = o.height;
    if (a.resetTransform(), a.scale(i, i), a.textBaseline = e.textBaseline, e._stroke?.width) {
      const v = e._stroke;
      a.lineWidth = v.width, a.miterLimit = v.miterLimit, a.lineJoin = v.join, a.lineCap = v.cap;
    }
    a.font = l;
    let m, y;
    const x = e.dropShadow ? 2 : 1;
    for (let v = 0; v < x; ++v) {
      const _ = e.dropShadow && v === 0, b = _ ? Math.ceil(Math.max(1, g) + s * 2) : 0, w = b * i;
      if (_) {
        a.fillStyle = "black", a.strokeStyle = "black";
        const k = e.dropShadow, C = k.color, M = k.alpha;
        a.shadowColor = Bt.shared.setValue(C).setAlpha(M).toRgbaString();
        const A = k.blur * i, I = k.distance * i;
        a.shadowBlur = A, a.shadowOffsetX = Math.cos(k.angle) * I, a.shadowOffsetY = Math.sin(k.angle) * I + w;
      } else {
        if (a.fillStyle = e._fill ? Uu(e._fill, a, c, s * 2) : null, e._stroke?.width) {
          const k = e._stroke.width * 0.5 + s * 2;
          a.strokeStyle = Uu(e._stroke, a, c, k);
        }
        a.shadowColor = "black";
      }
      let S = (u - p.fontSize) / 2;
      u - p.fontSize < 0 && (S = 0);
      const T = e._stroke?.width ?? 0;
      for (let k = 0; k < h.length; k++)
        m = T / 2, y = T / 2 + k * u + p.ascent + S, e.align === "right" ? m += f - d[k] : e.align === "center" && (m += (f - d[k]) / 2), e._stroke?.width && this._drawLetterSpacing(
          h[k],
          e,
          r,
          m + s,
          y + s - b,
          !0
        ), e._fill !== void 0 && this._drawLetterSpacing(
          h[k],
          e,
          r,
          m + s,
          y + s - b
        );
    }
  }
  /**
   * Render the text with letter-spacing.
   *
   * This method handles rendering text with the correct letter spacing, using either:
   * 1. Native letter spacing if supported by the browser
   * 2. Manual letter spacing calculation if not natively supported
   *
   * For manual letter spacing, it calculates the position of each character
   * based on its width and the desired spacing.
   * @param text - The text to draw
   * @param style - The text style to apply
   * @param canvasAndContext - The canvas and context to draw to
   * @param x - Horizontal position to draw the text
   * @param y - Vertical position to draw the text
   * @param isStroke - Whether to render the stroke (true) or fill (false)
   * @private
   */
  _drawLetterSpacing(t, e, s, i, r, o = !1) {
    const { context: a } = s, l = e.letterSpacing;
    let c = !1;
    if (Bn.experimentalLetterSpacingSupported && (Bn.experimentalLetterSpacing ? (a.letterSpacing = `${l}px`, a.textLetterSpacing = `${l}px`, c = !0) : (a.letterSpacing = "0px", a.textLetterSpacing = "0px")), l === 0 || c) {
      o ? a.strokeText(t, i, r) : a.fillText(t, i, r);
      return;
    }
    let h = i;
    const u = Bn.graphemeSegmenter(t);
    let d = a.measureText(t).width, f = 0;
    for (let p = 0; p < u.length; ++p) {
      const g = u[p];
      o ? a.strokeText(g, h, r) : a.fillText(g, h, r);
      let m = "";
      for (let y = p + 1; y < u.length; ++y)
        m += u[y];
      f = a.measureText(m).width, h += d - f + l, d = f;
    }
  }
}
const ju = new $_();
class Ga extends q_ {
  constructor(...t) {
    const e = U_(t, "Text");
    super(e, Hp), this.renderPipeId = "text", e.textureStyle && (this.textureStyle = e.textureStyle instanceof mo ? e.textureStyle : new mo(e.textureStyle));
  }
  /** @private */
  updateBounds() {
    const t = this._bounds, e = this._anchor;
    let s = 0, i = 0;
    if (this._style.trim) {
      const { frame: r, canvasAndContext: o } = ju.getCanvasAndContext({
        text: this.text,
        style: this._style,
        resolution: 1
      });
      ju.returnCanvasAndContext(o), s = r.width, i = r.height;
    } else {
      const r = Bn.measureText(
        this._text,
        this._style
      );
      s = r.width, i = r.height;
    }
    t.minX = -e._x * s, t.maxX = t.minX + s, t.minY = -e._y * i, t.maxY = t.minY + i;
  }
}
ze.add($g, Hg);
function co(n, t) {
  return n == null || t == null ? NaN : n < t ? -1 : n > t ? 1 : n >= t ? 0 : NaN;
}
function H_(n, t) {
  return n == null || t == null ? NaN : t < n ? -1 : t > n ? 1 : t >= n ? 0 : NaN;
}
function Xp(n) {
  let t, e, s;
  n.length !== 2 ? (t = co, e = (a, l) => co(n(a), l), s = (a, l) => n(a) - l) : (t = n === co || n === H_ ? n : j_, e = n, s = n);
  function i(a, l, c = 0, h = a.length) {
    if (c < h) {
      if (t(l, l) !== 0) return h;
      do {
        const u = c + h >>> 1;
        e(a[u], l) < 0 ? c = u + 1 : h = u;
      } while (c < h);
    }
    return c;
  }
  function r(a, l, c = 0, h = a.length) {
    if (c < h) {
      if (t(l, l) !== 0) return h;
      do {
        const u = c + h >>> 1;
        e(a[u], l) <= 0 ? c = u + 1 : h = u;
      } while (c < h);
    }
    return c;
  }
  function o(a, l, c = 0, h = a.length) {
    const u = i(a, l, c, h - 1);
    return u > c && s(a[u - 1], l) > -s(a[u], l) ? u - 1 : u;
  }
  return { left: i, center: o, right: r };
}
function j_() {
  return 0;
}
function X_(n) {
  return n === null ? NaN : +n;
}
const Y_ = Xp(co), Z_ = Y_.right;
Xp(X_).center;
const K_ = Math.sqrt(50), Q_ = Math.sqrt(10), J_ = Math.sqrt(2);
function xo(n, t, e) {
  const s = (t - n) / Math.max(0, e), i = Math.floor(Math.log10(s)), r = s / Math.pow(10, i), o = r >= K_ ? 10 : r >= Q_ ? 5 : r >= J_ ? 2 : 1;
  let a, l, c;
  return i < 0 ? (c = Math.pow(10, -i) / o, a = Math.round(n * c), l = Math.round(t * c), a / c < n && ++a, l / c > t && --l, c = -c) : (c = Math.pow(10, i) * o, a = Math.round(n / c), l = Math.round(t / c), a * c < n && ++a, l * c > t && --l), l < a && 0.5 <= e && e < 2 ? xo(n, t, e * 2) : [a, l, c];
}
function tv(n, t, e) {
  if (t = +t, n = +n, e = +e, !(e > 0)) return [];
  if (n === t) return [n];
  const s = t < n, [i, r, o] = s ? xo(t, n, e) : xo(n, t, e);
  if (!(r >= i)) return [];
  const a = r - i + 1, l = new Array(a);
  if (s)
    if (o < 0) for (let c = 0; c < a; ++c) l[c] = (r - c) / -o;
    else for (let c = 0; c < a; ++c) l[c] = (r - c) * o;
  else if (o < 0) for (let c = 0; c < a; ++c) l[c] = (i + c) / -o;
  else for (let c = 0; c < a; ++c) l[c] = (i + c) * o;
  return l;
}
function wl(n, t, e) {
  return t = +t, n = +n, e = +e, xo(n, t, e)[2];
}
function ev(n, t, e) {
  t = +t, n = +n, e = +e;
  const s = t < n, i = s ? wl(t, n, e) : wl(n, t, e);
  return (s ? -1 : 1) * (i < 0 ? 1 / -i : i);
}
function sv(n, t) {
  switch (arguments.length) {
    case 0:
      break;
    case 1:
      this.range(n);
      break;
    default:
      this.range(t).domain(n);
      break;
  }
  return this;
}
function rc(n, t, e) {
  n.prototype = t.prototype = e, e.constructor = n;
}
function Yp(n, t) {
  var e = Object.create(n.prototype);
  for (var s in t) e[s] = t[s];
  return e;
}
function ur() {
}
var er = 0.7, _o = 1 / er, Hn = "\\s*([+-]?\\d+)\\s*", sr = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*", cs = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*", nv = /^#([0-9a-f]{3,8})$/, iv = new RegExp(`^rgb\\(${Hn},${Hn},${Hn}\\)$`), rv = new RegExp(`^rgb\\(${cs},${cs},${cs}\\)$`), ov = new RegExp(`^rgba\\(${Hn},${Hn},${Hn},${sr}\\)$`), av = new RegExp(`^rgba\\(${cs},${cs},${cs},${sr}\\)$`), lv = new RegExp(`^hsl\\(${sr},${cs},${cs}\\)$`), cv = new RegExp(`^hsla\\(${sr},${cs},${cs},${sr}\\)$`), Xu = {
  aliceblue: 15792383,
  antiquewhite: 16444375,
  aqua: 65535,
  aquamarine: 8388564,
  azure: 15794175,
  beige: 16119260,
  bisque: 16770244,
  black: 0,
  blanchedalmond: 16772045,
  blue: 255,
  blueviolet: 9055202,
  brown: 10824234,
  burlywood: 14596231,
  cadetblue: 6266528,
  chartreuse: 8388352,
  chocolate: 13789470,
  coral: 16744272,
  cornflowerblue: 6591981,
  cornsilk: 16775388,
  crimson: 14423100,
  cyan: 65535,
  darkblue: 139,
  darkcyan: 35723,
  darkgoldenrod: 12092939,
  darkgray: 11119017,
  darkgreen: 25600,
  darkgrey: 11119017,
  darkkhaki: 12433259,
  darkmagenta: 9109643,
  darkolivegreen: 5597999,
  darkorange: 16747520,
  darkorchid: 10040012,
  darkred: 9109504,
  darksalmon: 15308410,
  darkseagreen: 9419919,
  darkslateblue: 4734347,
  darkslategray: 3100495,
  darkslategrey: 3100495,
  darkturquoise: 52945,
  darkviolet: 9699539,
  deeppink: 16716947,
  deepskyblue: 49151,
  dimgray: 6908265,
  dimgrey: 6908265,
  dodgerblue: 2003199,
  firebrick: 11674146,
  floralwhite: 16775920,
  forestgreen: 2263842,
  fuchsia: 16711935,
  gainsboro: 14474460,
  ghostwhite: 16316671,
  gold: 16766720,
  goldenrod: 14329120,
  gray: 8421504,
  green: 32768,
  greenyellow: 11403055,
  grey: 8421504,
  honeydew: 15794160,
  hotpink: 16738740,
  indianred: 13458524,
  indigo: 4915330,
  ivory: 16777200,
  khaki: 15787660,
  lavender: 15132410,
  lavenderblush: 16773365,
  lawngreen: 8190976,
  lemonchiffon: 16775885,
  lightblue: 11393254,
  lightcoral: 15761536,
  lightcyan: 14745599,
  lightgoldenrodyellow: 16448210,
  lightgray: 13882323,
  lightgreen: 9498256,
  lightgrey: 13882323,
  lightpink: 16758465,
  lightsalmon: 16752762,
  lightseagreen: 2142890,
  lightskyblue: 8900346,
  lightslategray: 7833753,
  lightslategrey: 7833753,
  lightsteelblue: 11584734,
  lightyellow: 16777184,
  lime: 65280,
  limegreen: 3329330,
  linen: 16445670,
  magenta: 16711935,
  maroon: 8388608,
  mediumaquamarine: 6737322,
  mediumblue: 205,
  mediumorchid: 12211667,
  mediumpurple: 9662683,
  mediumseagreen: 3978097,
  mediumslateblue: 8087790,
  mediumspringgreen: 64154,
  mediumturquoise: 4772300,
  mediumvioletred: 13047173,
  midnightblue: 1644912,
  mintcream: 16121850,
  mistyrose: 16770273,
  moccasin: 16770229,
  navajowhite: 16768685,
  navy: 128,
  oldlace: 16643558,
  olive: 8421376,
  olivedrab: 7048739,
  orange: 16753920,
  orangered: 16729344,
  orchid: 14315734,
  palegoldenrod: 15657130,
  palegreen: 10025880,
  paleturquoise: 11529966,
  palevioletred: 14381203,
  papayawhip: 16773077,
  peachpuff: 16767673,
  peru: 13468991,
  pink: 16761035,
  plum: 14524637,
  powderblue: 11591910,
  purple: 8388736,
  rebeccapurple: 6697881,
  red: 16711680,
  rosybrown: 12357519,
  royalblue: 4286945,
  saddlebrown: 9127187,
  salmon: 16416882,
  sandybrown: 16032864,
  seagreen: 3050327,
  seashell: 16774638,
  sienna: 10506797,
  silver: 12632256,
  skyblue: 8900331,
  slateblue: 6970061,
  slategray: 7372944,
  slategrey: 7372944,
  snow: 16775930,
  springgreen: 65407,
  steelblue: 4620980,
  tan: 13808780,
  teal: 32896,
  thistle: 14204888,
  tomato: 16737095,
  turquoise: 4251856,
  violet: 15631086,
  wheat: 16113331,
  white: 16777215,
  whitesmoke: 16119285,
  yellow: 16776960,
  yellowgreen: 10145074
};
rc(ur, nr, {
  copy(n) {
    return Object.assign(new this.constructor(), this, n);
  },
  displayable() {
    return this.rgb().displayable();
  },
  hex: Yu,
  // Deprecated! Use color.formatHex.
  formatHex: Yu,
  formatHex8: hv,
  formatHsl: uv,
  formatRgb: Zu,
  toString: Zu
});
function Yu() {
  return this.rgb().formatHex();
}
function hv() {
  return this.rgb().formatHex8();
}
function uv() {
  return Zp(this).formatHsl();
}
function Zu() {
  return this.rgb().formatRgb();
}
function nr(n) {
  var t, e;
  return n = (n + "").trim().toLowerCase(), (t = nv.exec(n)) ? (e = t[1].length, t = parseInt(t[1], 16), e === 6 ? Ku(t) : e === 3 ? new _e(t >> 8 & 15 | t >> 4 & 240, t >> 4 & 15 | t & 240, (t & 15) << 4 | t & 15, 1) : e === 8 ? Kr(t >> 24 & 255, t >> 16 & 255, t >> 8 & 255, (t & 255) / 255) : e === 4 ? Kr(t >> 12 & 15 | t >> 8 & 240, t >> 8 & 15 | t >> 4 & 240, t >> 4 & 15 | t & 240, ((t & 15) << 4 | t & 15) / 255) : null) : (t = iv.exec(n)) ? new _e(t[1], t[2], t[3], 1) : (t = rv.exec(n)) ? new _e(t[1] * 255 / 100, t[2] * 255 / 100, t[3] * 255 / 100, 1) : (t = ov.exec(n)) ? Kr(t[1], t[2], t[3], t[4]) : (t = av.exec(n)) ? Kr(t[1] * 255 / 100, t[2] * 255 / 100, t[3] * 255 / 100, t[4]) : (t = lv.exec(n)) ? td(t[1], t[2] / 100, t[3] / 100, 1) : (t = cv.exec(n)) ? td(t[1], t[2] / 100, t[3] / 100, t[4]) : Xu.hasOwnProperty(n) ? Ku(Xu[n]) : n === "transparent" ? new _e(NaN, NaN, NaN, 0) : null;
}
function Ku(n) {
  return new _e(n >> 16 & 255, n >> 8 & 255, n & 255, 1);
}
function Kr(n, t, e, s) {
  return s <= 0 && (n = t = e = NaN), new _e(n, t, e, s);
}
function dv(n) {
  return n instanceof ur || (n = nr(n)), n ? (n = n.rgb(), new _e(n.r, n.g, n.b, n.opacity)) : new _e();
}
function Sl(n, t, e, s) {
  return arguments.length === 1 ? dv(n) : new _e(n, t, e, s ?? 1);
}
function _e(n, t, e, s) {
  this.r = +n, this.g = +t, this.b = +e, this.opacity = +s;
}
rc(_e, Sl, Yp(ur, {
  brighter(n) {
    return n = n == null ? _o : Math.pow(_o, n), new _e(this.r * n, this.g * n, this.b * n, this.opacity);
  },
  darker(n) {
    return n = n == null ? er : Math.pow(er, n), new _e(this.r * n, this.g * n, this.b * n, this.opacity);
  },
  rgb() {
    return this;
  },
  clamp() {
    return new _e(bn(this.r), bn(this.g), bn(this.b), vo(this.opacity));
  },
  displayable() {
    return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
  },
  hex: Qu,
  // Deprecated! Use color.formatHex.
  formatHex: Qu,
  formatHex8: fv,
  formatRgb: Ju,
  toString: Ju
}));
function Qu() {
  return `#${yn(this.r)}${yn(this.g)}${yn(this.b)}`;
}
function fv() {
  return `#${yn(this.r)}${yn(this.g)}${yn(this.b)}${yn((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;
}
function Ju() {
  const n = vo(this.opacity);
  return `${n === 1 ? "rgb(" : "rgba("}${bn(this.r)}, ${bn(this.g)}, ${bn(this.b)}${n === 1 ? ")" : `, ${n})`}`;
}
function vo(n) {
  return isNaN(n) ? 1 : Math.max(0, Math.min(1, n));
}
function bn(n) {
  return Math.max(0, Math.min(255, Math.round(n) || 0));
}
function yn(n) {
  return n = bn(n), (n < 16 ? "0" : "") + n.toString(16);
}
function td(n, t, e, s) {
  return s <= 0 ? n = t = e = NaN : e <= 0 || e >= 1 ? n = t = NaN : t <= 0 && (n = NaN), new He(n, t, e, s);
}
function Zp(n) {
  if (n instanceof He) return new He(n.h, n.s, n.l, n.opacity);
  if (n instanceof ur || (n = nr(n)), !n) return new He();
  if (n instanceof He) return n;
  n = n.rgb();
  var t = n.r / 255, e = n.g / 255, s = n.b / 255, i = Math.min(t, e, s), r = Math.max(t, e, s), o = NaN, a = r - i, l = (r + i) / 2;
  return a ? (t === r ? o = (e - s) / a + (e < s) * 6 : e === r ? o = (s - t) / a + 2 : o = (t - e) / a + 4, a /= l < 0.5 ? r + i : 2 - r - i, o *= 60) : a = l > 0 && l < 1 ? 0 : o, new He(o, a, l, n.opacity);
}
function pv(n, t, e, s) {
  return arguments.length === 1 ? Zp(n) : new He(n, t, e, s ?? 1);
}
function He(n, t, e, s) {
  this.h = +n, this.s = +t, this.l = +e, this.opacity = +s;
}
rc(He, pv, Yp(ur, {
  brighter(n) {
    return n = n == null ? _o : Math.pow(_o, n), new He(this.h, this.s, this.l * n, this.opacity);
  },
  darker(n) {
    return n = n == null ? er : Math.pow(er, n), new He(this.h, this.s, this.l * n, this.opacity);
  },
  rgb() {
    var n = this.h % 360 + (this.h < 0) * 360, t = isNaN(n) || isNaN(this.s) ? 0 : this.s, e = this.l, s = e + (e < 0.5 ? e : 1 - e) * t, i = 2 * e - s;
    return new _e(
      Wa(n >= 240 ? n - 240 : n + 120, i, s),
      Wa(n, i, s),
      Wa(n < 120 ? n + 240 : n - 120, i, s),
      this.opacity
    );
  },
  clamp() {
    return new He(ed(this.h), Qr(this.s), Qr(this.l), vo(this.opacity));
  },
  displayable() {
    return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
  },
  formatHsl() {
    const n = vo(this.opacity);
    return `${n === 1 ? "hsl(" : "hsla("}${ed(this.h)}, ${Qr(this.s) * 100}%, ${Qr(this.l) * 100}%${n === 1 ? ")" : `, ${n})`}`;
  }
}));
function ed(n) {
  return n = (n || 0) % 360, n < 0 ? n + 360 : n;
}
function Qr(n) {
  return Math.max(0, Math.min(1, n || 0));
}
function Wa(n, t, e) {
  return (n < 60 ? t + (e - t) * n / 60 : n < 180 ? e : n < 240 ? t + (e - t) * (240 - n) / 60 : t) * 255;
}
const oc = (n) => () => n;
function mv(n, t) {
  return function(e) {
    return n + e * t;
  };
}
function gv(n, t, e) {
  return n = Math.pow(n, e), t = Math.pow(t, e) - n, e = 1 / e, function(s) {
    return Math.pow(n + s * t, e);
  };
}
function yv(n) {
  return (n = +n) == 1 ? Kp : function(t, e) {
    return e - t ? gv(t, e, n) : oc(isNaN(t) ? e : t);
  };
}
function Kp(n, t) {
  var e = t - n;
  return e ? mv(n, e) : oc(isNaN(n) ? t : n);
}
const sd = function n(t) {
  var e = yv(t);
  function s(i, r) {
    var o = e((i = Sl(i)).r, (r = Sl(r)).r), a = e(i.g, r.g), l = e(i.b, r.b), c = Kp(i.opacity, r.opacity);
    return function(h) {
      return i.r = o(h), i.g = a(h), i.b = l(h), i.opacity = c(h), i + "";
    };
  }
  return s.gamma = n, s;
}(1);
function xv(n, t) {
  t || (t = []);
  var e = n ? Math.min(t.length, n.length) : 0, s = t.slice(), i;
  return function(r) {
    for (i = 0; i < e; ++i) s[i] = n[i] * (1 - r) + t[i] * r;
    return s;
  };
}
function _v(n) {
  return ArrayBuffer.isView(n) && !(n instanceof DataView);
}
function vv(n, t) {
  var e = t ? t.length : 0, s = n ? Math.min(e, n.length) : 0, i = new Array(s), r = new Array(e), o;
  for (o = 0; o < s; ++o) i[o] = ac(n[o], t[o]);
  for (; o < e; ++o) r[o] = t[o];
  return function(a) {
    for (o = 0; o < s; ++o) r[o] = i[o](a);
    return r;
  };
}
function bv(n, t) {
  var e = /* @__PURE__ */ new Date();
  return n = +n, t = +t, function(s) {
    return e.setTime(n * (1 - s) + t * s), e;
  };
}
function bo(n, t) {
  return n = +n, t = +t, function(e) {
    return n * (1 - e) + t * e;
  };
}
function wv(n, t) {
  var e = {}, s = {}, i;
  (n === null || typeof n != "object") && (n = {}), (t === null || typeof t != "object") && (t = {});
  for (i in t)
    i in n ? e[i] = ac(n[i], t[i]) : s[i] = t[i];
  return function(r) {
    for (i in e) s[i] = e[i](r);
    return s;
  };
}
var Tl = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, $a = new RegExp(Tl.source, "g");
function Sv(n) {
  return function() {
    return n;
  };
}
function Tv(n) {
  return function(t) {
    return n(t) + "";
  };
}
function Mv(n, t) {
  var e = Tl.lastIndex = $a.lastIndex = 0, s, i, r, o = -1, a = [], l = [];
  for (n = n + "", t = t + ""; (s = Tl.exec(n)) && (i = $a.exec(t)); )
    (r = i.index) > e && (r = t.slice(e, r), a[o] ? a[o] += r : a[++o] = r), (s = s[0]) === (i = i[0]) ? a[o] ? a[o] += i : a[++o] = i : (a[++o] = null, l.push({ i: o, x: bo(s, i) })), e = $a.lastIndex;
  return e < t.length && (r = t.slice(e), a[o] ? a[o] += r : a[++o] = r), a.length < 2 ? l[0] ? Tv(l[0].x) : Sv(t) : (t = l.length, function(c) {
    for (var h = 0, u; h < t; ++h) a[(u = l[h]).i] = u.x(c);
    return a.join("");
  });
}
function ac(n, t) {
  var e = typeof t, s;
  return t == null || e === "boolean" ? oc(t) : (e === "number" ? bo : e === "string" ? (s = nr(t)) ? (t = s, sd) : Mv : t instanceof nr ? sd : t instanceof Date ? bv : _v(t) ? xv : Array.isArray(t) ? vv : typeof t.valueOf != "function" && typeof t.toString != "function" || isNaN(t) ? wv : bo)(n, t);
}
function kv(n, t) {
  return n = +n, t = +t, function(e) {
    return Math.round(n * (1 - e) + t * e);
  };
}
function Cv(n) {
  return function() {
    return n;
  };
}
function Av(n) {
  return +n;
}
var nd = [0, 1];
function Un(n) {
  return n;
}
function Ml(n, t) {
  return (t -= n = +n) ? function(e) {
    return (e - n) / t;
  } : Cv(isNaN(t) ? NaN : 0.5);
}
function Ev(n, t) {
  var e;
  return n > t && (e = n, n = t, t = e), function(s) {
    return Math.max(n, Math.min(t, s));
  };
}
function Pv(n, t, e) {
  var s = n[0], i = n[1], r = t[0], o = t[1];
  return i < s ? (s = Ml(i, s), r = e(o, r)) : (s = Ml(s, i), r = e(r, o)), function(a) {
    return r(s(a));
  };
}
function Iv(n, t, e) {
  var s = Math.min(n.length, t.length) - 1, i = new Array(s), r = new Array(s), o = -1;
  for (n[s] < n[0] && (n = n.slice().reverse(), t = t.slice().reverse()); ++o < s; )
    i[o] = Ml(n[o], n[o + 1]), r[o] = e(t[o], t[o + 1]);
  return function(a) {
    var l = Z_(n, a, 1, s) - 1;
    return r[l](i[l](a));
  };
}
function Fv(n, t) {
  return t.domain(n.domain()).range(n.range()).interpolate(n.interpolate()).clamp(n.clamp()).unknown(n.unknown());
}
function Rv() {
  var n = nd, t = nd, e = ac, s, i, r, o = Un, a, l, c;
  function h() {
    var d = Math.min(n.length, t.length);
    return o !== Un && (o = Ev(n[0], n[d - 1])), a = d > 2 ? Iv : Pv, l = c = null, u;
  }
  function u(d) {
    return d == null || isNaN(d = +d) ? r : (l || (l = a(n.map(s), t, e)))(s(o(d)));
  }
  return u.invert = function(d) {
    return o(i((c || (c = a(t, n.map(s), bo)))(d)));
  }, u.domain = function(d) {
    return arguments.length ? (n = Array.from(d, Av), h()) : n.slice();
  }, u.range = function(d) {
    return arguments.length ? (t = Array.from(d), h()) : t.slice();
  }, u.rangeRound = function(d) {
    return t = Array.from(d), e = kv, h();
  }, u.clamp = function(d) {
    return arguments.length ? (o = d ? !0 : Un, h()) : o !== Un;
  }, u.interpolate = function(d) {
    return arguments.length ? (e = d, h()) : e;
  }, u.unknown = function(d) {
    return arguments.length ? (r = d, u) : r;
  }, function(d, f) {
    return s = d, i = f, h();
  };
}
function Dv() {
  return Rv()(Un, Un);
}
function Ov(n) {
  return Math.abs(n = Math.round(n)) >= 1e21 ? n.toLocaleString("en").replace(/,/g, "") : n.toString(10);
}
function wo(n, t) {
  if ((e = (n = t ? n.toExponential(t - 1) : n.toExponential()).indexOf("e")) < 0) return null;
  var e, s = n.slice(0, e);
  return [
    s.length > 1 ? s[0] + s.slice(2) : s,
    +n.slice(e + 1)
  ];
}
function Qn(n) {
  return n = wo(Math.abs(n)), n ? n[1] : NaN;
}
function Nv(n, t) {
  return function(e, s) {
    for (var i = e.length, r = [], o = 0, a = n[0], l = 0; i > 0 && a > 0 && (l + a + 1 > s && (a = Math.max(1, s - l)), r.push(e.substring(i -= a, i + a)), !((l += a + 1) > s)); )
      a = n[o = (o + 1) % n.length];
    return r.reverse().join(t);
  };
}
function Lv(n) {
  return function(t) {
    return t.replace(/[0-9]/g, function(e) {
      return n[+e];
    });
  };
}
var Vv = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
function So(n) {
  if (!(t = Vv.exec(n))) throw new Error("invalid format: " + n);
  var t;
  return new lc({
    fill: t[1],
    align: t[2],
    sign: t[3],
    symbol: t[4],
    zero: t[5],
    width: t[6],
    comma: t[7],
    precision: t[8] && t[8].slice(1),
    trim: t[9],
    type: t[10]
  });
}
So.prototype = lc.prototype;
function lc(n) {
  this.fill = n.fill === void 0 ? " " : n.fill + "", this.align = n.align === void 0 ? ">" : n.align + "", this.sign = n.sign === void 0 ? "-" : n.sign + "", this.symbol = n.symbol === void 0 ? "" : n.symbol + "", this.zero = !!n.zero, this.width = n.width === void 0 ? void 0 : +n.width, this.comma = !!n.comma, this.precision = n.precision === void 0 ? void 0 : +n.precision, this.trim = !!n.trim, this.type = n.type === void 0 ? "" : n.type + "";
}
lc.prototype.toString = function() {
  return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === void 0 ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === void 0 ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type;
};
function Bv(n) {
  t: for (var t = n.length, e = 1, s = -1, i; e < t; ++e)
    switch (n[e]) {
      case ".":
        s = i = e;
        break;
      case "0":
        s === 0 && (s = e), i = e;
        break;
      default:
        if (!+n[e]) break t;
        s > 0 && (s = 0);
        break;
    }
  return s > 0 ? n.slice(0, s) + n.slice(i + 1) : n;
}
var Qp;
function zv(n, t) {
  var e = wo(n, t);
  if (!e) return n + "";
  var s = e[0], i = e[1], r = i - (Qp = Math.max(-8, Math.min(8, Math.floor(i / 3))) * 3) + 1, o = s.length;
  return r === o ? s : r > o ? s + new Array(r - o + 1).join("0") : r > 0 ? s.slice(0, r) + "." + s.slice(r) : "0." + new Array(1 - r).join("0") + wo(n, Math.max(0, t + r - 1))[0];
}
function id(n, t) {
  var e = wo(n, t);
  if (!e) return n + "";
  var s = e[0], i = e[1];
  return i < 0 ? "0." + new Array(-i).join("0") + s : s.length > i + 1 ? s.slice(0, i + 1) + "." + s.slice(i + 1) : s + new Array(i - s.length + 2).join("0");
}
const rd = {
  "%": (n, t) => (n * 100).toFixed(t),
  b: (n) => Math.round(n).toString(2),
  c: (n) => n + "",
  d: Ov,
  e: (n, t) => n.toExponential(t),
  f: (n, t) => n.toFixed(t),
  g: (n, t) => n.toPrecision(t),
  o: (n) => Math.round(n).toString(8),
  p: (n, t) => id(n * 100, t),
  r: id,
  s: zv,
  X: (n) => Math.round(n).toString(16).toUpperCase(),
  x: (n) => Math.round(n).toString(16)
};
function od(n) {
  return n;
}
var ad = Array.prototype.map, ld = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
function qv(n) {
  var t = n.grouping === void 0 || n.thousands === void 0 ? od : Nv(ad.call(n.grouping, Number), n.thousands + ""), e = n.currency === void 0 ? "" : n.currency[0] + "", s = n.currency === void 0 ? "" : n.currency[1] + "", i = n.decimal === void 0 ? "." : n.decimal + "", r = n.numerals === void 0 ? od : Lv(ad.call(n.numerals, String)), o = n.percent === void 0 ? "%" : n.percent + "", a = n.minus === void 0 ? "−" : n.minus + "", l = n.nan === void 0 ? "NaN" : n.nan + "";
  function c(u) {
    u = So(u);
    var d = u.fill, f = u.align, p = u.sign, g = u.symbol, m = u.zero, y = u.width, x = u.comma, v = u.precision, _ = u.trim, b = u.type;
    b === "n" ? (x = !0, b = "g") : rd[b] || (v === void 0 && (v = 12), _ = !0, b = "g"), (m || d === "0" && f === "=") && (m = !0, d = "0", f = "=");
    var w = g === "$" ? e : g === "#" && /[boxX]/.test(b) ? "0" + b.toLowerCase() : "", S = g === "$" ? s : /[%p]/.test(b) ? o : "", T = rd[b], k = /[defgprs%]/.test(b);
    v = v === void 0 ? 6 : /[gprs]/.test(b) ? Math.max(1, Math.min(21, v)) : Math.max(0, Math.min(20, v));
    function C(M) {
      var A = w, I = S, F, R, E;
      if (b === "c")
        I = T(M) + I, M = "";
      else {
        M = +M;
        var P = M < 0 || 1 / M < 0;
        if (M = isNaN(M) ? l : T(Math.abs(M), v), _ && (M = Bv(M)), P && +M == 0 && p !== "+" && (P = !1), A = (P ? p === "(" ? p : a : p === "-" || p === "(" ? "" : p) + A, I = (b === "s" ? ld[8 + Qp / 3] : "") + I + (P && p === "(" ? ")" : ""), k) {
          for (F = -1, R = M.length; ++F < R; )
            if (E = M.charCodeAt(F), 48 > E || E > 57) {
              I = (E === 46 ? i + M.slice(F + 1) : M.slice(F)) + I, M = M.slice(0, F);
              break;
            }
        }
      }
      x && !m && (M = t(M, 1 / 0));
      var N = A.length + M.length + I.length, D = N < y ? new Array(y - N + 1).join(d) : "";
      switch (x && m && (M = t(D + M, D.length ? y - I.length : 1 / 0), D = ""), f) {
        case "<":
          M = A + M + I + D;
          break;
        case "=":
          M = A + D + M + I;
          break;
        case "^":
          M = D.slice(0, N = D.length >> 1) + A + M + I + D.slice(N);
          break;
        default:
          M = D + A + M + I;
          break;
      }
      return r(M);
    }
    return C.toString = function() {
      return u + "";
    }, C;
  }
  function h(u, d) {
    var f = c((u = So(u), u.type = "f", u)), p = Math.max(-8, Math.min(8, Math.floor(Qn(d) / 3))) * 3, g = Math.pow(10, -p), m = ld[8 + p / 3];
    return function(y) {
      return f(g * y) + m;
    };
  }
  return {
    format: c,
    formatPrefix: h
  };
}
var Jr, Jp, tm;
Uv({
  thousands: ",",
  grouping: [3],
  currency: ["$", ""]
});
function Uv(n) {
  return Jr = qv(n), Jp = Jr.format, tm = Jr.formatPrefix, Jr;
}
function Gv(n) {
  return Math.max(0, -Qn(Math.abs(n)));
}
function Wv(n, t) {
  return Math.max(0, Math.max(-8, Math.min(8, Math.floor(Qn(t) / 3))) * 3 - Qn(Math.abs(n)));
}
function $v(n, t) {
  return n = Math.abs(n), t = Math.abs(t) - n, Math.max(0, Qn(t) - Qn(n)) + 1;
}
function Hv(n, t, e, s) {
  var i = ev(n, t, e), r;
  switch (s = So(s ?? ",f"), s.type) {
    case "s": {
      var o = Math.max(Math.abs(n), Math.abs(t));
      return s.precision == null && !isNaN(r = Wv(i, o)) && (s.precision = r), tm(s, o);
    }
    case "":
    case "e":
    case "g":
    case "p":
    case "r": {
      s.precision == null && !isNaN(r = $v(i, Math.max(Math.abs(n), Math.abs(t)))) && (s.precision = r - (s.type === "e"));
      break;
    }
    case "f":
    case "%": {
      s.precision == null && !isNaN(r = Gv(i)) && (s.precision = r - (s.type === "%") * 2);
      break;
    }
  }
  return Jp(s);
}
function jv(n) {
  var t = n.domain;
  return n.ticks = function(e) {
    var s = t();
    return tv(s[0], s[s.length - 1], e ?? 10);
  }, n.tickFormat = function(e, s) {
    var i = t();
    return Hv(i[0], i[i.length - 1], e ?? 10, s);
  }, n.nice = function(e) {
    e == null && (e = 10);
    var s = t(), i = 0, r = s.length - 1, o = s[i], a = s[r], l, c, h = 10;
    for (a < o && (c = o, o = a, a = c, c = i, i = r, r = c); h-- > 0; ) {
      if (c = wl(o, a, e), c === l)
        return s[i] = o, s[r] = a, t(s);
      if (c > 0)
        o = Math.floor(o / c) * c, a = Math.ceil(a / c) * c;
      else if (c < 0)
        o = Math.ceil(o * c) / c, a = Math.floor(a * c) / c;
      else
        break;
      l = c;
    }
    return n;
  }, n;
}
function kl() {
  var n = Dv();
  return n.copy = function() {
    return Fv(n, kl());
  }, sv.apply(n, arguments), jv(n);
}
function Xv(n, t, e = null, s = 8, i = 0) {
  const r = n.length > 0 ? Math.max(...n.map((u) => u.time + u.duration)) : 60, o = t.showPianoKeys ? 60 : 0, a = e ?? (t.width - o) / s, l = r * a, c = kl().domain([0, r]).range([0, l]), h = kl().domain([t.noteRange.min, t.noteRange.max]).range([t.height - 20 - i, 20]);
  return { timeScale: c, pitchScale: h, pxPerSecond: a };
}
function Yv(n, t, e) {
  n /= 255, t /= 255, e /= 255;
  const s = Math.max(n, t, e), i = Math.min(n, t, e), r = s - i;
  let o = 0;
  if (r !== 0)
    switch (s) {
      case n:
        o = (t - e) / r % 6;
        break;
      case t:
        o = (e - n) / r + 2;
        break;
      default:
        o = (n - t) / r + 4;
    }
  const a = o < 0 ? o * 60 + 360 : o * 60, l = s === 0 ? 0 : r / s;
  return [a, l, s];
}
function Zv(n, t, e) {
  const s = e * t, i = n % 360 / 60, r = s * (1 - Math.abs(i % 2 - 1));
  let o = 0, a = 0, l = 0;
  i >= 0 && i < 1 ? (o = s, a = r) : i >= 1 && i < 2 ? (o = r, a = s) : i >= 2 && i < 3 ? (a = s, l = r) : i >= 3 && i < 4 ? (a = r, l = s) : i >= 4 && i < 5 ? (o = r, l = s) : (o = s, l = r);
  const c = e - s, h = (o + c) * 255, u = (a + c) * 255, d = (l + c) * 255, f = 0.2, p = Math.round(h + (255 - h) * f), g = Math.round(u + (255 - u) * f), m = Math.round(d + (255 - d) * f);
  return [p, g, m];
}
function Ne(n) {
  return "#" + n.toString(16).padStart(6, "0");
}
function Hs(n, t = []) {
  if (n.length === 0)
    return 16777215;
  let e = 0, s = 0, i = 0, r = 0;
  for (const p of n) {
    const g = p >> 16 & 255, m = p >> 8 & 255, y = p & 255, [x, v, _] = Yv(g, m, y), b = x * Math.PI / 180;
    e += Math.cos(b), s += Math.sin(b), i += v, r += _;
  }
  const o = n.length, a = Math.atan2(s / o, e / o), l = a * 180 / Math.PI + (a < 0 ? 360 : 0), c = Math.min(1, Math.max(0, i / o)), h = Math.min(1, Math.max(0, r / o)), [u, d, f] = Zv(l, c, h);
  return u << 16 | d << 8 | f;
}
function ht(n, t, e = 0.5) {
  const s = Kv(e), i = cd(n), r = cd(t), o = hd(i[0], i[1], i[2]), a = hd(r[0], r[1], r[2]), l = ud(o.L, o.a, o.b), c = ud(a.L, a.a, a.b), h = l.L * (1 - s) + c.L * s, u = l.C * (1 - s) + c.C * s, d = eb(l.h, c.h, s), { L: f, a: p, b: g } = tb(h, u, d), m = Jv(f, p, g);
  return Qv(m[0], m[1], m[2]);
}
function Kv(n) {
  return n < 0 ? 0 : n > 1 ? 1 : n;
}
function cd(n) {
  const t = n >> 16 & 255, e = n >> 8 & 255, s = n & 255;
  return [t, e, s];
}
function Qv(n, t, e) {
  const s = Math.max(0, Math.min(255, Math.round(n))), i = Math.max(0, Math.min(255, Math.round(t))), r = Math.max(0, Math.min(255, Math.round(e)));
  return s << 16 | i << 8 | r;
}
function Ha(n) {
  const t = n / 255;
  return t <= 0.04045 ? t / 12.92 : Math.pow((t + 0.055) / 1.055, 2.4);
}
function ja(n) {
  const t = n <= 31308e-7 ? n * 12.92 : 1.055 * Math.pow(n, 0.4166666666666667) - 0.055;
  return Math.max(0, Math.min(1, t)) * 255;
}
function hd(n, t, e) {
  const s = Ha(n), i = Ha(t), r = Ha(e), o = 0.4122214708 * s + 0.5363325363 * i + 0.0514459929 * r, a = 0.2119034982 * s + 0.6806995451 * i + 0.1073969566 * r, l = 0.0883024619 * s + 0.2817188376 * i + 0.6299787005 * r, c = Math.cbrt(o), h = Math.cbrt(a), u = Math.cbrt(l);
  return {
    L: 0.2104542553 * c + 0.793617785 * h - 0.0040720468 * u,
    a: 1.9779984951 * c - 2.428592205 * h + 0.4505937099 * u,
    b: 0.0259040371 * c + 0.7827717662 * h - 0.808675766 * u
  };
}
function Jv(n, t, e) {
  const s = n + 0.3963377774 * t + 0.2158037573 * e, i = n - 0.1055613458 * t - 0.0638541728 * e, r = n - 0.0894841775 * t - 1.291485548 * e, o = s * s * s, a = i * i * i, l = r * r * r, c = 4.0767416621 * o - 3.3077115913 * a + 0.2309699292 * l, h = -1.2684380046 * o + 2.6097574011 * a - 0.3413193965 * l, u = 0.0044210633 * o - 0.7034186147 * a + 1.7035977687 * l;
  return [ja(c), ja(h), ja(u)];
}
function ud(n, t, e) {
  const s = Math.sqrt(t * t + e * e);
  let i = Math.atan2(e, t) * (180 / Math.PI);
  return i < 0 && (i += 360), { L: n, C: s, h: i };
}
function tb(n, t, e) {
  const s = e % 360 * (Math.PI / 180), i = Math.cos(s) * t, r = Math.sin(s) * t;
  return { L: n, a: i, b: r };
}
function eb(n, t, e) {
  let s = (t - n + 540) % 360 - 180;
  return (n + s * e + 360) % 360;
}
function hs(n, t, e) {
  return Math.min(Math.max(n, t), e);
}
function Cl(n) {
  if (!isFinite(n) || isNaN(n) || n == null)
    return "00:00:00";
  const t = Math.max(0, n), e = Math.floor(t / 60), s = Math.floor(t % 60), i = Math.floor(
    (t - Math.floor(t)) * 100
  );
  return `${e.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}:${i.toString().padStart(2, "0")}`;
}
function Gn(n, t) {
  const s = -(n.range()[1] * t.zoomX), i = 0;
  t.panX = hs(t.panX, s, i);
}
function ji(n, t, e) {
  const s = n.range(), i = Math.max(0, e - 20 - Math.max(s[0], s[1])), r = e - i, o = e / 2, a = n.domain(), l = Math.min(a[0], a[1]), c = Math.max(a[0], a[1]), h = n(c), u = n(l), d = (h - o) * t.zoomY + o, f = (u - o) * t.zoomY + o, p = -d, g = r - f, m = Math.min(p, g), y = Math.max(p, g);
  t.panY = hs(t.panY, m, y);
}
function dd(n, t) {
  n.preventDefault();
  const e = em(n, t.app);
  t.state.isPanning = !0, t.state.lastPointerPos = e;
}
function fd(n, t) {
  if (!t.state.isPanning) return;
  n.preventDefault();
  const e = em(n, t.app), s = e.x - t.state.lastPointerPos.x, i = e.y - t.state.lastPointerPos.y;
  n.altKey === !0 || Math.abs(i) > Math.abs(s) * 1.25 ? (t.state.panY += i, ji(t.pitchScale, t.state, t.options.height)) : (t.state.panX += s, Gn(t.timeScale, t.state)), t.state.lastPointerPos = e, t.state.currentTime = t.computeTimeAtPlayhead(), t.requestRender();
}
function Xa(n, t) {
  const e = t.state.isPanning === !0;
  if (t.state.isPanning = !1, !e)
    return;
  const s = t.computeTimeAtPlayhead();
  t.state.currentTime = s, t.onTimeChangeCallback && t.onTimeChangeCallback(s);
}
function em(n, t) {
  const s = t.canvas.getBoundingClientRect();
  let i, r;
  if (n instanceof TouchEvent && n.touches.length > 0)
    i = n.touches[0].clientX, r = n.touches[0].clientY;
  else if (n instanceof MouseEvent)
    i = n.clientX, r = n.clientY;
  else
    return { x: 0, y: 0 };
  return {
    x: i - s.left,
    y: r - s.top
  };
}
const pd = /* @__PURE__ */ new WeakMap();
function sb(n, t) {
  n.preventDefault();
  const e = 1.1, s = n.deltaY, i = n.deltaX, r = t.app.canvas.getBoundingClientRect(), o = t.options.showPianoKeys ? 60 : 0, a = n.ctrlKey && !n.altKey && !n.shiftKey && Math.abs(i) < 2;
  let l;
  if (a && typeof n.offsetX == "number" && n.offsetX > 0)
    l = Math.max(o, Math.min(t.options.width, n.offsetX));
  else {
    const g = n.clientX - r.left;
    l = Math.max(
      o,
      Math.min(
        t.options.width,
        Number.isFinite(g) ? g : o
      )
    );
  }
  if (n.altKey) {
    s < 0 ? t.zoomY(e) : t.zoomY(1 / e);
    return;
  }
  const c = typeof performance < "u" && typeof performance.now == "function" ? performance.now() : Date.now(), h = pd.get(t), u = n.shiftKey === !0, d = n.ctrlKey === !0 || n.metaKey === !0, f = Math.abs(i) >= Math.abs(s) * 0.8;
  let p;
  if (u ? p = "pan" : d ? p = "zoom" : h && c < h.expiresAt ? p = h.mode : (p = f ? "pan" : "zoom", pd.set(t, { mode: p, expiresAt: c + 120 })), p === "pan") {
    let g = i;
    u && Math.abs(g) < 0.5 && (g = s), t.state.panX -= g, Gn(t.timeScale, t.state), t.state.currentTime = t.computeTimeAtPlayhead(), t.onTimeChangeCallback && t.onTimeChangeCallback(t.state.currentTime), t.requestRender();
    return;
  }
  s < 0 ? t.zoomX(e, l) : t.zoomX(1 / e, l);
}
function nb(n) {
  return n.app.canvas.getBoundingClientRect();
}
function sm(n, t) {
  const e = n.clientX - t.clientX, s = n.clientY - t.clientY;
  return Math.hypot(e, s);
}
function ib(n, t) {
  return (n.clientX + t.clientX) / 2;
}
function rb(n, t, e) {
  if (n.touches.length < 2) return;
  const s = n.touches[0], i = n.touches[1], r = nb(t);
  e.isPinching = !0, e.lastDistance = sm(s, i);
  const o = ib(s, i);
  e.anchorX = Math.max(0, Math.min(t.options.width, o - r.left));
}
function ob(n, t, e) {
  if (!e.isPinching || n.touches.length < 2) return;
  n.preventDefault();
  const s = n.touches[0], i = n.touches[1], r = sm(s, i);
  if (e.lastDistance <= 0) {
    e.lastDistance = r;
    return;
  }
  const o = r / e.lastDistance;
  if (Math.abs(o - 1) < 0.01) return;
  const a = Math.max(0.8, Math.min(1.25, o));
  t.zoomX(a, e.anchorX), e.lastDistance = r;
}
function ab(n, t, e) {
  n.touches.length < 2 && (e.isPinching = !1);
}
const Me = "#2563eb", Wn = "#0ea5e9", mn = "#e11d48", nm = "#64748b", Al = "#60A5FA", im = "#FB7185", To = "#B0B0B0", lb = "#707070", rm = "#7A6F66", cb = 64, hb = "#475569", om = "#0f172a", ub = "#ffffff", db = "#fde68a", fb = "#0ea5e9", pb = "#e11d48", as = [
  "circle",
  "square",
  "diamond",
  "triangle-up",
  "triangle-down",
  "triangle-left",
  "triangle-right",
  "star",
  "cross",
  "plus",
  "hexagon",
  "pentagon",
  "chevron-up",
  "chevron-down"
];
as.length * 2;
function mb(n) {
  n.playheadLine.clear();
  const t = n.options.showPianoKeys ? 60 : 0, e = n.timeScale(1) * n.state.zoomX;
  n.state.currentTime * e;
  const s = t;
  n.playheadX = s;
  const i = n.options.playheadColor ?? parseInt(om.replace("#", ""), 16), r = parseInt(ub.replace("#", ""), 16);
  n.playheadLine.moveTo(s, 0), n.playheadLine.lineTo(s, n.options.height), n.playheadLine.stroke({ width: 7, color: r, alpha: 0.95 }), n.playheadLine.moveTo(s, 0), n.playheadLine.lineTo(s, n.options.height), n.playheadLine.stroke({ width: 3, color: i, alpha: 1 });
  const o = 6;
  n.playheadLine.moveTo(s - o - 1, 0), n.playheadLine.lineTo(s + o + 1, 0), n.playheadLine.stroke({ width: 5, color: r, alpha: 0.95 }), n.playheadLine.moveTo(s - o, 0), n.playheadLine.lineTo(s + o, 0), n.playheadLine.stroke({ width: 3, color: i, alpha: 1 });
  const a = n.options.height;
  n.playheadLine.moveTo(s - o - 1, a), n.playheadLine.lineTo(s + o + 1, a), n.playheadLine.stroke({ width: 5, color: r, alpha: 0.95 }), n.playheadLine.moveTo(s - o, a), n.playheadLine.lineTo(s + o, a), n.playheadLine.stroke({ width: 3, color: i, alpha: 1 }), n.playheadLine.visible = !0, n.playheadLine.zIndex = 1e3, n.container.sortChildren();
}
class Gs {
  /**
   * Get the color for a note
   */
  static getNoteColor(t, e, s) {
    return t.options.noteRenderer ? t.options.noteRenderer(e, s) : t.options.noteColor;
  }
  /**
   * Convert hex color string to number
   */
  static hexToNumber(t) {
    const e = t.startsWith("#") ? t.slice(1) : t;
    return parseInt(e, 16);
  }
  /**
   * Convert number to hex color string
   */
  static numberToHex(t) {
    return "#" + t.toString(16).padStart(6, "0");
  }
  /**
   * Apply transparency to a color
   */
  static applyTransparency(t, e) {
    const s = Math.max(0, Math.min(1, e)), i = t >> 16 & 255, r = t >> 8 & 255, o = t & 255;
    return Math.round(s * 255) << 24 | i << 16 | r << 8 | o;
  }
  /**
   * Lighten a color by a factor
   */
  static lighten(t, e = 0.2) {
    const s = t >> 16 & 255, i = t >> 8 & 255, r = t & 255, o = Math.min(255, Math.round(s + (255 - s) * e)), a = Math.min(255, Math.round(i + (255 - i) * e)), l = Math.min(255, Math.round(r + (255 - r) * e));
    return o << 16 | a << 8 | l;
  }
  /**
   * Darken a color by a factor
   */
  static darken(t, e = 0.2) {
    const s = t >> 16 & 255, i = t >> 8 & 255, r = t & 255, o = Math.round(s * (1 - e)), a = Math.round(i * (1 - e)), l = Math.round(r * (1 - e));
    return o << 16 | a << 8 | l;
  }
  /**
   * Get a contrasting color (for text on background)
   */
  static getContrastColor(t) {
    const e = t >> 16 & 255, s = t >> 8 & 255, i = t & 255;
    return (e * 299 + s * 587 + i * 114) / 1e3 > 128 ? 0 : 16777215;
  }
  /**
   * Blend two colors
   */
  static blend(t, e, s = 0.5) {
    const i = t >> 16 & 255, r = t >> 8 & 255, o = t & 255, a = e >> 16 & 255, l = e >> 8 & 255, c = e & 255, h = Math.round(i * (1 - s) + a * s), u = Math.round(r * (1 - s) + l * s), d = Math.round(o * (1 - s) + c * s);
    return h << 16 | u << 8 | d;
  }
  /**
   * Convert RGB color (hex number) to HSL
   * @returns Object with h (0-360), s (0-1), l (0-1)
   */
  static rgbToHsl(t) {
    const e = (t >> 16 & 255) / 255, s = (t >> 8 & 255) / 255, i = (t & 255) / 255, r = Math.max(e, s, i), o = Math.min(e, s, i), a = (r + o) / 2;
    if (r === o)
      return { h: 0, s: 0, l: a };
    const l = r - o, c = a > 0.5 ? l / (2 - r - o) : l / (r + o);
    let h = 0;
    switch (r) {
      case e:
        h = ((s - i) / l + (s < i ? 6 : 0)) / 6;
        break;
      case s:
        h = ((i - e) / l + 2) / 6;
        break;
      case i:
        h = ((e - s) / l + 4) / 6;
        break;
    }
    return { h: h * 360, s: c, l: a };
  }
  /**
   * Convert HSL to RGB color (hex number)
   * @param h Hue (0-360)
   * @param s Saturation (0-1)
   * @param l Lightness (0-1)
   */
  static hslToRgb(t, e, s) {
    const i = t / 360;
    if (e === 0) {
      const u = Math.round(s * 255);
      return u << 16 | u << 8 | u;
    }
    const r = (u, d, f) => {
      let p = f;
      return p < 0 && (p += 1), p > 1 && (p -= 1), p < 1 / 6 ? u + (d - u) * 6 * p : p < 1 / 2 ? d : p < 2 / 3 ? u + (d - u) * (2 / 3 - p) * 6 : u;
    }, o = s < 0.5 ? s * (1 + e) : s + e - s * e, a = 2 * s - o, l = Math.round(r(a, o, i + 1 / 3) * 255), c = Math.round(r(a, o, i) * 255), h = Math.round(r(a, o, i - 1 / 3) * 255);
    return l << 16 | c << 8 | h;
  }
  /**
   * Get a lightness-variant color for a track within a file.
   * Uses HSL color space to adjust lightness while preserving hue,
   * ensuring file-level color identity is maintained.
   *
   * @param baseColor - The file's base color (hex number)
   * @param trackIndex - Index of the track within the file (0-based)
   * @param totalTracks - Total number of tracks in the file
   * @returns Adjusted color with modified lightness
   */
  static getTrackVariantColor(t, e, s) {
    if (s <= 1 || e === 0) return t;
    const { h: i, s: r, l: o } = Gs.rgbToHsl(t), l = Math.floor((e + 1) / 2) * 0.2, h = e % 2 === 1 ? Math.min(0.9, o + l) : Math.max(0.2, o - l);
    return Gs.hslToRgb(i, r, h);
  }
}
function am(n) {
  return {
    /**
     * Convert time to pixel position
     */
    timeToPixel(t) {
      const e = n.options.showPianoKeys ? 60 : 0;
      return n.timeScale(t) * n.state.zoomX + e;
    },
    /**
     * Convert pixel position to time
     */
    pixelToTime(t) {
      const e = n.options.showPianoKeys ? 60 : 0;
      return n.timeScale.invert((t - e) / n.state.zoomX);
    },
    /**
     * Convert pitch to pixel position
     */
    pitchToPixel(t) {
      return n.pitchScale(t) * n.state.zoomY;
    },
    /**
     * Convert pixel position to pitch
     */
    pixelToPitch(t) {
      return n.pitchScale.invert(t / n.state.zoomY);
    },
    /**
     * Get the piano keys offset
     */
    getPianoKeysOffset() {
      return n.options.showPianoKeys ? 60 : 0;
    },
    /**
     * Get pixels per second
     */
    getPixelsPerSecond() {
      return n.timeScale(1) * n.state.zoomX;
    }
  };
}
function gb(n) {
  const t = n.options.showPianoKeys ? 60 : 0, e = am(n), s = Math.max(
    0,
    n.timeScale.invert(
      (-n.state.panX - t) / n.state.zoomX
    )
  ), i = Math.min(
    n.timeScale.domain()[1],
    n.timeScale.invert(
      (n.options.width - t - n.state.panX) / n.state.zoomX
    )
  );
  return {
    timeStart: s,
    timeEnd: i,
    pixelStart: e.timeToPixel(s),
    pixelEnd: e.timeToPixel(i)
  };
}
class md {
  /**
   * Draw a vertical line
   */
  static drawVerticalLine(t, e, s, i, r = 0) {
    t.moveTo(e, r), t.lineTo(e, r + s), t.stroke(i);
  }
  /**
   * Draw a horizontal line
   */
  static drawHorizontalLine(t, e, s, i, r = 0) {
    t.moveTo(r, e), t.lineTo(r + s, e), t.stroke(i);
  }
  /**
   * Draw a rectangle with fill
   */
  static drawRectangle(t, e, s, i) {
    s && (t.rect(e.x, e.y, e.width, e.height), t.fill(s)), i && (t.rect(e.x, e.y, e.width, e.height), t.stroke(i));
  }
  /**
   * Draw a rounded rectangle
   */
  static drawRoundedRectangle(t, e, s, i, r) {
    i && (t.roundRect(e.x, e.y, e.width, e.height, s), t.fill(i)), r && (t.roundRect(e.x, e.y, e.width, e.height, s), t.stroke(r));
  }
  /**
   * Draw a circle
   */
  static drawCircle(t, e, s, i, r, o) {
    r && (t.circle(e, s, i), t.fill(r)), o && (t.circle(e, s, i), t.stroke(o));
  }
  /**
   * Draw a dashed line (vertical)
   */
  static drawDashedVerticalLine(t, e, s, i, r, o, a = 0) {
    let l = a;
    const c = a + s;
    for (; l < c; ) {
      const h = Math.min(l + i, c);
      t.moveTo(e, l), t.lineTo(e, h), t.stroke(o), l = h + r;
    }
  }
  /**
   * Draw a dashed line (horizontal)
   */
  static drawDashedHorizontalLine(t, e, s, i, r, o, a = 0) {
    let l = a;
    const c = a + s;
    for (; l < c; ) {
      const h = Math.min(l + i, c);
      t.moveTo(l, e), t.lineTo(h, e), t.stroke(o), l = h + r;
    }
  }
  /**
   * Clear and reset graphics object
   */
  static clearGraphics(t) {
    t.clear();
  }
  /**
   * Draw grid lines
   */
  static drawGrid(t, e, s, i, r) {
    for (let o = e.x; o <= e.x + e.width; o += s)
      this.drawVerticalLine(t, o, e.height, r, e.y);
    for (let o = e.y; o <= e.y + e.height; o += i)
      this.drawHorizontalLine(t, o, e.width, r, e.x);
  }
}
function yb(n, t, e) {
  if (e[t] !== void 0) return e[t];
  for (let s = 0; s < n.notes.length; s++) {
    const i = n.notes[s];
    if (i.fileId === t) {
      const o = (n.highlightMode ?? "file") === "file" && n.options.noteRenderer ? n.options.noteRenderer(i, s) : n.options.noteColor;
      return e[t] = o, o;
    }
  }
  return e[t] = n.options.noteColor;
}
function Mo(n) {
  const t = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(n);
  return t ? {
    r: parseInt(t[1], 16),
    g: parseInt(t[2], 16),
    b: parseInt(t[3], 16)
  } : { r: 0, g: 0, b: 0 };
}
function lm(n, t, e) {
  return "#" + ((1 << 24) + (n << 16) + (t << 8) + e).toString(16).slice(1);
}
function ko(n, t, e) {
  const s = n / 255, i = t / 255, r = e / 255, o = s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4), a = i <= 0.03928 ? i / 12.92 : Math.pow((i + 0.055) / 1.055, 2.4), l = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
  return 0.2126 * o + 0.7152 * a + 0.0722 * l;
}
function gd(n, t) {
  const e = Mo(n), s = Mo(t), i = ko(e.r, e.g, e.b), r = ko(s.r, s.g, s.b), o = Math.max(i, r), a = Math.min(i, r);
  return (o + 0.05) / (a + 0.05);
}
function xb(n, t = 3, e) {
  const s = Mo(n), i = ko(s.r, s.g, s.b), r = i > 0.3, o = 64, a = 192;
  let l;
  r ? (l = 96, i > 0.7 ? l = 80 : i > 0.5 ? l = 96 : l = 112) : (l = 144, i < 0.1 ? l = 160 : i < 0.2 ? l = 144 : l = 128);
  const c = ko(l, l, l);
  return (i > c ? (i + 0.05) / (c + 0.05) : (c + 0.05) / (i + 0.05)) < t && (r && l > o ? l = Math.max(o, l - 32) : !r && l < a && (l = Math.min(a, l + 32))), l = Math.max(o, Math.min(a, l)), lm(l, l, l);
}
function _b(n, t, e = "color") {
  if (e === "gray")
    return "#7a6f66";
  const s = (C) => {
    const { r: M, g: A, b: I } = Mo(C);
    let F = M / 255, R = A / 255, E = I / 255;
    const P = Math.max(F, R, E), N = Math.min(F, R, E), D = P - N;
    let z = 0;
    D !== 0 && (P === F ? z = (R - E) / D % 6 : P === R ? z = (E - F) / D + 2 : z = (F - R) / D + 4);
    const O = (z < 0 ? z + 6 : z) * 60, V = P === 0 ? 0 : D / P;
    return [O, V, P];
  }, i = (C, M, A) => {
    const I = A * M, F = C % 360 / 60, R = I * (1 - Math.abs(F % 2 - 1));
    let E = 0, P = 0, N = 0;
    F >= 0 && F < 1 ? (E = I, P = R) : F >= 1 && F < 2 ? (E = R, P = I) : F >= 2 && F < 3 ? (P = I, N = R) : F >= 3 && F < 4 ? (P = R, N = I) : F >= 4 && F < 5 ? (E = R, N = I) : (E = I, N = R);
    const D = A - I, z = Math.round((E + D) * 255), O = Math.round((P + D) * 255), V = Math.round((N + D) * 255);
    return lm(z, O, V);
  }, [r, o, a] = s(n), [l, c, h] = s(t), u = (C) => C * Math.PI / 180, d = (C) => (C * 180 / Math.PI + 360) % 360, f = Math.cos(u(r)) + Math.cos(u(l)), p = Math.sin(u(r)) + Math.sin(u(l)), g = Math.sqrt(f * f + p * p);
  let y = (d(Math.atan2(p, f)) + 180) % 360;
  g < 0.2 && (y = (r + 90) % 360);
  const x = (C, M) => {
    const A = Math.abs(C - M) % 360;
    return A > 180 ? 360 - A : A;
  };
  x(y, r) < 30 && (y = (y + 60) % 360), x(y, l) < 30 && (y = (y + 60) % 360);
  let v = Math.min(0.85, Math.max(0.55, Math.max(o, c) * 0.85)), _ = Math.min(0.8, Math.max(0.6, (a + h) / 2 * 0.9)), b = i(y, v, _);
  const w = (C) => Math.min(gd(C, n), gd(C, t));
  let S = w(b);
  const T = 3;
  let k = 0;
  for (; S < T && k < 10; ) {
    const C = Math.min(0.95, _ + 0.08), M = Math.max(0.35, _ - 0.08), A = i(y, v, C), I = i(y, v, M), F = w(A), R = w(I);
    if (F >= R ? (_ = C, b = A, S = F) : (_ = M, b = I, S = R), S < T) {
      const E = x(y, r), P = x(y, l);
      y = (y + (E < P ? 20 : -20) + 360) % 360, b = i(y, v, _), S = w(b);
    }
    k++;
  }
  return b;
}
const cm = [
  "C",
  "C#",
  "D",
  "D#",
  "E",
  "F",
  "F#",
  "G",
  "G#",
  "A",
  "A#",
  "B"
];
function cc(n) {
  if (n < 0 || n > 127)
    throw new Error(`MIDI note number must be between 0 and 127, got ${n}`);
  const t = Math.floor(n / 12) - 1, e = n % 12;
  return `${cm[e]}${t}`;
}
function vb(n) {
  n.backgroundLabelContainer && n.backgroundLabelContainer.removeChildren(), n.loopLabelContainer && n.loopLabelContainer.removeChildren(), n.pianoKeyLabelContainer && n.pianoKeyLabelContainer.removeChildren(), n.backgroundGrid.removeChildren(), n.backgroundGrid.clear(), n.pianoKeyLines && n.pianoKeyLines.clear(), n.waveformLayer && n.waveformLayer.clear();
  const t = n;
  if (t.waveformKeysLayer && t.waveformKeysLayer.clear(), n.loopOverlay.clear(), n.loopOverlay.removeChildren(), n.loopLines && (n.loopLines.start.clear(), n.loopLines.start.removeChildren(), n.loopLines.end.clear(), n.loopLines.end.removeChildren()), n.options.showPianoKeys) {
    const c = n.playheadX;
    n.backgroundGrid.rect(
      0,
      0,
      c,
      n.options.height
    ), n.backgroundGrid.fill({ color: 15790320 }), n.backgroundGrid.moveTo(c + 0.5, 0), n.backgroundGrid.lineTo(
      c + 0.5,
      n.options.height
    ), n.backgroundGrid.stroke({ width: 1, color: 10066329, alpha: 0.6 });
    const h = n.options.height / 2;
    for (let u = n.options.noteRange.min; u <= n.options.noteRange.max; u++)
      if (u % 12 === 0) {
        const f = (n.pitchScale(u) - h) * n.state.zoomY + h, g = (n.pitchScale(u + 1) - h) * n.state.zoomY + h, m = Math.abs(f - g);
        if (m >= 8) {
          const y = new Ga({
            text: cc(u),
            style: {
              fontSize: Math.min(9, Math.max(7, m * 0.7)),
              fill: 6710886,
              fontWeight: "500"
            }
          });
          y.x = 4, y.y = f - y.height / 2, n.pianoKeyLabelContainer.addChild(y);
        }
      }
  }
  const e = n.options.timeStep, s = n.options.minorTimeStep, i = n.timeScale.domain()[1], r = 50, o = am(n);
  o.getPixelsPerSecond();
  const a = (c, h, u) => {
    const d = o.timeToPixel(c) + n.state.panX;
    if (!(d < -10 || d > n.options.width + 10) && (md.drawVerticalLine(
      n.backgroundGrid,
      d,
      n.options.height,
      { width: 1, color: 14737632, alpha: h }
    ), u)) {
      const f = new Ga({
        text: c.toFixed(1) + "s",
        style: {
          fontSize: 10,
          fill: 5592405,
          align: "center"
        }
      });
      f.x = d + 2, f.y = n.options.height - 14, n.backgroundLabelContainer.addChild(f);
    }
  };
  let l = -1 / 0;
  for (let c = 0; c <= i; c += e) {
    const h = o.timeToPixel(c) + n.state.panX, u = h - l >= r;
    u && (l = h), a(c, 1, u);
  }
  if (s && s < e) {
    const c = s / 1e3;
    for (let h = 0; h <= i + c; h += s)
      Math.abs(h % e) < c || Math.abs(e - h % e) < c || a(h, 0.25, !1);
  }
  if (n.loopLines) {
    o.getPianoKeysOffset();
    let c = 3;
    const h = (p, g, m, y = 10, x = 6) => {
      let v = 0;
      for (; v < n.options.height; ) {
        const _ = Math.min(v + y, n.options.height);
        p.moveTo(g, v), p.lineTo(g, _), p.stroke({ width: c + 2, color: 16777215, alpha: 0.95 }), p.moveTo(g, v), p.lineTo(g, _), p.stroke({ width: c, color: m, alpha: 1 }), v = _ + x;
      }
    }, u = (p, g, m, y) => {
      p.moveTo(g, 0), p.lineTo(g, n.options.height), p.stroke({ width: c + 2, color: 16777215, alpha: 0.95 }), p.moveTo(g, 0), p.lineTo(g, n.options.height), p.stroke({ width: c, color: m, alpha: 1 });
      const x = new Ga({
        text: y,
        style: {
          fontSize: 11,
          fill: m,
          align: "center"
        }
      });
      x.x = g + 2, x.y = 0, n.loopLabelContainer.addChild(x);
    };
    let d = null, f = null;
    if (n.loopStart !== null) {
      d = o.timeToPixel(n.loopStart) + n.state.panX;
      const p = Gs.hexToNumber(fb);
      h(n.loopLines.start, d, p, 14, 8), u(n.loopLines.start, d, p, `A(${n.loopStart.toFixed(1)}s)`);
    }
    if (n.loopEnd !== null) {
      f = o.timeToPixel(n.loopEnd) + n.state.panX;
      const p = Gs.hexToNumber(pb);
      h(n.loopLines.end, f, p, 2, 4), u(n.loopLines.end, f, p, `B(${n.loopEnd.toFixed(1)}s)`);
    }
    if (d !== null && f !== null) {
      const p = Gs.hexToNumber(db);
      md.drawRectangle(
        n.loopOverlay,
        {
          x: d,
          y: 0,
          width: Math.max(0, f - d),
          height: n.options.height
        },
        { color: p, alpha: 0.22 }
      );
    }
  }
  if (n.options.showWaveformBand === !1)
    n.waveformLayer?.clear(), t.waveformKeysLayer?.clear();
  else try {
    const c = globalThis._waveRollAudio;
    if (c?.getVisiblePeaks) {
      const h = c.getVisiblePeaks();
      if (h && h.length > 0) {
        const u = o.getPianoKeysOffset(), d = n.options.height, p = 1 / o.getPixelsPerSecond();
        n.waveformLayer.clear(), t.waveformKeysLayer && t.waveformKeysLayer.clear();
        const g = gb(n), m = g.timeStart, y = g.timeEnd, x = Math.max(p, 5e-3), v = 0, _ = Math.max(
          24,
          Math.min(96, Math.floor(d * 0.22))
        ), b = d - _ - v, w = b + _ * 0.5;
        n.backgroundGrid.moveTo(0, b - 1), n.backgroundGrid.lineTo(n.options.width, b - 1), n.backgroundGrid.stroke({
          width: 1,
          color: 10066329,
          alpha: 0.5
        }), n.waveformLayer.rect(
          u,
          b,
          Math.max(0, n.options.width - u),
          _
        ), n.waveformLayer.fill({ color: 0, alpha: 0.04 });
        for (let S = m; S <= y; S += x) {
          const T = o.timeToPixel(S) + n.state.panX, k = c.sampleAtTime ? c.sampleAtTime(S) : null;
          if (!k) continue;
          const C = Math.max(
            Math.max(0, Math.min(1, k.max)),
            Math.max(0, Math.min(1, k.min))
          ), M = _ * 0.5 * C;
          n.waveformLayer.moveTo(T, w - M), n.waveformLayer.lineTo(T, w + M), n.waveformLayer.stroke({
            width: 1,
            color: k.color ?? 4674921,
            /* slate-600 for neutral, accessible contrast */
            alpha: 0.8
          });
        }
        if (n.options.showPianoKeys && t.waveformKeysLayer) {
          const S = t.waveformKeysLayer, T = _, k = b, C = w;
          S.rect(
            0,
            k,
            Math.max(0, n.playheadX),
            T
          ), S.fill({ color: 0, alpha: 0.04 });
          const M = Math.max(
            0,
            n.timeScale.invert(
              (0 - u - n.state.panX) / n.state.zoomX
            )
          ), A = Math.min(
            n.timeScale.domain()[1],
            n.timeScale.invert(
              (n.playheadX - u - n.state.panX) / n.state.zoomX
            )
          );
          for (let I = M; I <= A; I += x) {
            const F = o.timeToPixel(I) + n.state.panX;
            if (F < 0 || F >= n.playheadX) continue;
            const R = c.sampleAtTime ? c.sampleAtTime(I) : null;
            if (!R) continue;
            const E = Math.max(
              Math.max(0, Math.min(1, R.max)),
              Math.max(0, Math.min(1, R.min))
            ), P = T * 0.5 * E;
            S.moveTo(F, C - P), S.lineTo(F, C + P), S.stroke({
              width: 1,
              color: R.color ?? 4674921,
              alpha: 0.8
            });
          }
        }
      }
    }
  } catch {
  }
}
let yd = {}, xd = {}, _d = {};
function bb(n) {
  const t = n.options.showPianoKeys ? 60 : 0, e = n.options.noteRange.max - n.options.noteRange.min, s = n.pitchScale(n.options.noteRange.min), i = n.pitchScale(n.options.noteRange.max), o = Math.abs(s - i) / Math.max(1, e), a = n.state.zoomY, l = rt.WHITE;
  function c(d = "up") {
    const f = yd[d];
    if (f)
      return f;
    const p = 12, g = document.createElement("canvas");
    g.width = p, g.height = p;
    const m = g.getContext("2d");
    m.clearRect(0, 0, p, p), m.strokeStyle = "#ffffff", m.lineWidth = 2, m.lineCap = "butt", m.beginPath(), d === "up" ? (m.moveTo(-2, p - 2), m.lineTo(p - 2, -2), m.moveTo(0, p), m.lineTo(p, 0), m.moveTo(2, p + 2), m.lineTo(p + 2, 2)) : (m.moveTo(-2, -2), m.lineTo(p - 2, p - 2), m.moveTo(0, 0), m.lineTo(p, p), m.moveTo(2, 2), m.lineTo(p + 2, p + 2)), m.stroke();
    const y = rt.from(g), x = y.source;
    return x.style && (x.style.addressMode = "repeat"), yd[d] = y, y;
  }
  function h(d) {
    const f = xd[d];
    if (f) return f;
    const p = 10, g = document.createElement("canvas");
    g.width = p, g.height = p;
    const m = g.getContext("2d");
    if (m.clearRect(0, 0, p, p), m.strokeStyle = "#000000", m.fillStyle = "#000000", m.lineWidth = 1.5, m.lineCap = "butt", d === "up")
      m.beginPath(), m.moveTo(-2, p), m.lineTo(p, -2), m.moveTo(0, p + 2), m.lineTo(p + 2, 0), m.stroke();
    else if (d === "down")
      m.beginPath(), m.moveTo(-2, -2), m.lineTo(p, p), m.moveTo(0, 0), m.lineTo(p + 2, p + 2), m.stroke();
    else if (d === "cross")
      m.beginPath(), m.moveTo(p / 2, 0), m.lineTo(p / 2, p), m.moveTo(0, p / 2), m.lineTo(p, p / 2), m.stroke();
    else if (d === "dots")
      for (let v = 2; v < p; v += 4)
        for (let _ = 2; _ < p; _ += 4)
          m.beginPath(), m.arc(_, v, 0.8, 0, Math.PI * 2), m.fill();
    const y = rt.from(g), x = y.source;
    return x.style && (x.style.addressMode = "repeat"), xd[d] = y, y;
  }
  function u(d, f) {
    const p = `${d.shape}-${d.variant}-${d.strokeWidth}-${f}`, g = _d[p];
    if (g) return g;
    const y = 16, x = y / 2, v = y / 2, _ = y * 0.35, b = document.createElement("canvas");
    b.width = y, b.height = y;
    const w = b.getContext("2d");
    w.clearRect(0, 0, y, y), w.lineWidth = Math.max(1, d.strokeWidth), w.strokeStyle = f, w.fillStyle = d.variant === "filled" ? "#ffffff" : "transparent", w.lineJoin = "miter";
    const S = (C) => {
      w.beginPath(), w.moveTo(C[0][0], C[0][1]);
      for (let M = 1; M < C.length; M++) w.lineTo(C[M][0], C[M][1]);
      w.closePath(), d.variant === "filled" && w.fill(), w.stroke();
    };
    ((C) => {
      switch (C) {
        case "circle": {
          w.beginPath(), w.arc(x, v, _, 0, Math.PI * 2), d.variant === "filled" && w.fill(), w.stroke();
          return;
        }
        case "square": {
          const M = _ * Math.SQRT1_2;
          S([
            [x - M, v - M],
            [x + M, v - M],
            [x + M, v + M],
            [x - M, v + M]
          ]);
          return;
        }
        case "diamond": {
          S([
            [x, v - _],
            [x + _, v],
            [x, v + _],
            [x - _, v]
          ]);
          return;
        }
        case "triangle-up": {
          S([
            [x, v - _],
            [x + _ * 0.866, v + _ * 0.5],
            [x - _ * 0.866, v + _ * 0.5]
          ]);
          return;
        }
        case "triangle-down": {
          S([
            [x - _ * 0.866, v - _ * 0.5],
            [x + _ * 0.866, v - _ * 0.5],
            [x, v + _]
          ]);
          return;
        }
        case "triangle-left": {
          S([
            [x + _, v - _ * 0.866 * 0.5],
            [x + _, v + _ * 0.866 * 0.5],
            [x - _, v]
          ]);
          return;
        }
        case "triangle-right": {
          S([
            [x - _, v - _ * 0.866 * 0.5],
            [x - _, v + _ * 0.866 * 0.5],
            [x + _, v]
          ]);
          return;
        }
        case "star": {
          const M = [], I = _, F = _ * 0.45;
          for (let R = 0; R < 10; R++) {
            const E = R * Math.PI / 5 - Math.PI / 2, P = R % 2 === 0 ? I : F;
            M.push([x + Math.cos(E) * P, v + Math.sin(E) * P]);
          }
          S(M);
          return;
        }
        case "cross": {
          w.beginPath(), w.moveTo(x - _, v - _), w.lineTo(x + _, v + _), w.moveTo(x + _, v - _), w.lineTo(x - _, v + _), w.stroke();
          return;
        }
        case "plus": {
          w.beginPath(), w.moveTo(x - _, v), w.lineTo(x + _, v), w.moveTo(x, v - _), w.lineTo(x, v + _), w.stroke();
          return;
        }
        case "hexagon": {
          const M = [];
          for (let A = 0; A < 6; A++) {
            const I = Math.PI / 3 * A + Math.PI / 6;
            M.push([x + Math.cos(I) * _, v + Math.sin(I) * _]);
          }
          S(M);
          return;
        }
        case "pentagon": {
          const M = [];
          for (let A = 0; A < 5; A++) {
            const I = 2 * Math.PI / 5 * A - Math.PI / 2;
            M.push([x + Math.cos(I) * _, v + Math.sin(I) * _]);
          }
          S(M);
          return;
        }
        case "chevron-up": {
          S([
            [x - _, v + _ * 0.4],
            [x, v - _ * 0.6],
            [x + _, v + _ * 0.4]
          ]);
          return;
        }
        case "chevron-down": {
          S([
            [x - _, v - _ * 0.4],
            [x, v + _ * 0.6],
            [x + _, v - _ * 0.4]
          ]);
          return;
        }
        default: {
          const M = _ * Math.SQRT1_2;
          S([
            [x - M, v - M],
            [x + M, v - M],
            [x + M, v + M],
            [x - M, v + M]
          ]);
        }
      }
    })(d.shape);
    const k = rt.from(b);
    return _d[p] = k, k;
  }
  for (; n.noteSprites.length < n.notes.length; ) {
    const d = new wn(l);
    d.eventMode = "static", d.cursor = "pointer", d.on("pointerover", (_) => {
      const b = d.noteData;
      b && n.showNoteTooltip(b, _);
    }), d.on("pointermove", (_) => {
      n.moveTooltip(_);
    }), d.on("pointerout", () => {
      n.hideTooltip();
    }), n.notesContainer.addChild(d), n.noteSprites.push(d);
    const f = n, p = f.patternSprites ??= [], g = new Gu({
      texture: h("up"),
      width: 1,
      height: 1
    });
    g.visible = !1, g.alpha = 0.18, g.tint = 0, g.blendMode = "normal", n.notesContainer.addChild(g), p.push(g);
    const m = f.onsetSprites ??= [], y = new wn(rt.WHITE);
    y.visible = !1, y.alpha = 0.75, y.blendMode = "normal", n.notesContainer.addChild(y), m.push(y);
    const x = f.hatchSprites ??= [], v = new Gu({
      texture: c("up"),
      width: 1,
      height: 1
    });
    v.visible = !1, v.alpha = 0.55, v.tint = parseInt(Al.replace("#", ""), 16), n.notesContainer.addChild(v), x.push(v);
  }
  for (; n.noteSprites.length > n.notes.length; ) {
    const d = n.noteSprites.pop();
    d && (n.notesContainer.removeChild(d), d.destroy());
    const f = n, p = f.hatchSprites, g = f.patternSprites;
    if (g && g.length > n.noteSprites.length) {
      const y = g.pop();
      y && (n.notesContainer.removeChild(y), y.destroy());
    }
    if (p && p.length > n.noteSprites.length) {
      const y = p.pop();
      y && (n.notesContainer.removeChild(y), y.destroy());
    }
    const m = f.onsetSprites;
    if (m && m.length > n.noteSprites.length) {
      const y = m.pop();
      y && (n.notesContainer.removeChild(y), y.destroy());
    }
  }
  n.notes.forEach((d, f) => {
    const p = n.noteSprites[f], g = n.timeScale(d.time) * n.state.zoomX + t, m = n.pitchScale(d.midi), y = n.options.height / 2, x = (m - y) * a + y, v = n.timeScale(d.duration) * n.state.zoomX, _ = Math.max(1, o * 0.8 * a);
    p.x = g, p.y = x - _ / 2, p.width = v, p.height = _;
    const b = n.options.noteRenderer ? n.options.noteRenderer(d, f) : n.options.noteColor;
    p.tint = b, p.noteData = d;
    const w = 4473924;
    p.alpha = b === w ? 0.5 : 1;
    const S = n.highlightMode ?? "file";
    p.blendMode = S === "highlight-blend" ? "add" : "normal";
    const k = (n.patternSprites ??= [])[f];
    if (k) {
      k.visible = !1, k.x = p.x, k.y = p.y, k.width = p.width, k.height = p.height;
      const P = d.fileId || "", D = (n.onsetStyles || {})[P];
      if (D) {
        const G = {
          "triangle-up": "up",
          "triangle-down": "down",
          cross: "cross",
          plus: "cross"
        }[D.shape] ?? "dots";
        k.texture = h(G);
      } else {
        let V = 0;
        for (let q = 0; q < P.length; q++)
          V = V * 31 + P.charCodeAt(q) >>> 0;
        const G = [
          "up",
          "down",
          "cross",
          "dots"
        ], H = G[V % G.length];
        k.texture = h(H);
      }
      const O = Math.max(1, 10 / Math.max(6, _));
      k.tileScale.set(O, O), n.highlightMode, k.alpha = 0, k.visible = !1;
    }
    const M = (n.hatchSprites ??= [])[f];
    if (M) {
      const P = d.isEvalHighlightSegment === !0;
      if (d.noOverlay === !0)
        M.visible = !1;
      else if (P) {
        const N = d.evalSegmentKind ?? "intersection";
        let D;
        const z = n.highlightMode ?? "file";
        typeof z == "string" && z.includes("-gray") ? N === "exclusive" ? D = parseInt(lb.replace("#", ""), 16) : N === "ambiguous" ? D = parseInt(rm.replace("#", ""), 16) : D = parseInt(To.replace("#", ""), 16) : N === "exclusive" ? D = parseInt(im.replace("#", ""), 16) : N === "ambiguous" ? D = b : D = parseInt(Al.replace("#", ""), 16), M.visible = !0, M.x = p.x, M.y = p.y, M.width = p.width, M.height = p.height, M.tilePosition.set(0, 0);
        const V = N === "exclusive" ? "down" : N === "ambiguous" ? "cross" : "up";
        V === "cross" ? M.texture = h("cross") : M.texture = c(V), M.tint = D, M.alpha = N === "ambiguous" ? 0.4 : N === "intersection" ? 0.2 : 0.24, M.blendMode = "normal";
        const H = Math.max(1, (N === "ambiguous" ? 16 : N === "intersection" ? 10 : 12) / Math.max(6, _));
        M.tileScale.set(H, H);
      } else
        M.visible = !1;
    }
    const A = n.showOnsetMarkers === !0, F = (n.onsetSprites ??= [])[f], R = n.originalOnsetMap, E = n.onlyOriginalOnsets !== !1;
    if (F)
      if (A) {
        const P = d.fileId || "", z = "#" + (n.fileColors?.[P] ?? b).toString(16).padStart(6, "0"), V = (n.onsetStyles || {})[P] || { shape: "circle", variant: "filled", size: 12, strokeWidth: 2 };
        if (E && R) {
          const U = `${P}#${d.sourceIndex ?? -1}`, at = R[U];
          if (at === void 0 || Math.abs(at - d.time) > 1e-6) {
            F.visible = !1;
            return;
          }
        }
        const G = u(V, z);
        F.texture = G, F.tint = 16777215, F.blendMode = "normal", F.alpha = 0.95;
        const H = Math.max(8, V.size || 12), q = Math.max(6, Math.floor(_ * 0.9)), W = H * a, K = Math.max(6, Math.min(q, Math.floor(W)));
        F.width = K, F.height = K, F.x = p.x - K / 2, F.y = p.y + _ / 2 - K / 2, F.visible = !0, F.zIndex = (p.zIndex || 0) + 5;
      } else
        F.visible = !1;
  });
}
function wb(n) {
  const t = n.sustainOverlay;
  t.clear();
  const e = n.controlChanges.filter((l) => l.controller === cb).sort((l, c) => l.time - c.time), s = {};
  e.forEach((l) => {
    const c = l.fileId ?? "_unknown";
    (s[c] = s[c] || []).push(l);
  });
  const i = n.options.showPianoKeys ? 60 : 0, r = n.timeScale(1) * n.state.zoomX, o = {}, a = [];
  Object.entries(s).forEach(([l, c]) => {
    let h = !1, u = 0;
    if (c.forEach((d) => {
      d.value >= 0.5 ? h || (h = !0, u = d.time) : h && (a.push({ start: u, end: d.time, fid: l }), h = !1);
    }), h) {
      const d = n.notes.length ? Math.max(...n.notes.map((f) => f.time + f.duration)) : c[c.length - 1].time;
      a.push({ start: u, end: d, fid: l });
    }
  }), a.forEach(({ start: l, end: c, fid: h }) => {
    if (c <= l) return;
    const u = l * r + n.state.panX + i, d = (c - l) * r;
    if (d <= 0) return;
    const p = n.fileColors?.[h] ?? yb(n, h, o), g = 0.2;
    t.rect(u, 0, d, n.options.height), t.fill({ color: p, alpha: g });
  });
}
function hm(n) {
  window.getComputedStyle(n).position === "static" && (n.style.position = "relative");
}
function Sb(n, t) {
  const e = t || n.parentElement;
  if (!e)
    throw new Error("Tooltip parent element not found");
  hm(e);
  const s = document.createElement("div");
  return Object.assign(s.style, {
    position: "absolute",
    zIndex: "1000",
    pointerEvents: "none",
    background: "rgba(0, 0, 0, 0.8)",
    color: "#ffffff",
    padding: "4px 6px",
    borderRadius: "4px",
    fontSize: "12px",
    lineHeight: "1.2",
    whiteSpace: "nowrap",
    display: "none"
  }), e.appendChild(s), s;
}
function Tb(n, t) {
  const e = t || n.parentElement;
  if (!e)
    throw new Error("Help overlay parent element not found");
  hm(e);
  const s = document.createElement("button");
  s.type = "button", s.className = "wr-focusable", Object.assign(s.style, {
    position: "absolute",
    top: "8px",
    right: "8px",
    width: "24px",
    height: "24px",
    lineHeight: "22px",
    border: "1px solid var(--ui-border)",
    borderRadius: "6px",
    background: "var(--surface)",
    color: "var(--text-muted)",
    fontSize: "14px",
    fontWeight: "700",
    textAlign: "center",
    cursor: "help",
    zIndex: "1200"
  }), s.textContent = "?", s.setAttribute("aria-label", "Piano roll controls help");
  const i = document.createElement("div");
  i.setAttribute("role", "tooltip"), Object.assign(i.style, {
    position: "absolute",
    top: "36px",
    right: "8px",
    minWidth: "240px",
    maxWidth: "320px",
    background: "var(--surface)",
    border: "1px solid var(--ui-border)",
    borderRadius: "8px",
    boxShadow: "var(--shadow-md)",
    padding: "10px 12px",
    fontSize: "12px",
    color: "var(--text-primary)",
    display: "none",
    zIndex: "1200"
  }), i.innerHTML = `
    <div style="font-weight:700;margin-bottom:6px;">Piano roll controls</div>
    <ul style="margin:0;padding-left:16px;display:flex;flex-direction:column;gap:4px;">
      <li><strong>Horizontal zoom</strong>: Mouse wheel. Hold Ctrl/Cmd to zoom around cursor.</li>
      <li><strong>Vertical zoom</strong>: Alt/Option + Mouse wheel.</li>
      <li><strong>Pan left/right</strong>: Click & drag horizontally, or Shift + Mouse wheel.</li>
      <li><strong>Pan up/down</strong>: Click & drag vertically (Alt to force vertical-only).</li>
    </ul>
  `;
  let r = null;
  const o = () => {
    r && (window.clearTimeout(r), r = null), i.style.display = "block";
  }, a = () => {
    r && window.clearTimeout(r), r = window.setTimeout(() => {
      i.style.display = "none";
    }, 200);
  };
  return s.addEventListener("mouseenter", o), s.addEventListener("mouseleave", a), s.addEventListener("focus", o), s.addEventListener("blur", a), i.addEventListener("mouseenter", o), i.addEventListener("mouseleave", a), e.appendChild(s), e.appendChild(i), { button: s, panel: i };
}
const Mb = 16711680, kb = 0.25;
function Cb(n, t, e = Mb, s = kb) {
  if (!n.overlapOverlay) return;
  const i = n.overlapOverlay;
  if (i.clear(), !t || t.length === 0) return;
  const r = n.options.showPianoKeys ? 60 : 0, o = n.timeScale(1) * n.state.zoomX;
  t.forEach(({ start: a, end: l }) => {
    const c = a * o + n.state.panX + r, h = (l - a) * o;
    h <= 0 || (i.rect(c, 0, h, n.options.height), i.fill({ color: e, alpha: s }));
  });
}
function Ab(n) {
  n.container = new Te(), n.container.sortableChildren = !0, n.app.stage.addChild(n.container), n.backgroundGrid = new ie(), n.backgroundGrid.zIndex = 1, n.container.addChild(n.backgroundGrid), n.pianoKeyLines = new ie(), n.pianoKeyLines.zIndex = 2, n.container.addChild(n.pianoKeyLines), n.pianoKeyLabelContainer = new Te(), n.pianoKeyLabelContainer.zIndex = 3, n.container.addChild(n.pianoKeyLabelContainer), n.waveformLayer = new ie(), n.waveformLayer.zIndex = 0, n.container.addChild(n.waveformLayer), n.waveformKeysLayer = new ie(), n.waveformKeysLayer.zIndex = 2, n.container.addChild(n.waveformKeysLayer), n.backgroundLabelContainer = new Te(), n.backgroundLabelContainer.zIndex = 2, n.container.addChild(n.backgroundLabelContainer), n.notesContainer = new Te(), n.notesContainer.zIndex = 10, n.container.addChild(n.notesContainer), n.notesMask = new ie(), n.container.addChild(n.notesMask), n.notesContainer.mask = n.notesMask, n.sustainContainer = new Te(), n.sustainContainer.zIndex = 5, n.container.addChild(n.sustainContainer), n.sustainContainer.mask = n.notesMask, n.sustainOverlay = new ie(), n.sustainOverlay.zIndex = -10, n.sustainContainer.addChild(n.sustainOverlay), n.playheadLine = new ie(), n.playheadLine.zIndex = 1e3, n.container.addChild(n.playheadLine), n.loopOverlay = new ie(), n.loopOverlay.zIndex = 500, n.container.addChild(n.loopOverlay), n.overlapOverlay = new ie(), n.overlapOverlay.zIndex = 20, n.container.addChild(n.overlapOverlay), n.loopLabelContainer = new Te(), n.loopLabelContainer.zIndex = 600, n.container.addChild(n.loopLabelContainer);
  const t = new ie(), e = new ie();
  t.zIndex = 600, e.zIndex = 600, n.container.addChild(t), n.container.addChild(e), n.loopLines = { start: t, end: e };
}
class hc {
  constructor(t, e, s = {}) {
    this.loopLines = null, this.overlapIntervals = [], this.tooltipDiv = null, this.helpButtonEl = null, this.helpPanelEl = null, this.pitchHoverDiv = null, this.playheadX = 0, this.notes = [], this.noteGraphics = [], this.controlChanges = [], this.noteSprites = [], this.needsNotesRedraw = !0, this.lastRenderTime = 0, this.renderThrottleMs = 16, this.rafId = null, this.performanceMetrics = {
      renderCount: 0,
      totalRenderTime: 0,
      slowRenders: 0,
      skippedRenders: 0,
      setTimeCount: 0,
      lastRenderTime: 0
    }, this.loopStart = null, this.loopEnd = null, this.pxPerSecond = null, this.onTimeChangeCallback = null, this.domContainer = e, this.options = {
      width: 800,
      height: 400,
      backgroundColor: 16777215,
      noteColor: 4359668,
      playheadColor: 1982639,
      showPianoKeys: !0,
      noteRange: { min: 21, max: 108 },
      // A0 to C8
      timeStep: 1,
      minorTimeStep: 0.1,
      noteRenderer: void 0,
      showWaveformBand: !0,
      ...s
    }, this.state = {
      zoomX: 1,
      zoomY: 1,
      panX: 0,
      panY: 0,
      // Always 0 - no vertical panning
      currentTime: 0,
      isPanning: !1,
      lastPointerPos: { x: 0, y: 0 }
    }, this.app = new Mp(), this.initializeScales();
  }
  initializeScales() {
    let t = 0;
    this.options.showWaveformBand !== !1 && (t = 6 + Math.max(
      24,
      Math.min(96, Math.floor(this.options.height * 0.22))
    ));
    const { timeScale: e, pitchScale: s, pxPerSecond: i } = Xv(
      this.notes,
      {
        width: this.options.width,
        height: this.options.height,
        noteRange: this.options.noteRange,
        showPianoKeys: this.options.showPianoKeys
      },
      this.pxPerSecond,
      8,
      t
    );
    this.timeScale = e, this.pitchScale = s, this.pxPerSecond = i;
  }
  /**
   * Static factory method to create PianoRoll instance
   */
  static async create(t, e, s = {}) {
    const i = new hc(t, e, s);
    return await i.initializeApp(t), i.initializeContainers(), i.initializeScales(), i.initializeTooltip(t), i.initializeHelpButton(t), i.initializePitchHover(), i.setupInteraction(), i.render(), i.app.renderer.render(i.app.stage), i;
  }
  /**
   * Initialize PixiJS application with canvas
   */
  async initializeApp(t) {
    await this.app.init({
      canvas: t,
      width: this.options.width,
      height: this.options.height,
      backgroundColor: this.options.backgroundColor,
      antialias: !0,
      resolution: window.devicePixelRatio || 1,
      autoDensity: !0,
      // Only set preference if explicitly configured; otherwise let PixiJS auto-select
      ...this.options.rendererPreference && { preference: this.options.rendererPreference }
    });
  }
  /**
   * Initialize container hierarchy for organized rendering
   */
  initializeContainers() {
    Ab(this);
  }
  initializeTooltip(t) {
    this.tooltipDiv = Sb(t, this.domContainer);
  }
  /** Create a top-right help button with hover panel explaining interactions */
  initializeHelpButton(t) {
    const { button: e, panel: s } = Tb(t, this.domContainer);
    this.helpButtonEl = e, this.helpPanelEl = s;
  }
  /** Initialize pitch hover indicator for showing current pitch row */
  initializePitchHover() {
    this.pitchHoverDiv = document.createElement("div"), this.pitchHoverDiv.style.cssText = `
      position: absolute;
      left: 0;
      width: 60px;
      padding: 2px 6px;
      background: rgba(30, 64, 175, 0.9);
      color: white;
      font-size: 10px;
      font-weight: 600;
      border-radius: 0 4px 4px 0;
      pointer-events: none;
      z-index: 100;
      display: none;
      white-space: nowrap;
      box-sizing: border-box;
    `, this.domContainer.appendChild(this.pitchHoverDiv), this.pitchHoverHighlight = new ie(), this.pitchHoverHighlight.zIndex = 5, this.container.addChild(this.pitchHoverHighlight);
  }
  /**
   * Find all notes at the given time and pitch position
   */
  findNotesAtPosition(t, e) {
    const s = [];
    for (const r of this.notes)
      t >= r.time && t <= r.time + r.duration && Math.abs(r.midi - e) <= 0.5 && s.push(r);
    return s;
  }
  /**
   * Show tooltip populated with the given note information.
   */
  showNoteTooltip(t, e) {
    if (!this.tooltipDiv) return;
    const s = this.options.showPianoKeys ? 60 : 0, i = e.global.x - s - this.state.panX, r = this.timeScale.invert(i / this.state.zoomX), o = this.findNotesAtPosition(r, t.midi), a = this.fileInfoMap, l = /* @__PURE__ */ new Map();
    for (const y of o)
      if (y.fileId && a) {
        const x = a[y.fileId];
        x && (l.has(y.fileId) || l.set(y.fileId, { info: x, notes: [] }), l.get(y.fileId).notes.push(y));
      }
    const c = `${t.name} (MIDI: ${t.midi})`;
    let h = "";
    l.size > 0 && (h = Array.from(l.entries()).sort((x, v) => {
      const _ = {
        Reference: 0,
        Comparison: 1,
        MIDI: 2
      }, b = _[x[1].info.kind] ?? 3, w = _[v[1].info.kind] ?? 3;
      return b - w;
    }).map(([x, { info: v, notes: _ }]) => {
      const b = `<span style="display:inline-block;width:12px;height:12px;background:#${v.color.toString(16).padStart(
        6,
        "0"
      )};border-radius:2px;margin-right:8px;vertical-align:middle;border:1px solid rgba(255,255,255,0.3);"></span>`, S = [
        ...new Set(
          _.map((k) => k.trackId).filter((k) => k !== void 0)
        )
      ].map((k) => v.tracks?.find((C) => C.id === k)?.name).filter((k) => k !== void 0), T = S.length > 0 ? ` · ${S.join(", ")}` : "";
      return `<div style="margin-top:4px;display:flex;align-items:center;">${b}<span style="font-weight:500;">${v.kind}: ${v.name}${T}</span></div>`;
    }).join(""));
    const u = t.evalSegmentKind, d = t.isEvalHighlightSegment === !0;
    let f = null;
    if (t.fileId && this.fileInfoMap) {
      const y = t.fileId;
      f = this.fileInfoMap[y]?.kind ?? null;
    }
    let p = "";
    d ? u === "intersection" ? p = "Matched overlap (Reference + Comparison blended)" : u === "exclusive" ? p = `Matched exclusive (${f ?? "Track"} part)` : u === "ambiguous" && (p = "Ambiguous (same pitch, overlapped, not matched)<br/>Possible cause: near-onset but offset too different (length mismatch)") : (f === "Reference" || f === "Comparison") && (p = `${f} only`);
    let g = t.time, m = t.time + t.duration;
    if (o.length > 1)
      for (const y of o)
        g = Math.min(g, y.time), m = Math.max(m, y.time + y.duration);
    this.tooltipDiv.innerHTML = `
      <div><strong>${c}</strong></div>
      ${h}
      <div style="margin-top:4px;color:rgba(255,255,255,0.9);">Time: ${g.toFixed(2)}s - ${m.toFixed(2)}s</div>
      <div style="color:rgba(255,255,255,0.9);">Velocity: ${t.velocity.toFixed(2)}</div>
      ${p ? `<div style="margin-top:4px;color:rgba(255,255,255,0.95);font-weight:600;">${p}</div>` : ""}
    `, this.tooltipDiv.style.display = "block", this.moveTooltip(e);
  }
  /** Update tooltip position to follow the pointer */
  moveTooltip(t) {
    if (!this.tooltipDiv) return;
    const e = 10, s = this.tooltipDiv.parentElement;
    if (!s) return;
    const i = s.getBoundingClientRect(), r = t.clientX - i.left + e, o = t.clientY - i.top + e;
    this.tooltipDiv.style.left = `${r}px`, this.tooltipDiv.style.top = `${o}px`;
  }
  /** Hide the tooltip */
  hideTooltip() {
    this.tooltipDiv && (this.tooltipDiv.style.display = "none");
  }
  /**
   * Update pitch hover indicator based on mouse Y position
   * @param clientY - Mouse Y position relative to viewport
   */
  updatePitchHover(t) {
    if (!this.pitchHoverDiv || !this.options.showPianoKeys) return;
    const s = this.app.canvas.getBoundingClientRect(), i = t - s.top;
    let r = 0;
    this.options.showWaveformBand !== !1 && (r = 6 + Math.max(
      24,
      Math.min(96, Math.floor(this.options.height * 0.22))
    ));
    const o = this.options.height - r;
    if (i < 0 || i > o) {
      this.hidePitchHover();
      return;
    }
    const a = this.options.height / 2, c = (i - this.state.panY - a) / this.state.zoomY + a, h = Math.round(this.pitchScale.invert(c)), u = hs(
      h,
      this.options.noteRange.min,
      this.options.noteRange.max
    );
    let d;
    try {
      d = cc(u);
    } catch {
      d = `MIDI ${u}`;
    }
    const f = this.pitchScale(u), p = this.pitchScale(u + 1), g = Math.abs(
      (f - a) * this.state.zoomY - (p - a) * this.state.zoomY
    ), m = (f - a) * this.state.zoomY + a, y = m - g / 2;
    this.pitchHoverDiv.textContent = `${d} (${u})`, this.pitchHoverDiv.style.display = "block", this.pitchHoverDiv.style.top = `${m - 10 + this.state.panY}px`;
    const x = this.playheadX;
    this.pitchHoverHighlight.clear(), this.pitchHoverHighlight.rect(0, y, x, g), this.pitchHoverHighlight.fill({ color: 1982639, alpha: 0.15 });
    const _ = (this.pitchScale(u) - a) * this.state.zoomY + a, b = 4, w = 4, S = 1982639, T = 0.15;
    let k = x;
    for (; k < this.options.width; ) {
      const C = Math.min(k + b, this.options.width);
      this.pitchHoverHighlight.moveTo(k, _), this.pitchHoverHighlight.lineTo(C, _), this.pitchHoverHighlight.stroke({ width: 1, color: S, alpha: T }), k += b + w;
    }
  }
  /** Hide pitch hover indicator */
  hidePitchHover() {
    this.pitchHoverDiv && (this.pitchHoverDiv.style.display = "none"), this.pitchHoverHighlight && this.pitchHoverHighlight.clear();
  }
  /**
   * Set up mouse/touch interaction for panning and zooming
   */
  setupInteraction() {
    const t = this.app.canvas, e = { passive: !1 }, s = { isPinching: !1, lastDistance: 0, anchorX: 0 };
    t.addEventListener(
      "mousedown",
      // this.onPointerDown.bind(this),
      (i) => dd(i, this),
      e
    ), t.addEventListener(
      "mousemove",
      (i) => {
        fd(i, this), this.updatePitchHover(i.clientY);
      },
      e
    ), t.addEventListener("mouseup", (i) => Xa(i, this)), t.addEventListener("mouseleave", (i) => {
      Xa(i, this), this.hidePitchHover();
    }), t.addEventListener(
      "touchstart",
      (i) => {
        (i.touches?.length ?? 0) >= 2 ? rb(i, this, s) : dd(i, this);
      },
      e
    ), t.addEventListener(
      "touchmove",
      (i) => {
        s.isPinching && (i.touches?.length ?? 0) >= 2 ? ob(i, this, s) : fd(i, this);
      },
      e
    ), t.addEventListener(
      "touchend",
      (i) => {
        s.isPinching ? ab(i, this, s) : Xa(i, this);
      }
    ), t.addEventListener(
      "wheel",
      (i) => {
        sb(i, this), this.updatePitchHover(i.clientY);
      },
      e
    ), t.style.touchAction = "none";
  }
  /**
   * Request render with throttling for performance
   */
  requestRender() {
    this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
    const t = performance.now(), e = t - this.lastRenderTime;
    e >= this.renderThrottleMs ? (this.lastRenderTime = t, this.render()) : (this.performanceMetrics.skippedRenders++, this.renderThrottleMs - e, this.rafId = requestAnimationFrame(() => {
      this.rafId = null, this.lastRenderTime = performance.now(), this.render();
    }));
  }
  /**
   * Full render of all components
   */
  render() {
    const t = performance.now();
    {
      let i = 0;
      this.options.showWaveformBand !== !1 && (i = 6 + Math.max(
        24,
        Math.min(96, Math.floor(this.options.height * 0.22))
      ));
      const r = Math.max(0, this.options.height - i);
      this.notesMask.clear(), this.notesMask.rect(0, 0, this.options.width, r), this.notesMask.fill({ color: 16777215, alpha: 1 });
    }
    mb(this), vb(this), this.needsNotesRedraw && (bb(this), this.needsNotesRedraw = !1), wb(this), this.notesContainer.x = this.state.panX, this.notesContainer.y = this.state.panY, this.sustainContainer.x = this.state.panX, this.sustainContainer.y = this.state.panY, this.overlapOverlay.x = this.state.panX, this.overlapOverlay.y = this.state.panY, this.pianoKeyLines.y = this.state.panY, this.pianoKeyLabelContainer.y = this.state.panY, this.pitchHoverHighlight.y = this.state.panY, this.container.sortChildren();
    const s = performance.now() - t;
    this.performanceMetrics.renderCount++, this.performanceMetrics.totalRenderTime += s, this.performanceMetrics.lastRenderTime = s, s > 16 && (this.performanceMetrics.slowRenders++, console.warn(`[PianoRoll] Slow render: ${s.toFixed(2)}ms`)), this.performanceMetrics.renderCount % 100 === 0 && this.performanceMetrics.totalRenderTime / this.performanceMetrics.renderCount;
  }
  /**
   * Set note data and trigger re-render
   */
  setNotes(t) {
    this.notes = t, this.initializeScales(), this.needsNotesRedraw = !0, this.render(), this.app.renderer.render(this.app.stage);
  }
  /**
   * Set current playback time and update playhead
   */
  setTime(t) {
    if (this.performanceMetrics.setTimeCount++, this.state.currentTime = t, !this.state.isPanning) {
      const e = this.timeScale(1) * this.state.zoomX, s = t * e;
      this.state.panX = -s, Gn(this.timeScale, this.state);
    }
    this.requestRender();
  }
  /**
   * Zoom in/out on X axis (time)
   */
  zoomX(t, e) {
    if (t === 1) return;
    const s = this.state.zoomX, i = Math.max(0.1, Math.min(10, s * t)), r = this.options.showPianoKeys ? 60 : 0, o = e !== void 0 ? e : r, a = this.timeScale.invert(
      (o - r - this.state.panX) / s
    );
    this.state.zoomX = i;
    const l = o - r - this.timeScale(a) * i;
    this.state.panX = l;
    const c = this.state.panX;
    Gn(this.timeScale, this.state), e !== void 0 && this.state.panX !== c && this.timeScale.invert(
      (o - r - this.state.panX) / i
    ), this.needsNotesRedraw = !0, this.requestRender();
  }
  /**
   * Zoom in/out on Y axis (pitch)
   */
  zoomY(t) {
    if (t === 1) return;
    const e = this.state.zoomY, s = Math.max(0.2, Math.min(5, e * t));
    s !== e && (this.state.zoomY = s, ji(this.pitchScale, this.state, this.options.height), this.needsNotesRedraw = !0, this.requestRender());
  }
  /**
   * Pan the view by specified pixels
   */
  pan(t, e) {
    this.state.panX = this.state.panX + t, this.state.panY = this.state.panY + e, Gn(this.timeScale, this.state), ji(this.pitchScale, this.state, this.options.height), this.requestRender();
  }
  /**
   * Reset zoom and pan to default values
   */
  resetView() {
    const t = this.state.currentTime || 0;
    this.state.zoomX = 1, this.state.zoomY = 1;
    const e = this.timeScale(1) * this.state.zoomX;
    this.state.panX = -t * e, this.state.panY = 0, Gn(this.timeScale, this.state), ji(this.pitchScale, this.state, this.options.height), this.needsNotesRedraw = !0, this.requestRender();
  }
  /**
   * Resize the PixiJS renderer and recompute scales/render.
   * @param width New canvas width in pixels
   * @param height New canvas height in pixels (defaults to existing height)
   */
  resize(t, e) {
    const s = Math.max(1, Math.floor(t)), i = Math.max(1, Math.floor(e ?? this.options.height));
    if (s === this.options.width && i === this.options.height)
      return;
    this.options.width = s, this.options.height = i, this.app.renderer.resize(s, i);
    const r = this.app.canvas;
    r.style.width = "100%", r.style.height = "100%", this.pxPerSecond = null, this.initializeScales(), this.needsNotesRedraw = !0, this.requestRender();
  }
  /**
   * Update timeStep (grid spacing in seconds) and re-render background
   */
  setTimeStep(t) {
    this.options.timeStep = Math.max(0.01, t), this.requestRender();
  }
  /**
   * Update minor grid step and re-render
   */
  setMinorTimeStep(t) {
    this.options.minorTimeStep = Math.max(1e-3, t), this.requestRender();
  }
  /**
   * Get current timeStep
   */
  getTimeStep() {
    return this.options.timeStep;
  }
  /**
   * Get current minor timeStep
   */
  getMinorTimeStep() {
    return this.options.minorTimeStep;
  }
  /**
   * Destroy the piano roll and clean up resources
   */
  destroy() {
    this.noteGraphics.forEach((t) => t.destroy()), this.noteSprites.forEach((t) => t.destroy()), this.pitchHoverDiv && this.pitchHoverDiv.parentElement && this.pitchHoverDiv.parentElement.removeChild(this.pitchHoverDiv), this.pitchHoverHighlight && this.pitchHoverHighlight.destroy(), this.app.destroy(!0);
  }
  /**
   * Get current state for debugging
   */
  getState() {
    return { ...this.state };
  }
  /**
   * Clamp panX so that the playhead (fixed at pianoKeysOffset) always lies within
   * the timeline content. Prevents scrolling past the beginning or end.
   */
  /**
   * Update loop window markers (A-B). Pass nulls to clear.
   */
  setLoopWindow(t, e) {
    this.loopStart = t, this.loopEnd = e, this.requestRender();
  }
  /**
   * Register a callback that fires whenever the time under the fixed playhead changes.
   * This happens when the visual timeline is panned or zoomed.
   */
  onTimeChange(t) {
    this.onTimeChangeCallback = t;
  }
  computeTimeAtPlayhead() {
    const t = this.timeScale.invert(-this.state.panX / this.state.zoomX);
    return hs(t, 0, this.timeScale.domain()[1]);
  }
  setOverlapRegions(t) {
    this.overlapIntervals = t, Cb(this, t);
  }
  setControlChanges(t) {
    this.controlChanges = t, this.needsNotesRedraw = !0, this.render();
  }
}
async function Eb(n, t = [], e = {}) {
  const s = document.createElement("canvas");
  s.style.display = "block", s.style.width = "100%", s.style.height = "100%", n.innerHTML = "", n.appendChild(s);
  const i = await hc.create(s, n, e), r = new ResizeObserver((o) => {
    for (const a of o) {
      const { width: l, height: c } = a.contentRect;
      l > 0 && c > 0 && i.resize(Math.floor(l), Math.floor(c));
    }
  });
  return r.observe(n), t.length > 0 && i.setNotes(t), {
    /**
     * Update the notes being displayed
     */
    setNotes: (o) => i.setNotes(o),
    /**
     * Update control-change events (e.g., sustain pedal)
     */
    setControlChanges: (o) => i.setControlChanges(o),
    /**
     * Update current playback time
     */
    setTime: (o) => i.setTime(o),
    /**
     * Zoom in/out on time axis
     */
    zoomX: (o) => i.zoomX(o),
    /**
     * Zoom in/out on pitch axis
     */
    zoomY: (o) => i.zoomY(o),
    /**
     * Pan the view
     */
    pan: (o, a) => i.pan(o, a),
    /**
     * Reset view to default zoom and pan
     */
    resetView: () => i.resetView(),
    /**
     * Get current state for debugging
     */
    getState: () => i.getState(),
    /**
     * Clean up resources
     */
    destroy: () => {
      r.disconnect(), i.destroy();
    },
    /**
     * Update timeStep (grid spacing in seconds)
     */
    setTimeStep: (o) => i.setTimeStep(o),
    /**
     * Get current timeStep
     */
    getTimeStep: () => i.getTimeStep(),
    /**
     * Update loop window markers (A-B)
     */
    setLoopWindow: (o, a) => i.setLoopWindow(o, a),
    /**
     * Register callback for time changes due to panning/zooming
     */
    onTimeChange: (o) => i.onTimeChange(o),
    /**
     * Update minor grid step and re-render
     */
    setMinorTimeStep: (o) => i.setMinorTimeStep(o),
    /**
     * Get current minor timeStep
     */
    getMinorTimeStep: () => i.getMinorTimeStep(),
    /** Update overlap highlight bars */
    setOverlapRegions: (o) => i.setOverlapRegions(o),
    /** Resize the PixiJS renderer */
    resize: (o, a) => i.resize(o, a),
    /**
     * Get the underlying PianoRoll instance for direct access
     * This is needed for setting internal properties like fileInfoMap
     */
    _instance: i
  };
}
const Cs = [
  {
    id: "default",
    name: "Default",
    /**
     * Tableau‑inspired, eye‑friendly set with varied luminance.
     * Chosen for low eye‑strain and clear mutual separation.
     */
    colors: [
      5142951,
      // Blue
      15896107,
      // Orange
      5873999,
      // Green
      14767961,
      // Red
      11565729,
      // Purple
      7780274,
      // Teal
      15583560,
      // Mustard
      10253663
      // Brown
    ]
  },
  {
    id: "vibrant",
    name: "Vibrant (Accessible)",
    /**
     * Okabe–Ito 8‑color palette (CVD‑safe) with varied luminance.
     * Order alternates lighter/darker tones to improve adjacency legibility.
     * Reference: Okabe & Ito (2008), widely used for color vision deficiency.
     */
    colors: [
      12131356,
      // Red (dark)  - 1
      3900150,
      // Blue (brighter) - 2
      889992,
      // Teal (darker, higher legibility) - 3
      40563,
      // Bluish green (dark)
      13400487,
      // Reddish purple (medium)
      2916280,
      // Sky blue (darker)
      11754496,
      // Burnt orange (darker)
      0
      // Black (very dark)
    ]
  },
  {
    id: "pastel",
    name: "Pastel",
    colors: [
      11454159,
      // Pastel Blue
      16757690,
      // Pastel Red
      16777146,
      // Pastel Yellow
      12255177,
      // Pastel Green
      14728164,
      // Pastel Purple
      16767153,
      // Pastel Orange
      11922135,
      // Pastel Mint
      16761035
      // Pastel Pink
    ]
  },
  {
    id: "monochrome",
    name: "Monochrome",
    colors: [
      2171169,
      // Black
      4342338,
      // Dark Gray
      6381921,
      // Gray
      7697781,
      // Medium Gray
      10395294,
      // Light Gray
      12434877,
      // Lighter Gray
      14737632,
      // Very Light Gray
      15658734
      // Near White
    ]
  }
];
function um(n = "id") {
  return `${n}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
}
const Pb = () => um("midi"), Ib = () => um("audio");
function Fb(n, t, e, s, i) {
  const r = typeof globalThis.acquireVsCodeApi == "function";
  return {
    id: Pb(),
    // VS Code 통합 시에는 확장자를 포함한 원본 파일명을 그대로 사용해 표시를 보존한다.
    name: s ?? (r ? n : n.replace(/\.mid$/i, "")),
    fileName: n,
    parsedData: t,
    isVisible: !0,
    isPianoRollVisible: !0,
    isSustainVisible: !1,
    fileColor: e,
    color: e,
    isMuted: !1,
    originalInput: i
  };
}
function Ya(n, t) {
  n.forEach((e, s) => {
    e.color = t.colors[s % t.colors.length];
  });
}
var an = {}, to = {}, Za, vd;
function Rb() {
  if (vd) return Za;
  vd = 1;
  function n(i) {
    var r = new s(i), o = r.readChunk();
    if (o.id != "MThd")
      throw "Bad MIDI file.  Expected 'MHdr', got: '" + o.id + "'";
    for (var a = t(o.data), l = [], c = 0; !r.eof() && c < a.numTracks; c++) {
      var h = r.readChunk();
      if (h.id != "MTrk")
        throw "Bad MIDI file.  Expected 'MTrk', got: '" + h.id + "'";
      var u = e(h.data);
      l.push(u);
    }
    return {
      header: a,
      tracks: l
    };
  }
  function t(i) {
    var r = new s(i), o = r.readUInt16(), a = r.readUInt16(), l = {
      format: o,
      numTracks: a
    }, c = r.readUInt16();
    return c & 32768 ? (l.framesPerSecond = 256 - (c >> 8), l.ticksPerFrame = c & 255) : l.ticksPerBeat = c, l;
  }
  function e(i) {
    for (var r = new s(i), o = []; !r.eof(); ) {
      var a = c();
      o.push(a);
    }
    return o;
    var l;
    function c() {
      var h = {};
      h.deltaTime = r.readVarInt();
      var u = r.readUInt8();
      if ((u & 240) === 240)
        if (u === 255) {
          h.meta = !0;
          var d = r.readUInt8(), f = r.readVarInt();
          switch (d) {
            case 0:
              if (h.type = "sequenceNumber", f !== 2) throw "Expected length for sequenceNumber event is 2, got " + f;
              return h.number = r.readUInt16(), h;
            case 1:
              return h.type = "text", h.text = r.readString(f), h;
            case 2:
              return h.type = "copyrightNotice", h.text = r.readString(f), h;
            case 3:
              return h.type = "trackName", h.text = r.readString(f), h;
            case 4:
              return h.type = "instrumentName", h.text = r.readString(f), h;
            case 5:
              return h.type = "lyrics", h.text = r.readString(f), h;
            case 6:
              return h.type = "marker", h.text = r.readString(f), h;
            case 7:
              return h.type = "cuePoint", h.text = r.readString(f), h;
            case 32:
              if (h.type = "channelPrefix", f != 1) throw "Expected length for channelPrefix event is 1, got " + f;
              return h.channel = r.readUInt8(), h;
            case 33:
              if (h.type = "portPrefix", f != 1) throw "Expected length for portPrefix event is 1, got " + f;
              return h.port = r.readUInt8(), h;
            case 47:
              if (h.type = "endOfTrack", f != 0) throw "Expected length for endOfTrack event is 0, got " + f;
              return h;
            case 81:
              if (h.type = "setTempo", f != 3) throw "Expected length for setTempo event is 3, got " + f;
              return h.microsecondsPerBeat = r.readUInt24(), h;
            case 84:
              if (h.type = "smpteOffset", f != 5) throw "Expected length for smpteOffset event is 5, got " + f;
              var p = r.readUInt8(), g = { 0: 24, 32: 25, 64: 29, 96: 30 };
              return h.frameRate = g[p & 96], h.hour = p & 31, h.min = r.readUInt8(), h.sec = r.readUInt8(), h.frame = r.readUInt8(), h.subFrame = r.readUInt8(), h;
            case 88:
              if (h.type = "timeSignature", f != 2 && f != 4) throw "Expected length for timeSignature event is 4 or 2, got " + f;
              return h.numerator = r.readUInt8(), h.denominator = 1 << r.readUInt8(), f === 4 ? (h.metronome = r.readUInt8(), h.thirtyseconds = r.readUInt8()) : (h.metronome = 36, h.thirtyseconds = 8), h;
            case 89:
              if (h.type = "keySignature", f != 2) throw "Expected length for keySignature event is 2, got " + f;
              return h.key = r.readInt8(), h.scale = r.readUInt8(), h;
            case 127:
              return h.type = "sequencerSpecific", h.data = r.readBytes(f), h;
            default:
              return h.type = "unknownMeta", h.data = r.readBytes(f), h.metatypeByte = d, h;
          }
        } else if (u == 240) {
          h.type = "sysEx";
          var f = r.readVarInt();
          return h.data = r.readBytes(f), h;
        } else if (u == 247) {
          h.type = "endSysEx";
          var f = r.readVarInt();
          return h.data = r.readBytes(f), h;
        } else
          throw "Unrecognised MIDI event type byte: " + u;
      else {
        var m;
        if ((u & 128) === 0) {
          if (l === null)
            throw "Running status byte encountered before status byte";
          m = u, u = l, h.running = !0;
        } else
          m = r.readUInt8(), l = u;
        var y = u >> 4;
        switch (h.channel = u & 15, y) {
          case 8:
            return h.type = "noteOff", h.noteNumber = m, h.velocity = r.readUInt8(), h;
          case 9:
            var x = r.readUInt8();
            return h.type = x === 0 ? "noteOff" : "noteOn", h.noteNumber = m, h.velocity = x, x === 0 && (h.byte9 = !0), h;
          case 10:
            return h.type = "noteAftertouch", h.noteNumber = m, h.amount = r.readUInt8(), h;
          case 11:
            return h.type = "controller", h.controllerType = m, h.value = r.readUInt8(), h;
          case 12:
            return h.type = "programChange", h.programNumber = m, h;
          case 13:
            return h.type = "channelAftertouch", h.amount = m, h;
          case 14:
            return h.type = "pitchBend", h.value = m + (r.readUInt8() << 7) - 8192, h;
          default:
            throw "Unrecognised MIDI event type: " + y;
        }
      }
    }
  }
  function s(i) {
    this.buffer = i, this.bufferLen = this.buffer.length, this.pos = 0;
  }
  return s.prototype.eof = function() {
    return this.pos >= this.bufferLen;
  }, s.prototype.readUInt8 = function() {
    var i = this.buffer[this.pos];
    return this.pos += 1, i;
  }, s.prototype.readInt8 = function() {
    var i = this.readUInt8();
    return i & 128 ? i - 256 : i;
  }, s.prototype.readUInt16 = function() {
    var i = this.readUInt8(), r = this.readUInt8();
    return (i << 8) + r;
  }, s.prototype.readInt16 = function() {
    var i = this.readUInt16();
    return i & 32768 ? i - 65536 : i;
  }, s.prototype.readUInt24 = function() {
    var i = this.readUInt8(), r = this.readUInt8(), o = this.readUInt8();
    return (i << 16) + (r << 8) + o;
  }, s.prototype.readInt24 = function() {
    var i = this.readUInt24();
    return i & 8388608 ? i - 16777216 : i;
  }, s.prototype.readUInt32 = function() {
    var i = this.readUInt8(), r = this.readUInt8(), o = this.readUInt8(), a = this.readUInt8();
    return (i << 24) + (r << 16) + (o << 8) + a;
  }, s.prototype.readBytes = function(i) {
    var r = this.buffer.slice(this.pos, this.pos + i);
    return this.pos += i, r;
  }, s.prototype.readString = function(i) {
    var r = this.readBytes(i);
    return String.fromCharCode.apply(null, r);
  }, s.prototype.readVarInt = function() {
    for (var i = 0; !this.eof(); ) {
      var r = this.readUInt8();
      if (r & 128)
        i += r & 127, i <<= 7;
      else
        return i + r;
    }
    return i;
  }, s.prototype.readChunk = function() {
    var i = this.readString(4), r = this.readUInt32(), o = this.readBytes(r);
    return {
      id: i,
      length: r,
      data: o
    };
  }, Za = n, Za;
}
var Ka, bd;
function Db() {
  if (bd) return Ka;
  bd = 1;
  function n(r, o) {
    if (typeof r != "object")
      throw "Invalid MIDI data";
    o = o || {};
    var a = r.header || {}, l = r.tracks || [], c, h = l.length, u = new i();
    for (t(u, a, h), c = 0; c < h; c++)
      e(u, l[c], o);
    return u.buffer;
  }
  function t(r, o, a) {
    var l = o.format == null ? 1 : o.format, c = 128;
    o.timeDivision ? c = o.timeDivision : o.ticksPerFrame && o.framesPerSecond ? c = -(o.framesPerSecond & 255) << 8 | o.ticksPerFrame & 255 : o.ticksPerBeat && (c = o.ticksPerBeat & 32767);
    var h = new i();
    h.writeUInt16(l), h.writeUInt16(a), h.writeUInt16(c), r.writeChunk("MThd", h.buffer);
  }
  function e(r, o, a) {
    var l = new i(), c, h = o.length, u = null;
    for (c = 0; c < h; c++)
      (a.running === !1 || !a.running && !o[c].running) && (u = null), u = s(l, o[c], u, a.useByte9ForNoteOff);
    r.writeChunk("MTrk", l.buffer);
  }
  function s(r, o, a, l) {
    var c = o.type, h = o.deltaTime, u = o.text || "", d = o.data || [], f = null;
    switch (r.writeVarInt(h), c) {
      // meta events
      case "sequenceNumber":
        r.writeUInt8(255), r.writeUInt8(0), r.writeVarInt(2), r.writeUInt16(o.number);
        break;
      case "text":
        r.writeUInt8(255), r.writeUInt8(1), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "copyrightNotice":
        r.writeUInt8(255), r.writeUInt8(2), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "trackName":
        r.writeUInt8(255), r.writeUInt8(3), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "instrumentName":
        r.writeUInt8(255), r.writeUInt8(4), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "lyrics":
        r.writeUInt8(255), r.writeUInt8(5), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "marker":
        r.writeUInt8(255), r.writeUInt8(6), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "cuePoint":
        r.writeUInt8(255), r.writeUInt8(7), r.writeVarInt(u.length), r.writeString(u);
        break;
      case "channelPrefix":
        r.writeUInt8(255), r.writeUInt8(32), r.writeVarInt(1), r.writeUInt8(o.channel);
        break;
      case "portPrefix":
        r.writeUInt8(255), r.writeUInt8(33), r.writeVarInt(1), r.writeUInt8(o.port);
        break;
      case "endOfTrack":
        r.writeUInt8(255), r.writeUInt8(47), r.writeVarInt(0);
        break;
      case "setTempo":
        r.writeUInt8(255), r.writeUInt8(81), r.writeVarInt(3), r.writeUInt24(o.microsecondsPerBeat);
        break;
      case "smpteOffset":
        r.writeUInt8(255), r.writeUInt8(84), r.writeVarInt(5);
        var p = { 24: 0, 25: 32, 29: 64, 30: 96 }, g = o.hour & 31 | p[o.frameRate];
        r.writeUInt8(g), r.writeUInt8(o.min), r.writeUInt8(o.sec), r.writeUInt8(o.frame), r.writeUInt8(o.subFrame);
        break;
      case "timeSignature":
        r.writeUInt8(255), r.writeUInt8(88), r.writeVarInt(4), r.writeUInt8(o.numerator);
        var m = Math.floor(Math.log(o.denominator) / Math.LN2) & 255;
        r.writeUInt8(m), r.writeUInt8(o.metronome), r.writeUInt8(o.thirtyseconds || 8);
        break;
      case "keySignature":
        r.writeUInt8(255), r.writeUInt8(89), r.writeVarInt(2), r.writeInt8(o.key), r.writeUInt8(o.scale);
        break;
      case "sequencerSpecific":
        r.writeUInt8(255), r.writeUInt8(127), r.writeVarInt(d.length), r.writeBytes(d);
        break;
      case "unknownMeta":
        o.metatypeByte != null && (r.writeUInt8(255), r.writeUInt8(o.metatypeByte), r.writeVarInt(d.length), r.writeBytes(d));
        break;
      // system-exclusive
      case "sysEx":
        r.writeUInt8(240), r.writeVarInt(d.length), r.writeBytes(d);
        break;
      case "endSysEx":
        r.writeUInt8(247), r.writeVarInt(d.length), r.writeBytes(d);
        break;
      // channel events
      case "noteOff":
        var y = l !== !1 && o.byte9 || l && o.velocity == 0 ? 144 : 128;
        f = y | o.channel, f !== a && r.writeUInt8(f), r.writeUInt8(o.noteNumber), r.writeUInt8(o.velocity);
        break;
      case "noteOn":
        f = 144 | o.channel, f !== a && r.writeUInt8(f), r.writeUInt8(o.noteNumber), r.writeUInt8(o.velocity);
        break;
      case "noteAftertouch":
        f = 160 | o.channel, f !== a && r.writeUInt8(f), r.writeUInt8(o.noteNumber), r.writeUInt8(o.amount);
        break;
      case "controller":
        f = 176 | o.channel, f !== a && r.writeUInt8(f), r.writeUInt8(o.controllerType), r.writeUInt8(o.value);
        break;
      case "programChange":
        f = 192 | o.channel, f !== a && r.writeUInt8(f), r.writeUInt8(o.programNumber);
        break;
      case "channelAftertouch":
        f = 208 | o.channel, f !== a && r.writeUInt8(f), r.writeUInt8(o.amount);
        break;
      case "pitchBend":
        f = 224 | o.channel, f !== a && r.writeUInt8(f);
        var x = 8192 + o.value, v = x & 127, _ = x >> 7 & 127;
        r.writeUInt8(v), r.writeUInt8(_);
        break;
      default:
        throw "Unrecognized event type: " + c;
    }
    return f;
  }
  function i() {
    this.buffer = [];
  }
  return i.prototype.writeUInt8 = function(r) {
    this.buffer.push(r & 255);
  }, i.prototype.writeInt8 = i.prototype.writeUInt8, i.prototype.writeUInt16 = function(r) {
    var o = r >> 8 & 255, a = r & 255;
    this.writeUInt8(o), this.writeUInt8(a);
  }, i.prototype.writeInt16 = i.prototype.writeUInt16, i.prototype.writeUInt24 = function(r) {
    var o = r >> 16 & 255, a = r >> 8 & 255, l = r & 255;
    this.writeUInt8(o), this.writeUInt8(a), this.writeUInt8(l);
  }, i.prototype.writeInt24 = i.prototype.writeUInt24, i.prototype.writeUInt32 = function(r) {
    var o = r >> 24 & 255, a = r >> 16 & 255, l = r >> 8 & 255, c = r & 255;
    this.writeUInt8(o), this.writeUInt8(a), this.writeUInt8(l), this.writeUInt8(c);
  }, i.prototype.writeInt32 = i.prototype.writeUInt32, i.prototype.writeBytes = function(r) {
    this.buffer = this.buffer.concat(Array.prototype.slice.call(r, 0));
  }, i.prototype.writeString = function(r) {
    var o, a = r.length, l = [];
    for (o = 0; o < a; o++)
      l.push(r.codePointAt(o));
    this.writeBytes(l);
  }, i.prototype.writeVarInt = function(r) {
    if (r < 0) throw "Cannot write negative variable-length integer";
    if (r <= 127)
      this.writeUInt8(r);
    else {
      var o = r, a = [];
      for (a.push(o & 127), o >>= 7; o; ) {
        var l = o & 127 | 128;
        a.push(l), o >>= 7;
      }
      this.writeBytes(a.reverse());
    }
  }, i.prototype.writeChunk = function(r, o) {
    this.writeString(r), this.writeUInt32(o.length), this.writeBytes(o);
  }, Ka = n, Ka;
}
var wd;
function dm() {
  return wd || (wd = 1, to.parseMidi = Rb(), to.writeMidi = Db()), to;
}
var Qa = {}, ln = {}, Sd;
function fm() {
  if (Sd) return ln;
  Sd = 1, Object.defineProperty(ln, "__esModule", { value: !0 }), ln.insert = ln.search = void 0;
  function n(e, s, i) {
    i === void 0 && (i = "ticks");
    var r = 0, o = e.length, a = o;
    if (o > 0 && e[o - 1][i] <= s)
      return o - 1;
    for (; r < a; ) {
      var l = Math.floor(r + (a - r) / 2), c = e[l], h = e[l + 1];
      if (c[i] === s) {
        for (var u = l; u < e.length; u++) {
          var d = e[u];
          d[i] === s && (l = u);
        }
        return l;
      } else {
        if (c[i] < s && h[i] > s)
          return l;
        c[i] > s ? a = l : c[i] < s && (r = l + 1);
      }
    }
    return -1;
  }
  ln.search = n;
  function t(e, s, i) {
    if (i === void 0 && (i = "ticks"), e.length) {
      var r = n(e, s[i], i);
      e.splice(r + 1, 0, s);
    } else
      e.push(s);
  }
  return ln.insert = t, ln;
}
var Td;
function El() {
  return Td || (Td = 1, function(n) {
    Object.defineProperty(n, "__esModule", { value: !0 }), n.Header = n.keySignatureKeys = void 0;
    var t = fm(), e = /* @__PURE__ */ new WeakMap();
    n.keySignatureKeys = [
      "Cb",
      "Gb",
      "Db",
      "Ab",
      "Eb",
      "Bb",
      "F",
      "C",
      "G",
      "D",
      "A",
      "E",
      "B",
      "F#",
      "C#"
    ];
    var s = (
      /** @class */
      function() {
        function i(r) {
          var o = this;
          if (this.tempos = [], this.timeSignatures = [], this.keySignatures = [], this.meta = [], this.name = "", e.set(this, 480), r) {
            e.set(this, r.header.ticksPerBeat), r.tracks.forEach(function(l) {
              l.forEach(function(c) {
                c.meta && (c.type === "timeSignature" ? o.timeSignatures.push({
                  ticks: c.absoluteTime,
                  timeSignature: [
                    c.numerator,
                    c.denominator
                  ]
                }) : c.type === "setTempo" ? o.tempos.push({
                  bpm: 6e7 / c.microsecondsPerBeat,
                  ticks: c.absoluteTime
                }) : c.type === "keySignature" && o.keySignatures.push({
                  key: n.keySignatureKeys[c.key + 7],
                  scale: c.scale === 0 ? "major" : "minor",
                  ticks: c.absoluteTime
                }));
              });
            });
            var a = 0;
            r.tracks[0].forEach(function(l) {
              a += l.deltaTime, l.meta && (l.type === "trackName" ? o.name = l.text : (l.type === "text" || l.type === "cuePoint" || l.type === "marker" || l.type === "lyrics") && o.meta.push({
                text: l.text,
                ticks: a,
                type: l.type
              }));
            }), this.update();
          }
        }
        return i.prototype.update = function() {
          var r = this, o = 0, a = 0;
          this.tempos.sort(function(l, c) {
            return l.ticks - c.ticks;
          }), this.tempos.forEach(function(l, c) {
            var h = c > 0 ? r.tempos[c - 1].bpm : r.tempos[0].bpm, u = l.ticks / r.ppq - a, d = 60 / h * u;
            l.time = d + o, o = l.time, a += u;
          }), this.timeSignatures.sort(function(l, c) {
            return l.ticks - c.ticks;
          }), this.timeSignatures.forEach(function(l, c) {
            var h = c > 0 ? r.timeSignatures[c - 1] : r.timeSignatures[0], u = (l.ticks - h.ticks) / r.ppq, d = u / h.timeSignature[0] / (h.timeSignature[1] / 4);
            h.measures = h.measures || 0, l.measures = d + h.measures;
          });
        }, i.prototype.ticksToSeconds = function(r) {
          var o = (0, t.search)(this.tempos, r);
          if (o !== -1) {
            var a = this.tempos[o], l = a.time, c = (r - a.ticks) / this.ppq;
            return l + 60 / a.bpm * c;
          } else {
            var h = r / this.ppq;
            return 60 / 120 * h;
          }
        }, i.prototype.ticksToMeasures = function(r) {
          var o = (0, t.search)(this.timeSignatures, r);
          if (o !== -1) {
            var a = this.timeSignatures[o], l = (r - a.ticks) / this.ppq;
            return a.measures + l / (a.timeSignature[0] / a.timeSignature[1]) / 4;
          } else
            return r / this.ppq / 4;
        }, Object.defineProperty(i.prototype, "ppq", {
          /**
           * The number of ticks per quarter note.
           */
          get: function() {
            return e.get(this);
          },
          enumerable: !1,
          configurable: !0
        }), i.prototype.secondsToTicks = function(r) {
          var o = (0, t.search)(this.tempos, r, "time");
          if (o !== -1) {
            var a = this.tempos[o], l = a.time, c = r - l, h = c / (60 / a.bpm);
            return Math.round(a.ticks + h * this.ppq);
          } else {
            var u = r / 0.5;
            return Math.round(u * this.ppq);
          }
        }, i.prototype.toJSON = function() {
          return {
            keySignatures: this.keySignatures,
            meta: this.meta,
            name: this.name,
            ppq: this.ppq,
            tempos: this.tempos.map(function(r) {
              return {
                bpm: r.bpm,
                ticks: r.ticks
              };
            }),
            timeSignatures: this.timeSignatures
          };
        }, i.prototype.fromJSON = function(r) {
          this.name = r.name, this.tempos = r.tempos.map(function(o) {
            return Object.assign({}, o);
          }), this.timeSignatures = r.timeSignatures.map(function(o) {
            return Object.assign({}, o);
          }), this.keySignatures = r.keySignatures.map(function(o) {
            return Object.assign({}, o);
          }), this.meta = r.meta.map(function(o) {
            return Object.assign({}, o);
          }), e.set(this, r.ppq), this.update();
        }, i.prototype.setTempo = function(r) {
          this.tempos = [
            {
              bpm: r,
              ticks: 0
            }
          ], this.update();
        }, i;
      }()
    );
    n.Header = s;
  }(Qa)), Qa;
}
var Fi = {}, Ja = {}, Md;
function pm() {
  return Md || (Md = 1, function(n) {
    Object.defineProperty(n, "__esModule", { value: !0 }), n.ControlChange = n.controlChangeIds = n.controlChangeNames = void 0, n.controlChangeNames = {
      1: "modulationWheel",
      2: "breath",
      4: "footController",
      5: "portamentoTime",
      7: "volume",
      8: "balance",
      10: "pan",
      64: "sustain",
      65: "portamentoTime",
      66: "sostenuto",
      67: "softPedal",
      68: "legatoFootswitch",
      84: "portamentoControl"
    }, n.controlChangeIds = Object.keys(n.controlChangeNames).reduce(function(i, r) {
      return i[n.controlChangeNames[r]] = r, i;
    }, {});
    var t = /* @__PURE__ */ new WeakMap(), e = /* @__PURE__ */ new WeakMap(), s = (
      /** @class */
      function() {
        function i(r, o) {
          t.set(this, o), e.set(this, r.controllerType), this.ticks = r.absoluteTime, this.value = r.value;
        }
        return Object.defineProperty(i.prototype, "number", {
          /**
           * The controller number
           */
          get: function() {
            return e.get(this);
          },
          enumerable: !1,
          configurable: !0
        }), Object.defineProperty(i.prototype, "name", {
          /**
           * return the common name of the control number if it exists
           */
          get: function() {
            return n.controlChangeNames[this.number] ? n.controlChangeNames[this.number] : null;
          },
          enumerable: !1,
          configurable: !0
        }), Object.defineProperty(i.prototype, "time", {
          /**
           * The time of the event in seconds
           */
          get: function() {
            var r = t.get(this);
            return r.ticksToSeconds(this.ticks);
          },
          set: function(r) {
            var o = t.get(this);
            this.ticks = o.secondsToTicks(r);
          },
          enumerable: !1,
          configurable: !0
        }), i.prototype.toJSON = function() {
          return {
            number: this.number,
            ticks: this.ticks,
            time: this.time,
            value: this.value
          };
        }, i;
      }()
    );
    n.ControlChange = s;
  }(Ja)), Ja;
}
var Ri = {}, kd;
function Ob() {
  if (kd) return Ri;
  kd = 1, Object.defineProperty(Ri, "__esModule", { value: !0 }), Ri.createControlChanges = void 0;
  var n = pm();
  function t() {
    return new Proxy({}, {
      // tslint:disable-next-line: typedef
      get: function(e, s) {
        if (e[s])
          return e[s];
        if (n.controlChangeIds.hasOwnProperty(s))
          return e[n.controlChangeIds[s]];
      },
      // tslint:disable-next-line: typedef
      set: function(e, s, i) {
        return n.controlChangeIds.hasOwnProperty(s) ? e[n.controlChangeIds[s]] = i : e[s] = i, !0;
      }
    });
  }
  return Ri.createControlChanges = t, Ri;
}
var Di = {}, Cd;
function Nb() {
  if (Cd) return Di;
  Cd = 1, Object.defineProperty(Di, "__esModule", { value: !0 }), Di.PitchBend = void 0;
  var n = /* @__PURE__ */ new WeakMap(), t = (
    /** @class */
    function() {
      function e(s, i) {
        n.set(this, i), this.ticks = s.absoluteTime, this.value = s.value;
      }
      return Object.defineProperty(e.prototype, "time", {
        /**
         * The time of the event in seconds
         */
        get: function() {
          var s = n.get(this);
          return s.ticksToSeconds(this.ticks);
        },
        set: function(s) {
          var i = n.get(this);
          this.ticks = i.secondsToTicks(s);
        },
        enumerable: !1,
        configurable: !0
      }), e.prototype.toJSON = function() {
        return {
          ticks: this.ticks,
          time: this.time,
          value: this.value
        };
      }, e;
    }()
  );
  return Di.PitchBend = t, Di;
}
var Oi = {}, bs = {}, Ad;
function Lb() {
  return Ad || (Ad = 1, Object.defineProperty(bs, "__esModule", { value: !0 }), bs.DrumKitByPatchID = bs.InstrumentFamilyByID = bs.instrumentByPatchID = void 0, bs.instrumentByPatchID = [
    "acoustic grand piano",
    "bright acoustic piano",
    "electric grand piano",
    "honky-tonk piano",
    "electric piano 1",
    "electric piano 2",
    "harpsichord",
    "clavi",
    "celesta",
    "glockenspiel",
    "music box",
    "vibraphone",
    "marimba",
    "xylophone",
    "tubular bells",
    "dulcimer",
    "drawbar organ",
    "percussive organ",
    "rock organ",
    "church organ",
    "reed organ",
    "accordion",
    "harmonica",
    "tango accordion",
    "acoustic guitar (nylon)",
    "acoustic guitar (steel)",
    "electric guitar (jazz)",
    "electric guitar (clean)",
    "electric guitar (muted)",
    "overdriven guitar",
    "distortion guitar",
    "guitar harmonics",
    "acoustic bass",
    "electric bass (finger)",
    "electric bass (pick)",
    "fretless bass",
    "slap bass 1",
    "slap bass 2",
    "synth bass 1",
    "synth bass 2",
    "violin",
    "viola",
    "cello",
    "contrabass",
    "tremolo strings",
    "pizzicato strings",
    "orchestral harp",
    "timpani",
    "string ensemble 1",
    "string ensemble 2",
    "synthstrings 1",
    "synthstrings 2",
    "choir aahs",
    "voice oohs",
    "synth voice",
    "orchestra hit",
    "trumpet",
    "trombone",
    "tuba",
    "muted trumpet",
    "french horn",
    "brass section",
    "synthbrass 1",
    "synthbrass 2",
    "soprano sax",
    "alto sax",
    "tenor sax",
    "baritone sax",
    "oboe",
    "english horn",
    "bassoon",
    "clarinet",
    "piccolo",
    "flute",
    "recorder",
    "pan flute",
    "blown bottle",
    "shakuhachi",
    "whistle",
    "ocarina",
    "lead 1 (square)",
    "lead 2 (sawtooth)",
    "lead 3 (calliope)",
    "lead 4 (chiff)",
    "lead 5 (charang)",
    "lead 6 (voice)",
    "lead 7 (fifths)",
    "lead 8 (bass + lead)",
    "pad 1 (new age)",
    "pad 2 (warm)",
    "pad 3 (polysynth)",
    "pad 4 (choir)",
    "pad 5 (bowed)",
    "pad 6 (metallic)",
    "pad 7 (halo)",
    "pad 8 (sweep)",
    "fx 1 (rain)",
    "fx 2 (soundtrack)",
    "fx 3 (crystal)",
    "fx 4 (atmosphere)",
    "fx 5 (brightness)",
    "fx 6 (goblins)",
    "fx 7 (echoes)",
    "fx 8 (sci-fi)",
    "sitar",
    "banjo",
    "shamisen",
    "koto",
    "kalimba",
    "bag pipe",
    "fiddle",
    "shanai",
    "tinkle bell",
    "agogo",
    "steel drums",
    "woodblock",
    "taiko drum",
    "melodic tom",
    "synth drum",
    "reverse cymbal",
    "guitar fret noise",
    "breath noise",
    "seashore",
    "bird tweet",
    "telephone ring",
    "helicopter",
    "applause",
    "gunshot"
  ], bs.InstrumentFamilyByID = [
    "piano",
    "chromatic percussion",
    "organ",
    "guitar",
    "bass",
    "strings",
    "ensemble",
    "brass",
    "reed",
    "pipe",
    "synth lead",
    "synth pad",
    "synth effects",
    "world",
    "percussive",
    "sound effects"
  ], bs.DrumKitByPatchID = {
    0: "standard kit",
    8: "room kit",
    16: "power kit",
    24: "electronic kit",
    25: "tr-808 kit",
    32: "jazz kit",
    40: "brush kit",
    48: "orchestra kit",
    56: "sound fx kit"
  }), bs;
}
var Ed;
function Vb() {
  if (Ed) return Oi;
  Ed = 1, Object.defineProperty(Oi, "__esModule", { value: !0 }), Oi.Instrument = void 0;
  var n = Lb(), t = /* @__PURE__ */ new WeakMap(), e = (
    /** @class */
    function() {
      function s(i, r) {
        if (this.number = 0, t.set(this, r), this.number = 0, i) {
          var o = i.find(function(a) {
            return a.type === "programChange";
          });
          o && (this.number = o.programNumber);
        }
      }
      return Object.defineProperty(s.prototype, "name", {
        /**
         * The common name of the instrument.
         */
        get: function() {
          return this.percussion ? n.DrumKitByPatchID[this.number] : n.instrumentByPatchID[this.number];
        },
        set: function(i) {
          var r = n.instrumentByPatchID.indexOf(i);
          r !== -1 && (this.number = r);
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(s.prototype, "family", {
        /**
         * The instrument family, e.g. "piano".
         */
        get: function() {
          return this.percussion ? "drums" : n.InstrumentFamilyByID[Math.floor(this.number / 8)];
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(s.prototype, "percussion", {
        /**
         * If the instrument is a percussion instrument.
         */
        get: function() {
          var i = t.get(this);
          return i.channel === 9;
        },
        enumerable: !1,
        configurable: !0
      }), s.prototype.toJSON = function() {
        return {
          family: this.family,
          number: this.number,
          name: this.name
        };
      }, s.prototype.fromJSON = function(i) {
        this.number = i.number;
      }, s;
    }()
  );
  return Oi.Instrument = e, Oi;
}
var Ni = {}, Pd;
function Bb() {
  if (Pd) return Ni;
  Pd = 1, Object.defineProperty(Ni, "__esModule", { value: !0 }), Ni.Note = void 0;
  function n(o) {
    var a = Math.floor(o / 12) - 1;
    return t(o) + a.toString();
  }
  function t(o) {
    var a = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"], l = o % 12;
    return a[l];
  }
  function e(o) {
    var a = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
    return a.indexOf(o);
  }
  var s = /* @__PURE__ */ function() {
    var o = /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, a = {
      // tslint:disable-next-line: object-literal-sort-keys
      cbb: -2,
      cb: -1,
      c: 0,
      "c#": 1,
      cx: 2,
      dbb: 0,
      db: 1,
      d: 2,
      "d#": 3,
      dx: 4,
      ebb: 2,
      eb: 3,
      e: 4,
      "e#": 5,
      ex: 6,
      fbb: 3,
      fb: 4,
      f: 5,
      "f#": 6,
      fx: 7,
      gbb: 5,
      gb: 6,
      g: 7,
      "g#": 8,
      gx: 9,
      abb: 7,
      ab: 8,
      a: 9,
      "a#": 10,
      ax: 11,
      bbb: 9,
      bb: 10,
      b: 11,
      "b#": 12,
      bx: 13
    };
    return function(l) {
      var c = o.exec(l), h = c[1], u = c[2], d = a[h.toLowerCase()];
      return d + (parseInt(u, 10) + 1) * 12;
    };
  }(), i = /* @__PURE__ */ new WeakMap(), r = (
    /** @class */
    function() {
      function o(a, l, c) {
        i.set(this, c), this.midi = a.midi, this.velocity = a.velocity, this.noteOffVelocity = l.velocity, this.ticks = a.ticks, this.durationTicks = l.ticks - a.ticks;
      }
      return Object.defineProperty(o.prototype, "name", {
        /**
         * The note name and octave in scientific pitch notation, e.g. "C4".
         */
        get: function() {
          return n(this.midi);
        },
        set: function(a) {
          this.midi = s(a);
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(o.prototype, "octave", {
        /**
         * The notes octave number.
         */
        get: function() {
          return Math.floor(this.midi / 12) - 1;
        },
        set: function(a) {
          var l = a - this.octave;
          this.midi += l * 12;
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(o.prototype, "pitch", {
        /**
         * The pitch class name. e.g. "A".
         */
        get: function() {
          return t(this.midi);
        },
        set: function(a) {
          this.midi = 12 * (this.octave + 1) + e(a);
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(o.prototype, "duration", {
        /**
         * The duration of the segment in seconds.
         */
        get: function() {
          var a = i.get(this);
          return a.ticksToSeconds(this.ticks + this.durationTicks) - a.ticksToSeconds(this.ticks);
        },
        set: function(a) {
          var l = i.get(this), c = l.secondsToTicks(this.time + a);
          this.durationTicks = c - this.ticks;
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(o.prototype, "time", {
        /**
         * The time of the event in seconds.
         */
        get: function() {
          var a = i.get(this);
          return a.ticksToSeconds(this.ticks);
        },
        set: function(a) {
          var l = i.get(this);
          this.ticks = l.secondsToTicks(a);
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(o.prototype, "bars", {
        /**
         * The number of measures (and partial measures) to this beat.
         * Takes into account time signature changes.
         * @readonly
         */
        get: function() {
          var a = i.get(this);
          return a.ticksToMeasures(this.ticks);
        },
        enumerable: !1,
        configurable: !0
      }), o.prototype.toJSON = function() {
        return {
          duration: this.duration,
          durationTicks: this.durationTicks,
          midi: this.midi,
          name: this.name,
          ticks: this.ticks,
          time: this.time,
          velocity: this.velocity
        };
      }, o;
    }()
  );
  return Ni.Note = r, Ni;
}
var Id;
function Fd() {
  if (Id) return Fi;
  Id = 1, Object.defineProperty(Fi, "__esModule", { value: !0 }), Fi.Track = void 0;
  var n = fm(), t = pm(), e = Ob(), s = Nb(), i = Vb(), r = Bb(), o = /* @__PURE__ */ new WeakMap(), a = (
    /** @class */
    function() {
      function l(c, h) {
        var u = this;
        if (this.name = "", this.notes = [], this.controlChanges = (0, e.createControlChanges)(), this.pitchBends = [], o.set(this, h), c) {
          var d = c.find(function(_) {
            return _.type === "trackName";
          });
          this.name = d ? d.text : "";
        }
        if (this.instrument = new i.Instrument(c, this), this.channel = 0, c) {
          for (var f = c.filter(function(_) {
            return _.type === "noteOn";
          }), p = c.filter(function(_) {
            return _.type === "noteOff";
          }), g = function() {
            var _ = f.shift();
            m.channel = _.channel;
            var b = p.findIndex(function(S) {
              return S.noteNumber === _.noteNumber && S.absoluteTime >= _.absoluteTime;
            });
            if (b !== -1) {
              var w = p.splice(b, 1)[0];
              m.addNote({
                durationTicks: w.absoluteTime - _.absoluteTime,
                midi: _.noteNumber,
                noteOffVelocity: w.velocity / 127,
                ticks: _.absoluteTime,
                velocity: _.velocity / 127
              });
            }
          }, m = this; f.length; )
            g();
          var y = c.filter(function(_) {
            return _.type === "controller";
          });
          y.forEach(function(_) {
            u.addCC({
              number: _.controllerType,
              ticks: _.absoluteTime,
              value: _.value / 127
            });
          });
          var x = c.filter(function(_) {
            return _.type === "pitchBend";
          });
          x.forEach(function(_) {
            u.addPitchBend({
              ticks: _.absoluteTime,
              // Scale the value between -2^13 to 2^13 to -2 to 2.
              value: _.value / Math.pow(2, 13)
            });
          });
          var v = c.find(function(_) {
            return _.type === "endOfTrack";
          });
          this.endOfTrackTicks = v !== void 0 ? v.absoluteTime : void 0;
        }
      }
      return l.prototype.addNote = function(c) {
        var h = o.get(this), u = new r.Note({
          midi: 0,
          ticks: 0,
          velocity: 1
        }, {
          ticks: 0,
          velocity: 0
        }, h);
        return Object.assign(u, c), (0, n.insert)(this.notes, u, "ticks"), this;
      }, l.prototype.addCC = function(c) {
        var h = o.get(this), u = new t.ControlChange({
          controllerType: c.number
        }, h);
        return delete c.number, Object.assign(u, c), Array.isArray(this.controlChanges[u.number]) || (this.controlChanges[u.number] = []), (0, n.insert)(this.controlChanges[u.number], u, "ticks"), this;
      }, l.prototype.addPitchBend = function(c) {
        var h = o.get(this), u = new s.PitchBend({}, h);
        return Object.assign(u, c), (0, n.insert)(this.pitchBends, u, "ticks"), this;
      }, Object.defineProperty(l.prototype, "duration", {
        /**
         * The end time of the last event in the track.
         */
        get: function() {
          if (!this.notes.length)
            return 0;
          for (var c = this.notes[this.notes.length - 1].time + this.notes[this.notes.length - 1].duration, h = 0; h < this.notes.length - 1; h++) {
            var u = this.notes[h].time + this.notes[h].duration;
            c < u && (c = u);
          }
          return c;
        },
        enumerable: !1,
        configurable: !0
      }), Object.defineProperty(l.prototype, "durationTicks", {
        /**
         * The end time of the last event in the track in ticks.
         */
        get: function() {
          if (!this.notes.length)
            return 0;
          for (var c = this.notes[this.notes.length - 1].ticks + this.notes[this.notes.length - 1].durationTicks, h = 0; h < this.notes.length - 1; h++) {
            var u = this.notes[h].ticks + this.notes[h].durationTicks;
            c < u && (c = u);
          }
          return c;
        },
        enumerable: !1,
        configurable: !0
      }), l.prototype.fromJSON = function(c) {
        var h = this;
        this.name = c.name, this.channel = c.channel, this.instrument = new i.Instrument(void 0, this), this.instrument.fromJSON(c.instrument), c.endOfTrackTicks !== void 0 && (this.endOfTrackTicks = c.endOfTrackTicks);
        for (var u in c.controlChanges)
          c.controlChanges[u] && c.controlChanges[u].forEach(function(d) {
            h.addCC({
              number: d.number,
              ticks: d.ticks,
              value: d.value
            });
          });
        c.notes.forEach(function(d) {
          h.addNote({
            durationTicks: d.durationTicks,
            midi: d.midi,
            ticks: d.ticks,
            velocity: d.velocity
          });
        });
      }, l.prototype.toJSON = function() {
        for (var c = {}, h = 0; h < 127; h++)
          this.controlChanges.hasOwnProperty(h) && (c[h] = this.controlChanges[h].map(function(d) {
            return d.toJSON();
          }));
        var u = {
          channel: this.channel,
          controlChanges: c,
          pitchBends: this.pitchBends.map(function(d) {
            return d.toJSON();
          }),
          instrument: this.instrument.toJSON(),
          name: this.name,
          notes: this.notes.map(function(d) {
            return d.toJSON();
          })
        };
        return this.endOfTrackTicks !== void 0 && (u.endOfTrackTicks = this.endOfTrackTicks), u;
      }, l;
    }()
  );
  return Fi.Track = a, Fi;
}
var cn = {};
function zb(n) {
  var t = [];
  return mm(n, t), t;
}
function mm(n, t) {
  for (var e = 0; e < n.length; e++) {
    var s = n[e];
    Array.isArray(s) ? mm(s, t) : t.push(s);
  }
}
const qb = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  flatten: zb
}, Symbol.toStringTag, { value: "Module" })), Ub = /* @__PURE__ */ jg(qb);
var Rd;
function Gb() {
  if (Rd) return cn;
  Rd = 1;
  var n = cn && cn.__spreadArray || function(y, x, v) {
    if (v || arguments.length === 2) for (var _ = 0, b = x.length, w; _ < b; _++)
      (w || !(_ in x)) && (w || (w = Array.prototype.slice.call(x, 0, _)), w[_] = x[_]);
    return y.concat(w || Array.prototype.slice.call(x));
  };
  Object.defineProperty(cn, "__esModule", { value: !0 }), cn.encode = void 0;
  var t = dm(), e = El(), s = Ub;
  function i(y, x) {
    return [
      {
        absoluteTime: y.ticks,
        channel: x,
        deltaTime: 0,
        noteNumber: y.midi,
        type: "noteOn",
        velocity: Math.floor(y.velocity * 127)
      },
      {
        absoluteTime: y.ticks + y.durationTicks,
        channel: x,
        deltaTime: 0,
        noteNumber: y.midi,
        type: "noteOff",
        velocity: Math.floor(y.noteOffVelocity * 127)
      }
    ];
  }
  function r(y) {
    return (0, s.flatten)(y.notes.map(function(x) {
      return i(x, y.channel);
    }));
  }
  function o(y, x) {
    return {
      absoluteTime: y.ticks,
      channel: x,
      controllerType: y.number,
      deltaTime: 0,
      type: "controller",
      value: Math.floor(y.value * 127)
    };
  }
  function a(y) {
    for (var x = [], v = 0; v < 127; v++)
      y.controlChanges.hasOwnProperty(v) && y.controlChanges[v].forEach(function(_) {
        x.push(o(_, y.channel));
      });
    return x;
  }
  function l(y, x) {
    return {
      absoluteTime: y.ticks,
      channel: x,
      deltaTime: 0,
      type: "pitchBend",
      value: y.value
    };
  }
  function c(y) {
    var x = [];
    return y.pitchBends.forEach(function(v) {
      x.push(l(v, y.channel));
    }), x;
  }
  function h(y) {
    return {
      absoluteTime: 0,
      channel: y.channel,
      deltaTime: 0,
      programNumber: y.instrument.number,
      type: "programChange"
    };
  }
  function u(y) {
    return {
      absoluteTime: 0,
      deltaTime: 0,
      meta: !0,
      text: y,
      type: "trackName"
    };
  }
  function d(y) {
    return {
      absoluteTime: y.ticks,
      deltaTime: 0,
      meta: !0,
      microsecondsPerBeat: Math.floor(6e7 / y.bpm),
      type: "setTempo"
    };
  }
  function f(y) {
    return {
      absoluteTime: y.ticks,
      deltaTime: 0,
      denominator: y.timeSignature[1],
      meta: !0,
      metronome: 24,
      numerator: y.timeSignature[0],
      thirtyseconds: 8,
      type: "timeSignature"
    };
  }
  function p(y) {
    var x = e.keySignatureKeys.indexOf(y.key);
    return {
      absoluteTime: y.ticks,
      deltaTime: 0,
      key: x + 7,
      meta: !0,
      scale: y.scale === "major" ? 0 : 1,
      type: "keySignature"
    };
  }
  function g(y) {
    return {
      absoluteTime: y.ticks,
      deltaTime: 0,
      meta: !0,
      text: y.text,
      type: y.type
    };
  }
  function m(y) {
    var x = {
      header: {
        format: 1,
        numTracks: y.tracks.length + 1,
        ticksPerBeat: y.header.ppq
      },
      tracks: n([
        n(n(n(n([
          // The name data.
          {
            absoluteTime: 0,
            deltaTime: 0,
            meta: !0,
            text: y.header.name,
            type: "trackName"
          }
        ], y.header.keySignatures.map(function(v) {
          return p(v);
        }), !0), y.header.meta.map(function(v) {
          return g(v);
        }), !0), y.header.tempos.map(function(v) {
          return d(v);
        }), !0), y.header.timeSignatures.map(function(v) {
          return f(v);
        }), !0)
      ], y.tracks.map(function(v) {
        return n(n(n([
          // Add the name
          u(v.name),
          // the instrument
          h(v)
        ], r(v), !0), a(v), !0), c(v), !0);
      }), !0)
    };
    return x.tracks = x.tracks.map(function(v) {
      v = v.sort(function(b, w) {
        return b.absoluteTime - w.absoluteTime;
      });
      var _ = 0;
      return v.forEach(function(b) {
        b.deltaTime = b.absoluteTime - _, _ = b.absoluteTime, delete b.absoluteTime;
      }), v.push({
        deltaTime: 0,
        meta: !0,
        type: "endOfTrack"
      }), v;
    }), new Uint8Array((0, t.writeMidi)(x));
  }
  return cn.encode = m, cn;
}
var Dd;
function Wb() {
  return Dd || (Dd = 1, function(n) {
    var t = an && an.__awaiter || function(u, d, f, p) {
      function g(m) {
        return m instanceof f ? m : new f(function(y) {
          y(m);
        });
      }
      return new (f || (f = Promise))(function(m, y) {
        function x(b) {
          try {
            _(p.next(b));
          } catch (w) {
            y(w);
          }
        }
        function v(b) {
          try {
            _(p.throw(b));
          } catch (w) {
            y(w);
          }
        }
        function _(b) {
          b.done ? m(b.value) : g(b.value).then(x, v);
        }
        _((p = p.apply(u, d || [])).next());
      });
    }, e = an && an.__generator || function(u, d) {
      var f = { label: 0, sent: function() {
        if (m[0] & 1) throw m[1];
        return m[1];
      }, trys: [], ops: [] }, p, g, m, y;
      return y = { next: x(0), throw: x(1), return: x(2) }, typeof Symbol == "function" && (y[Symbol.iterator] = function() {
        return this;
      }), y;
      function x(_) {
        return function(b) {
          return v([_, b]);
        };
      }
      function v(_) {
        if (p) throw new TypeError("Generator is already executing.");
        for (; f; ) try {
          if (p = 1, g && (m = _[0] & 2 ? g.return : _[0] ? g.throw || ((m = g.return) && m.call(g), 0) : g.next) && !(m = m.call(g, _[1])).done) return m;
          switch (g = 0, m && (_ = [_[0] & 2, m.value]), _[0]) {
            case 0:
            case 1:
              m = _;
              break;
            case 4:
              return f.label++, { value: _[1], done: !1 };
            case 5:
              f.label++, g = _[1], _ = [0];
              continue;
            case 7:
              _ = f.ops.pop(), f.trys.pop();
              continue;
            default:
              if (m = f.trys, !(m = m.length > 0 && m[m.length - 1]) && (_[0] === 6 || _[0] === 2)) {
                f = 0;
                continue;
              }
              if (_[0] === 3 && (!m || _[1] > m[0] && _[1] < m[3])) {
                f.label = _[1];
                break;
              }
              if (_[0] === 6 && f.label < m[1]) {
                f.label = m[1], m = _;
                break;
              }
              if (m && f.label < m[2]) {
                f.label = m[2], f.ops.push(_);
                break;
              }
              m[2] && f.ops.pop(), f.trys.pop();
              continue;
          }
          _ = d.call(u, f);
        } catch (b) {
          _ = [6, b], g = 0;
        } finally {
          p = m = 0;
        }
        if (_[0] & 5) throw _[1];
        return { value: _[0] ? _[1] : void 0, done: !0 };
      }
    };
    Object.defineProperty(n, "__esModule", { value: !0 }), n.Header = n.Track = n.Midi = void 0;
    var s = dm(), i = El(), r = Fd(), o = Gb(), a = (
      /** @class */
      function() {
        function u(d) {
          var f = this, p = null;
          if (d) {
            var g = d instanceof ArrayBuffer ? new Uint8Array(d) : d;
            p = (0, s.parseMidi)(g), p.tracks.forEach(function(m) {
              var y = 0;
              m.forEach(function(x) {
                y += x.deltaTime, x.absoluteTime = y;
              });
            }), p.tracks = h(p.tracks);
          }
          this.header = new i.Header(p), this.tracks = [], d && (this.tracks = p.tracks.map(function(m) {
            return new r.Track(m, f.header);
          }), p.header.format === 1 && this.tracks[0].duration === 0 && this.tracks.shift());
        }
        return u.fromUrl = function(d) {
          return t(this, void 0, void 0, function() {
            var f, p;
            return e(this, function(g) {
              switch (g.label) {
                case 0:
                  return [4, fetch(d)];
                case 1:
                  return f = g.sent(), f.ok ? [4, f.arrayBuffer()] : [3, 3];
                case 2:
                  return p = g.sent(), [2, new u(p)];
                case 3:
                  throw new Error("Could not load '".concat(d, "'"));
              }
            });
          });
        }, Object.defineProperty(u.prototype, "name", {
          /**
           * The name of the midi file, taken from the first track.
           */
          get: function() {
            return this.header.name;
          },
          set: function(d) {
            this.header.name = d;
          },
          enumerable: !1,
          configurable: !0
        }), Object.defineProperty(u.prototype, "duration", {
          /**
           * The total length of the file in seconds.
           */
          get: function() {
            var d = this.tracks.map(function(f) {
              return f.duration;
            });
            return Math.max.apply(Math, d);
          },
          enumerable: !1,
          configurable: !0
        }), Object.defineProperty(u.prototype, "durationTicks", {
          /**
           * The total length of the file in ticks.
           */
          get: function() {
            var d = this.tracks.map(function(f) {
              return f.durationTicks;
            });
            return Math.max.apply(Math, d);
          },
          enumerable: !1,
          configurable: !0
        }), u.prototype.addTrack = function() {
          var d = new r.Track(void 0, this.header);
          return this.tracks.push(d), d;
        }, u.prototype.toArray = function() {
          return (0, o.encode)(this);
        }, u.prototype.toJSON = function() {
          return {
            header: this.header.toJSON(),
            tracks: this.tracks.map(function(d) {
              return d.toJSON();
            })
          };
        }, u.prototype.fromJSON = function(d) {
          var f = this;
          this.header = new i.Header(), this.header.fromJSON(d.header), this.tracks = d.tracks.map(function(p) {
            var g = new r.Track(void 0, f.header);
            return g.fromJSON(p), g;
          });
        }, u.prototype.clone = function() {
          var d = new u();
          return d.fromJSON(this.toJSON()), d;
        }, u;
      }()
    );
    n.Midi = a;
    var l = Fd();
    Object.defineProperty(n, "Track", { enumerable: !0, get: function() {
      return l.Track;
    } });
    var c = El();
    Object.defineProperty(n, "Header", { enumerable: !0, get: function() {
      return c.Header;
    } });
    function h(u) {
      for (var d = [], f = 0; f < u.length; f++)
        for (var p = d.length, g = /* @__PURE__ */ new Map(), m = Array(16).fill(0), y = 0, x = u[f]; y < x.length; y++) {
          var v = x[y], _ = p, b = v.channel;
          if (b !== void 0) {
            v.type === "programChange" && (m[b] = v.programNumber);
            var w = m[b], S = "".concat(w, " ").concat(b);
            g.has(S) ? _ = g.get(S) : (_ = p + g.size, g.set(S, _));
          }
          d[_] || d.push([]), d[_].push(v);
        }
      return d;
    }
  }(an)), an;
}
var gm = Wb();
function $b(n) {
  if (n < 0 || n > 127)
    throw new Error(`MIDI note number must be between 0 and 127, got ${n}`);
  return Math.floor(n / 12) - 1;
}
function Hb(n) {
  if (n < 0 || n > 127)
    throw new Error(`MIDI note number must be between 0 and 127, got ${n}`);
  return cm[n % 12];
}
const Od = [
  // Piano (0-7)
  "acoustic_grand_piano",
  // 0
  "bright_acoustic_piano",
  // 1
  "electric_grand_piano",
  // 2
  "honkytonk_piano",
  // 3
  "electric_piano_1",
  // 4
  "electric_piano_2",
  // 5
  "harpsichord",
  // 6
  "clavinet",
  // 7
  // Chromatic Percussion (8-15)
  "celesta",
  // 8
  "glockenspiel",
  // 9
  "music_box",
  // 10
  "vibraphone",
  // 11
  "marimba",
  // 12
  "xylophone",
  // 13
  "tubular_bells",
  // 14
  "dulcimer",
  // 15
  // Organ (16-23)
  "drawbar_organ",
  // 16
  "percussive_organ",
  // 17
  "rock_organ",
  // 18
  "church_organ",
  // 19
  "reed_organ",
  // 20
  "accordion",
  // 21
  "harmonica",
  // 22
  "tango_accordion",
  // 23
  // Guitar (24-31)
  "acoustic_guitar_nylon",
  // 24
  "acoustic_guitar_steel",
  // 25
  "electric_guitar_jazz",
  // 26
  "electric_guitar_clean",
  // 27
  "electric_guitar_muted",
  // 28
  "overdriven_guitar",
  // 29
  "distortion_guitar",
  // 30
  "guitar_harmonics",
  // 31
  // Bass (32-39)
  "acoustic_bass",
  // 32
  "electric_bass_finger",
  // 33
  "electric_bass_pick",
  // 34
  "fretless_bass",
  // 35
  "slap_bass_1",
  // 36
  "slap_bass_2",
  // 37
  "synth_bass_1",
  // 38
  "synth_bass_2",
  // 39
  // Strings (40-47)
  "violin",
  // 40
  "viola",
  // 41
  "cello",
  // 42
  "contrabass",
  // 43
  "tremolo_strings",
  // 44
  "pizzicato_strings",
  // 45
  "orchestral_harp",
  // 46
  "timpani",
  // 47
  // Ensemble (48-55)
  "string_ensemble_1",
  // 48
  "string_ensemble_2",
  // 49
  "synth_strings_1",
  // 50
  "synth_strings_2",
  // 51
  "choir_aahs",
  // 52
  "voice_oohs",
  // 53
  "synth_choir",
  // 54
  "orchestra_hit",
  // 55
  // Brass (56-63)
  "trumpet",
  // 56
  "trombone",
  // 57
  "tuba",
  // 58
  "muted_trumpet",
  // 59
  "french_horn",
  // 60
  "brass_section",
  // 61
  "synth_brass_1",
  // 62
  "synth_brass_2",
  // 63
  // Reed (64-71)
  "soprano_sax",
  // 64
  "alto_sax",
  // 65
  "tenor_sax",
  // 66
  "baritone_sax",
  // 67
  "oboe",
  // 68
  "english_horn",
  // 69
  "bassoon",
  // 70
  "clarinet",
  // 71
  // Pipe (72-79)
  "piccolo",
  // 72
  "flute",
  // 73
  "recorder",
  // 74
  "pan_flute",
  // 75
  "blown_bottle",
  // 76
  "shakuhachi",
  // 77
  "whistle",
  // 78
  "ocarina",
  // 79
  // Synth Lead (80-87)
  "lead_1_square",
  // 80
  "lead_2_sawtooth",
  // 81
  "lead_3_calliope",
  // 82
  "lead_4_chiff",
  // 83
  "lead_5_charang",
  // 84
  "lead_6_voice",
  // 85
  "lead_7_fifths",
  // 86
  "lead_8_bass__lead",
  // 87
  // Synth Pad (88-95)
  "pad_1_new_age",
  // 88
  "pad_2_warm",
  // 89
  "pad_3_polysynth",
  // 90
  "pad_4_choir",
  // 91
  "pad_5_bowed",
  // 92
  "pad_6_metallic",
  // 93
  "pad_7_halo",
  // 94
  "pad_8_sweep",
  // 95
  // Synth Effects (96-103)
  "fx_1_rain",
  // 96
  "fx_2_soundtrack",
  // 97
  "fx_3_crystal",
  // 98
  "fx_4_atmosphere",
  // 99
  "fx_5_brightness",
  // 100
  "fx_6_goblins",
  // 101
  "fx_7_echoes",
  // 102
  "fx_8_scifi",
  // 103
  // Ethnic (104-111)
  "sitar",
  // 104
  "banjo",
  // 105
  "shamisen",
  // 106
  "koto",
  // 107
  "kalimba",
  // 108
  "bagpipe",
  // 109
  "fiddle",
  // 110
  "shanai",
  // 111
  // Percussive (112-119)
  "tinkle_bell",
  // 112
  "agogo",
  // 113
  "steel_drums",
  // 114
  "woodblock",
  // 115
  "taiko_drum",
  // 116
  "melodic_tom",
  // 117
  "synth_drum",
  // 118
  "reverse_cymbal",
  // 119
  // Sound Effects (120-127)
  "guitar_fret_noise",
  // 120
  "breath_noise",
  // 121
  "seashore",
  // 122
  "bird_tweet",
  // 123
  "telephone_ring",
  // 124
  "helicopter",
  // 125
  "applause",
  // 126
  "gunshot"
  // 127
], jb = "https://paulrosen.github.io/midi-js-soundfonts/FluidR3_GM/";
function ym(n) {
  return n < 0 || n > 127 ? Od[0] : Od[n];
}
function Xb(n) {
  return ym(n).split("_").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" ");
}
function Yb(n) {
  const t = ym(n);
  return `${jb}${t}-mp3/`;
}
const Zb = {
  C3: "C3.mp3",
  "D#3": "Eb3.mp3",
  // flat notation for paulrosen soundfonts
  "F#3": "Gb3.mp3",
  A3: "A3.mp3",
  C4: "C4.mp3",
  "D#4": "Eb4.mp3",
  "F#4": "Gb4.mp3",
  A4: "A4.mp3"
};
function xm(n, t) {
  return t === 9 || t === 10 ? "drums" : n >= 0 && n <= 7 ? "piano" : n >= 8 && n <= 15 ? "mallet" : n >= 16 && n <= 23 ? "organ" : n >= 24 && n <= 31 ? "guitar" : n >= 32 && n <= 39 ? "bass" : n >= 40 && n <= 51 ? "strings" : n >= 52 && n <= 54 ? "vocal" : n === 55 ? "strings" : n >= 56 && n <= 63 ? "brass" : n >= 64 && n <= 79 ? "winds" : n >= 80 && n <= 103 ? "synth" : n >= 104 && n <= 111 ? "others" : n >= 112 && n <= 119 ? "drums" : (n >= 120 && n <= 127, "others");
}
async function Kb(n) {
  const t = await fetch(n);
  if (!t.ok)
    throw new Error(
      `Failed to fetch MIDI file from URL: ${t.status} ${t.statusText}`
    );
  return t.arrayBuffer();
}
async function Qb(n) {
  return new Promise((t, e) => {
    const s = new FileReader();
    s.onload = () => {
      s.result instanceof ArrayBuffer ? t(s.result) : e(new Error("Failed to read file as ArrayBuffer"));
    }, s.onerror = () => e(new Error("Failed to read file")), s.readAsArrayBuffer(n);
  });
}
function Jb(n, t) {
  const e = n.name || "Piano", s = n.channel || 0;
  return { name: e, channel: s };
}
function t1(n) {
  let t = "Untitled";
  for (const i of n.tracks)
    if (i.name) {
      t = i.name;
      break;
    }
  const e = n.header.tempos.map((i) => ({
    time: i.time,
    ticks: i.ticks,
    bpm: Math.round(i.bpm)
  })), s = n.header.timeSignatures.map(
    (i) => ({
      time: i.time,
      ticks: i.ticks,
      numerator: i.numerator,
      denominator: i.denominator
    })
  );
  return {
    name: t,
    tempos: e,
    timeSignatures: s,
    PPQ: n.header.ppq
  };
}
function Nd(n, t) {
  const e = [];
  for (const s of Object.keys(n.controlChanges ?? {})) {
    const i = n.controlChanges[s];
    if (Array.isArray(i))
      for (const r of i)
        e.push({
          controller: r.number,
          value: r.value,
          // already normalized 0-1 in Tone.js
          time: r.time,
          ticks: r.ticks,
          name: r.name,
          fileId: n.name,
          trackId: t
        });
  }
  return e;
}
function e1(n, t) {
  return {
    midi: n.midi,
    time: n.time,
    ticks: n.ticks,
    name: cc(n.midi),
    pitch: Hb(n.midi),
    octave: $b(n.midi),
    velocity: n.velocity,
    duration: n.duration,
    trackId: t
  };
}
function _m(n, t, e = 64, s = 0) {
  if (n.length === 0) return [];
  const i = 1e-9, r = e / 127, o = [];
  n.forEach((m, y) => {
    o.push({
      time: m.time,
      type: "note_on",
      index: y,
      midi: m.midi,
      velocity: m.velocity
    }), o.push({
      time: m.time + m.duration,
      type: "note_off",
      index: y,
      midi: m.midi,
      velocity: m.velocity
    });
  });
  let a = !1;
  t.filter((m) => m.controller === 64).forEach((m) => {
    const y = (m.value ?? 0) >= r;
    y !== a && (o.push({
      time: m.time,
      type: y ? "sustain_on" : "sustain_off",
      index: -1
    }), a = y);
  }), o.sort((m, y) => {
    if (Math.abs(m.time - y.time) > i) return m.time - y.time;
    const x = {
      sustain_off: 0,
      note_off: 1,
      sustain_on: 2,
      note_on: 3
    };
    return x[m.type] - x[y.type];
  });
  let l = !1;
  const c = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = (m) => {
    for (const [y, x] of h.entries())
      for (const v of x) {
        const _ = n[v.index], b = Math.max(i, m - v.startTime);
        u.set(v.index, { ..._, duration: b });
      }
    h.clear();
  }, f = (m, y) => {
    const x = h.get(m);
    if (x && x.length > 0) {
      const v = x.shift(), _ = n[v.index], b = Math.max(i, y - v.startTime);
      u.set(v.index, { ..._, duration: b }), x.length === 0 && h.delete(m);
    }
  };
  for (const m of o)
    switch (m.type) {
      case "sustain_on":
        l = !0;
        break;
      case "sustain_off":
        l = !1, d(m.time);
        break;
      case "note_on":
        m.midi !== void 0 && (f(m.midi, m.time), c.set(m.index, {
          startTime: m.time,
          midi: m.midi,
          velocity: m.velocity || 0
        }));
        break;
      case "note_off":
        if (!c.has(m.index)) break;
        const y = c.get(m.index);
        if (c.delete(m.index), l && m.midi !== void 0) {
          const x = h.get(m.midi) ?? [];
          x.push({
            index: m.index,
            startTime: y.startTime,
            velocity: y.velocity
          }), h.set(m.midi, x);
        } else
          u.has(m.index) || u.set(m.index, n[m.index]);
        break;
    }
  const p = Math.max(...n.map((m) => m.time + m.duration));
  h.size > 0 && d(p);
  for (const [m] of c)
    u.has(m) || u.set(m, n[m]);
  const g = [];
  for (let m = 0; m < n.length; m++)
    g.push(u.get(m) ?? n[m]);
  return g.sort(
    (m, y) => Math.abs(m.time - y.time) > i ? m.time - y.time : m.midi - y.midi
  ), g;
}
async function ci(n, t = {}) {
  try {
    let e;
    typeof n == "string" ? e = await Kb(n) : e = await Qb(n);
    const s = new gm.Midi(e), i = t1(s), r = s.tracks.filter(
      (g) => g.notes && g.notes.length > 0
    );
    if (r.length === 0)
      throw new Error("No tracks with notes found in MIDI file");
    const o = r[0], a = Jb(o, 0), l = t.applyPedalElongate !== !1, c = t.pedalThreshold ?? 64, h = [], u = [];
    for (let g = 0; g < r.length; g++) {
      const m = r[g], y = m.channel ?? 0, x = m.instrument?.number ?? 0, v = y === 9 || y === 10, _ = xm(x, y);
      let b;
      v ? b = m.name ? `${m.name} (ch.${y})` : `Drums (ch.${y})` : m.name ? b = `${m.name} (${x})` : b = `${Xb(x)} (${x})`;
      const w = {
        id: g,
        name: b,
        channel: y,
        program: x,
        isDrum: v,
        instrumentFamily: _,
        noteCount: m.notes.length
      };
      u.push(w);
      let S = m.notes.map(
        (T) => e1(T, g)
      );
      if (l) {
        const T = Nd(m, g);
        T.some((k) => k.controller === 64) && (S = _m(
          S,
          T,
          c,
          y
        ));
      }
      h.push(...S);
    }
    let d = h.sort(
      (g, m) => g.time !== m.time ? g.time - m.time : g.midi - m.midi
    );
    const f = [];
    for (let g = 0; g < r.length; g++) {
      const m = r[g], y = Nd(m, g).map((x) => ({
        ...x,
        fileId: o.name
      }));
      f.push(...y);
    }
    const p = s.duration;
    return {
      header: i,
      duration: p,
      track: a,
      notes: d,
      controlChanges: f,
      // merged CC events from all note tracks
      tracks: u
      // detailed track info for multi-instrument support
    };
  } catch (e) {
    throw e instanceof Error ? new Error(`Failed to parse MIDI file: ${e.message}`) : new Error("Failed to parse MIDI file: Unknown error");
  }
}
const s1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  applySustainPedalElongation: _m,
  getInstrumentFamily: xm,
  parseMidi: ci
}, Symbol.toStringTag, { value: "Module" }));
class n1 {
  constructor() {
    this.listeners = /* @__PURE__ */ new Set(), this.baselineListeners = /* @__PURE__ */ new Set(), this.lastTempo = null, this.lastFileId = null, this.baselineTempo = null, this.baselineFileId = null;
  }
  /**
   * Emit a tempo event to all subscribers.
   * Always stores the latest value for late subscribers.
   *
   * @param tempo - The tempo in BPM extracted from MIDI header
   * @param fileId - The ID of the MIDI file
   */
  emit(t, e) {
    this.lastTempo = t, this.lastFileId = e, this.listeners.forEach((s) => {
      try {
        s(t, e);
      } catch (i) {
        console.error("[TempoEventBus] Error in listener callback:", i);
      }
    });
  }
  /**
   * Subscribe to tempo events.
   * If a tempo has already been emitted, the callback is invoked immediately
   * with the stored value (late subscriber pattern).
   *
   * @param cb - Callback function to invoke on tempo events
   * @returns Unsubscribe function to remove the listener
   */
  subscribe(t) {
    if (this.listeners.add(t), this.lastTempo !== null && this.lastFileId !== null)
      try {
        t(this.lastTempo, this.lastFileId);
      } catch (e) {
        console.error(
          "[TempoEventBus] Error in late subscriber callback:",
          e
        );
      }
    return () => {
      this.listeners.delete(t);
    };
  }
  /**
   * Get the last emitted tempo value.
   * @returns The last tempo or null if none emitted yet
   */
  getLastTempo() {
    return this.lastTempo;
  }
  /**
   * Emit a baseline reset event.
   * This is used when the "top file" (first file in the list) changes,
   * such as when a file is deleted or files are reordered.
   * Subscribers should update their originalTempo to this new baseline.
   *
   * @param tempo - The new baseline tempo in BPM
   * @param fileId - The ID of the new top file
   */
  emitBaselineReset(t, e) {
    this.baselineTempo = t, this.baselineFileId = e, this.lastTempo = t, this.lastFileId = e, this.baselineListeners.forEach((s) => {
      try {
        s(t, e);
      } catch (i) {
        console.error(
          "[TempoEventBus] Error in baseline listener callback:",
          i
        );
      }
    }), this.listeners.forEach((s) => {
      try {
        s(t, e);
      } catch (i) {
        console.error("[TempoEventBus] Error in listener callback:", i);
      }
    });
  }
  /**
   * Subscribe to baseline reset events.
   * These events are emitted when the top file changes and the baseline
   * tempo should be updated (e.g., for originalTempo in VisualizationEngine).
   *
   * @param cb - Callback function to invoke on baseline reset
   * @returns Unsubscribe function to remove the listener
   */
  subscribeBaseline(t) {
    if (this.baselineListeners.add(t), this.baselineTempo !== null && this.baselineFileId !== null)
      try {
        t(this.baselineTempo, this.baselineFileId);
      } catch (e) {
        console.error(
          "[TempoEventBus] Error in late baseline subscriber callback:",
          e
        );
      }
    return () => {
      this.baselineListeners.delete(t);
    };
  }
  /**
   * Get the baseline tempo value.
   * @returns The baseline tempo or null if none set
   */
  getBaselineTempo() {
    return this.baselineTempo;
  }
  /**
   * Reset the event bus state.
   * Useful for testing or when clearing all MIDI files.
   */
  reset() {
    this.lastTempo = null, this.lastFileId = null, this.baselineTempo = null, this.baselineFileId = null;
  }
}
const ho = new n1(), Ld = "waveRoll.paletteState";
class i1 {
  constructor() {
    this.colorIndex = 0, this.listeners = [];
    let t = null;
    if (typeof window < "u" && "localStorage" in window)
      try {
        t = JSON.parse(
          window.localStorage.getItem(Ld) || "null"
        );
      } catch {
      }
    this.state = {
      files: [],
      activePaletteId: t?.activePaletteId ?? "vibrant",
      customPalettes: t?.customPalettes ?? []
    };
  }
  /**
   * Set state change callback
   */
  setOnStateChange(t) {
    this.onStateChange = t, this.notifyStateChange();
  }
  /**
   * Subscribe to state changes. Returns an unsubscribe function.
   */
  subscribe(t) {
    return this.listeners.push(t), t(this.getState()), () => {
      this.listeners = this.listeners.filter((e) => e !== t);
    };
  }
  /**
   * Get current state
   */
  getState() {
    return { ...this.state };
  }
  /**
   * Get active palette
   */
  getActivePalette() {
    return [...Cs, ...this.state.customPalettes].find((e) => e.id === this.state.activePaletteId) || Cs[0];
  }
  /**
   * Get next color from active palette
   */
  getNextColor() {
    const e = this.getActivePalette().colors, s = e.length > 0 ? e[this.colorIndex % e.length] : 6710886;
    return this.colorIndex++, s;
  }
  /**
   * Reset color index to match current file count
   */
  resetColorIndex() {
    this.colorIndex = this.state.files.length;
  }
  /**
   * Add a MIDI file
   */
  addMidiFile(t, e, s, i) {
    const r = this.state.files.length === 0, o = Fb(
      t,
      e,
      this.getNextColor(),
      s,
      i || t
    ), a = this.state.files.length < 2;
    if (o.isPianoRollVisible = a, o.isVisible = a, e.tracks && e.tracks.length > 0) {
      o.trackVisibility = {}, o.trackMuted = {}, o.trackVolume = {}, o.trackLastNonZeroVolume = {}, o.trackSustainVisibility = {};
      for (const l of e.tracks)
        o.trackVisibility[l.id] = !0, o.trackMuted[l.id] = !1, o.trackVolume[l.id] = 1, o.trackLastNonZeroVolume[l.id] = 1, o.trackSustainVisibility[l.id] = !0;
    }
    this.state.files.push(o);
    try {
      const l = this.extractInitialBpm(e);
      if (r ? ho.emitBaselineReset(l, o.id) : ho.emit(l, o.id), r) {
        const c = window._waveRollViz;
        c?.setOriginalTempo && c?.setTempo && (c.setOriginalTempo(l), c.setTempo(l));
      }
    } catch {
    }
    return this.notifyStateChange(), o.id;
  }
  /**
   * Extract initial BPM from parsed MIDI data.
   * Uses tempo event at or closest to time=0.
   * Falls back to 120 BPM if no tempo events are present.
   */
  extractInitialBpm(t) {
    const e = t.header?.tempos || [], s = 1e-3, i = e.filter((o) => Math.abs(o.time || 0) <= s), r = (i.length > 0 ? i : e).sort(
      (o, a) => (o.time || 0) - (a.time || 0)
    )[0];
    return Math.max(20, Math.min(300, r?.bpm || 120));
  }
  /**
   * Remove a MIDI file
   */
  removeMidiFile(t) {
    const e = this.state.files.length > 0 && this.state.files[0].id === t;
    if (this.state.files = this.state.files.filter((s) => s.id !== t), this.resetColorIndex(), e && this.state.files.length > 0) {
      const s = this.state.files[0];
      if (s.parsedData) {
        const i = this.extractInitialBpm(s.parsedData);
        ho.emitBaselineReset(i, s.id);
      }
    }
    this.notifyStateChange();
  }
  /**
   * Toggle visibility of a MIDI file
   */
  toggleVisibility(t) {
    const e = this.state.files.find((s) => s.id === t);
    if (e) {
      const s = !e.isPianoRollVisible;
      e.isPianoRollVisible = s, e.isVisible = s, this.notifyStateChange();
    }
  }
  /**
   * Toggle mute state of a MIDI file (audio only)
   */
  toggleMute(t) {
    const e = this.state.files.find((s) => s.id === t);
    e && (e.isMuted = !e.isMuted, this.notifyStateChange());
  }
  /**
   * Set visibility of a specific track within a MIDI file.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   * @param visible - Whether the track should be visible
   */
  setTrackVisibility(t, e, s) {
    const i = this.state.files.find((r) => r.id === t);
    i && (i.trackVisibility || (i.trackVisibility = {}), i.trackVisibility[e] = s, this.notifyStateChange());
  }
  /**
   * Toggle visibility of a specific track within a MIDI file.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  toggleTrackVisibility(t, e) {
    const s = this.state.files.find((r) => r.id === t);
    if (!s) return;
    s.trackVisibility || (s.trackVisibility = {});
    const i = s.trackVisibility[e] ?? !0;
    s.trackVisibility[e] = !i, this.notifyStateChange();
  }
  /**
   * Check if a specific track is visible.
   * Returns true if trackVisibility is not set (default visible).
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  isTrackVisible(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    return s ? s.trackVisibility?.[e] ?? !0 : !1;
  }
  /**
   * Toggle sustain pedal visibility for a specific track within a MIDI file.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  toggleTrackSustainVisibility(t, e) {
    const s = this.state.files.find((r) => r.id === t);
    if (!s) return;
    s.trackSustainVisibility || (s.trackSustainVisibility = {});
    const i = s.trackSustainVisibility[e] ?? !0;
    s.trackSustainVisibility[e] = !i, this.notifyStateChange();
  }
  /**
   * Check if sustain pedal is visible for a specific track.
   * Returns true if trackSustainVisibility is not set (default visible).
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  isTrackSustainVisible(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    return s ? s.trackSustainVisibility?.[e] ?? !0 : !1;
  }
  /**
   * Toggle mute state of a specific track within a MIDI file.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  toggleTrackMute(t, e) {
    const s = this.state.files.find((r) => r.id === t);
    if (!s) return;
    s.trackMuted || (s.trackMuted = {});
    const i = s.trackMuted[e] ?? !1;
    s.trackMuted[e] = !i, this.notifyStateChange();
  }
  /**
   * Check if a specific track is muted.
   * Returns false if trackMuted is not set (default unmuted).
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  isTrackMuted(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    return s ? s.trackMuted?.[e] ?? !1 : !1;
  }
  /**
   * Set volume for a specific track within a MIDI file.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   * @param volume - Volume level (0-1)
   */
  setTrackVolume(t, e, s) {
    const i = this.state.files.find((o) => o.id === t);
    if (!i) return;
    i.trackVolume || (i.trackVolume = {}), i.trackLastNonZeroVolume || (i.trackLastNonZeroVolume = {});
    const r = Math.max(0, Math.min(1, s));
    i.trackVolume[e] = r, r > 0 && (i.trackLastNonZeroVolume[e] = r), this.notifyStateChange();
  }
  /**
   * Get volume for a specific track.
   * Returns 1.0 if trackVolume is not set (default full volume).
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  getTrackVolume(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    return s ? s.trackVolume?.[e] ?? 1 : 1;
  }
  /**
   * Get last non-zero volume for a specific track.
   * Used to restore volume when unmuting a track.
   * Returns 1.0 if trackLastNonZeroVolume is not set (default full volume).
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  getTrackLastNonZeroVolume(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    return s ? s.trackLastNonZeroVolume?.[e] ?? 1 : 1;
  }
  /**
   * Set auto instrument state for a specific track within a MIDI file.
   * When enabled, the track will use its instrumentFamily soundfont instead of default piano.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   * @param useAuto - Whether to use auto instrument matching
   */
  setTrackAutoInstrument(t, e, s) {
    const i = this.state.files.find((r) => r.id === t);
    i && (i.trackUseAutoInstrument || (i.trackUseAutoInstrument = {}), i.trackUseAutoInstrument[e] = s, this.notifyStateChange());
  }
  /**
   * Check if a specific track uses auto instrument matching.
   * Returns true if trackUseAutoInstrument is not set (default auto-instrument).
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  isTrackAutoInstrument(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    return s ? s.trackUseAutoInstrument?.[e] ?? !0 : !0;
  }
  /**
   * Get the instrument family for a specific track.
   * Looks up the instrumentFamily from the parsed MIDI track data.
   * Returns 'piano' as fallback if track info is not available.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  getTrackInstrumentFamily(t, e) {
    const s = this.state.files.find((r) => r.id === t);
    return s?.parsedData?.tracks ? s.parsedData.tracks.find((r) => r.id === e)?.instrumentFamily ?? "piano" : "piano";
  }
  /**
   * Get the MIDI Program Number for a specific track.
   * Returns 118 (synth_drum) for drum tracks (channel 9/10).
   * Returns 0 (acoustic_grand_piano) as fallback if track info is not available.
   * @param fileId - The ID of the MIDI file
   * @param trackId - The track ID (0-based index)
   */
  getTrackProgram(t, e) {
    const s = this.state.files.find((r) => r.id === t);
    if (!s?.parsedData?.tracks) return 0;
    const i = s.parsedData.tracks.find((r) => r.id === e);
    return i ? i.isDrum ? 118 : i.program ?? 0 : 0;
  }
  /**
   * Update name
   */
  updateName(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    s && (s.name = e, this.notifyStateChange());
  }
  /**
   * Update file color
   */
  updateColor(t, e) {
    const s = this.state.files.find((i) => i.id === t);
    s && (s.color = e, this.notifyStateChange());
  }
  /**
   * Reorder files within the state array.
   * @param sourceIndex - The current index of the file.
   * @param targetIndex - The desired index after the move.
   */
  reorderFiles(t, e) {
    const { files: s } = this.state;
    if (t === e || t < 0 || e < 0 || t >= s.length || e >= s.length)
      return;
    const [i] = s.splice(t, 1);
    s.splice(e, 0, i), this.notifyStateChange();
  }
  /**
   * Set active palette
   */
  setActivePalette(t) {
    if (this.state.activePaletteId === t) return;
    this.state.activePaletteId = t, this.colorIndex = 0;
    const e = this.getActivePalette();
    Ya(this.state.files, e), this.resetColorIndex(), this.notifyStateChange();
  }
  /**
   * Add custom palette
   */
  addCustomPalette(t) {
    this.state.customPalettes.push(t), this.notifyStateChange();
  }
  /**
   * Update an existing custom palette. Only applicable to user-defined palettes.
   * If the palette is currently active, note that colors of existing files will be reassigned.
   * @param id     Palette identifier
   * @param patch  Partial properties to update (name and/or colors)
   */
  updateCustomPalette(t, e) {
    const s = this.state.customPalettes.findIndex((i) => i.id === t);
    s !== -1 && (this.state.customPalettes[s] = {
      ...this.state.customPalettes[s],
      ...e,
      id: t
      // Ensure id stays unchanged
    }, this.state.activePaletteId === t && (this.colorIndex = 0, Ya(this.state.files, this.state.customPalettes[s]), this.resetColorIndex()), this.notifyStateChange());
  }
  /**
   * Remove a user-defined custom palette.
   * If the palette is active, fall back to another palette and reassign colors.
   */
  removeCustomPalette(t) {
    const e = this.state.customPalettes.findIndex((s) => s.id === t);
    e !== -1 && (this.state.customPalettes.splice(e, 1), this.state.activePaletteId === t && (this.state.activePaletteId = this.state.customPalettes[0]?.id ?? Cs[0].id, this.colorIndex = 0, Ya(this.state.files, this.getActivePalette())), this.notifyStateChange());
  }
  /**
   * Get combined notes from visible files, respecting track visibility.
   * Notes from hidden tracks are excluded.
   */
  getVisibleNotes() {
    const t = [];
    return this.state.files.forEach((e) => {
      e.isPianoRollVisible && e.parsedData && e.parsedData.notes.forEach((s) => {
        const i = s.trackId;
        (i === void 0 || e.trackVisibility?.[i] !== !1) && t.push({
          note: s,
          color: e.color,
          fileId: e.id
        });
      });
    }), t.sort((e, s) => e.note.time - s.note.time), t;
  }
  /**
   * Get total duration across all visible files
   */
  getTotalDuration() {
    let t = 0;
    return this.state.files.forEach((e) => {
      e.isPianoRollVisible && e.parsedData && (t = Math.max(t, e.parsedData.duration));
    }), t;
  }
  /**
   * Clear all files
   */
  clearAll() {
    this.state.files = [], this.resetColorIndex(), this.notifyStateChange();
  }
  /**
   * Notify state change
   */
  notifyStateChange() {
    if (this.onStateChange && this.onStateChange(this.getState()), this.listeners.forEach((t) => t(this.getState())), typeof window < "u" && "localStorage" in window)
      try {
        const t = {
          activePaletteId: this.state.activePaletteId,
          customPalettes: this.state.customPalettes
        };
        window.localStorage.setItem(
          Ld,
          JSON.stringify(t)
        );
      } catch {
      }
  }
  /**
   * Toggle sustain overlay visibility of a MIDI file (visualisation only)
   */
  toggleSustainVisibility(t) {
    const e = this.state.files.find((s) => s.id === t);
    e && (e.isSustainVisible = !(e.isSustainVisible ?? !0), this.notifyStateChange());
  }
  /**
   * Reparse all MIDI files with new settings (e.g., pedal elongate)
   */
  async reparseAllFiles(t = {}, e) {
    const s = this.state.files.length;
    let i = 0;
    for (const r of this.state.files)
      if (r.originalInput && r.parsedData)
        try {
          const o = await ci(r.originalInput, t);
          r.parsedData = o, i++, e && e(i, s);
        } catch (o) {
          console.error(`Failed to reparse ${r.fileName}:`, o), r.error = `Failed to reparse: ${o}`;
        }
    this.notifyStateChange();
  }
}
class Co {
  static setupLayout(t, e, s) {
    t.innerHTML = "", e.mainContainer.style.cssText = `
      position: relative;
      display: flex;
      flex-direction: column;
      height: 100%;
      min-height: 600px;
      overflow: visible;
    `, e.playerContainer.style.cssText = `
      flex: 1;
      min-width: 0;
      display: flex;
      flex-direction: column;
      padding: 16px;
    `, e.sidebarContainer.style.display = "none", e.mainContainer.appendChild(e.playerContainer), t.appendChild(e.mainContainer);
    const i = () => {
      const r = s.pianoRoll;
      if (r?.resize) {
        const o = e.playerContainer.clientWidth;
        r.resize(o);
      }
    };
    window.addEventListener("resize", i), i();
  }
  /* -------------------------------- sidebar -------------------------------- */
  // Deprecated - sidebar no longer used
  static setupSidebar(t, e) {
  }
  /**
   * Refresh file list when midi-manager state changes.
   */
  // Deprecated - sidebar no longer used
  static updateSidebar(t, e) {
  }
}
const mt = 'width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;"', lt = {
  play: `<svg ${mt}>
    <polygon points="5 3 19 12 5 21 5 3" />
  </svg>`,
  pause: `<svg ${mt}>
    <line x1="8" y1="4" x2="8" y2="20" />
    <line x1="16" y1="4" x2="16" y2="20" />
  </svg>`,
  // Restart: Skip Back / Rewind style
  restart: `<svg ${mt}>
    <polygon points="11 19 2 12 11 5 11 19" />
    <polygon points="22 19 13 12 22 5 22 19" />
  </svg>`,
  // Repeat: Cycle arrows
  repeat: `<svg ${mt}>
    <path d="M17 1l4 4-4 4" />
    <path d="M3 11V9a4 4 0 0 1 4-4h14" />
    <path d="M7 23l-4-4 4-4" />
    <path d="M21 13v2a4 4 0 0 1-4 4H3" />
  </svg>`,
  // Volume: Speaker with waves
  volume: `<svg ${mt}>
    <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
    <path d="M15.54 8.46a5 5 0 0 1 0 7.07" />
    <path d="M19.07 4.93a10 10 0 0 1 0 14.14" />
  </svg>`,
  // Mute: Speaker with X
  mute: `<svg ${mt}>
    <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
    <line x1="23" y1="9" x2="17" y2="15" />
    <line x1="17" y1="9" x2="23" y2="15" />
  </svg>`,
  // Tempo: Gauge / Speedometer style
  tempo: `<svg ${mt}>
    <path d="M12 20V10" />
    <path d="M18 20V6" />
    <path d="M6 20V16" />
  </svg>`,
  skip_forward: `<svg ${mt}>
    <polygon points="5 4 15 12 5 20 5 4" />
    <line x1="19" y1="5" x2="19" y2="19" />
  </svg>`,
  skip_backward: `<svg ${mt}>
    <polygon points="19 20 9 12 19 4 19 20" />
    <line x1="5" y1="19" x2="5" y2="5" />
  </svg>`,
  // Shuffle: Crossed arrows
  shuffle: `<svg ${mt}>
    <polyline points="16 3 21 3 21 8" />
    <line x1="4" y1="20" x2="21" y2="3" />
    <polyline points="21 16 21 21 16 21" />
    <line x1="15" y1="15" x2="21" y2="21" />
    <line x1="4" y1="4" x2="9" y2="9" />
  </svg>`,
  // List: Menu list
  list: `<svg ${mt}>
    <line x1="8" y1="6" x2="21" y2="6" />
    <line x1="8" y1="12" x2="21" y2="12" />
    <line x1="8" y1="18" x2="21" y2="18" />
    <line x1="3" y1="6" x2="3.01" y2="6" />
    <line x1="3" y1="12" x2="3.01" y2="12" />
    <line x1="3" y1="18" x2="3.01" y2="18" />
  </svg>`,
  // Menu: Hamburger
  menu: `<svg ${mt}>
    <line x1="3" y1="12" x2="21" y2="12" />
    <line x1="3" y1="6" x2="21" y2="6" />
    <line x1="3" y1="18" x2="21" y2="18" />
  </svg>`,
  // Midi: DIN connector style
  midi: `<svg ${mt}>
    <circle cx="12" cy="12" r="10" />
    <circle cx="12" cy="12" r="2" />
    <path d="M7 7h.01" />
    <path d="M17 7h.01" />
    <path d="M7 17h.01" />
    <path d="M17 17h.01" />
  </svg>`,
  zoom_reset: `<svg ${mt}>
    <circle cx="11" cy="11" r="8" />
    <line x1="21" y1="21" x2="16.65" y2="16.65" />
    <path d="M8 11h6" />
  </svg>`,
  settings: `<svg ${mt}>
    <circle cx="12" cy="12" r="3" />
    <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" />
  </svg>`,
  // AB Loop start: play-sized triangle with "AB" label
  loop_start: `<svg ${mt}>
    <text x="24" y="8" text-anchor="end" font-size="11" font-weight="bold" font-family="Arial" stroke="none" fill="currentColor">AB</text>
    <polygon points="4 4 18 13 4 22" />
  </svg>`,
  eye_open: `<svg ${mt}>
    <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
    <circle cx="12" cy="12" r="3" />
  </svg>`,
  eye_closed: `<svg ${mt}>
    <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" />
    <line x1="1" y1="1" x2="23" y2="23" />
  </svg>`,
  // Pin: Push pin
  pin: `<svg ${mt}>
    <line x1="12" y1="17" x2="12" y2="22" />
    <path d="M5 17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1v4.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24Z" />
  </svg>`,
  // Edit: Pencil
  edit: `<svg ${mt}>
    <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
    <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
  </svg>`,
  // Duplicate: Copy
  duplicate: `<svg ${mt}>
    <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
    <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
  </svg>`,
  // Trash: Trash can
  trash: `<svg ${mt}>
    <polyline points="3 6 5 6 21 6" />
    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
  </svg>`,
  // Palette: Color palette
  palette: `<svg ${mt}>
    <circle cx="13.5" cy="6.5" r=".5" fill="currentColor" />
    <circle cx="17.5" cy="10.5" r=".5" fill="currentColor" />
    <circle cx="8.5" cy="7.5" r=".5" fill="currentColor" />
    <circle cx="6.5" cy="12.5" r=".5" fill="currentColor" />
    <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" />
  </svg>`,
  sustain: `<svg ${mt}>
    <text x="12" y="12" text-anchor="middle" dominant-baseline="central" font-size="18" font-weight="bold" font-family="Arial" stroke="none" fill="currentColor">S</text>
  </svg>`,
  est: `<svg ${mt}>
    <text x="12" y="16" text-anchor="middle" font-size="14" font-weight="bold" font-family="Arial" stroke="none" fill="currentColor">E</text>
  </svg>`,
  // File: Document / File
  file: `<svg ${mt}>
    <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" />
    <polyline points="13 2 13 9 20 9" />
  </svg>`,
  // Results: Bar Chart
  results: `<svg ${mt}>
    <line x1="18" y1="20" x2="18" y2="10" />
    <line x1="12" y1="20" x2="12" y2="4" />
    <line x1="6" y1="20" x2="6" y2="14" />
  </svg>`
}, Vd = {
  // Piano: keyboard piano keys play (from SVG Repo)
  piano: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" style="pointer-events: none;">
    <rect x="3" y="4" width="26" height="24"/>
    <line x1="9" y1="17" x2="9" y2="28"/>
    <rect x="6" y="4" width="4" height="13"/>
    <line x1="16" y1="17" x2="16" y2="28"/>
    <rect x="14" y="4" width="4" height="13"/>
    <line x1="23" y1="17" x2="23" y2="28"/>
    <rect x="22" y="4" width="4" height="13"/>
  </svg>`,
  // Strings: violin/cello with bow (from SVG Repo)
  strings: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <polygon points="8.1,25.4 6.6,23.9 8.9,20.1 11.9,23.1"/>
    <polygon points="24.5,6 26,7.5 17.1,17.9 14.1,14.9"/>
    <polygon points="26,7.5 24.5,6 26,3 29,6"/>
    <line x1="23.1" y1="4.5" x2="24.5" y2="6"/>
    <line x1="26" y1="7.5" x2="27.5" y2="8.9"/>
    <line x1="20.1" y1="6" x2="21.6" y2="7.5"/>
    <line x1="24.5" y1="10.4" x2="26" y2="11.9"/>
    <path d="M18.8,10.9c-2.4-1.4-5.6-1.1-7.6,1L11,12.1c0.6,1.2,0.4,2.6-0.6,3.6c-1.2,1.2-3.2,1.2-4.4,0.1c-0.3,0.2-0.6,0.4-0.8,0.7c-2.9,2.9-2.9,7.6,0,10.4c2.9,2.9,7.6,2.9,10.4,0c0.3-0.3,0.5-0.5,0.7-0.8c-1.2-1.2-1.2-3.2,0.1-4.4c1-1,2.4-1.2,3.6-0.6l0.1-0.1c2.1-2.1,2.4-5.2,1-7.6"/>
  </svg>`,
  // Drums: snare drum with stick (from SVG Repo)
  drums: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M4,17v8c0,2.2,5.4,4,12,4s12-1.8,12-4v-8"/>
    <line x1="13" y1="17" x2="29" y2="3"/>
    <ellipse cx="16" cy="17" rx="12" ry="4"/>
  </svg>`,
  // Guitar: classic guitar (from SVG Repo)
  guitar: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M20.4,24.8l1.5-3.9c0.4-1.1,1.3-2.1,2.4-2.7l0,0c3.2-1.7,3.7-6.1,1-8.8l-2.3-2.3c-2.7-2.7-7.1-2.2-8.8,1l0,0c-0.6,1.1-1.5,1.9-2.7,2.4l-3.9,1.5c-4.6,1.8-5.6,7.8-2,11.4L9,26.8C12.7,30.4,18.6,29.4,20.4,24.8z"/>
    <circle cx="18.2" cy="14.3" r="2.9"/>
    <line x1="9.7" y1="19.1" x2="13.4" y2="22.8"/>
    <polyline points="26.3,3.5 22.9,6.9 25.6,9.6 29,6.2"/>
  </svg>`,
  // Bass: electric bass guitar (from SVG Repo)
  bass: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M12.8,21.8L12.8,21.8c-1.7-1.4-2.3-3.8-1.5-5.9l4.1-10.7C16.3,3,19,2.3,20.8,3.8l0,0c1.4,1.2,1.6,3.3,0.5,4.7l-1.1,1.5l1.4,6.2c0.4,1.9-0.2,3.9-1.7,5.1l-0.4,0.4C17.5,23.4,14.7,23.4,12.8,21.8z"/>
    <line x1="14" y1="29" x2="14" y2="22.5"/>
    <line x1="19" y1="22.1" x2="19" y2="29"/>
    <line x1="9.6" y1="14.9" x2="11.4" y2="15.7"/>
    <line x1="10.6" y1="11.9" x2="12.5" y2="12.8"/>
    <line x1="11.6" y1="8.9" x2="13.6" y2="9.8"/>
    <line x1="12.6" y1="5.9" x2="14.8" y2="6.9"/>
  </svg>`,
  // Synth: keyboard piano synth midi vst (from SVG Repo)
  synth: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" style="pointer-events: none;">
    <rect x="3" y="13" width="26" height="16"/>
    <line x1="9" y1="21" x2="9" y2="29"/>
    <rect x="6" y="13" width="4" height="8"/>
    <line x1="16" y1="21" x2="16" y2="29"/>
    <rect x="14" y="13" width="4" height="8"/>
    <line x1="23" y1="21" x2="23" y2="29"/>
    <rect x="22" y="13" width="4" height="8"/>
    <rect x="3" y="3" width="26" height="10"/>
    <rect x="7" y="6" width="10" height="4"/>
    <circle cx="23" cy="8" r="2"/>
  </svg>`,
  // Winds: flute instrument (from SVG Repo)
  winds: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M26.5,10h-21C4.7,10,4,9.3,4,8.5v0C4,7.7,4.7,7,5.5,7h21C27.3,7,28,7.7,28,8.5v0C28,9.3,27.3,10,26.5,10z"/>
    <polyline points="10,10 10,29 6,29 6,10.1"/>
    <polyline points="6,7 6,3 10,3 10,7"/>
    <polyline points="10,7 10,3 14,3 14,7"/>
    <polyline points="14,10 14,26 10,26 10,10"/>
    <polyline points="14,7 14,3 18,3 18,7"/>
    <polyline points="18,10 18,23 14,23 14,10"/>
    <polyline points="18,7 18,3 22,3 22,7"/>
    <polyline points="22,10 22,20 18,20 18,10"/>
    <polyline points="22,7 22,3 26,3 26,7"/>
    <polyline points="26,10 26,17 22,17 22,10"/>
  </svg>`,
  // Brass: jazz trumpet band (from SVG Repo)
  brass: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M29,9L29,9c-1.9,3.1-5.2,5-8.8,5H7l0,0c-0.6-0.6-1.5-1-2.4-1h0C3.7,13,3,13.7,3,14.6v2.8C3,18.3,3.7,19,4.6,19h0c0.9,0,1.8-0.4,2.4-1l0,0h13.2c3.6,0,7,1.9,8.8,5l0,0V9z"/>
    <path d="M17.5,23h-6C10.1,23,9,21.9,9,20.5v0c0-1.4,1.1-2.5,2.5-2.5h6c1.4,0,2.5,1.1,2.5,2.5v0C20,21.9,18.9,23,17.5,23z"/>
    <line x1="29" y1="8" x2="29" y2="24"/>
    <line x1="11" y1="11" x2="11" y2="11"/>
    <line x1="14" y1="11" x2="14" y2="11"/>
    <line x1="17" y1="11" x2="17" y2="11"/>
  </svg>`,
  // Vocal: microphone with singing figure (from SVG Repo)
  vocal: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M7.6,12c2.1,2.1,4.7,1.3,6.7-0.7s2.8-4.7,0.7-6.7s-5.4-2.1-7.5,0S5.5,9.9,7.6,12z"/>
    <path d="M6.8,11c1.7,0.3,3.5-0.6,5-2.1c1.5-1.5,2.4-3.3,2.1-5"/>
    <path d="M16.3,7.3c4.8,5,9.3,11.3,10.1,14.3l-1.7,1.7c-3-0.7-9.3-5.3-14.3-10.1"/>
    <line x1="16.9" y1="14" x2="17.8" y2="14.9"/>
    <path d="M8.4,21.5L8.4,21.5c1.5-2,4.5-2.3,6.4-0.7l8.6,7.5c1.1,0.9,2.7,0.9,3.8-0.1l0,0c1.1-1.1,1.1-2.8,0-3.9l-1.8-1.8"/>
  </svg>`,
  // Organ: pipe organ with vertical pipes (stroke style)
  organ: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <rect x="4" y="22" width="24" height="7"/>
    <line x1="8" y1="22" x2="8" y2="8"/>
    <line x1="12" y1="22" x2="12" y2="5"/>
    <line x1="16" y1="22" x2="16" y2="3"/>
    <line x1="20" y1="22" x2="20" y2="5"/>
    <line x1="24" y1="22" x2="24" y2="8"/>
    <circle cx="8" cy="7" r="1.5"/>
    <circle cx="12" cy="4" r="1.5"/>
    <circle cx="16" cy="2" r="1.5"/>
    <circle cx="20" cy="4" r="1.5"/>
    <circle cx="24" cy="7" r="1.5"/>
  </svg>`,
  // Mallet: maracas percussion (from SVG Repo)
  mallet: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none;">
    <path d="M13.6,26l-3-12.2c1.9-1,3-3.5,2.5-6.1C12.5,4.6,10,2.5,7.4,3C4.8,3.5,3.2,6.4,3.8,9.5c0.5,2.6,2.4,4.5,4.5,4.8l1.8,12.5c0.1,1,1.1,1.7,2.1,1.5C13.2,28,13.8,27,13.6,26z"/>
    <path d="M3.8,9.5L3.8,9.5c3.2,0.6,6.6,0,9.4-1.8l0,0"/>
    <path d="M24.5,5C22,4.5,19.6,6.5,19,9.5c-0.5,2.5,0.6,4.9,2.4,5.8l-2.8,11.7c-0.3,0.9,0.4,1.9,1.3,2.1s1.9-0.5,2-1.5l1.7-11.9c2-0.2,3.8-2.1,4.3-4.5C28.5,8.2,27,5.4,24.5,5z"/>
    <path d="M27.9,11.2L27.9,11.2c-3.1,0.6-6.3,0-8.9-1.7l0,0"/>
  </svg>`,
  // Others: scores notes audio (from SVG Repo)
  others: `<svg width="24" height="24" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" style="pointer-events: none;">
    <ellipse cx="18" cy="24" rx="4" ry="3"/>
    <path d="M22,24V5l0.4,0.8C23.4,7.9,25,9.7,27,11l0,0c1.7,1.1,2.1,3.3,1,5l0,0"/>
    <line x1="3" y1="26" x2="10" y2="26"/>
    <line x1="3" y1="21" x2="10" y2="21"/>
    <line x1="3" y1="16" x2="17" y2="16"/>
    <line x1="3" y1="11" x2="17" y2="11"/>
    <line x1="3" y1="6" x2="17" y2="6"/>
  </svg>`
};
function uo(n) {
  return Vd[n] ?? Vd.others;
}
const Ao = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none; transition: transform 0.2s;">
  <path d="M6 9l6 6 6-6" />
</svg>`, Eo = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="pointer-events: none; transition: transform 0.2s;">
  <path d="M9 6l6 6-6 6" />
</svg>`, js = (n, t, e, s = {}) => {
  const { size: i = 32 } = s, r = document.createElement("button");
  return r.innerHTML = n, r.onclick = t, e && (r.title = e), r.style.cssText = `
    width: ${i}px;
    height: ${i}px;
    padding: 0;
    border: 1px solid var(--ui-border);
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  `, r.classList.add("wr-focusable"), r.addEventListener("mouseenter", () => {
    r.style.transform = "translateY(-1px)", r.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)";
  }), r.addEventListener("mouseleave", () => {
    r.style.transform = "translateY(0)", r.style.boxShadow = "none";
  }), r.addEventListener("mousedown", () => {
    r.style.transform = "translateY(0) scale(0.96)";
  }), r.addEventListener("mouseup", () => {
    r.style.transform = "translateY(-1px) scale(1)";
  }), r;
};
class Pl {
  constructor(t = {}) {
    this.isSliderVisible = !1, this.hideTimeout = null, this.suppressOnChange = !1, this.currentVolume = t.initialVolume ?? 1, this.lastNonZeroVolume = t.lastNonZeroVolume ?? this.currentVolume, this.onVolumeChange = t.onVolumeChange, this.container = document.createElement("div"), this.container.style.cssText = `
      position: relative;
      display: inline-flex;
      align-items: center;
    `, this.volumeBtn = document.createElement("button"), this.updateVolumeIcon(), this.volumeBtn.style.cssText = `
      background: none;
      border: none;
      padding: 4px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      width: ${t.size ?? 24}px;
      height: ${t.size ?? 24}px;
      transition: opacity 0.2s ease;
      color: ${this.currentVolume > 0 ? "var(--text-muted)" : "rgba(71,85,105,0.5)"};
    `, this.volumeBtn.setAttribute(
      "aria-label",
      `Volume: ${Math.round(this.currentVolume * 100)}%`
    ), this.volumeBtn.setAttribute("role", "button"), this.volumeBtn.setAttribute("tabindex", "0"), this.sliderContainer = document.createElement("div"), this.sliderContainer.style.cssText = `
      position: absolute;
      bottom: 100%;
      left: 50%;
      transform: translateX(-50%);
      margin-bottom: 4px;
      background: var(--surface);
      border: 1px solid var(--ui-border);
      border-radius: 8px;
      padding: 8px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      display: none;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 4px;
      z-index: 1000;
      width: 40px;
      height: 140px;
    `, this.volumeDisplay = document.createElement("span"), this.volumeDisplay.textContent = `${Math.round(this.currentVolume * 100)}%`, this.volumeDisplay.style.cssText = `
      font-size: 10px;
      color: var(--text-muted);
      font-weight: 600;
      user-select: none;
      margin-bottom: 4px;
    `;
    const e = document.createElement("div");
    e.style.cssText = `
      width: 24px;
      height: 80px;
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
    `, this.slider = document.createElement("input"), this.slider.type = "range", this.slider.min = "0", this.slider.max = "100", this.slider.step = "1", this.slider.value = String(this.currentVolume * 100), this.slider.setAttribute("aria-label", "Volume slider"), this.slider.setAttribute("aria-orientation", "vertical"), this.slider.style.cssText = `
      width: 80px;
      height: 4px;
      transform: rotate(-90deg);
      transform-origin: center;
      position: absolute;
      cursor: pointer;
      -webkit-appearance: none;
      appearance: none;
      background: var(--ui-border);
      outline: none;
      border-radius: 2px;
    `;
    const s = document.createElement("style"), i = `volume-slider-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    this.slider.className = i, s.textContent = `
      .${i}::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 12px;
        height: 12px;
        background: #0d6efd;
        cursor: pointer;
        border-radius: 50%;
        border: 2px solid white;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
      }
      .${i}::-moz-range-thumb {
        width: 12px;
        height: 12px;
        background: #0d6efd;
        cursor: pointer;
        border-radius: 50%;
        border: 2px solid white;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
      }
      .${i}::-webkit-slider-runnable-track {
        background: linear-gradient(to right, #0d6efd 0%, #0d6efd ${this.currentVolume * 100}%, #dee2e6 ${this.currentVolume * 100}%, #dee2e6 100%);
      }
    `, document.head.appendChild(s), e.appendChild(this.slider), this.sliderContainer.appendChild(this.volumeDisplay), this.sliderContainer.appendChild(e), this.container.__controlInstance = this, this.container.appendChild(this.volumeBtn), this.container.appendChild(this.sliderContainer), this.setupEventHandlers(), this.updateSliderTrack(), this.handleMasterMirrorBound = (r) => {
      try {
        const o = r.detail;
        if (!o || !o.mode) return;
        if (this.suppressOnChange = !0, o.mode !== "mirror-mute") {
          if (o.mode !== "mirror-restore") {
            if (o.mode === "mirror-set") {
              const a = typeof o.volume == "number" ? Math.max(0, Math.min(1, o.volume)) : void 0;
              typeof a == "number" && this.setVolume(a);
            }
          }
        }
      } finally {
        this.suppressOnChange = !1;
      }
    }, window.addEventListener("wr-master-mirror", this.handleMasterMirrorBound);
  }
  setupEventHandlers() {
    this.volumeBtn.addEventListener("click", (t) => {
      t.stopPropagation(), this.currentVolume > 0 ? (this.lastNonZeroVolume = this.currentVolume, this.setVolume(0)) : this.setVolume(this.lastNonZeroVolume);
    }), this.volumeBtn.addEventListener("mouseenter", () => this.showSlider()), this.volumeBtn.addEventListener("focus", () => this.showSlider()), this.sliderContainer.addEventListener(
      "mouseenter",
      () => this.clearHideTimeout()
    ), this.sliderContainer.addEventListener(
      "mouseleave",
      () => this.hideSliderDelayed()
    ), this.container.addEventListener(
      "mouseleave",
      () => this.hideSliderDelayed()
    ), this.slider.addEventListener("input", (t) => {
      const s = parseInt(t.target.value) / 100;
      this.setVolume(s);
    }), this.container.addEventListener("keydown", (t) => {
      t.key === "Escape" ? (this.hideSlider(), this.volumeBtn.focus()) : t.key === "ArrowUp" || t.key === "ArrowRight" ? (t.preventDefault(), this.setVolume(Math.min(1, this.currentVolume + 0.05))) : (t.key === "ArrowDown" || t.key === "ArrowLeft") && (t.preventDefault(), this.setVolume(Math.max(0, this.currentVolume - 0.05)));
    });
  }
  showSlider() {
    this.clearHideTimeout(), this.sliderContainer.style.display = "flex", this.isSliderVisible = !0;
  }
  hideSlider() {
    this.sliderContainer.style.display = "none", this.isSliderVisible = !1;
  }
  hideSliderDelayed() {
    this.clearHideTimeout(), this.hideTimeout = window.setTimeout(() => {
      this.hideSlider();
    }, 300);
  }
  clearHideTimeout() {
    this.hideTimeout !== null && (clearTimeout(this.hideTimeout), this.hideTimeout = null);
  }
  updateVolumeIcon() {
    this.currentVolume === 0 ? this.volumeBtn.innerHTML = lt.mute : this.volumeBtn.innerHTML = lt.volume;
  }
  updateSliderTrack() {
    const t = this.currentVolume * 100, e = `linear-gradient(to right, var(--accent) 0%, var(--accent) ${t}%, var(--ui-border) ${t}%, var(--ui-border) 100%)`;
    this.slider.style.background = e;
  }
  setVolume(t) {
    this.currentVolume = Math.max(0, Math.min(1, t)), this.currentVolume > 0 && (this.lastNonZeroVolume = this.currentVolume), this.updateVolumeIcon(), this.slider.value = String(this.currentVolume * 100), this.volumeDisplay.textContent = `${Math.round(this.currentVolume * 100)}%`, this.volumeBtn.setAttribute(
      "aria-label",
      `Volume: ${Math.round(this.currentVolume * 100)}%`
    ), this.volumeBtn.style.color = this.currentVolume > 0 ? "var(--text-muted)" : "rgba(71,85,105,0.5)", this.updateSliderTrack(), this.onVolumeChange && !this.suppressOnChange && this.onVolumeChange(this.currentVolume);
  }
  getVolume() {
    return this.currentVolume;
  }
  getLastNonZeroVolume() {
    return this.lastNonZeroVolume;
  }
  getElement() {
    return this.container;
  }
  destroy() {
    this.clearHideTimeout(), this.handleMasterMirrorBound && (window.removeEventListener("wr-master-mirror", this.handleMasterMirrorBound), this.handleMasterMirrorBound = void 0), this.container.remove();
  }
}
function ir(n, t, e = 16) {
  const s = t, i = n.variant === "filled" ? t : "transparent", r = n.strokeWidth || 2, o = Math.max(1, r), a = 12, l = 12, c = 9, h = (d) => `M ${d.map(([f, p], g) => `${g === 0 ? "" : "L "}${f} ${p}`).join(" ")} Z`;
  return `<svg width="${e}" height="${e}" viewBox="0 0 24 24" aria-hidden="true" style="pointer-events: none;">${((d) => {
    switch (d) {
      case "circle":
        return `<circle cx="${a}" cy="${l}" r="${c}" fill="${i}" stroke="${s}" stroke-width="${o}"/>`;
      case "square":
        return `<rect x="4" y="4" width="16" height="16" rx="2" fill="${i}" stroke="${s}" stroke-width="${o}"/>`;
      case "diamond":
        return `<path d="${h([
          [a, l - c],
          [a + c, l],
          [a, l + c],
          [a - c, l]
        ])}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      case "triangle-up":
        return `<path d="${h([
          [a, l - c],
          [a + c * 0.866, l + c * 0.5],
          [a - c * 0.866, l + c * 0.5]
        ])}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      case "triangle-down":
        return `<path d="${h([
          [a - c * 0.866, l - c * 0.5],
          [a + c * 0.866, l - c * 0.5],
          [a, l + c]
        ])}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      case "triangle-left":
        return `<path d="${h([
          [a + c * 0.5, l - c * 0.866],
          [a + c * 0.5, l + c * 0.866],
          [a - c, l]
        ])}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      case "triangle-right":
        return `<path d="${h([
          [a - c * 0.5, l - c * 0.866],
          [a - c * 0.5, l + c * 0.866],
          [a + c, l]
        ])}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      case "star": {
        const f = [], g = c, m = c * 0.4;
        for (let y = 0; y < 10; y++) {
          const x = y * Math.PI / 5 - Math.PI / 2, v = y % 2 === 0 ? g : m;
          f.push([a + Math.cos(x) * v, l + Math.sin(x) * v]);
        }
        return `<path d="${h(f)}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      }
      case "cross":
        return `<path d="M7 7l10 10M17 7l-10 10" stroke="${s}" stroke-width="${o}" stroke-linecap="round"/>`;
      case "plus":
        return `<path d="M12 5v14M5 12h14" stroke="${s}" stroke-width="${o}" stroke-linecap="round"/>`;
      case "hexagon": {
        const f = [];
        for (let p = 0; p < 6; p++) {
          const m = Math.PI / 3 * p - Math.PI / 6;
          f.push([a + Math.cos(m) * c, l + Math.sin(m) * c]);
        }
        return `<path d="${h(f)}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      }
      case "pentagon": {
        const f = [];
        for (let p = 0; p < 5; p++) {
          const g = 2 * Math.PI / 5 * p - Math.PI / 2;
          f.push([a + Math.cos(g) * c, l + Math.sin(g) * c]);
        }
        return `<path d="${h(f)}" fill="${i}" stroke="${s}" stroke-width="${o}" stroke-linejoin="round"/>`;
      }
      case "chevron-up":
        return `<path d="M6 15l6-6 6 6" stroke="${s}" stroke-width="${o}" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`;
      case "chevron-down":
        return `<path d="M6 9l6 6 6-6" stroke="${s}" stroke-width="${o}" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`;
      default:
        return `<rect x="4" y="4" width="16" height="16" rx="2" fill="${i}" stroke="${s}" stroke-width="${o}"/>`;
    }
  })(
    n.shape
  )}</svg>`;
}
class vm {
  /**
   * Get shape type based on file ID hash
   */
  static getShapeType(t, e) {
    try {
      const r = e?.getOnsetMarkerForFile?.(t);
      if (r?.shape) return r.shape;
    } catch {
    }
    let s = 0;
    for (let r = 0; r < t.length; r++)
      s = s * 31 + t.charCodeAt(r) >>> 0;
    const i = ["circle", "triangle", "diamond", "square"];
    return i[s % i.length];
  }
  /**
   * Create SVG shape element
   */
  static createShapeSVG(t, e, s = 12, i = "filled") {
    const r = "http://www.w3.org/2000/svg", o = document.createElementNS(r, "svg");
    o.setAttribute("width", String(s)), o.setAttribute("height", String(s)), o.setAttribute("viewBox", `0 0 ${s} ${s}`);
    let a;
    const l = s / 2, c = s / 3;
    switch (t) {
      case "circle":
        a = document.createElementNS(r, "circle"), a.setAttribute("cx", String(l)), a.setAttribute("cy", String(l)), a.setAttribute("r", String(c));
        break;
      case "triangle":
        a = document.createElementNS(r, "polygon");
        const h = `${l},${s * 0.17}`, u = `${s * 0.83},${s * 0.83}`, d = `${s * 0.17},${s * 0.83}`;
        a.setAttribute("points", `${h} ${u} ${d}`);
        break;
      case "diamond":
        a = document.createElementNS(r, "polygon");
        const f = `${l},${s * 0.08}`, p = `${s * 0.92},${l}`, g = `${l},${s * 0.92}`, m = `${s * 0.08},${l}`;
        a.setAttribute("points", `${f} ${p} ${g} ${m}`);
        break;
      case "square":
      default:
        a = document.createElementNS(r, "rect");
        const y = s * 0.67, x = (s - y) / 2;
        a.setAttribute("x", String(x)), a.setAttribute("y", String(x)), a.setAttribute("width", String(y)), a.setAttribute("height", String(y));
        break;
    }
    return a.setAttribute("fill", i === "filled" ? e : "transparent"), a.setAttribute("stroke", e), a.setAttribute("stroke-width", "2"), o.appendChild(a), o;
  }
  /**
   * Create color indicator element with shape
   */
  static createColorIndicator(t, e, s) {
    const i = document.createElement("div");
    i.style.cssText = `
      width: 12px;
      height: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
    `;
    const r = s?.getOnsetMarkerForFile?.(t), o = r?.shape ?? this.getShapeType(t, s), a = r?.variant ?? "filled";
    return i.innerHTML = ir({ shape: o, variant: a, strokeWidth: 2 }, e, 12), i;
  }
  /**
   * Create simple square color chip (for WAV files)
   */
  static createSquareColorChip(t) {
    const e = document.createElement("div");
    return e.style.cssText = `
      width: 12px;
      height: 12px;
      border-radius: 2px;
      border: 1px solid var(--ui-border);
      background: ${t};
      flex-shrink: 0;
    `, e;
  }
}
class Il {
  /**
   * Create reference pin button
   */
  static createReferenceButton(t) {
    const { fileId: e, isReference: s, isEstimated: i, dependencies: r, container: o } = t, a = document.createElement("button");
    return a.type = "button", a.textContent = "[REF]", a.title = s ? "Unset as reference" : "Set as reference", a.onclick = () => this.handleReferenceToggle(e, r, o), a.style.cssText = `
      height: 24px;
      padding: 0 8px;
      border: none;
      border-radius: 6px;
      background: transparent;
      color: ${s ? "#0d6efd" : "#adb5bd"};
      cursor: pointer;
      font-size: 11px;
      font-weight: 700;
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
      line-height: 22px;
    `, a.style.boxShadow = "none", a.setAttribute("data-role", "ref-pin"), a.setAttribute("data-file-id", e), a;
  }
  /**
   * Create estimation toggle button
   */
  static createEstimationButton(t) {
    const { fileId: e, isReference: s, isEstimated: i, dependencies: r, container: o } = t, a = document.createElement("button");
    return a.type = "button", a.textContent = "[COMP]", a.title = i ? "Unset as comparison" : "Set as comparison", a.onclick = () => this.handleEstimationToggle(e, r, o), a.style.cssText = `
      height: 24px;
      padding: 0 8px;
      border: none;
      border-radius: 6px;
      background: transparent;
      color: ${i ? "#198754" : "#adb5bd"};
      cursor: pointer;
      font-size: 11px;
      font-weight: 700;
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
      line-height: 22px;
    `, a.style.boxShadow = "none", a.setAttribute("data-role", "est-toggle"), a.setAttribute("data-file-id", e), a;
  }
  /**
   * Handle reference toggle
   */
  static handleReferenceToggle(t, e, s) {
    const i = e.stateManager.getState().evaluation, r = i.refId === t ? null : t, o = r ? i.estIds.filter((a) => a !== r) : i.estIds.slice();
    e.stateManager.updateEvaluationState({
      refId: r,
      estIds: o
    }), this.updateReferenceButtons(s, r, o), this.updateEstimationButtons(s, r, o);
  }
  /**
   * Handle estimation toggle
   */
  static handleEstimationToggle(t, e, s) {
    const i = e.stateManager.getState().evaluation;
    if (i.refId === t) {
      const l = [t];
      e.stateManager.updateEvaluationState({ refId: null, estIds: l }), this.updateEstimationButtons(s, null, l), this.updateReferenceButtons(s, null, l);
      return;
    }
    const o = i.estIds.includes(t) ? [] : [t], a = i.refId ? o.filter((l) => l !== i.refId) : o;
    e.stateManager.updateEvaluationState({ estIds: a }), this.updateEstimationButtons(s, i.refId, a), this.updateReferenceButtons(s, i.refId, a);
  }
  /**
   * Update reference buttons UI
   */
  static updateReferenceButtons(t, e, s) {
    Array.from(
      t.querySelectorAll("button[data-role=ref-pin]")
    ).forEach((r) => {
      const o = r.getAttribute("data-file-id") || "", a = e !== null && o === e;
      r.style.color = a ? "#0d6efd" : "#adb5bd", r.title = a ? "Unset as reference" : "Set as reference", r.style.opacity = "1", r.style.pointerEvents = "auto";
    });
  }
  /**
   * Update estimation buttons UI
   */
  static updateEstimationButtons(t, e, s) {
    Array.from(
      t.querySelectorAll("button[data-role=est-toggle]")
    ).forEach((r) => {
      const o = r.getAttribute("data-file-id") || "", a = s.includes(o);
      r.style.color = a ? "#198754" : "#adb5bd", r.title = a ? "Unset as comparison" : "Set as comparison", r.style.opacity = "1", r.style.pointerEvents = "auto";
    });
  }
  /**
   * Ensure default reference and estimation files
   */
  static ensureDefaults(t) {
    const e = t.stateManager.getState().evaluation, s = t.midiManager.getState().files, i = e.refId, r = i ? s.some((c) => c.id === i) : !1;
    !i && s.length > 0 ? t.stateManager.updateEvaluationState({ refId: s[0].id }) : i && !r && t.stateManager.updateEvaluationState({
      refId: s.length > 0 ? s[0].id : null
    });
    const o = t.stateManager.getState().evaluation;
    if (o.estIds.length === 0 && s.length > 1) {
      const c = o.refId ?? s[0].id, h = s.find((u) => u.id !== c);
      h && t.stateManager.updateEvaluationState({
        estIds: [h.id]
      });
    }
    const a = t.stateManager.getState().evaluation;
    if (a.refId && a.estIds.includes(a.refId)) {
      const c = a.estIds.filter((h) => h !== a.refId);
      t.stateManager.updateEvaluationState({ estIds: c });
    }
    const l = t.stateManager.getState().evaluation;
    l.estIds.length > 1 && t.stateManager.updateEvaluationState({ estIds: [l.estIds[0]] });
  }
}
const Bd = /* @__PURE__ */ new Map();
class r1 {
  /**
   * Create a MIDI file toggle item with optional track accordion
   */
  static create(t, e) {
    const s = document.createElement("div");
    s.style.cssText = "display:flex;flex-direction:column;gap:0;";
    const i = document.createElement("div");
    i.style.cssText = `
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 6px 8px;
      background: var(--surface-alt);
      border-radius: 6px;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
      border: 1px solid var(--ui-border);
    `;
    const r = t.parsedData?.tracks, o = r && r.length > 1;
    let a = null, l = null, c = Bd.get(t.id) ?? !1;
    a = document.createElement("span"), a.style.cssText = "display:flex;align-items:center;width:16px;min-width:16px;", o && (a.innerHTML = c ? Ao : Eo, a.style.cursor = "pointer", a.style.color = "var(--text-muted)", a.style.transition = "transform 0.2s", a.title = `${r.length} tracks`), i.appendChild(a), i.appendChild(this.createColorIndicator(t, e)), i.appendChild(this.createFileName(t));
    const h = document.createElement("div");
    h.style.cssText = "display:flex;align-items:center;gap:2px;", h.appendChild(this.createReferenceButton(t, e, i)), h.appendChild(
      this.createEstimationButton(t, e, i)
    ), i.appendChild(h), i.appendChild(this.createVisibilityButton(t, e)), i.appendChild(this.createSustainButton(t, e)), i.appendChild(this.createVolumeControl(t, e));
    const { labelL: u, slider: d, labelR: f } = this.createPanControls(
      t,
      e
    );
    i.appendChild(u), i.appendChild(d), i.appendChild(f);
    const p = (g) => {
      const m = g.detail;
      !m || !m.mode || (m.mode === "mirror-mute" ? (i.style.opacity = "0.6", i.title = "Master muted — changes apply after unmute") : m.mode === "mirror-restore" && (i.style.opacity = "", i.removeAttribute("title")));
    };
    return window.addEventListener("wr-master-mirror", p), i.__cleanupMasterMirror = () => window.removeEventListener("wr-master-mirror", p), s.appendChild(i), o && a && (l = this.createTrackAccordion(
      t,
      r,
      e,
      c
    ).trackList, s.appendChild(l), a.onclick = (m) => {
      m.stopPropagation(), c = !c, Bd.set(t.id, c), l && (l.style.display = c ? "flex" : "none"), a && (a.innerHTML = c ? Ao : Eo);
    }), s;
  }
  /**
   * Create track accordion for multi-track MIDI files
   * Returns the track list element for external toggle control
   */
  static createTrackAccordion(t, e, s, i) {
    const r = document.createElement("div");
    r.style.cssText = `display:${i ? "flex" : "none"};flex-direction:column;gap:1px;padding:4px 8px;background:var(--surface);border-radius:4px;margin-left:27px;margin-top:2px;`;
    const o = [...e].sort((h, u) => h.isDrum && !u.isDrum ? 1 : !h.isDrum && u.isDrum ? -1 : (h.program ?? 0) - (u.program ?? 0)), a = t.color, l = e.length, c = s.stateManager.getState().visual.uniformTrackColor ?? !1;
    return o.forEach((h) => {
      const u = document.createElement("div");
      u.style.cssText = "display:flex;align-items:center;gap:8px;padding:2px 0;";
      const d = c ? a : Gs.getTrackVariantColor(
        a,
        h.id,
        l
      ), f = document.createElement("span");
      f.style.cssText = `
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background-color: #${d.toString(16).padStart(6, "0")};
        flex-shrink: 0;
      `, f.title = `Track ${h.id + 1} color`;
      const p = document.createElement("span");
      p.innerHTML = uo(h.instrumentFamily), p.style.cssText = "display:flex;align-items:center;justify-content:center;width:18px;height:18px;color:var(--text-muted);", p.title = h.instrumentFamily;
      const g = document.createElement("span");
      g.textContent = h.name, g.style.cssText = "flex:1;font-size:12px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";
      const m = s.midiManager.isTrackVisible(
        t.id,
        h.id
      ), y = js(
        m ? lt.eye_open : lt.eye_closed,
        () => {
          s.midiManager.toggleTrackVisibility(t.id, h.id);
        },
        "Toggle track visibility",
        { size: 20 }
      );
      y.onclick = (A) => {
        A.stopPropagation(), s.midiManager.toggleTrackVisibility(t.id, h.id);
      }, y.style.color = m ? "var(--text-muted)" : "rgba(71,85,105,0.4)", y.style.border = "none", y.style.boxShadow = "none", y.style.padding = "0", y.style.minWidth = "20px", y.style.marginRight = "2px";
      const x = s.midiManager.isTrackSustainVisible?.(t.id, h.id) ?? !0, v = document.createElement("button");
      v.innerHTML = lt.sustain, v.style.cssText = `
        width: 20px;
        height: 20px;
        padding: 0;
        border: none;
        background: transparent;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        color: ${x ? "var(--text-muted)" : "rgba(71,85,105,0.4)"};
        transition: color 0.15s ease;
      `, v.title = x ? "Hide sustain pedal regions" : "Show sustain pedal regions", v.onclick = (A) => {
        A.stopPropagation(), s.midiManager.toggleTrackSustainVisibility?.(
          t.id,
          h.id
        );
      };
      const _ = s.midiManager.isTrackAutoInstrument?.(t.id, h.id) ?? !0, b = document.createElement("button");
      b.innerHTML = uo(_ ? h.instrumentFamily : "piano"), b.style.cssText = `
        width: 20px;
        height: 20px;
        padding: 0;
        border: none;
        background: transparent;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        color: ${_ ? "var(--accent-primary, #3b82f6)" : "var(--text-muted)"};
        transition: color 0.15s ease;
        margin-right: 20px;
        `, b.title = _ ? `Using ${h.instrumentFamily} sound (click for piano)` : "Using piano sound (click for auto instrument)", b.onclick = (A) => {
        A.stopPropagation();
        const I = !s.midiManager.isTrackAutoInstrument?.(
          t.id,
          h.id
        );
        s.midiManager.setTrackAutoInstrument?.(
          t.id,
          h.id,
          I
        );
      };
      const w = s.midiManager.isTrackMuted(
        t.id,
        h.id
      ), S = s.midiManager.getTrackVolume(
        t.id,
        h.id
      ), T = s.midiManager.getTrackLastNonZeroVolume(t.id, h.id), C = new Pl({
        initialVolume: w ? 0 : S,
        lastNonZeroVolume: T,
        size: 22,
        onVolumeChange: (A) => {
          s.midiManager.setTrackVolume(t.id, h.id, A);
          const I = A === 0, F = s.midiManager.isTrackMuted(
            t.id,
            h.id
          );
          I !== F && s.midiManager.toggleTrackMute(t.id, h.id);
        }
      }).getElement(), M = document.createElement("span");
      M.textContent = `${h.noteCount} notes`, M.style.cssText = "font-size:10px;color:var(--text-muted);padding:2px 6px;background:var(--surface-alt);border-radius:10px;min-width:95px;text-align:right;margin-right:10px;", u.appendChild(f), u.appendChild(p), u.appendChild(g), u.appendChild(b), u.appendChild(y), u.appendChild(v), u.appendChild(C), u.appendChild(M), r.appendChild(u);
    }), { trackList: r };
  }
  static createColorIndicator(t, e) {
    const s = `#${t.color.toString(16).padStart(6, "0")}`;
    return vm.createColorIndicator(
      t.id,
      s,
      e.stateManager
    );
  }
  static createFileName(t) {
    const e = document.createElement("span");
    return e.textContent = t.name, e.style.cssText = `
      flex: 1;
      font-size: 14px;
      color: ${t.isPianoRollVisible ? "var(--text-primary)" : "var(--text-muted)"};
    `, e;
  }
  static createReferenceButton(t, e, s) {
    const i = e.stateManager.getState().evaluation;
    return Il.createReferenceButton({
      fileId: t.id,
      isReference: i.refId === t.id,
      isEstimated: i.estIds.includes(t.id),
      dependencies: e,
      container: s.parentElement || s
    });
  }
  static createEstimationButton(t, e, s) {
    const i = e.stateManager.getState().evaluation;
    return Il.createEstimationButton({
      fileId: t.id,
      isReference: i.refId === t.id,
      isEstimated: i.estIds.includes(t.id),
      dependencies: e,
      container: s.parentElement || s
    });
  }
  static createVisibilityButton(t, e) {
    const s = js(
      t.isPianoRollVisible ? lt.eye_open : lt.eye_closed,
      () => e.midiManager.toggleVisibility(t.id),
      "Toggle visibility",
      { size: 24 }
    );
    return s.style.color = t.isPianoRollVisible ? "var(--text-muted)" : "rgba(71,85,105,0.5)", s.style.border = "none", s.style.boxShadow = "none", s;
  }
  static createSustainButton(t, e) {
    const s = document.createElement("button"), i = t.isSustainVisible ?? !0;
    return s.innerHTML = lt.sustain, s.style.cssText = `
      width: 20px;
      height: 20px;
      padding: 0;
      border: none;
      background: transparent;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      color: ${i ? "#495057" : "#adb5bd"};
      transition: color 0.15s ease;
    `, s.addEventListener("click", () => {
      e.midiManager.toggleSustainVisibility(t.id);
    }), s;
  }
  static createVolumeControl(t, e) {
    const i = new Pl({
      initialVolume: t.isMuted ? 0 : t.volume ?? 1,
      fileId: t.id,
      lastNonZeroVolume: t.volume ?? 1,
      onVolumeChange: (r) => {
        const o = r === 0;
        t.isMuted !== o && e.midiManager.toggleMute(t.id), e.audioPlayer?.setFileVolume && e.audioPlayer.setFileVolume(t.id, r), e.audioPlayer?.setFileMute && e.audioPlayer.setFileMute(t.id, o), e.silenceDetector?.setFileVolume?.(t.id, r), e.silenceDetector?.setFileMute?.(t.id, o);
      }
    }).getElement();
    return i.setAttribute("data-role", "file-volume"), i.setAttribute("data-file-id", t.id), i;
  }
  static createPanControls(t, e) {
    const s = document.createElement("span");
    s.textContent = "L", s.style.cssText = "font-size: 12px; color: #6c757d;";
    const i = document.createElement("span");
    i.textContent = "R", i.style.cssText = "font-size: 12px; color: #6c757d;";
    const r = document.createElement("input");
    r.type = "range", r.min = "-100", r.max = "100", r.step = "1";
    const o = (e.filePanValues?.[t.id] ?? 0) * 100;
    return r.value = o.toString(), r.title = "Pan (L • R)", r.style.cssText = `
      width: 80px;
      -webkit-appearance: none;
      appearance: none;
      height: 4px;
      background: #e9ecef;
      border-radius: 8px;
      outline: none;
      cursor: pointer;
    `, r.addEventListener("input", () => {
      const a = parseFloat(r.value) / 100;
      e.filePanValues && (e.filePanValues[t.id] = a), e.audioPlayer?.setFilePan?.(t.id, a);
    }), r.addEventListener("dblclick", () => {
      r.value = "0", e.filePanValues && (e.filePanValues[t.id] = 0), e.audioPlayer?.setFilePan?.(t.id, 0);
    }), { labelL: s, slider: r, labelR: i };
  }
}
class o1 {
  /**
   * Create an audio file toggle item
   */
  static create(t, e) {
    const s = document.createElement("div");
    s.style.cssText = `
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 6px 8px;
      background: var(--surface-alt);
      border-radius: 6px;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
      border: 1px solid var(--ui-border);
    `, s.appendChild(this.createColorIndicator(t)), s.appendChild(this.createFileName(t)), s.appendChild(this.createVisibilityButton(t, e, s)), s.appendChild(this.createVolumeControl(t, e));
    const { labelL: i, slider: r, labelR: o } = this.createPanControls(t, e);
    s.appendChild(i), s.appendChild(r), s.appendChild(o);
    const a = (l) => {
      const c = l.detail;
      !c || !c.mode || (c.mode === "mirror-mute" ? (s.style.opacity = "0.6", s.title = "Master muted — changes apply after unmute") : c.mode === "mirror-restore" && (s.style.opacity = "", s.removeAttribute("title")));
    };
    return window.addEventListener("wr-master-mirror", a), s.__cleanupMasterMirror = () => window.removeEventListener("wr-master-mirror", a), s;
  }
  static createColorIndicator(t) {
    const e = `#${t.color.toString(16).padStart(6, "0")}`;
    return vm.createSquareColorChip(e);
  }
  static createFileName(t) {
    const e = document.createElement("span");
    return e.textContent = t.name, e.style.cssText = `
      flex: 1;
      font-size: 14px;
      color: ${t.isVisible ? "var(--text-primary)" : "var(--text-muted)"};
    `, e;
  }
  static createVisibilityButton(t, e, s) {
    const i = js(
      t.isVisible ? lt.eye_open : lt.eye_closed,
      () => {
        const r = this.getAudioAPI();
        r?.toggleVisibility?.(t.id);
        const o = s.closest('[data-role="file-toggle"]');
        if (o && e) {
          const a = window.FileToggleManager;
          a && a.updateFileToggleSection(o, e);
        }
        try {
          const c = !!(r?.getFiles?.() || []).find((h) => h.id === t.id)?.isVisible;
          window.dispatchEvent(
            new CustomEvent("wr-wav-visibility-changed", {
              detail: { id: t.id, isVisible: c }
            })
          );
        } catch {
        }
      },
      "Toggle waveform visibility",
      { size: 24 }
    );
    return i.style.color = t.isVisible ? "var(--text-muted)" : "rgba(71,85,105,0.5)", i.style.border = "none", i.style.boxShadow = "none", i;
  }
  static createVolumeControl(t, e) {
    const i = new Pl({
      initialVolume: t.isMuted ? 0 : t.volume ?? 1,
      fileId: t.id,
      lastNonZeroVolume: t.volume ?? 1,
      onVolumeChange: (r) => {
        const o = r === 0, a = this.getAudioAPI();
        if (a?.getFiles) {
          const c = (a.getFiles() || []).find((h) => h.id === t.id);
          if (c && c.isMuted !== o) {
            a.toggleMute?.(t.id);
            try {
              window.dispatchEvent(
                new CustomEvent("wr-wav-mute-changed", {
                  detail: { id: t.id, isMuted: o }
                })
              );
            } catch {
            }
          }
        }
        e.audioPlayer?.setWavVolume?.(t.id, r), e.audioPlayer?.refreshAudioPlayers?.(), e.silenceDetector?.setWavVolume?.(t.id, r), e.silenceDetector?.setWavMute?.(t.id, o);
      }
    }).getElement();
    return i.setAttribute("data-role", "wav-volume"), i.setAttribute("data-file-id", t.id), i;
  }
  static createPanControls(t, e) {
    const s = document.createElement("span");
    s.textContent = "L", s.style.cssText = "font-size: 12px; color: var(--text-muted);";
    const i = document.createElement("span");
    i.textContent = "R", i.style.cssText = "font-size: 12px; color: var(--text-muted);";
    const r = document.createElement("input");
    return r.type = "range", r.min = "-100", r.max = "100", r.step = "1", r.value = String((t.pan ?? 0) * 100), r.title = "Pan (L • R)", r.style.cssText = `
      width: 80px;
      -webkit-appearance: none;
      appearance: none;
      height: 4px;
      background: var(--track-bg);
      border-radius: 8px;
      outline: none;
      cursor: pointer;
    `, r.addEventListener("input", () => {
      const o = parseFloat(r.value) / 100;
      e.audioPlayer?.setFilePan?.(t.id, o), this.getAudioAPI()?.setPan?.(t.id, o);
    }), r.addEventListener("dblclick", () => {
      r.value = "0", e.audioPlayer?.setFilePan?.(t.id, 0), this.getAudioAPI()?.setPan?.(t.id, 0);
    }), { labelL: s, slider: r, labelR: i };
  }
  /**
   * Get global audio API
   */
  static getAudioAPI() {
    return globalThis._waveRollAudio;
  }
}
class dr {
  /**
   * Setup the file toggle section
   */
  static setupFileToggleSection(t, e) {
    const s = document.createElement("div");
    s.setAttribute("data-role", "file-toggle"), s.style.cssText = `
      background: var(--surface-alt);
      padding: 12px 0;
      border-radius: 8px;
      margin-top: 12px;
    `, s.appendChild(this.createHeader(e)), s.appendChild(this.createWavSection()), s.appendChild(this.createMidiSection()), t.appendChild(s), window.FileToggleManager = dr;
    const i = () => {
      this.updateFileToggleSection(s, e);
    };
    return window.addEventListener("wr-audio-files-changed", i), s;
  }
  /**
   * Create header with title and control buttons
   */
  static createHeader(t) {
    const e = document.createElement("div");
    e.style.cssText = `
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 8px;
    `;
    const s = document.createElement("h4");
    s.textContent = "Files", s.style.cssText = `
      margin: 0;
      font-size: 14px;
      font-weight: 600;
      color: var(--text-muted);
    `;
    const i = document.createElement("div");
    return i.style.cssText = `
      display: flex;
      align-items: center;
      gap: 6px;
    `, i.appendChild(this.createSettingsButton(t)), i.appendChild(this.createEvaluationButton(t)), e.appendChild(s), e.appendChild(i), e;
  }
  /**
   * Create settings button
   */
  static createSettingsButton(t) {
    const e = document.createElement("button");
    return e.innerHTML = `${lt.file} <span>Files & Appearance</span>`, e.style.cssText = `
      padding: 4px 8px;
      border: none;
      border-radius: 4px;
      background: var(--surface);
      color: var(--text-muted);
      font-size: 12px;
      font-weight: 500;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 4px;
      transition: all 0.2s ease;
    `, e.addEventListener("mouseenter", () => {
      e.style.background = "var(--hover-surface)";
    }), e.addEventListener("mouseleave", () => {
      e.style.background = "var(--surface)";
    }), e.addEventListener("click", () => {
      t.openSettingsModal();
    }), e;
  }
  /**
   * Create evaluation results button
   */
  static createEvaluationButton(t) {
    const e = document.createElement("button");
    return e.innerHTML = `${lt.results} <span>Evaluation Results</span>`, e.style.cssText = `
      padding: 4px 8px;
      border: none;
      border-radius: 4px;
      background: var(--surface);
      color: var(--text-muted);
      font-size: 12px;
      font-weight: 500;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 4px;
      transition: all 0.2s ease;
    `, e.addEventListener("mouseenter", () => {
      e.style.background = "var(--hover-surface)";
    }), e.addEventListener("mouseleave", () => {
      e.style.background = "var(--surface)";
    }), e.addEventListener("click", () => {
      t.openEvaluationResultsModal?.();
    }), e;
  }
  /**
   * Create WAV files section
   */
  static createWavSection() {
    const t = document.createElement("div"), e = document.createElement("h4");
    e.textContent = "WAV File", e.style.cssText = `
      margin: 12px 0 8px 0;
      font-size: 14px;
      font-weight: 600;
      color: var(--text-muted);
    `, e.id = "audio-header";
    const s = document.createElement("div");
    return s.id = "audio-controls", s.style.cssText = `
      display: flex;
      flex-direction: column;
      gap: 8px;
    `, t.appendChild(e), t.appendChild(s), t;
  }
  /**
   * Create MIDI files section
   */
  static createMidiSection() {
    const t = document.createElement("div"), e = document.createElement("h4");
    e.textContent = "MIDI Files", e.style.cssText = `
      margin: 12px 0 8px 0;
      font-size: 14px;
      font-weight: 600;
      color: var(--text-muted);
    `, e.id = "midi-header";
    const s = document.createElement("div");
    return s.id = "file-controls", s.style.cssText = `
      display: flex;
      flex-direction: column;
      gap: 8px;
    `, t.appendChild(e), t.appendChild(s), t;
  }
  /**
   * Update the file toggle section
   */
  static updateFileToggleSection(t, e) {
    Il.ensureDefaults(e), this.updateSectionVisibility(t, e), this.updateMidiFiles(t, e), this.updateWavFiles(t, e);
  }
  /**
   * Update section visibility based on file counts
   */
  static updateSectionVisibility(t, e) {
    const s = t.querySelector("#audio-header"), i = t.querySelector("#midi-header"), r = t.querySelector("#audio-controls"), o = e.midiManager.getState().files.length, l = globalThis._waveRollAudio?.getFiles?.() ?? [], c = Array.isArray(l) ? l.length : 0;
    s && (s.style.display = c > 0 ? "" : "none"), r && (r.style.display = c > 0 ? "" : "none"), i && (i.style.display = o > 0 ? "" : "none");
  }
  /**
   * Update MIDI file controls
   */
  static updateMidiFiles(t, e) {
    const s = t.querySelector("#file-controls");
    if (!s) return;
    s.innerHTML = "", e.midiManager.getState().files.forEach((r) => {
      const o = r1.create(r, e);
      s.appendChild(o);
    });
  }
  /**
   * Update WAV file controls
   */
  static updateWavFiles(t, e) {
    const s = t.querySelector("#audio-controls");
    if (!s) return;
    s.innerHTML = "";
    const o = globalThis._waveRollAudio?.getFiles?.() ?? [];
    for (const a of o) {
      const l = o1.create(a, e);
      s.appendChild(l);
    }
  }
}
function a1(n, t, e, s) {
  Co.setupLayout(n, t, e), Co.setupSidebar(t.sidebarContainer, e), s.style.cssText = `
    width: 100%;
    height: 400px;
    min-height: 400px;
    margin-bottom: 12px;
    background: var(--surface-alt);
    border-radius: 8px;
    position: relative;
    z-index: 1;
  `, t.playerContainer.appendChild(s);
}
function l1() {
  return {
    audioController: {
      defaultVolume: 1,
      defaultTempo: 120,
      minTempo: 20,
      maxTempo: 300,
      updateInterval: 50
    },
    pianoRoll: {
      width: 800,
      height: 400,
      backgroundColor: 16316922,
      // Use theme playhead color for better visibility
      playheadColor: parseInt(om.replace("#", ""), 16),
      showPianoKeys: !0,
      noteRange: { min: 21, max: 108 },
      minorTimeStep: 0.1
    },
    ui: {
      sidebarWidth: 280,
      minHeight: 600,
      updateInterval: 50
    }
  };
}
function c1(n, t) {
  return dr.setupFileToggleSection(n, t);
}
const uc = "15.1.22", zd = (n, t, e) => ({ endTime: t, insertTime: e, type: "exponentialRampToValue", value: n }), qd = (n, t, e) => ({ endTime: t, insertTime: e, type: "linearRampToValue", value: n }), Fl = (n, t) => ({ startTime: t, type: "setValue", value: n }), bm = (n, t, e) => ({ duration: e, startTime: t, type: "setValueCurve", values: n }), wm = (n, t, { startTime: e, target: s, timeConstant: i }) => s + (t - s) * Math.exp((e - n) / i), $n = (n) => n.type === "exponentialRampToValue", Po = (n) => n.type === "linearRampToValue", Bs = (n) => $n(n) || Po(n), dc = (n) => n.type === "setValue", Ss = (n) => n.type === "setValueCurve", Io = (n, t, e, s) => {
  const i = n[t];
  return i === void 0 ? s : Bs(i) || dc(i) ? i.value : Ss(i) ? i.values[i.values.length - 1] : wm(e, Io(n, t - 1, i.startTime, s), i);
}, Ud = (n, t, e, s, i) => e === void 0 ? [s.insertTime, i] : Bs(e) ? [e.endTime, e.value] : dc(e) ? [e.startTime, e.value] : Ss(e) ? [
  e.startTime + e.duration,
  e.values[e.values.length - 1]
] : [
  e.startTime,
  Io(n, t - 1, e.startTime, i)
], Rl = (n) => n.type === "cancelAndHold", Dl = (n) => n.type === "cancelScheduledValues", Vs = (n) => Rl(n) || Dl(n) ? n.cancelTime : $n(n) || Po(n) ? n.endTime : n.startTime, Gd = (n, t, e, { endTime: s, value: i }) => e === i ? i : 0 < e && 0 < i || e < 0 && i < 0 ? e * (i / e) ** ((n - t) / (s - t)) : 0, Wd = (n, t, e, { endTime: s, value: i }) => e + (n - t) / (s - t) * (i - e), h1 = (n, t) => {
  const e = Math.floor(t), s = Math.ceil(t);
  return e === s ? n[e] : (1 - (t - e)) * n[e] + (1 - (s - t)) * n[s];
}, u1 = (n, { duration: t, startTime: e, values: s }) => {
  const i = (n - e) / t * (s.length - 1);
  return h1(s, i);
}, eo = (n) => n.type === "setTarget";
class d1 {
  constructor(t) {
    this._automationEvents = [], this._currenTime = 0, this._defaultValue = t;
  }
  [Symbol.iterator]() {
    return this._automationEvents[Symbol.iterator]();
  }
  add(t) {
    const e = Vs(t);
    if (Rl(t) || Dl(t)) {
      const s = this._automationEvents.findIndex((r) => Dl(t) && Ss(r) ? r.startTime + r.duration >= e : Vs(r) >= e), i = this._automationEvents[s];
      if (s !== -1 && (this._automationEvents = this._automationEvents.slice(0, s)), Rl(t)) {
        const r = this._automationEvents[this._automationEvents.length - 1];
        if (i !== void 0 && Bs(i)) {
          if (r !== void 0 && eo(r))
            throw new Error("The internal list is malformed.");
          const o = r === void 0 ? i.insertTime : Ss(r) ? r.startTime + r.duration : Vs(r), a = r === void 0 ? this._defaultValue : Ss(r) ? r.values[r.values.length - 1] : r.value, l = $n(i) ? Gd(e, o, a, i) : Wd(e, o, a, i), c = $n(i) ? zd(l, e, this._currenTime) : qd(l, e, this._currenTime);
          this._automationEvents.push(c);
        }
        if (r !== void 0 && eo(r) && this._automationEvents.push(Fl(this.getValue(e), e)), r !== void 0 && Ss(r) && r.startTime + r.duration > e) {
          const o = e - r.startTime, a = (r.values.length - 1) / r.duration, l = Math.max(2, 1 + Math.ceil(o * a)), c = o / (l - 1) * a, h = r.values.slice(0, l);
          if (c < 1)
            for (let u = 1; u < l; u += 1) {
              const d = c * u % 1;
              h[u] = r.values[u - 1] * (1 - d) + r.values[u] * d;
            }
          this._automationEvents[this._automationEvents.length - 1] = bm(h, r.startTime, o);
        }
      }
    } else {
      const s = this._automationEvents.findIndex((o) => Vs(o) > e), i = s === -1 ? this._automationEvents[this._automationEvents.length - 1] : this._automationEvents[s - 1];
      if (i !== void 0 && Ss(i) && Vs(i) + i.duration > e)
        return !1;
      const r = $n(t) ? zd(t.value, t.endTime, this._currenTime) : Po(t) ? qd(t.value, e, this._currenTime) : t;
      if (s === -1)
        this._automationEvents.push(r);
      else {
        if (Ss(t) && e + t.duration > Vs(this._automationEvents[s]))
          return !1;
        this._automationEvents.splice(s, 0, r);
      }
    }
    return !0;
  }
  flush(t) {
    const e = this._automationEvents.findIndex((s) => Vs(s) > t);
    if (e > 1) {
      const s = this._automationEvents.slice(e - 1), i = s[0];
      eo(i) && s.unshift(Fl(Io(this._automationEvents, e - 2, i.startTime, this._defaultValue), i.startTime)), this._automationEvents = s;
    }
  }
  getValue(t) {
    if (this._automationEvents.length === 0)
      return this._defaultValue;
    const e = this._automationEvents.findIndex((o) => Vs(o) > t), s = this._automationEvents[e], i = (e === -1 ? this._automationEvents.length : e) - 1, r = this._automationEvents[i];
    if (r !== void 0 && eo(r) && (s === void 0 || !Bs(s) || s.insertTime > t))
      return wm(t, Io(this._automationEvents, i - 1, r.startTime, this._defaultValue), r);
    if (r !== void 0 && dc(r) && (s === void 0 || !Bs(s)))
      return r.value;
    if (r !== void 0 && Ss(r) && (s === void 0 || !Bs(s) || r.startTime + r.duration > t))
      return t < r.startTime + r.duration ? u1(t, r) : r.values[r.values.length - 1];
    if (r !== void 0 && Bs(r) && (s === void 0 || !Bs(s)))
      return r.value;
    if (s !== void 0 && $n(s)) {
      const [o, a] = Ud(this._automationEvents, i, r, s, this._defaultValue);
      return Gd(t, o, a, s);
    }
    if (s !== void 0 && Po(s)) {
      const [o, a] = Ud(this._automationEvents, i, r, s, this._defaultValue);
      return Wd(t, o, a, s);
    }
    return this._defaultValue;
  }
}
const f1 = (n) => ({ cancelTime: n, type: "cancelAndHold" }), p1 = (n) => ({ cancelTime: n, type: "cancelScheduledValues" }), m1 = (n, t) => ({ endTime: t, type: "exponentialRampToValue", value: n }), g1 = (n, t) => ({ endTime: t, type: "linearRampToValue", value: n }), y1 = (n, t, e) => ({ startTime: t, target: n, timeConstant: e, type: "setTarget" }), x1 = () => new DOMException("", "AbortError"), _1 = (n) => (t, e, [s, i, r], o) => {
  n(t[i], [e, s, r], (a) => a[0] === e && a[1] === s, o);
}, v1 = (n) => (t, e, s) => {
  const i = [];
  for (let r = 0; r < s.numberOfInputs; r += 1)
    i.push(/* @__PURE__ */ new Set());
  n.set(t, {
    activeInputs: i,
    outputs: /* @__PURE__ */ new Set(),
    passiveInputs: /* @__PURE__ */ new WeakMap(),
    renderer: e
  });
}, b1 = (n) => (t, e) => {
  n.set(t, { activeInputs: /* @__PURE__ */ new Set(), passiveInputs: /* @__PURE__ */ new WeakMap(), renderer: e });
}, Jn = /* @__PURE__ */ new WeakSet(), Sm = /* @__PURE__ */ new WeakMap(), fc = /* @__PURE__ */ new WeakMap(), Tm = /* @__PURE__ */ new WeakMap(), pc = /* @__PURE__ */ new WeakMap(), Qo = /* @__PURE__ */ new WeakMap(), Mm = /* @__PURE__ */ new WeakMap(), Ol = /* @__PURE__ */ new WeakMap(), Nl = /* @__PURE__ */ new WeakMap(), Ll = /* @__PURE__ */ new WeakMap(), km = {
  construct() {
    return km;
  }
}, w1 = (n) => {
  try {
    const t = new Proxy(n, km);
    new t();
  } catch {
    return !1;
  }
  return !0;
}, $d = /^import(?:(?:[\s]+[\w]+|(?:[\s]+[\w]+[\s]*,)?[\s]*\{[\s]*[\w]+(?:[\s]+as[\s]+[\w]+)?(?:[\s]*,[\s]*[\w]+(?:[\s]+as[\s]+[\w]+)?)*[\s]*}|(?:[\s]+[\w]+[\s]*,)?[\s]*\*[\s]+as[\s]+[\w]+)[\s]+from)?(?:[\s]*)("([^"\\]|\\.)+"|'([^'\\]|\\.)+')(?:[\s]*);?/, Hd = (n, t) => {
  const e = [];
  let s = n.replace(/^[\s]+/, ""), i = s.match($d);
  for (; i !== null; ) {
    const r = i[1].slice(1, -1), o = i[0].replace(/([\s]+)?;?$/, "").replace(r, new URL(r, t).toString());
    e.push(o), s = s.slice(i[0].length).replace(/^[\s]+/, ""), i = s.match($d);
  }
  return [e.join(";"), s];
}, jd = (n) => {
  if (n !== void 0 && !Array.isArray(n))
    throw new TypeError("The parameterDescriptors property of given value for processorCtor is not an array.");
}, Xd = (n) => {
  if (!w1(n))
    throw new TypeError("The given value for processorCtor should be a constructor.");
  if (n.prototype === null || typeof n.prototype != "object")
    throw new TypeError("The given value for processorCtor should have a prototype.");
}, S1 = (n, t, e, s, i, r, o, a, l, c, h, u, d) => {
  let f = 0;
  return (p, g, m = { credentials: "omit" }) => {
    const y = h.get(p);
    if (y !== void 0 && y.has(g))
      return Promise.resolve();
    const x = c.get(p);
    if (x !== void 0) {
      const b = x.get(g);
      if (b !== void 0)
        return b;
    }
    const v = r(p), _ = v.audioWorklet === void 0 ? i(g).then(([b, w]) => {
      const [S, T] = Hd(b, w), k = `${S};((a,b)=>{(a[b]=a[b]||[]).push((AudioWorkletProcessor,global,registerProcessor,sampleRate,self,window)=>{${T}
})})(window,'_AWGS')`;
      return e(k);
    }).then(() => {
      const b = d._AWGS.pop();
      if (b === void 0)
        throw new SyntaxError();
      s(v.currentTime, v.sampleRate, () => b(class {
      }, void 0, (w, S) => {
        if (w.trim() === "")
          throw t();
        const T = Nl.get(v);
        if (T !== void 0) {
          if (T.has(w))
            throw t();
          Xd(S), jd(S.parameterDescriptors), T.set(w, S);
        } else
          Xd(S), jd(S.parameterDescriptors), Nl.set(v, /* @__PURE__ */ new Map([[w, S]]));
      }, v.sampleRate, void 0, void 0));
    }) : Promise.all([
      i(g),
      Promise.resolve(n(u, u))
    ]).then(([[b, w], S]) => {
      const T = f + 1;
      f = T;
      const [k, C] = Hd(b, w), F = `${k};((AudioWorkletProcessor,registerProcessor)=>{${C}
})(${S ? "AudioWorkletProcessor" : "class extends AudioWorkletProcessor {__b=new WeakSet();constructor(){super();(p=>p.postMessage=(q=>(m,t)=>q.call(p,m,t?t.filter(u=>!this.__b.has(u)):t))(p.postMessage))(this.port)}}"},(n,p)=>registerProcessor(n,class extends p{${S ? "" : "__c = (a) => a.forEach(e=>this.__b.add(e.buffer));"}process(i,o,p){${S ? "" : "i.forEach(this.__c);o.forEach(this.__c);this.__c(Object.values(p));"}return super.process(i.map(j=>j.some(k=>k.length===0)?[]:j),o,p)}}));registerProcessor('__sac${T}',class extends AudioWorkletProcessor{process(){return !1}})`, R = new Blob([F], { type: "application/javascript; charset=utf-8" }), E = URL.createObjectURL(R);
      return v.audioWorklet.addModule(E, m).then(() => {
        if (a(v))
          return v;
        const P = o(v);
        return P.audioWorklet.addModule(E, m).then(() => P);
      }).then((P) => {
        if (l === null)
          throw new SyntaxError();
        try {
          new l(P, `__sac${T}`);
        } catch {
          throw new SyntaxError();
        }
      }).finally(() => URL.revokeObjectURL(E));
    });
    return x === void 0 ? c.set(p, /* @__PURE__ */ new Map([[g, _]])) : x.set(g, _), _.then(() => {
      const b = h.get(p);
      b === void 0 ? h.set(p, /* @__PURE__ */ new Set([g])) : b.add(g);
    }).finally(() => {
      const b = c.get(p);
      b !== void 0 && b.delete(g);
    }), _;
  };
}, Ze = (n, t) => {
  const e = n.get(t);
  if (e === void 0)
    throw new Error("A value with the given key could not be found.");
  return e;
}, Jo = (n, t) => {
  const e = Array.from(n).filter(t);
  if (e.length > 1)
    throw Error("More than one element was found.");
  if (e.length === 0)
    throw Error("No element was found.");
  const [s] = e;
  return n.delete(s), s;
}, Cm = (n, t, e, s) => {
  const i = Ze(n, t), r = Jo(i, (o) => o[0] === e && o[1] === s);
  return i.size === 0 && n.delete(t), r;
}, fr = (n) => Ze(Mm, n), ti = (n) => {
  if (Jn.has(n))
    throw new Error("The AudioNode is already stored.");
  Jn.add(n), fr(n).forEach((t) => t(!0));
}, Am = (n) => "port" in n, pr = (n) => {
  if (!Jn.has(n))
    throw new Error("The AudioNode is not stored.");
  Jn.delete(n), fr(n).forEach((t) => t(!1));
}, Vl = (n, t) => {
  !Am(n) && t.every((e) => e.size === 0) && pr(n);
}, T1 = (n, t, e, s, i, r, o, a, l, c, h, u, d) => {
  const f = /* @__PURE__ */ new WeakMap();
  return (p, g, m, y, x) => {
    const { activeInputs: v, passiveInputs: _ } = r(g), { outputs: b } = r(p), w = a(p), S = (T) => {
      const k = l(g), C = l(p);
      if (T) {
        const M = Cm(_, p, m, y);
        n(v, p, M, !1), !x && !u(p) && e(C, k, m, y), d(g) && ti(g);
      } else {
        const M = s(v, p, m, y);
        t(_, y, M, !1), !x && !u(p) && i(C, k, m, y);
        const A = o(g);
        if (A === 0)
          h(g) && Vl(g, v);
        else {
          const I = f.get(g);
          I !== void 0 && clearTimeout(I), f.set(g, setTimeout(() => {
            h(g) && Vl(g, v);
          }, A * 1e3));
        }
      }
    };
    return c(b, [g, m, y], (T) => T[0] === g && T[1] === m && T[2] === y, !0) ? (w.add(S), h(p) ? n(v, p, [m, y, S], !0) : t(_, y, [p, m, S], !0), !0) : !1;
  };
}, M1 = (n) => (t, e, [s, i, r], o) => {
  const a = t.get(s);
  a === void 0 ? t.set(s, /* @__PURE__ */ new Set([[i, e, r]])) : n(a, [i, e, r], (l) => l[0] === i && l[1] === e, o);
}, k1 = (n) => (t, e) => {
  const s = n(t, {
    channelCount: 1,
    channelCountMode: "explicit",
    channelInterpretation: "discrete",
    gain: 0
  });
  e.connect(s).connect(t.destination);
  const i = () => {
    e.removeEventListener("ended", i), e.disconnect(s), s.disconnect();
  };
  e.addEventListener("ended", i);
}, C1 = (n) => (t, e) => {
  n(t).add(e);
}, A1 = {
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  fftSize: 2048,
  maxDecibels: -30,
  minDecibels: -100,
  smoothingTimeConstant: 0.8
}, E1 = (n, t, e, s, i, r) => class extends n {
  constructor(a, l) {
    const c = i(a), h = { ...A1, ...l }, u = s(c, h), d = r(c) ? t() : null;
    super(a, !1, u, d), this._nativeAnalyserNode = u;
  }
  get fftSize() {
    return this._nativeAnalyserNode.fftSize;
  }
  set fftSize(a) {
    this._nativeAnalyserNode.fftSize = a;
  }
  get frequencyBinCount() {
    return this._nativeAnalyserNode.frequencyBinCount;
  }
  get maxDecibels() {
    return this._nativeAnalyserNode.maxDecibels;
  }
  set maxDecibels(a) {
    const l = this._nativeAnalyserNode.maxDecibels;
    if (this._nativeAnalyserNode.maxDecibels = a, !(a > this._nativeAnalyserNode.minDecibels))
      throw this._nativeAnalyserNode.maxDecibels = l, e();
  }
  get minDecibels() {
    return this._nativeAnalyserNode.minDecibels;
  }
  set minDecibels(a) {
    const l = this._nativeAnalyserNode.minDecibels;
    if (this._nativeAnalyserNode.minDecibels = a, !(this._nativeAnalyserNode.maxDecibels > a))
      throw this._nativeAnalyserNode.minDecibels = l, e();
  }
  get smoothingTimeConstant() {
    return this._nativeAnalyserNode.smoothingTimeConstant;
  }
  set smoothingTimeConstant(a) {
    this._nativeAnalyserNode.smoothingTimeConstant = a;
  }
  getByteFrequencyData(a) {
    this._nativeAnalyserNode.getByteFrequencyData(a);
  }
  getByteTimeDomainData(a) {
    this._nativeAnalyserNode.getByteTimeDomainData(a);
  }
  getFloatFrequencyData(a) {
    this._nativeAnalyserNode.getFloatFrequencyData(a);
  }
  getFloatTimeDomainData(a) {
    this._nativeAnalyserNode.getFloatTimeDomainData(a);
  }
}, ne = (n, t) => n.context === t, P1 = (n, t, e) => () => {
  const s = /* @__PURE__ */ new WeakMap(), i = async (r, o) => {
    let a = t(r);
    if (!ne(a, o)) {
      const c = {
        channelCount: a.channelCount,
        channelCountMode: a.channelCountMode,
        channelInterpretation: a.channelInterpretation,
        fftSize: a.fftSize,
        maxDecibels: a.maxDecibels,
        minDecibels: a.minDecibels,
        smoothingTimeConstant: a.smoothingTimeConstant
      };
      a = n(o, c);
    }
    return s.set(o, a), await e(r, o, a), a;
  };
  return {
    render(r, o) {
      const a = s.get(o);
      return a !== void 0 ? Promise.resolve(a) : i(r, o);
    }
  };
}, Fo = (n) => {
  try {
    n.copyToChannel(new Float32Array(1), 0, -1);
  } catch {
    return !1;
  }
  return !0;
}, gs = () => new DOMException("", "IndexSizeError"), mc = (n) => {
  n.getChannelData = /* @__PURE__ */ ((t) => (e) => {
    try {
      return t.call(n, e);
    } catch (s) {
      throw s.code === 12 ? gs() : s;
    }
  })(n.getChannelData);
}, I1 = {
  numberOfChannels: 1
}, F1 = (n, t, e, s, i, r, o, a) => {
  let l = null;
  return class Em {
    constructor(h) {
      if (i === null)
        throw new Error("Missing the native OfflineAudioContext constructor.");
      const { length: u, numberOfChannels: d, sampleRate: f } = { ...I1, ...h };
      l === null && (l = new i(1, 1, 44100));
      const p = s !== null && t(r, r) ? new s({ length: u, numberOfChannels: d, sampleRate: f }) : l.createBuffer(d, u, f);
      if (p.numberOfChannels === 0)
        throw e();
      return typeof p.copyFromChannel != "function" ? (o(p), mc(p)) : t(Fo, () => Fo(p)) || a(p), n.add(p), p;
    }
    static [Symbol.hasInstance](h) {
      return h !== null && typeof h == "object" && Object.getPrototypeOf(h) === Em.prototype || n.has(h);
    }
  };
}, ye = -34028234663852886e22, re = -ye, As = (n) => Jn.has(n), R1 = {
  buffer: null,
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  // Bug #149: Safari does not yet support the detune AudioParam.
  loop: !1,
  loopEnd: 0,
  loopStart: 0,
  playbackRate: 1
}, D1 = (n, t, e, s, i, r, o, a) => class extends n {
  constructor(c, h) {
    const u = r(c), d = { ...R1, ...h }, f = i(u, d), p = o(u), g = p ? t() : null;
    super(c, !1, f, g), this._audioBufferSourceNodeRenderer = g, this._isBufferNullified = !1, this._isBufferSet = d.buffer !== null, this._nativeAudioBufferSourceNode = f, this._onended = null, this._playbackRate = e(this, p, f.playbackRate, re, ye);
  }
  get buffer() {
    return this._isBufferNullified ? null : this._nativeAudioBufferSourceNode.buffer;
  }
  set buffer(c) {
    if (this._nativeAudioBufferSourceNode.buffer = c, c !== null) {
      if (this._isBufferSet)
        throw s();
      this._isBufferSet = !0;
    }
  }
  get loop() {
    return this._nativeAudioBufferSourceNode.loop;
  }
  set loop(c) {
    this._nativeAudioBufferSourceNode.loop = c;
  }
  get loopEnd() {
    return this._nativeAudioBufferSourceNode.loopEnd;
  }
  set loopEnd(c) {
    this._nativeAudioBufferSourceNode.loopEnd = c;
  }
  get loopStart() {
    return this._nativeAudioBufferSourceNode.loopStart;
  }
  set loopStart(c) {
    this._nativeAudioBufferSourceNode.loopStart = c;
  }
  get onended() {
    return this._onended;
  }
  set onended(c) {
    const h = typeof c == "function" ? a(this, c) : null;
    this._nativeAudioBufferSourceNode.onended = h;
    const u = this._nativeAudioBufferSourceNode.onended;
    this._onended = u !== null && u === h ? c : u;
  }
  get playbackRate() {
    return this._playbackRate;
  }
  start(c = 0, h = 0, u) {
    if (this._nativeAudioBufferSourceNode.start(c, h, u), this._audioBufferSourceNodeRenderer !== null && (this._audioBufferSourceNodeRenderer.start = u === void 0 ? [c, h] : [c, h, u]), this.context.state !== "closed") {
      ti(this);
      const d = () => {
        this._nativeAudioBufferSourceNode.removeEventListener("ended", d), As(this) && pr(this);
      };
      this._nativeAudioBufferSourceNode.addEventListener("ended", d);
    }
  }
  stop(c = 0) {
    this._nativeAudioBufferSourceNode.stop(c), this._audioBufferSourceNodeRenderer !== null && (this._audioBufferSourceNodeRenderer.stop = c);
  }
}, O1 = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap();
  let o = null, a = null;
  const l = async (c, h) => {
    let u = e(c);
    const d = ne(u, h);
    if (!d) {
      const f = {
        buffer: u.buffer,
        channelCount: u.channelCount,
        channelCountMode: u.channelCountMode,
        channelInterpretation: u.channelInterpretation,
        // Bug #149: Safari does not yet support the detune AudioParam.
        loop: u.loop,
        loopEnd: u.loopEnd,
        loopStart: u.loopStart,
        playbackRate: u.playbackRate.value
      };
      u = t(h, f), o !== null && u.start(...o), a !== null && u.stop(a);
    }
    return r.set(h, u), d ? await n(h, c.playbackRate, u.playbackRate) : await s(h, c.playbackRate, u.playbackRate), await i(c, h, u), u;
  };
  return {
    set start(c) {
      o = c;
    },
    set stop(c) {
      a = c;
    },
    render(c, h) {
      const u = r.get(h);
      return u !== void 0 ? Promise.resolve(u) : l(c, h);
    }
  };
}, N1 = (n) => "playbackRate" in n, L1 = (n) => "frequency" in n && "gain" in n, V1 = (n) => "offset" in n, B1 = (n) => !("frequency" in n) && "gain" in n, z1 = (n) => "detune" in n && "frequency" in n && !("gain" in n), q1 = (n) => "pan" in n, le = (n) => Ze(Sm, n), mr = (n) => Ze(Tm, n), Bl = (n, t) => {
  const { activeInputs: e } = le(n);
  e.forEach((i) => i.forEach(([r]) => {
    t.includes(n) || Bl(r, [...t, n]);
  }));
  const s = N1(n) ? [
    // Bug #149: Safari does not yet support the detune AudioParam.
    n.playbackRate
  ] : Am(n) ? Array.from(n.parameters.values()) : L1(n) ? [n.Q, n.detune, n.frequency, n.gain] : V1(n) ? [n.offset] : B1(n) ? [n.gain] : z1(n) ? [n.detune, n.frequency] : q1(n) ? [n.pan] : [];
  for (const i of s) {
    const r = mr(i);
    r !== void 0 && r.activeInputs.forEach(([o]) => Bl(o, t));
  }
  As(n) && pr(n);
}, Pm = (n) => {
  Bl(n.destination, []);
}, U1 = (n) => n === void 0 || typeof n == "number" || typeof n == "string" && (n === "balanced" || n === "interactive" || n === "playback"), G1 = (n, t, e, s, i, r, o, a, l) => class extends n {
  constructor(h = {}) {
    if (l === null)
      throw new Error("Missing the native AudioContext constructor.");
    let u;
    try {
      u = new l(h);
    } catch (p) {
      throw p.code === 12 && p.message === "sampleRate is not in range" ? e() : p;
    }
    if (u === null)
      throw s();
    if (!U1(h.latencyHint))
      throw new TypeError(`The provided value '${h.latencyHint}' is not a valid enum value of type AudioContextLatencyCategory.`);
    if (h.sampleRate !== void 0 && u.sampleRate !== h.sampleRate)
      throw e();
    super(u, 2);
    const { latencyHint: d } = h, { sampleRate: f } = u;
    if (this._baseLatency = typeof u.baseLatency == "number" ? u.baseLatency : d === "balanced" ? 512 / f : d === "interactive" || d === void 0 ? 256 / f : d === "playback" ? 1024 / f : (
      /*
       * @todo The min (256) and max (16384) values are taken from the allowed bufferSize values of a
       * ScriptProcessorNode.
       */
      Math.max(2, Math.min(128, Math.round(d * f / 128))) * 128 / f
    ), this._nativeAudioContext = u, l.name === "webkitAudioContext" ? (this._nativeGainNode = u.createGain(), this._nativeOscillatorNode = u.createOscillator(), this._nativeGainNode.gain.value = 1e-37, this._nativeOscillatorNode.connect(this._nativeGainNode).connect(u.destination), this._nativeOscillatorNode.start()) : (this._nativeGainNode = null, this._nativeOscillatorNode = null), this._state = null, u.state === "running") {
      this._state = "suspended";
      const p = () => {
        this._state === "suspended" && (this._state = null), u.removeEventListener("statechange", p);
      };
      u.addEventListener("statechange", p);
    }
  }
  get baseLatency() {
    return this._baseLatency;
  }
  get state() {
    return this._state !== null ? this._state : this._nativeAudioContext.state;
  }
  close() {
    return this.state === "closed" ? this._nativeAudioContext.close().then(() => {
      throw t();
    }) : (this._state === "suspended" && (this._state = null), this._nativeAudioContext.close().then(() => {
      this._nativeGainNode !== null && this._nativeOscillatorNode !== null && (this._nativeOscillatorNode.stop(), this._nativeGainNode.disconnect(), this._nativeOscillatorNode.disconnect()), Pm(this);
    }));
  }
  createMediaElementSource(h) {
    return new i(this, { mediaElement: h });
  }
  createMediaStreamDestination() {
    return new r(this);
  }
  createMediaStreamSource(h) {
    return new o(this, { mediaStream: h });
  }
  createMediaStreamTrackSource(h) {
    return new a(this, { mediaStreamTrack: h });
  }
  resume() {
    return this._state === "suspended" ? new Promise((h, u) => {
      const d = () => {
        this._nativeAudioContext.removeEventListener("statechange", d), this._nativeAudioContext.state === "running" ? h() : this.resume().then(h, u);
      };
      this._nativeAudioContext.addEventListener("statechange", d);
    }) : this._nativeAudioContext.resume().catch((h) => {
      throw h === void 0 || h.code === 15 ? t() : h;
    });
  }
  suspend() {
    return this._nativeAudioContext.suspend().catch((h) => {
      throw h === void 0 ? t() : h;
    });
  }
}, W1 = (n, t, e, s, i, r, o, a) => class extends n {
  constructor(c, h) {
    const u = r(c), d = o(u), f = i(u, h, d), p = d ? t(a) : null;
    super(c, !1, f, p), this._isNodeOfNativeOfflineAudioContext = d, this._nativeAudioDestinationNode = f;
  }
  get channelCount() {
    return this._nativeAudioDestinationNode.channelCount;
  }
  set channelCount(c) {
    if (this._isNodeOfNativeOfflineAudioContext)
      throw s();
    if (c > this._nativeAudioDestinationNode.maxChannelCount)
      throw e();
    this._nativeAudioDestinationNode.channelCount = c;
  }
  get channelCountMode() {
    return this._nativeAudioDestinationNode.channelCountMode;
  }
  set channelCountMode(c) {
    if (this._isNodeOfNativeOfflineAudioContext)
      throw s();
    this._nativeAudioDestinationNode.channelCountMode = c;
  }
  get maxChannelCount() {
    return this._nativeAudioDestinationNode.maxChannelCount;
  }
}, $1 = (n) => {
  const t = /* @__PURE__ */ new WeakMap(), e = async (s, i) => {
    const r = i.destination;
    return t.set(i, r), await n(s, i, r), r;
  };
  return {
    render(s, i) {
      const r = t.get(i);
      return r !== void 0 ? Promise.resolve(r) : e(s, i);
    }
  };
}, H1 = (n, t, e, s, i, r, o, a) => (l, c) => {
  const h = c.listener, u = () => {
    const b = new Float32Array(1), w = t(c, {
      channelCount: 1,
      channelCountMode: "explicit",
      channelInterpretation: "speakers",
      numberOfInputs: 9
    }), S = o(c);
    let T = !1, k = [0, 0, -1, 0, 1, 0], C = [0, 0, 0];
    const M = () => {
      if (T)
        return;
      T = !0;
      const R = s(c, 256, 9, 0);
      R.onaudioprocess = ({ inputBuffer: E }) => {
        const P = [
          r(E, b, 0),
          r(E, b, 1),
          r(E, b, 2),
          r(E, b, 3),
          r(E, b, 4),
          r(E, b, 5)
        ];
        P.some((D, z) => D !== k[z]) && (h.setOrientation(...P), k = P);
        const N = [
          r(E, b, 6),
          r(E, b, 7),
          r(E, b, 8)
        ];
        N.some((D, z) => D !== C[z]) && (h.setPosition(...N), C = N);
      }, w.connect(R);
    }, A = (R) => (E) => {
      E !== k[R] && (k[R] = E, h.setOrientation(...k));
    }, I = (R) => (E) => {
      E !== C[R] && (C[R] = E, h.setPosition(...C));
    }, F = (R, E, P) => {
      const N = e(c, {
        channelCount: 1,
        channelCountMode: "explicit",
        channelInterpretation: "discrete",
        offset: E
      });
      N.connect(w, 0, R), N.start(), Object.defineProperty(N.offset, "defaultValue", {
        get() {
          return E;
        }
      });
      const D = n({ context: l }, S, N.offset, re, ye);
      return a(D, "value", (z) => () => z.call(D), (z) => (O) => {
        try {
          z.call(D, O);
        } catch (V) {
          if (V.code !== 9)
            throw V;
        }
        M(), S && P(O);
      }), D.cancelAndHoldAtTime = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.cancelAndHoldAtTime), D.cancelScheduledValues = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.cancelScheduledValues), D.exponentialRampToValueAtTime = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.exponentialRampToValueAtTime), D.linearRampToValueAtTime = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.linearRampToValueAtTime), D.setTargetAtTime = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.setTargetAtTime), D.setValueAtTime = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.setValueAtTime), D.setValueCurveAtTime = /* @__PURE__ */ ((z) => S ? () => {
        throw i();
      } : (...O) => {
        const V = z.apply(D, O);
        return M(), V;
      })(D.setValueCurveAtTime), D;
    };
    return {
      forwardX: F(0, 0, A(0)),
      forwardY: F(1, 0, A(1)),
      forwardZ: F(2, -1, A(2)),
      positionX: F(6, 0, I(0)),
      positionY: F(7, 0, I(1)),
      positionZ: F(8, 0, I(2)),
      upX: F(3, 0, A(3)),
      upY: F(4, 1, A(4)),
      upZ: F(5, 0, A(5))
    };
  }, { forwardX: d, forwardY: f, forwardZ: p, positionX: g, positionY: m, positionZ: y, upX: x, upY: v, upZ: _ } = h.forwardX === void 0 ? u() : h;
  return {
    get forwardX() {
      return d;
    },
    get forwardY() {
      return f;
    },
    get forwardZ() {
      return p;
    },
    get positionX() {
      return g;
    },
    get positionY() {
      return m;
    },
    get positionZ() {
      return y;
    },
    get upX() {
      return x;
    },
    get upY() {
      return v;
    },
    get upZ() {
      return _;
    }
  };
}, Ro = (n) => "context" in n, gr = (n) => Ro(n[0]), Cn = (n, t, e, s) => {
  for (const i of n)
    if (e(i)) {
      if (s)
        return !1;
      throw Error("The set contains at least one similar element.");
    }
  return n.add(t), !0;
}, Yd = (n, t, [e, s], i) => {
  Cn(n, [t, e, s], (r) => r[0] === t && r[1] === e, i);
}, Zd = (n, [t, e, s], i) => {
  const r = n.get(t);
  r === void 0 ? n.set(t, /* @__PURE__ */ new Set([[e, s]])) : Cn(r, [e, s], (o) => o[0] === e, i);
}, hi = (n) => "inputs" in n, Do = (n, t, e, s) => {
  if (hi(t)) {
    const i = t.inputs[s];
    return n.connect(i, e, 0), [i, e, 0];
  }
  return n.connect(t, e, s), [t, e, s];
}, Im = (n, t, e) => {
  for (const s of n)
    if (s[0] === t && s[1] === e)
      return n.delete(s), s;
  return null;
}, j1 = (n, t, e) => Jo(n, (s) => s[0] === t && s[1] === e), Fm = (n, t) => {
  if (!fr(n).delete(t))
    throw new Error("Missing the expected event listener.");
}, Rm = (n, t, e) => {
  const s = Ze(n, t), i = Jo(s, (r) => r[0] === e);
  return s.size === 0 && n.delete(t), i;
}, Oo = (n, t, e, s) => {
  hi(t) ? n.disconnect(t.inputs[s], e, 0) : n.disconnect(t, e, s);
}, vt = (n) => Ze(fc, n), rr = (n) => Ze(pc, n), Tn = (n) => Ol.has(n), fo = (n) => !Jn.has(n), Kd = (n, t) => new Promise((e) => {
  if (t !== null)
    e(!0);
  else {
    const s = n.createScriptProcessor(256, 1, 1), i = n.createGain(), r = n.createBuffer(1, 2, 44100), o = r.getChannelData(0);
    o[0] = 1, o[1] = 1;
    const a = n.createBufferSource();
    a.buffer = r, a.loop = !0, a.connect(s).connect(n.destination), a.connect(i), a.disconnect(i), s.onaudioprocess = (l) => {
      const c = l.inputBuffer.getChannelData(0);
      Array.prototype.some.call(c, (h) => h === 1) ? e(!0) : e(!1), a.stop(), s.onaudioprocess = null, a.disconnect(s), s.disconnect(n.destination);
    }, a.start();
  }
}), tl = (n, t) => {
  const e = /* @__PURE__ */ new Map();
  for (const s of n)
    for (const i of s) {
      const r = e.get(i);
      e.set(i, r === void 0 ? 1 : r + 1);
    }
  e.forEach((s, i) => t(i, s));
}, No = (n) => "context" in n, X1 = (n) => {
  const t = /* @__PURE__ */ new Map();
  n.connect = /* @__PURE__ */ ((e) => (s, i = 0, r = 0) => {
    const o = No(s) ? e(s, i, r) : e(s, i), a = t.get(s);
    return a === void 0 ? t.set(s, [{ input: r, output: i }]) : a.every((l) => l.input !== r || l.output !== i) && a.push({ input: r, output: i }), o;
  })(n.connect.bind(n)), n.disconnect = /* @__PURE__ */ ((e) => (s, i, r) => {
    if (e.apply(n), s === void 0)
      t.clear();
    else if (typeof s == "number")
      for (const [o, a] of t) {
        const l = a.filter((c) => c.output !== s);
        l.length === 0 ? t.delete(o) : t.set(o, l);
      }
    else if (t.has(s))
      if (i === void 0)
        t.delete(s);
      else {
        const o = t.get(s);
        if (o !== void 0) {
          const a = o.filter((l) => l.output !== i && (l.input !== r || r === void 0));
          a.length === 0 ? t.delete(s) : t.set(s, a);
        }
      }
    for (const [o, a] of t)
      a.forEach((l) => {
        No(o) ? n.connect(o, l.output, l.input) : n.connect(o, l.output);
      });
  })(n.disconnect);
}, Y1 = (n, t, e, s) => {
  const { activeInputs: i, passiveInputs: r } = mr(t), { outputs: o } = le(n), a = fr(n), l = (c) => {
    const h = vt(n), u = rr(t);
    if (c) {
      const d = Rm(r, n, e);
      Yd(i, n, d, !1), !s && !Tn(n) && h.connect(u, e);
    } else {
      const d = j1(i, n, e);
      Zd(r, d, !1), !s && !Tn(n) && h.disconnect(u, e);
    }
  };
  return Cn(o, [t, e], (c) => c[0] === t && c[1] === e, !0) ? (a.add(l), As(n) ? Yd(i, n, [e, l], !0) : Zd(r, [n, e, l], !0), !0) : !1;
}, Z1 = (n, t, e, s) => {
  const { activeInputs: i, passiveInputs: r } = le(t), o = Im(i[s], n, e);
  return o === null ? [Cm(r, n, e, s)[2], !1] : [o[2], !0];
}, K1 = (n, t, e) => {
  const { activeInputs: s, passiveInputs: i } = mr(t), r = Im(s, n, e);
  return r === null ? [Rm(i, n, e)[1], !1] : [r[2], !0];
}, gc = (n, t, e, s, i) => {
  const [r, o] = Z1(n, e, s, i);
  if (r !== null && (Fm(n, r), o && !t && !Tn(n) && Oo(vt(n), vt(e), s, i)), As(e)) {
    const { activeInputs: a } = le(e);
    Vl(e, a);
  }
}, yc = (n, t, e, s) => {
  const [i, r] = K1(n, e, s);
  i !== null && (Fm(n, i), r && !t && !Tn(n) && vt(n).disconnect(rr(e), s));
}, Q1 = (n, t) => {
  const e = le(n), s = [];
  for (const i of e.outputs)
    gr(i) ? gc(n, t, ...i) : yc(n, t, ...i), s.push(i[0]);
  return e.outputs.clear(), s;
}, J1 = (n, t, e) => {
  const s = le(n), i = [];
  for (const r of s.outputs)
    r[1] === e && (gr(r) ? gc(n, t, ...r) : yc(n, t, ...r), i.push(r[0]), s.outputs.delete(r));
  return i;
}, tw = (n, t, e, s, i) => {
  const r = le(n);
  return Array.from(r.outputs).filter((o) => o[0] === e && (s === void 0 || o[1] === s) && (i === void 0 || o[2] === i)).map((o) => (gr(o) ? gc(n, t, ...o) : yc(n, t, ...o), r.outputs.delete(o), o[0]));
}, ew = (n, t, e, s, i, r, o, a, l, c, h, u, d, f, p, g) => class extends c {
  constructor(y, x, v, _) {
    super(v), this._context = y, this._nativeAudioNode = v;
    const b = h(y);
    u(b) && e(Kd, () => Kd(b, g)) !== !0 && X1(v), fc.set(this, v), Mm.set(this, /* @__PURE__ */ new Set()), y.state !== "closed" && x && ti(this), n(this, _, v);
  }
  get channelCount() {
    return this._nativeAudioNode.channelCount;
  }
  set channelCount(y) {
    this._nativeAudioNode.channelCount = y;
  }
  get channelCountMode() {
    return this._nativeAudioNode.channelCountMode;
  }
  set channelCountMode(y) {
    this._nativeAudioNode.channelCountMode = y;
  }
  get channelInterpretation() {
    return this._nativeAudioNode.channelInterpretation;
  }
  set channelInterpretation(y) {
    this._nativeAudioNode.channelInterpretation = y;
  }
  get context() {
    return this._context;
  }
  get numberOfInputs() {
    return this._nativeAudioNode.numberOfInputs;
  }
  get numberOfOutputs() {
    return this._nativeAudioNode.numberOfOutputs;
  }
  // tslint:disable-next-line:invalid-void
  connect(y, x = 0, v = 0) {
    if (x < 0 || x >= this._nativeAudioNode.numberOfOutputs)
      throw i();
    const _ = h(this._context), b = p(_);
    if (d(y) || f(y))
      throw r();
    if (Ro(y)) {
      const T = vt(y);
      try {
        const C = Do(this._nativeAudioNode, T, x, v), M = fo(this);
        (b || M) && this._nativeAudioNode.disconnect(...C), this.context.state !== "closed" && !M && fo(y) && ti(y);
      } catch (C) {
        throw C.code === 12 ? r() : C;
      }
      if (t(this, y, x, v, b)) {
        const C = l([this], y);
        tl(C, s(b));
      }
      return y;
    }
    const w = rr(y);
    if (w.name === "playbackRate" && w.maxValue === 1024)
      throw o();
    try {
      this._nativeAudioNode.connect(w, x), (b || fo(this)) && this._nativeAudioNode.disconnect(w, x);
    } catch (T) {
      throw T.code === 12 ? r() : T;
    }
    if (Y1(this, y, x, b)) {
      const T = l([this], y);
      tl(T, s(b));
    }
  }
  disconnect(y, x, v) {
    let _;
    const b = h(this._context), w = p(b);
    if (y === void 0)
      _ = Q1(this, w);
    else if (typeof y == "number") {
      if (y < 0 || y >= this.numberOfOutputs)
        throw i();
      _ = J1(this, w, y);
    } else {
      if (x !== void 0 && (x < 0 || x >= this.numberOfOutputs) || Ro(y) && v !== void 0 && (v < 0 || v >= y.numberOfInputs))
        throw i();
      if (_ = tw(this, w, y, x, v), _.length === 0)
        throw r();
    }
    for (const S of _) {
      const T = l([this], S);
      tl(T, a);
    }
  }
}, sw = (n, t, e, s, i, r, o, a, l, c, h, u, d) => (f, p, g, m = null, y = null) => {
  const x = g.value, v = new d1(x), _ = p ? s(v) : null, b = {
    get defaultValue() {
      return x;
    },
    get maxValue() {
      return m === null ? g.maxValue : m;
    },
    get minValue() {
      return y === null ? g.minValue : y;
    },
    get value() {
      return g.value;
    },
    set value(w) {
      g.value = w, b.setValueAtTime(w, f.context.currentTime);
    },
    cancelAndHoldAtTime(w) {
      if (typeof g.cancelAndHoldAtTime == "function")
        _ === null && v.flush(f.context.currentTime), v.add(i(w)), g.cancelAndHoldAtTime(w);
      else {
        const S = Array.from(v).pop();
        _ === null && v.flush(f.context.currentTime), v.add(i(w));
        const T = Array.from(v).pop();
        g.cancelScheduledValues(w), S !== T && T !== void 0 && (T.type === "exponentialRampToValue" ? g.exponentialRampToValueAtTime(T.value, T.endTime) : T.type === "linearRampToValue" ? g.linearRampToValueAtTime(T.value, T.endTime) : T.type === "setValue" ? g.setValueAtTime(T.value, T.startTime) : T.type === "setValueCurve" && g.setValueCurveAtTime(T.values, T.startTime, T.duration));
      }
      return b;
    },
    cancelScheduledValues(w) {
      return _ === null && v.flush(f.context.currentTime), v.add(r(w)), g.cancelScheduledValues(w), b;
    },
    exponentialRampToValueAtTime(w, S) {
      if (w === 0)
        throw new RangeError();
      if (!Number.isFinite(S) || S < 0)
        throw new RangeError();
      const T = f.context.currentTime;
      return _ === null && v.flush(T), Array.from(v).length === 0 && (v.add(c(x, T)), g.setValueAtTime(x, T)), v.add(o(w, S)), g.exponentialRampToValueAtTime(w, S), b;
    },
    linearRampToValueAtTime(w, S) {
      const T = f.context.currentTime;
      return _ === null && v.flush(T), Array.from(v).length === 0 && (v.add(c(x, T)), g.setValueAtTime(x, T)), v.add(a(w, S)), g.linearRampToValueAtTime(w, S), b;
    },
    setTargetAtTime(w, S, T) {
      return _ === null && v.flush(f.context.currentTime), v.add(l(w, S, T)), g.setTargetAtTime(w, S, T), b;
    },
    setValueAtTime(w, S) {
      return _ === null && v.flush(f.context.currentTime), v.add(c(w, S)), g.setValueAtTime(w, S), b;
    },
    setValueCurveAtTime(w, S, T) {
      const k = w instanceof Float32Array ? w : new Float32Array(w);
      if (u !== null && u.name === "webkitAudioContext") {
        const C = S + T, M = f.context.sampleRate, A = Math.ceil(S * M), I = Math.floor(C * M), F = I - A, R = new Float32Array(F);
        for (let P = 0; P < F; P += 1) {
          const N = (k.length - 1) / T * ((A + P) / M - S), D = Math.floor(N), z = Math.ceil(N);
          R[P] = D === z ? k[D] : (1 - (N - D)) * k[D] + (1 - (z - N)) * k[z];
        }
        _ === null && v.flush(f.context.currentTime), v.add(h(R, S, T)), g.setValueCurveAtTime(R, S, T);
        const E = I / M;
        E < C && d(b, R[R.length - 1], E), d(b, k[k.length - 1], C);
      } else
        _ === null && v.flush(f.context.currentTime), v.add(h(k, S, T)), g.setValueCurveAtTime(k, S, T);
      return b;
    }
  };
  return e.set(b, g), t.set(b, f), n(b, _), b;
}, nw = (n) => ({
  replay(t) {
    for (const e of n)
      if (e.type === "exponentialRampToValue") {
        const { endTime: s, value: i } = e;
        t.exponentialRampToValueAtTime(i, s);
      } else if (e.type === "linearRampToValue") {
        const { endTime: s, value: i } = e;
        t.linearRampToValueAtTime(i, s);
      } else if (e.type === "setTarget") {
        const { startTime: s, target: i, timeConstant: r } = e;
        t.setTargetAtTime(i, s, r);
      } else if (e.type === "setValue") {
        const { startTime: s, value: i } = e;
        t.setValueAtTime(i, s);
      } else if (e.type === "setValueCurve") {
        const { duration: s, startTime: i, values: r } = e;
        t.setValueCurveAtTime(r, i, s);
      } else
        throw new Error("Can't apply an unknown automation.");
  }
});
class Dm {
  constructor(t) {
    this._map = new Map(t);
  }
  get size() {
    return this._map.size;
  }
  entries() {
    return this._map.entries();
  }
  forEach(t, e = null) {
    return this._map.forEach((s, i) => t.call(e, s, i, this));
  }
  get(t) {
    return this._map.get(t);
  }
  has(t) {
    return this._map.has(t);
  }
  keys() {
    return this._map.keys();
  }
  values() {
    return this._map.values();
  }
}
const iw = {
  channelCount: 2,
  // Bug #61: The channelCountMode should be 'max' according to the spec but is set to 'explicit' to achieve consistent behavior.
  channelCountMode: "explicit",
  channelInterpretation: "speakers",
  numberOfInputs: 1,
  numberOfOutputs: 1,
  parameterData: {},
  processorOptions: {}
}, rw = (n, t, e, s, i, r, o, a, l, c, h, u, d, f) => class extends t {
  constructor(g, m, y) {
    var x;
    const v = a(g), _ = l(v), b = h({ ...iw, ...y });
    d(b);
    const w = Nl.get(v), S = w?.get(m), T = _ || v.state !== "closed" ? v : (x = o(v)) !== null && x !== void 0 ? x : v, k = i(T, _ ? null : g.baseLatency, c, m, S, b), C = _ ? s(m, b, S) : null;
    super(g, !0, k, C);
    const M = [];
    k.parameters.forEach((I, F) => {
      const R = e(this, _, I);
      M.push([F, R]);
    }), this._nativeAudioWorkletNode = k, this._onprocessorerror = null, this._parameters = new Dm(M), _ && n(v, this);
    const { activeInputs: A } = r(this);
    u(k, A);
  }
  get onprocessorerror() {
    return this._onprocessorerror;
  }
  set onprocessorerror(g) {
    const m = typeof g == "function" ? f(this, g) : null;
    this._nativeAudioWorkletNode.onprocessorerror = m;
    const y = this._nativeAudioWorkletNode.onprocessorerror;
    this._onprocessorerror = y !== null && y === m ? g : y;
  }
  get parameters() {
    return this._parameters === null ? this._nativeAudioWorkletNode.parameters : this._parameters;
  }
  get port() {
    return this._nativeAudioWorkletNode.port;
  }
};
function Lo(n, t, e, s, i) {
  if (typeof n.copyFromChannel == "function")
    t[e].byteLength === 0 && (t[e] = new Float32Array(128)), n.copyFromChannel(t[e], s, i);
  else {
    const r = n.getChannelData(s);
    if (t[e].byteLength === 0)
      t[e] = r.slice(i, i + 128);
    else {
      const o = new Float32Array(r.buffer, i * Float32Array.BYTES_PER_ELEMENT, 128);
      t[e].set(o);
    }
  }
}
const Om = (n, t, e, s, i) => {
  typeof n.copyToChannel == "function" ? t[e].byteLength !== 0 && n.copyToChannel(t[e], s, i) : t[e].byteLength !== 0 && n.getChannelData(s).set(t[e], i);
}, Vo = (n, t) => {
  const e = [];
  for (let s = 0; s < n; s += 1) {
    const i = [], r = typeof t == "number" ? t : t[s];
    for (let o = 0; o < r; o += 1)
      i.push(new Float32Array(128));
    e.push(i);
  }
  return e;
}, ow = (n, t) => {
  const e = Ze(Ll, n), s = vt(t);
  return Ze(e, s);
}, aw = async (n, t, e, s, i, r, o) => {
  const a = t === null ? Math.ceil(n.context.length / 128) * 128 : t.length, l = s.channelCount * s.numberOfInputs, c = i.reduce((m, y) => m + y, 0), h = c === 0 ? null : e.createBuffer(c, a, e.sampleRate);
  if (r === void 0)
    throw new Error("Missing the processor constructor.");
  const u = le(n), d = await ow(e, n), f = Vo(s.numberOfInputs, s.channelCount), p = Vo(s.numberOfOutputs, i), g = Array.from(n.parameters.keys()).reduce((m, y) => ({ ...m, [y]: new Float32Array(128) }), {});
  for (let m = 0; m < a; m += 128) {
    if (s.numberOfInputs > 0 && t !== null)
      for (let y = 0; y < s.numberOfInputs; y += 1)
        for (let x = 0; x < s.channelCount; x += 1)
          Lo(t, f[y], x, x, m);
    r.parameterDescriptors !== void 0 && t !== null && r.parameterDescriptors.forEach(({ name: y }, x) => {
      Lo(t, g, y, l + x, m);
    });
    for (let y = 0; y < s.numberOfInputs; y += 1)
      for (let x = 0; x < i[y]; x += 1)
        p[y][x].byteLength === 0 && (p[y][x] = new Float32Array(128));
    try {
      const y = f.map((v, _) => u.activeInputs[_].size === 0 ? [] : v), x = o(m / e.sampleRate, e.sampleRate, () => d.process(y, p, g));
      if (h !== null)
        for (let v = 0, _ = 0; v < s.numberOfOutputs; v += 1) {
          for (let b = 0; b < i[v]; b += 1)
            Om(h, p[v], b, _ + b, m);
          _ += i[v];
        }
      if (!x)
        break;
    } catch (y) {
      n.dispatchEvent(new ErrorEvent("processorerror", {
        colno: y.colno,
        filename: y.filename,
        lineno: y.lineno,
        message: y.message
      }));
      break;
    }
  }
  return h;
}, lw = (n, t, e, s, i, r, o, a, l, c, h, u, d, f, p, g) => (m, y, x) => {
  const v = /* @__PURE__ */ new WeakMap();
  let _ = null;
  const b = async (w, S) => {
    let T = h(w), k = null;
    const C = ne(T, S), M = Array.isArray(y.outputChannelCount) ? y.outputChannelCount : Array.from(y.outputChannelCount);
    if (u === null) {
      const A = M.reduce((E, P) => E + P, 0), I = i(S, {
        channelCount: Math.max(1, A),
        channelCountMode: "explicit",
        channelInterpretation: "discrete",
        numberOfOutputs: Math.max(1, A)
      }), F = [];
      for (let E = 0; E < w.numberOfOutputs; E += 1)
        F.push(s(S, {
          channelCount: 1,
          channelCountMode: "explicit",
          channelInterpretation: "speakers",
          numberOfInputs: M[E]
        }));
      const R = o(S, {
        channelCount: y.channelCount,
        channelCountMode: y.channelCountMode,
        channelInterpretation: y.channelInterpretation,
        gain: 1
      });
      R.connect = t.bind(null, F), R.disconnect = l.bind(null, F), k = [I, F, R];
    } else C || (T = new u(S, m));
    if (v.set(S, k === null ? T : k[2]), k !== null) {
      if (_ === null) {
        if (x === void 0)
          throw new Error("Missing the processor constructor.");
        if (d === null)
          throw new Error("Missing the native OfflineAudioContext constructor.");
        const P = w.channelCount * w.numberOfInputs, N = x.parameterDescriptors === void 0 ? 0 : x.parameterDescriptors.length, D = P + N;
        _ = aw(w, D === 0 ? null : await (async () => {
          const O = new d(
            D,
            // Ceil the length to the next full render quantum.
            // Bug #17: Safari does not yet expose the length.
            Math.ceil(w.context.length / 128) * 128,
            S.sampleRate
          ), V = [], G = [];
          for (let W = 0; W < y.numberOfInputs; W += 1)
            V.push(o(O, {
              channelCount: y.channelCount,
              channelCountMode: y.channelCountMode,
              channelInterpretation: y.channelInterpretation,
              gain: 1
            })), G.push(i(O, {
              channelCount: y.channelCount,
              channelCountMode: "explicit",
              channelInterpretation: "discrete",
              numberOfOutputs: y.channelCount
            }));
          const H = await Promise.all(Array.from(w.parameters.values()).map(async (W) => {
            const K = r(O, {
              channelCount: 1,
              channelCountMode: "explicit",
              channelInterpretation: "discrete",
              offset: W.value
            });
            return await f(O, W, K.offset), K;
          })), q = s(O, {
            channelCount: 1,
            channelCountMode: "explicit",
            channelInterpretation: "speakers",
            numberOfInputs: Math.max(1, P + N)
          });
          for (let W = 0; W < y.numberOfInputs; W += 1) {
            V[W].connect(G[W]);
            for (let K = 0; K < y.channelCount; K += 1)
              G[W].connect(q, K, W * y.channelCount + K);
          }
          for (const [W, K] of H.entries())
            K.connect(q, 0, P + W), K.start(0);
          return q.connect(O.destination), await Promise.all(V.map((W) => p(w, O, W))), g(O);
        })(), S, y, M, x, c);
      }
      const A = await _, I = e(S, {
        buffer: null,
        channelCount: 2,
        channelCountMode: "max",
        channelInterpretation: "speakers",
        loop: !1,
        loopEnd: 0,
        loopStart: 0,
        playbackRate: 1
      }), [F, R, E] = k;
      A !== null && (I.buffer = A, I.start(0)), I.connect(F);
      for (let P = 0, N = 0; P < w.numberOfOutputs; P += 1) {
        const D = R[P];
        for (let z = 0; z < M[P]; z += 1)
          F.connect(D, N + z, z);
        N += M[P];
      }
      return E;
    }
    if (C)
      for (const [A, I] of w.parameters.entries())
        await n(
          S,
          I,
          // @todo The definition that TypeScript uses of the AudioParamMap is lacking many methods.
          T.parameters.get(A)
        );
    else
      for (const [A, I] of w.parameters.entries())
        await f(
          S,
          I,
          // @todo The definition that TypeScript uses of the AudioParamMap is lacking many methods.
          T.parameters.get(A)
        );
    return await p(w, S, T), T;
  };
  return {
    render(w, S) {
      a(S, w);
      const T = v.get(S);
      return T !== void 0 ? Promise.resolve(T) : b(w, S);
    }
  };
}, cw = (n, t, e, s, i, r, o, a, l, c, h, u, d, f, p, g, m, y, x, v) => class extends p {
  constructor(b, w) {
    super(b, w), this._nativeContext = b, this._audioWorklet = n === void 0 ? void 0 : {
      addModule: (S, T) => n(this, S, T)
    };
  }
  get audioWorklet() {
    return this._audioWorklet;
  }
  createAnalyser() {
    return new t(this);
  }
  createBiquadFilter() {
    return new i(this);
  }
  createBuffer(b, w, S) {
    return new e({ length: w, numberOfChannels: b, sampleRate: S });
  }
  createBufferSource() {
    return new s(this);
  }
  createChannelMerger(b = 6) {
    return new r(this, { numberOfInputs: b });
  }
  createChannelSplitter(b = 6) {
    return new o(this, { numberOfOutputs: b });
  }
  createConstantSource() {
    return new a(this);
  }
  createConvolver() {
    return new l(this);
  }
  createDelay(b = 1) {
    return new h(this, { maxDelayTime: b });
  }
  createDynamicsCompressor() {
    return new u(this);
  }
  createGain() {
    return new d(this);
  }
  createIIRFilter(b, w) {
    return new f(this, { feedback: w, feedforward: b });
  }
  createOscillator() {
    return new g(this);
  }
  createPanner() {
    return new m(this);
  }
  createPeriodicWave(b, w, S = { disableNormalization: !1 }) {
    return new y(this, { ...S, imag: w, real: b });
  }
  createStereoPanner() {
    return new x(this);
  }
  createWaveShaper() {
    return new v(this);
  }
  decodeAudioData(b, w, S) {
    return c(this._nativeContext, b).then((T) => (typeof w == "function" && w(T), T), (T) => {
      throw typeof S == "function" && S(T), T;
    });
  }
}, hw = {
  Q: 1,
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  detune: 0,
  frequency: 350,
  gain: 0,
  type: "lowpass"
}, uw = (n, t, e, s, i, r, o, a) => class extends n {
  constructor(c, h) {
    const u = r(c), d = { ...hw, ...h }, f = i(u, d), p = o(u), g = p ? e() : null;
    super(c, !1, f, g), this._Q = t(this, p, f.Q, re, ye), this._detune = t(this, p, f.detune, 1200 * Math.log2(re), -1200 * Math.log2(re)), this._frequency = t(this, p, f.frequency, c.sampleRate / 2, 0), this._gain = t(this, p, f.gain, 40 * Math.log10(re), ye), this._nativeBiquadFilterNode = f, a(this, 1);
  }
  get detune() {
    return this._detune;
  }
  get frequency() {
    return this._frequency;
  }
  get gain() {
    return this._gain;
  }
  get Q() {
    return this._Q;
  }
  get type() {
    return this._nativeBiquadFilterNode.type;
  }
  set type(c) {
    this._nativeBiquadFilterNode.type = c;
  }
  getFrequencyResponse(c, h, u) {
    try {
      this._nativeBiquadFilterNode.getFrequencyResponse(c, h, u);
    } catch (d) {
      throw d.code === 11 ? s() : d;
    }
    if (c.length !== h.length || h.length !== u.length)
      throw s();
  }
}, dw = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap(), o = async (a, l) => {
    let c = e(a);
    const h = ne(c, l);
    if (!h) {
      const u = {
        Q: c.Q.value,
        channelCount: c.channelCount,
        channelCountMode: c.channelCountMode,
        channelInterpretation: c.channelInterpretation,
        detune: c.detune.value,
        frequency: c.frequency.value,
        gain: c.gain.value,
        type: c.type
      };
      c = t(l, u);
    }
    return r.set(l, c), h ? (await n(l, a.Q, c.Q), await n(l, a.detune, c.detune), await n(l, a.frequency, c.frequency), await n(l, a.gain, c.gain)) : (await s(l, a.Q, c.Q), await s(l, a.detune, c.detune), await s(l, a.frequency, c.frequency), await s(l, a.gain, c.gain)), await i(a, l, c), c;
  };
  return {
    render(a, l) {
      const c = r.get(l);
      return c !== void 0 ? Promise.resolve(c) : o(a, l);
    }
  };
}, fw = (n, t) => (e, s) => {
  const i = t.get(e);
  if (i !== void 0)
    return i;
  const r = n.get(e);
  if (r !== void 0)
    return r;
  try {
    const o = s();
    return o instanceof Promise ? (n.set(e, o), o.catch(() => !1).then((a) => (n.delete(e), t.set(e, a), a))) : (t.set(e, o), o);
  } catch {
    return t.set(e, !1), !1;
  }
}, pw = {
  channelCount: 1,
  channelCountMode: "explicit",
  channelInterpretation: "speakers",
  numberOfInputs: 6
}, mw = (n, t, e, s, i) => class extends n {
  constructor(o, a) {
    const l = s(o), c = { ...pw, ...a }, h = e(l, c), u = i(l) ? t() : null;
    super(o, !1, h, u);
  }
}, gw = (n, t, e) => () => {
  const s = /* @__PURE__ */ new WeakMap(), i = async (r, o) => {
    let a = t(r);
    if (!ne(a, o)) {
      const c = {
        channelCount: a.channelCount,
        channelCountMode: a.channelCountMode,
        channelInterpretation: a.channelInterpretation,
        numberOfInputs: a.numberOfInputs
      };
      a = n(o, c);
    }
    return s.set(o, a), await e(r, o, a), a;
  };
  return {
    render(r, o) {
      const a = s.get(o);
      return a !== void 0 ? Promise.resolve(a) : i(r, o);
    }
  };
}, yw = {
  channelCount: 6,
  channelCountMode: "explicit",
  channelInterpretation: "discrete",
  numberOfOutputs: 6
}, xw = (n, t, e, s, i, r) => class extends n {
  constructor(a, l) {
    const c = s(a), h = r({ ...yw, ...l }), u = e(c, h), d = i(c) ? t() : null;
    super(a, !1, u, d);
  }
}, _w = (n, t, e) => () => {
  const s = /* @__PURE__ */ new WeakMap(), i = async (r, o) => {
    let a = t(r);
    if (!ne(a, o)) {
      const c = {
        channelCount: a.channelCount,
        channelCountMode: a.channelCountMode,
        channelInterpretation: a.channelInterpretation,
        numberOfOutputs: a.numberOfOutputs
      };
      a = n(o, c);
    }
    return s.set(o, a), await e(r, o, a), a;
  };
  return {
    render(r, o) {
      const a = s.get(o);
      return a !== void 0 ? Promise.resolve(a) : i(r, o);
    }
  };
}, vw = (n) => (t, e, s) => n(e, t, s), bw = (n) => (t, e, s = 0, i = 0) => {
  const r = t[s];
  if (r === void 0)
    throw n();
  return No(e) ? r.connect(e, 0, i) : r.connect(e, 0);
}, ww = (n) => (t, e) => {
  const s = n(t, {
    buffer: null,
    channelCount: 2,
    channelCountMode: "max",
    channelInterpretation: "speakers",
    loop: !1,
    loopEnd: 0,
    loopStart: 0,
    playbackRate: 1
  }), i = t.createBuffer(1, 2, 44100);
  return s.buffer = i, s.loop = !0, s.connect(e), s.start(), () => {
    s.stop(), s.disconnect(e);
  };
}, Sw = {
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  offset: 1
}, Tw = (n, t, e, s, i, r, o) => class extends n {
  constructor(l, c) {
    const h = i(l), u = { ...Sw, ...c }, d = s(h, u), f = r(h), p = f ? e() : null;
    super(l, !1, d, p), this._constantSourceNodeRenderer = p, this._nativeConstantSourceNode = d, this._offset = t(this, f, d.offset, re, ye), this._onended = null;
  }
  get offset() {
    return this._offset;
  }
  get onended() {
    return this._onended;
  }
  set onended(l) {
    const c = typeof l == "function" ? o(this, l) : null;
    this._nativeConstantSourceNode.onended = c;
    const h = this._nativeConstantSourceNode.onended;
    this._onended = h !== null && h === c ? l : h;
  }
  start(l = 0) {
    if (this._nativeConstantSourceNode.start(l), this._constantSourceNodeRenderer !== null && (this._constantSourceNodeRenderer.start = l), this.context.state !== "closed") {
      ti(this);
      const c = () => {
        this._nativeConstantSourceNode.removeEventListener("ended", c), As(this) && pr(this);
      };
      this._nativeConstantSourceNode.addEventListener("ended", c);
    }
  }
  stop(l = 0) {
    this._nativeConstantSourceNode.stop(l), this._constantSourceNodeRenderer !== null && (this._constantSourceNodeRenderer.stop = l);
  }
}, Mw = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap();
  let o = null, a = null;
  const l = async (c, h) => {
    let u = e(c);
    const d = ne(u, h);
    if (!d) {
      const f = {
        channelCount: u.channelCount,
        channelCountMode: u.channelCountMode,
        channelInterpretation: u.channelInterpretation,
        offset: u.offset.value
      };
      u = t(h, f), o !== null && u.start(o), a !== null && u.stop(a);
    }
    return r.set(h, u), d ? await n(h, c.offset, u.offset) : await s(h, c.offset, u.offset), await i(c, h, u), u;
  };
  return {
    set start(c) {
      o = c;
    },
    set stop(c) {
      a = c;
    },
    render(c, h) {
      const u = r.get(h);
      return u !== void 0 ? Promise.resolve(u) : l(c, h);
    }
  };
}, kw = (n) => (t) => (n[0] = t, n[0]), Cw = {
  buffer: null,
  channelCount: 2,
  channelCountMode: "clamped-max",
  channelInterpretation: "speakers",
  disableNormalization: !1
}, Aw = (n, t, e, s, i, r) => class extends n {
  constructor(a, l) {
    const c = s(a), h = { ...Cw, ...l }, u = e(c, h), f = i(c) ? t() : null;
    super(a, !1, u, f), this._isBufferNullified = !1, this._nativeConvolverNode = u, h.buffer !== null && r(this, h.buffer.duration);
  }
  get buffer() {
    return this._isBufferNullified ? null : this._nativeConvolverNode.buffer;
  }
  set buffer(a) {
    if (this._nativeConvolverNode.buffer = a, a === null && this._nativeConvolverNode.buffer !== null) {
      const l = this._nativeConvolverNode.context;
      this._nativeConvolverNode.buffer = l.createBuffer(1, 1, l.sampleRate), this._isBufferNullified = !0, r(this, 0);
    } else
      this._isBufferNullified = !1, r(this, this._nativeConvolverNode.buffer === null ? 0 : this._nativeConvolverNode.buffer.duration);
  }
  get normalize() {
    return this._nativeConvolverNode.normalize;
  }
  set normalize(a) {
    this._nativeConvolverNode.normalize = a;
  }
}, Ew = (n, t, e) => () => {
  const s = /* @__PURE__ */ new WeakMap(), i = async (r, o) => {
    let a = t(r);
    if (!ne(a, o)) {
      const c = {
        buffer: a.buffer,
        channelCount: a.channelCount,
        channelCountMode: a.channelCountMode,
        channelInterpretation: a.channelInterpretation,
        disableNormalization: !a.normalize
      };
      a = n(o, c);
    }
    return s.set(o, a), hi(a) ? await e(r, o, a.inputs[0]) : await e(r, o, a), a;
  };
  return {
    render(r, o) {
      const a = s.get(o);
      return a !== void 0 ? Promise.resolve(a) : i(r, o);
    }
  };
}, Pw = (n, t) => (e, s, i) => {
  if (t === null)
    throw new Error("Missing the native OfflineAudioContext constructor.");
  try {
    return new t(e, s, i);
  } catch (r) {
    throw r.name === "SyntaxError" ? n() : r;
  }
}, Iw = () => new DOMException("", "DataCloneError"), Qd = (n) => {
  const { port1: t, port2: e } = new MessageChannel();
  return new Promise((s) => {
    const i = () => {
      e.onmessage = null, t.close(), e.close(), s();
    };
    e.onmessage = () => i();
    try {
      t.postMessage(n, [n]);
    } catch {
    } finally {
      i();
    }
  });
}, Fw = (n, t, e, s, i, r, o, a, l, c, h) => (u, d) => {
  const f = o(u) ? u : r(u);
  if (i.has(d)) {
    const p = e();
    return Promise.reject(p);
  }
  try {
    i.add(d);
  } catch {
  }
  return t(l, () => l(f)) ? f.decodeAudioData(d).then((p) => (Qd(d).catch(() => {
  }), t(a, () => a(p)) || h(p), n.add(p), p)) : new Promise((p, g) => {
    const m = async () => {
      try {
        await Qd(d);
      } catch {
      }
    }, y = (x) => {
      g(x), m();
    };
    try {
      f.decodeAudioData(d, (x) => {
        typeof x.copyFromChannel != "function" && (c(x), mc(x)), n.add(x), m().then(() => p(x));
      }, (x) => {
        y(x === null ? s() : x);
      });
    } catch (x) {
      y(x);
    }
  });
}, Rw = (n, t, e, s, i, r, o, a) => (l, c) => {
  const h = t.get(l);
  if (h === void 0)
    throw new Error("Missing the expected cycle count.");
  const u = r(l.context), d = a(u);
  if (h === c) {
    if (t.delete(l), !d && o(l)) {
      const f = s(l), { outputs: p } = e(l);
      for (const g of p)
        if (gr(g)) {
          const m = s(g[0]);
          n(f, m, g[1], g[2]);
        } else {
          const m = i(g[0]);
          f.connect(m, g[1]);
        }
    }
  } else
    t.set(l, h - c);
}, Dw = {
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  delayTime: 0,
  maxDelayTime: 1
}, Ow = (n, t, e, s, i, r, o) => class extends n {
  constructor(l, c) {
    const h = i(l), u = { ...Dw, ...c }, d = s(h, u), f = r(h), p = f ? e(u.maxDelayTime) : null;
    super(l, !1, d, p), this._delayTime = t(this, f, d.delayTime), o(this, u.maxDelayTime);
  }
  get delayTime() {
    return this._delayTime;
  }
}, Nw = (n, t, e, s, i) => (r) => {
  const o = /* @__PURE__ */ new WeakMap(), a = async (l, c) => {
    let h = e(l);
    const u = ne(h, c);
    if (!u) {
      const d = {
        channelCount: h.channelCount,
        channelCountMode: h.channelCountMode,
        channelInterpretation: h.channelInterpretation,
        delayTime: h.delayTime.value,
        maxDelayTime: r
      };
      h = t(c, d);
    }
    return o.set(c, h), u ? await n(c, l.delayTime, h.delayTime) : await s(c, l.delayTime, h.delayTime), await i(l, c, h), h;
  };
  return {
    render(l, c) {
      const h = o.get(c);
      return h !== void 0 ? Promise.resolve(h) : a(l, c);
    }
  };
}, Lw = (n) => (t, e, s, i) => n(t[i], (r) => r[0] === e && r[1] === s), Vw = (n) => (t, e) => {
  n(t).delete(e);
}, Bw = (n) => "delayTime" in n, zw = (n, t, e) => function s(i, r) {
  const o = Ro(r) ? r : e(n, r);
  if (Bw(o))
    return [];
  if (i[0] === o)
    return [i];
  if (i.includes(o))
    return [];
  const { outputs: a } = t(o);
  return Array.from(a).map((l) => s([...i, o], l[0])).reduce((l, c) => l.concat(c), []);
}, so = (n, t, e) => {
  const s = t[e];
  if (s === void 0)
    throw n();
  return s;
}, qw = (n) => (t, e = void 0, s = void 0, i = 0) => e === void 0 ? t.forEach((r) => r.disconnect()) : typeof e == "number" ? so(n, t, e).disconnect() : No(e) ? s === void 0 ? t.forEach((r) => r.disconnect(e)) : i === void 0 ? so(n, t, s).disconnect(e, 0) : so(n, t, s).disconnect(e, 0, i) : s === void 0 ? t.forEach((r) => r.disconnect(e)) : so(n, t, s).disconnect(e, 0), Uw = {
  attack: 3e-3,
  channelCount: 2,
  channelCountMode: "clamped-max",
  channelInterpretation: "speakers",
  knee: 30,
  ratio: 12,
  release: 0.25,
  threshold: -24
}, Gw = (n, t, e, s, i, r, o, a) => class extends n {
  constructor(c, h) {
    const u = r(c), d = { ...Uw, ...h }, f = s(u, d), p = o(u), g = p ? e() : null;
    super(c, !1, f, g), this._attack = t(this, p, f.attack), this._knee = t(this, p, f.knee), this._nativeDynamicsCompressorNode = f, this._ratio = t(this, p, f.ratio), this._release = t(this, p, f.release), this._threshold = t(this, p, f.threshold), a(this, 6e-3);
  }
  get attack() {
    return this._attack;
  }
  // Bug #108: Safari allows a channelCount of three and above which is why the getter and setter needs to be overwritten here.
  get channelCount() {
    return this._nativeDynamicsCompressorNode.channelCount;
  }
  set channelCount(c) {
    const h = this._nativeDynamicsCompressorNode.channelCount;
    if (this._nativeDynamicsCompressorNode.channelCount = c, c > 2)
      throw this._nativeDynamicsCompressorNode.channelCount = h, i();
  }
  /*
   * Bug #109: Only Chrome and Firefox disallow a channelCountMode of 'max' yet which is why the getter and setter needs to be
   * overwritten here.
   */
  get channelCountMode() {
    return this._nativeDynamicsCompressorNode.channelCountMode;
  }
  set channelCountMode(c) {
    const h = this._nativeDynamicsCompressorNode.channelCountMode;
    if (this._nativeDynamicsCompressorNode.channelCountMode = c, c === "max")
      throw this._nativeDynamicsCompressorNode.channelCountMode = h, i();
  }
  get knee() {
    return this._knee;
  }
  get ratio() {
    return this._ratio;
  }
  get reduction() {
    return typeof this._nativeDynamicsCompressorNode.reduction.value == "number" ? this._nativeDynamicsCompressorNode.reduction.value : this._nativeDynamicsCompressorNode.reduction;
  }
  get release() {
    return this._release;
  }
  get threshold() {
    return this._threshold;
  }
}, Ww = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap(), o = async (a, l) => {
    let c = e(a);
    const h = ne(c, l);
    if (!h) {
      const u = {
        attack: c.attack.value,
        channelCount: c.channelCount,
        channelCountMode: c.channelCountMode,
        channelInterpretation: c.channelInterpretation,
        knee: c.knee.value,
        ratio: c.ratio.value,
        release: c.release.value,
        threshold: c.threshold.value
      };
      c = t(l, u);
    }
    return r.set(l, c), h ? (await n(l, a.attack, c.attack), await n(l, a.knee, c.knee), await n(l, a.ratio, c.ratio), await n(l, a.release, c.release), await n(l, a.threshold, c.threshold)) : (await s(l, a.attack, c.attack), await s(l, a.knee, c.knee), await s(l, a.ratio, c.ratio), await s(l, a.release, c.release), await s(l, a.threshold, c.threshold)), await i(a, l, c), c;
  };
  return {
    render(a, l) {
      const c = r.get(l);
      return c !== void 0 ? Promise.resolve(c) : o(a, l);
    }
  };
}, $w = () => new DOMException("", "EncodingError"), Hw = (n) => (t) => new Promise((e, s) => {
  if (n === null) {
    s(new SyntaxError());
    return;
  }
  const i = n.document.head;
  if (i === null)
    s(new SyntaxError());
  else {
    const r = n.document.createElement("script"), o = new Blob([t], { type: "application/javascript" }), a = URL.createObjectURL(o), l = n.onerror, c = () => {
      n.onerror = l, URL.revokeObjectURL(a);
    };
    n.onerror = (h, u, d, f, p) => {
      if (u === a || u === n.location.href && d === 1 && f === 1)
        return c(), s(p), !1;
      if (l !== null)
        return l(h, u, d, f, p);
    }, r.onerror = () => {
      c(), s(new SyntaxError());
    }, r.onload = () => {
      c(), e();
    }, r.src = a, r.type = "module", i.appendChild(r);
  }
}), jw = (n) => class {
  constructor(e) {
    this._nativeEventTarget = e, this._listeners = /* @__PURE__ */ new WeakMap();
  }
  addEventListener(e, s, i) {
    if (s !== null) {
      let r = this._listeners.get(s);
      r === void 0 && (r = n(this, s), typeof s == "function" && this._listeners.set(s, r)), this._nativeEventTarget.addEventListener(e, r, i);
    }
  }
  dispatchEvent(e) {
    return this._nativeEventTarget.dispatchEvent(e);
  }
  removeEventListener(e, s, i) {
    const r = s === null ? void 0 : this._listeners.get(s);
    this._nativeEventTarget.removeEventListener(e, r === void 0 ? null : r, i);
  }
}, Xw = (n) => (t, e, s) => {
  Object.defineProperties(n, {
    currentFrame: {
      configurable: !0,
      get() {
        return Math.round(t * e);
      }
    },
    currentTime: {
      configurable: !0,
      get() {
        return t;
      }
    }
  });
  try {
    return s();
  } finally {
    n !== null && (delete n.currentFrame, delete n.currentTime);
  }
}, Yw = (n) => async (t) => {
  try {
    const e = await fetch(t);
    if (e.ok)
      return [await e.text(), e.url];
  } catch {
  }
  throw n();
}, Zw = {
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  gain: 1
}, Kw = (n, t, e, s, i, r) => class extends n {
  constructor(a, l) {
    const c = i(a), h = { ...Zw, ...l }, u = s(c, h), d = r(c), f = d ? e() : null;
    super(a, !1, u, f), this._gain = t(this, d, u.gain, re, ye);
  }
  get gain() {
    return this._gain;
  }
}, Qw = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap(), o = async (a, l) => {
    let c = e(a);
    const h = ne(c, l);
    if (!h) {
      const u = {
        channelCount: c.channelCount,
        channelCountMode: c.channelCountMode,
        channelInterpretation: c.channelInterpretation,
        gain: c.gain.value
      };
      c = t(l, u);
    }
    return r.set(l, c), h ? await n(l, a.gain, c.gain) : await s(l, a.gain, c.gain), await i(a, l, c), c;
  };
  return {
    render(a, l) {
      const c = r.get(l);
      return c !== void 0 ? Promise.resolve(c) : o(a, l);
    }
  };
}, Jw = (n, t) => (e) => t(n, e), tS = (n) => (t) => {
  const e = n(t);
  if (e.renderer === null)
    throw new Error("Missing the renderer of the given AudioNode in the audio graph.");
  return e.renderer;
}, eS = (n) => (t) => {
  var e;
  return (e = n.get(t)) !== null && e !== void 0 ? e : 0;
}, sS = (n) => (t) => {
  const e = n(t);
  if (e.renderer === null)
    throw new Error("Missing the renderer of the given AudioParam in the audio graph.");
  return e.renderer;
}, nS = (n) => (t) => n.get(t), jt = () => new DOMException("", "InvalidStateError"), iS = (n) => (t) => {
  const e = n.get(t);
  if (e === void 0)
    throw jt();
  return e;
}, rS = (n, t) => (e) => {
  let s = n.get(e);
  if (s !== void 0)
    return s;
  if (t === null)
    throw new Error("Missing the native OfflineAudioContext constructor.");
  return s = new t(1, 1, 44100), n.set(e, s), s;
}, oS = (n) => (t) => {
  const e = n.get(t);
  if (e === void 0)
    throw new Error("The context has no set of AudioWorkletNodes.");
  return e;
}, ta = () => new DOMException("", "InvalidAccessError"), aS = (n) => {
  n.getFrequencyResponse = /* @__PURE__ */ ((t) => (e, s, i) => {
    if (e.length !== s.length || s.length !== i.length)
      throw ta();
    return t.call(n, e, s, i);
  })(n.getFrequencyResponse);
}, lS = {
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers"
}, cS = (n, t, e, s, i, r) => class extends n {
  constructor(a, l) {
    const c = s(a), h = i(c), u = { ...lS, ...l }, d = t(c, h ? null : a.baseLatency, u), f = h ? e(u.feedback, u.feedforward) : null;
    super(a, !1, d, f), aS(d), this._nativeIIRFilterNode = d, r(this, 1);
  }
  getFrequencyResponse(a, l, c) {
    return this._nativeIIRFilterNode.getFrequencyResponse(a, l, c);
  }
}, Nm = (n, t, e, s, i, r, o, a, l, c, h) => {
  const u = c.length;
  let d = a;
  for (let f = 0; f < u; f += 1) {
    let p = e[0] * c[f];
    for (let g = 1; g < i; g += 1) {
      const m = d - g & l - 1;
      p += e[g] * r[m], p -= n[g] * o[m];
    }
    for (let g = i; g < s; g += 1)
      p += e[g] * r[d - g & l - 1];
    for (let g = i; g < t; g += 1)
      p -= n[g] * o[d - g & l - 1];
    r[d] = c[f], o[d] = p, d = d + 1 & l - 1, h[f] = p;
  }
  return d;
}, hS = (n, t, e, s) => {
  const i = e instanceof Float64Array ? e : new Float64Array(e), r = s instanceof Float64Array ? s : new Float64Array(s), o = i.length, a = r.length, l = Math.min(o, a);
  if (i[0] !== 1) {
    for (let p = 0; p < o; p += 1)
      r[p] /= i[0];
    for (let p = 1; p < a; p += 1)
      i[p] /= i[0];
  }
  const c = 32, h = new Float32Array(c), u = new Float32Array(c), d = t.createBuffer(n.numberOfChannels, n.length, n.sampleRate), f = n.numberOfChannels;
  for (let p = 0; p < f; p += 1) {
    const g = n.getChannelData(p), m = d.getChannelData(p);
    h.fill(0), u.fill(0), Nm(i, o, r, a, l, h, u, 0, c, g, m);
  }
  return d;
}, uS = (n, t, e, s, i) => (r, o) => {
  const a = /* @__PURE__ */ new WeakMap();
  let l = null;
  const c = async (h, u) => {
    let d = null, f = t(h);
    const p = ne(f, u);
    if (u.createIIRFilter === void 0 ? d = n(u, {
      buffer: null,
      channelCount: 2,
      channelCountMode: "max",
      channelInterpretation: "speakers",
      loop: !1,
      loopEnd: 0,
      loopStart: 0,
      playbackRate: 1
    }) : p || (f = u.createIIRFilter(o, r)), a.set(u, d === null ? f : d), d !== null) {
      if (l === null) {
        if (e === null)
          throw new Error("Missing the native OfflineAudioContext constructor.");
        const m = new e(
          // Bug #47: The AudioDestinationNode in Safari gets not initialized correctly.
          h.context.destination.channelCount,
          // Bug #17: Safari does not yet expose the length.
          h.context.length,
          u.sampleRate
        );
        l = (async () => {
          await s(h, m, m.destination);
          const y = await i(m);
          return hS(y, u, r, o);
        })();
      }
      const g = await l;
      return d.buffer = g, d.start(0), d;
    }
    return await s(h, u, f), f;
  };
  return {
    render(h, u) {
      const d = a.get(u);
      return d !== void 0 ? Promise.resolve(d) : c(h, u);
    }
  };
}, dS = (n, t, e, s, i, r) => (o) => (a, l) => {
  const c = n.get(a);
  if (c === void 0) {
    if (!o && r(a)) {
      const h = s(a), { outputs: u } = e(a);
      for (const d of u)
        if (gr(d)) {
          const f = s(d[0]);
          t(h, f, d[1], d[2]);
        } else {
          const f = i(d[0]);
          h.disconnect(f, d[1]);
        }
    }
    n.set(a, l);
  } else
    n.set(a, c + l);
}, fS = (n, t) => (e) => {
  const s = n.get(e);
  return t(s) || t(e);
}, pS = (n, t) => (e) => n.has(e) || t(e), mS = (n, t) => (e) => n.has(e) || t(e), gS = (n, t) => (e) => {
  const s = n.get(e);
  return t(s) || t(e);
}, yS = (n) => (t) => n !== null && t instanceof n, xS = (n) => (t) => n !== null && typeof n.AudioNode == "function" && t instanceof n.AudioNode, _S = (n) => (t) => n !== null && typeof n.AudioParam == "function" && t instanceof n.AudioParam, vS = (n, t) => (e) => n(e) || t(e), bS = (n) => (t) => n !== null && t instanceof n, wS = (n) => n !== null && n.isSecureContext, SS = async (n, t, e, s, i, r, o, a, l, c, h, u, d, f, p, g) => n(t, t) && n(e, e) && n(i, i) && n(r, r) && n(a, a) && n(l, l) && n(c, c) && n(h, h) && n(u, u) && n(d, d) && n(f, f) ? (await Promise.all([
  n(s, s),
  n(o, o),
  n(p, p),
  n(g, g)
])).every((y) => y) : !1, TS = (n, t, e, s) => class extends n {
  constructor(r, o) {
    const a = e(r), l = t(a, o);
    if (s(a))
      throw TypeError();
    super(r, !0, l, null), this._nativeMediaElementAudioSourceNode = l;
  }
  get mediaElement() {
    return this._nativeMediaElementAudioSourceNode.mediaElement;
  }
}, MS = {
  channelCount: 2,
  channelCountMode: "explicit",
  channelInterpretation: "speakers"
}, kS = (n, t, e, s) => class extends n {
  constructor(r, o) {
    const a = e(r);
    if (s(a))
      throw new TypeError();
    const l = { ...MS, ...o }, c = t(a, l);
    super(r, !1, c, null), this._nativeMediaStreamAudioDestinationNode = c;
  }
  get stream() {
    return this._nativeMediaStreamAudioDestinationNode.stream;
  }
}, CS = (n, t, e, s) => class extends n {
  constructor(r, o) {
    const a = e(r), l = t(a, o);
    if (s(a))
      throw new TypeError();
    super(r, !0, l, null), this._nativeMediaStreamAudioSourceNode = l;
  }
  get mediaStream() {
    return this._nativeMediaStreamAudioSourceNode.mediaStream;
  }
}, AS = (n, t, e) => class extends n {
  constructor(i, r) {
    const o = e(i), a = t(o, r);
    super(i, !0, a, null);
  }
}, ES = (n, t, e, s, i, r) => class extends e {
  constructor(a, l) {
    super(a), this._nativeContext = a, Qo.set(this, a), s(a) && i.set(a, /* @__PURE__ */ new Set()), this._destination = new n(this, l), this._listener = t(this, a), this._onstatechange = null;
  }
  get currentTime() {
    return this._nativeContext.currentTime;
  }
  get destination() {
    return this._destination;
  }
  get listener() {
    return this._listener;
  }
  get onstatechange() {
    return this._onstatechange;
  }
  set onstatechange(a) {
    const l = typeof a == "function" ? r(this, a) : null;
    this._nativeContext.onstatechange = l;
    const c = this._nativeContext.onstatechange;
    this._onstatechange = c !== null && c === l ? a : c;
  }
  get sampleRate() {
    return this._nativeContext.sampleRate;
  }
  get state() {
    return this._nativeContext.state;
  }
}, or = (n) => {
  const t = new Uint32Array([1179011410, 40, 1163280727, 544501094, 16, 131073, 44100, 176400, 1048580, 1635017060, 4, 0]);
  try {
    const e = n.decodeAudioData(t.buffer, () => {
    });
    return e === void 0 ? !1 : (e.catch(() => {
    }), !0);
  } catch {
  }
  return !1;
}, PS = (n, t) => (e, s, i) => {
  const r = /* @__PURE__ */ new Set();
  return e.connect = /* @__PURE__ */ ((o) => (a, l = 0, c = 0) => {
    const h = r.size === 0;
    if (t(a))
      return o.call(e, a, l, c), n(r, [a, l, c], (u) => u[0] === a && u[1] === l && u[2] === c, !0), h && s(), a;
    o.call(e, a, l), n(r, [a, l], (u) => u[0] === a && u[1] === l, !0), h && s();
  })(e.connect), e.disconnect = /* @__PURE__ */ ((o) => (a, l, c) => {
    const h = r.size > 0;
    if (a === void 0)
      o.apply(e), r.clear();
    else if (typeof a == "number") {
      o.call(e, a);
      for (const d of r)
        d[1] === a && r.delete(d);
    } else {
      t(a) ? o.call(e, a, l, c) : o.call(e, a, l);
      for (const d of r)
        d[0] === a && (l === void 0 || d[1] === l) && (c === void 0 || d[2] === c) && r.delete(d);
    }
    const u = r.size === 0;
    h && u && i();
  })(e.disconnect), e;
}, wt = (n, t, e) => {
  const s = t[e];
  s !== void 0 && s !== n[e] && (n[e] = s);
}, qt = (n, t) => {
  wt(n, t, "channelCount"), wt(n, t, "channelCountMode"), wt(n, t, "channelInterpretation");
}, Jd = (n) => typeof n.getFloatTimeDomainData == "function", IS = (n) => {
  n.getFloatTimeDomainData = (t) => {
    const e = new Uint8Array(t.length);
    n.getByteTimeDomainData(e);
    const s = Math.max(e.length, n.fftSize);
    for (let i = 0; i < s; i += 1)
      t[i] = (e[i] - 128) * 78125e-7;
    return t;
  };
}, FS = (n, t) => (e, s) => {
  const i = e.createAnalyser();
  if (qt(i, s), !(s.maxDecibels > s.minDecibels))
    throw t();
  return wt(i, s, "fftSize"), wt(i, s, "maxDecibels"), wt(i, s, "minDecibels"), wt(i, s, "smoothingTimeConstant"), n(Jd, () => Jd(i)) || IS(i), i;
}, RS = (n) => n === null ? null : n.hasOwnProperty("AudioBuffer") ? n.AudioBuffer : null, It = (n, t, e) => {
  const s = t[e];
  s !== void 0 && s !== n[e].value && (n[e].value = s);
}, DS = (n) => {
  n.start = /* @__PURE__ */ ((t) => {
    let e = !1;
    return (s = 0, i = 0, r) => {
      if (e)
        throw jt();
      t.call(n, s, i, r), e = !0;
    };
  })(n.start);
}, xc = (n) => {
  n.start = /* @__PURE__ */ ((t) => (e = 0, s = 0, i) => {
    if (typeof i == "number" && i < 0 || s < 0 || e < 0)
      throw new RangeError("The parameters can't be negative.");
    t.call(n, e, s, i);
  })(n.start);
}, _c = (n) => {
  n.stop = /* @__PURE__ */ ((t) => (e = 0) => {
    if (e < 0)
      throw new RangeError("The parameter can't be negative.");
    t.call(n, e);
  })(n.stop);
}, OS = (n, t, e, s, i, r, o, a, l, c, h) => (u, d) => {
  const f = u.createBufferSource();
  return qt(f, d), It(f, d, "playbackRate"), wt(f, d, "buffer"), wt(f, d, "loop"), wt(f, d, "loopEnd"), wt(f, d, "loopStart"), t(e, () => e(u)) || DS(f), t(s, () => s(u)) || l(f), t(i, () => i(u)) || c(f, u), t(r, () => r(u)) || xc(f), t(o, () => o(u)) || h(f, u), t(a, () => a(u)) || _c(f), n(u, f), f;
}, NS = (n) => n === null ? null : n.hasOwnProperty("AudioContext") ? n.AudioContext : n.hasOwnProperty("webkitAudioContext") ? n.webkitAudioContext : null, LS = (n, t) => (e, s, i) => {
  const r = e.destination;
  if (r.channelCount !== s)
    try {
      r.channelCount = s;
    } catch {
    }
  i && r.channelCountMode !== "explicit" && (r.channelCountMode = "explicit"), r.maxChannelCount === 0 && Object.defineProperty(r, "maxChannelCount", {
    value: s
  });
  const o = n(e, {
    channelCount: s,
    channelCountMode: r.channelCountMode,
    channelInterpretation: r.channelInterpretation,
    gain: 1
  });
  return t(o, "channelCount", (a) => () => a.call(o), (a) => (l) => {
    a.call(o, l);
    try {
      r.channelCount = l;
    } catch (c) {
      if (l > r.maxChannelCount)
        throw c;
    }
  }), t(o, "channelCountMode", (a) => () => a.call(o), (a) => (l) => {
    a.call(o, l), r.channelCountMode = l;
  }), t(o, "channelInterpretation", (a) => () => a.call(o), (a) => (l) => {
    a.call(o, l), r.channelInterpretation = l;
  }), Object.defineProperty(o, "maxChannelCount", {
    get: () => r.maxChannelCount
  }), o.connect(r), o;
}, VS = (n) => n === null ? null : n.hasOwnProperty("AudioWorkletNode") ? n.AudioWorkletNode : null, BS = (n) => {
  const { port1: t } = new MessageChannel();
  try {
    t.postMessage(n);
  } finally {
    t.close();
  }
}, zS = (n, t, e, s, i) => (r, o, a, l, c, h) => {
  if (a !== null)
    try {
      const u = new a(r, l, h), d = /* @__PURE__ */ new Map();
      let f = null;
      if (Object.defineProperties(u, {
        /*
         * Bug #61: Overwriting the property accessors for channelCount and channelCountMode is necessary as long as some
         * browsers have no native implementation to achieve a consistent behavior.
         */
        channelCount: {
          get: () => h.channelCount,
          set: () => {
            throw n();
          }
        },
        channelCountMode: {
          get: () => "explicit",
          set: () => {
            throw n();
          }
        },
        // Bug #156: Chrome and Edge do not yet fire an ErrorEvent.
        onprocessorerror: {
          get: () => f,
          set: (p) => {
            typeof f == "function" && u.removeEventListener("processorerror", f), f = typeof p == "function" ? p : null, typeof f == "function" && u.addEventListener("processorerror", f);
          }
        }
      }), u.addEventListener = /* @__PURE__ */ ((p) => (...g) => {
        if (g[0] === "processorerror") {
          const m = typeof g[1] == "function" ? g[1] : typeof g[1] == "object" && g[1] !== null && typeof g[1].handleEvent == "function" ? g[1].handleEvent : null;
          if (m !== null) {
            const y = d.get(g[1]);
            y !== void 0 ? g[1] = y : (g[1] = (x) => {
              x.type === "error" ? (Object.defineProperties(x, {
                type: { value: "processorerror" }
              }), m(x)) : m(new ErrorEvent(g[0], { ...x }));
            }, d.set(m, g[1]));
          }
        }
        return p.call(u, "error", g[1], g[2]), p.call(u, ...g);
      })(u.addEventListener), u.removeEventListener = /* @__PURE__ */ ((p) => (...g) => {
        if (g[0] === "processorerror") {
          const m = d.get(g[1]);
          m !== void 0 && (d.delete(g[1]), g[1] = m);
        }
        return p.call(u, "error", g[1], g[2]), p.call(u, g[0], g[1], g[2]);
      })(u.removeEventListener), h.numberOfOutputs !== 0) {
        const p = e(r, {
          channelCount: 1,
          channelCountMode: "explicit",
          channelInterpretation: "discrete",
          gain: 0
        });
        return u.connect(p).connect(r.destination), i(u, () => p.disconnect(), () => p.connect(r.destination));
      }
      return u;
    } catch (u) {
      throw u.code === 11 ? s() : u;
    }
  if (c === void 0)
    throw s();
  return BS(h), t(r, o, c, h);
}, Lm = (n, t) => n === null ? 512 : Math.max(512, Math.min(16384, Math.pow(2, Math.round(Math.log2(n * t))))), qS = (n) => new Promise((t, e) => {
  const { port1: s, port2: i } = new MessageChannel();
  s.onmessage = ({ data: r }) => {
    s.close(), i.close(), t(r);
  }, s.onmessageerror = ({ data: r }) => {
    s.close(), i.close(), e(r);
  }, i.postMessage(n);
}), US = async (n, t) => {
  const e = await qS(t);
  return new n(e);
}, GS = (n, t, e, s) => {
  let i = Ll.get(n);
  i === void 0 && (i = /* @__PURE__ */ new WeakMap(), Ll.set(n, i));
  const r = US(e, s);
  return i.set(t, r), r;
}, WS = (n, t, e, s, i, r, o, a, l, c, h, u, d) => (f, p, g, m) => {
  if (m.numberOfInputs === 0 && m.numberOfOutputs === 0)
    throw l();
  const y = Array.isArray(m.outputChannelCount) ? m.outputChannelCount : Array.from(m.outputChannelCount);
  if (y.some(($) => $ < 1))
    throw l();
  if (y.length !== m.numberOfOutputs)
    throw t();
  if (m.channelCountMode !== "explicit")
    throw l();
  const x = m.channelCount * m.numberOfInputs, v = y.reduce(($, J) => $ + J, 0), _ = g.parameterDescriptors === void 0 ? 0 : g.parameterDescriptors.length;
  if (x + _ > 6 || v > 6)
    throw l();
  const b = new MessageChannel(), w = [], S = [];
  for (let $ = 0; $ < m.numberOfInputs; $ += 1)
    w.push(o(f, {
      channelCount: m.channelCount,
      channelCountMode: m.channelCountMode,
      channelInterpretation: m.channelInterpretation,
      gain: 1
    })), S.push(i(f, {
      channelCount: m.channelCount,
      channelCountMode: "explicit",
      channelInterpretation: "discrete",
      numberOfOutputs: m.channelCount
    }));
  const T = [];
  if (g.parameterDescriptors !== void 0)
    for (const { defaultValue: $, maxValue: J, minValue: bt, name: pt } of g.parameterDescriptors) {
      const it = r(f, {
        channelCount: 1,
        channelCountMode: "explicit",
        channelInterpretation: "discrete",
        offset: m.parameterData[pt] !== void 0 ? m.parameterData[pt] : $ === void 0 ? 0 : $
      });
      Object.defineProperties(it.offset, {
        defaultValue: {
          get: () => $ === void 0 ? 0 : $
        },
        maxValue: {
          get: () => J === void 0 ? re : J
        },
        minValue: {
          get: () => bt === void 0 ? ye : bt
        }
      }), T.push(it);
    }
  const k = s(f, {
    channelCount: 1,
    channelCountMode: "explicit",
    channelInterpretation: "speakers",
    numberOfInputs: Math.max(1, x + _)
  }), C = Lm(p, f.sampleRate), M = a(
    f,
    C,
    x + _,
    // Bug #87: Only Firefox will fire an AudioProcessingEvent if there is no connected output.
    Math.max(1, v)
  ), A = i(f, {
    channelCount: Math.max(1, v),
    channelCountMode: "explicit",
    channelInterpretation: "discrete",
    numberOfOutputs: Math.max(1, v)
  }), I = [];
  for (let $ = 0; $ < m.numberOfOutputs; $ += 1)
    I.push(s(f, {
      channelCount: 1,
      channelCountMode: "explicit",
      channelInterpretation: "speakers",
      numberOfInputs: y[$]
    }));
  for (let $ = 0; $ < m.numberOfInputs; $ += 1) {
    w[$].connect(S[$]);
    for (let J = 0; J < m.channelCount; J += 1)
      S[$].connect(k, J, $ * m.channelCount + J);
  }
  const F = new Dm(g.parameterDescriptors === void 0 ? [] : g.parameterDescriptors.map(({ name: $ }, J) => {
    const bt = T[J];
    return bt.connect(k, 0, x + J), bt.start(0), [$, bt.offset];
  }));
  k.connect(M);
  let R = m.channelInterpretation, E = null;
  const P = m.numberOfOutputs === 0 ? [M] : I, N = {
    get bufferSize() {
      return C;
    },
    get channelCount() {
      return m.channelCount;
    },
    set channelCount($) {
      throw e();
    },
    get channelCountMode() {
      return m.channelCountMode;
    },
    set channelCountMode($) {
      throw e();
    },
    get channelInterpretation() {
      return R;
    },
    set channelInterpretation($) {
      for (const J of w)
        J.channelInterpretation = $;
      R = $;
    },
    get context() {
      return M.context;
    },
    get inputs() {
      return w;
    },
    get numberOfInputs() {
      return m.numberOfInputs;
    },
    get numberOfOutputs() {
      return m.numberOfOutputs;
    },
    get onprocessorerror() {
      return E;
    },
    set onprocessorerror($) {
      typeof E == "function" && N.removeEventListener("processorerror", E), E = typeof $ == "function" ? $ : null, typeof E == "function" && N.addEventListener("processorerror", E);
    },
    get parameters() {
      return F;
    },
    get port() {
      return b.port2;
    },
    addEventListener(...$) {
      return M.addEventListener($[0], $[1], $[2]);
    },
    connect: n.bind(null, P),
    disconnect: c.bind(null, P),
    dispatchEvent(...$) {
      return M.dispatchEvent($[0]);
    },
    removeEventListener(...$) {
      return M.removeEventListener($[0], $[1], $[2]);
    }
  }, D = /* @__PURE__ */ new Map();
  b.port1.addEventListener = /* @__PURE__ */ (($) => (...J) => {
    if (J[0] === "message") {
      const bt = typeof J[1] == "function" ? J[1] : typeof J[1] == "object" && J[1] !== null && typeof J[1].handleEvent == "function" ? J[1].handleEvent : null;
      if (bt !== null) {
        const pt = D.get(J[1]);
        pt !== void 0 ? J[1] = pt : (J[1] = (it) => {
          h(f.currentTime, f.sampleRate, () => bt(it));
        }, D.set(bt, J[1]));
      }
    }
    return $.call(b.port1, J[0], J[1], J[2]);
  })(b.port1.addEventListener), b.port1.removeEventListener = /* @__PURE__ */ (($) => (...J) => {
    if (J[0] === "message") {
      const bt = D.get(J[1]);
      bt !== void 0 && (D.delete(J[1]), J[1] = bt);
    }
    return $.call(b.port1, J[0], J[1], J[2]);
  })(b.port1.removeEventListener);
  let z = null;
  Object.defineProperty(b.port1, "onmessage", {
    get: () => z,
    set: ($) => {
      typeof z == "function" && b.port1.removeEventListener("message", z), z = typeof $ == "function" ? $ : null, typeof z == "function" && (b.port1.addEventListener("message", z), b.port1.start());
    }
  }), g.prototype.port = b.port1;
  let O = null;
  GS(f, N, g, m).then(($) => O = $);
  const G = Vo(m.numberOfInputs, m.channelCount), H = Vo(m.numberOfOutputs, y), q = g.parameterDescriptors === void 0 ? [] : g.parameterDescriptors.reduce(($, { name: J }) => ({ ...$, [J]: new Float32Array(128) }), {});
  let W = !0;
  const K = () => {
    m.numberOfOutputs > 0 && M.disconnect(A);
    for (let $ = 0, J = 0; $ < m.numberOfOutputs; $ += 1) {
      const bt = I[$];
      for (let pt = 0; pt < y[$]; pt += 1)
        A.disconnect(bt, J + pt, pt);
      J += y[$];
    }
  }, U = /* @__PURE__ */ new Map();
  M.onaudioprocess = ({ inputBuffer: $, outputBuffer: J }) => {
    if (O !== null) {
      const bt = u(N);
      for (let pt = 0; pt < C; pt += 128) {
        for (let it = 0; it < m.numberOfInputs; it += 1)
          for (let _t = 0; _t < m.channelCount; _t += 1)
            Lo($, G[it], _t, _t, pt);
        g.parameterDescriptors !== void 0 && g.parameterDescriptors.forEach(({ name: it }, _t) => {
          Lo($, q, it, x + _t, pt);
        });
        for (let it = 0; it < m.numberOfInputs; it += 1)
          for (let _t = 0; _t < y[it]; _t += 1)
            H[it][_t].byteLength === 0 && (H[it][_t] = new Float32Array(128));
        try {
          const it = G.map((fe, ns) => {
            if (bt[ns].size > 0)
              return U.set(ns, C / 128), fe;
            const Ci = U.get(ns);
            return Ci === void 0 ? [] : (fe.every((ga) => ga.every((nn) => nn === 0)) && (Ci === 1 ? U.delete(ns) : U.set(ns, Ci - 1)), fe);
          });
          W = h(f.currentTime + pt / f.sampleRate, f.sampleRate, () => O.process(it, H, q));
          for (let fe = 0, ns = 0; fe < m.numberOfOutputs; fe += 1) {
            for (let sn = 0; sn < y[fe]; sn += 1)
              Om(J, H[fe], sn, ns + sn, pt);
            ns += y[fe];
          }
        } catch (it) {
          W = !1, N.dispatchEvent(new ErrorEvent("processorerror", {
            colno: it.colno,
            filename: it.filename,
            lineno: it.lineno,
            message: it.message
          }));
        }
        if (!W) {
          for (let it = 0; it < m.numberOfInputs; it += 1) {
            w[it].disconnect(S[it]);
            for (let _t = 0; _t < m.channelCount; _t += 1)
              S[pt].disconnect(k, _t, it * m.channelCount + _t);
          }
          if (g.parameterDescriptors !== void 0) {
            const it = g.parameterDescriptors.length;
            for (let _t = 0; _t < it; _t += 1) {
              const fe = T[_t];
              fe.disconnect(k, 0, x + _t), fe.stop();
            }
          }
          k.disconnect(M), M.onaudioprocess = null, at ? K() : ee();
          break;
        }
      }
    }
  };
  let at = !1;
  const At = o(f, {
    channelCount: 1,
    channelCountMode: "explicit",
    channelInterpretation: "discrete",
    gain: 0
  }), te = () => M.connect(At).connect(f.destination), ee = () => {
    M.disconnect(At), At.disconnect();
  }, Ue = () => {
    if (W) {
      ee(), m.numberOfOutputs > 0 && M.connect(A);
      for (let $ = 0, J = 0; $ < m.numberOfOutputs; $ += 1) {
        const bt = I[$];
        for (let pt = 0; pt < y[$]; pt += 1)
          A.connect(bt, J + pt, pt);
        J += y[$];
      }
    }
    at = !0;
  }, we = () => {
    W && (te(), K()), at = !1;
  };
  return te(), d(N, Ue, we);
}, Vm = (n, t) => {
  const e = n.createBiquadFilter();
  return qt(e, t), It(e, t, "Q"), It(e, t, "detune"), It(e, t, "frequency"), It(e, t, "gain"), wt(e, t, "type"), e;
}, $S = (n, t) => (e, s) => {
  const i = e.createChannelMerger(s.numberOfInputs);
  return n !== null && n.name === "webkitAudioContext" && t(e, i), qt(i, s), i;
}, HS = (n) => {
  const t = n.numberOfOutputs;
  Object.defineProperty(n, "channelCount", {
    get: () => t,
    set: (e) => {
      if (e !== t)
        throw jt();
    }
  }), Object.defineProperty(n, "channelCountMode", {
    get: () => "explicit",
    set: (e) => {
      if (e !== "explicit")
        throw jt();
    }
  }), Object.defineProperty(n, "channelInterpretation", {
    get: () => "discrete",
    set: (e) => {
      if (e !== "discrete")
        throw jt();
    }
  });
}, yr = (n, t) => {
  const e = n.createChannelSplitter(t.numberOfOutputs);
  return qt(e, t), HS(e), e;
}, jS = (n, t, e, s, i) => (r, o) => {
  if (r.createConstantSource === void 0)
    return e(r, o);
  const a = r.createConstantSource();
  return qt(a, o), It(a, o, "offset"), t(s, () => s(r)) || xc(a), t(i, () => i(r)) || _c(a), n(r, a), a;
}, ui = (n, t) => (n.connect = t.connect.bind(t), n.disconnect = t.disconnect.bind(t), n), XS = (n, t, e, s) => (i, { offset: r, ...o }) => {
  const a = i.createBuffer(1, 2, 44100), l = t(i, {
    buffer: null,
    channelCount: 2,
    channelCountMode: "max",
    channelInterpretation: "speakers",
    loop: !1,
    loopEnd: 0,
    loopStart: 0,
    playbackRate: 1
  }), c = e(i, { ...o, gain: r }), h = a.getChannelData(0);
  h[0] = 1, h[1] = 1, l.buffer = a, l.loop = !0;
  const u = {
    get bufferSize() {
    },
    get channelCount() {
      return c.channelCount;
    },
    set channelCount(p) {
      c.channelCount = p;
    },
    get channelCountMode() {
      return c.channelCountMode;
    },
    set channelCountMode(p) {
      c.channelCountMode = p;
    },
    get channelInterpretation() {
      return c.channelInterpretation;
    },
    set channelInterpretation(p) {
      c.channelInterpretation = p;
    },
    get context() {
      return c.context;
    },
    get inputs() {
      return [];
    },
    get numberOfInputs() {
      return l.numberOfInputs;
    },
    get numberOfOutputs() {
      return c.numberOfOutputs;
    },
    get offset() {
      return c.gain;
    },
    get onended() {
      return l.onended;
    },
    set onended(p) {
      l.onended = p;
    },
    addEventListener(...p) {
      return l.addEventListener(p[0], p[1], p[2]);
    },
    dispatchEvent(...p) {
      return l.dispatchEvent(p[0]);
    },
    removeEventListener(...p) {
      return l.removeEventListener(p[0], p[1], p[2]);
    },
    start(p = 0) {
      l.start.call(l, p);
    },
    stop(p = 0) {
      l.stop.call(l, p);
    }
  }, d = () => l.connect(c), f = () => l.disconnect(c);
  return n(i, l), s(ui(u, c), d, f);
}, YS = (n, t) => (e, s) => {
  const i = e.createConvolver();
  if (qt(i, s), s.disableNormalization === i.normalize && (i.normalize = !s.disableNormalization), wt(i, s, "buffer"), s.channelCount > 2 || (t(i, "channelCount", (r) => () => r.call(i), (r) => (o) => {
    if (o > 2)
      throw n();
    return r.call(i, o);
  }), s.channelCountMode === "max"))
    throw n();
  return t(i, "channelCountMode", (r) => () => r.call(i), (r) => (o) => {
    if (o === "max")
      throw n();
    return r.call(i, o);
  }), i;
}, Bm = (n, t) => {
  const e = n.createDelay(t.maxDelayTime);
  return qt(e, t), It(e, t, "delayTime"), e;
}, ZS = (n) => (t, e) => {
  const s = t.createDynamicsCompressor();
  if (qt(s, e), e.channelCount > 2 || e.channelCountMode === "max")
    throw n();
  return It(s, e, "attack"), It(s, e, "knee"), It(s, e, "ratio"), It(s, e, "release"), It(s, e, "threshold"), s;
}, be = (n, t) => {
  const e = n.createGain();
  return qt(e, t), It(e, t, "gain"), e;
}, KS = (n) => (t, e, s) => {
  if (t.createIIRFilter === void 0)
    return n(t, e, s);
  const i = t.createIIRFilter(s.feedforward, s.feedback);
  return qt(i, s), i;
};
function QS(n, t) {
  const e = t[0] * t[0] + t[1] * t[1];
  return [(n[0] * t[0] + n[1] * t[1]) / e, (n[1] * t[0] - n[0] * t[1]) / e];
}
function JS(n, t) {
  return [n[0] * t[0] - n[1] * t[1], n[0] * t[1] + n[1] * t[0]];
}
function tf(n, t) {
  let e = [0, 0];
  for (let s = n.length - 1; s >= 0; s -= 1)
    e = JS(e, t), e[0] += n[s];
  return e;
}
const tT = (n, t, e, s) => (i, r, { channelCount: o, channelCountMode: a, channelInterpretation: l, feedback: c, feedforward: h }) => {
  const u = Lm(r, i.sampleRate), d = c instanceof Float64Array ? c : new Float64Array(c), f = h instanceof Float64Array ? h : new Float64Array(h), p = d.length, g = f.length, m = Math.min(p, g);
  if (p === 0 || p > 20)
    throw s();
  if (d[0] === 0)
    throw t();
  if (g === 0 || g > 20)
    throw s();
  if (f[0] === 0)
    throw t();
  if (d[0] !== 1) {
    for (let T = 0; T < g; T += 1)
      f[T] /= d[0];
    for (let T = 1; T < p; T += 1)
      d[T] /= d[0];
  }
  const y = e(i, u, o, o);
  y.channelCount = o, y.channelCountMode = a, y.channelInterpretation = l;
  const x = 32, v = [], _ = [], b = [];
  for (let T = 0; T < o; T += 1) {
    v.push(0);
    const k = new Float32Array(x), C = new Float32Array(x);
    k.fill(0), C.fill(0), _.push(k), b.push(C);
  }
  y.onaudioprocess = (T) => {
    const k = T.inputBuffer, C = T.outputBuffer, M = k.numberOfChannels;
    for (let A = 0; A < M; A += 1) {
      const I = k.getChannelData(A), F = C.getChannelData(A);
      v[A] = Nm(d, p, f, g, m, _[A], b[A], v[A], x, I, F);
    }
  };
  const w = i.sampleRate / 2;
  return ui({
    get bufferSize() {
      return u;
    },
    get channelCount() {
      return y.channelCount;
    },
    set channelCount(T) {
      y.channelCount = T;
    },
    get channelCountMode() {
      return y.channelCountMode;
    },
    set channelCountMode(T) {
      y.channelCountMode = T;
    },
    get channelInterpretation() {
      return y.channelInterpretation;
    },
    set channelInterpretation(T) {
      y.channelInterpretation = T;
    },
    get context() {
      return y.context;
    },
    get inputs() {
      return [y];
    },
    get numberOfInputs() {
      return y.numberOfInputs;
    },
    get numberOfOutputs() {
      return y.numberOfOutputs;
    },
    addEventListener(...T) {
      return y.addEventListener(T[0], T[1], T[2]);
    },
    dispatchEvent(...T) {
      return y.dispatchEvent(T[0]);
    },
    getFrequencyResponse(T, k, C) {
      if (T.length !== k.length || k.length !== C.length)
        throw n();
      const M = T.length;
      for (let A = 0; A < M; A += 1) {
        const I = -Math.PI * (T[A] / w), F = [Math.cos(I), Math.sin(I)], R = tf(f, F), E = tf(d, F), P = QS(R, E);
        k[A] = Math.sqrt(P[0] * P[0] + P[1] * P[1]), C[A] = Math.atan2(P[1], P[0]);
      }
    },
    removeEventListener(...T) {
      return y.removeEventListener(T[0], T[1], T[2]);
    }
  }, y);
}, eT = (n, t) => n.createMediaElementSource(t.mediaElement), sT = (n, t) => {
  const e = n.createMediaStreamDestination();
  return qt(e, t), e.numberOfOutputs === 1 && Object.defineProperty(e, "numberOfOutputs", { get: () => 0 }), e;
}, nT = (n, { mediaStream: t }) => {
  const e = t.getAudioTracks();
  e.sort((r, o) => r.id < o.id ? -1 : r.id > o.id ? 1 : 0);
  const s = e.slice(0, 1), i = n.createMediaStreamSource(new MediaStream(s));
  return Object.defineProperty(i, "mediaStream", { value: t }), i;
}, iT = (n, t) => (e, { mediaStreamTrack: s }) => {
  if (typeof e.createMediaStreamTrackSource == "function")
    return e.createMediaStreamTrackSource(s);
  const i = new MediaStream([s]), r = e.createMediaStreamSource(i);
  if (s.kind !== "audio")
    throw n();
  if (t(e))
    throw new TypeError();
  return r;
}, rT = (n) => n === null ? null : n.hasOwnProperty("OfflineAudioContext") ? n.OfflineAudioContext : n.hasOwnProperty("webkitOfflineAudioContext") ? n.webkitOfflineAudioContext : null, oT = (n, t, e, s, i, r) => (o, a) => {
  const l = o.createOscillator();
  return qt(l, a), It(l, a, "detune"), It(l, a, "frequency"), a.periodicWave !== void 0 ? l.setPeriodicWave(a.periodicWave) : wt(l, a, "type"), t(e, () => e(o)) || xc(l), t(s, () => s(o)) || r(l, o), t(i, () => i(o)) || _c(l), n(o, l), l;
}, aT = (n) => (t, e) => {
  const s = t.createPanner();
  return s.orientationX === void 0 ? n(t, e) : (qt(s, e), It(s, e, "orientationX"), It(s, e, "orientationY"), It(s, e, "orientationZ"), It(s, e, "positionX"), It(s, e, "positionY"), It(s, e, "positionZ"), wt(s, e, "coneInnerAngle"), wt(s, e, "coneOuterAngle"), wt(s, e, "coneOuterGain"), wt(s, e, "distanceModel"), wt(s, e, "maxDistance"), wt(s, e, "panningModel"), wt(s, e, "refDistance"), wt(s, e, "rolloffFactor"), s);
}, lT = (n, t, e, s, i, r, o, a, l, c) => (h, { coneInnerAngle: u, coneOuterAngle: d, coneOuterGain: f, distanceModel: p, maxDistance: g, orientationX: m, orientationY: y, orientationZ: x, panningModel: v, positionX: _, positionY: b, positionZ: w, refDistance: S, rolloffFactor: T, ...k }) => {
  const C = h.createPanner();
  if (k.channelCount > 2 || k.channelCountMode === "max")
    throw o();
  qt(C, k);
  const M = {
    channelCount: 1,
    channelCountMode: "explicit",
    channelInterpretation: "discrete"
  }, A = e(h, {
    ...M,
    channelInterpretation: "speakers",
    numberOfInputs: 6
  }), I = s(h, { ...k, gain: 1 }), F = s(h, { ...M, gain: 1 }), R = s(h, { ...M, gain: 0 }), E = s(h, { ...M, gain: 0 }), P = s(h, { ...M, gain: 0 }), N = s(h, { ...M, gain: 0 }), D = s(h, { ...M, gain: 0 }), z = i(h, 256, 6, 1), O = r(h, {
    ...M,
    curve: new Float32Array([1, 1]),
    oversample: "none"
  });
  let V = [m, y, x], G = [_, b, w];
  const H = new Float32Array(1);
  z.onaudioprocess = ({ inputBuffer: U }) => {
    const at = [
      l(U, H, 0),
      l(U, H, 1),
      l(U, H, 2)
    ];
    at.some((te, ee) => te !== V[ee]) && (C.setOrientation(...at), V = at);
    const At = [
      l(U, H, 3),
      l(U, H, 4),
      l(U, H, 5)
    ];
    At.some((te, ee) => te !== G[ee]) && (C.setPosition(...At), G = At);
  }, Object.defineProperty(R.gain, "defaultValue", { get: () => 0 }), Object.defineProperty(E.gain, "defaultValue", { get: () => 0 }), Object.defineProperty(P.gain, "defaultValue", { get: () => 0 }), Object.defineProperty(N.gain, "defaultValue", { get: () => 0 }), Object.defineProperty(D.gain, "defaultValue", { get: () => 0 });
  const q = {
    get bufferSize() {
    },
    get channelCount() {
      return C.channelCount;
    },
    set channelCount(U) {
      if (U > 2)
        throw o();
      I.channelCount = U, C.channelCount = U;
    },
    get channelCountMode() {
      return C.channelCountMode;
    },
    set channelCountMode(U) {
      if (U === "max")
        throw o();
      I.channelCountMode = U, C.channelCountMode = U;
    },
    get channelInterpretation() {
      return C.channelInterpretation;
    },
    set channelInterpretation(U) {
      I.channelInterpretation = U, C.channelInterpretation = U;
    },
    get coneInnerAngle() {
      return C.coneInnerAngle;
    },
    set coneInnerAngle(U) {
      C.coneInnerAngle = U;
    },
    get coneOuterAngle() {
      return C.coneOuterAngle;
    },
    set coneOuterAngle(U) {
      C.coneOuterAngle = U;
    },
    get coneOuterGain() {
      return C.coneOuterGain;
    },
    set coneOuterGain(U) {
      if (U < 0 || U > 1)
        throw t();
      C.coneOuterGain = U;
    },
    get context() {
      return C.context;
    },
    get distanceModel() {
      return C.distanceModel;
    },
    set distanceModel(U) {
      C.distanceModel = U;
    },
    get inputs() {
      return [I];
    },
    get maxDistance() {
      return C.maxDistance;
    },
    set maxDistance(U) {
      if (U < 0)
        throw new RangeError();
      C.maxDistance = U;
    },
    get numberOfInputs() {
      return C.numberOfInputs;
    },
    get numberOfOutputs() {
      return C.numberOfOutputs;
    },
    get orientationX() {
      return F.gain;
    },
    get orientationY() {
      return R.gain;
    },
    get orientationZ() {
      return E.gain;
    },
    get panningModel() {
      return C.panningModel;
    },
    set panningModel(U) {
      C.panningModel = U;
    },
    get positionX() {
      return P.gain;
    },
    get positionY() {
      return N.gain;
    },
    get positionZ() {
      return D.gain;
    },
    get refDistance() {
      return C.refDistance;
    },
    set refDistance(U) {
      if (U < 0)
        throw new RangeError();
      C.refDistance = U;
    },
    get rolloffFactor() {
      return C.rolloffFactor;
    },
    set rolloffFactor(U) {
      if (U < 0)
        throw new RangeError();
      C.rolloffFactor = U;
    },
    addEventListener(...U) {
      return I.addEventListener(U[0], U[1], U[2]);
    },
    dispatchEvent(...U) {
      return I.dispatchEvent(U[0]);
    },
    removeEventListener(...U) {
      return I.removeEventListener(U[0], U[1], U[2]);
    }
  };
  u !== q.coneInnerAngle && (q.coneInnerAngle = u), d !== q.coneOuterAngle && (q.coneOuterAngle = d), f !== q.coneOuterGain && (q.coneOuterGain = f), p !== q.distanceModel && (q.distanceModel = p), g !== q.maxDistance && (q.maxDistance = g), m !== q.orientationX.value && (q.orientationX.value = m), y !== q.orientationY.value && (q.orientationY.value = y), x !== q.orientationZ.value && (q.orientationZ.value = x), v !== q.panningModel && (q.panningModel = v), _ !== q.positionX.value && (q.positionX.value = _), b !== q.positionY.value && (q.positionY.value = b), w !== q.positionZ.value && (q.positionZ.value = w), S !== q.refDistance && (q.refDistance = S), T !== q.rolloffFactor && (q.rolloffFactor = T), (V[0] !== 1 || V[1] !== 0 || V[2] !== 0) && C.setOrientation(...V), (G[0] !== 0 || G[1] !== 0 || G[2] !== 0) && C.setPosition(...G);
  const W = () => {
    I.connect(C), n(I, O, 0, 0), O.connect(F).connect(A, 0, 0), O.connect(R).connect(A, 0, 1), O.connect(E).connect(A, 0, 2), O.connect(P).connect(A, 0, 3), O.connect(N).connect(A, 0, 4), O.connect(D).connect(A, 0, 5), A.connect(z).connect(h.destination);
  }, K = () => {
    I.disconnect(C), a(I, O, 0, 0), O.disconnect(F), F.disconnect(A), O.disconnect(R), R.disconnect(A), O.disconnect(E), E.disconnect(A), O.disconnect(P), P.disconnect(A), O.disconnect(N), N.disconnect(A), O.disconnect(D), D.disconnect(A), A.disconnect(z), z.disconnect(h.destination);
  };
  return c(ui(q, C), W, K);
}, cT = (n) => (t, { disableNormalization: e, imag: s, real: i }) => {
  const r = s instanceof Float32Array ? s : new Float32Array(s), o = i instanceof Float32Array ? i : new Float32Array(i), a = t.createPeriodicWave(o, r, { disableNormalization: e });
  if (Array.from(s).length < 2)
    throw n();
  return a;
}, xr = (n, t, e, s) => n.createScriptProcessor(t, e, s), hT = (n, t) => (e, s) => {
  const i = s.channelCountMode;
  if (i === "clamped-max")
    throw t();
  if (e.createStereoPanner === void 0)
    return n(e, s);
  const r = e.createStereoPanner();
  return qt(r, s), It(r, s, "pan"), Object.defineProperty(r, "channelCountMode", {
    get: () => i,
    set: (o) => {
      if (o !== i)
        throw t();
    }
  }), r;
}, uT = (n, t, e, s, i, r) => {
  const a = new Float32Array([1, 1]), l = Math.PI / 2, c = { channelCount: 1, channelCountMode: "explicit", channelInterpretation: "discrete" }, h = { ...c, oversample: "none" }, u = (p, g, m, y) => {
    const x = new Float32Array(16385), v = new Float32Array(16385);
    for (let k = 0; k < 16385; k += 1) {
      const C = k / 16384 * l;
      x[k] = Math.cos(C), v[k] = Math.sin(C);
    }
    const _ = e(p, { ...c, gain: 0 }), b = s(p, { ...h, curve: x }), w = s(p, { ...h, curve: a }), S = e(p, { ...c, gain: 0 }), T = s(p, { ...h, curve: v });
    return {
      connectGraph() {
        g.connect(_), g.connect(w.inputs === void 0 ? w : w.inputs[0]), g.connect(S), w.connect(m), m.connect(b.inputs === void 0 ? b : b.inputs[0]), m.connect(T.inputs === void 0 ? T : T.inputs[0]), b.connect(_.gain), T.connect(S.gain), _.connect(y, 0, 0), S.connect(y, 0, 1);
      },
      disconnectGraph() {
        g.disconnect(_), g.disconnect(w.inputs === void 0 ? w : w.inputs[0]), g.disconnect(S), w.disconnect(m), m.disconnect(b.inputs === void 0 ? b : b.inputs[0]), m.disconnect(T.inputs === void 0 ? T : T.inputs[0]), b.disconnect(_.gain), T.disconnect(S.gain), _.disconnect(y, 0, 0), S.disconnect(y, 0, 1);
      }
    };
  }, d = (p, g, m, y) => {
    const x = new Float32Array(16385), v = new Float32Array(16385), _ = new Float32Array(16385), b = new Float32Array(16385), w = Math.floor(16385 / 2);
    for (let P = 0; P < 16385; P += 1)
      if (P > w) {
        const N = (P - w) / (16384 - w) * l;
        x[P] = Math.cos(N), v[P] = Math.sin(N), _[P] = 0, b[P] = 1;
      } else {
        const N = P / (16384 - w) * l;
        x[P] = 1, v[P] = 0, _[P] = Math.cos(N), b[P] = Math.sin(N);
      }
    const S = t(p, {
      channelCount: 2,
      channelCountMode: "explicit",
      channelInterpretation: "discrete",
      numberOfOutputs: 2
    }), T = e(p, { ...c, gain: 0 }), k = s(p, {
      ...h,
      curve: x
    }), C = e(p, { ...c, gain: 0 }), M = s(p, {
      ...h,
      curve: v
    }), A = s(p, { ...h, curve: a }), I = e(p, { ...c, gain: 0 }), F = s(p, {
      ...h,
      curve: _
    }), R = e(p, { ...c, gain: 0 }), E = s(p, {
      ...h,
      curve: b
    });
    return {
      connectGraph() {
        g.connect(S), g.connect(A.inputs === void 0 ? A : A.inputs[0]), S.connect(T, 0), S.connect(C, 0), S.connect(I, 1), S.connect(R, 1), A.connect(m), m.connect(k.inputs === void 0 ? k : k.inputs[0]), m.connect(M.inputs === void 0 ? M : M.inputs[0]), m.connect(F.inputs === void 0 ? F : F.inputs[0]), m.connect(E.inputs === void 0 ? E : E.inputs[0]), k.connect(T.gain), M.connect(C.gain), F.connect(I.gain), E.connect(R.gain), T.connect(y, 0, 0), I.connect(y, 0, 0), C.connect(y, 0, 1), R.connect(y, 0, 1);
      },
      disconnectGraph() {
        g.disconnect(S), g.disconnect(A.inputs === void 0 ? A : A.inputs[0]), S.disconnect(T, 0), S.disconnect(C, 0), S.disconnect(I, 1), S.disconnect(R, 1), A.disconnect(m), m.disconnect(k.inputs === void 0 ? k : k.inputs[0]), m.disconnect(M.inputs === void 0 ? M : M.inputs[0]), m.disconnect(F.inputs === void 0 ? F : F.inputs[0]), m.disconnect(E.inputs === void 0 ? E : E.inputs[0]), k.disconnect(T.gain), M.disconnect(C.gain), F.disconnect(I.gain), E.disconnect(R.gain), T.disconnect(y, 0, 0), I.disconnect(y, 0, 0), C.disconnect(y, 0, 1), R.disconnect(y, 0, 1);
      }
    };
  }, f = (p, g, m, y, x) => {
    if (g === 1)
      return u(p, m, y, x);
    if (g === 2)
      return d(p, m, y, x);
    throw i();
  };
  return (p, { channelCount: g, channelCountMode: m, pan: y, ...x }) => {
    if (m === "max")
      throw i();
    const v = n(p, {
      ...x,
      channelCount: 1,
      channelCountMode: m,
      numberOfInputs: 2
    }), _ = e(p, { ...x, channelCount: g, channelCountMode: m, gain: 1 }), b = e(p, {
      channelCount: 1,
      channelCountMode: "explicit",
      channelInterpretation: "discrete",
      gain: y
    });
    let { connectGraph: w, disconnectGraph: S } = f(p, g, _, b, v);
    Object.defineProperty(b.gain, "defaultValue", { get: () => 0 }), Object.defineProperty(b.gain, "maxValue", { get: () => 1 }), Object.defineProperty(b.gain, "minValue", { get: () => -1 });
    const T = {
      get bufferSize() {
      },
      get channelCount() {
        return _.channelCount;
      },
      set channelCount(A) {
        _.channelCount !== A && (k && S(), { connectGraph: w, disconnectGraph: S } = f(p, A, _, b, v), k && w()), _.channelCount = A;
      },
      get channelCountMode() {
        return _.channelCountMode;
      },
      set channelCountMode(A) {
        if (A === "clamped-max" || A === "max")
          throw i();
        _.channelCountMode = A;
      },
      get channelInterpretation() {
        return _.channelInterpretation;
      },
      set channelInterpretation(A) {
        _.channelInterpretation = A;
      },
      get context() {
        return _.context;
      },
      get inputs() {
        return [_];
      },
      get numberOfInputs() {
        return _.numberOfInputs;
      },
      get numberOfOutputs() {
        return _.numberOfOutputs;
      },
      get pan() {
        return b.gain;
      },
      addEventListener(...A) {
        return _.addEventListener(A[0], A[1], A[2]);
      },
      dispatchEvent(...A) {
        return _.dispatchEvent(A[0]);
      },
      removeEventListener(...A) {
        return _.removeEventListener(A[0], A[1], A[2]);
      }
    };
    let k = !1;
    const C = () => {
      w(), k = !0;
    }, M = () => {
      S(), k = !1;
    };
    return r(ui(T, v), C, M);
  };
}, dT = (n, t, e, s, i, r, o) => (a, l) => {
  const c = a.createWaveShaper();
  if (r !== null && r.name === "webkitAudioContext" && a.createGain().gain.automationRate === void 0)
    return e(a, l);
  qt(c, l);
  const h = l.curve === null || l.curve instanceof Float32Array ? l.curve : new Float32Array(l.curve);
  if (h !== null && h.length < 2)
    throw t();
  wt(c, { curve: h }, "curve"), wt(c, l, "oversample");
  let u = null, d = !1;
  return o(c, "curve", (g) => () => g.call(c), (g) => (m) => (g.call(c, m), d && (s(m) && u === null ? u = n(a, c) : !s(m) && u !== null && (u(), u = null)), m)), i(c, () => {
    d = !0, s(c.curve) && (u = n(a, c));
  }, () => {
    d = !1, u !== null && (u(), u = null);
  });
}, fT = (n, t, e, s, i) => (r, { curve: o, oversample: a, ...l }) => {
  const c = r.createWaveShaper(), h = r.createWaveShaper();
  qt(c, l), qt(h, l);
  const u = e(r, { ...l, gain: 1 }), d = e(r, { ...l, gain: -1 }), f = e(r, { ...l, gain: 1 }), p = e(r, { ...l, gain: -1 });
  let g = null, m = !1, y = null;
  const x = {
    get bufferSize() {
    },
    get channelCount() {
      return c.channelCount;
    },
    set channelCount(b) {
      u.channelCount = b, d.channelCount = b, c.channelCount = b, f.channelCount = b, h.channelCount = b, p.channelCount = b;
    },
    get channelCountMode() {
      return c.channelCountMode;
    },
    set channelCountMode(b) {
      u.channelCountMode = b, d.channelCountMode = b, c.channelCountMode = b, f.channelCountMode = b, h.channelCountMode = b, p.channelCountMode = b;
    },
    get channelInterpretation() {
      return c.channelInterpretation;
    },
    set channelInterpretation(b) {
      u.channelInterpretation = b, d.channelInterpretation = b, c.channelInterpretation = b, f.channelInterpretation = b, h.channelInterpretation = b, p.channelInterpretation = b;
    },
    get context() {
      return c.context;
    },
    get curve() {
      return y;
    },
    set curve(b) {
      if (b !== null && b.length < 2)
        throw t();
      if (b === null)
        c.curve = b, h.curve = b;
      else {
        const w = b.length, S = new Float32Array(w + 2 - w % 2), T = new Float32Array(w + 2 - w % 2);
        S[0] = b[0], T[0] = -b[w - 1];
        const k = Math.ceil((w + 1) / 2), C = (w + 1) / 2 - 1;
        for (let M = 1; M < k; M += 1) {
          const A = M / k * C, I = Math.floor(A), F = Math.ceil(A);
          S[M] = I === F ? b[I] : (1 - (A - I)) * b[I] + (1 - (F - A)) * b[F], T[M] = I === F ? -b[w - 1 - I] : -((1 - (A - I)) * b[w - 1 - I]) - (1 - (F - A)) * b[w - 1 - F];
        }
        S[k] = w % 2 === 1 ? b[k - 1] : (b[k - 2] + b[k - 1]) / 2, c.curve = S, h.curve = T;
      }
      y = b, m && (s(y) && g === null ? g = n(r, u) : g !== null && (g(), g = null));
    },
    get inputs() {
      return [u];
    },
    get numberOfInputs() {
      return c.numberOfInputs;
    },
    get numberOfOutputs() {
      return c.numberOfOutputs;
    },
    get oversample() {
      return c.oversample;
    },
    set oversample(b) {
      c.oversample = b, h.oversample = b;
    },
    addEventListener(...b) {
      return u.addEventListener(b[0], b[1], b[2]);
    },
    dispatchEvent(...b) {
      return u.dispatchEvent(b[0]);
    },
    removeEventListener(...b) {
      return u.removeEventListener(b[0], b[1], b[2]);
    }
  };
  o !== null && (x.curve = o instanceof Float32Array ? o : new Float32Array(o)), a !== x.oversample && (x.oversample = a);
  const v = () => {
    u.connect(c).connect(f), u.connect(d).connect(h).connect(p).connect(f), m = !0, s(y) && (g = n(r, u));
  }, _ = () => {
    u.disconnect(c), c.disconnect(f), u.disconnect(d), d.disconnect(h), h.disconnect(p), p.disconnect(f), m = !1, g !== null && (g(), g = null);
  };
  return i(ui(x, f), v, _);
}, de = () => new DOMException("", "NotSupportedError"), pT = {
  numberOfChannels: 1
}, mT = (n, t, e, s, i) => class extends n {
  constructor(o, a, l) {
    let c;
    if (typeof o == "number" && a !== void 0 && l !== void 0)
      c = { length: a, numberOfChannels: o, sampleRate: l };
    else if (typeof o == "object")
      c = o;
    else
      throw new Error("The given parameters are not valid.");
    const { length: h, numberOfChannels: u, sampleRate: d } = { ...pT, ...c }, f = s(u, h, d);
    t(or, () => or(f)) || f.addEventListener("statechange", /* @__PURE__ */ (() => {
      let p = 0;
      const g = (m) => {
        this._state === "running" && (p > 0 ? (f.removeEventListener("statechange", g), m.stopImmediatePropagation(), this._waitForThePromiseToSettle(m)) : p += 1);
      };
      return g;
    })()), super(f, u), this._length = h, this._nativeOfflineAudioContext = f, this._state = null;
  }
  get length() {
    return this._nativeOfflineAudioContext.length === void 0 ? this._length : this._nativeOfflineAudioContext.length;
  }
  get state() {
    return this._state === null ? this._nativeOfflineAudioContext.state : this._state;
  }
  startRendering() {
    return this._state === "running" ? Promise.reject(e()) : (this._state = "running", i(this.destination, this._nativeOfflineAudioContext).finally(() => {
      this._state = null, Pm(this);
    }));
  }
  _waitForThePromiseToSettle(o) {
    this._state === null ? this._nativeOfflineAudioContext.dispatchEvent(o) : setTimeout(() => this._waitForThePromiseToSettle(o));
  }
}, gT = {
  channelCount: 2,
  channelCountMode: "max",
  // This attribute has no effect for nodes with no inputs.
  channelInterpretation: "speakers",
  // This attribute has no effect for nodes with no inputs.
  detune: 0,
  frequency: 440,
  periodicWave: void 0,
  type: "sine"
}, yT = (n, t, e, s, i, r, o) => class extends n {
  constructor(l, c) {
    const h = i(l), u = { ...gT, ...c }, d = e(h, u), f = r(h), p = f ? s() : null, g = l.sampleRate / 2;
    super(l, !1, d, p), this._detune = t(this, f, d.detune, 153600, -153600), this._frequency = t(this, f, d.frequency, g, -g), this._nativeOscillatorNode = d, this._onended = null, this._oscillatorNodeRenderer = p, this._oscillatorNodeRenderer !== null && u.periodicWave !== void 0 && (this._oscillatorNodeRenderer.periodicWave = u.periodicWave);
  }
  get detune() {
    return this._detune;
  }
  get frequency() {
    return this._frequency;
  }
  get onended() {
    return this._onended;
  }
  set onended(l) {
    const c = typeof l == "function" ? o(this, l) : null;
    this._nativeOscillatorNode.onended = c;
    const h = this._nativeOscillatorNode.onended;
    this._onended = h !== null && h === c ? l : h;
  }
  get type() {
    return this._nativeOscillatorNode.type;
  }
  set type(l) {
    this._nativeOscillatorNode.type = l, this._oscillatorNodeRenderer !== null && (this._oscillatorNodeRenderer.periodicWave = null);
  }
  setPeriodicWave(l) {
    this._nativeOscillatorNode.setPeriodicWave(l), this._oscillatorNodeRenderer !== null && (this._oscillatorNodeRenderer.periodicWave = l);
  }
  start(l = 0) {
    if (this._nativeOscillatorNode.start(l), this._oscillatorNodeRenderer !== null && (this._oscillatorNodeRenderer.start = l), this.context.state !== "closed") {
      ti(this);
      const c = () => {
        this._nativeOscillatorNode.removeEventListener("ended", c), As(this) && pr(this);
      };
      this._nativeOscillatorNode.addEventListener("ended", c);
    }
  }
  stop(l = 0) {
    this._nativeOscillatorNode.stop(l), this._oscillatorNodeRenderer !== null && (this._oscillatorNodeRenderer.stop = l);
  }
}, xT = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap();
  let o = null, a = null, l = null;
  const c = async (h, u) => {
    let d = e(h);
    const f = ne(d, u);
    if (!f) {
      const p = {
        channelCount: d.channelCount,
        channelCountMode: d.channelCountMode,
        channelInterpretation: d.channelInterpretation,
        detune: d.detune.value,
        frequency: d.frequency.value,
        periodicWave: o === null ? void 0 : o,
        type: d.type
      };
      d = t(u, p), a !== null && d.start(a), l !== null && d.stop(l);
    }
    return r.set(u, d), f ? (await n(u, h.detune, d.detune), await n(u, h.frequency, d.frequency)) : (await s(u, h.detune, d.detune), await s(u, h.frequency, d.frequency)), await i(h, u, d), d;
  };
  return {
    set periodicWave(h) {
      o = h;
    },
    set start(h) {
      a = h;
    },
    set stop(h) {
      l = h;
    },
    render(h, u) {
      const d = r.get(u);
      return d !== void 0 ? Promise.resolve(d) : c(h, u);
    }
  };
}, _T = {
  channelCount: 2,
  channelCountMode: "clamped-max",
  channelInterpretation: "speakers",
  coneInnerAngle: 360,
  coneOuterAngle: 360,
  coneOuterGain: 0,
  distanceModel: "inverse",
  maxDistance: 1e4,
  orientationX: 1,
  orientationY: 0,
  orientationZ: 0,
  panningModel: "equalpower",
  positionX: 0,
  positionY: 0,
  positionZ: 0,
  refDistance: 1,
  rolloffFactor: 1
}, vT = (n, t, e, s, i, r, o) => class extends n {
  constructor(l, c) {
    const h = i(l), u = { ..._T, ...c }, d = e(h, u), f = r(h), p = f ? s() : null;
    super(l, !1, d, p), this._nativePannerNode = d, this._orientationX = t(this, f, d.orientationX, re, ye), this._orientationY = t(this, f, d.orientationY, re, ye), this._orientationZ = t(this, f, d.orientationZ, re, ye), this._positionX = t(this, f, d.positionX, re, ye), this._positionY = t(this, f, d.positionY, re, ye), this._positionZ = t(this, f, d.positionZ, re, ye), o(this, 1);
  }
  get coneInnerAngle() {
    return this._nativePannerNode.coneInnerAngle;
  }
  set coneInnerAngle(l) {
    this._nativePannerNode.coneInnerAngle = l;
  }
  get coneOuterAngle() {
    return this._nativePannerNode.coneOuterAngle;
  }
  set coneOuterAngle(l) {
    this._nativePannerNode.coneOuterAngle = l;
  }
  get coneOuterGain() {
    return this._nativePannerNode.coneOuterGain;
  }
  set coneOuterGain(l) {
    this._nativePannerNode.coneOuterGain = l;
  }
  get distanceModel() {
    return this._nativePannerNode.distanceModel;
  }
  set distanceModel(l) {
    this._nativePannerNode.distanceModel = l;
  }
  get maxDistance() {
    return this._nativePannerNode.maxDistance;
  }
  set maxDistance(l) {
    this._nativePannerNode.maxDistance = l;
  }
  get orientationX() {
    return this._orientationX;
  }
  get orientationY() {
    return this._orientationY;
  }
  get orientationZ() {
    return this._orientationZ;
  }
  get panningModel() {
    return this._nativePannerNode.panningModel;
  }
  set panningModel(l) {
    this._nativePannerNode.panningModel = l;
  }
  get positionX() {
    return this._positionX;
  }
  get positionY() {
    return this._positionY;
  }
  get positionZ() {
    return this._positionZ;
  }
  get refDistance() {
    return this._nativePannerNode.refDistance;
  }
  set refDistance(l) {
    this._nativePannerNode.refDistance = l;
  }
  get rolloffFactor() {
    return this._nativePannerNode.rolloffFactor;
  }
  set rolloffFactor(l) {
    this._nativePannerNode.rolloffFactor = l;
  }
}, bT = (n, t, e, s, i, r, o, a, l, c) => () => {
  const h = /* @__PURE__ */ new WeakMap();
  let u = null;
  const d = async (f, p) => {
    let g = null, m = r(f);
    const y = {
      channelCount: m.channelCount,
      channelCountMode: m.channelCountMode,
      channelInterpretation: m.channelInterpretation
    }, x = {
      ...y,
      coneInnerAngle: m.coneInnerAngle,
      coneOuterAngle: m.coneOuterAngle,
      coneOuterGain: m.coneOuterGain,
      distanceModel: m.distanceModel,
      maxDistance: m.maxDistance,
      panningModel: m.panningModel,
      refDistance: m.refDistance,
      rolloffFactor: m.rolloffFactor
    }, v = ne(m, p);
    if ("bufferSize" in m)
      g = s(p, { ...y, gain: 1 });
    else if (!v) {
      const _ = {
        ...x,
        orientationX: m.orientationX.value,
        orientationY: m.orientationY.value,
        orientationZ: m.orientationZ.value,
        positionX: m.positionX.value,
        positionY: m.positionY.value,
        positionZ: m.positionZ.value
      };
      m = i(p, _);
    }
    if (h.set(p, g === null ? m : g), g !== null) {
      if (u === null) {
        if (o === null)
          throw new Error("Missing the native OfflineAudioContext constructor.");
        const M = new o(
          6,
          // Bug #17: Safari does not yet expose the length.
          f.context.length,
          p.sampleRate
        ), A = t(M, {
          channelCount: 1,
          channelCountMode: "explicit",
          channelInterpretation: "speakers",
          numberOfInputs: 6
        });
        A.connect(M.destination), u = (async () => {
          const I = await Promise.all([
            f.orientationX,
            f.orientationY,
            f.orientationZ,
            f.positionX,
            f.positionY,
            f.positionZ
          ].map(async (F, R) => {
            const E = e(M, {
              channelCount: 1,
              channelCountMode: "explicit",
              channelInterpretation: "discrete",
              offset: R === 0 ? 1 : 0
            });
            return await a(M, F, E.offset), E;
          }));
          for (let F = 0; F < 6; F += 1)
            I[F].connect(A, 0, F), I[F].start(0);
          return c(M);
        })();
      }
      const _ = await u, b = s(p, { ...y, gain: 1 });
      await l(f, p, b);
      const w = [];
      for (let M = 0; M < _.numberOfChannels; M += 1)
        w.push(_.getChannelData(M));
      let S = [w[0][0], w[1][0], w[2][0]], T = [w[3][0], w[4][0], w[5][0]], k = s(p, { ...y, gain: 1 }), C = i(p, {
        ...x,
        orientationX: S[0],
        orientationY: S[1],
        orientationZ: S[2],
        positionX: T[0],
        positionY: T[1],
        positionZ: T[2]
      });
      b.connect(k).connect(C.inputs[0]), C.connect(g);
      for (let M = 128; M < _.length; M += 128) {
        const A = [w[0][M], w[1][M], w[2][M]], I = [w[3][M], w[4][M], w[5][M]];
        if (A.some((F, R) => F !== S[R]) || I.some((F, R) => F !== T[R])) {
          S = A, T = I;
          const F = M / p.sampleRate;
          k.gain.setValueAtTime(0, F), k = s(p, { ...y, gain: 0 }), C = i(p, {
            ...x,
            orientationX: S[0],
            orientationY: S[1],
            orientationZ: S[2],
            positionX: T[0],
            positionY: T[1],
            positionZ: T[2]
          }), k.gain.setValueAtTime(1, F), b.connect(k).connect(C.inputs[0]), C.connect(g);
        }
      }
      return g;
    }
    return v ? (await n(p, f.orientationX, m.orientationX), await n(p, f.orientationY, m.orientationY), await n(p, f.orientationZ, m.orientationZ), await n(p, f.positionX, m.positionX), await n(p, f.positionY, m.positionY), await n(p, f.positionZ, m.positionZ)) : (await a(p, f.orientationX, m.orientationX), await a(p, f.orientationY, m.orientationY), await a(p, f.orientationZ, m.orientationZ), await a(p, f.positionX, m.positionX), await a(p, f.positionY, m.positionY), await a(p, f.positionZ, m.positionZ)), hi(m) ? await l(f, p, m.inputs[0]) : await l(f, p, m), m;
  };
  return {
    render(f, p) {
      const g = h.get(p);
      return g !== void 0 ? Promise.resolve(g) : d(f, p);
    }
  };
}, wT = {
  disableNormalization: !1
}, ST = (n, t, e, s) => class zm {
  constructor(r, o) {
    const a = t(r), l = s({ ...wT, ...o }), c = n(a, l);
    return e.add(c), c;
  }
  static [Symbol.hasInstance](r) {
    return r !== null && typeof r == "object" && Object.getPrototypeOf(r) === zm.prototype || e.has(r);
  }
}, TT = (n, t) => (e, s, i) => (n(s).replay(i), t(s, e, i)), MT = (n, t, e) => async (s, i, r) => {
  const o = n(s);
  await Promise.all(o.activeInputs.map((a, l) => Array.from(a).map(async ([c, h]) => {
    const d = await t(c).render(c, i), f = s.context.destination;
    !e(c) && (s !== f || !e(s)) && d.connect(r, h, l);
  })).reduce((a, l) => [...a, ...l], []));
}, kT = (n, t, e) => async (s, i, r) => {
  const o = t(s);
  await Promise.all(Array.from(o.activeInputs).map(async ([a, l]) => {
    const h = await n(a).render(a, i);
    e(a) || h.connect(r, l);
  }));
}, CT = (n, t, e, s) => (i) => n(or, () => or(i)) ? Promise.resolve(n(s, s)).then((r) => {
  if (!r) {
    const o = e(i, 512, 0, 1);
    i.oncomplete = () => {
      o.onaudioprocess = null, o.disconnect();
    }, o.onaudioprocess = () => i.currentTime, o.connect(i.destination);
  }
  return i.startRendering();
}) : new Promise((r) => {
  const o = t(i, {
    channelCount: 1,
    channelCountMode: "explicit",
    channelInterpretation: "discrete",
    gain: 0
  });
  i.oncomplete = (a) => {
    o.disconnect(), r(a.renderedBuffer);
  }, o.connect(i.destination), i.startRendering();
}), AT = (n) => (t, e) => {
  n.set(t, e);
}, ET = (n) => (t, e) => n.set(t, e), PT = (n, t, e, s, i, r, o, a) => (l, c) => e(l).render(l, c).then(() => Promise.all(Array.from(s(c)).map((h) => e(h).render(h, c)))).then(() => i(c)).then((h) => (typeof h.copyFromChannel != "function" ? (o(h), mc(h)) : t(r, () => r(h)) || a(h), n.add(h), h)), IT = {
  channelCount: 2,
  /*
   * Bug #105: The channelCountMode should be 'clamped-max' according to the spec but is set to 'explicit' to achieve consistent
   * behavior.
   */
  channelCountMode: "explicit",
  channelInterpretation: "speakers",
  pan: 0
}, FT = (n, t, e, s, i, r) => class extends n {
  constructor(a, l) {
    const c = i(a), h = { ...IT, ...l }, u = e(c, h), d = r(c), f = d ? s() : null;
    super(a, !1, u, f), this._pan = t(this, d, u.pan);
  }
  get pan() {
    return this._pan;
  }
}, RT = (n, t, e, s, i) => () => {
  const r = /* @__PURE__ */ new WeakMap(), o = async (a, l) => {
    let c = e(a);
    const h = ne(c, l);
    if (!h) {
      const u = {
        channelCount: c.channelCount,
        channelCountMode: c.channelCountMode,
        channelInterpretation: c.channelInterpretation,
        pan: c.pan.value
      };
      c = t(l, u);
    }
    return r.set(l, c), h ? await n(l, a.pan, c.pan) : await s(l, a.pan, c.pan), hi(c) ? await i(a, l, c.inputs[0]) : await i(a, l, c), c;
  };
  return {
    render(a, l) {
      const c = r.get(l);
      return c !== void 0 ? Promise.resolve(c) : o(a, l);
    }
  };
}, DT = (n) => () => {
  if (n === null)
    return !1;
  try {
    new n({ length: 1, sampleRate: 44100 });
  } catch {
    return !1;
  }
  return !0;
}, OT = (n) => () => {
  if (n === null)
    return !1;
  const e = new n(1, 1, 44100).createBuffer(1, 1, 44100);
  if (e.copyToChannel === void 0)
    return !0;
  const s = new Float32Array(2);
  try {
    e.copyFromChannel(s, 0, 0);
  } catch {
    return !1;
  }
  return !0;
}, NT = (n) => () => {
  if (n === null)
    return !1;
  if (n.prototype !== void 0 && n.prototype.close !== void 0)
    return !0;
  const t = new n(), e = t.close !== void 0;
  try {
    t.close();
  } catch {
  }
  return e;
}, LT = (n) => () => {
  if (n === null)
    return Promise.resolve(!1);
  const t = new n(1, 1, 44100);
  return new Promise((e) => {
    let s = !0;
    const i = (o) => {
      s && (s = !1, t.startRendering(), e(o instanceof TypeError));
    };
    let r;
    try {
      r = t.decodeAudioData(null, () => {
      }, i);
    } catch (o) {
      i(o);
    }
    r !== void 0 && r.catch(i);
  });
}, VT = (n) => () => {
  if (n === null)
    return !1;
  let t;
  try {
    t = new n({ latencyHint: "balanced" });
  } catch {
    return !1;
  }
  return t.close(), !0;
}, BT = (n) => () => {
  if (n === null)
    return !1;
  const e = new n(1, 1, 44100).createGain(), s = e.connect(e) === e;
  return e.disconnect(e), s;
}, zT = (n, t) => async () => {
  if (n === null)
    return !0;
  if (t === null)
    return !1;
  const e = new Blob([
    'let c,p;class A extends AudioWorkletProcessor{constructor(){super();this.port.onmessage=(e)=>{p=e.data;p.onmessage=()=>{p.postMessage(c);p.close()};this.port.postMessage(0)}}process(){c=1}}registerProcessor("a",A)'
  ], {
    type: "application/javascript; charset=utf-8"
  }), s = new MessageChannel(), i = new t(1, 128, 44100), r = URL.createObjectURL(e);
  let o = !1;
  try {
    await i.audioWorklet.addModule(r);
    const a = new n(i, "a", { numberOfOutputs: 0 }), l = i.createOscillator();
    await new Promise((c) => {
      a.port.onmessage = () => c(), a.port.postMessage(s.port2, [s.port2]);
    }), a.port.onmessage = () => o = !0, l.connect(a), l.start(0), await i.startRendering(), o = await new Promise((c) => {
      s.port1.onmessage = ({ data: h }) => c(h === 1), s.port1.postMessage(0);
    });
  } catch {
  } finally {
    s.port1.close(), URL.revokeObjectURL(r);
  }
  return o;
}, qT = (n, t) => async () => {
  if (n === null)
    return !0;
  if (t === null)
    return !1;
  const e = new Blob(['class A extends AudioWorkletProcessor{process(i){this.port.postMessage(i,[i[0][0].buffer])}}registerProcessor("a",A)'], {
    type: "application/javascript; charset=utf-8"
  }), s = new t(1, 128, 44100), i = URL.createObjectURL(e);
  let r = !1, o = !1;
  try {
    await s.audioWorklet.addModule(i);
    const a = new n(s, "a", { numberOfOutputs: 0 }), l = s.createOscillator();
    a.port.onmessage = () => r = !0, a.onprocessorerror = () => o = !0, l.connect(a), l.start(0), await s.startRendering(), await new Promise((c) => setTimeout(c));
  } catch {
  } finally {
    URL.revokeObjectURL(i);
  }
  return r && !o;
}, UT = (n) => () => {
  if (n === null)
    return !1;
  const e = new n(1, 1, 44100).createChannelMerger();
  if (e.channelCountMode === "max")
    return !0;
  try {
    e.channelCount = 2;
  } catch {
    return !0;
  }
  return !1;
}, GT = (n) => () => {
  if (n === null)
    return !1;
  const t = new n(1, 1, 44100);
  return t.createConstantSource === void 0 ? !0 : t.createConstantSource().offset.maxValue !== Number.POSITIVE_INFINITY;
}, WT = (n) => () => {
  if (n === null)
    return !1;
  const t = new n(1, 1, 44100), e = t.createConvolver();
  e.buffer = t.createBuffer(1, 1, t.sampleRate);
  try {
    e.buffer = t.createBuffer(1, 1, t.sampleRate);
  } catch {
    return !1;
  }
  return !0;
}, $T = (n) => () => {
  if (n === null)
    return !1;
  const e = new n(1, 1, 44100).createConvolver();
  try {
    e.channelCount = 1;
  } catch {
    return !1;
  }
  return !0;
}, HT = (n) => () => n !== null && n.hasOwnProperty("isSecureContext"), jT = (n) => () => {
  if (n === null)
    return !1;
  const t = new n();
  try {
    return t.createMediaStreamSource(new MediaStream()), !1;
  } catch {
    return !0;
  } finally {
    t.close();
  }
}, XT = (n, t) => () => {
  if (t === null)
    return Promise.resolve(!1);
  const e = new t(1, 1, 44100), s = n(e, {
    channelCount: 1,
    channelCountMode: "explicit",
    channelInterpretation: "discrete",
    gain: 0
  });
  return new Promise((i) => {
    e.oncomplete = () => {
      s.disconnect(), i(e.currentTime !== 0);
    }, e.startRendering();
  });
}, YT = (n) => () => {
  if (n === null)
    return Promise.resolve(!1);
  const t = new n(1, 1, 44100);
  if (t.createStereoPanner === void 0 || t.createConstantSource === void 0)
    return Promise.resolve(!0);
  const e = t.createConstantSource(), s = t.createStereoPanner();
  return e.channelCount = 1, e.offset.value = 1, s.channelCount = 1, e.start(), e.connect(s).connect(t.destination), t.startRendering().then((i) => i.getChannelData(0)[0] !== 1);
}, ZT = () => new DOMException("", "UnknownError"), KT = {
  channelCount: 2,
  channelCountMode: "max",
  channelInterpretation: "speakers",
  curve: null,
  oversample: "none"
}, QT = (n, t, e, s, i, r, o) => class extends n {
  constructor(l, c) {
    const h = i(l), u = { ...KT, ...c }, d = e(h, u), p = r(h) ? s() : null;
    super(l, !0, d, p), this._isCurveNullified = !1, this._nativeWaveShaperNode = d, o(this, 1);
  }
  get curve() {
    return this._isCurveNullified ? null : this._nativeWaveShaperNode.curve;
  }
  set curve(l) {
    if (l === null)
      this._isCurveNullified = !0, this._nativeWaveShaperNode.curve = new Float32Array([0, 0]);
    else {
      if (l.length < 2)
        throw t();
      this._isCurveNullified = !1, this._nativeWaveShaperNode.curve = l;
    }
  }
  get oversample() {
    return this._nativeWaveShaperNode.oversample;
  }
  set oversample(l) {
    this._nativeWaveShaperNode.oversample = l;
  }
}, JT = (n, t, e) => () => {
  const s = /* @__PURE__ */ new WeakMap(), i = async (r, o) => {
    let a = t(r);
    if (!ne(a, o)) {
      const c = {
        channelCount: a.channelCount,
        channelCountMode: a.channelCountMode,
        channelInterpretation: a.channelInterpretation,
        curve: a.curve,
        oversample: a.oversample
      };
      a = n(o, c);
    }
    return s.set(o, a), hi(a) ? await e(r, o, a.inputs[0]) : await e(r, o, a), a;
  };
  return {
    render(r, o) {
      const a = s.get(o);
      return a !== void 0 ? Promise.resolve(a) : i(r, o);
    }
  };
}, tM = () => typeof window > "u" ? null : window, eM = (n, t) => (e) => {
  e.copyFromChannel = (s, i, r = 0) => {
    const o = n(r), a = n(i);
    if (a >= e.numberOfChannels)
      throw t();
    const l = e.length, c = e.getChannelData(a), h = s.length;
    for (let u = o < 0 ? -o : 0; u + o < l && u < h; u += 1)
      s[u] = c[u + o];
  }, e.copyToChannel = (s, i, r = 0) => {
    const o = n(r), a = n(i);
    if (a >= e.numberOfChannels)
      throw t();
    const l = e.length, c = e.getChannelData(a), h = s.length;
    for (let u = o < 0 ? -o : 0; u + o < l && u < h; u += 1)
      c[u + o] = s[u];
  };
}, sM = (n) => (t) => {
  t.copyFromChannel = /* @__PURE__ */ ((e) => (s, i, r = 0) => {
    const o = n(r), a = n(i);
    if (o < t.length)
      return e.call(t, s, a, o);
  })(t.copyFromChannel), t.copyToChannel = /* @__PURE__ */ ((e) => (s, i, r = 0) => {
    const o = n(r), a = n(i);
    if (o < t.length)
      return e.call(t, s, a, o);
  })(t.copyToChannel);
}, nM = (n) => (t, e) => {
  const s = e.createBuffer(1, 1, 44100);
  t.buffer === null && (t.buffer = s), n(t, "buffer", (i) => () => {
    const r = i.call(t);
    return r === s ? null : r;
  }, (i) => (r) => i.call(t, r === null ? s : r));
}, iM = (n, t) => (e, s) => {
  s.channelCount = 1, s.channelCountMode = "explicit", Object.defineProperty(s, "channelCount", {
    get: () => 1,
    set: () => {
      throw n();
    }
  }), Object.defineProperty(s, "channelCountMode", {
    get: () => "explicit",
    set: () => {
      throw n();
    }
  });
  const i = e.createBufferSource();
  t(s, () => {
    const a = s.numberOfInputs;
    for (let l = 0; l < a; l += 1)
      i.connect(s, 0, l);
  }, () => i.disconnect(s));
}, qm = (n, t, e) => n.copyFromChannel === void 0 ? n.getChannelData(e)[0] : (n.copyFromChannel(t, e), t[0]), Um = (n) => {
  if (n === null)
    return !1;
  const t = n.length;
  return t % 2 !== 0 ? n[Math.floor(t / 2)] !== 0 : n[t / 2 - 1] + n[t / 2] !== 0;
}, _r = (n, t, e, s) => {
  let i = n;
  for (; !i.hasOwnProperty(t); )
    i = Object.getPrototypeOf(i);
  const { get: r, set: o } = Object.getOwnPropertyDescriptor(i, t);
  Object.defineProperty(n, t, { get: e(r), set: s(o) });
}, rM = (n) => ({
  ...n,
  outputChannelCount: n.outputChannelCount !== void 0 ? n.outputChannelCount : n.numberOfInputs === 1 && n.numberOfOutputs === 1 ? (
    /*
     * Bug #61: This should be the computedNumberOfChannels, but unfortunately that is almost impossible to fake. That's why
     * the channelCountMode is required to be 'explicit' as long as there is not a native implementation in every browser. That
     * makes sure the computedNumberOfChannels is equivilant to the channelCount which makes it much easier to compute.
     */
    [n.channelCount]
  ) : Array.from({ length: n.numberOfOutputs }, () => 1)
}), oM = (n) => ({ ...n, channelCount: n.numberOfOutputs }), aM = (n) => {
  const { imag: t, real: e } = n;
  return t === void 0 ? e === void 0 ? { ...n, imag: [0, 0], real: [0, 0] } : { ...n, imag: Array.from(e, () => 0), real: e } : e === void 0 ? { ...n, imag: t, real: Array.from(t, () => 0) } : { ...n, imag: t, real: e };
}, Gm = (n, t, e) => {
  try {
    n.setValueAtTime(t, e);
  } catch (s) {
    if (s.code !== 9)
      throw s;
    Gm(n, t, e + 1e-7);
  }
}, lM = (n) => {
  const t = n.createBufferSource();
  t.start();
  try {
    t.start();
  } catch {
    return !0;
  }
  return !1;
}, cM = (n) => {
  const t = n.createBufferSource(), e = n.createBuffer(1, 1, 44100);
  t.buffer = e;
  try {
    t.start(0, 1);
  } catch {
    return !1;
  }
  return !0;
}, hM = (n) => {
  const t = n.createBufferSource();
  t.start();
  try {
    t.stop();
  } catch {
    return !1;
  }
  return !0;
}, vc = (n) => {
  const t = n.createOscillator();
  try {
    t.start(-1);
  } catch (e) {
    return e instanceof RangeError;
  }
  return !1;
}, Wm = (n) => {
  const t = n.createBuffer(1, 1, 44100), e = n.createBufferSource();
  e.buffer = t, e.start(), e.stop();
  try {
    return e.stop(), !0;
  } catch {
    return !1;
  }
}, bc = (n) => {
  const t = n.createOscillator();
  try {
    t.stop(-1);
  } catch (e) {
    return e instanceof RangeError;
  }
  return !1;
}, uM = (n) => {
  const { port1: t, port2: e } = new MessageChannel();
  try {
    t.postMessage(n);
  } finally {
    t.close(), e.close();
  }
}, dM = () => {
  try {
    new DOMException();
  } catch {
    return !1;
  }
  return !0;
}, fM = () => new Promise((n) => {
  const t = new ArrayBuffer(0), { port1: e, port2: s } = new MessageChannel();
  e.onmessage = ({ data: i }) => n(i !== null), s.postMessage(t, [t]);
}), pM = (n) => {
  n.start = /* @__PURE__ */ ((t) => (e = 0, s = 0, i) => {
    const r = n.buffer, o = r === null ? s : Math.min(r.duration, s);
    r !== null && o > r.duration - 0.5 / n.context.sampleRate ? t.call(n, e, 0, 0) : t.call(n, e, o, i);
  })(n.start);
}, $m = (n, t) => {
  const e = t.createGain();
  n.connect(e);
  const s = /* @__PURE__ */ ((i) => () => {
    i.call(n, e), n.removeEventListener("ended", s);
  })(n.disconnect);
  n.addEventListener("ended", s), ui(n, e), n.stop = /* @__PURE__ */ ((i) => {
    let r = !1;
    return (o = 0) => {
      if (r)
        try {
          i.call(n, o);
        } catch {
          e.gain.setValueAtTime(0, o);
        }
      else
        i.call(n, o), r = !0;
    };
  })(n.stop);
}, di = (n, t) => (e) => {
  const s = { value: n };
  return Object.defineProperties(e, {
    currentTarget: s,
    target: s
  }), typeof t == "function" ? t.call(n, e) : t.handleEvent.call(n, e);
}, mM = _1(Cn), gM = M1(Cn), yM = Lw(Jo), Hm = /* @__PURE__ */ new WeakMap(), xM = eS(Hm), qe = fw(/* @__PURE__ */ new Map(), /* @__PURE__ */ new WeakMap()), Ke = tM(), jm = FS(qe, gs), wc = tS(le), Jt = MT(le, wc, Tn), _M = P1(jm, vt, Jt), xt = iS(Qo), Wt = rT(Ke), ft = bS(Wt), Xm = /* @__PURE__ */ new WeakMap(), Ym = jw(di), Ws = NS(Ke), Sc = yS(Ws), Tc = xS(Ke), Zm = _S(Ke), ei = VS(Ke), Nt = ew(v1(Sm), T1(mM, gM, Do, yM, Oo, le, xM, fr, vt, Cn, As, Tn, fo), qe, dS(Ol, Oo, le, vt, rr, As), gs, ta, de, Rw(Do, Ol, le, vt, rr, xt, As, ft), zw(Xm, le, Ze), Ym, xt, Sc, Tc, Zm, ft, ei), vM = E1(Nt, _M, gs, jm, xt, ft), Mc = /* @__PURE__ */ new WeakSet(), ef = RS(Ke), Km = kw(new Uint32Array(1)), kc = eM(Km, gs), Cc = sM(Km), Qm = F1(Mc, qe, de, ef, Wt, DT(ef), kc, Cc), ea = k1(be), Jm = kT(wc, mr, Tn), ys = vw(Jm), fi = OS(ea, qe, lM, cM, hM, vc, Wm, bc, pM, nM(_r), $m), xs = TT(sS(mr), Jm), bM = O1(ys, fi, vt, xs, Jt), ts = sw(b1(Tm), Xm, pc, nw, f1, p1, m1, g1, y1, Fl, bm, Ws, Gm), wM = D1(Nt, bM, ts, jt, fi, xt, ft, di), SM = W1(Nt, $1, gs, jt, LS(be, _r), xt, ft, Jt), TM = dw(ys, Vm, vt, xs, Jt), An = ET(Hm), MM = uw(Nt, ts, TM, ta, Vm, xt, ft, An), Qs = PS(Cn, Tc), kM = iM(jt, Qs), Js = $S(Ws, kM), CM = gw(Js, vt, Jt), AM = mw(Nt, CM, Js, xt, ft), EM = _w(yr, vt, Jt), PM = xw(Nt, EM, yr, xt, ft, oM), IM = XS(ea, fi, be, Qs), pi = jS(ea, qe, IM, vc, bc), FM = Mw(ys, pi, vt, xs, Jt), RM = Tw(Nt, ts, FM, pi, xt, ft, di), tg = YS(de, _r), DM = Ew(tg, vt, Jt), OM = Aw(Nt, DM, tg, xt, ft, An), NM = Nw(ys, Bm, vt, xs, Jt), LM = Ow(Nt, ts, NM, Bm, xt, ft, An), eg = ZS(de), VM = Ww(ys, eg, vt, xs, Jt), BM = Gw(Nt, ts, VM, eg, de, xt, ft, An), zM = Qw(ys, be, vt, xs, Jt), qM = Kw(Nt, ts, zM, be, xt, ft), UM = tT(ta, jt, xr, de), sa = CT(qe, be, xr, XT(be, Wt)), GM = uS(fi, vt, Wt, Jt, sa), WM = KS(UM), $M = cS(Nt, WM, GM, xt, ft, An), HM = H1(ts, Js, pi, xr, de, qm, ft, _r), sg = /* @__PURE__ */ new WeakMap(), jM = ES(SM, HM, Ym, ft, sg, di), ng = oT(ea, qe, vc, Wm, bc, $m), XM = xT(ys, ng, vt, xs, Jt), YM = yT(Nt, ts, ng, XM, xt, ft, di), ig = ww(fi), ZM = fT(ig, jt, be, Um, Qs), na = dT(ig, jt, ZM, Um, Qs, Ws, _r), KM = lT(Do, jt, Js, be, xr, na, de, Oo, qm, Qs), rg = aT(KM), QM = bT(ys, Js, pi, be, rg, vt, Wt, xs, Jt, sa), JM = vT(Nt, ts, rg, QM, xt, ft, An), tk = cT(gs), ek = ST(tk, xt, /* @__PURE__ */ new WeakSet(), aM), sk = uT(Js, yr, be, na, de, Qs), og = hT(sk, de), nk = RT(ys, og, vt, xs, Jt), ik = FT(Nt, ts, og, nk, xt, ft), rk = JT(na, vt, Jt), ok = QT(Nt, jt, na, rk, xt, ft, An), ag = wS(Ke), Ac = Xw(Ke), lg = /* @__PURE__ */ new WeakMap(), ak = rS(lg, Wt), lk = ag ? S1(
  qe,
  de,
  Hw(Ke),
  Ac,
  Yw(x1),
  xt,
  ak,
  ft,
  ei,
  /* @__PURE__ */ new WeakMap(),
  /* @__PURE__ */ new WeakMap(),
  qT(ei, Wt),
  // @todo window is guaranteed to be defined because isSecureContext checks that as well.
  Ke
) : void 0, ck = vS(Sc, ft), hk = Fw(Mc, qe, Iw, $w, /* @__PURE__ */ new WeakSet(), xt, ck, Fo, or, kc, Cc), cg = cw(lk, vM, Qm, wM, MM, AM, PM, RM, OM, hk, LM, BM, qM, $M, jM, YM, JM, ek, ik, ok), uk = TS(Nt, eT, xt, ft), dk = kS(Nt, sT, xt, ft), fk = CS(Nt, nT, xt, ft), pk = iT(jt, ft), mk = AS(Nt, pk, xt), gk = G1(cg, jt, de, ZT, uk, dk, fk, mk, Ws), Ec = oS(sg), yk = C1(Ec), hg = bw(gs), xk = Vw(Ec), ug = qw(gs), dg = /* @__PURE__ */ new WeakMap(), _k = Jw(dg, Ze), vk = WS(hg, gs, jt, Js, yr, pi, be, xr, de, ug, Ac, _k, Qs), bk = zS(jt, vk, be, de, Qs), wk = lw(ys, hg, fi, Js, yr, pi, be, xk, ug, Ac, vt, ei, Wt, xs, Jt, sa), Sk = nS(lg), Tk = AT(dg), sf = ag ? rw(yk, Nt, ts, wk, bk, le, Sk, xt, ft, ei, rM, Tk, uM, di) : void 0, Mk = Pw(de, Wt), kk = PT(Mc, qe, wc, Ec, sa, Fo, kc, Cc), Ck = mT(cg, qe, jt, Mk, kk), Ak = fS(Qo, Sc), Ek = pS(fc, Tc), Pk = mS(pc, Zm), Ik = gS(Qo, ft), Fk = () => SS(qe, OT(Wt), NT(Ws), LT(Wt), VT(Ws), BT(Wt), zT(ei, Wt), UT(Wt), GT(Wt), WT(Wt), $T(Wt), dM, HT(Ke), jT(Ws), YT(Wt), fM);
function ve(n) {
  return n === void 0;
}
function et(n) {
  return n !== void 0;
}
function fg(n) {
  return typeof n == "function";
}
function Ie(n) {
  return typeof n == "number";
}
function Es(n) {
  return Object.prototype.toString.call(n) === "[object Object]" && n.constructor === Object;
}
function Pc(n) {
  return typeof n == "boolean";
}
function Kt(n) {
  return Array.isArray(n);
}
function Qe(n) {
  return typeof n == "string";
}
function Ui(n) {
  return Qe(n) && /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i.test(n);
}
function X(n, t) {
  if (!n)
    throw new Error(t);
}
function zt(n, t, e = 1 / 0) {
  if (!(t <= n && n <= e))
    throw new RangeError(`Value must be within [${t}, ${e}], got: ${n}`);
}
function Ic(n) {
  !n.isOffline && n.state !== "running" && mi('The AudioContext is "suspended". Invoke Tone.start() from a user action to start the audio.');
}
let pg = !1, nf = !1;
function zl(n) {
  pg = n;
}
function mg(n) {
  ve(n) && pg && !nf && (nf = !0, mi("Events scheduled inside of scheduled callbacks should use the passed in scheduling time. See https://github.com/Tonejs/Tone.js/wiki/Accurate-Timing"));
}
let Fc = console;
function Rk(n) {
  Fc = n;
}
function gg(...n) {
  Fc.log(...n);
}
function mi(...n) {
  Fc.warn(...n);
}
const Dk = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  assert: X,
  assertContextRunning: Ic,
  assertRange: zt,
  assertUsedScheduleTime: mg,
  enterScheduledCallback: zl,
  log: gg,
  setLogger: Rk,
  warn: mi
}, Symbol.toStringTag, { value: "Module" }));
function Ok(n) {
  return new gk(n);
}
function Nk(n, t, e) {
  return new Ck(n, t, e);
}
const oe = typeof self == "object" ? self : null, Lk = oe && (oe.hasOwnProperty("AudioContext") || oe.hasOwnProperty("webkitAudioContext"));
function Vk(n, t, e) {
  return X(et(sf), "AudioWorkletNode only works in a secure context (https or localhost)"), new (n instanceof oe?.BaseAudioContext ? oe?.AudioWorkletNode : sf)(n, t, e);
}
function es(n, t, e, s) {
  var i = arguments.length, r = i < 3 ? t : s === null ? s = Object.getOwnPropertyDescriptor(t, e) : s, o;
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") r = Reflect.decorate(n, t, e, s);
  else for (var a = n.length - 1; a >= 0; a--) (o = n[a]) && (r = (i < 3 ? o(r) : i > 3 ? o(t, e, r) : o(t, e)) || r);
  return i > 3 && r && Object.defineProperty(t, e, r), r;
}
function yt(n, t, e, s) {
  function i(r) {
    return r instanceof e ? r : new e(function(o) {
      o(r);
    });
  }
  return new (e || (e = Promise))(function(r, o) {
    function a(h) {
      try {
        c(s.next(h));
      } catch (u) {
        o(u);
      }
    }
    function l(h) {
      try {
        c(s.throw(h));
      } catch (u) {
        o(u);
      }
    }
    function c(h) {
      h.done ? r(h.value) : i(h.value).then(a, l);
    }
    c((s = s.apply(n, t || [])).next());
  });
}
class Bk {
  constructor(t, e, s, i) {
    this._callback = t, this._type = e, this._minimumUpdateInterval = Math.max(128 / (i || 44100), 1e-3), this.updateInterval = s, this._createClock();
  }
  /**
   * Generate a web worker
   */
  _createWorker() {
    const t = new Blob([
      /* javascript */
      `
			// the initial timeout time
			let timeoutTime =  ${(this._updateInterval * 1e3).toFixed(1)};
			// onmessage callback
			self.onmessage = function(msg){
				timeoutTime = parseInt(msg.data);
			};
			// the tick function which posts a message
			// and schedules a new tick
			function tick(){
				setTimeout(tick, timeoutTime);
				self.postMessage('tick');
			}
			// call tick initially
			tick();
			`
    ], { type: "text/javascript" }), e = URL.createObjectURL(t), s = new Worker(e);
    s.onmessage = this._callback.bind(this), this._worker = s;
  }
  /**
   * Create a timeout loop
   */
  _createTimeout() {
    this._timeout = setTimeout(() => {
      this._createTimeout(), this._callback();
    }, this._updateInterval * 1e3);
  }
  /**
   * Create the clock source.
   */
  _createClock() {
    if (this._type === "worker")
      try {
        this._createWorker();
      } catch {
        this._type = "timeout", this._createClock();
      }
    else this._type === "timeout" && this._createTimeout();
  }
  /**
   * Clean up the current clock source
   */
  _disposeClock() {
    this._timeout && clearTimeout(this._timeout), this._worker && (this._worker.terminate(), this._worker.onmessage = null);
  }
  /**
   * The rate in seconds the ticker will update
   */
  get updateInterval() {
    return this._updateInterval;
  }
  set updateInterval(t) {
    var e;
    this._updateInterval = Math.max(t, this._minimumUpdateInterval), this._type === "worker" && ((e = this._worker) === null || e === void 0 || e.postMessage(this._updateInterval * 1e3));
  }
  /**
   * The type of the ticker, either a worker or a timeout
   */
  get type() {
    return this._type;
  }
  set type(t) {
    this._disposeClock(), this._type = t, this._createClock();
  }
  /**
   * Clean up
   */
  dispose() {
    this._disposeClock();
  }
}
function Mn(n) {
  return Pk(n);
}
function $s(n) {
  return Ek(n);
}
function po(n) {
  return Ik(n);
}
function qn(n) {
  return Ak(n);
}
function zk(n) {
  return n instanceof Qm;
}
function qk(n, t) {
  return n === "value" || Mn(t) || $s(t) || zk(t);
}
function Le(n, ...t) {
  if (!t.length)
    return n;
  const e = t.shift();
  if (Es(n) && Es(e))
    for (const s in e)
      qk(s, e[s]) ? n[s] = e[s] : Es(e[s]) ? (n[s] || Object.assign(n, { [s]: {} }), Le(n[s], e[s])) : Object.assign(n, { [s]: e[s] });
  return Le(n, ...t);
}
function Uk(n, t) {
  return n.length === t.length && n.every((e, s) => t[s] === e);
}
function L(n, t, e = [], s) {
  const i = {}, r = Array.from(t);
  if (Es(r[0]) && s && !Reflect.has(r[0], s) && (Object.keys(r[0]).some((a) => Reflect.has(n, a)) || (Le(i, { [s]: r[0] }), e.splice(e.indexOf(s), 1), r.shift())), r.length === 1 && Es(r[0]))
    Le(i, r[0]);
  else
    for (let o = 0; o < e.length; o++)
      et(r[o]) && (i[e[o]] = r[o]);
  return Le(n, i);
}
function Gk(n) {
  return n.constructor.getDefaults();
}
function Ve(n, t) {
  return ve(n) ? t : n;
}
function Yt(n, t) {
  return t.forEach((e) => {
    Reflect.has(n, e) && delete n[e];
  }), n;
}
let Ds = class {
  constructor() {
    this.debug = !1, this._wasDisposed = !1;
  }
  /**
   * Returns all of the default options belonging to the class.
   */
  static getDefaults() {
    return {};
  }
  /**
   * Prints the outputs to the console log for debugging purposes.
   * Prints the contents only if either the object has a property
   * called `debug` set to true, or a variable called TONE_DEBUG_CLASS
   * is set to the name of the class.
   * @example
   * const osc = new Tone.Oscillator();
   * // prints all logs originating from this oscillator
   * osc.debug = true;
   * // calls to start/stop will print in the console
   * osc.start();
   */
  log(...t) {
    (this.debug || oe && this.toString() === oe.TONE_DEBUG_CLASS) && gg(this, ...t);
  }
  /**
   * disconnect and dispose.
   */
  dispose() {
    return this._wasDisposed = !0, this;
  }
  /**
   * Indicates if the instance was disposed. 'Disposing' an
   * instance means that all of the Web Audio nodes that were
   * created for the instance are disconnected and freed for garbage collection.
   */
  get disposed() {
    return this._wasDisposed;
  }
  /**
   * Convert the class to a string
   * @example
   * const osc = new Tone.Oscillator();
   * console.log(osc.toString());
   */
  toString() {
    return this.name;
  }
};
Ds.version = uc;
const Rc = 1e-6;
function si(n, t) {
  return n > t + Rc;
}
function ql(n, t) {
  return si(n, t) || $e(n, t);
}
function Bo(n, t) {
  return n + Rc < t;
}
function $e(n, t) {
  return Math.abs(n - t) < Rc;
}
function En(n, t, e) {
  return Math.max(Math.min(n, e), t);
}
class Ee extends Ds {
  constructor() {
    super(), this.name = "Timeline", this._timeline = [];
    const t = L(Ee.getDefaults(), arguments, ["memory"]);
    this.memory = t.memory, this.increasing = t.increasing;
  }
  static getDefaults() {
    return {
      memory: 1 / 0,
      increasing: !1
    };
  }
  /**
   * The number of items in the timeline.
   */
  get length() {
    return this._timeline.length;
  }
  /**
   * Insert an event object onto the timeline. Events must have a "time" attribute.
   * @param event  The event object to insert into the timeline.
   */
  add(t) {
    if (X(Reflect.has(t, "time"), "Timeline: events must have a time attribute"), t.time = t.time.valueOf(), this.increasing && this.length) {
      const e = this._timeline[this.length - 1];
      X(ql(t.time, e.time), "The time must be greater than or equal to the last scheduled time"), this._timeline.push(t);
    } else {
      const e = this._search(t.time);
      this._timeline.splice(e + 1, 0, t);
    }
    if (this.length > this.memory) {
      const e = this.length - this.memory;
      this._timeline.splice(0, e);
    }
    return this;
  }
  /**
   * Remove an event from the timeline.
   * @param  {Object}  event  The event object to remove from the list.
   * @returns {Timeline} this
   */
  remove(t) {
    const e = this._timeline.indexOf(t);
    return e !== -1 && this._timeline.splice(e, 1), this;
  }
  /**
   * Get the nearest event whose time is less than or equal to the given time.
   * @param  time  The time to query.
   */
  get(t, e = "time") {
    const s = this._search(t, e);
    return s !== -1 ? this._timeline[s] : null;
  }
  /**
   * Return the first event in the timeline without removing it
   * @returns {Object} The first event object
   * @deprecated
   */
  peek() {
    return this._timeline[0];
  }
  /**
   * Return the first event in the timeline and remove it
   * @deprecated
   */
  shift() {
    return this._timeline.shift();
  }
  /**
   * Get the event which is scheduled after the given time.
   * @param  time  The time to query.
   */
  getAfter(t, e = "time") {
    const s = this._search(t, e);
    return s + 1 < this._timeline.length ? this._timeline[s + 1] : null;
  }
  /**
   * Get the event before the event at the given time.
   * @param  time  The time to query.
   */
  getBefore(t) {
    const e = this._timeline.length;
    if (e > 0 && this._timeline[e - 1].time < t)
      return this._timeline[e - 1];
    const s = this._search(t);
    return s - 1 >= 0 ? this._timeline[s - 1] : null;
  }
  /**
   * Cancel events at and after the given time
   * @param  after  The time to query.
   */
  cancel(t) {
    if (this._timeline.length > 1) {
      let e = this._search(t);
      if (e >= 0)
        if ($e(this._timeline[e].time, t)) {
          for (let s = e; s >= 0 && $e(this._timeline[s].time, t); s--)
            e = s;
          this._timeline = this._timeline.slice(0, e);
        } else
          this._timeline = this._timeline.slice(0, e + 1);
      else
        this._timeline = [];
    } else this._timeline.length === 1 && ql(this._timeline[0].time, t) && (this._timeline = []);
    return this;
  }
  /**
   * Cancel events before or equal to the given time.
   * @param  time  The time to cancel before.
   */
  cancelBefore(t) {
    const e = this._search(t);
    return e >= 0 && (this._timeline = this._timeline.slice(e + 1)), this;
  }
  /**
   * Returns the previous event if there is one. null otherwise
   * @param  event The event to find the previous one of
   * @return The event right before the given event
   */
  previousEvent(t) {
    const e = this._timeline.indexOf(t);
    return e > 0 ? this._timeline[e - 1] : null;
  }
  /**
   * Does a binary search on the timeline array and returns the
   * nearest event index whose time is after or equal to the given time.
   * If a time is searched before the first index in the timeline, -1 is returned.
   * If the time is after the end, the index of the last item is returned.
   */
  _search(t, e = "time") {
    if (this._timeline.length === 0)
      return -1;
    let s = 0;
    const i = this._timeline.length;
    let r = i;
    if (i > 0 && this._timeline[i - 1][e] <= t)
      return i - 1;
    for (; s < r; ) {
      let o = Math.floor(s + (r - s) / 2);
      const a = this._timeline[o], l = this._timeline[o + 1];
      if ($e(a[e], t)) {
        for (let c = o; c < this._timeline.length; c++) {
          const h = this._timeline[c];
          if ($e(h[e], t))
            o = c;
          else
            break;
        }
        return o;
      } else {
        if (Bo(a[e], t) && si(l[e], t))
          return o;
        si(a[e], t) ? r = o : s = o + 1;
      }
    }
    return -1;
  }
  /**
   * Internal iterator. Applies extra safety checks for
   * removing items from the array.
   */
  _iterate(t, e = 0, s = this._timeline.length - 1) {
    this._timeline.slice(e, s + 1).forEach(t);
  }
  /**
   * Iterate over everything in the array
   * @param  callback The callback to invoke with every item
   */
  forEach(t) {
    return this._iterate(t), this;
  }
  /**
   * Iterate over everything in the array at or before the given time.
   * @param  time The time to check if items are before
   * @param  callback The callback to invoke with every item
   */
  forEachBefore(t, e) {
    const s = this._search(t);
    return s !== -1 && this._iterate(e, 0, s), this;
  }
  /**
   * Iterate over everything in the array after the given time.
   * @param  time The time to check if items are before
   * @param  callback The callback to invoke with every item
   */
  forEachAfter(t, e) {
    const s = this._search(t);
    return this._iterate(e, s + 1), this;
  }
  /**
   * Iterate over everything in the array between the startTime and endTime.
   * The timerange is inclusive of the startTime, but exclusive of the endTime.
   * range = [startTime, endTime).
   * @param  startTime The time to check if items are before
   * @param  endTime The end of the test interval.
   * @param  callback The callback to invoke with every item
   */
  forEachBetween(t, e, s) {
    let i = this._search(t), r = this._search(e);
    return i !== -1 && r !== -1 ? (this._timeline[i].time !== t && (i += 1), this._timeline[r].time === e && (r -= 1), this._iterate(s, i, r)) : i === -1 && this._iterate(s, 0, r), this;
  }
  /**
   * Iterate over everything in the array at or after the given time. Similar to
   * forEachAfter, but includes the item(s) at the given time.
   * @param  time The time to check if items are before
   * @param  callback The callback to invoke with every item
   */
  forEachFrom(t, e) {
    let s = this._search(t);
    for (; s >= 0 && this._timeline[s].time >= t; )
      s--;
    return this._iterate(e, s + 1), this;
  }
  /**
   * Iterate over everything in the array at the given time
   * @param  time The time to check if items are before
   * @param  callback The callback to invoke with every item
   */
  forEachAtTime(t, e) {
    const s = this._search(t);
    if (s !== -1 && $e(this._timeline[s].time, t)) {
      let i = s;
      for (let r = s; r >= 0 && $e(this._timeline[r].time, t); r--)
        i = r;
      this._iterate((r) => {
        e(r);
      }, i, s);
    }
    return this;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._timeline = [], this;
  }
}
const yg = [];
function ia(n) {
  yg.push(n);
}
function Wk(n) {
  yg.forEach((t) => t(n));
}
const xg = [];
function ra(n) {
  xg.push(n);
}
function $k(n) {
  xg.forEach((t) => t(n));
}
class gi extends Ds {
  constructor() {
    super(...arguments), this.name = "Emitter";
  }
  /**
   * Bind a callback to a specific event.
   * @param  event     The name of the event to listen for.
   * @param  callback  The callback to invoke when the event is emitted
   */
  on(t, e) {
    return t.split(/\W+/).forEach((i) => {
      ve(this._events) && (this._events = {}), this._events.hasOwnProperty(i) || (this._events[i] = []), this._events[i].push(e);
    }), this;
  }
  /**
   * Bind a callback which is only invoked once
   * @param  event     The name of the event to listen for.
   * @param  callback  The callback to invoke when the event is emitted
   */
  once(t, e) {
    const s = (...i) => {
      e(...i), this.off(t, s);
    };
    return this.on(t, s), this;
  }
  /**
   * Remove the event listener.
   * @param  event     The event to stop listening to.
   * @param  callback  The callback which was bound to the event with Emitter.on.
   *                   If no callback is given, all callbacks events are removed.
   */
  off(t, e) {
    return t.split(/\W+/).forEach((i) => {
      if (ve(this._events) && (this._events = {}), this._events.hasOwnProperty(i))
        if (ve(e))
          this._events[i] = [];
        else {
          const r = this._events[i];
          for (let o = r.length - 1; o >= 0; o--)
            r[o] === e && r.splice(o, 1);
        }
    }), this;
  }
  /**
   * Invoke all of the callbacks bound to the event
   * with any arguments passed in.
   * @param  event  The name of the event.
   * @param args The arguments to pass to the functions listening.
   */
  emit(t, ...e) {
    if (this._events && this._events.hasOwnProperty(t)) {
      const s = this._events[t].slice(0);
      for (let i = 0, r = s.length; i < r; i++)
        s[i].apply(this, e);
    }
    return this;
  }
  /**
   * Add Emitter functions (on/off/emit) to the object
   */
  static mixin(t) {
    ["on", "once", "off", "emit"].forEach((e) => {
      const s = Object.getOwnPropertyDescriptor(gi.prototype, e);
      Object.defineProperty(t.prototype, e, s);
    });
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this._events = void 0, this;
  }
}
class Dc extends gi {
  constructor() {
    super(...arguments), this.isOffline = !1;
  }
  /*
   * This is a placeholder so that JSON.stringify does not throw an error
   * This matches what JSON.stringify(audioContext) returns on a native
   * audioContext instance.
   */
  toJSON() {
    return {};
  }
}
class yi extends Dc {
  constructor() {
    var t, e;
    super(), this.name = "Context", this._constants = /* @__PURE__ */ new Map(), this._timeouts = new Ee(), this._timeoutIds = 0, this._initialized = !1, this._closeStarted = !1, this.isOffline = !1, this._workletPromise = null;
    const s = L(yi.getDefaults(), arguments, [
      "context"
    ]);
    s.context ? (this._context = s.context, this._latencyHint = ((t = arguments[0]) === null || t === void 0 ? void 0 : t.latencyHint) || "") : (this._context = Ok({
      latencyHint: s.latencyHint
    }), this._latencyHint = s.latencyHint), this._ticker = new Bk(this.emit.bind(this, "tick"), s.clockSource, s.updateInterval, this._context.sampleRate), this.on("tick", this._timeoutLoop.bind(this)), this._context.onstatechange = () => {
      this.emit("statechange", this.state);
    }, this[!((e = arguments[0]) === null || e === void 0) && e.hasOwnProperty("updateInterval") ? "_lookAhead" : "lookAhead"] = s.lookAhead;
  }
  static getDefaults() {
    return {
      clockSource: "worker",
      latencyHint: "interactive",
      lookAhead: 0.1,
      updateInterval: 0.05
    };
  }
  /**
   * Finish setting up the context. **You usually do not need to do this manually.**
   */
  initialize() {
    return this._initialized || (Wk(this), this._initialized = !0), this;
  }
  //---------------------------
  // BASE AUDIO CONTEXT METHODS
  //---------------------------
  createAnalyser() {
    return this._context.createAnalyser();
  }
  createOscillator() {
    return this._context.createOscillator();
  }
  createBufferSource() {
    return this._context.createBufferSource();
  }
  createBiquadFilter() {
    return this._context.createBiquadFilter();
  }
  createBuffer(t, e, s) {
    return this._context.createBuffer(t, e, s);
  }
  createChannelMerger(t) {
    return this._context.createChannelMerger(t);
  }
  createChannelSplitter(t) {
    return this._context.createChannelSplitter(t);
  }
  createConstantSource() {
    return this._context.createConstantSource();
  }
  createConvolver() {
    return this._context.createConvolver();
  }
  createDelay(t) {
    return this._context.createDelay(t);
  }
  createDynamicsCompressor() {
    return this._context.createDynamicsCompressor();
  }
  createGain() {
    return this._context.createGain();
  }
  createIIRFilter(t, e) {
    return this._context.createIIRFilter(t, e);
  }
  createPanner() {
    return this._context.createPanner();
  }
  createPeriodicWave(t, e, s) {
    return this._context.createPeriodicWave(t, e, s);
  }
  createStereoPanner() {
    return this._context.createStereoPanner();
  }
  createWaveShaper() {
    return this._context.createWaveShaper();
  }
  createMediaStreamSource(t) {
    return X(qn(this._context), "Not available if OfflineAudioContext"), this._context.createMediaStreamSource(t);
  }
  createMediaElementSource(t) {
    return X(qn(this._context), "Not available if OfflineAudioContext"), this._context.createMediaElementSource(t);
  }
  createMediaStreamDestination() {
    return X(qn(this._context), "Not available if OfflineAudioContext"), this._context.createMediaStreamDestination();
  }
  decodeAudioData(t) {
    return this._context.decodeAudioData(t);
  }
  /**
   * The current time in seconds of the AudioContext.
   */
  get currentTime() {
    return this._context.currentTime;
  }
  /**
   * The current time in seconds of the AudioContext.
   */
  get state() {
    return this._context.state;
  }
  /**
   * The current time in seconds of the AudioContext.
   */
  get sampleRate() {
    return this._context.sampleRate;
  }
  /**
   * The listener
   */
  get listener() {
    return this.initialize(), this._listener;
  }
  set listener(t) {
    X(!this._initialized, "The listener cannot be set after initialization."), this._listener = t;
  }
  /**
   * There is only one Transport per Context. It is created on initialization.
   */
  get transport() {
    return this.initialize(), this._transport;
  }
  set transport(t) {
    X(!this._initialized, "The transport cannot be set after initialization."), this._transport = t;
  }
  /**
   * This is the Draw object for the context which is useful for synchronizing the draw frame with the Tone.js clock.
   */
  get draw() {
    return this.initialize(), this._draw;
  }
  set draw(t) {
    X(!this._initialized, "Draw cannot be set after initialization."), this._draw = t;
  }
  /**
   * A reference to the Context's destination node.
   */
  get destination() {
    return this.initialize(), this._destination;
  }
  set destination(t) {
    X(!this._initialized, "The destination cannot be set after initialization."), this._destination = t;
  }
  /**
   * Create an audio worklet node from a name and options. The module
   * must first be loaded using {@link addAudioWorkletModule}.
   */
  createAudioWorkletNode(t, e) {
    return Vk(this.rawContext, t, e);
  }
  /**
   * Add an AudioWorkletProcessor module
   * @param url The url of the module
   */
  addAudioWorkletModule(t) {
    return yt(this, void 0, void 0, function* () {
      X(et(this.rawContext.audioWorklet), "AudioWorkletNode is only available in a secure context (https or localhost)"), this._workletPromise || (this._workletPromise = this.rawContext.audioWorklet.addModule(t)), yield this._workletPromise;
    });
  }
  /**
   * Returns a promise which resolves when all of the worklets have been loaded on this context
   */
  workletsAreReady() {
    return yt(this, void 0, void 0, function* () {
      (yield this._workletPromise) ? this._workletPromise : Promise.resolve();
    });
  }
  //---------------------------
  // TICKER
  //---------------------------
  /**
   * How often the interval callback is invoked.
   * This number corresponds to how responsive the scheduling
   * can be. Setting to 0 will result in the lowest practial interval
   * based on context properties. context.updateInterval + context.lookAhead
   * gives you the total latency between scheduling an event and hearing it.
   */
  get updateInterval() {
    return this._ticker.updateInterval;
  }
  set updateInterval(t) {
    this._ticker.updateInterval = t;
  }
  /**
   * What the source of the clock is, either "worker" (default),
   * "timeout", or "offline" (none).
   */
  get clockSource() {
    return this._ticker.type;
  }
  set clockSource(t) {
    this._ticker.type = t;
  }
  /**
   * The amount of time into the future events are scheduled. Giving Web Audio
   * a short amount of time into the future to schedule events can reduce clicks and
   * improve performance. This value can be set to 0 to get the lowest latency.
   * Adjusting this value also affects the {@link updateInterval}.
   */
  get lookAhead() {
    return this._lookAhead;
  }
  set lookAhead(t) {
    this._lookAhead = t, this.updateInterval = t ? t / 2 : 0.01;
  }
  /**
   * The type of playback, which affects tradeoffs between audio
   * output latency and responsiveness.
   * In addition to setting the value in seconds, the latencyHint also
   * accepts the strings "interactive" (prioritizes low latency),
   * "playback" (prioritizes sustained playback), "balanced" (balances
   * latency and performance).
   * @example
   * // prioritize sustained playback
   * const context = new Tone.Context({ latencyHint: "playback" });
   * // set this context as the global Context
   * Tone.setContext(context);
   * // the global context is gettable with Tone.getContext()
   * console.log(Tone.getContext().latencyHint);
   */
  get latencyHint() {
    return this._latencyHint;
  }
  /**
   * The unwrapped AudioContext or OfflineAudioContext
   */
  get rawContext() {
    return this._context;
  }
  /**
   * The current audio context time plus a short {@link lookAhead}.
   * @example
   * setInterval(() => {
   * 	console.log("now", Tone.now());
   * }, 100);
   */
  now() {
    return this._context.currentTime + this._lookAhead;
  }
  /**
   * The current audio context time without the {@link lookAhead}.
   * In most cases it is better to use {@link now} instead of {@link immediate} since
   * with {@link now} the {@link lookAhead} is applied equally to _all_ components including internal components,
   * to making sure that everything is scheduled in sync. Mixing {@link now} and {@link immediate}
   * can cause some timing issues. If no lookAhead is desired, you can set the {@link lookAhead} to `0`.
   */
  immediate() {
    return this._context.currentTime;
  }
  /**
   * Starts the audio context from a suspended state. This is required
   * to initially start the AudioContext.
   * @see {@link start}
   */
  resume() {
    return qn(this._context) ? this._context.resume() : Promise.resolve();
  }
  /**
   * Close the context. Once closed, the context can no longer be used and
   * any AudioNodes created from the context will be silent.
   */
  close() {
    return yt(this, void 0, void 0, function* () {
      qn(this._context) && this.state !== "closed" && !this._closeStarted && (this._closeStarted = !0, yield this._context.close()), this._initialized && $k(this);
    });
  }
  /**
   * **Internal** Generate a looped buffer at some constant value.
   */
  getConstant(t) {
    if (this._constants.has(t))
      return this._constants.get(t);
    {
      const e = this._context.createBuffer(1, 128, this._context.sampleRate), s = e.getChannelData(0);
      for (let r = 0; r < s.length; r++)
        s[r] = t;
      const i = this._context.createBufferSource();
      return i.channelCount = 1, i.channelCountMode = "explicit", i.buffer = e, i.loop = !0, i.start(0), this._constants.set(t, i), i;
    }
  }
  /**
   * Clean up. Also closes the audio context.
   */
  dispose() {
    return super.dispose(), this._ticker.dispose(), this._timeouts.dispose(), Object.keys(this._constants).map((t) => this._constants[t].disconnect()), this.close(), this;
  }
  //---------------------------
  // TIMEOUTS
  //---------------------------
  /**
   * The private loop which keeps track of the context scheduled timeouts
   * Is invoked from the clock source
   */
  _timeoutLoop() {
    const t = this.now();
    this._timeouts.forEachBefore(t, (e) => {
      e.callback(), this._timeouts.remove(e);
    });
  }
  /**
   * A setTimeout which is guaranteed by the clock source.
   * Also runs in the offline context.
   * @param  fn       The callback to invoke
   * @param  timeout  The timeout in seconds
   * @returns ID to use when invoking Context.clearTimeout
   */
  setTimeout(t, e) {
    this._timeoutIds++;
    const s = this.now();
    return this._timeouts.add({
      callback: t,
      id: this._timeoutIds,
      time: s + e
    }), this._timeoutIds;
  }
  /**
   * Clears a previously scheduled timeout with Tone.context.setTimeout
   * @param  id  The ID returned from setTimeout
   */
  clearTimeout(t) {
    return this._timeouts.forEach((e) => {
      e.id === t && this._timeouts.remove(e);
    }), this;
  }
  /**
   * Clear the function scheduled by {@link setInterval}
   */
  clearInterval(t) {
    return this.clearTimeout(t);
  }
  /**
   * Adds a repeating event to the context's callback clock
   */
  setInterval(t, e) {
    const s = ++this._timeoutIds, i = () => {
      const r = this.now();
      this._timeouts.add({
        callback: () => {
          t(), i();
        },
        id: s,
        time: r + e
      });
    };
    return i(), s;
  }
}
class Hk extends Dc {
  constructor() {
    super(...arguments), this.lookAhead = 0, this.latencyHint = 0, this.isOffline = !1;
  }
  //---------------------------
  // BASE AUDIO CONTEXT METHODS
  //---------------------------
  createAnalyser() {
    return {};
  }
  createOscillator() {
    return {};
  }
  createBufferSource() {
    return {};
  }
  createBiquadFilter() {
    return {};
  }
  createBuffer(t, e, s) {
    return {};
  }
  createChannelMerger(t) {
    return {};
  }
  createChannelSplitter(t) {
    return {};
  }
  createConstantSource() {
    return {};
  }
  createConvolver() {
    return {};
  }
  createDelay(t) {
    return {};
  }
  createDynamicsCompressor() {
    return {};
  }
  createGain() {
    return {};
  }
  createIIRFilter(t, e) {
    return {};
  }
  createPanner() {
    return {};
  }
  createPeriodicWave(t, e, s) {
    return {};
  }
  createStereoPanner() {
    return {};
  }
  createWaveShaper() {
    return {};
  }
  createMediaStreamSource(t) {
    return {};
  }
  createMediaElementSource(t) {
    return {};
  }
  createMediaStreamDestination() {
    return {};
  }
  decodeAudioData(t) {
    return Promise.resolve({});
  }
  //---------------------------
  // TONE AUDIO CONTEXT METHODS
  //---------------------------
  createAudioWorkletNode(t, e) {
    return {};
  }
  get rawContext() {
    return {};
  }
  addAudioWorkletModule(t) {
    return yt(this, void 0, void 0, function* () {
      return Promise.resolve();
    });
  }
  resume() {
    return Promise.resolve();
  }
  setTimeout(t, e) {
    return 0;
  }
  clearTimeout(t) {
    return this;
  }
  setInterval(t, e) {
    return 0;
  }
  clearInterval(t) {
    return this;
  }
  getConstant(t) {
    return {};
  }
  get currentTime() {
    return 0;
  }
  get state() {
    return {};
  }
  get sampleRate() {
    return 0;
  }
  get listener() {
    return {};
  }
  get transport() {
    return {};
  }
  get draw() {
    return {};
  }
  set draw(t) {
  }
  get destination() {
    return {};
  }
  set destination(t) {
  }
  now() {
    return 0;
  }
  immediate() {
    return 0;
  }
}
function Z(n, t) {
  Kt(t) ? t.forEach((e) => Z(n, e)) : Object.defineProperty(n, t, {
    enumerable: !0,
    writable: !1
  });
}
function vr(n, t) {
  Kt(t) ? t.forEach((e) => vr(n, e)) : Object.defineProperty(n, t, {
    writable: !0
  });
}
const st = () => {
};
class ot extends Ds {
  constructor() {
    super(), this.name = "ToneAudioBuffer", this.onload = st;
    const t = L(ot.getDefaults(), arguments, ["url", "onload", "onerror"]);
    this.reverse = t.reverse, this.onload = t.onload, Qe(t.url) ? this.load(t.url).catch(t.onerror) : t.url && this.set(t.url);
  }
  static getDefaults() {
    return {
      onerror: st,
      onload: st,
      reverse: !1
    };
  }
  /**
   * The sample rate of the AudioBuffer
   */
  get sampleRate() {
    return this._buffer ? this._buffer.sampleRate : ut().sampleRate;
  }
  /**
   * Pass in an AudioBuffer or ToneAudioBuffer to set the value of this buffer.
   */
  set(t) {
    return t instanceof ot ? t.loaded ? this._buffer = t.get() : t.onload = () => {
      this.set(t), this.onload(this);
    } : this._buffer = t, this._reversed && this._reverse(), this;
  }
  /**
   * The audio buffer stored in the object.
   */
  get() {
    return this._buffer;
  }
  /**
   * Makes an fetch request for the selected url then decodes the file as an audio buffer.
   * Invokes the callback once the audio buffer loads.
   * @param url The url of the buffer to load. filetype support depends on the browser.
   * @returns A Promise which resolves with this ToneAudioBuffer
   */
  load(t) {
    return yt(this, void 0, void 0, function* () {
      const e = ot.load(t).then((s) => {
        this.set(s), this.onload(this);
      });
      ot.downloads.push(e);
      try {
        yield e;
      } finally {
        const s = ot.downloads.indexOf(e);
        ot.downloads.splice(s, 1);
      }
      return this;
    });
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), this._buffer = void 0, this;
  }
  /**
   * Set the audio buffer from the array.
   * To create a multichannel AudioBuffer, pass in a multidimensional array.
   * @param array The array to fill the audio buffer
   */
  fromArray(t) {
    const e = Kt(t) && t[0].length > 0, s = e ? t.length : 1, i = e ? t[0].length : t.length, r = ut(), o = r.createBuffer(s, i, r.sampleRate), a = !e && s === 1 ? [t] : t;
    for (let l = 0; l < s; l++)
      o.copyToChannel(a[l], l);
    return this._buffer = o, this;
  }
  /**
   * Sums multiple channels into 1 channel
   * @param chanNum Optionally only copy a single channel from the array.
   */
  toMono(t) {
    if (Ie(t))
      this.fromArray(this.toArray(t));
    else {
      let e = new Float32Array(this.length);
      const s = this.numberOfChannels;
      for (let i = 0; i < s; i++) {
        const r = this.toArray(i);
        for (let o = 0; o < r.length; o++)
          e[o] += r[o];
      }
      e = e.map((i) => i / s), this.fromArray(e);
    }
    return this;
  }
  /**
   * Get the buffer as an array. Single channel buffers will return a 1-dimensional
   * Float32Array, and multichannel buffers will return multidimensional arrays.
   * @param channel Optionally only copy a single channel from the array.
   */
  toArray(t) {
    if (Ie(t))
      return this.getChannelData(t);
    if (this.numberOfChannels === 1)
      return this.toArray(0);
    {
      const e = [];
      for (let s = 0; s < this.numberOfChannels; s++)
        e[s] = this.getChannelData(s);
      return e;
    }
  }
  /**
   * Returns the Float32Array representing the PCM audio data for the specific channel.
   * @param  channel  The channel number to return
   * @return The audio as a TypedArray
   */
  getChannelData(t) {
    return this._buffer ? this._buffer.getChannelData(t) : new Float32Array(0);
  }
  /**
   * Cut a subsection of the array and return a buffer of the
   * subsection. Does not modify the original buffer
   * @param start The time to start the slice
   * @param end The end time to slice. If none is given will default to the end of the buffer
   */
  slice(t, e = this.duration) {
    X(this.loaded, "Buffer is not loaded");
    const s = Math.floor(t * this.sampleRate), i = Math.floor(e * this.sampleRate);
    X(s < i, "The start time must be less than the end time");
    const r = i - s, o = ut().createBuffer(this.numberOfChannels, r, this.sampleRate);
    for (let a = 0; a < this.numberOfChannels; a++)
      o.copyToChannel(this.getChannelData(a).subarray(s, i), a);
    return new ot(o);
  }
  /**
   * Reverse the buffer.
   */
  _reverse() {
    if (this.loaded)
      for (let t = 0; t < this.numberOfChannels; t++)
        this.getChannelData(t).reverse();
    return this;
  }
  /**
   * If the buffer is loaded or not
   */
  get loaded() {
    return this.length > 0;
  }
  /**
   * The duration of the buffer in seconds.
   */
  get duration() {
    return this._buffer ? this._buffer.duration : 0;
  }
  /**
   * The length of the buffer in samples
   */
  get length() {
    return this._buffer ? this._buffer.length : 0;
  }
  /**
   * The number of discrete audio channels. Returns 0 if no buffer is loaded.
   */
  get numberOfChannels() {
    return this._buffer ? this._buffer.numberOfChannels : 0;
  }
  /**
   * Reverse the buffer.
   */
  get reverse() {
    return this._reversed;
  }
  set reverse(t) {
    this._reversed !== t && (this._reversed = t, this._reverse());
  }
  /**
   * Create a ToneAudioBuffer from the array. To create a multichannel AudioBuffer,
   * pass in a multidimensional array.
   * @param array The array to fill the audio buffer
   * @return A ToneAudioBuffer created from the array
   */
  static fromArray(t) {
    return new ot().fromArray(t);
  }
  /**
   * Creates a ToneAudioBuffer from a URL, returns a promise which resolves to a ToneAudioBuffer
   * @param  url The url to load.
   * @return A promise which resolves to a ToneAudioBuffer
   */
  static fromUrl(t) {
    return yt(this, void 0, void 0, function* () {
      return yield new ot().load(t);
    });
  }
  /**
   * Loads a url using fetch and returns the AudioBuffer.
   */
  static load(t) {
    return yt(this, void 0, void 0, function* () {
      const e = ot.baseUrl === "" || ot.baseUrl.endsWith("/") ? ot.baseUrl : ot.baseUrl + "/", s = yield fetch(e + t);
      if (!s.ok)
        throw new Error(`could not load url: ${t}`);
      const i = yield s.arrayBuffer();
      return yield ut().decodeAudioData(i);
    });
  }
  /**
   * Checks a url's extension to see if the current browser can play that file type.
   * @param url The url/extension to test
   * @return If the file extension can be played
   * @static
   * @example
   * Tone.ToneAudioBuffer.supportsType("wav"); // returns true
   * Tone.ToneAudioBuffer.supportsType("path/to/file.wav"); // returns true
   */
  static supportsType(t) {
    const e = t.split("."), s = e[e.length - 1];
    return document.createElement("audio").canPlayType("audio/" + s) !== "";
  }
  /**
   * Returns a Promise which resolves when all of the buffers have loaded
   */
  static loaded() {
    return yt(this, void 0, void 0, function* () {
      for (yield Promise.resolve(); ot.downloads.length; )
        yield ot.downloads[0];
    });
  }
}
ot.baseUrl = "";
ot.downloads = [];
class xi extends yi {
  constructor() {
    super({
      clockSource: "offline",
      context: po(arguments[0]) ? arguments[0] : Nk(arguments[0], arguments[1] * arguments[2], arguments[2]),
      lookAhead: 0,
      updateInterval: po(arguments[0]) ? 128 / arguments[0].sampleRate : 128 / arguments[2]
    }), this.name = "OfflineContext", this._currentTime = 0, this.isOffline = !0, this._duration = po(arguments[0]) ? arguments[0].length / arguments[0].sampleRate : arguments[1];
  }
  /**
   * Override the now method to point to the internal clock time
   */
  now() {
    return this._currentTime;
  }
  /**
   * Same as this.now()
   */
  get currentTime() {
    return this._currentTime;
  }
  /**
   * Render just the clock portion of the audio context.
   */
  _renderClock(t) {
    return yt(this, void 0, void 0, function* () {
      let e = 0;
      for (; this._duration - this._currentTime >= 0; ) {
        this.emit("tick"), this._currentTime += 128 / this.sampleRate, e++;
        const s = Math.floor(this.sampleRate / 128);
        t && e % s === 0 && (yield new Promise((i) => setTimeout(i, 1)));
      }
    });
  }
  /**
   * Render the output of the OfflineContext
   * @param asynchronous If the clock should be rendered asynchronously, which will not block the main thread, but be slightly slower.
   */
  render() {
    return yt(this, arguments, void 0, function* (t = !0) {
      yield this.workletsAreReady(), yield this._renderClock(t);
      const e = yield this._context.startRendering();
      return new ot(e);
    });
  }
  /**
   * Close the context
   */
  close() {
    return Promise.resolve();
  }
}
const _g = new Hk();
let xn = _g;
function ut() {
  return xn === _g && Lk && zo(new yi()), xn;
}
function zo(n, t = !1) {
  t && xn.dispose(), qn(n) ? xn = new yi(n) : po(n) ? xn = new xi(n) : xn = n;
}
function Oc() {
  return xn.resume();
}
if (oe && !oe.TONE_SILENCE_LOGGING) {
  const t = ` * Tone.js v${uc} * `;
  console.log(`%c${t}`, "background: #000; color: #fff");
}
function ni(n) {
  return Math.pow(10, n / 20);
}
function br(n) {
  return 20 * (Math.log(n) / Math.LN10);
}
function ii(n) {
  return Math.pow(2, n / 12);
}
let oa = 440;
function jk() {
  return oa;
}
function Xk(n) {
  oa = n;
}
function Us(n) {
  return Math.round(vg(n));
}
function vg(n) {
  return 69 + 12 * Math.log2(n / oa);
}
function Nc(n) {
  return oa * Math.pow(2, (n - 69) / 12);
}
class Lc extends Ds {
  /**
   * @param context The context associated with the time value. Used to compute
   * Transport and context-relative timing.
   * @param  value  The time value as a number, string or object
   * @param  units  Unit values
   */
  constructor(t, e, s) {
    super(), this.defaultUnits = "s", this._val = e, this._units = s, this.context = t, this._expressions = this._getExpressions();
  }
  /**
   * All of the time encoding expressions
   */
  _getExpressions() {
    return {
      hz: {
        method: (t) => this._frequencyToUnits(parseFloat(t)),
        regexp: /^(\d+(?:\.\d+)?)hz$/i
      },
      i: {
        method: (t) => this._ticksToUnits(parseInt(t, 10)),
        regexp: /^(\d+)i$/i
      },
      m: {
        method: (t) => this._beatsToUnits(parseInt(t, 10) * this._getTimeSignature()),
        regexp: /^(\d+)m$/i
      },
      n: {
        method: (t, e) => {
          const s = parseInt(t, 10), i = e === "." ? 1.5 : 1;
          return s === 1 ? this._beatsToUnits(this._getTimeSignature()) * i : this._beatsToUnits(4 / s) * i;
        },
        regexp: /^(\d+)n(\.?)$/i
      },
      number: {
        method: (t) => this._expressions[this.defaultUnits].method.call(this, t),
        regexp: /^(\d+(?:\.\d+)?)$/
      },
      s: {
        method: (t) => this._secondsToUnits(parseFloat(t)),
        regexp: /^(\d+(?:\.\d+)?)s$/
      },
      samples: {
        method: (t) => parseInt(t, 10) / this.context.sampleRate,
        regexp: /^(\d+)samples$/
      },
      t: {
        method: (t) => {
          const e = parseInt(t, 10);
          return this._beatsToUnits(8 / (Math.floor(e) * 3));
        },
        regexp: /^(\d+)t$/i
      },
      tr: {
        method: (t, e, s) => {
          let i = 0;
          return t && t !== "0" && (i += this._beatsToUnits(this._getTimeSignature() * parseFloat(t))), e && e !== "0" && (i += this._beatsToUnits(parseFloat(e))), s && s !== "0" && (i += this._beatsToUnits(parseFloat(s) / 4)), i;
        },
        regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?$/
      }
    };
  }
  //-------------------------------------
  // 	VALUE OF
  //-------------------------------------
  /**
   * Evaluate the time value. Returns the time in seconds.
   */
  valueOf() {
    if (this._val instanceof Lc && this.fromType(this._val), ve(this._val))
      return this._noArg();
    if (Qe(this._val) && ve(this._units)) {
      for (const t in this._expressions)
        if (this._expressions[t].regexp.test(this._val.trim())) {
          this._units = t;
          break;
        }
    } else if (Es(this._val)) {
      let t = 0;
      for (const e in this._val)
        if (et(this._val[e])) {
          const s = this._val[e], i = (
            // @ts-ignore
            new this.constructor(this.context, e).valueOf() * s
          );
          t += i;
        }
      return t;
    }
    if (et(this._units)) {
      const t = this._expressions[this._units], e = this._val.toString().trim().match(t.regexp);
      return e ? t.method.apply(this, e.slice(1)) : t.method.call(this, this._val);
    } else return Qe(this._val) ? parseFloat(this._val) : this._val;
  }
  //-------------------------------------
  // 	UNIT CONVERSIONS
  //-------------------------------------
  /**
   * Returns the value of a frequency in the current units
   */
  _frequencyToUnits(t) {
    return 1 / t;
  }
  /**
   * Return the value of the beats in the current units
   */
  _beatsToUnits(t) {
    return 60 / this._getBpm() * t;
  }
  /**
   * Returns the value of a second in the current units
   */
  _secondsToUnits(t) {
    return t;
  }
  /**
   * Returns the value of a tick in the current time units
   */
  _ticksToUnits(t) {
    return t * this._beatsToUnits(1) / this._getPPQ();
  }
  /**
   * With no arguments, return 'now'
   */
  _noArg() {
    return this._now();
  }
  //-------------------------------------
  // 	TEMPO CONVERSIONS
  //-------------------------------------
  /**
   * Return the bpm
   */
  _getBpm() {
    return this.context.transport.bpm.value;
  }
  /**
   * Return the timeSignature
   */
  _getTimeSignature() {
    return this.context.transport.timeSignature;
  }
  /**
   * Return the PPQ or 192 if Transport is not available
   */
  _getPPQ() {
    return this.context.transport.PPQ;
  }
  //-------------------------------------
  // 	CONVERSION INTERFACE
  //-------------------------------------
  /**
   * Coerce a time type into this units type.
   * @param type Any time type units
   */
  fromType(t) {
    switch (this._units = void 0, this.defaultUnits) {
      case "s":
        this._val = t.toSeconds();
        break;
      case "i":
        this._val = t.toTicks();
        break;
      case "hz":
        this._val = t.toFrequency();
        break;
      case "midi":
        this._val = t.toMidi();
        break;
    }
    return this;
  }
  /**
   * Return the value in hertz
   */
  toFrequency() {
    return 1 / this.toSeconds();
  }
  /**
   * Return the time in samples
   */
  toSamples() {
    return this.toSeconds() * this.context.sampleRate;
  }
  /**
   * Return the time in milliseconds.
   */
  toMilliseconds() {
    return this.toSeconds() * 1e3;
  }
}
class ke extends Lc {
  constructor() {
    super(...arguments), this.name = "TimeClass";
  }
  _getExpressions() {
    return Object.assign(super._getExpressions(), {
      now: {
        method: (t) => this._now() + new this.constructor(this.context, t).valueOf(),
        regexp: /^\+(.+)/
      },
      quantize: {
        method: (t) => {
          const e = new ke(this.context, t).valueOf();
          return this._secondsToUnits(this.context.transport.nextSubdivision(e));
        },
        regexp: /^@(.+)/
      }
    });
  }
  /**
   * Quantize the time by the given subdivision. Optionally add a
   * percentage which will move the time value towards the ideal
   * quantized value by that percentage.
   * @param  subdiv    The subdivision to quantize to
   * @param  percent  Move the time value towards the quantized value by a percentage.
   * @example
   * Tone.Time(21).quantize(2); // returns 22
   * Tone.Time(0.6).quantize("4n", 0.5); // returns 0.55
   */
  quantize(t, e = 1) {
    const s = new this.constructor(this.context, t).valueOf(), i = this.valueOf(), a = Math.round(i / s) * s - i;
    return i + a * e;
  }
  //-------------------------------------
  // CONVERSIONS
  //-------------------------------------
  /**
   * Convert a Time to Notation. The notation values are will be the
   * closest representation between 1m to 128th note.
   * @return {Notation}
   * @example
   * // if the Transport is at 120bpm:
   * Tone.Time(2).toNotation(); // returns "1m"
   */
  toNotation() {
    const t = this.toSeconds(), e = ["1m"];
    for (let r = 1; r < 9; r++) {
      const o = Math.pow(2, r);
      e.push(o + "n."), e.push(o + "n"), e.push(o + "t");
    }
    e.push("0");
    let s = e[0], i = new ke(this.context, e[0]).toSeconds();
    return e.forEach((r) => {
      const o = new ke(this.context, r).toSeconds();
      Math.abs(o - t) < Math.abs(i - t) && (s = r, i = o);
    }), s;
  }
  /**
   * Return the time encoded as Bars:Beats:Sixteenths.
   */
  toBarsBeatsSixteenths() {
    const t = this._beatsToUnits(1);
    let e = this.valueOf() / t;
    e = parseFloat(e.toFixed(4));
    const s = Math.floor(e / this._getTimeSignature());
    let i = e % 1 * 4;
    e = Math.floor(e) % this._getTimeSignature();
    const r = i.toString();
    return r.length > 3 && (i = parseFloat(parseFloat(r).toFixed(3))), [s, e, i].join(":");
  }
  /**
   * Return the time in ticks.
   */
  toTicks() {
    const t = this._beatsToUnits(1);
    return this.valueOf() / t * this._getPPQ();
  }
  /**
   * Return the time in seconds.
   */
  toSeconds() {
    return this.valueOf();
  }
  /**
   * Return the value as a midi note.
   */
  toMidi() {
    return Us(this.toFrequency());
  }
  _now() {
    return this.context.now();
  }
}
function Yk(n, t) {
  return new ke(ut(), n, t);
}
class ce extends ke {
  constructor() {
    super(...arguments), this.name = "Frequency", this.defaultUnits = "hz";
  }
  /**
   * The [concert tuning pitch](https://en.wikipedia.org/wiki/Concert_pitch) which is used
   * to generate all the other pitch values from notes. A4's values in Hertz.
   */
  static get A4() {
    return jk();
  }
  static set A4(t) {
    Xk(t);
  }
  //-------------------------------------
  // 	AUGMENT BASE EXPRESSIONS
  //-------------------------------------
  _getExpressions() {
    return Object.assign({}, super._getExpressions(), {
      midi: {
        regexp: /^(\d+(?:\.\d+)?midi)/,
        method(t) {
          return this.defaultUnits === "midi" ? t : ce.mtof(t);
        }
      },
      note: {
        regexp: /^([a-g]{1}(?:b|#|##|x|bb|###|#x|x#|bbb)?)(-?[0-9]+)/i,
        method(t, e) {
          const i = Zk[t.toLowerCase()] + (parseInt(e, 10) + 1) * 12;
          return this.defaultUnits === "midi" ? i : ce.mtof(i);
        }
      },
      tr: {
        regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,
        method(t, e, s) {
          let i = 1;
          return t && t !== "0" && (i *= this._beatsToUnits(this._getTimeSignature() * parseFloat(t))), e && e !== "0" && (i *= this._beatsToUnits(parseFloat(e))), s && s !== "0" && (i *= this._beatsToUnits(parseFloat(s) / 4)), i;
        }
      }
    });
  }
  //-------------------------------------
  // 	EXPRESSIONS
  //-------------------------------------
  /**
   * Transposes the frequency by the given number of semitones.
   * @return  A new transposed frequency
   * @example
   * Tone.Frequency("A4").transpose(3); // "C5"
   */
  transpose(t) {
    return new ce(this.context, this.valueOf() * ii(t));
  }
  /**
   * Takes an array of semitone intervals and returns
   * an array of frequencies transposed by those intervals.
   * @return  Returns an array of Frequencies
   * @example
   * Tone.Frequency("A4").harmonize([0, 3, 7]); // ["A4", "C5", "E5"]
   */
  harmonize(t) {
    return t.map((e) => this.transpose(e));
  }
  //-------------------------------------
  // 	UNIT CONVERSIONS
  //-------------------------------------
  /**
   * Return the value of the frequency as a MIDI note
   * @example
   * Tone.Frequency("C4").toMidi(); // 60
   */
  toMidi() {
    return Us(this.valueOf());
  }
  /**
   * Return the value of the frequency in Scientific Pitch Notation
   * @example
   * Tone.Frequency(69, "midi").toNote(); // "A4"
   */
  toNote() {
    const t = this.toFrequency(), e = Math.log2(t / ce.A4);
    let s = Math.round(12 * e) + 57;
    const i = Math.floor(s / 12);
    return i < 0 && (s += -12 * i), Kk[s % 12] + i.toString();
  }
  /**
   * Return the duration of one cycle in seconds.
   */
  toSeconds() {
    return 1 / super.toSeconds();
  }
  /**
   * Return the duration of one cycle in ticks
   */
  toTicks() {
    const t = this._beatsToUnits(1), e = this.valueOf() / t;
    return Math.floor(e * this._getPPQ());
  }
  //-------------------------------------
  // 	UNIT CONVERSIONS HELPERS
  //-------------------------------------
  /**
   * With no arguments, return 0
   */
  _noArg() {
    return 0;
  }
  /**
   * Returns the value of a frequency in the current units
   */
  _frequencyToUnits(t) {
    return t;
  }
  /**
   * Returns the value of a tick in the current time units
   */
  _ticksToUnits(t) {
    return 1 / (t * 60 / (this._getBpm() * this._getPPQ()));
  }
  /**
   * Return the value of the beats in the current units
   */
  _beatsToUnits(t) {
    return 1 / super._beatsToUnits(t);
  }
  /**
   * Returns the value of a second in the current units
   */
  _secondsToUnits(t) {
    return 1 / t;
  }
  /**
   * Convert a MIDI note to frequency value.
   * @param  midi The midi number to convert.
   * @return The corresponding frequency value
   */
  static mtof(t) {
    return Nc(t);
  }
  /**
   * Convert a frequency value to a MIDI note.
   * @param frequency The value to frequency value to convert.
   */
  static ftom(t) {
    return Us(t);
  }
}
const Zk = {
  cbbb: -3,
  cbb: -2,
  cb: -1,
  c: 0,
  "c#": 1,
  cx: 2,
  "c##": 2,
  "c###": 3,
  "cx#": 3,
  "c#x": 3,
  dbbb: -1,
  dbb: 0,
  db: 1,
  d: 2,
  "d#": 3,
  dx: 4,
  "d##": 4,
  "d###": 5,
  "dx#": 5,
  "d#x": 5,
  ebbb: 1,
  ebb: 2,
  eb: 3,
  e: 4,
  "e#": 5,
  ex: 6,
  "e##": 6,
  "e###": 7,
  "ex#": 7,
  "e#x": 7,
  fbbb: 2,
  fbb: 3,
  fb: 4,
  f: 5,
  "f#": 6,
  fx: 7,
  "f##": 7,
  "f###": 8,
  "fx#": 8,
  "f#x": 8,
  gbbb: 4,
  gbb: 5,
  gb: 6,
  g: 7,
  "g#": 8,
  gx: 9,
  "g##": 9,
  "g###": 10,
  "gx#": 10,
  "g#x": 10,
  abbb: 6,
  abb: 7,
  ab: 8,
  a: 9,
  "a#": 10,
  ax: 11,
  "a##": 11,
  "a###": 12,
  "ax#": 12,
  "a#x": 12,
  bbbb: 8,
  bbb: 9,
  bb: 10,
  b: 11,
  "b#": 12,
  bx: 13,
  "b##": 13,
  "b###": 14,
  "bx#": 14,
  "b#x": 14
}, Kk = [
  "C",
  "C#",
  "D",
  "D#",
  "E",
  "F",
  "F#",
  "G",
  "G#",
  "A",
  "A#",
  "B"
];
function Qk(n, t) {
  return new ce(ut(), n, t);
}
class Lt extends ke {
  constructor() {
    super(...arguments), this.name = "TransportTime";
  }
  /**
   * Return the current time in whichever context is relevant
   */
  _now() {
    return this.context.transport.seconds;
  }
}
function Jk(n, t) {
  return new Lt(ut(), n, t);
}
class Xt extends Ds {
  constructor() {
    super();
    const t = L(Xt.getDefaults(), arguments, ["context"]);
    this.defaultContext ? this.context = this.defaultContext : this.context = t.context;
  }
  static getDefaults() {
    return {
      context: ut()
    };
  }
  /**
   * Return the current time of the Context clock plus the lookAhead.
   * @example
   * setInterval(() => {
   * 	console.log(Tone.now());
   * }, 100);
   */
  now() {
    return this.context.currentTime + this.context.lookAhead;
  }
  /**
   * Return the current time of the Context clock without any lookAhead.
   * @example
   * setInterval(() => {
   * 	console.log(Tone.immediate());
   * }, 100);
   */
  immediate() {
    return this.context.currentTime;
  }
  /**
   * The duration in seconds of one sample.
   */
  get sampleTime() {
    return 1 / this.context.sampleRate;
  }
  /**
   * The number of seconds of 1 processing block (128 samples)
   * @example
   * console.log(Tone.Destination.blockTime);
   */
  get blockTime() {
    return 128 / this.context.sampleRate;
  }
  /**
   * Convert the incoming time to seconds.
   * This is calculated against the current {@link TransportClass} bpm
   * @example
   * const gain = new Tone.Gain();
   * setInterval(() => console.log(gain.toSeconds("4n")), 100);
   * // ramp the tempo to 60 bpm over 30 seconds
   * Tone.getTransport().bpm.rampTo(60, 30);
   */
  toSeconds(t) {
    return mg(t), new ke(this.context, t).toSeconds();
  }
  /**
   * Convert the input to a frequency number
   * @example
   * const gain = new Tone.Gain();
   * console.log(gain.toFrequency("4n"));
   */
  toFrequency(t) {
    return new ce(this.context, t).toFrequency();
  }
  /**
   * Convert the input time into ticks
   * @example
   * const gain = new Tone.Gain();
   * console.log(gain.toTicks("4n"));
   */
  toTicks(t) {
    return new Lt(this.context, t).toTicks();
  }
  //-------------------------------------
  // 	GET/SET
  //-------------------------------------
  /**
   * Get a subset of the properties which are in the partial props
   */
  _getPartialProperties(t) {
    const e = this.get();
    return Object.keys(e).forEach((s) => {
      ve(t[s]) && delete e[s];
    }), e;
  }
  /**
   * Get the object's attributes.
   * @example
   * const osc = new Tone.Oscillator();
   * console.log(osc.get());
   */
  get() {
    const t = Gk(this);
    return Object.keys(t).forEach((e) => {
      if (Reflect.has(this, e)) {
        const s = this[e];
        et(s) && et(s.value) && et(s.setValueAtTime) ? t[e] = s.value : s instanceof Xt ? t[e] = s._getPartialProperties(t[e]) : Kt(s) || Ie(s) || Qe(s) || Pc(s) ? t[e] = s : delete t[e];
      }
    }), t;
  }
  /**
   * Set multiple properties at once with an object.
   * @example
   * const filter = new Tone.Filter().toDestination();
   * // set values using an object
   * filter.set({
   * 	frequency: "C6",
   * 	type: "highpass"
   * });
   * const player = new Tone.Player("https://tonejs.github.io/audio/berklee/Analogsynth_octaves_highmid.mp3").connect(filter);
   * player.autostart = true;
   */
  set(t) {
    return Object.keys(t).forEach((e) => {
      Reflect.has(this, e) && et(this[e]) && (this[e] && et(this[e].value) && et(this[e].setValueAtTime) ? this[e].value !== t[e] && (this[e].value = t[e]) : this[e] instanceof Xt ? this[e].set(t[e]) : this[e] = t[e]);
    }), this;
  }
}
class _i extends Ee {
  constructor(t = "stopped") {
    super(), this.name = "StateTimeline", this._initial = t, this.setStateAtTime(this._initial, 0);
  }
  /**
   * Returns the scheduled state scheduled before or at
   * the given time.
   * @param  time  The time to query.
   * @return  The name of the state input in setStateAtTime.
   */
  getValueAtTime(t) {
    const e = this.get(t);
    return e !== null ? e.state : this._initial;
  }
  /**
   * Add a state to the timeline.
   * @param  state The name of the state to set.
   * @param  time  The time to query.
   * @param options Any additional options that are needed in the timeline.
   */
  setStateAtTime(t, e, s) {
    return zt(e, 0), this.add(Object.assign({}, s, {
      state: t,
      time: e
    })), this;
  }
  /**
   * Return the event before the time with the given state
   * @param  state The state to look for
   * @param  time  When to check before
   * @return  The event with the given state before the time
   */
  getLastState(t, e) {
    const s = this._search(e);
    for (let i = s; i >= 0; i--) {
      const r = this._timeline[i];
      if (r.state === t)
        return r;
    }
  }
  /**
   * Return the event after the time with the given state
   * @param  state The state to look for
   * @param  time  When to check from
   * @return  The event with the given state after the time
   */
  getNextState(t, e) {
    const s = this._search(e);
    if (s !== -1)
      for (let i = s; i < this._timeline.length; i++) {
        const r = this._timeline[i];
        if (r.state === t)
          return r;
      }
  }
}
class tt extends Xt {
  constructor() {
    const t = L(tt.getDefaults(), arguments, [
      "param",
      "units",
      "convert"
    ]);
    for (super(t), this.name = "Param", this.overridden = !1, this._minOutput = 1e-7, X(et(t.param) && (Mn(t.param) || t.param instanceof tt), "param must be an AudioParam"); !Mn(t.param); )
      t.param = t.param._param;
    this._swappable = et(t.swappable) ? t.swappable : !1, this._swappable ? (this.input = this.context.createGain(), this._param = t.param, this.input.connect(this._param)) : this._param = this.input = t.param, this._events = new Ee(1e3), this._initialValue = this._param.defaultValue, this.units = t.units, this.convert = t.convert, this._minValue = t.minValue, this._maxValue = t.maxValue, et(t.value) && t.value !== this._toType(this._initialValue) && this.setValueAtTime(t.value, 0);
  }
  static getDefaults() {
    return Object.assign(Xt.getDefaults(), {
      convert: !0,
      units: "number"
    });
  }
  get value() {
    const t = this.now();
    return this.getValueAtTime(t);
  }
  set value(t) {
    this.cancelScheduledValues(this.now()), this.setValueAtTime(t, this.now());
  }
  get minValue() {
    return et(this._minValue) ? this._minValue : this.units === "time" || this.units === "frequency" || this.units === "normalRange" || this.units === "positive" || this.units === "transportTime" || this.units === "ticks" || this.units === "bpm" || this.units === "hertz" || this.units === "samples" ? 0 : this.units === "audioRange" ? -1 : this.units === "decibels" ? -1 / 0 : this._param.minValue;
  }
  get maxValue() {
    return et(this._maxValue) ? this._maxValue : this.units === "normalRange" || this.units === "audioRange" ? 1 : this._param.maxValue;
  }
  /**
   * Type guard based on the unit name
   */
  _is(t, e) {
    return this.units === e;
  }
  /**
   * Make sure the value is always in the defined range
   */
  _assertRange(t) {
    return et(this.maxValue) && et(this.minValue) && zt(t, this._fromType(this.minValue), this._fromType(this.maxValue)), t;
  }
  /**
   * Convert the given value from the type specified by Param.units
   * into the destination value (such as Gain or Frequency).
   */
  _fromType(t) {
    return this.convert && !this.overridden ? this._is(t, "time") ? this.toSeconds(t) : this._is(t, "decibels") ? ni(t) : this._is(t, "frequency") ? this.toFrequency(t) : t : this.overridden ? 0 : t;
  }
  /**
   * Convert the parameters value into the units specified by Param.units.
   */
  _toType(t) {
    return this.convert && this.units === "decibels" ? br(t) : t;
  }
  //-------------------------------------
  // ABSTRACT PARAM INTERFACE
  // all docs are generated from ParamInterface.ts
  //-------------------------------------
  setValueAtTime(t, e) {
    const s = this.toSeconds(e), i = this._fromType(t);
    return X(isFinite(i) && isFinite(s), `Invalid argument(s) to setValueAtTime: ${JSON.stringify(t)}, ${JSON.stringify(e)}`), this._assertRange(i), this.log(this.units, "setValueAtTime", t, s), this._events.add({
      time: s,
      type: "setValueAtTime",
      value: i
    }), this._param.setValueAtTime(i, s), this;
  }
  getValueAtTime(t) {
    const e = Math.max(this.toSeconds(t), 0), s = this._events.getAfter(e), i = this._events.get(e);
    let r = this._initialValue;
    if (i === null)
      r = this._initialValue;
    else if (i.type === "setTargetAtTime" && (s === null || s.type === "setValueAtTime")) {
      const o = this._events.getBefore(i.time);
      let a;
      o === null ? a = this._initialValue : a = o.value, i.type === "setTargetAtTime" && (r = this._exponentialApproach(i.time, a, i.value, i.constant, e));
    } else if (s === null)
      r = i.value;
    else if (s.type === "linearRampToValueAtTime" || s.type === "exponentialRampToValueAtTime") {
      let o = i.value;
      if (i.type === "setTargetAtTime") {
        const a = this._events.getBefore(i.time);
        a === null ? o = this._initialValue : o = a.value;
      }
      s.type === "linearRampToValueAtTime" ? r = this._linearInterpolate(i.time, o, s.time, s.value, e) : r = this._exponentialInterpolate(i.time, o, s.time, s.value, e);
    } else
      r = i.value;
    return this._toType(r);
  }
  setRampPoint(t) {
    t = this.toSeconds(t);
    let e = this.getValueAtTime(t);
    return this.cancelAndHoldAtTime(t), this._fromType(e) === 0 && (e = this._toType(this._minOutput)), this.setValueAtTime(e, t), this;
  }
  linearRampToValueAtTime(t, e) {
    const s = this._fromType(t), i = this.toSeconds(e);
    return X(isFinite(s) && isFinite(i), `Invalid argument(s) to linearRampToValueAtTime: ${JSON.stringify(t)}, ${JSON.stringify(e)}`), this._assertRange(s), this._events.add({
      time: i,
      type: "linearRampToValueAtTime",
      value: s
    }), this.log(this.units, "linearRampToValueAtTime", t, i), this._param.linearRampToValueAtTime(s, i), this;
  }
  exponentialRampToValueAtTime(t, e) {
    let s = this._fromType(t);
    s = $e(s, 0) ? this._minOutput : s, this._assertRange(s);
    const i = this.toSeconds(e);
    return X(isFinite(s) && isFinite(i), `Invalid argument(s) to exponentialRampToValueAtTime: ${JSON.stringify(t)}, ${JSON.stringify(e)}`), this._events.add({
      time: i,
      type: "exponentialRampToValueAtTime",
      value: s
    }), this.log(this.units, "exponentialRampToValueAtTime", t, i), this._param.exponentialRampToValueAtTime(s, i), this;
  }
  exponentialRampTo(t, e, s) {
    return s = this.toSeconds(s), this.setRampPoint(s), this.exponentialRampToValueAtTime(t, s + this.toSeconds(e)), this;
  }
  linearRampTo(t, e, s) {
    return s = this.toSeconds(s), this.setRampPoint(s), this.linearRampToValueAtTime(t, s + this.toSeconds(e)), this;
  }
  targetRampTo(t, e, s) {
    return s = this.toSeconds(s), this.setRampPoint(s), this.exponentialApproachValueAtTime(t, s, e), this;
  }
  exponentialApproachValueAtTime(t, e, s) {
    e = this.toSeconds(e), s = this.toSeconds(s);
    const i = Math.log(s + 1) / Math.log(200);
    return this.setTargetAtTime(t, e, i), this.cancelAndHoldAtTime(e + s * 0.9), this.linearRampToValueAtTime(t, e + s), this;
  }
  setTargetAtTime(t, e, s) {
    const i = this._fromType(t);
    X(isFinite(s) && s > 0, "timeConstant must be a number greater than 0");
    const r = this.toSeconds(e);
    return this._assertRange(i), X(isFinite(i) && isFinite(r), `Invalid argument(s) to setTargetAtTime: ${JSON.stringify(t)}, ${JSON.stringify(e)}`), this._events.add({
      constant: s,
      time: r,
      type: "setTargetAtTime",
      value: i
    }), this.log(this.units, "setTargetAtTime", t, r, s), this._param.setTargetAtTime(i, r, s), this;
  }
  setValueCurveAtTime(t, e, s, i = 1) {
    s = this.toSeconds(s), e = this.toSeconds(e);
    const r = this._fromType(t[0]) * i;
    this.setValueAtTime(this._toType(r), e);
    const o = s / (t.length - 1);
    for (let a = 1; a < t.length; a++) {
      const l = this._fromType(t[a]) * i;
      this.linearRampToValueAtTime(this._toType(l), e + a * o);
    }
    return this;
  }
  cancelScheduledValues(t) {
    const e = this.toSeconds(t);
    return X(isFinite(e), `Invalid argument to cancelScheduledValues: ${JSON.stringify(t)}`), this._events.cancel(e), this._param.cancelScheduledValues(e), this.log(this.units, "cancelScheduledValues", e), this;
  }
  cancelAndHoldAtTime(t) {
    const e = this.toSeconds(t), s = this._fromType(this.getValueAtTime(e));
    X(isFinite(e), `Invalid argument to cancelAndHoldAtTime: ${JSON.stringify(t)}`), this.log(this.units, "cancelAndHoldAtTime", e, "value=" + s);
    const i = this._events.get(e), r = this._events.getAfter(e);
    return i && $e(i.time, e) ? r ? (this._param.cancelScheduledValues(r.time), this._events.cancel(r.time)) : (this._param.cancelAndHoldAtTime(e), this._events.cancel(e + this.sampleTime)) : r && (this._param.cancelScheduledValues(r.time), this._events.cancel(r.time), r.type === "linearRampToValueAtTime" ? this.linearRampToValueAtTime(this._toType(s), e) : r.type === "exponentialRampToValueAtTime" && this.exponentialRampToValueAtTime(this._toType(s), e)), this._events.add({
      time: e,
      type: "setValueAtTime",
      value: s
    }), this._param.setValueAtTime(s, e), this;
  }
  rampTo(t, e = 0.1, s) {
    return this.units === "frequency" || this.units === "bpm" || this.units === "decibels" ? this.exponentialRampTo(t, e, s) : this.linearRampTo(t, e, s), this;
  }
  /**
   * Apply all of the previously scheduled events to the passed in Param or AudioParam.
   * The applied values will start at the context's current time and schedule
   * all of the events which are scheduled on this Param onto the passed in param.
   */
  apply(t) {
    const e = this.context.currentTime;
    t.setValueAtTime(this.getValueAtTime(e), e);
    const s = this._events.get(e);
    if (s && s.type === "setTargetAtTime") {
      const i = this._events.getAfter(s.time), r = i ? i.time : e + 2, o = (r - e) / 10;
      for (let a = e; a < r; a += o)
        t.linearRampToValueAtTime(this.getValueAtTime(a), a);
    }
    return this._events.forEachAfter(this.context.currentTime, (i) => {
      i.type === "cancelScheduledValues" ? t.cancelScheduledValues(i.time) : i.type === "setTargetAtTime" ? t.setTargetAtTime(i.value, i.time, i.constant) : t[i.type](i.value, i.time);
    }), this;
  }
  /**
   * Replace the Param's internal AudioParam. Will apply scheduled curves
   * onto the parameter and replace the connections.
   */
  setParam(t) {
    X(this._swappable, "The Param must be assigned as 'swappable' in the constructor");
    const e = this.input;
    return e.disconnect(this._param), this.apply(t), this._param = t, e.connect(this._param), this;
  }
  dispose() {
    return super.dispose(), this._events.dispose(), this;
  }
  get defaultValue() {
    return this._toType(this._param.defaultValue);
  }
  //-------------------------------------
  // 	AUTOMATION CURVE CALCULATIONS
  // 	MIT License, copyright (c) 2014 Jordan Santell
  //-------------------------------------
  // Calculates the the value along the curve produced by setTargetAtTime
  _exponentialApproach(t, e, s, i, r) {
    return s + (e - s) * Math.exp(-(r - t) / i);
  }
  // Calculates the the value along the curve produced by linearRampToValueAtTime
  _linearInterpolate(t, e, s, i, r) {
    return e + (i - e) * ((r - t) / (s - t));
  }
  // Calculates the the value along the curve produced by exponentialRampToValueAtTime
  _exponentialInterpolate(t, e, s, i, r) {
    return e * Math.pow(i / e, (r - t) / (s - t));
  }
}
class B extends Xt {
  constructor() {
    super(...arguments), this._internalChannels = [];
  }
  /**
   * The number of inputs feeding into the AudioNode.
   * For source nodes, this will be 0.
   * @example
   * const node = new Tone.Gain();
   * console.log(node.numberOfInputs);
   */
  get numberOfInputs() {
    return et(this.input) ? Mn(this.input) || this.input instanceof tt ? 1 : this.input.numberOfInputs : 0;
  }
  /**
   * The number of outputs of the AudioNode.
   * @example
   * const node = new Tone.Gain();
   * console.log(node.numberOfOutputs);
   */
  get numberOfOutputs() {
    return et(this.output) ? this.output.numberOfOutputs : 0;
  }
  //-------------------------------------
  // AUDIO PROPERTIES
  //-------------------------------------
  /**
   * Used to decide which nodes to get/set properties on
   */
  _isAudioNode(t) {
    return et(t) && (t instanceof B || $s(t));
  }
  /**
   * Get all of the audio nodes (either internal or input/output) which together
   * make up how the class node responds to channel input/output
   */
  _getInternalNodes() {
    const t = this._internalChannels.slice(0);
    return this._isAudioNode(this.input) && t.push(this.input), this._isAudioNode(this.output) && this.input !== this.output && t.push(this.output), t;
  }
  /**
   * Set the audio options for this node such as channelInterpretation
   * channelCount, etc.
   * @param options
   */
  _setChannelProperties(t) {
    this._getInternalNodes().forEach((s) => {
      s.channelCount = t.channelCount, s.channelCountMode = t.channelCountMode, s.channelInterpretation = t.channelInterpretation;
    });
  }
  /**
   * Get the current audio options for this node such as channelInterpretation
   * channelCount, etc.
   */
  _getChannelProperties() {
    const t = this._getInternalNodes();
    X(t.length > 0, "ToneAudioNode does not have any internal nodes");
    const e = t[0];
    return {
      channelCount: e.channelCount,
      channelCountMode: e.channelCountMode,
      channelInterpretation: e.channelInterpretation
    };
  }
  /**
   * channelCount is the number of channels used when up-mixing and down-mixing
   * connections to any inputs to the node. The default value is 2 except for
   * specific nodes where its value is specially determined.
   */
  get channelCount() {
    return this._getChannelProperties().channelCount;
  }
  set channelCount(t) {
    const e = this._getChannelProperties();
    this._setChannelProperties(Object.assign(e, { channelCount: t }));
  }
  /**
   * channelCountMode determines how channels will be counted when up-mixing and
   * down-mixing connections to any inputs to the node.
   * The default value is "max". This attribute has no effect for nodes with no inputs.
   * * "max" - computedNumberOfChannels is the maximum of the number of channels of all connections to an input. In this mode channelCount is ignored.
   * * "clamped-max" - computedNumberOfChannels is determined as for "max" and then clamped to a maximum value of the given channelCount.
   * * "explicit" - computedNumberOfChannels is the exact value as specified by the channelCount.
   */
  get channelCountMode() {
    return this._getChannelProperties().channelCountMode;
  }
  set channelCountMode(t) {
    const e = this._getChannelProperties();
    this._setChannelProperties(Object.assign(e, { channelCountMode: t }));
  }
  /**
   * channelInterpretation determines how individual channels will be treated
   * when up-mixing and down-mixing connections to any inputs to the node.
   * The default value is "speakers".
   */
  get channelInterpretation() {
    return this._getChannelProperties().channelInterpretation;
  }
  set channelInterpretation(t) {
    const e = this._getChannelProperties();
    this._setChannelProperties(Object.assign(e, { channelInterpretation: t }));
  }
  //-------------------------------------
  // CONNECTIONS
  //-------------------------------------
  /**
   * connect the output of a ToneAudioNode to an AudioParam, AudioNode, or ToneAudioNode
   * @param destination The output to connect to
   * @param outputNum The output to connect from
   * @param inputNum The input to connect to
   */
  connect(t, e = 0, s = 0) {
    return ue(this, t, e, s), this;
  }
  /**
   * Connect the output to the context's destination node.
   * @example
   * const osc = new Tone.Oscillator("C2").start();
   * osc.toDestination();
   */
  toDestination() {
    return this.connect(this.context.destination), this;
  }
  /**
   * Connect the output to the context's destination node.
   * @see {@link toDestination}
   * @deprecated
   */
  toMaster() {
    return mi("toMaster() has been renamed toDestination()"), this.toDestination();
  }
  /**
   * disconnect the output
   */
  disconnect(t, e = 0, s = 0) {
    return Vc(this, t, e, s), this;
  }
  /**
   * Connect the output of this node to the rest of the nodes in series.
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/drum-samples/handdrum-loop.mp3");
   * player.autostart = true;
   * const filter = new Tone.AutoFilter(4).start();
   * const distortion = new Tone.Distortion(0.5);
   * // connect the player to the filter, distortion and then to the master output
   * player.chain(filter, distortion, Tone.Destination);
   */
  chain(...t) {
    return Fe(this, ...t), this;
  }
  /**
   * connect the output of this node to the rest of the nodes in parallel.
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/drum-samples/conga-rhythm.mp3");
   * player.autostart = true;
   * const pitchShift = new Tone.PitchShift(4).toDestination();
   * const filter = new Tone.Filter("G5").toDestination();
   * // connect a node to the pitch shift and filter in parallel
   * player.fan(pitchShift, filter);
   */
  fan(...t) {
    return t.forEach((e) => this.connect(e)), this;
  }
  /**
   * Dispose and disconnect
   */
  dispose() {
    return super.dispose(), et(this.input) && (this.input instanceof B ? this.input.dispose() : $s(this.input) && this.input.disconnect()), et(this.output) && (this.output instanceof B ? this.output.dispose() : $s(this.output) && this.output.disconnect()), this._internalChannels = [], this;
  }
}
function Fe(...n) {
  const t = n.shift();
  n.reduce((e, s) => (e instanceof B ? e.connect(s) : $s(e) && ue(e, s), s), t);
}
function ue(n, t, e = 0, s = 0) {
  for (X(et(n), "Cannot connect from undefined node"), X(et(t), "Cannot connect to undefined node"), (t instanceof B || $s(t)) && X(t.numberOfInputs > 0, "Cannot connect to node with no inputs"), X(n.numberOfOutputs > 0, "Cannot connect from node with no outputs"); t instanceof B || t instanceof tt; )
    et(t.input) && (t = t.input);
  for (; n instanceof B; )
    et(n.output) && (n = n.output);
  Mn(t) ? n.connect(t, e) : n.connect(t, e, s);
}
function Vc(n, t, e = 0, s = 0) {
  if (et(t))
    for (; t instanceof B; )
      t = t.input;
  for (; !$s(n); )
    et(n.output) && (n = n.output);
  Mn(t) ? n.disconnect(t, e) : $s(t) ? n.disconnect(t, e, s) : n.disconnect();
}
function tC(...n) {
  const t = n.pop();
  et(t) && n.forEach((e) => ue(e, t));
}
class j extends B {
  constructor() {
    const t = L(j.getDefaults(), arguments, [
      "gain",
      "units"
    ]);
    super(t), this.name = "Gain", this._gainNode = this.context.createGain(), this.input = this._gainNode, this.output = this._gainNode, this.gain = new tt({
      context: this.context,
      convert: t.convert,
      param: this._gainNode.gain,
      units: t.units,
      value: t.gain,
      minValue: t.minValue,
      maxValue: t.maxValue
    }), Z(this, "gain");
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      convert: !0,
      gain: 1,
      units: "gain"
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._gainNode.disconnect(), this.gain.dispose(), this;
  }
}
class ri extends B {
  constructor(t) {
    super(t), this.onended = st, this._startTime = -1, this._stopTime = -1, this._timeout = -1, this.output = new j({
      context: this.context,
      gain: 0
    }), this._gainNode = this.output, this.getStateAtTime = function(e) {
      const s = this.toSeconds(e);
      return this._startTime !== -1 && s >= this._startTime && (this._stopTime === -1 || s <= this._stopTime) ? "started" : "stopped";
    }, this._fadeIn = t.fadeIn, this._fadeOut = t.fadeOut, this._curve = t.curve, this.onended = t.onended;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      curve: "linear",
      fadeIn: 0,
      fadeOut: 0,
      onended: st
    });
  }
  /**
   * Start the source at the given time
   * @param  time When to start the source
   */
  _startGain(t, e = 1) {
    X(this._startTime === -1, "Source cannot be started more than once");
    const s = this.toSeconds(this._fadeIn);
    return this._startTime = t + s, this._startTime = Math.max(this._startTime, this.context.currentTime), s > 0 ? (this._gainNode.gain.setValueAtTime(0, t), this._curve === "linear" ? this._gainNode.gain.linearRampToValueAtTime(e, t + s) : this._gainNode.gain.exponentialApproachValueAtTime(e, t, s)) : this._gainNode.gain.setValueAtTime(e, t), this;
  }
  /**
   * Stop the source node at the given time.
   * @param time When to stop the source
   */
  stop(t) {
    return this.log("stop", t), this._stopGain(this.toSeconds(t)), this;
  }
  /**
   * Stop the source at the given time
   * @param  time When to stop the source
   */
  _stopGain(t) {
    X(this._startTime !== -1, "'start' must be called before 'stop'"), this.cancelStop();
    const e = this.toSeconds(this._fadeOut);
    return this._stopTime = this.toSeconds(t) + e, this._stopTime = Math.max(this._stopTime, this.now()), e > 0 ? this._curve === "linear" ? this._gainNode.gain.linearRampTo(0, e, t) : this._gainNode.gain.targetRampTo(0, e, t) : (this._gainNode.gain.cancelAndHoldAtTime(t), this._gainNode.gain.setValueAtTime(0, t)), this.context.clearTimeout(this._timeout), this._timeout = this.context.setTimeout(() => {
      const s = this._curve === "exponential" ? e * 2 : 0;
      this._stopSource(this.now() + s), this._onended();
    }, this._stopTime - this.context.currentTime), this;
  }
  /**
   * Invoke the onended callback
   */
  _onended() {
    if (this.onended !== st && (this.onended(this), this.onended = st, !this.context.isOffline)) {
      const t = () => this.dispose();
      typeof requestIdleCallback < "u" ? requestIdleCallback(t) : setTimeout(t, 10);
    }
  }
  /**
   * Get the playback state at the current time
   */
  get state() {
    return this.getStateAtTime(this.now());
  }
  /**
   * Cancel a scheduled stop event
   */
  cancelStop() {
    return this.log("cancelStop"), X(this._startTime !== -1, "Source is not started"), this._gainNode.gain.cancelScheduledValues(this._startTime + this.sampleTime), this.context.clearTimeout(this._timeout), this._stopTime = -1, this;
  }
  dispose() {
    return super.dispose(), this._gainNode.dispose(), this.onended = st, this;
  }
}
class aa extends ri {
  constructor() {
    const t = L(aa.getDefaults(), arguments, ["offset"]);
    super(t), this.name = "ToneConstantSource", this._source = this.context.createConstantSource(), ue(this._source, this._gainNode), this.offset = new tt({
      context: this.context,
      convert: t.convert,
      param: this._source.offset,
      units: t.units,
      value: t.offset,
      minValue: t.minValue,
      maxValue: t.maxValue
    });
  }
  static getDefaults() {
    return Object.assign(ri.getDefaults(), {
      convert: !0,
      offset: 1,
      units: "number"
    });
  }
  /**
   * Start the source node at the given time
   * @param  time When to start the source
   */
  start(t) {
    const e = this.toSeconds(t);
    return this.log("start", e), this._startGain(e), this._source.start(e), this;
  }
  _stopSource(t) {
    this._source.stop(t);
  }
  dispose() {
    return super.dispose(), this.state === "started" && this.stop(), this._source.disconnect(), this.offset.dispose(), this;
  }
}
class Q extends B {
  constructor() {
    const t = L(Q.getDefaults(), arguments, [
      "value",
      "units"
    ]);
    super(t), this.name = "Signal", this.override = !0, this.output = this._constantSource = new aa({
      context: this.context,
      convert: t.convert,
      offset: t.value,
      units: t.units,
      minValue: t.minValue,
      maxValue: t.maxValue
    }), this._constantSource.start(0), this.input = this._param = this._constantSource.offset;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      convert: !0,
      units: "number",
      value: 0
    });
  }
  connect(t, e = 0, s = 0) {
    return wr(this, t, e, s), this;
  }
  dispose() {
    return super.dispose(), this._param.dispose(), this._constantSource.dispose(), this;
  }
  //-------------------------------------
  // ABSTRACT PARAM INTERFACE
  // just a proxy for the ConstantSourceNode's offset AudioParam
  // all docs are generated from AbstractParam.ts
  //-------------------------------------
  setValueAtTime(t, e) {
    return this._param.setValueAtTime(t, e), this;
  }
  getValueAtTime(t) {
    return this._param.getValueAtTime(t);
  }
  setRampPoint(t) {
    return this._param.setRampPoint(t), this;
  }
  linearRampToValueAtTime(t, e) {
    return this._param.linearRampToValueAtTime(t, e), this;
  }
  exponentialRampToValueAtTime(t, e) {
    return this._param.exponentialRampToValueAtTime(t, e), this;
  }
  exponentialRampTo(t, e, s) {
    return this._param.exponentialRampTo(t, e, s), this;
  }
  linearRampTo(t, e, s) {
    return this._param.linearRampTo(t, e, s), this;
  }
  targetRampTo(t, e, s) {
    return this._param.targetRampTo(t, e, s), this;
  }
  exponentialApproachValueAtTime(t, e, s) {
    return this._param.exponentialApproachValueAtTime(t, e, s), this;
  }
  setTargetAtTime(t, e, s) {
    return this._param.setTargetAtTime(t, e, s), this;
  }
  setValueCurveAtTime(t, e, s, i) {
    return this._param.setValueCurveAtTime(t, e, s, i), this;
  }
  cancelScheduledValues(t) {
    return this._param.cancelScheduledValues(t), this;
  }
  cancelAndHoldAtTime(t) {
    return this._param.cancelAndHoldAtTime(t), this;
  }
  rampTo(t, e, s) {
    return this._param.rampTo(t, e, s), this;
  }
  get value() {
    return this._param.value;
  }
  set value(t) {
    this._param.value = t;
  }
  get convert() {
    return this._param.convert;
  }
  set convert(t) {
    this._param.convert = t;
  }
  get units() {
    return this._param.units;
  }
  get overridden() {
    return this._param.overridden;
  }
  set overridden(t) {
    this._param.overridden = t;
  }
  get maxValue() {
    return this._param.maxValue;
  }
  get minValue() {
    return this._param.minValue;
  }
  /**
   * @see {@link Param.apply}.
   */
  apply(t) {
    return this._param.apply(t), this;
  }
}
function wr(n, t, e, s) {
  (t instanceof tt || Mn(t) || t instanceof Q && t.override) && (t.cancelScheduledValues(0), t.setValueAtTime(0, 0), t instanceof Q && (t.overridden = !0)), ue(n, t, e, s);
}
class Bc extends tt {
  constructor() {
    const t = L(Bc.getDefaults(), arguments, ["value"]);
    super(t), this.name = "TickParam", this._events = new Ee(1 / 0), this._multiplier = 1, this._multiplier = t.multiplier, this._events.cancel(0), this._events.add({
      ticks: 0,
      time: 0,
      type: "setValueAtTime",
      value: this._fromType(t.value)
    }), this.setValueAtTime(t.value, 0);
  }
  static getDefaults() {
    return Object.assign(tt.getDefaults(), {
      multiplier: 1,
      units: "hertz",
      value: 1
    });
  }
  setTargetAtTime(t, e, s) {
    e = this.toSeconds(e), this.setRampPoint(e);
    const i = this._fromType(t), r = this._events.get(e), o = Math.round(Math.max(1 / s, 1));
    for (let a = 0; a <= o; a++) {
      const l = s * a + e, c = this._exponentialApproach(r.time, r.value, i, s, l);
      this.linearRampToValueAtTime(this._toType(c), l);
    }
    return this;
  }
  setValueAtTime(t, e) {
    const s = this.toSeconds(e);
    super.setValueAtTime(t, e);
    const i = this._events.get(s), r = this._events.previousEvent(i), o = this._getTicksUntilEvent(r, s);
    return i.ticks = Math.max(o, 0), this;
  }
  linearRampToValueAtTime(t, e) {
    const s = this.toSeconds(e);
    super.linearRampToValueAtTime(t, e);
    const i = this._events.get(s), r = this._events.previousEvent(i), o = this._getTicksUntilEvent(r, s);
    return i.ticks = Math.max(o, 0), this;
  }
  exponentialRampToValueAtTime(t, e) {
    e = this.toSeconds(e);
    const s = this._fromType(t), i = this._events.get(e), r = Math.round(Math.max((e - i.time) * 10, 1)), o = (e - i.time) / r;
    for (let a = 0; a <= r; a++) {
      const l = o * a + i.time, c = this._exponentialInterpolate(i.time, i.value, e, s, l);
      this.linearRampToValueAtTime(this._toType(c), l);
    }
    return this;
  }
  /**
   * Returns the tick value at the time. Takes into account
   * any automation curves scheduled on the signal.
   * @param  event The time to get the tick count at
   * @return The number of ticks which have elapsed at the time given any automations.
   */
  _getTicksUntilEvent(t, e) {
    if (t === null)
      t = {
        ticks: 0,
        time: 0,
        type: "setValueAtTime",
        value: 0
      };
    else if (ve(t.ticks)) {
      const o = this._events.previousEvent(t);
      t.ticks = this._getTicksUntilEvent(o, t.time);
    }
    const s = this._fromType(this.getValueAtTime(t.time));
    let i = this._fromType(this.getValueAtTime(e));
    const r = this._events.get(e);
    return r && r.time === e && r.type === "setValueAtTime" && (i = this._fromType(this.getValueAtTime(e - this.sampleTime))), 0.5 * (e - t.time) * (s + i) + t.ticks;
  }
  /**
   * Returns the tick value at the time. Takes into account
   * any automation curves scheduled on the signal.
   * @param  time The time to get the tick count at
   * @return The number of ticks which have elapsed at the time given any automations.
   */
  getTicksAtTime(t) {
    const e = this.toSeconds(t), s = this._events.get(e);
    return Math.max(this._getTicksUntilEvent(s, e), 0);
  }
  /**
   * Return the elapsed time of the number of ticks from the given time
   * @param ticks The number of ticks to calculate
   * @param  time The time to get the next tick from
   * @return The duration of the number of ticks from the given time in seconds
   */
  getDurationOfTicks(t, e) {
    const s = this.toSeconds(e), i = this.getTicksAtTime(e);
    return this.getTimeOfTick(i + t) - s;
  }
  /**
   * Given a tick, returns the time that tick occurs at.
   * @return The time that the tick occurs.
   */
  getTimeOfTick(t) {
    const e = this._events.get(t, "ticks"), s = this._events.getAfter(t, "ticks");
    if (e && e.ticks === t)
      return e.time;
    if (e && s && s.type === "linearRampToValueAtTime" && e.value !== s.value) {
      const i = this._fromType(this.getValueAtTime(e.time)), o = (this._fromType(this.getValueAtTime(s.time)) - i) / (s.time - e.time), a = Math.sqrt(Math.pow(i, 2) - 2 * o * (e.ticks - t)), l = (-i + a) / o, c = (-i - a) / o;
      return (l > 0 ? l : c) + e.time;
    } else return e ? e.value === 0 ? 1 / 0 : e.time + (t - e.ticks) / e.value : t / this._initialValue;
  }
  /**
   * Convert some number of ticks their the duration in seconds accounting
   * for any automation curves starting at the given time.
   * @param  ticks The number of ticks to convert to seconds.
   * @param  when  When along the automation timeline to convert the ticks.
   * @return The duration in seconds of the ticks.
   */
  ticksToTime(t, e) {
    return this.getDurationOfTicks(t, e);
  }
  /**
   * The inverse of {@link ticksToTime}. Convert a duration in
   * seconds to the corresponding number of ticks accounting for any
   * automation curves starting at the given time.
   * @param  duration The time interval to convert to ticks.
   * @param  when When along the automation timeline to convert the ticks.
   * @return The duration in ticks.
   */
  timeToTicks(t, e) {
    const s = this.toSeconds(e), i = this.toSeconds(t), r = this.getTicksAtTime(s);
    return this.getTicksAtTime(s + i) - r;
  }
  /**
   * Convert from the type when the unit value is BPM
   */
  _fromType(t) {
    return this.units === "bpm" && this.multiplier ? 1 / (60 / t / this.multiplier) : super._fromType(t);
  }
  /**
   * Special case of type conversion where the units === "bpm"
   */
  _toType(t) {
    return this.units === "bpm" && this.multiplier ? t / this.multiplier * 60 : super._toType(t);
  }
  /**
   * A multiplier on the bpm value. Useful for setting a PPQ relative to the base frequency value.
   */
  get multiplier() {
    return this._multiplier;
  }
  set multiplier(t) {
    const e = this.value;
    this._multiplier = t, this.cancelScheduledValues(0), this.setValueAtTime(e, 0);
  }
}
class zc extends Q {
  constructor() {
    const t = L(zc.getDefaults(), arguments, ["value"]);
    super(t), this.name = "TickSignal", this.input = this._param = new Bc({
      context: this.context,
      convert: t.convert,
      multiplier: t.multiplier,
      param: this._constantSource.offset,
      units: t.units,
      value: t.value
    });
  }
  static getDefaults() {
    return Object.assign(Q.getDefaults(), {
      multiplier: 1,
      units: "hertz",
      value: 1
    });
  }
  ticksToTime(t, e) {
    return this._param.ticksToTime(t, e);
  }
  timeToTicks(t, e) {
    return this._param.timeToTicks(t, e);
  }
  getTimeOfTick(t) {
    return this._param.getTimeOfTick(t);
  }
  getDurationOfTicks(t, e) {
    return this._param.getDurationOfTicks(t, e);
  }
  getTicksAtTime(t) {
    return this._param.getTicksAtTime(t);
  }
  /**
   * A multiplier on the bpm value. Useful for setting a PPQ relative to the base frequency value.
   */
  get multiplier() {
    return this._param.multiplier;
  }
  set multiplier(t) {
    this._param.multiplier = t;
  }
  dispose() {
    return super.dispose(), this._param.dispose(), this;
  }
}
class qc extends Xt {
  constructor() {
    const t = L(qc.getDefaults(), arguments, ["frequency"]);
    super(t), this.name = "TickSource", this._state = new _i(), this._tickOffset = new Ee(), this._ticksAtTime = new Ee(), this._secondsAtTime = new Ee(), this.frequency = new zc({
      context: this.context,
      units: t.units,
      value: t.frequency
    }), Z(this, "frequency"), this._state.setStateAtTime("stopped", 0), this.setTicksAtTime(0, 0);
  }
  static getDefaults() {
    return Object.assign({
      frequency: 1,
      units: "hertz"
    }, Xt.getDefaults());
  }
  /**
   * Returns the playback state of the source, either "started", "stopped" or "paused".
   */
  get state() {
    return this.getStateAtTime(this.now());
  }
  /**
   * Start the clock at the given time. Optionally pass in an offset
   * of where to start the tick counter from.
   * @param  time    The time the clock should start
   * @param offset The number of ticks to start the source at
   */
  start(t, e) {
    const s = this.toSeconds(t);
    return this._state.getValueAtTime(s) !== "started" && (this._state.setStateAtTime("started", s), et(e) && this.setTicksAtTime(e, s), this._ticksAtTime.cancel(s), this._secondsAtTime.cancel(s)), this;
  }
  /**
   * Stop the clock. Stopping the clock resets the tick counter to 0.
   * @param time The time when the clock should stop.
   */
  stop(t) {
    const e = this.toSeconds(t);
    if (this._state.getValueAtTime(e) === "stopped") {
      const s = this._state.get(e);
      s && s.time > 0 && (this._tickOffset.cancel(s.time), this._state.cancel(s.time));
    }
    return this._state.cancel(e), this._state.setStateAtTime("stopped", e), this.setTicksAtTime(0, e), this._ticksAtTime.cancel(e), this._secondsAtTime.cancel(e), this;
  }
  /**
   * Pause the clock. Pausing does not reset the tick counter.
   * @param time The time when the clock should stop.
   */
  pause(t) {
    const e = this.toSeconds(t);
    return this._state.getValueAtTime(e) === "started" && (this._state.setStateAtTime("paused", e), this._ticksAtTime.cancel(e), this._secondsAtTime.cancel(e)), this;
  }
  /**
   * Cancel start/stop/pause and setTickAtTime events scheduled after the given time.
   * @param time When to clear the events after
   */
  cancel(t) {
    return t = this.toSeconds(t), this._state.cancel(t), this._tickOffset.cancel(t), this._ticksAtTime.cancel(t), this._secondsAtTime.cancel(t), this;
  }
  /**
   * Get the elapsed ticks at the given time
   * @param  time  When to get the tick value
   * @return The number of ticks
   */
  getTicksAtTime(t) {
    const e = this.toSeconds(t), s = this._state.getLastState("stopped", e), i = this._ticksAtTime.get(e), r = {
      state: "paused",
      time: e
    };
    this._state.add(r);
    let o = i || s, a = i ? i.ticks : 0, l = null;
    return this._state.forEachBetween(o.time, e + this.sampleTime, (c) => {
      let h = o.time;
      const u = this._tickOffset.get(c.time);
      u && u.time >= o.time && (a = u.ticks, h = u.time), o.state === "started" && c.state !== "started" && (a += this.frequency.getTicksAtTime(c.time) - this.frequency.getTicksAtTime(h), c.time !== r.time && (l = {
        state: c.state,
        time: c.time,
        ticks: a
      })), o = c;
    }), this._state.remove(r), l && this._ticksAtTime.add(l), a;
  }
  /**
   * The number of times the callback was invoked. Starts counting at 0
   * and increments after the callback was invoked. Returns -1 when stopped.
   */
  get ticks() {
    return this.getTicksAtTime(this.now());
  }
  set ticks(t) {
    this.setTicksAtTime(t, this.now());
  }
  /**
   * The time since ticks=0 that the TickSource has been running. Accounts
   * for tempo curves
   */
  get seconds() {
    return this.getSecondsAtTime(this.now());
  }
  set seconds(t) {
    const e = this.now(), s = this.frequency.timeToTicks(t, e);
    this.setTicksAtTime(s, e);
  }
  /**
   * Return the elapsed seconds at the given time.
   * @param  time  When to get the elapsed seconds
   * @return  The number of elapsed seconds
   */
  getSecondsAtTime(t) {
    t = this.toSeconds(t);
    const e = this._state.getLastState("stopped", t), s = { state: "paused", time: t };
    this._state.add(s);
    const i = this._secondsAtTime.get(t);
    let r = i || e, o = i ? i.seconds : 0, a = null;
    return this._state.forEachBetween(r.time, t + this.sampleTime, (l) => {
      let c = r.time;
      const h = this._tickOffset.get(l.time);
      h && h.time >= r.time && (o = h.seconds, c = h.time), r.state === "started" && l.state !== "started" && (o += l.time - c, l.time !== s.time && (a = {
        state: l.state,
        time: l.time,
        seconds: o
      })), r = l;
    }), this._state.remove(s), a && this._secondsAtTime.add(a), o;
  }
  /**
   * Set the clock's ticks at the given time.
   * @param  ticks The tick value to set
   * @param  time  When to set the tick value
   */
  setTicksAtTime(t, e) {
    return e = this.toSeconds(e), this._tickOffset.cancel(e), this._tickOffset.add({
      seconds: this.frequency.getDurationOfTicks(t, e),
      ticks: t,
      time: e
    }), this._ticksAtTime.cancel(e), this._secondsAtTime.cancel(e), this;
  }
  /**
   * Returns the scheduled state at the given time.
   * @param  time  The time to query.
   */
  getStateAtTime(t) {
    return t = this.toSeconds(t), this._state.getValueAtTime(t);
  }
  /**
   * Get the time of the given tick. The second argument
   * is when to test before. Since ticks can be set (with setTicksAtTime)
   * there may be multiple times for a given tick value.
   * @param  tick The tick number.
   * @param  before When to measure the tick value from.
   * @return The time of the tick
   */
  getTimeOfTick(t, e = this.now()) {
    const s = this._tickOffset.get(e), i = this._state.get(e), r = Math.max(s.time, i.time), o = this.frequency.getTicksAtTime(r) + t - s.ticks;
    return this.frequency.getTimeOfTick(o);
  }
  /**
   * Invoke the callback event at all scheduled ticks between the
   * start time and the end time
   * @param  startTime  The beginning of the search range
   * @param  endTime    The end of the search range
   * @param  callback   The callback to invoke with each tick
   */
  forEachTickBetween(t, e, s) {
    let i = this._state.get(t);
    this._state.forEachBetween(t, e, (o) => {
      i && i.state === "started" && o.state !== "started" && this.forEachTickBetween(Math.max(i.time, t), o.time - this.sampleTime, s), i = o;
    });
    let r = null;
    if (i && i.state === "started") {
      const o = Math.max(i.time, t), a = this.frequency.getTicksAtTime(o), l = this.frequency.getTicksAtTime(i.time), c = a - l;
      let h = Math.ceil(c) - c;
      h = $e(h, 1) ? 0 : h;
      let u = this.frequency.getTimeOfTick(a + h);
      for (; u < e; ) {
        try {
          s(u, Math.round(this.getTicksAtTime(u)));
        } catch (d) {
          r = d;
          break;
        }
        u += this.frequency.getDurationOfTicks(1, u);
      }
    }
    if (r)
      throw r;
    return this;
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this._state.dispose(), this._tickOffset.dispose(), this._ticksAtTime.dispose(), this._secondsAtTime.dispose(), this.frequency.dispose(), this;
  }
}
class vi extends Xt {
  constructor() {
    const t = L(vi.getDefaults(), arguments, [
      "callback",
      "frequency"
    ]);
    super(t), this.name = "Clock", this.callback = st, this._lastUpdate = 0, this._state = new _i("stopped"), this._boundLoop = this._loop.bind(this), this.callback = t.callback, this._tickSource = new qc({
      context: this.context,
      frequency: t.frequency,
      units: t.units
    }), this._lastUpdate = 0, this.frequency = this._tickSource.frequency, Z(this, "frequency"), this._state.setStateAtTime("stopped", 0), this.context.on("tick", this._boundLoop);
  }
  static getDefaults() {
    return Object.assign(Xt.getDefaults(), {
      callback: st,
      frequency: 1,
      units: "hertz"
    });
  }
  /**
   * Returns the playback state of the source, either "started", "stopped" or "paused".
   */
  get state() {
    return this._state.getValueAtTime(this.now());
  }
  /**
   * Start the clock at the given time. Optionally pass in an offset
   * of where to start the tick counter from.
   * @param  time    The time the clock should start
   * @param offset  Where the tick counter starts counting from.
   */
  start(t, e) {
    Ic(this.context);
    const s = this.toSeconds(t);
    return this.log("start", s), this._state.getValueAtTime(s) !== "started" && (this._state.setStateAtTime("started", s), this._tickSource.start(s, e), s < this._lastUpdate && this.emit("start", s, e)), this;
  }
  /**
   * Stop the clock. Stopping the clock resets the tick counter to 0.
   * @param time The time when the clock should stop.
   * @example
   * const clock = new Tone.Clock(time => {
   * 	console.log(time);
   * }, 1);
   * clock.start();
   * // stop the clock after 10 seconds
   * clock.stop("+10");
   */
  stop(t) {
    const e = this.toSeconds(t);
    return this.log("stop", e), this._state.cancel(e), this._state.setStateAtTime("stopped", e), this._tickSource.stop(e), e < this._lastUpdate && this.emit("stop", e), this;
  }
  /**
   * Pause the clock. Pausing does not reset the tick counter.
   * @param time The time when the clock should stop.
   */
  pause(t) {
    const e = this.toSeconds(t);
    return this._state.getValueAtTime(e) === "started" && (this._state.setStateAtTime("paused", e), this._tickSource.pause(e), e < this._lastUpdate && this.emit("pause", e)), this;
  }
  /**
   * The number of times the callback was invoked. Starts counting at 0
   * and increments after the callback was invoked.
   */
  get ticks() {
    return Math.ceil(this.getTicksAtTime(this.now()));
  }
  set ticks(t) {
    this._tickSource.ticks = t;
  }
  /**
   * The time since ticks=0 that the Clock has been running. Accounts for tempo curves
   */
  get seconds() {
    return this._tickSource.seconds;
  }
  set seconds(t) {
    this._tickSource.seconds = t;
  }
  /**
   * Return the elapsed seconds at the given time.
   * @param  time  When to get the elapsed seconds
   * @return  The number of elapsed seconds
   */
  getSecondsAtTime(t) {
    return this._tickSource.getSecondsAtTime(t);
  }
  /**
   * Set the clock's ticks at the given time.
   * @param  ticks The tick value to set
   * @param  time  When to set the tick value
   */
  setTicksAtTime(t, e) {
    return this._tickSource.setTicksAtTime(t, e), this;
  }
  /**
   * Get the time of the given tick. The second argument
   * is when to test before. Since ticks can be set (with setTicksAtTime)
   * there may be multiple times for a given tick value.
   * @param  tick The tick number.
   * @param  before When to measure the tick value from.
   * @return The time of the tick
   */
  getTimeOfTick(t, e = this.now()) {
    return this._tickSource.getTimeOfTick(t, e);
  }
  /**
   * Get the clock's ticks at the given time.
   * @param  time  When to get the tick value
   * @return The tick value at the given time.
   */
  getTicksAtTime(t) {
    return this._tickSource.getTicksAtTime(t);
  }
  /**
   * Get the time of the next tick
   * @param  offset The tick number.
   */
  nextTickTime(t, e) {
    const s = this.toSeconds(e), i = this.getTicksAtTime(s);
    return this._tickSource.getTimeOfTick(i + t, s);
  }
  /**
   * The scheduling loop.
   */
  _loop() {
    const t = this._lastUpdate, e = this.now();
    this._lastUpdate = e, this.log("loop", t, e), t !== e && (this._state.forEachBetween(t, e, (s) => {
      switch (s.state) {
        case "started":
          const i = this._tickSource.getTicksAtTime(s.time);
          this.emit("start", s.time, i);
          break;
        case "stopped":
          s.time !== 0 && this.emit("stop", s.time);
          break;
        case "paused":
          this.emit("pause", s.time);
          break;
      }
    }), this._tickSource.forEachTickBetween(t, e, (s, i) => {
      this.callback(s, i);
    }));
  }
  /**
   * Returns the scheduled state at the given time.
   * @param  time  The time to query.
   * @return  The name of the state input in setStateAtTime.
   * @example
   * const clock = new Tone.Clock();
   * clock.start("+0.1");
   * clock.getStateAtTime("+0.1"); // returns "started"
   */
  getStateAtTime(t) {
    const e = this.toSeconds(t);
    return this._state.getValueAtTime(e);
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this.context.off("tick", this._boundLoop), this._tickSource.dispose(), this._state.dispose(), this;
  }
}
gi.mixin(vi);
class Pe extends B {
  constructor() {
    const t = L(Pe.getDefaults(), arguments, [
      "delayTime",
      "maxDelay"
    ]);
    super(t), this.name = "Delay";
    const e = this.toSeconds(t.maxDelay);
    this._maxDelay = Math.max(e, this.toSeconds(t.delayTime)), this._delayNode = this.input = this.output = this.context.createDelay(e), this.delayTime = new tt({
      context: this.context,
      param: this._delayNode.delayTime,
      units: "time",
      value: t.delayTime,
      minValue: 0,
      maxValue: this.maxDelay
    }), Z(this, "delayTime");
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      delayTime: 0,
      maxDelay: 1
    });
  }
  /**
   * The maximum delay time. This cannot be changed after
   * the value is passed into the constructor.
   */
  get maxDelay() {
    return this._maxDelay;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._delayNode.disconnect(), this.delayTime.dispose(), this;
  }
}
class Os extends B {
  constructor() {
    const t = L(Os.getDefaults(), arguments, [
      "volume"
    ]);
    super(t), this.name = "Volume", this.input = this.output = new j({
      context: this.context,
      gain: t.volume,
      units: "decibels"
    }), this.volume = this.output.gain, Z(this, "volume"), this._unmutedVolume = t.volume, this.mute = t.mute;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      mute: !1,
      volume: 0
    });
  }
  /**
   * Mute the output.
   * @example
   * const vol = new Tone.Volume(-12).toDestination();
   * const osc = new Tone.Oscillator().connect(vol).start();
   * // mute the output
   * vol.mute = true;
   */
  get mute() {
    return this.volume.value === -1 / 0;
  }
  set mute(t) {
    !this.mute && t ? (this._unmutedVolume = this.volume.value, this.volume.value = -1 / 0) : this.mute && !t && (this.volume.value = this._unmutedVolume);
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), this.input.dispose(), this.volume.dispose(), this;
  }
}
class Uc extends B {
  constructor() {
    const t = L(Uc.getDefaults(), arguments);
    super(t), this.name = "Destination", this.input = new Os({ context: this.context }), this.output = new j({ context: this.context }), this.volume = this.input.volume, Fe(this.input, this.output, this.context.rawContext.destination), this.mute = t.mute, this._internalChannels = [
      this.input,
      this.context.rawContext.destination,
      this.output
    ];
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      mute: !1,
      volume: 0
    });
  }
  /**
   * Mute the output.
   * @example
   * const oscillator = new Tone.Oscillator().start().toDestination();
   * setTimeout(() => {
   * 	// mute the output
   * 	Tone.Destination.mute = true;
   * }, 1000);
   */
  get mute() {
    return this.input.mute;
  }
  set mute(t) {
    this.input.mute = t;
  }
  /**
   * Add a master effects chain. NOTE: this will disconnect any nodes which were previously
   * chained in the master effects chain.
   * @param args All arguments will be connected in a row and the Master will be routed through it.
   * @example
   * // route all audio through a filter and compressor
   * const lowpass = new Tone.Filter(800, "lowpass");
   * const compressor = new Tone.Compressor(-18);
   * Tone.Destination.chain(lowpass, compressor);
   */
  chain(...t) {
    return this.input.disconnect(), t.unshift(this.input), t.push(this.output), Fe(...t), this;
  }
  /**
   * The maximum number of channels the system can output
   * @example
   * console.log(Tone.Destination.maxChannelCount);
   */
  get maxChannelCount() {
    return this.context.rawContext.destination.maxChannelCount;
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this.volume.dispose(), this;
  }
}
ia((n) => {
  n.destination = new Uc({ context: n });
});
ra((n) => {
  n.destination.dispose();
});
class eC extends B {
  constructor() {
    super(...arguments), this.name = "Listener", this.positionX = new tt({
      context: this.context,
      param: this.context.rawContext.listener.positionX
    }), this.positionY = new tt({
      context: this.context,
      param: this.context.rawContext.listener.positionY
    }), this.positionZ = new tt({
      context: this.context,
      param: this.context.rawContext.listener.positionZ
    }), this.forwardX = new tt({
      context: this.context,
      param: this.context.rawContext.listener.forwardX
    }), this.forwardY = new tt({
      context: this.context,
      param: this.context.rawContext.listener.forwardY
    }), this.forwardZ = new tt({
      context: this.context,
      param: this.context.rawContext.listener.forwardZ
    }), this.upX = new tt({
      context: this.context,
      param: this.context.rawContext.listener.upX
    }), this.upY = new tt({
      context: this.context,
      param: this.context.rawContext.listener.upY
    }), this.upZ = new tt({
      context: this.context,
      param: this.context.rawContext.listener.upZ
    });
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      positionX: 0,
      positionY: 0,
      positionZ: 0,
      forwardX: 0,
      forwardY: 0,
      forwardZ: -1,
      upX: 0,
      upY: 1,
      upZ: 0
    });
  }
  dispose() {
    return super.dispose(), this.positionX.dispose(), this.positionY.dispose(), this.positionZ.dispose(), this.forwardX.dispose(), this.forwardY.dispose(), this.forwardZ.dispose(), this.upX.dispose(), this.upY.dispose(), this.upZ.dispose(), this;
  }
}
ia((n) => {
  n.listener = new eC({ context: n });
});
ra((n) => {
  n.listener.dispose();
});
function sC(n, t) {
  return yt(this, arguments, void 0, function* (e, s, i = 2, r = ut().sampleRate) {
    const o = ut(), a = new xi(i, s, r);
    zo(a), yield e(a);
    const l = a.render();
    zo(o);
    const c = yield l;
    return new ot(c);
  });
}
class bi extends Ds {
  constructor() {
    super(), this.name = "ToneAudioBuffers", this._buffers = /* @__PURE__ */ new Map(), this._loadingCount = 0;
    const t = L(bi.getDefaults(), arguments, ["urls", "onload", "baseUrl"], "urls");
    this.baseUrl = t.baseUrl, Object.keys(t.urls).forEach((e) => {
      this._loadingCount++;
      const s = t.urls[e];
      this.add(e, s, this._bufferLoaded.bind(this, t.onload), t.onerror);
    });
  }
  static getDefaults() {
    return {
      baseUrl: "",
      onerror: st,
      onload: st,
      urls: {}
    };
  }
  /**
   * True if the buffers object has a buffer by that name.
   * @param  name  The key or index of the buffer.
   */
  has(t) {
    return this._buffers.has(t.toString());
  }
  /**
   * Get a buffer by name. If an array was loaded,
   * then use the array index.
   * @param  name  The key or index of the buffer.
   */
  get(t) {
    return X(this.has(t), `ToneAudioBuffers has no buffer named: ${t}`), this._buffers.get(t.toString());
  }
  /**
   * A buffer was loaded. decrement the counter.
   */
  _bufferLoaded(t) {
    this._loadingCount--, this._loadingCount === 0 && t && t();
  }
  /**
   * If the buffers are loaded or not
   */
  get loaded() {
    return Array.from(this._buffers).every(([t, e]) => e.loaded);
  }
  /**
   * Add a buffer by name and url to the Buffers
   * @param  name      A unique name to give the buffer
   * @param  url  Either the url of the bufer, or a buffer which will be added with the given name.
   * @param  callback  The callback to invoke when the url is loaded.
   * @param  onerror  Invoked if the buffer can't be loaded
   */
  add(t, e, s = st, i = st) {
    return Qe(e) ? (this.baseUrl && e.trim().substring(0, 11).toLowerCase() === "data:audio/" && (this.baseUrl = ""), this._buffers.set(t.toString(), new ot(this.baseUrl + e, s, i))) : this._buffers.set(t.toString(), new ot(e, s, i)), this;
  }
  dispose() {
    return super.dispose(), this._buffers.forEach((t) => t.dispose()), this._buffers.clear(), this;
  }
}
class oi extends ce {
  constructor() {
    super(...arguments), this.name = "MidiClass", this.defaultUnits = "midi";
  }
  /**
   * Returns the value of a frequency in the current units
   */
  _frequencyToUnits(t) {
    return Us(super._frequencyToUnits(t));
  }
  /**
   * Returns the value of a tick in the current time units
   */
  _ticksToUnits(t) {
    return Us(super._ticksToUnits(t));
  }
  /**
   * Return the value of the beats in the current units
   */
  _beatsToUnits(t) {
    return Us(super._beatsToUnits(t));
  }
  /**
   * Returns the value of a second in the current units
   */
  _secondsToUnits(t) {
    return Us(super._secondsToUnits(t));
  }
  /**
   * Return the value of the frequency as a MIDI note
   * @example
   * Tone.Midi(60).toMidi(); // 60
   */
  toMidi() {
    return this.valueOf();
  }
  /**
   * Return the value of the frequency as a MIDI note
   * @example
   * Tone.Midi(60).toFrequency(); // 261.6255653005986
   */
  toFrequency() {
    return Nc(this.toMidi());
  }
  /**
   * Transposes the frequency by the given number of semitones.
   * @return A new transposed MidiClass
   * @example
   * Tone.Midi("A4").transpose(3); // "C5"
   */
  transpose(t) {
    return new oi(this.context, this.toMidi() + t);
  }
}
function nC(n, t) {
  return new oi(ut(), n, t);
}
class St extends Lt {
  constructor() {
    super(...arguments), this.name = "Ticks", this.defaultUnits = "i";
  }
  /**
   * Get the current time in the given units
   */
  _now() {
    return this.context.transport.ticks;
  }
  /**
   * Return the value of the beats in the current units
   */
  _beatsToUnits(t) {
    return this._getPPQ() * t;
  }
  /**
   * Returns the value of a second in the current units
   */
  _secondsToUnits(t) {
    return Math.floor(t / (60 / this._getBpm()) * this._getPPQ());
  }
  /**
   * Returns the value of a tick in the current time units
   */
  _ticksToUnits(t) {
    return t;
  }
  /**
   * Return the time in ticks
   */
  toTicks() {
    return this.valueOf();
  }
  /**
   * Return the time in seconds
   */
  toSeconds() {
    return this.valueOf() / this._getPPQ() * (60 / this._getBpm());
  }
}
function iC(n, t) {
  return new St(ut(), n, t);
}
class rC extends Xt {
  constructor() {
    super(...arguments), this.name = "Draw", this.expiration = 0.25, this.anticipation = 8e-3, this._events = new Ee(), this._boundDrawLoop = this._drawLoop.bind(this), this._animationFrame = -1;
  }
  /**
   * Schedule a function at the given time to be invoked
   * on the nearest animation frame.
   * @param  callback  Callback is invoked at the given time.
   * @param  time      The time relative to the AudioContext time to invoke the callback.
   * @example
   * Tone.Transport.scheduleRepeat(time => {
   * 	Tone.Draw.schedule(() => console.log(time), time);
   * }, 1);
   * Tone.Transport.start();
   */
  schedule(t, e) {
    return this._events.add({
      callback: t,
      time: this.toSeconds(e)
    }), this._events.length === 1 && (this._animationFrame = requestAnimationFrame(this._boundDrawLoop)), this;
  }
  /**
   * Cancel events scheduled after the given time
   * @param  after  Time after which scheduled events will be removed from the scheduling timeline.
   */
  cancel(t) {
    return this._events.cancel(this.toSeconds(t)), this;
  }
  /**
   * The draw loop
   */
  _drawLoop() {
    const t = this.context.currentTime;
    this._events.forEachBefore(t + this.anticipation, (e) => {
      t - e.time <= this.expiration && e.callback(), this._events.remove(e);
    }), this._events.length > 0 && (this._animationFrame = requestAnimationFrame(this._boundDrawLoop));
  }
  dispose() {
    return super.dispose(), this._events.dispose(), cancelAnimationFrame(this._animationFrame), this;
  }
}
ia((n) => {
  n.draw = new rC({ context: n });
});
ra((n) => {
  n.draw.dispose();
});
class bg extends Ds {
  constructor() {
    super(...arguments), this.name = "IntervalTimeline", this._root = null, this._length = 0;
  }
  /**
   * The event to add to the timeline. All events must
   * have a time and duration value
   * @param  event  The event to add to the timeline
   */
  add(t) {
    X(et(t.time), "Events must have a time property"), X(et(t.duration), "Events must have a duration parameter"), t.time = t.time.valueOf();
    let e = new oC(t.time, t.time + t.duration, t);
    for (this._root === null ? this._root = e : this._root.insert(e), this._length++; e !== null; )
      e.updateHeight(), e.updateMax(), this._rebalance(e), e = e.parent;
    return this;
  }
  /**
   * Remove an event from the timeline.
   * @param  event  The event to remove from the timeline
   */
  remove(t) {
    if (this._root !== null) {
      const e = [];
      this._root.search(t.time, e);
      for (const s of e)
        if (s.event === t) {
          this._removeNode(s), this._length--;
          break;
        }
    }
    return this;
  }
  /**
   * The number of items in the timeline.
   * @readOnly
   */
  get length() {
    return this._length;
  }
  /**
   * Remove events whose time time is after the given time
   * @param  after  The time to query.
   */
  cancel(t) {
    return this.forEachFrom(t, (e) => this.remove(e)), this;
  }
  /**
   * Set the root node as the given node
   */
  _setRoot(t) {
    this._root = t, this._root !== null && (this._root.parent = null);
  }
  /**
   * Replace the references to the node in the node's parent
   * with the replacement node.
   */
  _replaceNodeInParent(t, e) {
    t.parent !== null ? (t.isLeftChild() ? t.parent.left = e : t.parent.right = e, this._rebalance(t.parent)) : this._setRoot(e);
  }
  /**
   * Remove the node from the tree and replace it with
   * a successor which follows the schema.
   */
  _removeNode(t) {
    if (t.left === null && t.right === null)
      this._replaceNodeInParent(t, null);
    else if (t.right === null)
      this._replaceNodeInParent(t, t.left);
    else if (t.left === null)
      this._replaceNodeInParent(t, t.right);
    else {
      const e = t.getBalance();
      let s, i = null;
      if (e > 0)
        if (t.left.right === null)
          s = t.left, s.right = t.right, i = s;
        else {
          for (s = t.left.right; s.right !== null; )
            s = s.right;
          s.parent && (s.parent.right = s.left, i = s.parent, s.left = t.left, s.right = t.right);
        }
      else if (t.right.left === null)
        s = t.right, s.left = t.left, i = s;
      else {
        for (s = t.right.left; s.left !== null; )
          s = s.left;
        s.parent && (s.parent.left = s.right, i = s.parent, s.left = t.left, s.right = t.right);
      }
      t.parent !== null ? t.isLeftChild() ? t.parent.left = s : t.parent.right = s : this._setRoot(s), i && this._rebalance(i);
    }
    t.dispose();
  }
  /**
   * Rotate the tree to the left
   */
  _rotateLeft(t) {
    const e = t.parent, s = t.isLeftChild(), i = t.right;
    i && (t.right = i.left, i.left = t), e !== null ? s ? e.left = i : e.right = i : this._setRoot(i);
  }
  /**
   * Rotate the tree to the right
   */
  _rotateRight(t) {
    const e = t.parent, s = t.isLeftChild(), i = t.left;
    i && (t.left = i.right, i.right = t), e !== null ? s ? e.left = i : e.right = i : this._setRoot(i);
  }
  /**
   * Balance the BST
   */
  _rebalance(t) {
    const e = t.getBalance();
    e > 1 && t.left ? t.left.getBalance() < 0 ? this._rotateLeft(t.left) : this._rotateRight(t) : e < -1 && t.right && (t.right.getBalance() > 0 ? this._rotateRight(t.right) : this._rotateLeft(t));
  }
  /**
   * Get an event whose time and duration span the give time. Will
   * return the match whose "time" value is closest to the given time.
   * @return  The event which spans the desired time
   */
  get(t) {
    if (this._root !== null) {
      const e = [];
      if (this._root.search(t, e), e.length > 0) {
        let s = e[0];
        for (let i = 1; i < e.length; i++)
          e[i].low > s.low && (s = e[i]);
        return s.event;
      }
    }
    return null;
  }
  /**
   * Iterate over everything in the timeline.
   * @param  callback The callback to invoke with every item
   */
  forEach(t) {
    if (this._root !== null) {
      const e = [];
      this._root.traverse((s) => e.push(s)), e.forEach((s) => {
        s.event && t(s.event);
      });
    }
    return this;
  }
  /**
   * Iterate over everything in the array in which the given time
   * overlaps with the time and duration time of the event.
   * @param  time The time to check if items are overlapping
   * @param  callback The callback to invoke with every item
   */
  forEachAtTime(t, e) {
    if (this._root !== null) {
      const s = [];
      this._root.search(t, s), s.forEach((i) => {
        i.event && e(i.event);
      });
    }
    return this;
  }
  /**
   * Iterate over everything in the array in which the time is greater
   * than or equal to the given time.
   * @param  time The time to check if items are before
   * @param  callback The callback to invoke with every item
   */
  forEachFrom(t, e) {
    if (this._root !== null) {
      const s = [];
      this._root.searchAfter(t, s), s.forEach((i) => {
        i.event && e(i.event);
      });
    }
    return this;
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this._root !== null && this._root.traverse((t) => t.dispose()), this._root = null, this;
  }
}
class oC {
  constructor(t, e, s) {
    this._left = null, this._right = null, this.parent = null, this.height = 0, this.event = s, this.low = t, this.high = e, this.max = this.high;
  }
  /**
   * Insert a node into the correct spot in the tree
   */
  insert(t) {
    t.low <= this.low ? this.left === null ? this.left = t : this.left.insert(t) : this.right === null ? this.right = t : this.right.insert(t);
  }
  /**
   * Search the tree for nodes which overlap
   * with the given point
   * @param  point  The point to query
   * @param  results  The array to put the results
   */
  search(t, e) {
    t > this.max || (this.left !== null && this.left.search(t, e), this.low <= t && this.high > t && e.push(this), !(this.low > t) && this.right !== null && this.right.search(t, e));
  }
  /**
   * Search the tree for nodes which are less
   * than the given point
   * @param  point  The point to query
   * @param  results  The array to put the results
   */
  searchAfter(t, e) {
    this.low >= t && (e.push(this), this.left !== null && this.left.searchAfter(t, e)), this.right !== null && this.right.searchAfter(t, e);
  }
  /**
   * Invoke the callback on this element and both it's branches
   * @param  {Function}  callback
   */
  traverse(t) {
    t(this), this.left !== null && this.left.traverse(t), this.right !== null && this.right.traverse(t);
  }
  /**
   * Update the height of the node
   */
  updateHeight() {
    this.left !== null && this.right !== null ? this.height = Math.max(this.left.height, this.right.height) + 1 : this.right !== null ? this.height = this.right.height + 1 : this.left !== null ? this.height = this.left.height + 1 : this.height = 0;
  }
  /**
   * Update the height of the node
   */
  updateMax() {
    this.max = this.high, this.left !== null && (this.max = Math.max(this.max, this.left.max)), this.right !== null && (this.max = Math.max(this.max, this.right.max));
  }
  /**
   * The balance is how the leafs are distributed on the node
   * @return  Negative numbers are balanced to the right
   */
  getBalance() {
    let t = 0;
    return this.left !== null && this.right !== null ? t = this.left.height - this.right.height : this.left !== null ? t = this.left.height + 1 : this.right !== null && (t = -(this.right.height + 1)), t;
  }
  /**
   * @returns true if this node is the left child of its parent
   */
  isLeftChild() {
    return this.parent !== null && this.parent.left === this;
  }
  /**
   * get/set the left node
   */
  get left() {
    return this._left;
  }
  set left(t) {
    this._left = t, t !== null && (t.parent = this), this.updateHeight(), this.updateMax();
  }
  /**
   * get/set the right node
   */
  get right() {
    return this._right;
  }
  set right(t) {
    this._right = t, t !== null && (t.parent = this), this.updateHeight(), this.updateMax();
  }
  /**
   * null out references.
   */
  dispose() {
    this.parent = null, this._left = null, this._right = null, this.event = null;
  }
}
const aC = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null
}, Symbol.toStringTag, { value: "Module" }));
class lC extends Ds {
  /**
   * @param initialValue The value to return if there is no scheduled values
   */
  constructor(t) {
    super(), this.name = "TimelineValue", this._timeline = new Ee({
      memory: 10
    }), this._initialValue = t;
  }
  /**
   * Set the value at the given time
   */
  set(t, e) {
    return this._timeline.add({
      value: t,
      time: e
    }), this;
  }
  /**
   * Get the value at the given time
   */
  get(t) {
    const e = this._timeline.get(t);
    return e ? e.value : this._initialValue;
  }
}
class Re extends B {
  constructor() {
    super(L(Re.getDefaults(), arguments, [
      "context"
    ]));
  }
  connect(t, e = 0, s = 0) {
    return wr(this, t, e, s), this;
  }
}
class ss extends Re {
  constructor() {
    const t = L(ss.getDefaults(), arguments, ["mapping", "length"]);
    super(t), this.name = "WaveShaper", this._shaper = this.context.createWaveShaper(), this.input = this._shaper, this.output = this._shaper, Kt(t.mapping) || t.mapping instanceof Float32Array ? this.curve = Float32Array.from(t.mapping) : fg(t.mapping) && this.setMap(t.mapping, t.length);
  }
  static getDefaults() {
    return Object.assign(Q.getDefaults(), {
      length: 1024
    });
  }
  /**
   * Uses a mapping function to set the value of the curve.
   * @param mapping The function used to define the values.
   *                The mapping function take two arguments:
   *                the first is the value at the current position
   *                which goes from -1 to 1 over the number of elements
   *                in the curve array. The second argument is the array position.
   * @example
   * const shaper = new Tone.WaveShaper();
   * // map the input signal from [-1, 1] to [0, 10]
   * shaper.setMap((val, index) => (val + 1) * 5);
   */
  setMap(t, e = 1024) {
    const s = new Float32Array(e);
    for (let i = 0, r = e; i < r; i++) {
      const o = i / (r - 1) * 2 - 1;
      s[i] = t(o, i);
    }
    return this.curve = s, this;
  }
  /**
   * The array to set as the waveshaper curve. For linear curves
   * array length does not make much difference, but for complex curves
   * longer arrays will provide smoother interpolation.
   */
  get curve() {
    return this._shaper.curve;
  }
  set curve(t) {
    this._shaper.curve = t;
  }
  /**
   * Specifies what type of oversampling (if any) should be used when
   * applying the shaping curve. Can either be "none", "2x" or "4x".
   */
  get oversample() {
    return this._shaper.oversample;
  }
  set oversample(t) {
    const e = ["none", "2x", "4x"].some((s) => s.includes(t));
    X(e, "oversampling must be either 'none', '2x', or '4x'"), this._shaper.oversample = t;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._shaper.disconnect(), this;
  }
}
class wi extends Re {
  constructor() {
    const t = L(wi.getDefaults(), arguments, [
      "value"
    ]);
    super(t), this.name = "Pow", this._exponentScaler = this.input = this.output = new ss({
      context: this.context,
      mapping: this._expFunc(t.value),
      length: 8192
    }), this._exponent = t.value;
  }
  static getDefaults() {
    return Object.assign(Re.getDefaults(), {
      value: 1
    });
  }
  /**
   * the function which maps the waveshaper
   * @param exponent exponent value
   */
  _expFunc(t) {
    return (e) => Math.pow(Math.abs(e), t);
  }
  /**
   * The value of the exponent.
   */
  get value() {
    return this._exponent;
  }
  set value(t) {
    this._exponent = t, this._exponentScaler.setMap(this._expFunc(this._exponent));
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._exponentScaler.dispose(), this;
  }
}
class Xs {
  /**
   * @param transport The transport object which the event belongs to
   */
  constructor(t, e) {
    this.id = Xs._eventId++, this._remainderTime = 0;
    const s = Object.assign(Xs.getDefaults(), e);
    this.transport = t, this.callback = s.callback, this._once = s.once, this.time = Math.floor(s.time), this._remainderTime = s.time - this.time;
  }
  static getDefaults() {
    return {
      callback: st,
      once: !1,
      time: 0
    };
  }
  /**
   * Get the time and remainder time.
   */
  get floatTime() {
    return this.time + this._remainderTime;
  }
  /**
   * Invoke the event callback.
   * @param  time  The AudioContext time in seconds of the event
   */
  invoke(t) {
    if (this.callback) {
      const e = this.transport.bpm.getDurationOfTicks(1, t);
      this.callback(t + this._remainderTime * e), this._once && this.transport.clear(this.id);
    }
  }
  /**
   * Clean up
   */
  dispose() {
    return this.callback = void 0, this;
  }
}
Xs._eventId = 0;
class Gc extends Xs {
  /**
   * @param transport The transport object which the event belongs to
   */
  constructor(t, e) {
    super(t, e), this._currentId = -1, this._nextId = -1, this._nextTick = this.time, this._boundRestart = this._restart.bind(this);
    const s = Object.assign(Gc.getDefaults(), e);
    this.duration = s.duration, this._interval = s.interval, this._nextTick = s.time, this.transport.on("start", this._boundRestart), this.transport.on("loopStart", this._boundRestart), this.transport.on("ticks", this._boundRestart), this.context = this.transport.context, this._restart();
  }
  static getDefaults() {
    return Object.assign({}, Xs.getDefaults(), {
      duration: 1 / 0,
      interval: 1,
      once: !1
    });
  }
  /**
   * Invoke the callback. Returns the tick time which
   * the next event should be scheduled at.
   * @param  time  The AudioContext time in seconds of the event
   */
  invoke(t) {
    this._createEvents(t), super.invoke(t);
  }
  /**
   * Create an event on the transport on the nextTick
   */
  _createEvent() {
    return Bo(this._nextTick, this.floatTime + this.duration) ? this.transport.scheduleOnce(this.invoke.bind(this), new St(this.context, this._nextTick).toSeconds()) : -1;
  }
  /**
   * Push more events onto the timeline to keep up with the position of the timeline
   */
  _createEvents(t) {
    Bo(this._nextTick + this._interval, this.floatTime + this.duration) && (this._nextTick += this._interval, this._currentId = this._nextId, this._nextId = this.transport.scheduleOnce(this.invoke.bind(this), new St(this.context, this._nextTick).toSeconds()));
  }
  /**
   * Re-compute the events when the transport time has changed from a start/ticks/loopStart event
   */
  _restart(t) {
    this.transport.clear(this._currentId), this.transport.clear(this._nextId), this._nextTick = this.floatTime;
    const e = this.transport.getTicksAtTime(t);
    si(e, this.time) && (this._nextTick = this.floatTime + Math.ceil((e - this.floatTime) / this._interval) * this._interval), this._currentId = this._createEvent(), this._nextTick += this._interval, this._nextId = this._createEvent();
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this.transport.clear(this._currentId), this.transport.clear(this._nextId), this.transport.off("start", this._boundRestart), this.transport.off("loopStart", this._boundRestart), this.transport.off("ticks", this._boundRestart), this;
  }
}
class la extends Xt {
  constructor() {
    const t = L(la.getDefaults(), arguments);
    super(t), this.name = "Transport", this._loop = new lC(!1), this._loopStart = 0, this._loopEnd = 0, this._scheduledEvents = {}, this._timeline = new Ee(), this._repeatedEvents = new bg(), this._syncedSignals = [], this._swingAmount = 0, this._ppq = t.ppq, this._clock = new vi({
      callback: this._processTick.bind(this),
      context: this.context,
      frequency: 0,
      units: "bpm"
    }), this._bindClockEvents(), this.bpm = this._clock.frequency, this._clock.frequency.multiplier = t.ppq, this.bpm.setValueAtTime(t.bpm, 0), Z(this, "bpm"), this._timeSignature = t.timeSignature, this._swingTicks = t.ppq / 2;
  }
  static getDefaults() {
    return Object.assign(Xt.getDefaults(), {
      bpm: 120,
      loopEnd: "4m",
      loopStart: 0,
      ppq: 192,
      swing: 0,
      swingSubdivision: "8n",
      timeSignature: 4
    });
  }
  //-------------------------------------
  // 	TICKS
  //-------------------------------------
  /**
   * called on every tick
   * @param  tickTime clock relative tick time
   */
  _processTick(t, e) {
    if (this._loop.get(t) && e >= this._loopEnd && (this.emit("loopEnd", t), this._clock.setTicksAtTime(this._loopStart, t), e = this._loopStart, this.emit("loopStart", t, this._clock.getSecondsAtTime(t)), this.emit("loop", t)), this._swingAmount > 0 && e % this._ppq !== 0 && // not on a downbeat
    e % (this._swingTicks * 2) !== 0) {
      const s = e % (this._swingTicks * 2) / (this._swingTicks * 2), i = Math.sin(s * Math.PI) * this._swingAmount;
      t += new St(this.context, this._swingTicks * 2 / 3).toSeconds() * i;
    }
    zl(!0), this._timeline.forEachAtTime(e, (s) => s.invoke(t)), zl(!1);
  }
  //-------------------------------------
  // 	SCHEDULABLE EVENTS
  //-------------------------------------
  /**
   * Schedule an event along the timeline.
   * @param callback The callback to be invoked at the time.
   * @param time The time to invoke the callback at.
   * @return The id of the event which can be used for canceling the event.
   * @example
   * // schedule an event on the 16th measure
   * Tone.getTransport().schedule((time) => {
   * 	// invoked on measure 16
   * 	console.log("measure 16!");
   * }, "16:0:0");
   */
  schedule(t, e) {
    const s = new Xs(this, {
      callback: t,
      time: new Lt(this.context, e).toTicks()
    });
    return this._addEvent(s, this._timeline);
  }
  /**
   * Schedule a repeated event along the timeline. The event will fire
   * at the `interval` starting at the `startTime` and for the specified
   * `duration`.
   * @param  callback   The callback to invoke.
   * @param  interval   The duration between successive callbacks. Must be a positive number.
   * @param  startTime  When along the timeline the events should start being invoked.
   * @param  duration How long the event should repeat.
   * @return  The ID of the scheduled event. Use this to cancel the event.
   * @example
   * const osc = new Tone.Oscillator().toDestination().start();
   * // a callback invoked every eighth note after the first measure
   * Tone.getTransport().scheduleRepeat((time) => {
   * 	osc.start(time).stop(time + 0.1);
   * }, "8n", "1m");
   */
  scheduleRepeat(t, e, s, i = 1 / 0) {
    const r = new Gc(this, {
      callback: t,
      duration: new ke(this.context, i).toTicks(),
      interval: new ke(this.context, e).toTicks(),
      time: new Lt(this.context, s).toTicks()
    });
    return this._addEvent(r, this._repeatedEvents);
  }
  /**
   * Schedule an event that will be removed after it is invoked.
   * @param callback The callback to invoke once.
   * @param time The time the callback should be invoked.
   * @returns The ID of the scheduled event.
   */
  scheduleOnce(t, e) {
    const s = new Xs(this, {
      callback: t,
      once: !0,
      time: new Lt(this.context, e).toTicks()
    });
    return this._addEvent(s, this._timeline);
  }
  /**
   * Clear the passed in event id from the timeline
   * @param eventId The id of the event.
   */
  clear(t) {
    if (this._scheduledEvents.hasOwnProperty(t)) {
      const e = this._scheduledEvents[t.toString()];
      e.timeline.remove(e.event), e.event.dispose(), delete this._scheduledEvents[t.toString()];
    }
    return this;
  }
  /**
   * Add an event to the correct timeline. Keep track of the
   * timeline it was added to.
   * @returns the event id which was just added
   */
  _addEvent(t, e) {
    return this._scheduledEvents[t.id.toString()] = {
      event: t,
      timeline: e
    }, e.add(t), t.id;
  }
  /**
   * Remove scheduled events from the timeline after
   * the given time. Repeated events will be removed
   * if their startTime is after the given time
   * @param after Clear all events after this time.
   */
  cancel(t = 0) {
    const e = this.toTicks(t);
    return this._timeline.forEachFrom(e, (s) => this.clear(s.id)), this._repeatedEvents.forEachFrom(e, (s) => this.clear(s.id)), this;
  }
  //-------------------------------------
  // 	START/STOP/PAUSE
  //-------------------------------------
  /**
   * Bind start/stop/pause events from the clock and emit them.
   */
  _bindClockEvents() {
    this._clock.on("start", (t, e) => {
      e = new St(this.context, e).toSeconds(), this.emit("start", t, e);
    }), this._clock.on("stop", (t) => {
      this.emit("stop", t);
    }), this._clock.on("pause", (t) => {
      this.emit("pause", t);
    });
  }
  /**
   * Returns the playback state of the source, either "started", "stopped", or "paused"
   */
  get state() {
    return this._clock.getStateAtTime(this.now());
  }
  /**
   * Start the transport and all sources synced to the transport.
   * @param  time The time when the transport should start.
   * @param  offset The timeline offset to start the transport.
   * @example
   * // start the transport in one second starting at beginning of the 5th measure.
   * Tone.getTransport().start("+1", "4:0:0");
   */
  start(t, e) {
    this.context.resume();
    let s;
    return et(e) && (s = this.toTicks(e)), this._clock.start(t, s), this;
  }
  /**
   * Stop the transport and all sources synced to the transport.
   * @param time The time when the transport should stop.
   * @example
   * Tone.getTransport().stop();
   */
  stop(t) {
    return this._clock.stop(t), this;
  }
  /**
   * Pause the transport and all sources synced to the transport.
   */
  pause(t) {
    return this._clock.pause(t), this;
  }
  /**
   * Toggle the current state of the transport. If it is
   * started, it will stop it, otherwise it will start the Transport.
   * @param  time The time of the event
   */
  toggle(t) {
    return t = this.toSeconds(t), this._clock.getStateAtTime(t) !== "started" ? this.start(t) : this.stop(t), this;
  }
  //-------------------------------------
  // 	SETTERS/GETTERS
  //-------------------------------------
  /**
   * The time signature as just the numerator over 4.
   * For example 4/4 would be just 4 and 6/8 would be 3.
   * @example
   * // common time
   * Tone.getTransport().timeSignature = 4;
   * // 7/8
   * Tone.getTransport().timeSignature = [7, 8];
   * // this will be reduced to a single number
   * Tone.getTransport().timeSignature; // returns 3.5
   */
  get timeSignature() {
    return this._timeSignature;
  }
  set timeSignature(t) {
    Kt(t) && (t = t[0] / t[1] * 4), this._timeSignature = t;
  }
  /**
   * When the Transport.loop = true, this is the starting position of the loop.
   */
  get loopStart() {
    return new ke(this.context, this._loopStart, "i").toSeconds();
  }
  set loopStart(t) {
    this._loopStart = this.toTicks(t);
  }
  /**
   * When the Transport.loop = true, this is the ending position of the loop.
   */
  get loopEnd() {
    return new ke(this.context, this._loopEnd, "i").toSeconds();
  }
  set loopEnd(t) {
    this._loopEnd = this.toTicks(t);
  }
  /**
   * If the transport loops or not.
   */
  get loop() {
    return this._loop.get(this.now());
  }
  set loop(t) {
    this._loop.set(t, this.now());
  }
  /**
   * Set the loop start and stop at the same time.
   * @example
   * // loop over the first measure
   * Tone.getTransport().setLoopPoints(0, "1m");
   * Tone.getTransport().loop = true;
   */
  setLoopPoints(t, e) {
    return this.loopStart = t, this.loopEnd = e, this;
  }
  /**
   * The swing value. Between 0-1 where 1 equal to the note + half the subdivision.
   */
  get swing() {
    return this._swingAmount;
  }
  set swing(t) {
    this._swingAmount = t;
  }
  /**
   * Set the subdivision which the swing will be applied to.
   * The default value is an 8th note. Value must be less
   * than a quarter note.
   */
  get swingSubdivision() {
    return new St(this.context, this._swingTicks).toNotation();
  }
  set swingSubdivision(t) {
    this._swingTicks = this.toTicks(t);
  }
  /**
   * The Transport's position in Bars:Beats:Sixteenths.
   * Setting the value will jump to that position right away.
   */
  get position() {
    const t = this.now(), e = this._clock.getTicksAtTime(t);
    return new St(this.context, e).toBarsBeatsSixteenths();
  }
  set position(t) {
    const e = this.toTicks(t);
    this.ticks = e;
  }
  /**
   * The Transport's position in seconds.
   * Setting the value will jump to that position right away.
   */
  get seconds() {
    return this._clock.seconds;
  }
  set seconds(t) {
    const e = this.now(), s = this._clock.frequency.timeToTicks(t, e);
    this.ticks = s;
  }
  /**
   * The Transport's loop position as a normalized value. Always
   * returns 0 if the Transport.loop = false.
   */
  get progress() {
    if (this.loop) {
      const t = this.now();
      return (this._clock.getTicksAtTime(t) - this._loopStart) / (this._loopEnd - this._loopStart);
    } else
      return 0;
  }
  /**
   * The Transport's current tick position.
   */
  get ticks() {
    return this._clock.ticks;
  }
  set ticks(t) {
    if (this._clock.ticks !== t) {
      const e = this.now();
      if (this.state === "started") {
        const s = this._clock.getTicksAtTime(e), i = this._clock.frequency.getDurationOfTicks(Math.ceil(s) - s, e), r = e + i;
        this.emit("stop", r), this._clock.setTicksAtTime(t, r), this.emit("start", r, this._clock.getSecondsAtTime(r));
      } else
        this.emit("ticks", e), this._clock.setTicksAtTime(t, e);
    }
  }
  /**
   * Get the clock's ticks at the given time.
   * @param  time  When to get the tick value
   * @return The tick value at the given time.
   */
  getTicksAtTime(t) {
    return this._clock.getTicksAtTime(t);
  }
  /**
   * Return the elapsed seconds at the given time.
   * @param  time  When to get the elapsed seconds
   * @return  The number of elapsed seconds
   */
  getSecondsAtTime(t) {
    return this._clock.getSecondsAtTime(t);
  }
  /**
   * Pulses Per Quarter note. This is the smallest resolution
   * the Transport timing supports. This should be set once
   * on initialization and not set again. Changing this value
   * after other objects have been created can cause problems.
   */
  get PPQ() {
    return this._clock.frequency.multiplier;
  }
  set PPQ(t) {
    this._clock.frequency.multiplier = t;
  }
  //-------------------------------------
  // 	SYNCING
  //-------------------------------------
  /**
   * Returns the time aligned to the next subdivision
   * of the Transport. If the Transport is not started,
   * it will return 0.
   * Note: this will not work precisely during tempo ramps.
   * @param  subdivision  The subdivision to quantize to
   * @return  The context time of the next subdivision.
   * @example
   * // the transport must be started, otherwise returns 0
   * Tone.getTransport().start();
   * Tone.getTransport().nextSubdivision("4n");
   */
  nextSubdivision(t) {
    if (t = this.toTicks(t), this.state !== "started")
      return 0;
    {
      const e = this.now(), s = this.getTicksAtTime(e), i = t - s % t;
      return this._clock.nextTickTime(i, e);
    }
  }
  /**
   * Attaches the signal to the tempo control signal so that
   * any changes in the tempo will change the signal in the same
   * ratio.
   *
   * @param signal
   * @param ratio Optionally pass in the ratio between the two signals.
   * 			Otherwise it will be computed based on their current values.
   */
  syncSignal(t, e) {
    const s = this.now();
    let i = this.bpm, r = 1 / (60 / i.getValueAtTime(s) / this.PPQ), o = [];
    if (t.units === "time") {
      const l = 0.015625 / r, c = new j(l), h = new wi(-1), u = new j(l);
      i.chain(c, h, u), i = u, r = 1 / r, o = [c, h, u];
    }
    e || (t.getValueAtTime(s) !== 0 ? e = t.getValueAtTime(s) / r : e = 0);
    const a = new j(e);
    return i.connect(a), a.connect(t._param), o.push(a), this._syncedSignals.push({
      initial: t.value,
      nodes: o,
      signal: t
    }), t.value = 0, this;
  }
  /**
   * Unsyncs a previously synced signal from the transport's control.
   * @see {@link syncSignal}.
   */
  unsyncSignal(t) {
    for (let e = this._syncedSignals.length - 1; e >= 0; e--) {
      const s = this._syncedSignals[e];
      s.signal === t && (s.nodes.forEach((i) => i.dispose()), s.signal.value = s.initial, this._syncedSignals.splice(e, 1));
    }
    return this;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._clock.dispose(), vr(this, "bpm"), this._timeline.dispose(), this._repeatedEvents.dispose(), this;
  }
}
gi.mixin(la);
ia((n) => {
  n.transport = new la({ context: n });
});
ra((n) => {
  n.transport.dispose();
});
class Ft extends B {
  constructor(t) {
    super(t), this.input = void 0, this._state = new _i("stopped"), this._synced = !1, this._scheduled = [], this._syncedStart = st, this._syncedStop = st, this._state.memory = 100, this._state.increasing = !0, this._volume = this.output = new Os({
      context: this.context,
      mute: t.mute,
      volume: t.volume
    }), this.volume = this._volume.volume, Z(this, "volume"), this.onstop = t.onstop;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      mute: !1,
      onstop: st,
      volume: 0
    });
  }
  /**
   * Returns the playback state of the source, either "started" or "stopped".
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/berklee/ahntone_c3.mp3", () => {
   * 	player.start();
   * 	console.log(player.state);
   * }).toDestination();
   */
  get state() {
    return this._synced ? this.context.transport.state === "started" ? this._state.getValueAtTime(this.context.transport.seconds) : "stopped" : this._state.getValueAtTime(this.now());
  }
  /**
   * Mute the output.
   * @example
   * const osc = new Tone.Oscillator().toDestination().start();
   * // mute the output
   * osc.mute = true;
   */
  get mute() {
    return this._volume.mute;
  }
  set mute(t) {
    this._volume.mute = t;
  }
  /**
   * Ensure that the scheduled time is not before the current time.
   * Should only be used when scheduled unsynced.
   */
  _clampToCurrentTime(t) {
    return this._synced ? t : Math.max(t, this.context.currentTime);
  }
  /**
   * Start the source at the specified time. If no time is given,
   * start the source now.
   * @param  time When the source should be started.
   * @example
   * const source = new Tone.Oscillator().toDestination();
   * source.start("+0.5"); // starts the source 0.5 seconds from now
   */
  start(t, e, s) {
    let i = ve(t) && this._synced ? this.context.transport.seconds : this.toSeconds(t);
    if (i = this._clampToCurrentTime(i), !this._synced && this._state.getValueAtTime(i) === "started")
      X(si(i, this._state.get(i).time), "Start time must be strictly greater than previous start time"), this._state.cancel(i), this._state.setStateAtTime("started", i), this.log("restart", i), this.restart(i, e, s);
    else if (this.log("start", i), this._state.setStateAtTime("started", i), this._synced) {
      const r = this._state.get(i);
      r && (r.offset = this.toSeconds(Ve(e, 0)), r.duration = s ? this.toSeconds(s) : void 0);
      const o = this.context.transport.schedule((a) => {
        this._start(a, e, s);
      }, i);
      this._scheduled.push(o), this.context.transport.state === "started" && this.context.transport.getSecondsAtTime(this.immediate()) > i && this._syncedStart(this.now(), this.context.transport.seconds);
    } else
      Ic(this.context), this._start(i, e, s);
    return this;
  }
  /**
   * Stop the source at the specified time. If no time is given,
   * stop the source now.
   * @param  time When the source should be stopped.
   * @example
   * const source = new Tone.Oscillator().toDestination();
   * source.start();
   * source.stop("+0.5"); // stops the source 0.5 seconds from now
   */
  stop(t) {
    let e = ve(t) && this._synced ? this.context.transport.seconds : this.toSeconds(t);
    if (e = this._clampToCurrentTime(e), this._state.getValueAtTime(e) === "started" || et(this._state.getNextState("started", e))) {
      if (this.log("stop", e), !this._synced)
        this._stop(e);
      else {
        const s = this.context.transport.schedule(this._stop.bind(this), e);
        this._scheduled.push(s);
      }
      this._state.cancel(e), this._state.setStateAtTime("stopped", e);
    }
    return this;
  }
  /**
   * Restart the source.
   */
  restart(t, e, s) {
    return t = this.toSeconds(t), this._state.getValueAtTime(t) === "started" && (this._state.cancel(t), this._restart(t, e, s)), this;
  }
  /**
   * Sync the source to the Transport so that all subsequent
   * calls to `start` and `stop` are synced to the TransportTime
   * instead of the AudioContext time.
   *
   * @example
   * const osc = new Tone.Oscillator().toDestination();
   * // sync the source so that it plays between 0 and 0.3 on the Transport's timeline
   * osc.sync().start(0).stop(0.3);
   * // start the transport.
   * Tone.Transport.start();
   * // set it to loop once a second
   * Tone.Transport.loop = true;
   * Tone.Transport.loopEnd = 1;
   */
  sync() {
    return this._synced || (this._synced = !0, this._syncedStart = (t, e) => {
      if (si(e, 0)) {
        const s = this._state.get(e);
        if (s && s.state === "started" && s.time !== e) {
          const i = e - this.toSeconds(s.time);
          let r;
          s.duration && (r = this.toSeconds(s.duration) - i), this._start(t, this.toSeconds(s.offset) + i, r);
        }
      }
    }, this._syncedStop = (t) => {
      const e = this.context.transport.getSecondsAtTime(Math.max(t - this.sampleTime, 0));
      this._state.getValueAtTime(e) === "started" && this._stop(t);
    }, this.context.transport.on("start", this._syncedStart), this.context.transport.on("loopStart", this._syncedStart), this.context.transport.on("stop", this._syncedStop), this.context.transport.on("pause", this._syncedStop), this.context.transport.on("loopEnd", this._syncedStop)), this;
  }
  /**
   * Unsync the source to the Transport.
   * @see {@link sync}
   */
  unsync() {
    return this._synced && (this.context.transport.off("stop", this._syncedStop), this.context.transport.off("pause", this._syncedStop), this.context.transport.off("loopEnd", this._syncedStop), this.context.transport.off("start", this._syncedStart), this.context.transport.off("loopStart", this._syncedStart)), this._synced = !1, this._scheduled.forEach((t) => this.context.transport.clear(t)), this._scheduled = [], this._state.cancel(0), this._stop(0), this;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this.onstop = st, this.unsync(), this._volume.dispose(), this._state.dispose(), this;
  }
}
class tn extends ri {
  constructor() {
    const t = L(tn.getDefaults(), arguments, ["url", "onload"]);
    super(t), this.name = "ToneBufferSource", this._source = this.context.createBufferSource(), this._internalChannels = [this._source], this._sourceStarted = !1, this._sourceStopped = !1, ue(this._source, this._gainNode), this._source.onended = () => this._stopSource(), this.playbackRate = new tt({
      context: this.context,
      param: this._source.playbackRate,
      units: "positive",
      value: t.playbackRate
    }), this.loop = t.loop, this.loopStart = t.loopStart, this.loopEnd = t.loopEnd, this._buffer = new ot(t.url, t.onload, t.onerror), this._internalChannels.push(this._source);
  }
  static getDefaults() {
    return Object.assign(ri.getDefaults(), {
      url: new ot(),
      loop: !1,
      loopEnd: 0,
      loopStart: 0,
      onload: st,
      onerror: st,
      playbackRate: 1
    });
  }
  /**
   * The fadeIn time of the amplitude envelope.
   */
  get fadeIn() {
    return this._fadeIn;
  }
  set fadeIn(t) {
    this._fadeIn = t;
  }
  /**
   * The fadeOut time of the amplitude envelope.
   */
  get fadeOut() {
    return this._fadeOut;
  }
  set fadeOut(t) {
    this._fadeOut = t;
  }
  /**
   * The curve applied to the fades, either "linear" or "exponential"
   */
  get curve() {
    return this._curve;
  }
  set curve(t) {
    this._curve = t;
  }
  /**
   * Start the buffer
   * @param  time When the player should start.
   * @param  offset The offset from the beginning of the sample to start at.
   * @param  duration How long the sample should play. If no duration is given, it will default to the full length of the sample (minus any offset)
   * @param  gain  The gain to play the buffer back at.
   */
  start(t, e, s, i = 1) {
    X(this.buffer.loaded, "buffer is either not set or not loaded");
    const r = this.toSeconds(t);
    this._startGain(r, i), this.loop ? e = Ve(e, this.loopStart) : e = Ve(e, 0);
    let o = Math.max(this.toSeconds(e), 0);
    if (this.loop) {
      const a = this.toSeconds(this.loopEnd) || this.buffer.duration, l = this.toSeconds(this.loopStart), c = a - l;
      ql(o, a) && (o = (o - l) % c + l), $e(o, this.buffer.duration) && (o = 0);
    }
    if (this._source.buffer = this.buffer.get(), this._source.loopEnd = this.toSeconds(this.loopEnd) || this.buffer.duration, Bo(o, this.buffer.duration) && (this._sourceStarted = !0, this._source.start(r, o)), et(s)) {
      let a = this.toSeconds(s);
      a = Math.max(a, 0), this.stop(r + a);
    }
    return this;
  }
  _stopSource(t) {
    !this._sourceStopped && this._sourceStarted && (this._sourceStopped = !0, this._source.stop(this.toSeconds(t)), this._onended());
  }
  /**
   * If loop is true, the loop will start at this position.
   */
  get loopStart() {
    return this._source.loopStart;
  }
  set loopStart(t) {
    this._source.loopStart = this.toSeconds(t);
  }
  /**
   * If loop is true, the loop will end at this position.
   */
  get loopEnd() {
    return this._source.loopEnd;
  }
  set loopEnd(t) {
    this._source.loopEnd = this.toSeconds(t);
  }
  /**
   * The audio buffer belonging to the player.
   */
  get buffer() {
    return this._buffer;
  }
  set buffer(t) {
    this._buffer.set(t);
  }
  /**
   * If the buffer should loop once it's over.
   */
  get loop() {
    return this._source.loop;
  }
  set loop(t) {
    this._source.loop = t, this._sourceStarted && this.cancelStop();
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._source.onended = null, this._source.disconnect(), this._buffer.dispose(), this.playbackRate.dispose(), this;
  }
}
class Ys extends Ft {
  constructor() {
    const t = L(Ys.getDefaults(), arguments, [
      "type"
    ]);
    super(t), this.name = "Noise", this._source = null, this._playbackRate = t.playbackRate, this.type = t.type, this._fadeIn = t.fadeIn, this._fadeOut = t.fadeOut;
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      fadeIn: 0,
      fadeOut: 0,
      playbackRate: 1,
      type: "white"
    });
  }
  /**
   * The type of the noise. Can be "white", "brown", or "pink".
   * @example
   * const noise = new Tone.Noise().toDestination().start();
   * noise.type = "brown";
   */
  get type() {
    return this._type;
  }
  set type(t) {
    if (X(t in rf, "Noise: invalid type: " + t), this._type !== t && (this._type = t, this.state === "started")) {
      const e = this.now();
      this._stop(e), this._start(e);
    }
  }
  /**
   * The playback rate of the noise. Affects
   * the "frequency" of the noise.
   */
  get playbackRate() {
    return this._playbackRate;
  }
  set playbackRate(t) {
    this._playbackRate = t, this._source && (this._source.playbackRate.value = t);
  }
  /**
   * internal start method
   */
  _start(t) {
    const e = rf[this._type];
    this._source = new tn({
      url: e,
      context: this.context,
      fadeIn: this._fadeIn,
      fadeOut: this._fadeOut,
      loop: !0,
      onended: () => this.onstop(this),
      playbackRate: this._playbackRate
    }).connect(this.output), this._source.start(this.toSeconds(t), Math.random() * (e.duration - 1e-3));
  }
  /**
   * internal stop method
   */
  _stop(t) {
    this._source && (this._source.stop(this.toSeconds(t)), this._source = null);
  }
  /**
   * The fadeIn time of the amplitude envelope.
   */
  get fadeIn() {
    return this._fadeIn;
  }
  set fadeIn(t) {
    this._fadeIn = t, this._source && (this._source.fadeIn = this._fadeIn);
  }
  /**
   * The fadeOut time of the amplitude envelope.
   */
  get fadeOut() {
    return this._fadeOut;
  }
  set fadeOut(t) {
    this._fadeOut = t, this._source && (this._source.fadeOut = this._fadeOut);
  }
  _restart(t) {
    this._stop(t), this._start(t);
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._source && this._source.disconnect(), this;
  }
}
const Ln = 44100 * 5, el = 2, ws = {
  brown: null,
  pink: null,
  white: null
}, rf = {
  get brown() {
    if (!ws.brown) {
      const n = [];
      for (let t = 0; t < el; t++) {
        const e = new Float32Array(Ln);
        n[t] = e;
        let s = 0;
        for (let i = 0; i < Ln; i++) {
          const r = Math.random() * 2 - 1;
          e[i] = (s + 0.02 * r) / 1.02, s = e[i], e[i] *= 3.5;
        }
      }
      ws.brown = new ot().fromArray(n);
    }
    return ws.brown;
  },
  get pink() {
    if (!ws.pink) {
      const n = [];
      for (let t = 0; t < el; t++) {
        const e = new Float32Array(Ln);
        n[t] = e;
        let s, i, r, o, a, l, c;
        s = i = r = o = a = l = c = 0;
        for (let h = 0; h < Ln; h++) {
          const u = Math.random() * 2 - 1;
          s = 0.99886 * s + u * 0.0555179, i = 0.99332 * i + u * 0.0750759, r = 0.969 * r + u * 0.153852, o = 0.8665 * o + u * 0.3104856, a = 0.55 * a + u * 0.5329522, l = -0.7616 * l - u * 0.016898, e[h] = s + i + r + o + a + l + c + u * 0.5362, e[h] *= 0.11, c = u * 0.115926;
        }
      }
      ws.pink = new ot().fromArray(n);
    }
    return ws.pink;
  },
  get white() {
    if (!ws.white) {
      const n = [];
      for (let t = 0; t < el; t++) {
        const e = new Float32Array(Ln);
        n[t] = e;
        for (let s = 0; s < Ln; s++)
          e[s] = Math.random() * 2 - 1;
      }
      ws.white = new ot().fromArray(n);
    }
    return ws.white;
  }
};
class Xi extends B {
  constructor() {
    const t = L(Xi.getDefaults(), arguments, ["volume"]);
    super(t), this.name = "UserMedia", this._volume = this.output = new Os({
      context: this.context,
      volume: t.volume
    }), this.volume = this._volume.volume, Z(this, "volume"), this.mute = t.mute;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      mute: !1,
      volume: 0
    });
  }
  /**
   * Open the media stream. If a string is passed in, it is assumed
   * to be the label or id of the stream, if a number is passed in,
   * it is the input number of the stream.
   * @param  labelOrId The label or id of the audio input media device.
   *                   With no argument, the default stream is opened.
   * @return The promise is resolved when the stream is open.
   */
  open(t) {
    return yt(this, void 0, void 0, function* () {
      X(Xi.supported, "UserMedia is not supported"), this.state === "started" && this.close();
      const e = yield Xi.enumerateDevices();
      Ie(t) ? this._device = e[t] : (this._device = e.find((r) => r.label === t || r.deviceId === t), !this._device && e.length > 0 && (this._device = e[0]), X(et(this._device), `No matching device ${t}`));
      const s = {
        audio: {
          echoCancellation: !1,
          sampleRate: this.context.sampleRate,
          noiseSuppression: !1,
          mozNoiseSuppression: !1
        }
      };
      this._device && (s.audio.deviceId = this._device.deviceId);
      const i = yield navigator.mediaDevices.getUserMedia(s);
      if (!this._stream) {
        this._stream = i;
        const r = this.context.createMediaStreamSource(i);
        ue(r, this.output), this._mediaStream = r;
      }
      return this;
    });
  }
  /**
   * Close the media stream
   */
  close() {
    return this._stream && this._mediaStream && (this._stream.getAudioTracks().forEach((t) => {
      t.stop();
    }), this._stream = void 0, this._mediaStream.disconnect(), this._mediaStream = void 0), this._device = void 0, this;
  }
  /**
   * Returns a promise which resolves with the list of audio input devices available.
   * @return The promise that is resolved with the devices
   * @example
   * Tone.UserMedia.enumerateDevices().then((devices) => {
   * 	// print the device labels
   * 	console.log(devices.map(device => device.label));
   * });
   */
  static enumerateDevices() {
    return yt(this, void 0, void 0, function* () {
      return (yield navigator.mediaDevices.enumerateDevices()).filter((e) => e.kind === "audioinput");
    });
  }
  /**
   * Returns the playback state of the source, "started" when the microphone is open
   * and "stopped" when the mic is closed.
   */
  get state() {
    return this._stream && this._stream.active ? "started" : "stopped";
  }
  /**
   * Returns an identifier for the represented device that is
   * persisted across sessions. It is un-guessable by other applications and
   * unique to the origin of the calling application. It is reset when the
   * user clears cookies (for Private Browsing, a different identifier is
   * used that is not persisted across sessions). Returns undefined when the
   * device is not open.
   */
  get deviceId() {
    if (this._device)
      return this._device.deviceId;
  }
  /**
   * Returns a group identifier. Two devices have the
   * same group identifier if they belong to the same physical device.
   * Returns null  when the device is not open.
   */
  get groupId() {
    if (this._device)
      return this._device.groupId;
  }
  /**
   * Returns a label describing this device (for example "Built-in Microphone").
   * Returns undefined when the device is not open or label is not available
   * because of permissions.
   */
  get label() {
    if (this._device)
      return this._device.label;
  }
  /**
   * Mute the output.
   * @example
   * const mic = new Tone.UserMedia();
   * mic.open().then(() => {
   * 	// promise resolves when input is available
   * });
   * // mute the output
   * mic.mute = true;
   */
  get mute() {
    return this._volume.mute;
  }
  set mute(t) {
    this._volume.mute = t;
  }
  dispose() {
    return super.dispose(), this.close(), this._volume.dispose(), this.volume.dispose(), this;
  }
  /**
   * If getUserMedia is supported by the browser.
   */
  static get supported() {
    return et(navigator.mediaDevices) && et(navigator.mediaDevices.getUserMedia);
  }
}
function Pn(n, t) {
  return yt(this, void 0, void 0, function* () {
    const e = t / n.context.sampleRate, s = new xi(1, e, n.context.sampleRate);
    return new n.constructor(Object.assign(n.get(), {
      // should do 2 iterations
      frequency: 2 / e,
      // zero out the detune
      detune: 0,
      context: s
    })).toDestination().start(0), (yield s.render()).getChannelData(0);
  });
}
class Sr extends ri {
  constructor() {
    const t = L(Sr.getDefaults(), arguments, ["frequency", "type"]);
    super(t), this.name = "ToneOscillatorNode", this._oscillator = this.context.createOscillator(), this._internalChannels = [this._oscillator], ue(this._oscillator, this._gainNode), this.type = t.type, this.frequency = new tt({
      context: this.context,
      param: this._oscillator.frequency,
      units: "frequency",
      value: t.frequency
    }), this.detune = new tt({
      context: this.context,
      param: this._oscillator.detune,
      units: "cents",
      value: t.detune
    }), Z(this, ["frequency", "detune"]);
  }
  static getDefaults() {
    return Object.assign(ri.getDefaults(), {
      detune: 0,
      frequency: 440,
      type: "sine"
    });
  }
  /**
   * Start the oscillator node at the given time
   * @param  time When to start the oscillator
   */
  start(t) {
    const e = this.toSeconds(t);
    return this.log("start", e), this._startGain(e), this._oscillator.start(e), this;
  }
  _stopSource(t) {
    this._oscillator.stop(t);
  }
  /**
   * Sets an arbitrary custom periodic waveform given a PeriodicWave.
   * @param  periodicWave PeriodicWave should be created with context.createPeriodicWave
   */
  setPeriodicWave(t) {
    return this._oscillator.setPeriodicWave(t), this;
  }
  /**
   * The oscillator type. Either 'sine', 'sawtooth', 'square', or 'triangle'
   */
  get type() {
    return this._oscillator.type;
  }
  set type(t) {
    this._oscillator.type = t;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this.state === "started" && this.stop(), this._oscillator.disconnect(), this.frequency.dispose(), this.detune.dispose(), this;
  }
}
class Tt extends Ft {
  constructor() {
    const t = L(Tt.getDefaults(), arguments, ["frequency", "type"]);
    super(t), this.name = "Oscillator", this._oscillator = null, this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.frequency
    }), Z(this, "frequency"), this.detune = new Q({
      context: this.context,
      units: "cents",
      value: t.detune
    }), Z(this, "detune"), this._partials = t.partials, this._partialCount = t.partialCount, this._type = t.type, t.partialCount && t.type !== "custom" && (this._type = this.baseType + t.partialCount.toString()), this.phase = t.phase;
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      detune: 0,
      frequency: 440,
      partialCount: 0,
      partials: [],
      phase: 0,
      type: "sine"
    });
  }
  /**
   * start the oscillator
   */
  _start(t) {
    const e = this.toSeconds(t), s = new Sr({
      context: this.context,
      onended: () => this.onstop(this)
    });
    this._oscillator = s, this._wave ? this._oscillator.setPeriodicWave(this._wave) : this._oscillator.type = this._type, this._oscillator.connect(this.output), this.frequency.connect(this._oscillator.frequency), this.detune.connect(this._oscillator.detune), this._oscillator.start(e);
  }
  /**
   * stop the oscillator
   */
  _stop(t) {
    const e = this.toSeconds(t);
    this._oscillator && this._oscillator.stop(e);
  }
  /**
   * Restart the oscillator. Does not stop the oscillator, but instead
   * just cancels any scheduled 'stop' from being invoked.
   */
  _restart(t) {
    const e = this.toSeconds(t);
    return this.log("restart", e), this._oscillator && this._oscillator.cancelStop(), this._state.cancel(e), this;
  }
  /**
   * Sync the signal to the Transport's bpm. Any changes to the transports bpm,
   * will also affect the oscillators frequency.
   * @example
   * const osc = new Tone.Oscillator().toDestination().start();
   * osc.frequency.value = 440;
   * // the ratio between the bpm and the frequency will be maintained
   * osc.syncFrequency();
   * // double the tempo
   * Tone.Transport.bpm.value *= 2;
   * // the frequency of the oscillator is doubled to 880
   */
  syncFrequency() {
    return this.context.transport.syncSignal(this.frequency), this;
  }
  /**
   * Unsync the oscillator's frequency from the Transport.
   * @see {@link syncFrequency}
   */
  unsyncFrequency() {
    return this.context.transport.unsyncSignal(this.frequency), this;
  }
  /**
   * Get a cached periodic wave. Avoids having to recompute
   * the oscillator values when they have already been computed
   * with the same values.
   */
  _getCachedPeriodicWave() {
    if (this._type === "custom")
      return Tt._periodicWaveCache.find((e) => e.phase === this._phase && Uk(e.partials, this._partials));
    {
      const t = Tt._periodicWaveCache.find((e) => e.type === this._type && e.phase === this._phase);
      return this._partialCount = t ? t.partialCount : this._partialCount, t;
    }
  }
  get type() {
    return this._type;
  }
  set type(t) {
    this._type = t;
    const e = ["sine", "square", "sawtooth", "triangle"].indexOf(t) !== -1;
    if (this._phase === 0 && e)
      this._wave = void 0, this._partialCount = 0, this._oscillator !== null && (this._oscillator.type = t);
    else {
      const s = this._getCachedPeriodicWave();
      if (et(s)) {
        const { partials: i, wave: r } = s;
        this._wave = r, this._partials = i, this._oscillator !== null && this._oscillator.setPeriodicWave(this._wave);
      } else {
        const [i, r] = this._getRealImaginary(t, this._phase), o = this.context.createPeriodicWave(i, r);
        this._wave = o, this._oscillator !== null && this._oscillator.setPeriodicWave(this._wave), Tt._periodicWaveCache.push({
          imag: r,
          partialCount: this._partialCount,
          partials: this._partials,
          phase: this._phase,
          real: i,
          type: this._type,
          wave: this._wave
        }), Tt._periodicWaveCache.length > 100 && Tt._periodicWaveCache.shift();
      }
    }
  }
  get baseType() {
    return this._type.replace(this.partialCount.toString(), "");
  }
  set baseType(t) {
    this.partialCount && this._type !== "custom" && t !== "custom" ? this.type = t + this.partialCount : this.type = t;
  }
  get partialCount() {
    return this._partialCount;
  }
  set partialCount(t) {
    zt(t, 0);
    let e = this._type;
    const s = /^(sine|triangle|square|sawtooth)(\d+)$/.exec(this._type);
    if (s && (e = s[1]), this._type !== "custom")
      t === 0 ? this.type = e : this.type = e + t.toString();
    else {
      const i = new Float32Array(t);
      this._partials.forEach((r, o) => i[o] = r), this._partials = Array.from(i), this.type = this._type;
    }
  }
  /**
   * Returns the real and imaginary components based
   * on the oscillator type.
   * @returns [real: Float32Array, imaginary: Float32Array]
   */
  _getRealImaginary(t, e) {
    let i = 2048;
    const r = new Float32Array(i), o = new Float32Array(i);
    let a = 1;
    if (t === "custom") {
      if (a = this._partials.length + 1, this._partialCount = this._partials.length, i = a, this._partials.length === 0)
        return [r, o];
    } else {
      const l = /^(sine|triangle|square|sawtooth)(\d+)$/.exec(t);
      l ? (a = parseInt(l[2], 10) + 1, this._partialCount = parseInt(l[2], 10), t = l[1], a = Math.max(a, 2), i = a) : this._partialCount = 0, this._partials = [];
    }
    for (let l = 1; l < i; ++l) {
      const c = 2 / (l * Math.PI);
      let h;
      switch (t) {
        case "sine":
          h = l <= a ? 1 : 0, this._partials[l - 1] = h;
          break;
        case "square":
          h = l & 1 ? 2 * c : 0, this._partials[l - 1] = h;
          break;
        case "sawtooth":
          h = c * (l & 1 ? 1 : -1), this._partials[l - 1] = h;
          break;
        case "triangle":
          l & 1 ? h = 2 * (c * c) * (l - 1 >> 1 & 1 ? -1 : 1) : h = 0, this._partials[l - 1] = h;
          break;
        case "custom":
          h = this._partials[l - 1];
          break;
        default:
          throw new TypeError("Oscillator: invalid type: " + t);
      }
      h !== 0 ? (r[l] = -h * Math.sin(e * l), o[l] = h * Math.cos(e * l)) : (r[l] = 0, o[l] = 0);
    }
    return [r, o];
  }
  /**
   * Compute the inverse FFT for a given phase.
   */
  _inverseFFT(t, e, s) {
    let i = 0;
    const r = t.length;
    for (let o = 0; o < r; o++)
      i += t[o] * Math.cos(o * s) + e[o] * Math.sin(o * s);
    return i;
  }
  /**
   * Returns the initial value of the oscillator when stopped.
   * E.g. a "sine" oscillator with phase = 90 would return an initial value of -1.
   */
  getInitialValue() {
    const [t, e] = this._getRealImaginary(this._type, 0);
    let s = 0;
    const i = Math.PI * 2, r = 32;
    for (let o = 0; o < r; o++)
      s = Math.max(this._inverseFFT(t, e, o / r * i), s);
    return En(-this._inverseFFT(t, e, this._phase) / s, -1, 1);
  }
  get partials() {
    return this._partials.slice(0, this.partialCount);
  }
  set partials(t) {
    this._partials = t, this._partialCount = this._partials.length, t.length && (this.type = "custom");
  }
  get phase() {
    return this._phase * (180 / Math.PI);
  }
  set phase(t) {
    this._phase = t * Math.PI / 180, this.type = this._type;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  dispose() {
    return super.dispose(), this._oscillator !== null && this._oscillator.dispose(), this._wave = void 0, this.frequency.dispose(), this.detune.dispose(), this;
  }
}
Tt._periodicWaveCache = [];
class ca extends Re {
  constructor() {
    super(...arguments), this.name = "AudioToGain", this._norm = new ss({
      context: this.context,
      mapping: (t) => (t + 1) / 2
    }), this.input = this._norm, this.output = this._norm;
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), this._norm.dispose(), this;
  }
}
class Mt extends Q {
  constructor() {
    const t = L(Mt.getDefaults(), arguments, ["value"]);
    super(t), this.name = "Multiply", this.override = !1, this._mult = this.input = this.output = new j({
      context: this.context,
      minValue: t.minValue,
      maxValue: t.maxValue
    }), this.factor = this._param = this._mult.gain, this.factor.setValueAtTime(t.value, 0);
  }
  static getDefaults() {
    return Object.assign(Q.getDefaults(), {
      value: 0
    });
  }
  dispose() {
    return super.dispose(), this._mult.dispose(), this;
  }
}
class Tr extends Ft {
  constructor() {
    const t = L(Tr.getDefaults(), arguments, ["frequency", "type", "modulationType"]);
    super(t), this.name = "AMOscillator", this._modulationScale = new ca({ context: this.context }), this._modulationNode = new j({
      context: this.context
    }), this._carrier = new Tt({
      context: this.context,
      detune: t.detune,
      frequency: t.frequency,
      onstop: () => this.onstop(this),
      phase: t.phase,
      type: t.type
    }), this.frequency = this._carrier.frequency, this.detune = this._carrier.detune, this._modulator = new Tt({
      context: this.context,
      phase: t.phase,
      type: t.modulationType
    }), this.harmonicity = new Mt({
      context: this.context,
      units: "positive",
      value: t.harmonicity
    }), this.frequency.chain(this.harmonicity, this._modulator.frequency), this._modulator.chain(this._modulationScale, this._modulationNode.gain), this._carrier.chain(this._modulationNode, this.output), Z(this, ["frequency", "detune", "harmonicity"]);
  }
  static getDefaults() {
    return Object.assign(Tt.getDefaults(), {
      harmonicity: 1,
      modulationType: "square"
    });
  }
  /**
   * start the oscillator
   */
  _start(t) {
    this._modulator.start(t), this._carrier.start(t);
  }
  /**
   * stop the oscillator
   */
  _stop(t) {
    this._modulator.stop(t), this._carrier.stop(t);
  }
  _restart(t) {
    this._modulator.restart(t), this._carrier.restart(t);
  }
  /**
   * The type of the carrier oscillator
   */
  get type() {
    return this._carrier.type;
  }
  set type(t) {
    this._carrier.type = t;
  }
  get baseType() {
    return this._carrier.baseType;
  }
  set baseType(t) {
    this._carrier.baseType = t;
  }
  get partialCount() {
    return this._carrier.partialCount;
  }
  set partialCount(t) {
    this._carrier.partialCount = t;
  }
  /**
   * The type of the modulator oscillator
   */
  get modulationType() {
    return this._modulator.type;
  }
  set modulationType(t) {
    this._modulator.type = t;
  }
  get phase() {
    return this._carrier.phase;
  }
  set phase(t) {
    this._carrier.phase = t, this._modulator.phase = t;
  }
  get partials() {
    return this._carrier.partials;
  }
  set partials(t) {
    this._carrier.partials = t;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this.frequency.dispose(), this.detune.dispose(), this.harmonicity.dispose(), this._carrier.dispose(), this._modulator.dispose(), this._modulationNode.dispose(), this._modulationScale.dispose(), this;
  }
}
class Si extends Ft {
  constructor() {
    const t = L(Si.getDefaults(), arguments, ["frequency", "type", "modulationType"]);
    super(t), this.name = "FMOscillator", this._modulationNode = new j({
      context: this.context,
      gain: 0
    }), this._carrier = new Tt({
      context: this.context,
      detune: t.detune,
      frequency: 0,
      onstop: () => this.onstop(this),
      phase: t.phase,
      type: t.type
    }), this.detune = this._carrier.detune, this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.frequency
    }), this._modulator = new Tt({
      context: this.context,
      phase: t.phase,
      type: t.modulationType
    }), this.harmonicity = new Mt({
      context: this.context,
      units: "positive",
      value: t.harmonicity
    }), this.modulationIndex = new Mt({
      context: this.context,
      units: "positive",
      value: t.modulationIndex
    }), this.frequency.connect(this._carrier.frequency), this.frequency.chain(this.harmonicity, this._modulator.frequency), this.frequency.chain(this.modulationIndex, this._modulationNode), this._modulator.connect(this._modulationNode.gain), this._modulationNode.connect(this._carrier.frequency), this._carrier.connect(this.output), this.detune.connect(this._modulator.detune), Z(this, [
      "modulationIndex",
      "frequency",
      "detune",
      "harmonicity"
    ]);
  }
  static getDefaults() {
    return Object.assign(Tt.getDefaults(), {
      harmonicity: 1,
      modulationIndex: 2,
      modulationType: "square"
    });
  }
  /**
   * start the oscillator
   */
  _start(t) {
    this._modulator.start(t), this._carrier.start(t);
  }
  /**
   * stop the oscillator
   */
  _stop(t) {
    this._modulator.stop(t), this._carrier.stop(t);
  }
  _restart(t) {
    return this._modulator.restart(t), this._carrier.restart(t), this;
  }
  get type() {
    return this._carrier.type;
  }
  set type(t) {
    this._carrier.type = t;
  }
  get baseType() {
    return this._carrier.baseType;
  }
  set baseType(t) {
    this._carrier.baseType = t;
  }
  get partialCount() {
    return this._carrier.partialCount;
  }
  set partialCount(t) {
    this._carrier.partialCount = t;
  }
  /**
   * The type of the modulator oscillator
   */
  get modulationType() {
    return this._modulator.type;
  }
  set modulationType(t) {
    this._modulator.type = t;
  }
  get phase() {
    return this._carrier.phase;
  }
  set phase(t) {
    this._carrier.phase = t, this._modulator.phase = t;
  }
  get partials() {
    return this._carrier.partials;
  }
  set partials(t) {
    this._carrier.partials = t;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this.frequency.dispose(), this.harmonicity.dispose(), this._carrier.dispose(), this._modulator.dispose(), this._modulationNode.dispose(), this.modulationIndex.dispose(), this;
  }
}
class Ti extends Ft {
  constructor() {
    const t = L(Ti.getDefaults(), arguments, ["frequency", "width"]);
    super(t), this.name = "PulseOscillator", this._widthGate = new j({
      context: this.context,
      gain: 0
    }), this._thresh = new ss({
      context: this.context,
      mapping: (e) => e <= 0 ? -1 : 1
    }), this.width = new Q({
      context: this.context,
      units: "audioRange",
      value: t.width
    }), this._triangle = new Tt({
      context: this.context,
      detune: t.detune,
      frequency: t.frequency,
      onstop: () => this.onstop(this),
      phase: t.phase,
      type: "triangle"
    }), this.frequency = this._triangle.frequency, this.detune = this._triangle.detune, this._triangle.chain(this._thresh, this.output), this.width.chain(this._widthGate, this._thresh), Z(this, ["width", "frequency", "detune"]);
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      detune: 0,
      frequency: 440,
      phase: 0,
      type: "pulse",
      width: 0.2
    });
  }
  /**
   * start the oscillator
   */
  _start(t) {
    t = this.toSeconds(t), this._triangle.start(t), this._widthGate.gain.setValueAtTime(1, t);
  }
  /**
   * stop the oscillator
   */
  _stop(t) {
    t = this.toSeconds(t), this._triangle.stop(t), this._widthGate.gain.cancelScheduledValues(t), this._widthGate.gain.setValueAtTime(0, t);
  }
  _restart(t) {
    this._triangle.restart(t), this._widthGate.gain.cancelScheduledValues(t), this._widthGate.gain.setValueAtTime(1, t);
  }
  /**
   * The phase of the oscillator in degrees.
   */
  get phase() {
    return this._triangle.phase;
  }
  set phase(t) {
    this._triangle.phase = t;
  }
  /**
   * The type of the oscillator. Always returns "pulse".
   */
  get type() {
    return "pulse";
  }
  /**
   * The baseType of the oscillator. Always returns "pulse".
   */
  get baseType() {
    return "pulse";
  }
  /**
   * The partials of the waveform. Cannot set partials for this waveform type
   */
  get partials() {
    return [];
  }
  /**
   * No partials for this waveform type.
   */
  get partialCount() {
    return 0;
  }
  /**
   * *Internal use* The carrier oscillator type is fed through the
   * waveshaper node to create the pulse. Using different carrier oscillators
   * changes oscillator's behavior.
   */
  set carrierType(t) {
    this._triangle.type = t;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  /**
   * Clean up method.
   */
  dispose() {
    return super.dispose(), this._triangle.dispose(), this.width.dispose(), this._widthGate.dispose(), this._thresh.dispose(), this;
  }
}
class Mr extends Ft {
  constructor() {
    const t = L(Mr.getDefaults(), arguments, ["frequency", "type", "spread"]);
    super(t), this.name = "FatOscillator", this._oscillators = [], this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.frequency
    }), this.detune = new Q({
      context: this.context,
      units: "cents",
      value: t.detune
    }), this._spread = t.spread, this._type = t.type, this._phase = t.phase, this._partials = t.partials, this._partialCount = t.partialCount, this.count = t.count, Z(this, ["frequency", "detune"]);
  }
  static getDefaults() {
    return Object.assign(Tt.getDefaults(), {
      count: 3,
      spread: 20,
      type: "sawtooth"
    });
  }
  /**
   * start the oscillator
   */
  _start(t) {
    t = this.toSeconds(t), this._forEach((e) => e.start(t));
  }
  /**
   * stop the oscillator
   */
  _stop(t) {
    t = this.toSeconds(t), this._forEach((e) => e.stop(t));
  }
  _restart(t) {
    this._forEach((e) => e.restart(t));
  }
  /**
   * Iterate over all of the oscillators
   */
  _forEach(t) {
    for (let e = 0; e < this._oscillators.length; e++)
      t(this._oscillators[e], e);
  }
  /**
   * The type of the oscillator
   */
  get type() {
    return this._type;
  }
  set type(t) {
    this._type = t, this._forEach((e) => e.type = t);
  }
  /**
   * The detune spread between the oscillators. If "count" is
   * set to 3 oscillators and the "spread" is set to 40,
   * the three oscillators would be detuned like this: [-20, 0, 20]
   * for a total detune spread of 40 cents.
   * @example
   * const fatOsc = new Tone.FatOscillator().toDestination().start();
   * fatOsc.spread = 70;
   */
  get spread() {
    return this._spread;
  }
  set spread(t) {
    if (this._spread = t, this._oscillators.length > 1) {
      const e = -t / 2, s = t / (this._oscillators.length - 1);
      this._forEach((i, r) => i.detune.value = e + s * r);
    }
  }
  /**
   * The number of detuned oscillators. Must be an integer greater than 1.
   * @example
   * const fatOsc = new Tone.FatOscillator("C#3", "sawtooth").toDestination().start();
   * // use 4 sawtooth oscillators
   * fatOsc.count = 4;
   */
  get count() {
    return this._oscillators.length;
  }
  set count(t) {
    if (zt(t, 1), this._oscillators.length !== t) {
      this._forEach((e) => e.dispose()), this._oscillators = [];
      for (let e = 0; e < t; e++) {
        const s = new Tt({
          context: this.context,
          volume: -6 - t * 1.1,
          type: this._type,
          phase: this._phase + e / t * 360,
          partialCount: this._partialCount,
          onstop: e === 0 ? () => this.onstop(this) : st
        });
        this.type === "custom" && (s.partials = this._partials), this.frequency.connect(s.frequency), this.detune.connect(s.detune), s.detune.overridden = !1, s.connect(this.output), this._oscillators[e] = s;
      }
      this.spread = this._spread, this.state === "started" && this._forEach((e) => e.start());
    }
  }
  get phase() {
    return this._phase;
  }
  set phase(t) {
    this._phase = t, this._forEach((e, s) => e.phase = this._phase + s / this.count * 360);
  }
  get baseType() {
    return this._oscillators[0].baseType;
  }
  set baseType(t) {
    this._forEach((e) => e.baseType = t), this._type = this._oscillators[0].type;
  }
  get partials() {
    return this._oscillators[0].partials;
  }
  set partials(t) {
    this._partials = t, this._partialCount = this._partials.length, t.length && (this._type = "custom", this._forEach((e) => e.partials = t));
  }
  get partialCount() {
    return this._oscillators[0].partialCount;
  }
  set partialCount(t) {
    this._partialCount = t, this._forEach((e) => e.partialCount = t), this._type = this._oscillators[0].type;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this.frequency.dispose(), this.detune.dispose(), this._forEach((t) => t.dispose()), this;
  }
}
class kr extends Ft {
  constructor() {
    const t = L(kr.getDefaults(), arguments, ["frequency", "modulationFrequency"]);
    super(t), this.name = "PWMOscillator", this.sourceType = "pwm", this._scale = new Mt({
      context: this.context,
      value: 2
    }), this._pulse = new Ti({
      context: this.context,
      frequency: t.modulationFrequency
    }), this._pulse.carrierType = "sine", this.modulationFrequency = this._pulse.frequency, this._modulator = new Tt({
      context: this.context,
      detune: t.detune,
      frequency: t.frequency,
      onstop: () => this.onstop(this),
      phase: t.phase
    }), this.frequency = this._modulator.frequency, this.detune = this._modulator.detune, this._modulator.chain(this._scale, this._pulse.width), this._pulse.connect(this.output), Z(this, ["modulationFrequency", "frequency", "detune"]);
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      detune: 0,
      frequency: 440,
      modulationFrequency: 0.4,
      phase: 0,
      type: "pwm"
    });
  }
  /**
   * start the oscillator
   */
  _start(t) {
    t = this.toSeconds(t), this._modulator.start(t), this._pulse.start(t);
  }
  /**
   * stop the oscillator
   */
  _stop(t) {
    t = this.toSeconds(t), this._modulator.stop(t), this._pulse.stop(t);
  }
  /**
   * restart the oscillator
   */
  _restart(t) {
    this._modulator.restart(t), this._pulse.restart(t);
  }
  /**
   * The type of the oscillator. Always returns "pwm".
   */
  get type() {
    return "pwm";
  }
  /**
   * The baseType of the oscillator. Always returns "pwm".
   */
  get baseType() {
    return "pwm";
  }
  /**
   * The partials of the waveform. Cannot set partials for this waveform type
   */
  get partials() {
    return [];
  }
  /**
   * No partials for this waveform type.
   */
  get partialCount() {
    return 0;
  }
  /**
   * The phase of the oscillator in degrees.
   */
  get phase() {
    return this._modulator.phase;
  }
  set phase(t) {
    this._modulator.phase = t;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._pulse.dispose(), this._scale.dispose(), this._modulator.dispose(), this;
  }
}
const of = {
  am: Tr,
  fat: Mr,
  fm: Si,
  oscillator: Tt,
  pulse: Ti,
  pwm: kr
};
class Fs extends Ft {
  constructor() {
    const t = L(Fs.getDefaults(), arguments, ["frequency", "type"]);
    super(t), this.name = "OmniOscillator", this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.frequency
    }), this.detune = new Q({
      context: this.context,
      units: "cents",
      value: t.detune
    }), Z(this, ["frequency", "detune"]), this.set(t);
  }
  static getDefaults() {
    return Object.assign(Tt.getDefaults(), Si.getDefaults(), Tr.getDefaults(), Mr.getDefaults(), Ti.getDefaults(), kr.getDefaults());
  }
  /**
   * start the oscillator
   */
  _start(t) {
    this._oscillator.start(t);
  }
  /**
   * start the oscillator
   */
  _stop(t) {
    this._oscillator.stop(t);
  }
  _restart(t) {
    return this._oscillator.restart(t), this;
  }
  /**
   * The type of the oscillator. Can be any of the basic types: sine, square, triangle, sawtooth. Or
   * prefix the basic types with "fm", "am", or "fat" to use the FMOscillator, AMOscillator or FatOscillator
   * types. The oscillator could also be set to "pwm" or "pulse". All of the parameters of the
   * oscillator's class are accessible when the oscillator is set to that type, but throws an error
   * when it's not.
   * @example
   * const omniOsc = new Tone.OmniOscillator().toDestination().start();
   * omniOsc.type = "pwm";
   * // modulationFrequency is parameter which is available
   * // only when the type is "pwm".
   * omniOsc.modulationFrequency.value = 0.5;
   */
  get type() {
    let t = "";
    return ["am", "fm", "fat"].some((e) => this._sourceType === e) && (t = this._sourceType), t + this._oscillator.type;
  }
  set type(t) {
    t.substr(0, 2) === "fm" ? (this._createNewOscillator("fm"), this._oscillator = this._oscillator, this._oscillator.type = t.substr(2)) : t.substr(0, 2) === "am" ? (this._createNewOscillator("am"), this._oscillator = this._oscillator, this._oscillator.type = t.substr(2)) : t.substr(0, 3) === "fat" ? (this._createNewOscillator("fat"), this._oscillator = this._oscillator, this._oscillator.type = t.substr(3)) : t === "pwm" ? (this._createNewOscillator("pwm"), this._oscillator = this._oscillator) : t === "pulse" ? this._createNewOscillator("pulse") : (this._createNewOscillator("oscillator"), this._oscillator = this._oscillator, this._oscillator.type = t);
  }
  /**
   * The value is an empty array when the type is not "custom".
   * This is not available on "pwm" and "pulse" oscillator types.
   * @see {@link Oscillator.partials}
   */
  get partials() {
    return this._oscillator.partials;
  }
  set partials(t) {
    !this._getOscType(this._oscillator, "pulse") && !this._getOscType(this._oscillator, "pwm") && (this._oscillator.partials = t);
  }
  get partialCount() {
    return this._oscillator.partialCount;
  }
  set partialCount(t) {
    !this._getOscType(this._oscillator, "pulse") && !this._getOscType(this._oscillator, "pwm") && (this._oscillator.partialCount = t);
  }
  set(t) {
    return Reflect.has(t, "type") && t.type && (this.type = t.type), super.set(t), this;
  }
  /**
   * connect the oscillator to the frequency and detune signals
   */
  _createNewOscillator(t) {
    if (t !== this._sourceType) {
      this._sourceType = t;
      const e = of[t], s = this.now();
      if (this._oscillator) {
        const i = this._oscillator;
        i.stop(s), this.context.setTimeout(() => i.dispose(), this.blockTime);
      }
      this._oscillator = new e({
        context: this.context
      }), this.frequency.connect(this._oscillator.frequency), this.detune.connect(this._oscillator.detune), this._oscillator.connect(this.output), this._oscillator.onstop = () => this.onstop(this), this.state === "started" && this._oscillator.start(s);
    }
  }
  get phase() {
    return this._oscillator.phase;
  }
  set phase(t) {
    this._oscillator.phase = t;
  }
  /**
   * The source type of the oscillator.
   * @example
   * const omniOsc = new Tone.OmniOscillator(440, "fmsquare");
   * console.log(omniOsc.sourceType); // 'fm'
   */
  get sourceType() {
    return this._sourceType;
  }
  set sourceType(t) {
    let e = "sine";
    this._oscillator.type !== "pwm" && this._oscillator.type !== "pulse" && (e = this._oscillator.type), t === "fm" ? this.type = "fm" + e : t === "am" ? this.type = "am" + e : t === "fat" ? this.type = "fat" + e : t === "oscillator" ? this.type = e : t === "pulse" ? this.type = "pulse" : t === "pwm" && (this.type = "pwm");
  }
  _getOscType(t, e) {
    return t instanceof of[e];
  }
  /**
   * The base type of the oscillator.
   * @see {@link Oscillator.baseType}
   * @example
   * const omniOsc = new Tone.OmniOscillator(440, "fmsquare4");
   * console.log(omniOsc.sourceType, omniOsc.baseType, omniOsc.partialCount);
   */
  get baseType() {
    return this._oscillator.baseType;
  }
  set baseType(t) {
    !this._getOscType(this._oscillator, "pulse") && !this._getOscType(this._oscillator, "pwm") && t !== "pulse" && t !== "pwm" && (this._oscillator.baseType = t);
  }
  /**
   * The width of the oscillator when sourceType === "pulse".
   * @see {@link PWMOscillator}
   */
  get width() {
    if (this._getOscType(this._oscillator, "pulse"))
      return this._oscillator.width;
  }
  /**
   * The number of detuned oscillators when sourceType === "fat".
   * @see {@link FatOscillator.count}
   */
  get count() {
    if (this._getOscType(this._oscillator, "fat"))
      return this._oscillator.count;
  }
  set count(t) {
    this._getOscType(this._oscillator, "fat") && Ie(t) && (this._oscillator.count = t);
  }
  /**
   * The detune spread between the oscillators when sourceType === "fat".
   * @see {@link FatOscillator.count}
   */
  get spread() {
    if (this._getOscType(this._oscillator, "fat"))
      return this._oscillator.spread;
  }
  set spread(t) {
    this._getOscType(this._oscillator, "fat") && Ie(t) && (this._oscillator.spread = t);
  }
  /**
   * The type of the modulator oscillator. Only if the oscillator is set to "am" or "fm" types.
   * @see {@link AMOscillator} or {@link FMOscillator}
   */
  get modulationType() {
    if (this._getOscType(this._oscillator, "fm") || this._getOscType(this._oscillator, "am"))
      return this._oscillator.modulationType;
  }
  set modulationType(t) {
    (this._getOscType(this._oscillator, "fm") || this._getOscType(this._oscillator, "am")) && Qe(t) && (this._oscillator.modulationType = t);
  }
  /**
   * The modulation index when the sourceType === "fm"
   * @see {@link FMOscillator}.
   */
  get modulationIndex() {
    if (this._getOscType(this._oscillator, "fm"))
      return this._oscillator.modulationIndex;
  }
  /**
   * Harmonicity is the frequency ratio between the carrier and the modulator oscillators.
   * @see {@link AMOscillator} or {@link FMOscillator}
   */
  get harmonicity() {
    if (this._getOscType(this._oscillator, "fm") || this._getOscType(this._oscillator, "am"))
      return this._oscillator.harmonicity;
  }
  /**
   * The modulationFrequency Signal of the oscillator when sourceType === "pwm"
   * see {@link PWMOscillator}
   * @min 0.1
   * @max 5
   */
  get modulationFrequency() {
    if (this._getOscType(this._oscillator, "pwm"))
      return this._oscillator.modulationFrequency;
  }
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      return Pn(this, t);
    });
  }
  dispose() {
    return super.dispose(), this.detune.dispose(), this.frequency.dispose(), this._oscillator.dispose(), this;
  }
}
class In extends Q {
  constructor() {
    super(L(In.getDefaults(), arguments, ["value"])), this.override = !1, this.name = "Add", this._sum = new j({ context: this.context }), this.input = this._sum, this.output = this._sum, this.addend = this._param, Fe(this._constantSource, this._sum);
  }
  static getDefaults() {
    return Object.assign(Q.getDefaults(), {
      value: 0
    });
  }
  dispose() {
    return super.dispose(), this._sum.dispose(), this;
  }
}
class Rs extends Re {
  constructor() {
    const t = L(Rs.getDefaults(), arguments, [
      "min",
      "max"
    ]);
    super(t), this.name = "Scale", this._mult = this.input = new Mt({
      context: this.context,
      value: t.max - t.min
    }), this._add = this.output = new In({
      context: this.context,
      value: t.min
    }), this._min = t.min, this._max = t.max, this.input.connect(this.output);
  }
  static getDefaults() {
    return Object.assign(Re.getDefaults(), {
      max: 1,
      min: 0
    });
  }
  /**
   * The minimum output value. This number is output when the value input value is 0.
   */
  get min() {
    return this._min;
  }
  set min(t) {
    this._min = t, this._setRange();
  }
  /**
   * The maximum output value. This number is output when the value input value is 1.
   */
  get max() {
    return this._max;
  }
  set max(t) {
    this._max = t, this._setRange();
  }
  /**
   * set the values
   */
  _setRange() {
    this._add.value = this._min, this._mult.value = this._max - this._min;
  }
  dispose() {
    return super.dispose(), this._add.dispose(), this._mult.dispose(), this;
  }
}
class ha extends Re {
  constructor() {
    super(L(ha.getDefaults(), arguments)), this.name = "Zero", this._gain = new j({ context: this.context }), this.output = this._gain, this.input = void 0, ue(this.context.getConstant(0), this._gain);
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), Vc(this.context.getConstant(0), this._gain), this;
  }
}
class he extends B {
  constructor() {
    const t = L(he.getDefaults(), arguments, [
      "frequency",
      "min",
      "max"
    ]);
    super(t), this.name = "LFO", this._stoppedValue = 0, this._units = "number", this.convert = !0, this._fromType = tt.prototype._fromType, this._toType = tt.prototype._toType, this._is = tt.prototype._is, this._clampValue = tt.prototype._clampValue, this._oscillator = new Tt(t), this.frequency = this._oscillator.frequency, this._amplitudeGain = new j({
      context: this.context,
      gain: t.amplitude,
      units: "normalRange"
    }), this.amplitude = this._amplitudeGain.gain, this._stoppedSignal = new Q({
      context: this.context,
      units: "audioRange",
      value: 0
    }), this._zeros = new ha({ context: this.context }), this._a2g = new ca({ context: this.context }), this._scaler = this.output = new Rs({
      context: this.context,
      max: t.max,
      min: t.min
    }), this.units = t.units, this.min = t.min, this.max = t.max, this._oscillator.chain(this._amplitudeGain, this._a2g, this._scaler), this._zeros.connect(this._a2g), this._stoppedSignal.connect(this._a2g), Z(this, ["amplitude", "frequency"]), this.phase = t.phase;
  }
  static getDefaults() {
    return Object.assign(Tt.getDefaults(), {
      amplitude: 1,
      frequency: "4n",
      max: 1,
      min: 0,
      type: "sine",
      units: "number"
    });
  }
  /**
   * Start the LFO.
   * @param time The time the LFO will start
   */
  start(t) {
    return t = this.toSeconds(t), this._stoppedSignal.setValueAtTime(0, t), this._oscillator.start(t), this;
  }
  /**
   * Stop the LFO.
   * @param  time The time the LFO will stop
   */
  stop(t) {
    return t = this.toSeconds(t), this._stoppedSignal.setValueAtTime(this._stoppedValue, t), this._oscillator.stop(t), this;
  }
  /**
   * Sync the start/stop/pause to the transport
   * and the frequency to the bpm of the transport
   * @example
   * const lfo = new Tone.LFO("8n");
   * lfo.sync().start(0);
   * // the rate of the LFO will always be an eighth note, even as the tempo changes
   */
  sync() {
    return this._oscillator.sync(), this._oscillator.syncFrequency(), this;
  }
  /**
   * unsync the LFO from transport control
   */
  unsync() {
    return this._oscillator.unsync(), this._oscillator.unsyncFrequency(), this;
  }
  /**
   * After the oscillator waveform is updated, reset the `_stoppedSignal` value to match the updated waveform
   */
  _setStoppedValue() {
    this._stoppedValue = this._oscillator.getInitialValue(), this._stoppedSignal.value = this._stoppedValue;
  }
  /**
   * The minimum output of the LFO.
   */
  get min() {
    return this._toType(this._scaler.min);
  }
  set min(t) {
    t = this._fromType(t), this._scaler.min = t;
  }
  /**
   * The maximum output of the LFO.
   */
  get max() {
    return this._toType(this._scaler.max);
  }
  set max(t) {
    t = this._fromType(t), this._scaler.max = t;
  }
  /**
   * The type of the oscillator.
   * @see {@link Oscillator.type}
   */
  get type() {
    return this._oscillator.type;
  }
  set type(t) {
    this._oscillator.type = t, this._setStoppedValue();
  }
  /**
   * The oscillator's partials array.
   * @see {@link Oscillator.partials}
   */
  get partials() {
    return this._oscillator.partials;
  }
  set partials(t) {
    this._oscillator.partials = t, this._setStoppedValue();
  }
  /**
   * The phase of the LFO.
   */
  get phase() {
    return this._oscillator.phase;
  }
  set phase(t) {
    this._oscillator.phase = t, this._setStoppedValue();
  }
  /**
   * The output units of the LFO.
   */
  get units() {
    return this._units;
  }
  set units(t) {
    const e = this.min, s = this.max;
    this._units = t, this.min = e, this.max = s;
  }
  /**
   * Returns the playback state of the source, either "started" or "stopped".
   */
  get state() {
    return this._oscillator.state;
  }
  /**
   * @param node the destination to connect to
   * @param outputNum the optional output number
   * @param inputNum the input number
   */
  connect(t, e, s) {
    return (t instanceof tt || t instanceof Q) && (this.convert = t.convert, this.units = t.units), wr(this, t, e, s), this;
  }
  dispose() {
    return super.dispose(), this._oscillator.dispose(), this._stoppedSignal.dispose(), this._zeros.dispose(), this._scaler.dispose(), this._a2g.dispose(), this._amplitudeGain.dispose(), this.amplitude.dispose(), this;
  }
}
function wg(n, t = 1 / 0) {
  const e = /* @__PURE__ */ new WeakMap();
  return function(s, i) {
    Reflect.defineProperty(s, i, {
      configurable: !0,
      enumerable: !0,
      get: function() {
        return e.get(this);
      },
      set: function(r) {
        zt(r, n, t), e.set(this, r);
      }
    });
  };
}
function Ns(n, t = 1 / 0) {
  const e = /* @__PURE__ */ new WeakMap();
  return function(s, i) {
    Reflect.defineProperty(s, i, {
      configurable: !0,
      enumerable: !0,
      get: function() {
        return e.get(this);
      },
      set: function(r) {
        zt(this.toSeconds(r), n, t), e.set(this, r);
      }
    });
  };
}
class Fn extends Ft {
  constructor() {
    const t = L(Fn.getDefaults(), arguments, [
      "url",
      "onload"
    ]);
    super(t), this.name = "Player", this._activeSources = /* @__PURE__ */ new Set(), this._buffer = new ot({
      onload: this._onload.bind(this, t.onload),
      onerror: t.onerror,
      reverse: t.reverse,
      url: t.url
    }), this.autostart = t.autostart, this._loop = t.loop, this._loopStart = t.loopStart, this._loopEnd = t.loopEnd, this._playbackRate = t.playbackRate, this.fadeIn = t.fadeIn, this.fadeOut = t.fadeOut;
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      autostart: !1,
      fadeIn: 0,
      fadeOut: 0,
      loop: !1,
      loopEnd: 0,
      loopStart: 0,
      onload: st,
      onerror: st,
      playbackRate: 1,
      reverse: !1
    });
  }
  /**
   * Load the audio file as an audio buffer.
   * Decodes the audio asynchronously and invokes
   * the callback once the audio buffer loads.
   * Note: this does not need to be called if a url
   * was passed in to the constructor. Only use this
   * if you want to manually load a new url.
   * @param url The url of the buffer to load. Filetype support depends on the browser.
   */
  load(t) {
    return yt(this, void 0, void 0, function* () {
      return yield this._buffer.load(t), this._onload(), this;
    });
  }
  /**
   * Internal callback when the buffer is loaded.
   */
  _onload(t = st) {
    t(), this.autostart && this.start();
  }
  /**
   * Internal callback when the buffer is done playing.
   */
  _onSourceEnd(t) {
    this.onstop(this), this._activeSources.delete(t), this._activeSources.size === 0 && !this._synced && this._state.getValueAtTime(this.now()) === "started" && (this._state.cancel(this.now()), this._state.setStateAtTime("stopped", this.now()));
  }
  /**
   * Play the buffer at the given startTime. Optionally add an offset
   * and/or duration which will play the buffer from a position
   * within the buffer for the given duration.
   *
   * @param  time When the player should start.
   * @param  offset The offset from the beginning of the sample to start at.
   * @param  duration How long the sample should play. If no duration is given, it will default to the full length of the sample (minus any offset)
   */
  start(t, e, s) {
    return super.start(t, e, s), this;
  }
  /**
   * Internal start method
   */
  _start(t, e, s) {
    this._loop ? e = Ve(e, this._loopStart) : e = Ve(e, 0);
    const i = this.toSeconds(e), r = s;
    s = Ve(s, Math.max(this._buffer.duration - i, 0));
    let o = this.toSeconds(s);
    o = o / this._playbackRate, t = this.toSeconds(t);
    const a = new tn({
      url: this._buffer,
      context: this.context,
      fadeIn: this.fadeIn,
      fadeOut: this.fadeOut,
      loop: this._loop,
      loopEnd: this._loopEnd,
      loopStart: this._loopStart,
      onended: this._onSourceEnd.bind(this),
      playbackRate: this._playbackRate
    }).connect(this.output);
    !this._loop && !this._synced && (this._state.cancel(t + o), this._state.setStateAtTime("stopped", t + o, {
      implicitEnd: !0
    })), this._activeSources.add(a), this._loop && ve(r) ? a.start(t, i) : a.start(t, i, o - this.toSeconds(this.fadeOut));
  }
  /**
   * Stop playback.
   */
  _stop(t) {
    const e = this.toSeconds(t);
    this._activeSources.forEach((s) => s.stop(e));
  }
  /**
   * Stop and then restart the player from the beginning (or offset)
   * @param  time When the player should start.
   * @param  offset The offset from the beginning of the sample to start at.
   * @param  duration How long the sample should play. If no duration is given,
   * 					it will default to the full length of the sample (minus any offset)
   */
  restart(t, e, s) {
    return super.restart(t, e, s), this;
  }
  _restart(t, e, s) {
    var i;
    (i = [...this._activeSources].pop()) === null || i === void 0 || i.stop(t), this._start(t, e, s);
  }
  /**
   * Seek to a specific time in the player's buffer. If the
   * source is no longer playing at that time, it will stop.
   * @param offset The time to seek to.
   * @param when The time for the seek event to occur.
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/berklee/gurgling_theremin_1.mp3", () => {
   * 	player.start();
   * 	// seek to the offset in 1 second from now
   * 	player.seek(0.4, "+1");
   * }).toDestination();
   */
  seek(t, e) {
    const s = this.toSeconds(e);
    if (this._state.getValueAtTime(s) === "started") {
      const i = this.toSeconds(t);
      this._stop(s), this._start(s, i);
    }
    return this;
  }
  /**
   * Set the loop start and end. Will only loop if loop is set to true.
   * @param loopStart The loop start time
   * @param loopEnd The loop end time
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/berklee/malevoices_aa2_F3.mp3").toDestination();
   * // loop between the given points
   * player.setLoopPoints(0.2, 0.3);
   * player.loop = true;
   * player.autostart = true;
   */
  setLoopPoints(t, e) {
    return this.loopStart = t, this.loopEnd = e, this;
  }
  /**
   * If loop is true, the loop will start at this position.
   */
  get loopStart() {
    return this._loopStart;
  }
  set loopStart(t) {
    this._loopStart = t, this.buffer.loaded && zt(this.toSeconds(t), 0, this.buffer.duration), this._activeSources.forEach((e) => {
      e.loopStart = t;
    });
  }
  /**
   * If loop is true, the loop will end at this position.
   */
  get loopEnd() {
    return this._loopEnd;
  }
  set loopEnd(t) {
    this._loopEnd = t, this.buffer.loaded && zt(this.toSeconds(t), 0, this.buffer.duration), this._activeSources.forEach((e) => {
      e.loopEnd = t;
    });
  }
  /**
   * The audio buffer belonging to the player.
   */
  get buffer() {
    return this._buffer;
  }
  set buffer(t) {
    this._buffer.set(t);
  }
  /**
   * If the buffer should loop once it's over.
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/drum-samples/breakbeat.mp3").toDestination();
   * player.loop = true;
   * player.autostart = true;
   */
  get loop() {
    return this._loop;
  }
  set loop(t) {
    if (this._loop !== t && (this._loop = t, this._activeSources.forEach((e) => {
      e.loop = t;
    }), t)) {
      const e = this._state.getNextState("stopped", this.now());
      e && this._state.cancel(e.time);
    }
  }
  /**
   * Normal speed is 1. The pitch will change with the playback rate.
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/berklee/femalevoices_aa2_A5.mp3").toDestination();
   * // play at 1/4 speed
   * player.playbackRate = 0.25;
   * // play as soon as the buffer is loaded
   * player.autostart = true;
   */
  get playbackRate() {
    return this._playbackRate;
  }
  set playbackRate(t) {
    this._playbackRate = t;
    const e = this.now(), s = this._state.getNextState("stopped", e);
    s && s.implicitEnd && (this._state.cancel(s.time), this._activeSources.forEach((i) => i.cancelStop())), this._activeSources.forEach((i) => {
      i.playbackRate.setValueAtTime(t, e);
    });
  }
  /**
   * If the buffer should be reversed. Note that this sets the underlying {@link ToneAudioBuffer.reverse}, so
   * if multiple players are pointing at the same ToneAudioBuffer, they will all be reversed.
   * @example
   * const player = new Tone.Player("https://tonejs.github.io/audio/berklee/chime_1.mp3").toDestination();
   * player.autostart = true;
   * player.reverse = true;
   */
  get reverse() {
    return this._buffer.reverse;
  }
  set reverse(t) {
    this._buffer.reverse = t;
  }
  /**
   * If the buffer is loaded
   */
  get loaded() {
    return this._buffer.loaded;
  }
  dispose() {
    return super.dispose(), this._activeSources.forEach((t) => t.dispose()), this._activeSources.clear(), this._buffer.dispose(), this;
  }
}
es([
  Ns(0)
], Fn.prototype, "fadeIn", void 0);
es([
  Ns(0)
], Fn.prototype, "fadeOut", void 0);
class Wc extends B {
  constructor() {
    const t = L(Wc.getDefaults(), arguments, ["urls", "onload"], "urls");
    super(t), this.name = "Players", this.input = void 0, this._players = /* @__PURE__ */ new Map(), this._volume = this.output = new Os({
      context: this.context,
      volume: t.volume
    }), this.volume = this._volume.volume, Z(this, "volume"), this._buffers = new bi({
      urls: t.urls,
      onload: t.onload,
      baseUrl: t.baseUrl,
      onerror: t.onerror
    }), this.mute = t.mute, this._fadeIn = t.fadeIn, this._fadeOut = t.fadeOut;
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      baseUrl: "",
      fadeIn: 0,
      fadeOut: 0,
      mute: !1,
      onload: st,
      onerror: st,
      urls: {},
      volume: 0
    });
  }
  /**
   * Mute the output.
   */
  get mute() {
    return this._volume.mute;
  }
  set mute(t) {
    this._volume.mute = t;
  }
  /**
   * The fadeIn time of the envelope applied to the source.
   */
  get fadeIn() {
    return this._fadeIn;
  }
  set fadeIn(t) {
    this._fadeIn = t, this._players.forEach((e) => {
      e.fadeIn = t;
    });
  }
  /**
   * The fadeOut time of the each of the sources.
   */
  get fadeOut() {
    return this._fadeOut;
  }
  set fadeOut(t) {
    this._fadeOut = t, this._players.forEach((e) => {
      e.fadeOut = t;
    });
  }
  /**
   * The state of the players object. Returns "started" if any of the players are playing.
   */
  get state() {
    return Array.from(this._players).some(([e, s]) => s.state === "started") ? "started" : "stopped";
  }
  /**
   * True if the buffers object has a buffer by that name.
   * @param name  The key or index of the buffer.
   */
  has(t) {
    return this._buffers.has(t);
  }
  /**
   * Get a player by name.
   * @param  name  The players name as defined in the constructor object or `add` method.
   */
  player(t) {
    if (X(this.has(t), `No Player with the name ${t} exists on this object`), !this._players.has(t)) {
      const e = new Fn({
        context: this.context,
        fadeIn: this._fadeIn,
        fadeOut: this._fadeOut,
        url: this._buffers.get(t)
      }).connect(this.output);
      this._players.set(t, e);
    }
    return this._players.get(t);
  }
  /**
   * If all the buffers are loaded or not
   */
  get loaded() {
    return this._buffers.loaded;
  }
  /**
   * Add a player by name and url to the Players
   * @param  name A unique name to give the player
   * @param  url  Either the url of the bufer or a buffer which will be added with the given name.
   * @param callback  The callback to invoke when the url is loaded.
   * @example
   * const players = new Tone.Players();
   * players.add("gong", "https://tonejs.github.io/audio/berklee/gong_1.mp3", () => {
   * 	console.log("gong loaded");
   * 	players.player("gong").start();
   * });
   */
  add(t, e, s) {
    return X(!this._buffers.has(t), "A buffer with that name already exists on this object"), this._buffers.add(t, e, s), this;
  }
  /**
   * Stop all of the players at the given time
   * @param time The time to stop all of the players.
   */
  stopAll(t) {
    return this._players.forEach((e) => e.stop(t)), this;
  }
  dispose() {
    return super.dispose(), this._volume.dispose(), this.volume.dispose(), this._players.forEach((t) => t.dispose()), this._buffers.dispose(), this;
  }
}
class $c extends Ft {
  constructor() {
    const t = L($c.getDefaults(), arguments, ["url", "onload"]);
    super(t), this.name = "GrainPlayer", this._loopStart = 0, this._loopEnd = 0, this._activeSources = [], this.buffer = new ot({
      onload: t.onload,
      onerror: t.onerror,
      reverse: t.reverse,
      url: t.url
    }), this._clock = new vi({
      context: this.context,
      callback: this._tick.bind(this),
      frequency: 1 / t.grainSize
    }), this._playbackRate = t.playbackRate, this._grainSize = t.grainSize, this._overlap = t.overlap, this.detune = t.detune, this.overlap = t.overlap, this.loop = t.loop, this.playbackRate = t.playbackRate, this.grainSize = t.grainSize, this.loopStart = t.loopStart, this.loopEnd = t.loopEnd, this.reverse = t.reverse, this._clock.on("stop", this._onstop.bind(this));
  }
  static getDefaults() {
    return Object.assign(Ft.getDefaults(), {
      onload: st,
      onerror: st,
      overlap: 0.1,
      grainSize: 0.2,
      playbackRate: 1,
      detune: 0,
      loop: !1,
      loopStart: 0,
      loopEnd: 0,
      reverse: !1
    });
  }
  /**
   * Internal start method
   */
  _start(t, e, s) {
    e = Ve(e, 0), e = this.toSeconds(e), t = this.toSeconds(t);
    const i = 1 / this._clock.frequency.getValueAtTime(t);
    this._clock.start(t, e / i), s && this.stop(t + this.toSeconds(s));
  }
  /**
   * Stop and then restart the player from the beginning (or offset)
   * @param  time When the player should start.
   * @param  offset The offset from the beginning of the sample to start at.
   * @param  duration How long the sample should play. If no duration is given,
   * 					it will default to the full length of the sample (minus any offset)
   */
  restart(t, e, s) {
    return super.restart(t, e, s), this;
  }
  _restart(t, e, s) {
    this._stop(t), this._start(t, e, s);
  }
  /**
   * Internal stop method
   */
  _stop(t) {
    this._clock.stop(t);
  }
  /**
   * Invoked when the clock is stopped
   */
  _onstop(t) {
    this._activeSources.forEach((e) => {
      e.fadeOut = 0, e.stop(t);
    }), this.onstop(this);
  }
  /**
   * Invoked on each clock tick. scheduled a new grain at this time.
   */
  _tick(t) {
    const e = this._clock.getTicksAtTime(t), s = e * this._grainSize;
    if (this.log("offset", s), !this.loop && s > this.buffer.duration) {
      this.stop(t);
      return;
    }
    const i = s < this._overlap ? 0 : this._overlap, r = new tn({
      context: this.context,
      url: this.buffer,
      fadeIn: i,
      fadeOut: this._overlap,
      loop: this.loop,
      loopStart: this._loopStart,
      loopEnd: this._loopEnd,
      // compute the playbackRate based on the detune
      playbackRate: ii(this.detune / 100)
    }).connect(this.output);
    r.start(t, this._grainSize * e), r.stop(t + this._grainSize / this.playbackRate), this._activeSources.push(r), r.onended = () => {
      const o = this._activeSources.indexOf(r);
      o !== -1 && this._activeSources.splice(o, 1);
    };
  }
  /**
   * The playback rate of the sample
   */
  get playbackRate() {
    return this._playbackRate;
  }
  set playbackRate(t) {
    zt(t, 1e-3), this._playbackRate = t, this.grainSize = this._grainSize;
  }
  /**
   * The loop start time.
   */
  get loopStart() {
    return this._loopStart;
  }
  set loopStart(t) {
    this.buffer.loaded && zt(this.toSeconds(t), 0, this.buffer.duration), this._loopStart = this.toSeconds(t);
  }
  /**
   * The loop end time.
   */
  get loopEnd() {
    return this._loopEnd;
  }
  set loopEnd(t) {
    this.buffer.loaded && zt(this.toSeconds(t), 0, this.buffer.duration), this._loopEnd = this.toSeconds(t);
  }
  /**
   * The direction the buffer should play in
   */
  get reverse() {
    return this.buffer.reverse;
  }
  set reverse(t) {
    this.buffer.reverse = t;
  }
  /**
   * The size of each chunk of audio that the
   * buffer is chopped into and played back at.
   */
  get grainSize() {
    return this._grainSize;
  }
  set grainSize(t) {
    this._grainSize = this.toSeconds(t), this._clock.frequency.setValueAtTime(this._playbackRate / this._grainSize, this.now());
  }
  /**
   * The duration of the cross-fade between successive grains.
   */
  get overlap() {
    return this._overlap;
  }
  set overlap(t) {
    const e = this.toSeconds(t);
    zt(e, 0), this._overlap = e;
  }
  /**
   * If all the buffer is loaded
   */
  get loaded() {
    return this.buffer.loaded;
  }
  dispose() {
    return super.dispose(), this.buffer.dispose(), this._clock.dispose(), this._activeSources.forEach((t) => t.dispose()), this;
  }
}
class Sg extends Re {
  constructor() {
    super(...arguments), this.name = "Abs", this._abs = new ss({
      context: this.context,
      mapping: (t) => Math.abs(t) < 1e-3 ? 0 : Math.abs(t)
    }), this.input = this._abs, this.output = this._abs;
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), this._abs.dispose(), this;
  }
}
class Tg extends Re {
  constructor() {
    super(...arguments), this.name = "GainToAudio", this._norm = new ss({
      context: this.context,
      mapping: (t) => Math.abs(t) * 2 - 1
    }), this.input = this._norm, this.output = this._norm;
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), this._norm.dispose(), this;
  }
}
class Hc extends Re {
  constructor() {
    super(...arguments), this.name = "Negate", this._multiply = new Mt({
      context: this.context,
      value: -1
    }), this.input = this._multiply, this.output = this._multiply;
  }
  /**
   * clean up
   * @returns {Negate} this
   */
  dispose() {
    return super.dispose(), this._multiply.dispose(), this;
  }
}
class Rn extends Q {
  constructor() {
    super(L(Rn.getDefaults(), arguments, ["value"])), this.override = !1, this.name = "Subtract", this._sum = new j({ context: this.context }), this.input = this._sum, this.output = this._sum, this._neg = new Hc({ context: this.context }), this.subtrahend = this._param, Fe(this._constantSource, this._neg, this._sum);
  }
  static getDefaults() {
    return Object.assign(Q.getDefaults(), {
      value: 0
    });
  }
  dispose() {
    return super.dispose(), this._neg.dispose(), this._sum.dispose(), this;
  }
}
class ua extends Re {
  constructor() {
    super(L(ua.getDefaults(), arguments)), this.name = "GreaterThanZero", this._thresh = this.output = new ss({
      context: this.context,
      length: 127,
      mapping: (t) => t <= 0 ? 0 : 1
    }), this._scale = this.input = new Mt({
      context: this.context,
      value: 1e4
    }), this._scale.connect(this._thresh);
  }
  dispose() {
    return super.dispose(), this._scale.dispose(), this._thresh.dispose(), this;
  }
}
class da extends Q {
  constructor() {
    const t = L(da.getDefaults(), arguments, ["value"]);
    super(t), this.name = "GreaterThan", this.override = !1, this._subtract = this.input = new Rn({
      context: this.context,
      value: t.value
    }), this._gtz = this.output = new ua({
      context: this.context
    }), this.comparator = this._param = this._subtract.subtrahend, Z(this, "comparator"), this._subtract.connect(this._gtz);
  }
  static getDefaults() {
    return Object.assign(Q.getDefaults(), {
      value: 0
    });
  }
  dispose() {
    return super.dispose(), this._gtz.dispose(), this._subtract.dispose(), this.comparator.dispose(), this;
  }
}
class fa extends Rs {
  constructor() {
    const t = L(fa.getDefaults(), arguments, ["min", "max", "exponent"]);
    super(t), this.name = "ScaleExp", this.input = this._exp = new wi({
      context: this.context,
      value: t.exponent
    }), this._exp.connect(this._mult);
  }
  static getDefaults() {
    return Object.assign(Rs.getDefaults(), {
      exponent: 1
    });
  }
  /**
   * Instead of interpolating linearly between the {@link min} and
   * {@link max} values, setting the exponent will interpolate between
   * the two values with an exponential curve.
   */
  get exponent() {
    return this._exp.value;
  }
  set exponent(t) {
    this._exp.value = t;
  }
  dispose() {
    return super.dispose(), this._exp.dispose(), this;
  }
}
class cC extends Q {
  constructor() {
    const t = L(Q.getDefaults(), arguments, [
      "value",
      "units"
    ]);
    super(t), this.name = "SyncedSignal", this.override = !1, this._lastVal = t.value, this._synced = this.context.transport.scheduleRepeat(this._onTick.bind(this), "1i"), this._syncedCallback = this._anchorValue.bind(this), this.context.transport.on("start", this._syncedCallback), this.context.transport.on("pause", this._syncedCallback), this.context.transport.on("stop", this._syncedCallback), this._constantSource.disconnect(), this._constantSource.stop(0), this._constantSource = this.output = new aa({
      context: this.context,
      offset: t.value,
      units: t.units
    }).start(0), this.setValueAtTime(t.value, 0);
  }
  /**
   * Callback which is invoked every tick.
   */
  _onTick(t) {
    const e = super.getValueAtTime(this.context.transport.seconds);
    this._lastVal !== e && (this._lastVal = e, this._constantSource.offset.setValueAtTime(e, t));
  }
  /**
   * Anchor the value at the start and stop of the Transport
   */
  _anchorValue(t) {
    const e = super.getValueAtTime(this.context.transport.seconds);
    this._lastVal = e, this._constantSource.offset.cancelAndHoldAtTime(t), this._constantSource.offset.setValueAtTime(e, t);
  }
  getValueAtTime(t) {
    const e = new Lt(this.context, t).toSeconds();
    return super.getValueAtTime(e);
  }
  setValueAtTime(t, e) {
    const s = new Lt(this.context, e).toSeconds();
    return super.setValueAtTime(t, s), this;
  }
  linearRampToValueAtTime(t, e) {
    const s = new Lt(this.context, e).toSeconds();
    return super.linearRampToValueAtTime(t, s), this;
  }
  exponentialRampToValueAtTime(t, e) {
    const s = new Lt(this.context, e).toSeconds();
    return super.exponentialRampToValueAtTime(t, s), this;
  }
  setTargetAtTime(t, e, s) {
    const i = new Lt(this.context, e).toSeconds();
    return super.setTargetAtTime(t, i, s), this;
  }
  cancelScheduledValues(t) {
    const e = new Lt(this.context, t).toSeconds();
    return super.cancelScheduledValues(e), this;
  }
  setValueCurveAtTime(t, e, s, i) {
    const r = new Lt(this.context, e).toSeconds();
    return s = this.toSeconds(s), super.setValueCurveAtTime(t, r, s, i), this;
  }
  cancelAndHoldAtTime(t) {
    const e = new Lt(this.context, t).toSeconds();
    return super.cancelAndHoldAtTime(e), this;
  }
  setRampPoint(t) {
    const e = new Lt(this.context, t).toSeconds();
    return super.setRampPoint(e), this;
  }
  exponentialRampTo(t, e, s) {
    const i = new Lt(this.context, s).toSeconds();
    return super.exponentialRampTo(t, e, i), this;
  }
  linearRampTo(t, e, s) {
    const i = new Lt(this.context, s).toSeconds();
    return super.linearRampTo(t, e, i), this;
  }
  targetRampTo(t, e, s) {
    const i = new Lt(this.context, s).toSeconds();
    return super.targetRampTo(t, e, i), this;
  }
  dispose() {
    return super.dispose(), this.context.transport.clear(this._synced), this.context.transport.off("start", this._syncedCallback), this.context.transport.off("pause", this._syncedCallback), this.context.transport.off("stop", this._syncedCallback), this._constantSource.dispose(), this;
  }
}
class Qt extends B {
  constructor() {
    const t = L(Qt.getDefaults(), arguments, ["attack", "decay", "sustain", "release"]);
    super(t), this.name = "Envelope", this._sig = new Q({
      context: this.context,
      value: 0
    }), this.output = this._sig, this.input = void 0, this.attack = t.attack, this.decay = t.decay, this.sustain = t.sustain, this.release = t.release, this.attackCurve = t.attackCurve, this.releaseCurve = t.releaseCurve, this.decayCurve = t.decayCurve;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      attack: 0.01,
      attackCurve: "linear",
      decay: 0.1,
      decayCurve: "exponential",
      release: 1,
      releaseCurve: "exponential",
      sustain: 0.5
    });
  }
  /**
   * Read the current value of the envelope. Useful for
   * synchronizing visual output to the envelope.
   */
  get value() {
    return this.getValueAtTime(this.now());
  }
  /**
   * Get the curve
   * @param  curve
   * @param  direction  In/Out
   * @return The curve name
   */
  _getCurve(t, e) {
    if (Qe(t))
      return t;
    {
      let s;
      for (s in no)
        if (no[s][e] === t)
          return s;
      return t;
    }
  }
  /**
   * Assign a the curve to the given name using the direction
   * @param  name
   * @param  direction In/Out
   * @param  curve
   */
  _setCurve(t, e, s) {
    if (Qe(s) && Reflect.has(no, s)) {
      const i = no[s];
      Es(i) ? t !== "_decayCurve" && (this[t] = i[e]) : this[t] = i;
    } else if (Kt(s) && t !== "_decayCurve")
      this[t] = s;
    else
      throw new Error("Envelope: invalid curve: " + s);
  }
  /**
   * The shape of the attack.
   * Can be any of these strings:
   * * "linear"
   * * "exponential"
   * * "sine"
   * * "cosine"
   * * "bounce"
   * * "ripple"
   * * "step"
   *
   * Can also be an array which describes the curve. Values
   * in the array are evenly subdivided and linearly
   * interpolated over the duration of the attack.
   * @example
   * return Tone.Offline(() => {
   * 	const env = new Tone.Envelope(0.4).toDestination();
   * 	env.attackCurve = "linear";
   * 	env.triggerAttack();
   * }, 1, 1);
   */
  get attackCurve() {
    return this._getCurve(this._attackCurve, "In");
  }
  set attackCurve(t) {
    this._setCurve("_attackCurve", "In", t);
  }
  /**
   * The shape of the release. See the attack curve types.
   * @example
   * return Tone.Offline(() => {
   * 	const env = new Tone.Envelope({
   * 		release: 0.8
   * 	}).toDestination();
   * 	env.triggerAttack();
   * 	// release curve could also be defined by an array
   * 	env.releaseCurve = [1, 0.3, 0.4, 0.2, 0.7, 0];
   * 	env.triggerRelease(0.2);
   * }, 1, 1);
   */
  get releaseCurve() {
    return this._getCurve(this._releaseCurve, "Out");
  }
  set releaseCurve(t) {
    this._setCurve("_releaseCurve", "Out", t);
  }
  /**
   * The shape of the decay either "linear" or "exponential"
   * @example
   * return Tone.Offline(() => {
   * 	const env = new Tone.Envelope({
   * 		sustain: 0.1,
   * 		decay: 0.5
   * 	}).toDestination();
   * 	env.decayCurve = "linear";
   * 	env.triggerAttack();
   * }, 1, 1);
   */
  get decayCurve() {
    return this._getCurve(this._decayCurve, "Out");
  }
  set decayCurve(t) {
    this._setCurve("_decayCurve", "Out", t);
  }
  /**
   * Trigger the attack/decay portion of the ADSR envelope.
   * @param  time When the attack should start.
   * @param velocity The velocity of the envelope scales the vales.
   *                             number between 0-1
   * @example
   * const env = new Tone.AmplitudeEnvelope().toDestination();
   * const osc = new Tone.Oscillator().connect(env).start();
   * // trigger the attack 0.5 seconds from now with a velocity of 0.2
   * env.triggerAttack("+0.5", 0.2);
   */
  triggerAttack(t, e = 1) {
    this.log("triggerAttack", t, e), t = this.toSeconds(t);
    let i = this.toSeconds(this.attack);
    const r = this.toSeconds(this.decay), o = this.getValueAtTime(t);
    if (o > 0) {
      const a = 1 / i;
      i = (1 - o) / a;
    }
    if (i < this.sampleTime)
      this._sig.cancelScheduledValues(t), this._sig.setValueAtTime(e, t);
    else if (this._attackCurve === "linear")
      this._sig.linearRampTo(e, i, t);
    else if (this._attackCurve === "exponential")
      this._sig.targetRampTo(e, i, t);
    else {
      this._sig.cancelAndHoldAtTime(t);
      let a = this._attackCurve;
      for (let l = 1; l < a.length; l++)
        if (a[l - 1] <= o && o <= a[l]) {
          a = this._attackCurve.slice(l), a[0] = o;
          break;
        }
      this._sig.setValueCurveAtTime(a, t, i, e);
    }
    if (r && this.sustain < 1) {
      const a = e * this.sustain, l = t + i;
      this.log("decay", l), this._decayCurve === "linear" ? this._sig.linearRampToValueAtTime(a, r + l) : this._sig.exponentialApproachValueAtTime(a, l, r);
    }
    return this;
  }
  /**
   * Triggers the release of the envelope.
   * @param  time When the release portion of the envelope should start.
   * @example
   * const env = new Tone.AmplitudeEnvelope().toDestination();
   * const osc = new Tone.Oscillator({
   * 	type: "sawtooth"
   * }).connect(env).start();
   * env.triggerAttack();
   * // trigger the release half a second after the attack
   * env.triggerRelease("+0.5");
   */
  triggerRelease(t) {
    this.log("triggerRelease", t), t = this.toSeconds(t);
    const e = this.getValueAtTime(t);
    if (e > 0) {
      const s = this.toSeconds(this.release);
      s < this.sampleTime ? this._sig.setValueAtTime(0, t) : this._releaseCurve === "linear" ? this._sig.linearRampTo(0, s, t) : this._releaseCurve === "exponential" ? this._sig.targetRampTo(0, s, t) : (X(Kt(this._releaseCurve), "releaseCurve must be either 'linear', 'exponential' or an array"), this._sig.cancelAndHoldAtTime(t), this._sig.setValueCurveAtTime(this._releaseCurve, t, s, e));
    }
    return this;
  }
  /**
   * Get the scheduled value at the given time. This will
   * return the unconverted (raw) value.
   * @example
   * const env = new Tone.Envelope(0.5, 1, 0.4, 2);
   * env.triggerAttackRelease(2);
   * setInterval(() => console.log(env.getValueAtTime(Tone.now())), 100);
   */
  getValueAtTime(t) {
    return this._sig.getValueAtTime(t);
  }
  /**
   * triggerAttackRelease is shorthand for triggerAttack, then waiting
   * some duration, then triggerRelease.
   * @param duration The duration of the sustain.
   * @param time When the attack should be triggered.
   * @param velocity The velocity of the envelope.
   * @example
   * const env = new Tone.AmplitudeEnvelope().toDestination();
   * const osc = new Tone.Oscillator().connect(env).start();
   * // trigger the release 0.5 seconds after the attack
   * env.triggerAttackRelease(0.5);
   */
  triggerAttackRelease(t, e, s = 1) {
    return e = this.toSeconds(e), this.triggerAttack(e, s), this.triggerRelease(e + this.toSeconds(t)), this;
  }
  /**
   * Cancels all scheduled envelope changes after the given time.
   */
  cancel(t) {
    return this._sig.cancelScheduledValues(this.toSeconds(t)), this;
  }
  /**
   * Connect the envelope to a destination node.
   */
  connect(t, e = 0, s = 0) {
    return wr(this, t, e, s), this;
  }
  /**
   * Render the envelope curve to an array of the given length.
   * Good for visualizing the envelope curve. Rescales the duration of the
   * envelope to fit the length.
   */
  asArray() {
    return yt(this, arguments, void 0, function* (t = 1024) {
      const e = t / this.context.sampleRate, s = new xi(1, e, this.context.sampleRate), i = this.toSeconds(this.attack) + this.toSeconds(this.decay), r = i + this.toSeconds(this.release), o = r * 0.1, a = r + o, l = new this.constructor(Object.assign(this.get(), {
        attack: e * this.toSeconds(this.attack) / a,
        decay: e * this.toSeconds(this.decay) / a,
        release: e * this.toSeconds(this.release) / a,
        context: s
      }));
      return l._sig.toDestination(), l.triggerAttackRelease(e * (i + o) / a, 0), (yield s.render()).getChannelData(0);
    });
  }
  dispose() {
    return super.dispose(), this._sig.dispose(), this;
  }
}
es([
  Ns(0)
], Qt.prototype, "attack", void 0);
es([
  Ns(0)
], Qt.prototype, "decay", void 0);
es([
  wg(0, 1)
], Qt.prototype, "sustain", void 0);
es([
  Ns(0)
], Qt.prototype, "release", void 0);
const no = (() => {
  let t, e;
  const s = [];
  for (t = 0; t < 128; t++)
    s[t] = Math.sin(t / 127 * (Math.PI / 2));
  const i = [], r = 6.4;
  for (t = 0; t < 127; t++) {
    e = t / 127;
    const d = Math.sin(e * (Math.PI * 2) * r - Math.PI / 2) + 1;
    i[t] = d / 10 + e * 0.83;
  }
  i[127] = 1;
  const o = [], a = 5;
  for (t = 0; t < 128; t++)
    o[t] = Math.ceil(t / 127 * a) / a;
  const l = [];
  for (t = 0; t < 128; t++)
    e = t / 127, l[t] = 0.5 * (1 - Math.cos(Math.PI * e));
  const c = [];
  for (t = 0; t < 128; t++) {
    e = t / 127;
    const d = Math.pow(e, 3) * 4 + 0.2, f = Math.cos(d * Math.PI * 2 * e);
    c[t] = Math.abs(f * (1 - e));
  }
  function h(d) {
    const f = new Array(d.length);
    for (let p = 0; p < d.length; p++)
      f[p] = 1 - d[p];
    return f;
  }
  function u(d) {
    return d.slice(0).reverse();
  }
  return {
    bounce: {
      In: h(c),
      Out: c
    },
    cosine: {
      In: s,
      Out: u(s)
    },
    exponential: "exponential",
    linear: "linear",
    ripple: {
      In: i,
      Out: h(i)
    },
    sine: {
      In: l,
      Out: h(l)
    },
    step: {
      In: o,
      Out: h(o)
    }
  };
})();
class Be extends B {
  constructor() {
    const t = L(Be.getDefaults(), arguments);
    super(t), this._scheduledEvents = [], this._synced = !1, this._original_triggerAttack = this.triggerAttack, this._original_triggerRelease = this.triggerRelease, this._syncedRelease = (e) => this._original_triggerRelease(e), this._volume = this.output = new Os({
      context: this.context,
      volume: t.volume
    }), this.volume = this._volume.volume, Z(this, "volume");
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      volume: 0
    });
  }
  /**
   * Sync the instrument to the Transport. All subsequent calls of
   * {@link triggerAttack} and {@link triggerRelease} will be scheduled along the transport.
   * @example
   * const fmSynth = new Tone.FMSynth().toDestination();
   * fmSynth.volume.value = -6;
   * fmSynth.sync();
   * // schedule 3 notes when the transport first starts
   * fmSynth.triggerAttackRelease("C4", "8n", 0);
   * fmSynth.triggerAttackRelease("E4", "8n", "8n");
   * fmSynth.triggerAttackRelease("G4", "8n", "4n");
   * // start the transport to hear the notes
   * Tone.Transport.start();
   */
  sync() {
    return this._syncState() && (this._syncMethod("triggerAttack", 1), this._syncMethod("triggerRelease", 0), this.context.transport.on("stop", this._syncedRelease), this.context.transport.on("pause", this._syncedRelease), this.context.transport.on("loopEnd", this._syncedRelease)), this;
  }
  /**
   * set _sync
   */
  _syncState() {
    let t = !1;
    return this._synced || (this._synced = !0, t = !0), t;
  }
  /**
   * Wrap the given method so that it can be synchronized
   * @param method Which method to wrap and sync
   * @param  timePosition What position the time argument appears in
   */
  _syncMethod(t, e) {
    const s = this["_original_" + t] = this[t];
    this[t] = (...i) => {
      const r = i[e], o = this.context.transport.schedule((a) => {
        i[e] = a, s.apply(this, i);
      }, r);
      this._scheduledEvents.push(o);
    };
  }
  /**
   * Unsync the instrument from the Transport
   */
  unsync() {
    return this._scheduledEvents.forEach((t) => this.context.transport.clear(t)), this._scheduledEvents = [], this._synced && (this._synced = !1, this.triggerAttack = this._original_triggerAttack, this.triggerRelease = this._original_triggerRelease, this.context.transport.off("stop", this._syncedRelease), this.context.transport.off("pause", this._syncedRelease), this.context.transport.off("loopEnd", this._syncedRelease)), this;
  }
  /**
   * Trigger the attack and then the release after the duration.
   * @param  note     The note to trigger.
   * @param  duration How long the note should be held for before
   *                         triggering the release. This value must be greater than 0.
   * @param time  When the note should be triggered.
   * @param  velocity The velocity the note should be triggered at.
   * @example
   * const synth = new Tone.Synth().toDestination();
   * // trigger "C4" for the duration of an 8th note
   * synth.triggerAttackRelease("C4", "8n");
   */
  triggerAttackRelease(t, e, s, i) {
    const r = this.toSeconds(s), o = this.toSeconds(e);
    return this.triggerAttack(t, r, i), this.triggerRelease(r + o), this;
  }
  /**
   * clean up
   * @returns {Instrument} this
   */
  dispose() {
    return super.dispose(), this._volume.dispose(), this.unsync(), this._scheduledEvents = [], this;
  }
}
class Zt extends Be {
  constructor() {
    const t = L(Zt.getDefaults(), arguments);
    super(t), this.portamento = t.portamento, this.onsilence = t.onsilence;
  }
  static getDefaults() {
    return Object.assign(Be.getDefaults(), {
      detune: 0,
      onsilence: st,
      portamento: 0
    });
  }
  /**
   * Trigger the attack of the note optionally with a given velocity.
   * @param  note The note to trigger.
   * @param  time When the note should start.
   * @param  velocity The velocity determines how "loud" the note will be.
   * @example
   * const synth = new Tone.Synth().toDestination();
   * // trigger the note a half second from now at half velocity
   * synth.triggerAttack("C4", "+0.5", 0.5);
   */
  triggerAttack(t, e, s = 1) {
    this.log("triggerAttack", t, e, s);
    const i = this.toSeconds(e);
    return this._triggerEnvelopeAttack(i, s), this.setNote(t, i), this;
  }
  /**
   * Trigger the release portion of the envelope.
   * @param  time If no time is given, the release happens immediately.
   * @example
   * const synth = new Tone.Synth().toDestination();
   * synth.triggerAttack("C4");
   * // trigger the release a second from now
   * synth.triggerRelease("+1");
   */
  triggerRelease(t) {
    this.log("triggerRelease", t);
    const e = this.toSeconds(t);
    return this._triggerEnvelopeRelease(e), this;
  }
  /**
   * Set the note at the given time. If no time is given, the note
   * will set immediately.
   * @param note The note to change to.
   * @param  time The time when the note should be set.
   * @example
   * const synth = new Tone.Synth().toDestination();
   * synth.triggerAttack("C4");
   * // change to F#6 in one quarter note from now.
   * synth.setNote("F#6", "+4n");
   */
  setNote(t, e) {
    const s = this.toSeconds(e), i = t instanceof ce ? t.toFrequency() : t;
    if (this.portamento > 0 && this.getLevelAtTime(s) > 0.05) {
      const r = this.toSeconds(this.portamento);
      this.frequency.exponentialRampTo(i, r, s);
    } else
      this.frequency.setValueAtTime(i, s);
    return this;
  }
}
es([
  Ns(0)
], Zt.prototype, "portamento", void 0);
class Mi extends Qt {
  constructor() {
    super(L(Mi.getDefaults(), arguments, [
      "attack",
      "decay",
      "sustain",
      "release"
    ])), this.name = "AmplitudeEnvelope", this._gainNode = new j({
      context: this.context,
      gain: 0
    }), this.output = this._gainNode, this.input = this._gainNode, this._sig.connect(this._gainNode.gain), this.output = this._gainNode, this.input = this._gainNode;
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this._gainNode.dispose(), this;
  }
}
class Zs extends Zt {
  constructor() {
    const t = L(Zs.getDefaults(), arguments);
    super(t), this.name = "Synth", this.oscillator = new Fs(Object.assign({
      context: this.context,
      detune: t.detune,
      onstop: () => this.onsilence(this)
    }, t.oscillator)), this.frequency = this.oscillator.frequency, this.detune = this.oscillator.detune, this.envelope = new Mi(Object.assign({
      context: this.context
    }, t.envelope)), this.oscillator.chain(this.envelope, this.output), Z(this, ["oscillator", "frequency", "detune", "envelope"]);
  }
  static getDefaults() {
    return Object.assign(Zt.getDefaults(), {
      envelope: Object.assign(Yt(Qt.getDefaults(), Object.keys(B.getDefaults())), {
        attack: 5e-3,
        decay: 0.1,
        release: 1,
        sustain: 0.3
      }),
      oscillator: Object.assign(Yt(Fs.getDefaults(), [
        ...Object.keys(Ft.getDefaults()),
        "frequency",
        "detune"
      ]), {
        type: "triangle"
      })
    });
  }
  /**
   * start the attack portion of the envelope
   * @param time the time the attack should start
   * @param velocity the velocity of the note (0-1)
   */
  _triggerEnvelopeAttack(t, e) {
    if (this.envelope.triggerAttack(t, e), this.oscillator.start(t), this.envelope.sustain === 0) {
      const s = this.toSeconds(this.envelope.attack), i = this.toSeconds(this.envelope.decay);
      this.oscillator.stop(t + s + i);
    }
  }
  /**
   * start the release portion of the envelope
   * @param time the time the release should start
   */
  _triggerEnvelopeRelease(t) {
    this.envelope.triggerRelease(t), this.oscillator.stop(t + this.toSeconds(this.envelope.release));
  }
  getLevelAtTime(t) {
    return t = this.toSeconds(t), this.envelope.getValueAtTime(t);
  }
  /**
   * clean up
   */
  dispose() {
    return super.dispose(), this.oscillator.dispose(), this.envelope.dispose(), this;
  }
}
class ar extends Zt {
  constructor() {
    const t = L(ar.getDefaults(), arguments);
    super(t), this.name = "ModulationSynth", this._carrier = new Zs({
      context: this.context,
      oscillator: t.oscillator,
      envelope: t.envelope,
      onsilence: () => this.onsilence(this),
      volume: -10
    }), this._modulator = new Zs({
      context: this.context,
      oscillator: t.modulation,
      envelope: t.modulationEnvelope,
      volume: -10
    }), this.oscillator = this._carrier.oscillator, this.envelope = this._carrier.envelope, this.modulation = this._modulator.oscillator, this.modulationEnvelope = this._modulator.envelope, this.frequency = new Q({
      context: this.context,
      units: "frequency"
    }), this.detune = new Q({
      context: this.context,
      value: t.detune,
      units: "cents"
    }), this.harmonicity = new Mt({
      context: this.context,
      value: t.harmonicity,
      minValue: 0
    }), this._modulationNode = new j({
      context: this.context,
      gain: 0
    }), Z(this, [
      "frequency",
      "harmonicity",
      "oscillator",
      "envelope",
      "modulation",
      "modulationEnvelope",
      "detune"
    ]);
  }
  static getDefaults() {
    return Object.assign(Zt.getDefaults(), {
      harmonicity: 3,
      oscillator: Object.assign(Yt(Fs.getDefaults(), [
        ...Object.keys(Ft.getDefaults()),
        "frequency",
        "detune"
      ]), {
        type: "sine"
      }),
      envelope: Object.assign(Yt(Qt.getDefaults(), Object.keys(B.getDefaults())), {
        attack: 0.01,
        decay: 0.01,
        sustain: 1,
        release: 0.5
      }),
      modulation: Object.assign(Yt(Fs.getDefaults(), [
        ...Object.keys(Ft.getDefaults()),
        "frequency",
        "detune"
      ]), {
        type: "square"
      }),
      modulationEnvelope: Object.assign(Yt(Qt.getDefaults(), Object.keys(B.getDefaults())), {
        attack: 0.5,
        decay: 0,
        sustain: 1,
        release: 0.5
      })
    });
  }
  /**
   * Trigger the attack portion of the note
   */
  _triggerEnvelopeAttack(t, e) {
    this._carrier._triggerEnvelopeAttack(t, e), this._modulator._triggerEnvelopeAttack(t, e);
  }
  /**
   * Trigger the release portion of the note
   */
  _triggerEnvelopeRelease(t) {
    return this._carrier._triggerEnvelopeRelease(t), this._modulator._triggerEnvelopeRelease(t), this;
  }
  getLevelAtTime(t) {
    return t = this.toSeconds(t), this.envelope.getValueAtTime(t);
  }
  dispose() {
    return super.dispose(), this._carrier.dispose(), this._modulator.dispose(), this.frequency.dispose(), this.detune.dispose(), this.harmonicity.dispose(), this._modulationNode.dispose(), this;
  }
}
class jc extends ar {
  constructor() {
    super(L(jc.getDefaults(), arguments)), this.name = "AMSynth", this._modulationScale = new ca({
      context: this.context
    }), this.frequency.connect(this._carrier.frequency), this.frequency.chain(this.harmonicity, this._modulator.frequency), this.detune.fan(this._carrier.detune, this._modulator.detune), this._modulator.chain(this._modulationScale, this._modulationNode.gain), this._carrier.chain(this._modulationNode, this.output);
  }
  dispose() {
    return super.dispose(), this._modulationScale.dispose(), this;
  }
}
class lr extends B {
  constructor() {
    const t = L(lr.getDefaults(), arguments, ["frequency", "type"]);
    super(t), this.name = "BiquadFilter", this._filter = this.context.createBiquadFilter(), this.input = this.output = this._filter, this.Q = new tt({
      context: this.context,
      units: "number",
      value: t.Q,
      param: this._filter.Q
    }), this.frequency = new tt({
      context: this.context,
      units: "frequency",
      value: t.frequency,
      param: this._filter.frequency
    }), this.detune = new tt({
      context: this.context,
      units: "cents",
      value: t.detune,
      param: this._filter.detune
    }), this.gain = new tt({
      context: this.context,
      units: "decibels",
      convert: !1,
      value: t.gain,
      param: this._filter.gain
    }), this.type = t.type;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      Q: 1,
      type: "lowpass",
      frequency: 350,
      detune: 0,
      gain: 0
    });
  }
  /**
   * The type of this BiquadFilterNode. For a complete list of types and their attributes, see the
   * [Web Audio API](https://webaudio.github.io/web-audio-api/#dom-biquadfiltertype-lowpass)
   */
  get type() {
    return this._filter.type;
  }
  set type(t) {
    X([
      "lowpass",
      "highpass",
      "bandpass",
      "lowshelf",
      "highshelf",
      "notch",
      "allpass",
      "peaking"
    ].indexOf(t) !== -1, `Invalid filter type: ${t}`), this._filter.type = t;
  }
  /**
   * Get the frequency response curve. This curve represents how the filter
   * responses to frequencies between 20hz-20khz.
   * @param  len The number of values to return
   * @return The frequency response curve between 20-20kHz
   */
  getFrequencyResponse(t = 128) {
    const e = new Float32Array(t);
    for (let o = 0; o < t; o++) {
      const l = Math.pow(o / t, 2) * 19980 + 20;
      e[o] = l;
    }
    const s = new Float32Array(t), i = new Float32Array(t), r = this.context.createBiquadFilter();
    return r.type = this.type, r.Q.value = this.Q.value, r.frequency.value = this.frequency.value, r.gain.value = this.gain.value, r.getFrequencyResponse(e, s, i), s;
  }
  dispose() {
    return super.dispose(), this._filter.disconnect(), this.Q.dispose(), this.frequency.dispose(), this.gain.dispose(), this.detune.dispose(), this;
  }
}
class Ce extends B {
  constructor() {
    const t = L(Ce.getDefaults(), arguments, [
      "frequency",
      "type",
      "rolloff"
    ]);
    super(t), this.name = "Filter", this.input = new j({ context: this.context }), this.output = new j({ context: this.context }), this._filters = [], this._filters = [], this.Q = new Q({
      context: this.context,
      units: "positive",
      value: t.Q
    }), this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.frequency
    }), this.detune = new Q({
      context: this.context,
      units: "cents",
      value: t.detune
    }), this.gain = new Q({
      context: this.context,
      units: "decibels",
      convert: !1,
      value: t.gain
    }), this._type = t.type, this.rolloff = t.rolloff, Z(this, ["detune", "frequency", "gain", "Q"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      Q: 1,
      detune: 0,
      frequency: 350,
      gain: 0,
      rolloff: -12,
      type: "lowpass"
    });
  }
  /**
   * The type of the filter. Types: "lowpass", "highpass",
   * "bandpass", "lowshelf", "highshelf", "notch", "allpass", or "peaking".
   */
  get type() {
    return this._type;
  }
  set type(t) {
    X([
      "lowpass",
      "highpass",
      "bandpass",
      "lowshelf",
      "highshelf",
      "notch",
      "allpass",
      "peaking"
    ].indexOf(t) !== -1, `Invalid filter type: ${t}`), this._type = t, this._filters.forEach((s) => s.type = t);
  }
  /**
   * The rolloff of the filter which is the drop in db
   * per octave. Implemented internally by cascading filters.
   * Only accepts the values -12, -24, -48 and -96.
   */
  get rolloff() {
    return this._rolloff;
  }
  set rolloff(t) {
    const e = Ie(t) ? t : parseInt(t, 10), s = [-12, -24, -48, -96];
    let i = s.indexOf(e);
    X(i !== -1, `rolloff can only be ${s.join(", ")}`), i += 1, this._rolloff = e, this.input.disconnect(), this._filters.forEach((r) => r.disconnect()), this._filters = new Array(i);
    for (let r = 0; r < i; r++) {
      const o = new lr({
        context: this.context
      });
      o.type = this._type, this.frequency.connect(o.frequency), this.detune.connect(o.detune), this.Q.connect(o.Q), this.gain.connect(o.gain), this._filters[r] = o;
    }
    this._internalChannels = this._filters, Fe(this.input, ...this._internalChannels, this.output);
  }
  /**
   * Get the frequency response curve. This curve represents how the filter
   * responses to frequencies between 20hz-20khz.
   * @param  len The number of values to return
   * @return The frequency response curve between 20-20kHz
   */
  getFrequencyResponse(t = 128) {
    const e = new lr({
      context: this.context,
      frequency: this.frequency.value,
      gain: this.gain.value,
      Q: this.Q.value,
      type: this._type,
      detune: this.detune.value
    }), s = new Float32Array(t).map(() => 1);
    return this._filters.forEach(() => {
      e.getFrequencyResponse(t).forEach((r, o) => s[o] *= r);
    }), e.dispose(), s;
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._filters.forEach((t) => {
      t.dispose();
    }), vr(this, ["detune", "frequency", "gain", "Q"]), this.frequency.dispose(), this.Q.dispose(), this.detune.dispose(), this.gain.dispose(), this;
  }
}
class cr extends Qt {
  constructor() {
    const t = L(cr.getDefaults(), arguments, ["attack", "decay", "sustain", "release"]);
    super(t), this.name = "FrequencyEnvelope", this._octaves = t.octaves, this._baseFrequency = this.toFrequency(t.baseFrequency), this._exponent = this.input = new wi({
      context: this.context,
      value: t.exponent
    }), this._scale = this.output = new Rs({
      context: this.context,
      min: this._baseFrequency,
      max: this._baseFrequency * Math.pow(2, this._octaves)
    }), this._sig.chain(this._exponent, this._scale);
  }
  static getDefaults() {
    return Object.assign(Qt.getDefaults(), {
      baseFrequency: 200,
      exponent: 1,
      octaves: 4
    });
  }
  /**
   * The envelope's minimum output value. This is the value which it
   * starts at.
   */
  get baseFrequency() {
    return this._baseFrequency;
  }
  set baseFrequency(t) {
    const e = this.toFrequency(t);
    zt(e, 0), this._baseFrequency = e, this._scale.min = this._baseFrequency, this.octaves = this._octaves;
  }
  /**
   * The number of octaves above the baseFrequency that the
   * envelope will scale to.
   */
  get octaves() {
    return this._octaves;
  }
  set octaves(t) {
    this._octaves = t, this._scale.max = this._baseFrequency * Math.pow(2, t);
  }
  /**
   * The envelope's exponent value.
   */
  get exponent() {
    return this._exponent.value;
  }
  set exponent(t) {
    this._exponent.value = t;
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this._exponent.dispose(), this._scale.dispose(), this;
  }
}
class _n extends Zt {
  constructor() {
    const t = L(_n.getDefaults(), arguments);
    super(t), this.name = "MonoSynth", this.oscillator = new Fs(Object.assign(t.oscillator, {
      context: this.context,
      detune: t.detune,
      onstop: () => this.onsilence(this)
    })), this.frequency = this.oscillator.frequency, this.detune = this.oscillator.detune, this.filter = new Ce(Object.assign(t.filter, { context: this.context })), this.filterEnvelope = new cr(Object.assign(t.filterEnvelope, { context: this.context })), this.envelope = new Mi(Object.assign(t.envelope, { context: this.context })), this.oscillator.chain(this.filter, this.envelope, this.output), this.filterEnvelope.connect(this.filter.frequency), Z(this, [
      "oscillator",
      "frequency",
      "detune",
      "filter",
      "filterEnvelope",
      "envelope"
    ]);
  }
  static getDefaults() {
    return Object.assign(Zt.getDefaults(), {
      envelope: Object.assign(Yt(Qt.getDefaults(), Object.keys(B.getDefaults())), {
        attack: 5e-3,
        decay: 0.1,
        release: 1,
        sustain: 0.9
      }),
      filter: Object.assign(Yt(Ce.getDefaults(), Object.keys(B.getDefaults())), {
        Q: 1,
        rolloff: -12,
        type: "lowpass"
      }),
      filterEnvelope: Object.assign(Yt(cr.getDefaults(), Object.keys(B.getDefaults())), {
        attack: 0.6,
        baseFrequency: 200,
        decay: 0.2,
        exponent: 2,
        octaves: 3,
        release: 2,
        sustain: 0.5
      }),
      oscillator: Object.assign(Yt(Fs.getDefaults(), Object.keys(Ft.getDefaults())), {
        type: "sawtooth"
      })
    });
  }
  /**
   * start the attack portion of the envelope
   * @param time the time the attack should start
   * @param velocity the velocity of the note (0-1)
   */
  _triggerEnvelopeAttack(t, e = 1) {
    if (this.envelope.triggerAttack(t, e), this.filterEnvelope.triggerAttack(t), this.oscillator.start(t), this.envelope.sustain === 0) {
      const s = this.toSeconds(this.envelope.attack), i = this.toSeconds(this.envelope.decay);
      this.oscillator.stop(t + s + i);
    }
  }
  /**
   * start the release portion of the envelope
   * @param time the time the release should start
   */
  _triggerEnvelopeRelease(t) {
    this.envelope.triggerRelease(t), this.filterEnvelope.triggerRelease(t), this.oscillator.stop(t + this.toSeconds(this.envelope.release));
  }
  getLevelAtTime(t) {
    return t = this.toSeconds(t), this.envelope.getValueAtTime(t);
  }
  dispose() {
    return super.dispose(), this.oscillator.dispose(), this.envelope.dispose(), this.filterEnvelope.dispose(), this.filter.dispose(), this;
  }
}
class Xc extends Zt {
  constructor() {
    const t = L(Xc.getDefaults(), arguments);
    super(t), this.name = "DuoSynth", this.voice0 = new _n(Object.assign(t.voice0, {
      context: this.context,
      onsilence: () => this.onsilence(this)
    })), this.voice1 = new _n(Object.assign(t.voice1, {
      context: this.context
    })), this.harmonicity = new Mt({
      context: this.context,
      units: "positive",
      value: t.harmonicity
    }), this._vibrato = new he({
      frequency: t.vibratoRate,
      context: this.context,
      min: -50,
      max: 50
    }), this._vibrato.start(), this.vibratoRate = this._vibrato.frequency, this._vibratoGain = new j({
      context: this.context,
      units: "normalRange",
      gain: t.vibratoAmount
    }), this.vibratoAmount = this._vibratoGain.gain, this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: 440
    }), this.detune = new Q({
      context: this.context,
      units: "cents",
      value: t.detune
    }), this.frequency.connect(this.voice0.frequency), this.frequency.chain(this.harmonicity, this.voice1.frequency), this._vibrato.connect(this._vibratoGain), this._vibratoGain.fan(this.voice0.detune, this.voice1.detune), this.detune.fan(this.voice0.detune, this.voice1.detune), this.voice0.connect(this.output), this.voice1.connect(this.output), Z(this, [
      "voice0",
      "voice1",
      "frequency",
      "vibratoAmount",
      "vibratoRate"
    ]);
  }
  getLevelAtTime(t) {
    return t = this.toSeconds(t), this.voice0.envelope.getValueAtTime(t) + this.voice1.envelope.getValueAtTime(t);
  }
  static getDefaults() {
    return Le(Zt.getDefaults(), {
      vibratoAmount: 0.5,
      vibratoRate: 5,
      harmonicity: 1.5,
      voice0: Le(Yt(_n.getDefaults(), Object.keys(Zt.getDefaults())), {
        filterEnvelope: {
          attack: 0.01,
          decay: 0,
          sustain: 1,
          release: 0.5
        },
        envelope: {
          attack: 0.01,
          decay: 0,
          sustain: 1,
          release: 0.5
        }
      }),
      voice1: Le(Yt(_n.getDefaults(), Object.keys(Zt.getDefaults())), {
        filterEnvelope: {
          attack: 0.01,
          decay: 0,
          sustain: 1,
          release: 0.5
        },
        envelope: {
          attack: 0.01,
          decay: 0,
          sustain: 1,
          release: 0.5
        }
      })
    });
  }
  /**
   * Trigger the attack portion of the note
   */
  _triggerEnvelopeAttack(t, e) {
    this.voice0._triggerEnvelopeAttack(t, e), this.voice1._triggerEnvelopeAttack(t, e);
  }
  /**
   * Trigger the release portion of the note
   */
  _triggerEnvelopeRelease(t) {
    return this.voice0._triggerEnvelopeRelease(t), this.voice1._triggerEnvelopeRelease(t), this;
  }
  dispose() {
    return super.dispose(), this.voice0.dispose(), this.voice1.dispose(), this.frequency.dispose(), this.detune.dispose(), this._vibrato.dispose(), this.vibratoRate.dispose(), this._vibratoGain.dispose(), this.harmonicity.dispose(), this;
  }
}
class Yc extends ar {
  constructor() {
    const t = L(Yc.getDefaults(), arguments);
    super(t), this.name = "FMSynth", this.modulationIndex = new Mt({
      context: this.context,
      value: t.modulationIndex
    }), this.frequency.connect(this._carrier.frequency), this.frequency.chain(this.harmonicity, this._modulator.frequency), this.frequency.chain(this.modulationIndex, this._modulationNode), this.detune.fan(this._carrier.detune, this._modulator.detune), this._modulator.connect(this._modulationNode.gain), this._modulationNode.connect(this._carrier.frequency), this._carrier.connect(this.output);
  }
  static getDefaults() {
    return Object.assign(ar.getDefaults(), {
      modulationIndex: 10
    });
  }
  dispose() {
    return super.dispose(), this.modulationIndex.dispose(), this;
  }
}
const af = [1, 1.483, 1.932, 2.546, 2.63, 3.897];
class Zc extends Zt {
  constructor() {
    const t = L(Zc.getDefaults(), arguments);
    super(t), this.name = "MetalSynth", this._oscillators = [], this._freqMultipliers = [], this.detune = new Q({
      context: this.context,
      units: "cents",
      value: t.detune
    }), this.frequency = new Q({
      context: this.context,
      units: "frequency"
    }), this._amplitude = new j({
      context: this.context,
      gain: 0
    }).connect(this.output), this._highpass = new Ce({
      // Q: -3.0102999566398125,
      Q: 0,
      context: this.context,
      type: "highpass"
    }).connect(this._amplitude);
    for (let e = 0; e < af.length; e++) {
      const s = new Si({
        context: this.context,
        harmonicity: t.harmonicity,
        modulationIndex: t.modulationIndex,
        modulationType: "square",
        onstop: e === 0 ? () => this.onsilence(this) : st,
        type: "square"
      });
      s.connect(this._highpass), this._oscillators[e] = s;
      const i = new Mt({
        context: this.context,
        value: af[e]
      });
      this._freqMultipliers[e] = i, this.frequency.chain(i, s.frequency), this.detune.connect(s.detune);
    }
    this._filterFreqScaler = new Rs({
      context: this.context,
      max: 7e3,
      min: this.toFrequency(t.resonance)
    }), this.envelope = new Qt({
      attack: t.envelope.attack,
      attackCurve: "linear",
      context: this.context,
      decay: t.envelope.decay,
      release: t.envelope.release,
      sustain: 0
    }), this.envelope.chain(this._filterFreqScaler, this._highpass.frequency), this.envelope.connect(this._amplitude.gain), this._octaves = t.octaves, this.octaves = t.octaves;
  }
  static getDefaults() {
    return Le(Zt.getDefaults(), {
      envelope: Object.assign(Yt(Qt.getDefaults(), Object.keys(B.getDefaults())), {
        attack: 1e-3,
        decay: 1.4,
        release: 0.2
      }),
      harmonicity: 5.1,
      modulationIndex: 32,
      octaves: 1.5,
      resonance: 4e3
    });
  }
  /**
   * Trigger the attack.
   * @param time When the attack should be triggered.
   * @param velocity The velocity that the envelope should be triggered at.
   */
  _triggerEnvelopeAttack(t, e = 1) {
    return this.envelope.triggerAttack(t, e), this._oscillators.forEach((s) => s.start(t)), this.envelope.sustain === 0 && this._oscillators.forEach((s) => {
      s.stop(t + this.toSeconds(this.envelope.attack) + this.toSeconds(this.envelope.decay));
    }), this;
  }
  /**
   * Trigger the release of the envelope.
   * @param time When the release should be triggered.
   */
  _triggerEnvelopeRelease(t) {
    return this.envelope.triggerRelease(t), this._oscillators.forEach((e) => e.stop(t + this.toSeconds(this.envelope.release))), this;
  }
  getLevelAtTime(t) {
    return t = this.toSeconds(t), this.envelope.getValueAtTime(t);
  }
  /**
   * The modulationIndex of the oscillators which make up the source.
   * see {@link FMOscillator.modulationIndex}
   * @min 1
   * @max 100
   */
  get modulationIndex() {
    return this._oscillators[0].modulationIndex.value;
  }
  set modulationIndex(t) {
    this._oscillators.forEach((e) => e.modulationIndex.value = t);
  }
  /**
   * The harmonicity of the oscillators which make up the source.
   * see Tone.FMOscillator.harmonicity
   * @min 0.1
   * @max 10
   */
  get harmonicity() {
    return this._oscillators[0].harmonicity.value;
  }
  set harmonicity(t) {
    this._oscillators.forEach((e) => e.harmonicity.value = t);
  }
  /**
   * The lower level of the highpass filter which is attached to the envelope.
   * This value should be between [0, 7000]
   * @min 0
   * @max 7000
   */
  get resonance() {
    return this._filterFreqScaler.min;
  }
  set resonance(t) {
    this._filterFreqScaler.min = this.toFrequency(t), this.octaves = this._octaves;
  }
  /**
   * The number of octaves above the "resonance" frequency
   * that the filter ramps during the attack/decay envelope
   * @min 0
   * @max 8
   */
  get octaves() {
    return this._octaves;
  }
  set octaves(t) {
    this._octaves = t, this._filterFreqScaler.max = this._filterFreqScaler.min * Math.pow(2, t);
  }
  dispose() {
    return super.dispose(), this._oscillators.forEach((t) => t.dispose()), this._freqMultipliers.forEach((t) => t.dispose()), this.frequency.dispose(), this.detune.dispose(), this._filterFreqScaler.dispose(), this._amplitude.dispose(), this.envelope.dispose(), this._highpass.dispose(), this;
  }
}
class Cr extends Zs {
  constructor() {
    const t = L(Cr.getDefaults(), arguments);
    super(t), this.name = "MembraneSynth", this.portamento = 0, this.pitchDecay = t.pitchDecay, this.octaves = t.octaves, Z(this, ["oscillator", "envelope"]);
  }
  static getDefaults() {
    return Le(Zt.getDefaults(), Zs.getDefaults(), {
      envelope: {
        attack: 1e-3,
        attackCurve: "exponential",
        decay: 0.4,
        release: 1.4,
        sustain: 0.01
      },
      octaves: 10,
      oscillator: {
        type: "sine"
      },
      pitchDecay: 0.05
    });
  }
  setNote(t, e) {
    const s = this.toSeconds(e), i = this.toFrequency(t instanceof ce ? t.toFrequency() : t), r = i * this.octaves;
    return this.oscillator.frequency.setValueAtTime(r, s), this.oscillator.frequency.exponentialRampToValueAtTime(i, s + this.toSeconds(this.pitchDecay)), this;
  }
  dispose() {
    return super.dispose(), this;
  }
}
es([
  wg(0)
], Cr.prototype, "octaves", void 0);
es([
  Ns(0)
], Cr.prototype, "pitchDecay", void 0);
class Kc extends Be {
  constructor() {
    const t = L(Kc.getDefaults(), arguments);
    super(t), this.name = "NoiseSynth", this.noise = new Ys(Object.assign({
      context: this.context
    }, t.noise)), this.envelope = new Mi(Object.assign({
      context: this.context
    }, t.envelope)), this.noise.chain(this.envelope, this.output);
  }
  static getDefaults() {
    return Object.assign(Be.getDefaults(), {
      envelope: Object.assign(Yt(Qt.getDefaults(), Object.keys(B.getDefaults())), {
        decay: 0.1,
        sustain: 0
      }),
      noise: Object.assign(Yt(Ys.getDefaults(), Object.keys(Ft.getDefaults())), {
        type: "white"
      })
    });
  }
  /**
   * Start the attack portion of the envelopes. Unlike other
   * instruments, Tone.NoiseSynth doesn't have a note.
   * @example
   * const noiseSynth = new Tone.NoiseSynth().toDestination();
   * noiseSynth.triggerAttack();
   */
  triggerAttack(t, e = 1) {
    return t = this.toSeconds(t), this.envelope.triggerAttack(t, e), this.noise.start(t), this.envelope.sustain === 0 && this.noise.stop(t + this.toSeconds(this.envelope.attack) + this.toSeconds(this.envelope.decay)), this;
  }
  /**
   * Start the release portion of the envelopes.
   */
  triggerRelease(t) {
    return t = this.toSeconds(t), this.envelope.triggerRelease(t), this.noise.stop(t + this.toSeconds(this.envelope.release)), this;
  }
  sync() {
    return this._syncState() && (this._syncMethod("triggerAttack", 0), this._syncMethod("triggerRelease", 0)), this;
  }
  /**
   * Trigger the attack and then the release after the duration.
   * @param duration The amount of time to hold the note for
   * @param time The time the note should start
   * @param velocity The volume of the note (0-1)
   * @example
   * const noiseSynth = new Tone.NoiseSynth().toDestination();
   * // hold the note for 0.5 seconds
   * noiseSynth.triggerAttackRelease(0.5);
   */
  triggerAttackRelease(t, e, s = 1) {
    return e = this.toSeconds(e), t = this.toSeconds(t), this.triggerAttack(e, s), this.triggerRelease(e + t), this;
  }
  dispose() {
    return super.dispose(), this.noise.dispose(), this.envelope.dispose(), this;
  }
}
const Qc = /* @__PURE__ */ new Set();
function Jc(n) {
  Qc.add(n);
}
function Mg(n, t) {
  const e = (
    /* javascript */
    `registerProcessor("${n}", ${t})`
  );
  Qc.add(e);
}
function hC() {
  return Array.from(Qc).join(`
`);
}
class Ul extends B {
  constructor(t) {
    super(t), this.name = "ToneAudioWorklet", this.workletOptions = {}, this.onprocessorerror = st;
    const e = URL.createObjectURL(new Blob([hC()], { type: "text/javascript" })), s = this._audioWorkletName();
    this._dummyGain = this.context.createGain(), this._dummyParam = this._dummyGain.gain, this.context.addAudioWorkletModule(e).then(() => {
      this.disposed || (this._worklet = this.context.createAudioWorkletNode(s, this.workletOptions), this._worklet.onprocessorerror = this.onprocessorerror.bind(this), this.onReady(this._worklet));
    });
  }
  dispose() {
    return super.dispose(), this._dummyGain.disconnect(), this._worklet && (this._worklet.port.postMessage("dispose"), this._worklet.disconnect()), this;
  }
}
const uC = (
  /* javascript */
  `
	/**
	 * The base AudioWorkletProcessor for use in Tone.js. Works with the {@link ToneAudioWorklet}. 
	 */
	class ToneAudioWorkletProcessor extends AudioWorkletProcessor {

		constructor(options) {
			
			super(options);
			/**
			 * If the processor was disposed or not. Keep alive until it's disposed.
			 */
			this.disposed = false;
		   	/** 
			 * The number of samples in the processing block
			 */
			this.blockSize = 128;
			/**
			 * the sample rate
			 */
			this.sampleRate = sampleRate;

			this.port.onmessage = (event) => {
				// when it receives a dispose 
				if (event.data === "dispose") {
					this.disposed = true;
				}
			};
		}
	}
`
);
Jc(uC);
const dC = (
  /* javascript */
  `
	/**
	 * Abstract class for a single input/output processor. 
	 * has a 'generate' function which processes one sample at a time
	 */
	class SingleIOProcessor extends ToneAudioWorkletProcessor {

		constructor(options) {
			super(Object.assign(options, {
				numberOfInputs: 1,
				numberOfOutputs: 1
			}));
			/**
			 * Holds the name of the parameter and a single value of that
			 * parameter at the current sample
			 * @type { [name: string]: number }
			 */
			this.params = {}
		}

		/**
		 * Generate an output sample from the input sample and parameters
		 * @abstract
		 * @param input number
		 * @param channel number
		 * @param parameters { [name: string]: number }
		 * @returns number
		 */
		generate(){}

		/**
		 * Update the private params object with the 
		 * values of the parameters at the given index
		 * @param parameters { [name: string]: Float32Array },
		 * @param index number
		 */
		updateParams(parameters, index) {
			for (const paramName in parameters) {
				const param = parameters[paramName];
				if (param.length > 1) {
					this.params[paramName] = parameters[paramName][index];
				} else {
					this.params[paramName] = parameters[paramName][0];
				}
			}
		}

		/**
		 * Process a single frame of the audio
		 * @param inputs Float32Array[][]
		 * @param outputs Float32Array[][]
		 */
		process(inputs, outputs, parameters) {
			const input = inputs[0];
			const output = outputs[0];
			// get the parameter values
			const channelCount = Math.max(input && input.length || 0, output.length);
			for (let sample = 0; sample < this.blockSize; sample++) {
				this.updateParams(parameters, sample);
				for (let channel = 0; channel < channelCount; channel++) {
					const inputSample = input && input.length ? input[channel][sample] : 0;
					output[channel][sample] = this.generate(inputSample, channel, this.params);
				}
			}
			return !this.disposed;
		}
	};
`
);
Jc(dC);
const fC = (
  /* javascript */
  `
	/**
	 * A multichannel buffer for use within an AudioWorkletProcessor as a delay line
	 */
	class DelayLine {
		
		constructor(size, channels) {
			this.buffer = [];
			this.writeHead = []
			this.size = size;

			// create the empty channels
			for (let i = 0; i < channels; i++) {
				this.buffer[i] = new Float32Array(this.size);
				this.writeHead[i] = 0;
			}
		}

		/**
		 * Push a value onto the end
		 * @param channel number
		 * @param value number
		 */
		push(channel, value) {
			this.writeHead[channel] += 1;
			if (this.writeHead[channel] > this.size) {
				this.writeHead[channel] = 0;
			}
			this.buffer[channel][this.writeHead[channel]] = value;
		}

		/**
		 * Get the recorded value of the channel given the delay
		 * @param channel number
		 * @param delay number delay samples
		 */
		get(channel, delay) {
			let readHead = this.writeHead[channel] - Math.floor(delay);
			if (readHead < 0) {
				readHead += this.size;
			}
			return this.buffer[channel][readHead];
		}
	}
`
);
Jc(fC);
const kg = "feedback-comb-filter", pC = (
  /* javascript */
  `
	class FeedbackCombFilterWorklet extends SingleIOProcessor {

		constructor(options) {
			super(options);
			this.delayLine = new DelayLine(this.sampleRate, options.channelCount || 2);
		}

		static get parameterDescriptors() {
			return [{
				name: "delayTime",
				defaultValue: 0.1,
				minValue: 0,
				maxValue: 1,
				automationRate: "k-rate"
			}, {
				name: "feedback",
				defaultValue: 0.5,
				minValue: 0,
				maxValue: 0.9999,
				automationRate: "k-rate"
			}];
		}

		generate(input, channel, parameters) {
			const delayedSample = this.delayLine.get(channel, parameters.delayTime * this.sampleRate);
			this.delayLine.push(channel, input + delayedSample * parameters.feedback);
			return delayedSample;
		}
	}
`
);
Mg(kg, pC);
class Ar extends Ul {
  constructor() {
    const t = L(Ar.getDefaults(), arguments, ["delayTime", "resonance"]);
    super(t), this.name = "FeedbackCombFilter", this.input = new j({ context: this.context }), this.output = new j({ context: this.context }), this.delayTime = new tt({
      context: this.context,
      value: t.delayTime,
      units: "time",
      minValue: 0,
      maxValue: 1,
      param: this._dummyParam,
      swappable: !0
    }), this.resonance = new tt({
      context: this.context,
      value: t.resonance,
      units: "normalRange",
      param: this._dummyParam,
      swappable: !0
    }), Z(this, ["resonance", "delayTime"]);
  }
  _audioWorkletName() {
    return kg;
  }
  /**
   * The default parameters
   */
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      delayTime: 0.1,
      resonance: 0.5
    });
  }
  onReady(t) {
    Fe(this.input, t, this.output);
    const e = t.parameters.get("delayTime");
    this.delayTime.setParam(e);
    const s = t.parameters.get("feedback");
    this.resonance.setParam(s);
  }
  dispose() {
    return super.dispose(), this.input.dispose(), this.output.dispose(), this.delayTime.dispose(), this.resonance.dispose(), this;
  }
}
class Er extends B {
  constructor() {
    const t = L(Er.getDefaults(), arguments, ["frequency", "type"]);
    super(t), this.name = "OnePoleFilter", this._frequency = t.frequency, this._type = t.type, this.input = new j({ context: this.context }), this.output = new j({ context: this.context }), this._createFilter();
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      frequency: 880,
      type: "lowpass"
    });
  }
  /**
   * Create a filter and dispose the old one
   */
  _createFilter() {
    const t = this._filter, e = this.toFrequency(this._frequency), s = 1 / (2 * Math.PI * e);
    if (this._type === "lowpass") {
      const i = 1 / (s * this.context.sampleRate), r = i - 1;
      this._filter = this.context.createIIRFilter([i, 0], [1, r]);
    } else {
      const i = 1 / (s * this.context.sampleRate) - 1;
      this._filter = this.context.createIIRFilter([1, -1], [1, i]);
    }
    this.input.chain(this._filter, this.output), t && this.context.setTimeout(() => {
      this.disposed || (this.input.disconnect(t), t.disconnect());
    }, this.blockTime);
  }
  /**
   * The frequency value.
   */
  get frequency() {
    return this._frequency;
  }
  set frequency(t) {
    this._frequency = t, this._createFilter();
  }
  /**
   * The OnePole Filter type, either "highpass" or "lowpass"
   */
  get type() {
    return this._type;
  }
  set type(t) {
    this._type = t, this._createFilter();
  }
  /**
   * Get the frequency response curve. This curve represents how the filter
   * responses to frequencies between 20hz-20khz.
   * @param  len The number of values to return
   * @return The frequency response curve between 20-20kHz
   */
  getFrequencyResponse(t = 128) {
    const e = new Float32Array(t);
    for (let r = 0; r < t; r++) {
      const a = Math.pow(r / t, 2) * 19980 + 20;
      e[r] = a;
    }
    const s = new Float32Array(t), i = new Float32Array(t);
    return this._filter.getFrequencyResponse(e, s, i), s;
  }
  dispose() {
    return super.dispose(), this.input.dispose(), this.output.dispose(), this._filter.disconnect(), this;
  }
}
class Pr extends B {
  constructor() {
    const t = L(Pr.getDefaults(), arguments, ["delayTime", "resonance", "dampening"]);
    super(t), this.name = "LowpassCombFilter", this._combFilter = this.output = new Ar({
      context: this.context,
      delayTime: t.delayTime,
      resonance: t.resonance
    }), this.delayTime = this._combFilter.delayTime, this.resonance = this._combFilter.resonance, this._lowpass = this.input = new Er({
      context: this.context,
      frequency: t.dampening,
      type: "lowpass"
    }), this._lowpass.connect(this._combFilter);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      dampening: 3e3,
      delayTime: 0.1,
      resonance: 0.5
    });
  }
  /**
   * The dampening control of the feedback
   */
  get dampening() {
    return this._lowpass.frequency;
  }
  set dampening(t) {
    this._lowpass.frequency = t;
  }
  dispose() {
    return super.dispose(), this._combFilter.dispose(), this._lowpass.dispose(), this;
  }
}
class th extends Be {
  constructor() {
    const t = L(th.getDefaults(), arguments);
    super(t), this.name = "PluckSynth", this._noise = new Ys({
      context: this.context,
      type: "pink"
    }), this.attackNoise = t.attackNoise, this._lfcf = new Pr({
      context: this.context,
      dampening: t.dampening,
      resonance: t.resonance
    }), this.resonance = t.resonance, this.release = t.release, this._noise.connect(this._lfcf), this._lfcf.connect(this.output);
  }
  static getDefaults() {
    return Le(Be.getDefaults(), {
      attackNoise: 1,
      dampening: 4e3,
      resonance: 0.7,
      release: 1
    });
  }
  /**
   * The dampening control. i.e. the lowpass filter frequency of the comb filter
   * @min 0
   * @max 7000
   */
  get dampening() {
    return this._lfcf.dampening;
  }
  set dampening(t) {
    this._lfcf.dampening = t;
  }
  triggerAttack(t, e) {
    const s = this.toFrequency(t);
    e = this.toSeconds(e);
    const i = 1 / s;
    return this._lfcf.delayTime.setValueAtTime(i, e), this._noise.start(e), this._noise.stop(e + i * this.attackNoise), this._lfcf.resonance.cancelScheduledValues(e), this._lfcf.resonance.setValueAtTime(this.resonance, e), this;
  }
  /**
   * Ramp down the {@link resonance} to 0 over the duration of the release time.
   */
  triggerRelease(t) {
    return this._lfcf.resonance.linearRampTo(0, this.release, t), this;
  }
  dispose() {
    return super.dispose(), this._noise.dispose(), this._lfcf.dispose(), this;
  }
}
class eh extends Be {
  constructor() {
    const t = L(eh.getDefaults(), arguments, ["voice", "options"]);
    super(t), this.name = "PolySynth", this._availableVoices = [], this._activeVoices = [], this._voices = [], this._gcTimeout = -1, this._averageActiveVoices = 0, this._syncedRelease = (i) => this.releaseAll(i), X(!Ie(t.voice), "DEPRECATED: The polyphony count is no longer the first argument.");
    const e = t.voice.getDefaults();
    this.options = Object.assign(e, t.options), this.voice = t.voice, this.maxPolyphony = t.maxPolyphony, this._dummyVoice = this._getNextAvailableVoice();
    const s = this._voices.indexOf(this._dummyVoice);
    this._voices.splice(s, 1), this._gcTimeout = this.context.setInterval(this._collectGarbage.bind(this), 1);
  }
  static getDefaults() {
    return Object.assign(Be.getDefaults(), {
      maxPolyphony: 32,
      options: {},
      voice: Zs
    });
  }
  /**
   * The number of active voices.
   */
  get activeVoices() {
    return this._activeVoices.length;
  }
  /**
   * Invoked when the source is done making sound, so that it can be
   * readded to the pool of available voices
   */
  _makeVoiceAvailable(t) {
    this._availableVoices.push(t);
    const e = this._activeVoices.findIndex((s) => s.voice === t);
    this._activeVoices.splice(e, 1);
  }
  /**
   * Get an available voice from the pool of available voices.
   * If one is not available and the maxPolyphony limit is reached,
   * steal a voice, otherwise return null.
   */
  _getNextAvailableVoice() {
    if (this._availableVoices.length)
      return this._availableVoices.shift();
    if (this._voices.length < this.maxPolyphony) {
      const t = new this.voice(Object.assign(this.options, {
        context: this.context,
        onsilence: this._makeVoiceAvailable.bind(this)
      }));
      return X(t instanceof Zt, "Voice must extend Monophonic class"), t.connect(this.output), this._voices.push(t), t;
    } else
      mi("Max polyphony exceeded. Note dropped.");
  }
  /**
   * Occasionally check if there are any allocated voices which can be cleaned up.
   */
  _collectGarbage() {
    if (this._averageActiveVoices = Math.max(this._averageActiveVoices * 0.95, this.activeVoices), this._availableVoices.length && this._voices.length > Math.ceil(this._averageActiveVoices + 1)) {
      const t = this._availableVoices.shift(), e = this._voices.indexOf(t);
      this._voices.splice(e, 1), this.context.isOffline || t.dispose();
    }
  }
  /**
   * Internal method which triggers the attack
   */
  _triggerAttack(t, e, s) {
    t.forEach((i) => {
      const r = new oi(this.context, i).toMidi(), o = this._getNextAvailableVoice();
      o && (o.triggerAttack(i, e, s), this._activeVoices.push({
        midi: r,
        voice: o,
        released: !1
      }), this.log("triggerAttack", i, e));
    });
  }
  /**
   * Internal method which triggers the release
   */
  _triggerRelease(t, e) {
    t.forEach((s) => {
      const i = new oi(this.context, s).toMidi(), r = this._activeVoices.find(({ midi: o, released: a }) => o === i && !a);
      r && (r.voice.triggerRelease(e), r.released = !0, this.log("triggerRelease", s, e));
    });
  }
  /**
   * Schedule the attack/release events. If the time is in the future, then it should set a timeout
   * to wait for just-in-time scheduling
   */
  _scheduleEvent(t, e, s, i) {
    X(!this.disposed, "Synth was already disposed"), s <= this.now() ? t === "attack" ? this._triggerAttack(e, s, i) : this._triggerRelease(e, s) : this.context.setTimeout(() => {
      this.disposed || this._scheduleEvent(t, e, s, i);
    }, s - this.now());
  }
  /**
   * Trigger the attack portion of the note
   * @param  notes The notes to play. Accepts a single Frequency or an array of frequencies.
   * @param  time  The start time of the note.
   * @param velocity The velocity of the note.
   * @example
   * const synth = new Tone.PolySynth(Tone.FMSynth).toDestination();
   * // trigger a chord immediately with a velocity of 0.2
   * synth.triggerAttack(["Ab3", "C4", "F5"], Tone.now(), 0.2);
   */
  triggerAttack(t, e, s) {
    Array.isArray(t) || (t = [t]);
    const i = this.toSeconds(e);
    return this._scheduleEvent("attack", t, i, s), this;
  }
  /**
   * Trigger the release of the note. Unlike monophonic instruments,
   * a note (or array of notes) needs to be passed in as the first argument.
   * @param  notes The notes to play. Accepts a single Frequency or an array of frequencies.
   * @param  time  When the release will be triggered.
   * @example
   * const poly = new Tone.PolySynth(Tone.AMSynth).toDestination();
   * poly.triggerAttack(["Ab3", "C4", "F5"]);
   * // trigger the release of the given notes.
   * poly.triggerRelease(["Ab3", "C4"], "+1");
   * poly.triggerRelease("F5", "+3");
   */
  triggerRelease(t, e) {
    Array.isArray(t) || (t = [t]);
    const s = this.toSeconds(e);
    return this._scheduleEvent("release", t, s), this;
  }
  /**
   * Trigger the attack and release after the specified duration
   * @param  notes The notes to play. Accepts a single  Frequency or an array of frequencies.
   * @param  duration the duration of the note
   * @param  time  if no time is given, defaults to now
   * @param  velocity the velocity of the attack (0-1)
   * @example
   * const poly = new Tone.PolySynth(Tone.AMSynth).toDestination();
   * // can pass in an array of durations as well
   * poly.triggerAttackRelease(["Eb3", "G4", "Bb4", "D5"], [4, 3, 2, 1]);
   */
  triggerAttackRelease(t, e, s, i) {
    const r = this.toSeconds(s);
    if (this.triggerAttack(t, r, i), Kt(e)) {
      X(Kt(t), "If the duration is an array, the notes must also be an array"), t = t;
      for (let o = 0; o < t.length; o++) {
        const a = e[Math.min(o, e.length - 1)], l = this.toSeconds(a);
        X(l > 0, "The duration must be greater than 0"), this.triggerRelease(t[o], r + l);
      }
    } else {
      const o = this.toSeconds(e);
      X(o > 0, "The duration must be greater than 0"), this.triggerRelease(t, r + o);
    }
    return this;
  }
  sync() {
    return this._syncState() && (this._syncMethod("triggerAttack", 1), this._syncMethod("triggerRelease", 1), this.context.transport.on("stop", this._syncedRelease), this.context.transport.on("pause", this._syncedRelease), this.context.transport.on("loopEnd", this._syncedRelease)), this;
  }
  /**
   * Set a member/attribute of the voices
   * @example
   * const poly = new Tone.PolySynth().toDestination();
   * // set all of the voices using an options object for the synth type
   * poly.set({
   * 	envelope: {
   * 		attack: 0.25
   * 	}
   * });
   * poly.triggerAttackRelease("Bb3", 0.2);
   */
  set(t) {
    const e = Yt(t, [
      "onsilence",
      "context"
    ]);
    return this.options = Le(this.options, e), this._voices.forEach((s) => s.set(e)), this._dummyVoice.set(e), this;
  }
  get() {
    return this._dummyVoice.get();
  }
  /**
   * Trigger the release portion of all the currently active voices immediately.
   * Useful for silencing the synth.
   */
  releaseAll(t) {
    const e = this.toSeconds(t);
    return this._activeVoices.forEach(({ voice: s }) => {
      s.triggerRelease(e);
    }), this;
  }
  dispose() {
    return super.dispose(), this._dummyVoice.dispose(), this._voices.forEach((t) => t.dispose()), this._activeVoices = [], this._availableVoices = [], this.context.clearInterval(this._gcTimeout), this;
  }
}
class kn extends Be {
  constructor() {
    const t = L(kn.getDefaults(), arguments, ["urls", "onload", "baseUrl"], "urls");
    super(t), this.name = "Sampler", this._activeSources = /* @__PURE__ */ new Map();
    const e = {};
    Object.keys(t.urls).forEach((s) => {
      const i = parseInt(s, 10);
      if (X(Ui(s) || Ie(i) && isFinite(i), `url key is neither a note or midi pitch: ${s}`), Ui(s)) {
        const r = new ce(this.context, s).toMidi();
        e[r] = t.urls[s];
      } else Ie(i) && isFinite(i) && (e[i] = t.urls[i]);
    }), this._buffers = new bi({
      urls: e,
      onload: t.onload,
      baseUrl: t.baseUrl,
      onerror: t.onerror
    }), this.attack = t.attack, this.release = t.release, this.curve = t.curve, this._buffers.loaded && Promise.resolve().then(t.onload);
  }
  static getDefaults() {
    return Object.assign(Be.getDefaults(), {
      attack: 0,
      baseUrl: "",
      curve: "exponential",
      onload: st,
      onerror: st,
      release: 0.1,
      urls: {}
    });
  }
  /**
   * Returns the difference in steps between the given midi note at the closets sample.
   */
  _findClosest(t) {
    let s = 0;
    for (; s < 96; ) {
      if (this._buffers.has(t + s))
        return -s;
      if (this._buffers.has(t - s))
        return s;
      s++;
    }
    throw new Error(`No available buffers for note: ${t}`);
  }
  /**
   * @param  notes	The note to play, or an array of notes.
   * @param  time     When to play the note
   * @param  velocity The velocity to play the sample back.
   */
  triggerAttack(t, e, s = 1) {
    return this.log("triggerAttack", t, e, s), Array.isArray(t) || (t = [t]), t.forEach((i) => {
      const r = vg(new ce(this.context, i).toFrequency()), o = Math.round(r), a = r - o, l = this._findClosest(o), c = o - l, h = this._buffers.get(c), u = ii(l + a), d = new tn({
        url: h,
        context: this.context,
        curve: this.curve,
        fadeIn: this.attack,
        fadeOut: this.release,
        playbackRate: u
      }).connect(this.output);
      d.start(e, 0, h.duration / u, s), Kt(this._activeSources.get(o)) || this._activeSources.set(o, []), this._activeSources.get(o).push(d), d.onended = () => {
        if (this._activeSources && this._activeSources.has(o)) {
          const f = this._activeSources.get(o), p = f.indexOf(d);
          p !== -1 && f.splice(p, 1);
        }
      };
    }), this;
  }
  /**
   * @param  notes	The note to release, or an array of notes.
   * @param  time     	When to release the note.
   */
  triggerRelease(t, e) {
    return this.log("triggerRelease", t, e), Array.isArray(t) || (t = [t]), t.forEach((s) => {
      const i = new ce(this.context, s).toMidi();
      if (this._activeSources.has(i) && this._activeSources.get(i).length) {
        const r = this._activeSources.get(i);
        e = this.toSeconds(e), r.forEach((o) => {
          o.stop(e);
        }), this._activeSources.set(i, []);
      }
    }), this;
  }
  /**
   * Release all currently active notes.
   * @param  time     	When to release the notes.
   */
  releaseAll(t) {
    const e = this.toSeconds(t);
    return this._activeSources.forEach((s) => {
      for (; s.length; )
        s.shift().stop(e);
    }), this;
  }
  sync() {
    return this._syncState() && (this._syncMethod("triggerAttack", 1), this._syncMethod("triggerRelease", 1)), this;
  }
  /**
   * Invoke the attack phase, then after the duration, invoke the release.
   * @param  notes	The note to play and release, or an array of notes.
   * @param  duration The time the note should be held
   * @param  time     When to start the attack
   * @param  velocity The velocity of the attack
   */
  triggerAttackRelease(t, e, s, i = 1) {
    const r = this.toSeconds(s);
    return this.triggerAttack(t, r, i), Kt(e) ? (X(Kt(t), "notes must be an array when duration is array"), t.forEach((o, a) => {
      const l = e[Math.min(a, e.length - 1)];
      this.triggerRelease(o, r + this.toSeconds(l));
    })) : this.triggerRelease(t, r + this.toSeconds(e)), this;
  }
  /**
   * Add a note to the sampler.
   * @param  note      The buffer's pitch.
   * @param  url  Either the url of the buffer, or a buffer which will be added with the given name.
   * @param  callback  The callback to invoke when the url is loaded.
   */
  add(t, e, s) {
    if (X(Ui(t) || isFinite(t), `note must be a pitch or midi: ${t}`), Ui(t)) {
      const i = new ce(this.context, t).toMidi();
      this._buffers.add(i, e, s);
    } else
      this._buffers.add(t, e, s);
    return this;
  }
  /**
   * If the buffers are loaded or not
   */
  get loaded() {
    return this._buffers.loaded;
  }
  /**
   * Clean up
   */
  dispose() {
    return super.dispose(), this._buffers.dispose(), this._activeSources.forEach((t) => {
      t.forEach((e) => e.dispose());
    }), this._activeSources.clear(), this;
  }
}
es([
  Ns(0)
], kn.prototype, "attack", void 0);
es([
  Ns(0)
], kn.prototype, "release", void 0);
class ls extends Xt {
  constructor() {
    const t = L(ls.getDefaults(), arguments, ["callback", "value"]);
    super(t), this.name = "ToneEvent", this._state = new _i("stopped"), this._startOffset = 0, this._loop = t.loop, this.callback = t.callback, this.value = t.value, this._loopStart = this.toTicks(t.loopStart), this._loopEnd = this.toTicks(t.loopEnd), this._playbackRate = t.playbackRate, this._probability = t.probability, this._humanize = t.humanize, this.mute = t.mute, this._playbackRate = t.playbackRate, this._state.increasing = !0, this._rescheduleEvents();
  }
  static getDefaults() {
    return Object.assign(Xt.getDefaults(), {
      callback: st,
      humanize: !1,
      loop: !1,
      loopEnd: "1m",
      loopStart: 0,
      mute: !1,
      playbackRate: 1,
      probability: 1,
      value: null
    });
  }
  /**
   * Reschedule all of the events along the timeline
   * with the updated values.
   * @param after Only reschedules events after the given time.
   */
  _rescheduleEvents(t = -1) {
    this._state.forEachFrom(t, (e) => {
      let s;
      if (e.state === "started") {
        e.id !== -1 && this.context.transport.clear(e.id);
        const i = e.time + Math.round(this.startOffset / this._playbackRate);
        if (this._loop === !0 || Ie(this._loop) && this._loop > 1) {
          s = 1 / 0, Ie(this._loop) && (s = this._loop * this._getLoopDuration());
          const r = this._state.getAfter(i);
          r !== null && (s = Math.min(s, r.time - i)), s !== 1 / 0 && (s = new St(this.context, s));
          const o = new St(this.context, this._getLoopDuration());
          e.id = this.context.transport.scheduleRepeat(this._tick.bind(this), o, new St(this.context, i), s);
        } else
          e.id = this.context.transport.schedule(this._tick.bind(this), new St(this.context, i));
      }
    });
  }
  /**
   * Returns the playback state of the note, either "started" or "stopped".
   */
  get state() {
    return this._state.getValueAtTime(this.context.transport.ticks);
  }
  /**
   * The start from the scheduled start time.
   */
  get startOffset() {
    return this._startOffset;
  }
  set startOffset(t) {
    this._startOffset = t;
  }
  /**
   * The probability of the notes being triggered.
   */
  get probability() {
    return this._probability;
  }
  set probability(t) {
    this._probability = t;
  }
  /**
   * If set to true, will apply small random variation
   * to the callback time. If the value is given as a time, it will randomize
   * by that amount.
   * @example
   * const event = new Tone.ToneEvent();
   * event.humanize = true;
   */
  get humanize() {
    return this._humanize;
  }
  set humanize(t) {
    this._humanize = t;
  }
  /**
   * Start the note at the given time.
   * @param  time  When the event should start.
   */
  start(t) {
    const e = this.toTicks(t);
    return this._state.getValueAtTime(e) === "stopped" && (this._state.add({
      id: -1,
      state: "started",
      time: e
    }), this._rescheduleEvents(e)), this;
  }
  /**
   * Stop the Event at the given time.
   * @param  time  When the event should stop.
   */
  stop(t) {
    this.cancel(t);
    const e = this.toTicks(t);
    if (this._state.getValueAtTime(e) === "started") {
      this._state.setStateAtTime("stopped", e, { id: -1 });
      const s = this._state.getBefore(e);
      let i = e;
      s !== null && (i = s.time), this._rescheduleEvents(i);
    }
    return this;
  }
  /**
   * Cancel all scheduled events greater than or equal to the given time
   * @param  time  The time after which events will be cancel.
   */
  cancel(t) {
    t = Ve(t, -1 / 0);
    const e = this.toTicks(t);
    return this._state.forEachFrom(e, (s) => {
      this.context.transport.clear(s.id);
    }), this._state.cancel(e), this;
  }
  /**
   * The callback function invoker. Also
   * checks if the Event is done playing
   * @param  time  The time of the event in seconds
   */
  _tick(t) {
    const e = this.context.transport.getTicksAtTime(t);
    if (!this.mute && this._state.getValueAtTime(e) === "started") {
      if (this.probability < 1 && Math.random() > this.probability)
        return;
      if (this.humanize) {
        let s = 0.02;
        Pc(this.humanize) || (s = this.toSeconds(this.humanize)), t += (Math.random() * 2 - 1) * s;
      }
      this.callback(t, this.value);
    }
  }
  /**
   * Get the duration of the loop.
   */
  _getLoopDuration() {
    return (this._loopEnd - this._loopStart) / this._playbackRate;
  }
  /**
   * If the note should loop or not
   * between ToneEvent.loopStart and
   * ToneEvent.loopEnd. If set to true,
   * the event will loop indefinitely,
   * if set to a number greater than 1
   * it will play a specific number of
   * times, if set to false, 0 or 1, the
   * part will only play once.
   */
  get loop() {
    return this._loop;
  }
  set loop(t) {
    this._loop = t, this._rescheduleEvents();
  }
  /**
   * The playback rate of the event. Defaults to 1.
   * @example
   * const note = new Tone.ToneEvent();
   * note.loop = true;
   * // repeat the note twice as fast
   * note.playbackRate = 2;
   */
  get playbackRate() {
    return this._playbackRate;
  }
  set playbackRate(t) {
    this._playbackRate = t, this._rescheduleEvents();
  }
  /**
   * The loopEnd point is the time the event will loop
   * if ToneEvent.loop is true.
   */
  get loopEnd() {
    return new St(this.context, this._loopEnd).toSeconds();
  }
  set loopEnd(t) {
    this._loopEnd = this.toTicks(t), this._loop && this._rescheduleEvents();
  }
  /**
   * The time when the loop should start.
   */
  get loopStart() {
    return new St(this.context, this._loopStart).toSeconds();
  }
  set loopStart(t) {
    this._loopStart = this.toTicks(t), this._loop && this._rescheduleEvents();
  }
  /**
   * The current progress of the loop interval.
   * Returns 0 if the event is not started yet or
   * it is not set to loop.
   */
  get progress() {
    if (this._loop) {
      const t = this.context.transport.ticks, e = this._state.get(t);
      if (e !== null && e.state === "started") {
        const s = this._getLoopDuration();
        return (t - e.time) % s / s;
      } else
        return 0;
    } else
      return 0;
  }
  dispose() {
    return super.dispose(), this.cancel(), this._state.dispose(), this;
  }
}
class hr extends Xt {
  constructor() {
    const t = L(hr.getDefaults(), arguments, [
      "callback",
      "interval"
    ]);
    super(t), this.name = "Loop", this._event = new ls({
      context: this.context,
      callback: this._tick.bind(this),
      loop: !0,
      loopEnd: t.interval,
      playbackRate: t.playbackRate,
      probability: t.probability,
      humanize: t.humanize
    }), this.callback = t.callback, this.iterations = t.iterations;
  }
  static getDefaults() {
    return Object.assign(Xt.getDefaults(), {
      interval: "4n",
      callback: st,
      playbackRate: 1,
      iterations: 1 / 0,
      probability: 1,
      mute: !1,
      humanize: !1
    });
  }
  /**
   * Start the loop at the specified time along the Transport's timeline.
   * @param  time  When to start the Loop.
   */
  start(t) {
    return this._event.start(t), this;
  }
  /**
   * Stop the loop at the given time.
   * @param  time  When to stop the Loop.
   */
  stop(t) {
    return this._event.stop(t), this;
  }
  /**
   * Cancel all scheduled events greater than or equal to the given time
   * @param  time  The time after which events will be cancel.
   */
  cancel(t) {
    return this._event.cancel(t), this;
  }
  /**
   * Internal function called when the notes should be called
   * @param time  The time the event occurs
   */
  _tick(t) {
    this.callback(t);
  }
  /**
   * The state of the Loop, either started or stopped.
   */
  get state() {
    return this._event.state;
  }
  /**
   * The progress of the loop as a value between 0-1. 0, when the loop is stopped or done iterating.
   */
  get progress() {
    return this._event.progress;
  }
  /**
   * The time between successive callbacks.
   * @example
   * const loop = new Tone.Loop();
   * loop.interval = "8n"; // loop every 8n
   */
  get interval() {
    return this._event.loopEnd;
  }
  set interval(t) {
    this._event.loopEnd = t;
  }
  /**
   * The playback rate of the loop. The normal playback rate is 1 (no change).
   * A `playbackRate` of 2 would be twice as fast.
   */
  get playbackRate() {
    return this._event.playbackRate;
  }
  set playbackRate(t) {
    this._event.playbackRate = t;
  }
  /**
   * Random variation +/-0.01s to the scheduled time.
   * Or give it a time value which it will randomize by.
   */
  get humanize() {
    return this._event.humanize;
  }
  set humanize(t) {
    this._event.humanize = t;
  }
  /**
   * The probably of the callback being invoked.
   */
  get probability() {
    return this._event.probability;
  }
  set probability(t) {
    this._event.probability = t;
  }
  /**
   * Muting the Loop means that no callbacks are invoked.
   */
  get mute() {
    return this._event.mute;
  }
  set mute(t) {
    this._event.mute = t;
  }
  /**
   * The number of iterations of the loop. The default value is `Infinity` (loop forever).
   */
  get iterations() {
    return this._event.loop === !0 ? 1 / 0 : this._event.loop;
  }
  set iterations(t) {
    t === 1 / 0 ? this._event.loop = !0 : this._event.loop = t;
  }
  dispose() {
    return super.dispose(), this._event.dispose(), this;
  }
}
class ai extends ls {
  constructor() {
    const t = L(ai.getDefaults(), arguments, [
      "callback",
      "events"
    ]);
    super(t), this.name = "Part", this._state = new _i("stopped"), this._events = /* @__PURE__ */ new Set(), this._state.increasing = !0, t.events.forEach((e) => {
      Kt(e) ? this.add(e[0], e[1]) : this.add(e);
    });
  }
  static getDefaults() {
    return Object.assign(ls.getDefaults(), {
      events: []
    });
  }
  /**
   * Start the part at the given time.
   * @param  time    When to start the part.
   * @param  offset  The offset from the start of the part to begin playing at.
   */
  start(t, e) {
    const s = this.toTicks(t);
    if (this._state.getValueAtTime(s) !== "started") {
      e = Ve(e, this._loop ? this._loopStart : 0), this._loop ? e = Ve(e, this._loopStart) : e = Ve(e, 0);
      const i = this.toTicks(e);
      this._state.add({
        id: -1,
        offset: i,
        state: "started",
        time: s
      }), this._forEach((r) => {
        this._startNote(r, s, i);
      });
    }
    return this;
  }
  /**
   * Start the event in the given event at the correct time given
   * the ticks and offset and looping.
   * @param  event
   * @param  ticks
   * @param  offset
   */
  _startNote(t, e, s) {
    e -= s, this._loop ? t.startOffset >= this._loopStart && t.startOffset < this._loopEnd ? (t.startOffset < s && (e += this._getLoopDuration()), t.start(new St(this.context, e))) : t.startOffset < this._loopStart && t.startOffset >= s && (t.loop = !1, t.start(new St(this.context, e))) : t.startOffset >= s && t.start(new St(this.context, e));
  }
  get startOffset() {
    return this._startOffset;
  }
  set startOffset(t) {
    this._startOffset = t, this._forEach((e) => {
      e.startOffset += this._startOffset;
    });
  }
  /**
   * Stop the part at the given time.
   * @param  time  When to stop the part.
   */
  stop(t) {
    const e = this.toTicks(t);
    return this._state.cancel(e), this._state.setStateAtTime("stopped", e), this._forEach((s) => {
      s.stop(t);
    }), this;
  }
  /**
   * Get/Set an Event's value at the given time.
   * If a value is passed in and no event exists at
   * the given time, one will be created with that value.
   * If two events are at the same time, the first one will
   * be returned.
   * @example
   * const part = new Tone.Part();
   * part.at("1m"); // returns the part at the first measure
   * part.at("2m", "C2"); // set the value at "2m" to C2.
   * // if an event didn't exist at that time, it will be created.
   * @param time The time of the event to get or set.
   * @param value If a value is passed in, the value of the event at the given time will be set to it.
   */
  at(t, e) {
    const s = new Lt(this.context, t).toTicks(), i = new St(this.context, 1).toSeconds(), r = this._events.values();
    let o = r.next();
    for (; !o.done; ) {
      const a = o.value;
      if (Math.abs(s - a.startOffset) < i)
        return et(e) && (a.value = e), a;
      o = r.next();
    }
    return et(e) ? (this.add(t, e), this.at(t)) : null;
  }
  add(t, e) {
    t instanceof Object && Reflect.has(t, "time") && (e = t, t = e.time);
    const s = this.toTicks(t);
    let i;
    return e instanceof ls ? (i = e, i.callback = this._tick.bind(this)) : i = new ls({
      callback: this._tick.bind(this),
      context: this.context,
      value: e
    }), i.startOffset = s, i.set({
      humanize: this.humanize,
      loop: this.loop,
      loopEnd: this.loopEnd,
      loopStart: this.loopStart,
      playbackRate: this.playbackRate,
      probability: this.probability
    }), this._events.add(i), this._restartEvent(i), this;
  }
  /**
   * Restart the given event
   */
  _restartEvent(t) {
    this._state.forEach((e) => {
      e.state === "started" ? this._startNote(t, e.time, e.offset) : t.stop(new St(this.context, e.time));
    });
  }
  remove(t, e) {
    return Es(t) && t.hasOwnProperty("time") && (e = t, t = e.time), t = this.toTicks(t), this._events.forEach((s) => {
      s.startOffset === t && (ve(e) || et(e) && s.value === e) && (this._events.delete(s), s.dispose());
    }), this;
  }
  /**
   * Remove all of the notes from the group.
   */
  clear() {
    return this._forEach((t) => t.dispose()), this._events.clear(), this;
  }
  /**
   * Cancel scheduled state change events: i.e. "start" and "stop".
   * @param after The time after which to cancel the scheduled events.
   */
  cancel(t) {
    return this._forEach((e) => e.cancel(t)), this._state.cancel(this.toTicks(t)), this;
  }
  /**
   * Iterate over all of the events
   */
  _forEach(t) {
    return this._events && this._events.forEach((e) => {
      e instanceof ai ? e._forEach(t) : t(e);
    }), this;
  }
  /**
   * Set the attribute of all of the events
   * @param  attr  the attribute to set
   * @param  value      The value to set it to
   */
  _setAll(t, e) {
    this._forEach((s) => {
      s[t] = e;
    });
  }
  /**
   * Internal tick method
   * @param  time  The time of the event in seconds
   */
  _tick(t, e) {
    this.mute || this.callback(t, e);
  }
  /**
   * Determine if the event should be currently looping
   * given the loop boundries of this Part.
   * @param  event  The event to test
   */
  _testLoopBoundries(t) {
    this._loop && (t.startOffset < this._loopStart || t.startOffset >= this._loopEnd) ? t.cancel(0) : t.state === "stopped" && this._restartEvent(t);
  }
  get probability() {
    return this._probability;
  }
  set probability(t) {
    this._probability = t, this._setAll("probability", t);
  }
  get humanize() {
    return this._humanize;
  }
  set humanize(t) {
    this._humanize = t, this._setAll("humanize", t);
  }
  /**
   * If the part should loop or not
   * between Part.loopStart and
   * Part.loopEnd. If set to true,
   * the part will loop indefinitely,
   * if set to a number greater than 1
   * it will play a specific number of
   * times, if set to false, 0 or 1, the
   * part will only play once.
   * @example
   * const part = new Tone.Part();
   * // loop the part 8 times
   * part.loop = 8;
   */
  get loop() {
    return this._loop;
  }
  set loop(t) {
    this._loop = t, this._forEach((e) => {
      e.loopStart = this.loopStart, e.loopEnd = this.loopEnd, e.loop = t, this._testLoopBoundries(e);
    });
  }
  /**
   * The loopEnd point determines when it will
   * loop if Part.loop is true.
   */
  get loopEnd() {
    return new St(this.context, this._loopEnd).toSeconds();
  }
  set loopEnd(t) {
    this._loopEnd = this.toTicks(t), this._loop && this._forEach((e) => {
      e.loopEnd = t, this._testLoopBoundries(e);
    });
  }
  /**
   * The loopStart point determines when it will
   * loop if Part.loop is true.
   */
  get loopStart() {
    return new St(this.context, this._loopStart).toSeconds();
  }
  set loopStart(t) {
    this._loopStart = this.toTicks(t), this._loop && this._forEach((e) => {
      e.loopStart = this.loopStart, this._testLoopBoundries(e);
    });
  }
  /**
   * The playback rate of the part
   */
  get playbackRate() {
    return this._playbackRate;
  }
  set playbackRate(t) {
    this._playbackRate = t, this._setAll("playbackRate", t);
  }
  /**
   * The number of scheduled notes in the part.
   */
  get length() {
    return this._events.size;
  }
  dispose() {
    return super.dispose(), this.clear(), this;
  }
}
function* mC(n) {
  let t = 0;
  for (; t < n; )
    t = En(t, 0, n - 1), yield t, t++;
}
function* gC(n) {
  let t = n - 1;
  for (; t >= 0; )
    t = En(t, 0, n - 1), yield t, t--;
}
function* Li(n, t) {
  for (; ; )
    yield* t(n);
}
function* lf(n, t) {
  let e = t ? 0 : n - 1;
  for (; ; )
    e = En(e, 0, n - 1), yield e, t ? (e++, e >= n - 1 && (t = !1)) : (e--, e <= 0 && (t = !0));
}
function* yC(n) {
  let t = 0, e = 0;
  for (; t < n; )
    t = En(t, 0, n - 1), yield t, e++, t += e % 2 ? 2 : -1;
}
function* xC(n) {
  let t = n - 1, e = 0;
  for (; t >= 0; )
    t = En(t, 0, n - 1), yield t, e++, t += e % 2 ? -2 : 1;
}
function* _C(n) {
  for (; ; )
    yield Math.floor(Math.random() * n);
}
function* vC(n) {
  const t = [];
  for (let e = 0; e < n; e++)
    t.push(e);
  for (; t.length > 0; ) {
    const e = t.splice(Math.floor(t.length * Math.random()), 1);
    yield En(e[0], 0, n - 1);
  }
}
function* bC(n) {
  let t = Math.floor(Math.random() * n);
  for (; ; )
    t === 0 ? t++ : t === n - 1 || Math.random() < 0.5 ? t-- : t++, yield t;
}
function* cf(n, t = "up", e = 0) {
  switch (X(n >= 1, "The number of values must be at least one"), t) {
    case "up":
      yield* Li(n, mC);
    case "down":
      yield* Li(n, gC);
    case "upDown":
      yield* lf(n, !0);
    case "downUp":
      yield* lf(n, !1);
    case "alternateUp":
      yield* Li(n, yC);
    case "alternateDown":
      yield* Li(n, xC);
    case "random":
      yield* _C(n);
    case "randomOnce":
      yield* Li(n, vC);
    case "randomWalk":
      yield* bC(n);
  }
}
class sh extends hr {
  constructor() {
    const t = L(sh.getDefaults(), arguments, [
      "callback",
      "values",
      "pattern"
    ]);
    super(t), this.name = "Pattern", this.callback = t.callback, this._values = t.values, this._pattern = cf(t.values.length, t.pattern), this._type = t.pattern;
  }
  static getDefaults() {
    return Object.assign(hr.getDefaults(), {
      pattern: "up",
      values: [],
      callback: st
    });
  }
  /**
   * Internal function called when the notes should be called
   */
  _tick(t) {
    const e = this._pattern.next();
    this._index = e.value, this._value = this._values[e.value], this.callback(t, this._value);
  }
  /**
   * The array of events.
   */
  get values() {
    return this._values;
  }
  set values(t) {
    this._values = t, this.pattern = this._type;
  }
  /**
   * The current value of the pattern.
   */
  get value() {
    return this._value;
  }
  /**
   * The current index of the pattern.
   */
  get index() {
    return this._index;
  }
  /**
   * The pattern type.
   */
  get pattern() {
    return this._type;
  }
  set pattern(t) {
    this._type = t, this._pattern = cf(this._values.length, this._type);
  }
}
class nh extends ls {
  constructor() {
    const t = L(nh.getDefaults(), arguments, ["callback", "events", "subdivision"]);
    super(t), this.name = "Sequence", this._part = new ai({
      callback: this._seqCallback.bind(this),
      context: this.context
    }), this._events = [], this._eventsArray = [], this._subdivision = this.toTicks(t.subdivision), this.events = t.events, this.loop = t.loop, this.loopStart = t.loopStart, this.loopEnd = t.loopEnd, this.playbackRate = t.playbackRate, this.probability = t.probability, this.humanize = t.humanize, this.mute = t.mute, this.playbackRate = t.playbackRate;
  }
  static getDefaults() {
    return Object.assign(Yt(ls.getDefaults(), ["value"]), {
      events: [],
      loop: !0,
      loopEnd: 0,
      loopStart: 0,
      subdivision: "8n"
    });
  }
  /**
   * The internal callback for when an event is invoked
   */
  _seqCallback(t, e) {
    e !== null && !this.mute && this.callback(t, e);
  }
  /**
   * The sequence
   */
  get events() {
    return this._events;
  }
  set events(t) {
    this.clear(), this._eventsArray = t, this._events = this._createSequence(this._eventsArray), this._eventsUpdated();
  }
  /**
   * Start the part at the given time.
   * @param  time    When to start the part.
   * @param  offset  The offset index to start at
   */
  start(t, e) {
    return this._part.start(t, e && this._indexTime(e)), this;
  }
  /**
   * Stop the part at the given time.
   * @param  time  When to stop the part.
   */
  stop(t) {
    return this._part.stop(t), this;
  }
  /**
   * The subdivision of the sequence. This can only be
   * set in the constructor. The subdivision is the
   * interval between successive steps.
   */
  get subdivision() {
    return new St(this.context, this._subdivision).toSeconds();
  }
  /**
   * Create a sequence proxy which can be monitored to create subsequences
   */
  _createSequence(t) {
    return new Proxy(t, {
      get: (e, s) => e[s],
      set: (e, s, i) => (Qe(s) && isFinite(parseInt(s, 10)) && Kt(i) ? e[s] = this._createSequence(i) : e[s] = i, this._eventsUpdated(), !0)
    });
  }
  /**
   * When the sequence has changed, all of the events need to be recreated
   */
  _eventsUpdated() {
    this._part.clear(), this._rescheduleSequence(this._eventsArray, this._subdivision, this.startOffset), this.loopEnd = this.loopEnd;
  }
  /**
   * reschedule all of the events that need to be rescheduled
   */
  _rescheduleSequence(t, e, s) {
    t.forEach((i, r) => {
      const o = r * e + s;
      if (Kt(i))
        this._rescheduleSequence(i, e / i.length, o);
      else {
        const a = new St(this.context, o, "i").toSeconds();
        this._part.add(a, i);
      }
    });
  }
  /**
   * Get the time of the index given the Sequence's subdivision
   * @param  index
   * @return The time of that index
   */
  _indexTime(t) {
    return new St(this.context, t * this._subdivision + this.startOffset).toSeconds();
  }
  /**
   * Clear all of the events
   */
  clear() {
    return this._part.clear(), this;
  }
  dispose() {
    return super.dispose(), this._part.dispose(), this;
  }
  //-------------------------------------
  // PROXY CALLS
  //-------------------------------------
  get loop() {
    return this._part.loop;
  }
  set loop(t) {
    this._part.loop = t;
  }
  /**
   * The index at which the sequence should start looping
   */
  get loopStart() {
    return this._loopStart;
  }
  set loopStart(t) {
    this._loopStart = t, this._part.loopStart = this._indexTime(t);
  }
  /**
   * The index at which the sequence should end looping
   */
  get loopEnd() {
    return this._loopEnd;
  }
  set loopEnd(t) {
    this._loopEnd = t, t === 0 ? this._part.loopEnd = this._indexTime(this._eventsArray.length) : this._part.loopEnd = this._indexTime(t);
  }
  get startOffset() {
    return this._part.startOffset;
  }
  set startOffset(t) {
    this._part.startOffset = t;
  }
  get playbackRate() {
    return this._part.playbackRate;
  }
  set playbackRate(t) {
    this._part.playbackRate = t;
  }
  get probability() {
    return this._part.probability;
  }
  set probability(t) {
    this._part.probability = t;
  }
  get progress() {
    return this._part.progress;
  }
  get humanize() {
    return this._part.humanize;
  }
  set humanize(t) {
    this._part.humanize = t;
  }
  /**
   * The number of scheduled events
   */
  get length() {
    return this._part.length;
  }
}
class ki extends B {
  constructor() {
    const t = L(ki.getDefaults(), arguments, ["fade"]);
    super(t), this.name = "CrossFade", this._panner = this.context.createStereoPanner(), this._split = this.context.createChannelSplitter(2), this._g2a = new Tg({ context: this.context }), this.a = new j({
      context: this.context,
      gain: 0
    }), this.b = new j({
      context: this.context,
      gain: 0
    }), this.output = new j({ context: this.context }), this._internalChannels = [this.a, this.b], this.fade = new Q({
      context: this.context,
      units: "normalRange",
      value: t.fade
    }), Z(this, "fade"), this.context.getConstant(1).connect(this._panner), this._panner.connect(this._split), this._panner.channelCount = 1, this._panner.channelCountMode = "explicit", ue(this._split, this.a.gain, 0), ue(this._split, this.b.gain, 1), this.fade.chain(this._g2a, this._panner.pan), this.a.connect(this.output), this.b.connect(this.output);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      fade: 0.5
    });
  }
  dispose() {
    return super.dispose(), this.a.dispose(), this.b.dispose(), this.output.dispose(), this.fade.dispose(), this._g2a.dispose(), this._panner.disconnect(), this._split.disconnect(), this;
  }
}
class Ut extends B {
  constructor(t) {
    super(t), this.name = "Effect", this._dryWet = new ki({ context: this.context }), this.wet = this._dryWet.fade, this.effectSend = new j({ context: this.context }), this.effectReturn = new j({ context: this.context }), this.input = new j({ context: this.context }), this.output = this._dryWet, this.input.fan(this._dryWet.a, this.effectSend), this.effectReturn.connect(this._dryWet.b), this.wet.setValueAtTime(t.wet, 0), this._internalChannels = [this.effectReturn, this.effectSend], Z(this, "wet");
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      wet: 1
    });
  }
  /**
   * chains the effect in between the effectSend and effectReturn
   */
  connectEffect(t) {
    return this._internalChannels.push(t), this.effectSend.chain(t, this.effectReturn), this;
  }
  dispose() {
    return super.dispose(), this._dryWet.dispose(), this.effectSend.dispose(), this.effectReturn.dispose(), this.wet.dispose(), this;
  }
}
class qo extends Ut {
  constructor(t) {
    super(t), this.name = "LFOEffect", this._lfo = new he({
      context: this.context,
      frequency: t.frequency,
      amplitude: t.depth
    }), this.depth = this._lfo.amplitude, this.frequency = this._lfo.frequency, this.type = t.type, Z(this, ["frequency", "depth"]);
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      frequency: 1,
      type: "sine",
      depth: 1
    });
  }
  /**
   * Start the effect.
   */
  start(t) {
    return this._lfo.start(t), this;
  }
  /**
   * Stop the lfo
   */
  stop(t) {
    return this._lfo.stop(t), this;
  }
  /**
   * Sync the filter to the transport.
   * @see {@link LFO.sync}
   */
  sync() {
    return this._lfo.sync(), this;
  }
  /**
   * Unsync the filter from the transport.
   */
  unsync() {
    return this._lfo.unsync(), this;
  }
  /**
   * The type of the LFO's oscillator.
   * @see {@link Oscillator.type}
   * @example
   * const autoFilter = new Tone.AutoFilter().start().toDestination();
   * const noise = new Tone.Noise().start().connect(autoFilter);
   * autoFilter.type = "square";
   */
  get type() {
    return this._lfo.type;
  }
  set type(t) {
    this._lfo.type = t;
  }
  dispose() {
    return super.dispose(), this._lfo.dispose(), this.frequency.dispose(), this.depth.dispose(), this;
  }
}
class ih extends qo {
  constructor() {
    const t = L(ih.getDefaults(), arguments, ["frequency", "baseFrequency", "octaves"]);
    super(t), this.name = "AutoFilter", this.filter = new Ce(Object.assign(t.filter, {
      context: this.context
    })), this.connectEffect(this.filter), this._lfo.connect(this.filter.frequency), this.octaves = t.octaves, this.baseFrequency = t.baseFrequency;
  }
  static getDefaults() {
    return Object.assign(qo.getDefaults(), {
      baseFrequency: 200,
      octaves: 2.6,
      filter: {
        type: "lowpass",
        rolloff: -12,
        Q: 1
      }
    });
  }
  /**
   * The minimum value of the filter's cutoff frequency.
   */
  get baseFrequency() {
    return this._lfo.min;
  }
  set baseFrequency(t) {
    this._lfo.min = this.toFrequency(t), this.octaves = this._octaves;
  }
  /**
   * The maximum value of the filter's cutoff frequency.
   */
  get octaves() {
    return this._octaves;
  }
  set octaves(t) {
    this._octaves = t, this._lfo.max = this._lfo.min * Math.pow(2, t);
  }
  dispose() {
    return super.dispose(), this.filter.dispose(), this;
  }
}
class Dn extends B {
  constructor() {
    const t = L(Dn.getDefaults(), arguments, [
      "pan"
    ]);
    super(t), this.name = "Panner", this._panner = this.context.createStereoPanner(), this.input = this._panner, this.output = this._panner, this.pan = new tt({
      context: this.context,
      param: this._panner.pan,
      value: t.pan,
      minValue: -1,
      maxValue: 1
    }), this._panner.channelCount = t.channelCount, this._panner.channelCountMode = "explicit", Z(this, "pan");
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      pan: 0,
      channelCount: 1
    });
  }
  dispose() {
    return super.dispose(), this._panner.disconnect(), this.pan.dispose(), this;
  }
}
class rh extends qo {
  constructor() {
    const t = L(rh.getDefaults(), arguments, ["frequency"]);
    super(t), this.name = "AutoPanner", this._panner = new Dn({
      context: this.context,
      channelCount: t.channelCount
    }), this.connectEffect(this._panner), this._lfo.connect(this._panner.pan), this._lfo.min = -1, this._lfo.max = 1;
  }
  static getDefaults() {
    return Object.assign(qo.getDefaults(), {
      channelCount: 1
    });
  }
  dispose() {
    return super.dispose(), this._panner.dispose(), this;
  }
}
class Ir extends B {
  constructor() {
    const t = L(Ir.getDefaults(), arguments, ["smoothing"]);
    super(t), this.name = "Follower", this._abs = this.input = new Sg({ context: this.context }), this._lowpass = this.output = new Er({
      context: this.context,
      frequency: 1 / this.toSeconds(t.smoothing),
      type: "lowpass"
    }), this._abs.connect(this._lowpass), this._smoothing = t.smoothing;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      smoothing: 0.05
    });
  }
  /**
   * The amount of time it takes a value change to arrive at the updated value.
   */
  get smoothing() {
    return this._smoothing;
  }
  set smoothing(t) {
    this._smoothing = t, this._lowpass.frequency = 1 / this.toSeconds(this.smoothing);
  }
  dispose() {
    return super.dispose(), this._abs.dispose(), this._lowpass.dispose(), this;
  }
}
class oh extends Ut {
  constructor() {
    const t = L(oh.getDefaults(), arguments, [
      "baseFrequency",
      "octaves",
      "sensitivity"
    ]);
    super(t), this.name = "AutoWah", this._follower = new Ir({
      context: this.context,
      smoothing: t.follower
    }), this._sweepRange = new fa({
      context: this.context,
      min: 0,
      max: 1,
      exponent: 0.5
    }), this._baseFrequency = this.toFrequency(t.baseFrequency), this._octaves = t.octaves, this._inputBoost = new j({ context: this.context }), this._bandpass = new Ce({
      context: this.context,
      rolloff: -48,
      frequency: 0,
      Q: t.Q
    }), this._peaking = new Ce({
      context: this.context,
      type: "peaking"
    }), this._peaking.gain.value = t.gain, this.gain = this._peaking.gain, this.Q = this._bandpass.Q, this.effectSend.chain(this._inputBoost, this._follower, this._sweepRange), this._sweepRange.connect(this._bandpass.frequency), this._sweepRange.connect(this._peaking.frequency), this.effectSend.chain(this._bandpass, this._peaking, this.effectReturn), this._setSweepRange(), this.sensitivity = t.sensitivity, Z(this, ["gain", "Q"]);
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      baseFrequency: 100,
      octaves: 6,
      sensitivity: 0,
      Q: 2,
      gain: 2,
      follower: 0.2
    });
  }
  /**
   * The number of octaves that the filter will sweep above the baseFrequency.
   */
  get octaves() {
    return this._octaves;
  }
  set octaves(t) {
    this._octaves = t, this._setSweepRange();
  }
  /**
   * The follower's smoothing time
   */
  get follower() {
    return this._follower.smoothing;
  }
  set follower(t) {
    this._follower.smoothing = t;
  }
  /**
   * The base frequency from which the sweep will start from.
   */
  get baseFrequency() {
    return this._baseFrequency;
  }
  set baseFrequency(t) {
    this._baseFrequency = this.toFrequency(t), this._setSweepRange();
  }
  /**
   * The sensitivity to control how responsive to the input signal the filter is.
   */
  get sensitivity() {
    return br(1 / this._inputBoost.gain.value);
  }
  set sensitivity(t) {
    this._inputBoost.gain.value = 1 / ni(t);
  }
  /**
   * sets the sweep range of the scaler
   */
  _setSweepRange() {
    this._sweepRange.min = this._baseFrequency, this._sweepRange.max = Math.min(this._baseFrequency * Math.pow(2, this._octaves), this.context.sampleRate / 2);
  }
  dispose() {
    return super.dispose(), this._follower.dispose(), this._sweepRange.dispose(), this._bandpass.dispose(), this._peaking.dispose(), this._inputBoost.dispose(), this;
  }
}
const Cg = "bit-crusher", wC = (
  /* javascript */
  `
	class BitCrusherWorklet extends SingleIOProcessor {

		static get parameterDescriptors() {
			return [{
				name: "bits",
				defaultValue: 12,
				minValue: 1,
				maxValue: 16,
				automationRate: 'k-rate'
			}];
		}

		generate(input, _channel, parameters) {
			const step = Math.pow(0.5, parameters.bits - 1);
			const val = step * Math.floor(input / step + 0.5);
			return val;
		}
	}
`
);
Mg(Cg, wC);
class ah extends Ut {
  constructor() {
    const t = L(ah.getDefaults(), arguments, ["bits"]);
    super(t), this.name = "BitCrusher", this._bitCrusherWorklet = new lh({
      context: this.context,
      bits: t.bits
    }), this.connectEffect(this._bitCrusherWorklet), this.bits = this._bitCrusherWorklet.bits;
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      bits: 4
    });
  }
  dispose() {
    return super.dispose(), this._bitCrusherWorklet.dispose(), this;
  }
}
class lh extends Ul {
  constructor() {
    const t = L(lh.getDefaults(), arguments);
    super(t), this.name = "BitCrusherWorklet", this.input = new j({ context: this.context }), this.output = new j({ context: this.context }), this.bits = new tt({
      context: this.context,
      value: t.bits,
      units: "positive",
      minValue: 1,
      maxValue: 16,
      param: this._dummyParam,
      swappable: !0
    });
  }
  static getDefaults() {
    return Object.assign(Ul.getDefaults(), {
      bits: 12
    });
  }
  _audioWorkletName() {
    return Cg;
  }
  onReady(t) {
    Fe(this.input, t, this.output);
    const e = t.parameters.get("bits");
    this.bits.setParam(e);
  }
  dispose() {
    return super.dispose(), this.input.dispose(), this.output.dispose(), this.bits.dispose(), this;
  }
}
class ch extends Ut {
  constructor() {
    const t = L(ch.getDefaults(), arguments, ["order"]);
    super(t), this.name = "Chebyshev", this._shaper = new ss({
      context: this.context,
      length: 4096
    }), this._order = t.order, this.connectEffect(this._shaper), this.order = t.order, this.oversample = t.oversample;
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      order: 1,
      oversample: "none"
    });
  }
  /**
   * get the coefficient for that degree
   * @param  x the x value
   * @param  degree
   * @param  memo memoize the computed value. this speeds up computation greatly.
   */
  _getCoefficient(t, e, s) {
    return s.has(e) || (e === 0 ? s.set(e, 0) : e === 1 ? s.set(e, t) : s.set(e, 2 * t * this._getCoefficient(t, e - 1, s) - this._getCoefficient(t, e - 2, s))), s.get(e);
  }
  /**
   * The order of the Chebyshev polynomial which creates the equation which is applied to the incoming
   * signal through a Tone.WaveShaper. Must be an integer. The equations are in the form:
   * ```
   * order 2: 2x^2 + 1
   * order 3: 4x^3 + 3x
   * ```
   * @min 1
   * @max 100
   */
  get order() {
    return this._order;
  }
  set order(t) {
    X(Number.isInteger(t), "'order' must be an integer"), this._order = t, this._shaper.setMap((e) => this._getCoefficient(e, t, /* @__PURE__ */ new Map()));
  }
  /**
   * The oversampling of the effect. Can either be "none", "2x" or "4x".
   */
  get oversample() {
    return this._shaper.oversample;
  }
  set oversample(t) {
    this._shaper.oversample = t;
  }
  dispose() {
    return super.dispose(), this._shaper.dispose(), this;
  }
}
class On extends B {
  constructor() {
    const t = L(On.getDefaults(), arguments, [
      "channels"
    ]);
    super(t), this.name = "Split", this._splitter = this.input = this.output = this.context.createChannelSplitter(t.channels), this._internalChannels = [this._splitter];
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      channels: 2
    });
  }
  dispose() {
    return super.dispose(), this._splitter.disconnect(), this;
  }
}
class en extends B {
  constructor() {
    const t = L(en.getDefaults(), arguments, [
      "channels"
    ]);
    super(t), this.name = "Merge", this._merger = this.output = this.input = this.context.createChannelMerger(t.channels);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      channels: 2
    });
  }
  dispose() {
    return super.dispose(), this._merger.disconnect(), this;
  }
}
class fs extends B {
  constructor(t) {
    super(t), this.name = "StereoEffect", this.input = new j({ context: this.context }), this.input.channelCount = 2, this.input.channelCountMode = "explicit", this._dryWet = this.output = new ki({
      context: this.context,
      fade: t.wet
    }), this.wet = this._dryWet.fade, this._split = new On({ context: this.context, channels: 2 }), this._merge = new en({ context: this.context, channels: 2 }), this.input.connect(this._split), this.input.connect(this._dryWet.a), this._merge.connect(this._dryWet.b), Z(this, ["wet"]);
  }
  /**
   * Connect the left part of the effect
   */
  connectEffectLeft(...t) {
    this._split.connect(t[0], 0, 0), Fe(...t), ue(t[t.length - 1], this._merge, 0, 0);
  }
  /**
   * Connect the right part of the effect
   */
  connectEffectRight(...t) {
    this._split.connect(t[0], 1, 0), Fe(...t), ue(t[t.length - 1], this._merge, 0, 1);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      wet: 1
    });
  }
  dispose() {
    return super.dispose(), this._dryWet.dispose(), this._split.dispose(), this._merge.dispose(), this;
  }
}
class Gl extends fs {
  constructor(t) {
    super(t), this.feedback = new Q({
      context: this.context,
      value: t.feedback,
      units: "normalRange"
    }), this._feedbackL = new j({ context: this.context }), this._feedbackR = new j({ context: this.context }), this._feedbackSplit = new On({ context: this.context, channels: 2 }), this._feedbackMerge = new en({ context: this.context, channels: 2 }), this._merge.connect(this._feedbackSplit), this._feedbackMerge.connect(this._split), this._feedbackSplit.connect(this._feedbackL, 0, 0), this._feedbackL.connect(this._feedbackMerge, 0, 0), this._feedbackSplit.connect(this._feedbackR, 1, 0), this._feedbackR.connect(this._feedbackMerge, 0, 1), this.feedback.fan(this._feedbackL.gain, this._feedbackR.gain), Z(this, ["feedback"]);
  }
  static getDefaults() {
    return Object.assign(fs.getDefaults(), {
      feedback: 0.5
    });
  }
  dispose() {
    return super.dispose(), this.feedback.dispose(), this._feedbackL.dispose(), this._feedbackR.dispose(), this._feedbackSplit.dispose(), this._feedbackMerge.dispose(), this;
  }
}
class hh extends Gl {
  constructor() {
    const t = L(hh.getDefaults(), arguments, [
      "frequency",
      "delayTime",
      "depth"
    ]);
    super(t), this.name = "Chorus", this._depth = t.depth, this._delayTime = t.delayTime / 1e3, this._lfoL = new he({
      context: this.context,
      frequency: t.frequency,
      min: 0,
      max: 1
    }), this._lfoR = new he({
      context: this.context,
      frequency: t.frequency,
      min: 0,
      max: 1,
      phase: 180
    }), this._delayNodeL = new Pe({ context: this.context }), this._delayNodeR = new Pe({ context: this.context }), this.frequency = this._lfoL.frequency, Z(this, ["frequency"]), this._lfoL.frequency.connect(this._lfoR.frequency), this.connectEffectLeft(this._delayNodeL), this.connectEffectRight(this._delayNodeR), this._lfoL.connect(this._delayNodeL.delayTime), this._lfoR.connect(this._delayNodeR.delayTime), this.depth = this._depth, this.type = t.type, this.spread = t.spread;
  }
  static getDefaults() {
    return Object.assign(Gl.getDefaults(), {
      frequency: 1.5,
      delayTime: 3.5,
      depth: 0.7,
      type: "sine",
      spread: 180,
      feedback: 0,
      wet: 0.5
    });
  }
  /**
   * The depth of the effect. A depth of 1 makes the delayTime
   * modulate between 0 and 2*delayTime (centered around the delayTime).
   */
  get depth() {
    return this._depth;
  }
  set depth(t) {
    this._depth = t;
    const e = this._delayTime * t;
    this._lfoL.min = Math.max(this._delayTime - e, 0), this._lfoL.max = this._delayTime + e, this._lfoR.min = Math.max(this._delayTime - e, 0), this._lfoR.max = this._delayTime + e;
  }
  /**
   * The delayTime in milliseconds of the chorus. A larger delayTime
   * will give a more pronounced effect. Nominal range a delayTime
   * is between 2 and 20ms.
   */
  get delayTime() {
    return this._delayTime * 1e3;
  }
  set delayTime(t) {
    this._delayTime = t / 1e3, this.depth = this._depth;
  }
  /**
   * The oscillator type of the LFO.
   */
  get type() {
    return this._lfoL.type;
  }
  set type(t) {
    this._lfoL.type = t, this._lfoR.type = t;
  }
  /**
   * Amount of stereo spread. When set to 0, both LFO's will be panned centrally.
   * When set to 180, LFO's will be panned hard left and right respectively.
   */
  get spread() {
    return this._lfoR.phase - this._lfoL.phase;
  }
  set spread(t) {
    this._lfoL.phase = 90 - t / 2, this._lfoR.phase = t / 2 + 90;
  }
  /**
   * Start the effect.
   */
  start(t) {
    return this._lfoL.start(t), this._lfoR.start(t), this;
  }
  /**
   * Stop the lfo
   */
  stop(t) {
    return this._lfoL.stop(t), this._lfoR.stop(t), this;
  }
  /**
   * Sync the filter to the transport.
   * @see {@link LFO.sync}
   */
  sync() {
    return this._lfoL.sync(), this._lfoR.sync(), this;
  }
  /**
   * Unsync the filter from the transport.
   */
  unsync() {
    return this._lfoL.unsync(), this._lfoR.unsync(), this;
  }
  dispose() {
    return super.dispose(), this._lfoL.dispose(), this._lfoR.dispose(), this._delayNodeL.dispose(), this._delayNodeR.dispose(), this.frequency.dispose(), this;
  }
}
class uh extends Ut {
  constructor() {
    const t = L(uh.getDefaults(), arguments, ["distortion"]);
    super(t), this.name = "Distortion", this._shaper = new ss({
      context: this.context,
      length: 4096
    }), this._distortion = t.distortion, this.connectEffect(this._shaper), this.distortion = t.distortion, this.oversample = t.oversample;
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      distortion: 0.4,
      oversample: "none"
    });
  }
  /**
   * The amount of distortion. Nominal range is between 0 and 1.
   */
  get distortion() {
    return this._distortion;
  }
  set distortion(t) {
    this._distortion = t;
    const e = t * 100, s = Math.PI / 180;
    this._shaper.setMap((i) => Math.abs(i) < 1e-3 ? 0 : (3 + e) * i * 20 * s / (Math.PI + e * Math.abs(i)));
  }
  /**
   * The oversampling of the effect. Can either be "none", "2x" or "4x".
   */
  get oversample() {
    return this._shaper.oversample;
  }
  set oversample(t) {
    this._shaper.oversample = t;
  }
  dispose() {
    return super.dispose(), this._shaper.dispose(), this;
  }
}
class Uo extends Ut {
  constructor(t) {
    super(t), this.name = "FeedbackEffect", this._feedbackGain = new j({
      context: this.context,
      gain: t.feedback,
      units: "normalRange"
    }), this.feedback = this._feedbackGain.gain, Z(this, "feedback"), this.effectReturn.chain(this._feedbackGain, this.effectSend);
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      feedback: 0.125
    });
  }
  dispose() {
    return super.dispose(), this._feedbackGain.dispose(), this.feedback.dispose(), this;
  }
}
class dh extends Uo {
  constructor() {
    const t = L(dh.getDefaults(), arguments, ["delayTime", "feedback"]);
    super(t), this.name = "FeedbackDelay", this._delayNode = new Pe({
      context: this.context,
      delayTime: t.delayTime,
      maxDelay: t.maxDelay
    }), this.delayTime = this._delayNode.delayTime, this.connectEffect(this._delayNode), Z(this, "delayTime");
  }
  static getDefaults() {
    return Object.assign(Uo.getDefaults(), {
      delayTime: 0.25,
      maxDelay: 1
    });
  }
  dispose() {
    return super.dispose(), this._delayNode.dispose(), this.delayTime.dispose(), this;
  }
}
class SC extends B {
  constructor(t) {
    super(t), this.name = "PhaseShiftAllpass", this.input = new j({ context: this.context }), this.output = new j({ context: this.context }), this.offset90 = new j({ context: this.context });
    const e = [
      0.6923878,
      0.9360654322959,
      0.988229522686,
      0.9987488452737
    ], s = [
      0.4021921162426,
      0.856171088242,
      0.9722909545651,
      0.9952884791278
    ];
    this._bank0 = this._createAllPassFilterBank(e), this._bank1 = this._createAllPassFilterBank(s), this._oneSampleDelay = this.context.createIIRFilter([0, 1], [1, 0]), Fe(this.input, ...this._bank0, this._oneSampleDelay, this.output), Fe(this.input, ...this._bank1, this.offset90);
  }
  /**
   * Create all of the IIR filters from an array of values using the coefficient calculation.
   */
  _createAllPassFilterBank(t) {
    return t.map((s) => {
      const i = [
        [s * s, 0, -1],
        [1, 0, -(s * s)]
      ];
      return this.context.createIIRFilter(i[0], i[1]);
    });
  }
  dispose() {
    return super.dispose(), this.input.dispose(), this.output.dispose(), this.offset90.dispose(), this._bank0.forEach((t) => t.disconnect()), this._bank1.forEach((t) => t.disconnect()), this._oneSampleDelay.disconnect(), this;
  }
}
class fh extends Ut {
  constructor() {
    const t = L(fh.getDefaults(), arguments, ["frequency"]);
    super(t), this.name = "FrequencyShifter", this.frequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.frequency,
      minValue: -this.context.sampleRate / 2,
      maxValue: this.context.sampleRate / 2
    }), this._sine = new Sr({
      context: this.context,
      type: "sine"
    }), this._cosine = new Tt({
      context: this.context,
      phase: -90,
      type: "sine"
    }), this._sineMultiply = new Mt({ context: this.context }), this._cosineMultiply = new Mt({ context: this.context }), this._negate = new Hc({ context: this.context }), this._add = new In({ context: this.context }), this._phaseShifter = new SC({ context: this.context }), this.effectSend.connect(this._phaseShifter), this.frequency.fan(this._sine.frequency, this._cosine.frequency), this._phaseShifter.offset90.connect(this._cosineMultiply), this._cosine.connect(this._cosineMultiply.factor), this._phaseShifter.connect(this._sineMultiply), this._sine.connect(this._sineMultiply.factor), this._sineMultiply.connect(this._negate), this._cosineMultiply.connect(this._add), this._negate.connect(this._add.addend), this._add.connect(this.effectReturn);
    const e = this.immediate();
    this._sine.start(e), this._cosine.start(e);
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      frequency: 0
    });
  }
  dispose() {
    return super.dispose(), this.frequency.dispose(), this._add.dispose(), this._cosine.dispose(), this._cosineMultiply.dispose(), this._negate.dispose(), this._phaseShifter.dispose(), this._sine.dispose(), this._sineMultiply.dispose(), this;
  }
}
const hf = [
  1557 / 44100,
  1617 / 44100,
  1491 / 44100,
  1422 / 44100,
  1277 / 44100,
  1356 / 44100,
  1188 / 44100,
  1116 / 44100
], uf = [225, 556, 441, 341];
class ph extends fs {
  constructor() {
    const t = L(ph.getDefaults(), arguments, ["roomSize", "dampening"]);
    super(t), this.name = "Freeverb", this._combFilters = [], this._allpassFiltersL = [], this._allpassFiltersR = [], this.roomSize = new Q({
      context: this.context,
      value: t.roomSize,
      units: "normalRange"
    }), this._allpassFiltersL = uf.map((e) => {
      const s = this.context.createBiquadFilter();
      return s.type = "allpass", s.frequency.value = e, s;
    }), this._allpassFiltersR = uf.map((e) => {
      const s = this.context.createBiquadFilter();
      return s.type = "allpass", s.frequency.value = e, s;
    }), this._combFilters = hf.map((e, s) => {
      const i = new Pr({
        context: this.context,
        dampening: t.dampening,
        delayTime: e
      });
      return s < hf.length / 2 ? this.connectEffectLeft(i, ...this._allpassFiltersL) : this.connectEffectRight(i, ...this._allpassFiltersR), this.roomSize.connect(i.resonance), i;
    }), Z(this, ["roomSize"]);
  }
  static getDefaults() {
    return Object.assign(fs.getDefaults(), {
      roomSize: 0.7,
      dampening: 3e3
    });
  }
  /**
   * The amount of dampening of the reverberant signal.
   */
  get dampening() {
    return this._combFilters[0].dampening;
  }
  set dampening(t) {
    this._combFilters.forEach((e) => e.dampening = t);
  }
  dispose() {
    return super.dispose(), this._allpassFiltersL.forEach((t) => t.disconnect()), this._allpassFiltersR.forEach((t) => t.disconnect()), this._combFilters.forEach((t) => t.dispose()), this.roomSize.dispose(), this;
  }
}
const df = [
  1687 / 25e3,
  1601 / 25e3,
  2053 / 25e3,
  2251 / 25e3
], TC = [0.773, 0.802, 0.753, 0.733], MC = [347, 113, 37];
class mh extends fs {
  constructor() {
    const t = L(mh.getDefaults(), arguments, ["roomSize"]);
    super(t), this.name = "JCReverb", this._allpassFilters = [], this._feedbackCombFilters = [], this.roomSize = new Q({
      context: this.context,
      value: t.roomSize,
      units: "normalRange"
    }), this._scaleRoomSize = new Rs({
      context: this.context,
      min: -0.733,
      max: 0.197
    }), this._allpassFilters = MC.map((e) => {
      const s = this.context.createBiquadFilter();
      return s.type = "allpass", s.frequency.value = e, s;
    }), this._feedbackCombFilters = df.map((e, s) => {
      const i = new Ar({
        context: this.context,
        delayTime: e
      });
      return this._scaleRoomSize.connect(i.resonance), i.resonance.value = TC[s], s < df.length / 2 ? this.connectEffectLeft(...this._allpassFilters, i) : this.connectEffectRight(...this._allpassFilters, i), i;
    }), this.roomSize.connect(this._scaleRoomSize), Z(this, ["roomSize"]);
  }
  static getDefaults() {
    return Object.assign(fs.getDefaults(), {
      roomSize: 0.5
    });
  }
  dispose() {
    return super.dispose(), this._allpassFilters.forEach((t) => t.disconnect()), this._feedbackCombFilters.forEach((t) => t.dispose()), this.roomSize.dispose(), this._scaleRoomSize.dispose(), this;
  }
}
class ff extends Gl {
  constructor(t) {
    super(t), this._feedbackL.disconnect(), this._feedbackL.connect(this._feedbackMerge, 0, 1), this._feedbackR.disconnect(), this._feedbackR.connect(this._feedbackMerge, 0, 0), Z(this, ["feedback"]);
  }
}
class gh extends ff {
  constructor() {
    const t = L(gh.getDefaults(), arguments, ["delayTime", "feedback"]);
    super(t), this.name = "PingPongDelay", this._leftDelay = new Pe({
      context: this.context,
      maxDelay: t.maxDelay
    }), this._rightDelay = new Pe({
      context: this.context,
      maxDelay: t.maxDelay
    }), this._rightPreDelay = new Pe({
      context: this.context,
      maxDelay: t.maxDelay
    }), this.delayTime = new Q({
      context: this.context,
      units: "time",
      value: t.delayTime
    }), this.connectEffectLeft(this._leftDelay), this.connectEffectRight(this._rightPreDelay, this._rightDelay), this.delayTime.fan(this._leftDelay.delayTime, this._rightDelay.delayTime, this._rightPreDelay.delayTime), this._feedbackL.disconnect(), this._feedbackL.connect(this._rightDelay), Z(this, ["delayTime"]);
  }
  static getDefaults() {
    return Object.assign(ff.getDefaults(), {
      delayTime: 0.25,
      maxDelay: 1
    });
  }
  dispose() {
    return super.dispose(), this._leftDelay.dispose(), this._rightDelay.dispose(), this._rightPreDelay.dispose(), this.delayTime.dispose(), this;
  }
}
class pa extends Uo {
  constructor() {
    const t = L(pa.getDefaults(), arguments, ["pitch"]);
    super(t), this.name = "PitchShift", this._frequency = new Q({ context: this.context }), this._delayA = new Pe({
      maxDelay: 1,
      context: this.context
    }), this._lfoA = new he({
      context: this.context,
      min: 0,
      max: 0.1,
      type: "sawtooth"
    }).connect(this._delayA.delayTime), this._delayB = new Pe({
      maxDelay: 1,
      context: this.context
    }), this._lfoB = new he({
      context: this.context,
      min: 0,
      max: 0.1,
      type: "sawtooth",
      phase: 180
    }).connect(this._delayB.delayTime), this._crossFade = new ki({ context: this.context }), this._crossFadeLFO = new he({
      context: this.context,
      min: 0,
      max: 1,
      type: "triangle",
      phase: 90
    }).connect(this._crossFade.fade), this._feedbackDelay = new Pe({
      delayTime: t.delayTime,
      context: this.context
    }), this.delayTime = this._feedbackDelay.delayTime, Z(this, "delayTime"), this._pitch = t.pitch, this._windowSize = t.windowSize, this._delayA.connect(this._crossFade.a), this._delayB.connect(this._crossFade.b), this._frequency.fan(this._lfoA.frequency, this._lfoB.frequency, this._crossFadeLFO.frequency), this.effectSend.fan(this._delayA, this._delayB), this._crossFade.chain(this._feedbackDelay, this.effectReturn);
    const e = this.now();
    this._lfoA.start(e), this._lfoB.start(e), this._crossFadeLFO.start(e), this.windowSize = this._windowSize;
  }
  static getDefaults() {
    return Object.assign(Uo.getDefaults(), {
      pitch: 0,
      windowSize: 0.1,
      delayTime: 0,
      feedback: 0
    });
  }
  /**
   * Repitch the incoming signal by some interval (measured in semi-tones).
   * @example
   * const pitchShift = new Tone.PitchShift().toDestination();
   * const osc = new Tone.Oscillator().connect(pitchShift).start().toDestination();
   * pitchShift.pitch = -12; // down one octave
   * pitchShift.pitch = 7; // up a fifth
   */
  get pitch() {
    return this._pitch;
  }
  set pitch(t) {
    this._pitch = t;
    let e = 0;
    t < 0 ? (this._lfoA.min = 0, this._lfoA.max = this._windowSize, this._lfoB.min = 0, this._lfoB.max = this._windowSize, e = ii(t - 1) + 1) : (this._lfoA.min = this._windowSize, this._lfoA.max = 0, this._lfoB.min = this._windowSize, this._lfoB.max = 0, e = ii(t) - 1), this._frequency.value = e * (1.2 / this._windowSize);
  }
  /**
   * The window size corresponds roughly to the sample length in a looping sampler.
   * Smaller values are desirable for a less noticeable delay time of the pitch shifted
   * signal, but larger values will result in smoother pitch shifting for larger intervals.
   * A nominal range of 0.03 to 0.1 is recommended.
   */
  get windowSize() {
    return this._windowSize;
  }
  set windowSize(t) {
    this._windowSize = this.toSeconds(t), this.pitch = this._pitch;
  }
  dispose() {
    return super.dispose(), this._frequency.dispose(), this._delayA.dispose(), this._delayB.dispose(), this._lfoA.dispose(), this._lfoB.dispose(), this._crossFade.dispose(), this._crossFadeLFO.dispose(), this._feedbackDelay.dispose(), this;
  }
}
class yh extends fs {
  constructor() {
    const t = L(yh.getDefaults(), arguments, [
      "frequency",
      "octaves",
      "baseFrequency"
    ]);
    super(t), this.name = "Phaser", this._lfoL = new he({
      context: this.context,
      frequency: t.frequency,
      min: 0,
      max: 1
    }), this._lfoR = new he({
      context: this.context,
      frequency: t.frequency,
      min: 0,
      max: 1,
      phase: 180
    }), this._baseFrequency = this.toFrequency(t.baseFrequency), this._octaves = t.octaves, this.Q = new Q({
      context: this.context,
      value: t.Q,
      units: "positive"
    }), this._filtersL = this._makeFilters(t.stages, this._lfoL), this._filtersR = this._makeFilters(t.stages, this._lfoR), this.frequency = this._lfoL.frequency, this.frequency.value = t.frequency, this.connectEffectLeft(...this._filtersL), this.connectEffectRight(...this._filtersR), this._lfoL.frequency.connect(this._lfoR.frequency), this.baseFrequency = t.baseFrequency, this.octaves = t.octaves, this._lfoL.start(), this._lfoR.start(), Z(this, ["frequency", "Q"]);
  }
  static getDefaults() {
    return Object.assign(fs.getDefaults(), {
      frequency: 0.5,
      octaves: 3,
      stages: 10,
      Q: 10,
      baseFrequency: 350
    });
  }
  _makeFilters(t, e) {
    const s = [];
    for (let i = 0; i < t; i++) {
      const r = this.context.createBiquadFilter();
      r.type = "allpass", this.Q.connect(r.Q), e.connect(r.frequency), s.push(r);
    }
    return s;
  }
  /**
   * The number of octaves the phase goes above the baseFrequency
   */
  get octaves() {
    return this._octaves;
  }
  set octaves(t) {
    this._octaves = t;
    const e = this._baseFrequency * Math.pow(2, t);
    this._lfoL.max = e, this._lfoR.max = e;
  }
  /**
   * The the base frequency of the filters.
   */
  get baseFrequency() {
    return this._baseFrequency;
  }
  set baseFrequency(t) {
    this._baseFrequency = this.toFrequency(t), this._lfoL.min = this._baseFrequency, this._lfoR.min = this._baseFrequency, this.octaves = this._octaves;
  }
  dispose() {
    return super.dispose(), this.Q.dispose(), this._lfoL.dispose(), this._lfoR.dispose(), this._filtersL.forEach((t) => t.disconnect()), this._filtersR.forEach((t) => t.disconnect()), this.frequency.dispose(), this;
  }
}
class xh extends Ut {
  constructor() {
    const t = L(xh.getDefaults(), arguments, [
      "decay"
    ]);
    super(t), this.name = "Reverb", this._convolver = this.context.createConvolver(), this.ready = Promise.resolve();
    const e = this.toSeconds(t.decay);
    zt(e, 1e-3), this._decay = e;
    const s = this.toSeconds(t.preDelay);
    zt(s, 0), this._preDelay = s, this.generate(), this.connectEffect(this._convolver);
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      decay: 1.5,
      preDelay: 0.01
    });
  }
  /**
   * The duration of the reverb.
   */
  get decay() {
    return this._decay;
  }
  set decay(t) {
    t = this.toSeconds(t), zt(t, 1e-3), this._decay = t, this.generate();
  }
  /**
   * The amount of time before the reverb is fully ramped in.
   */
  get preDelay() {
    return this._preDelay;
  }
  set preDelay(t) {
    t = this.toSeconds(t), zt(t, 0), this._preDelay = t, this.generate();
  }
  /**
   * Generate the Impulse Response. Returns a promise while the IR is being generated.
   * @return Promise which returns this object.
   */
  generate() {
    return yt(this, void 0, void 0, function* () {
      const t = this.ready, e = new xi(2, this._decay + this._preDelay, this.context.sampleRate), s = new Ys({ context: e }), i = new Ys({ context: e }), r = new en({ context: e });
      s.connect(r, 0, 0), i.connect(r, 0, 1);
      const o = new j({ context: e }).toDestination();
      r.connect(o), s.start(0), i.start(0), o.gain.setValueAtTime(0, 0), o.gain.setValueAtTime(1, this._preDelay), o.gain.exponentialApproachValueAtTime(0, this._preDelay, this.decay);
      const a = e.render();
      return this.ready = a.then(st), yield t, this._convolver.buffer = (yield a).get(), this;
    });
  }
  dispose() {
    return super.dispose(), this._convolver.disconnect(), this;
  }
}
class Fr extends B {
  constructor() {
    super(L(Fr.getDefaults(), arguments)), this.name = "MidSideSplit", this._split = this.input = new On({
      channels: 2,
      context: this.context
    }), this._midAdd = new In({ context: this.context }), this.mid = new Mt({
      context: this.context,
      value: Math.SQRT1_2
    }), this._sideSubtract = new Rn({ context: this.context }), this.side = new Mt({
      context: this.context,
      value: Math.SQRT1_2
    }), this._split.connect(this._midAdd, 0), this._split.connect(this._midAdd.addend, 1), this._split.connect(this._sideSubtract, 0), this._split.connect(this._sideSubtract.subtrahend, 1), this._midAdd.connect(this.mid), this._sideSubtract.connect(this.side);
  }
  dispose() {
    return super.dispose(), this.mid.dispose(), this.side.dispose(), this._midAdd.dispose(), this._sideSubtract.dispose(), this._split.dispose(), this;
  }
}
class Rr extends B {
  constructor() {
    super(L(Rr.getDefaults(), arguments)), this.name = "MidSideMerge", this.mid = new j({ context: this.context }), this.side = new j({ context: this.context }), this._left = new In({ context: this.context }), this._leftMult = new Mt({
      context: this.context,
      value: Math.SQRT1_2
    }), this._right = new Rn({ context: this.context }), this._rightMult = new Mt({
      context: this.context,
      value: Math.SQRT1_2
    }), this._merge = this.output = new en({ context: this.context }), this.mid.fan(this._left), this.side.connect(this._left.addend), this.mid.connect(this._right), this.side.connect(this._right.subtrahend), this._left.connect(this._leftMult), this._right.connect(this._rightMult), this._leftMult.connect(this._merge, 0, 0), this._rightMult.connect(this._merge, 0, 1);
  }
  dispose() {
    return super.dispose(), this.mid.dispose(), this.side.dispose(), this._leftMult.dispose(), this._rightMult.dispose(), this._left.dispose(), this._right.dispose(), this;
  }
}
class pf extends Ut {
  constructor(t) {
    super(t), this.name = "MidSideEffect", this._midSideMerge = new Rr({ context: this.context }), this._midSideSplit = new Fr({ context: this.context }), this._midSend = this._midSideSplit.mid, this._sideSend = this._midSideSplit.side, this._midReturn = this._midSideMerge.mid, this._sideReturn = this._midSideMerge.side, this.effectSend.connect(this._midSideSplit), this._midSideMerge.connect(this.effectReturn);
  }
  /**
   * Connect the mid chain of the effect
   */
  connectEffectMid(...t) {
    this._midSend.chain(...t, this._midReturn);
  }
  /**
   * Connect the side chain of the effect
   */
  connectEffectSide(...t) {
    this._sideSend.chain(...t, this._sideReturn);
  }
  dispose() {
    return super.dispose(), this._midSideSplit.dispose(), this._midSideMerge.dispose(), this._midSend.dispose(), this._sideSend.dispose(), this._midReturn.dispose(), this._sideReturn.dispose(), this;
  }
}
class _h extends pf {
  constructor() {
    const t = L(_h.getDefaults(), arguments, ["width"]);
    super(t), this.name = "StereoWidener", this.width = new Q({
      context: this.context,
      value: t.width,
      units: "normalRange"
    }), Z(this, ["width"]), this._twoTimesWidthMid = new Mt({
      context: this.context,
      value: 2
    }), this._twoTimesWidthSide = new Mt({
      context: this.context,
      value: 2
    }), this._midMult = new Mt({ context: this.context }), this._twoTimesWidthMid.connect(this._midMult.factor), this.connectEffectMid(this._midMult), this._oneMinusWidth = new Rn({ context: this.context }), this._oneMinusWidth.connect(this._twoTimesWidthMid), ue(this.context.getConstant(1), this._oneMinusWidth), this.width.connect(this._oneMinusWidth.subtrahend), this._sideMult = new Mt({ context: this.context }), this.width.connect(this._twoTimesWidthSide), this._twoTimesWidthSide.connect(this._sideMult.factor), this.connectEffectSide(this._sideMult);
  }
  static getDefaults() {
    return Object.assign(pf.getDefaults(), {
      width: 0.5
    });
  }
  dispose() {
    return super.dispose(), this.width.dispose(), this._midMult.dispose(), this._sideMult.dispose(), this._twoTimesWidthMid.dispose(), this._twoTimesWidthSide.dispose(), this._oneMinusWidth.dispose(), this;
  }
}
class vh extends fs {
  constructor() {
    const t = L(vh.getDefaults(), arguments, [
      "frequency",
      "depth"
    ]);
    super(t), this.name = "Tremolo", this._lfoL = new he({
      context: this.context,
      type: t.type,
      min: 1,
      max: 0
    }), this._lfoR = new he({
      context: this.context,
      type: t.type,
      min: 1,
      max: 0
    }), this._amplitudeL = new j({ context: this.context }), this._amplitudeR = new j({ context: this.context }), this.frequency = new Q({
      context: this.context,
      value: t.frequency,
      units: "frequency"
    }), this.depth = new Q({
      context: this.context,
      value: t.depth,
      units: "normalRange"
    }), Z(this, ["frequency", "depth"]), this.connectEffectLeft(this._amplitudeL), this.connectEffectRight(this._amplitudeR), this._lfoL.connect(this._amplitudeL.gain), this._lfoR.connect(this._amplitudeR.gain), this.frequency.fan(this._lfoL.frequency, this._lfoR.frequency), this.depth.fan(this._lfoR.amplitude, this._lfoL.amplitude), this.spread = t.spread;
  }
  static getDefaults() {
    return Object.assign(fs.getDefaults(), {
      frequency: 10,
      type: "sine",
      depth: 0.5,
      spread: 180
    });
  }
  /**
   * Start the tremolo.
   */
  start(t) {
    return this._lfoL.start(t), this._lfoR.start(t), this;
  }
  /**
   * Stop the tremolo.
   */
  stop(t) {
    return this._lfoL.stop(t), this._lfoR.stop(t), this;
  }
  /**
   * Sync the effect to the transport.
   */
  sync() {
    return this._lfoL.sync(), this._lfoR.sync(), this.context.transport.syncSignal(this.frequency), this;
  }
  /**
   * Unsync the filter from the transport
   */
  unsync() {
    return this._lfoL.unsync(), this._lfoR.unsync(), this.context.transport.unsyncSignal(this.frequency), this;
  }
  /**
   * The oscillator type.
   */
  get type() {
    return this._lfoL.type;
  }
  set type(t) {
    this._lfoL.type = t, this._lfoR.type = t;
  }
  /**
   * Amount of stereo spread. When set to 0, both LFO's will be panned centrally.
   * When set to 180, LFO's will be panned hard left and right respectively.
   */
  get spread() {
    return this._lfoR.phase - this._lfoL.phase;
  }
  set spread(t) {
    this._lfoL.phase = 90 - t / 2, this._lfoR.phase = t / 2 + 90;
  }
  dispose() {
    return super.dispose(), this._lfoL.dispose(), this._lfoR.dispose(), this._amplitudeL.dispose(), this._amplitudeR.dispose(), this.frequency.dispose(), this.depth.dispose(), this;
  }
}
class bh extends Ut {
  constructor() {
    const t = L(bh.getDefaults(), arguments, [
      "frequency",
      "depth"
    ]);
    super(t), this.name = "Vibrato", this._delayNode = new Pe({
      context: this.context,
      delayTime: 0,
      maxDelay: t.maxDelay
    }), this._lfo = new he({
      context: this.context,
      type: t.type,
      min: 0,
      max: t.maxDelay,
      frequency: t.frequency,
      phase: -90
      // offse the phase so the resting position is in the center
    }).start().connect(this._delayNode.delayTime), this.frequency = this._lfo.frequency, this.depth = this._lfo.amplitude, this.depth.value = t.depth, Z(this, ["frequency", "depth"]), this.effectSend.chain(this._delayNode, this.effectReturn);
  }
  static getDefaults() {
    return Object.assign(Ut.getDefaults(), {
      maxDelay: 5e-3,
      frequency: 5,
      depth: 0.1,
      type: "sine"
    });
  }
  /**
   * Type of oscillator attached to the Vibrato.
   */
  get type() {
    return this._lfo.type;
  }
  set type(t) {
    this._lfo.type = t;
  }
  dispose() {
    return super.dispose(), this._delayNode.dispose(), this._lfo.dispose(), this.frequency.dispose(), this.depth.dispose(), this;
  }
}
class Dr extends B {
  constructor() {
    const t = L(Dr.getDefaults(), arguments, ["type", "size"]);
    super(t), this.name = "Analyser", this._analysers = [], this._buffers = [], this.input = this.output = this._gain = new j({ context: this.context }), this._split = new On({
      context: this.context,
      channels: t.channels
    }), this.input.connect(this._split), zt(t.channels, 1);
    for (let e = 0; e < t.channels; e++)
      this._analysers[e] = this.context.createAnalyser(), this._split.connect(this._analysers[e], e, 0);
    this.size = t.size, this.type = t.type, this.smoothing = t.smoothing;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      size: 1024,
      smoothing: 0.8,
      type: "fft",
      channels: 1
    });
  }
  /**
   * Run the analysis given the current settings. If {@link channels} = 1,
   * it will return a Float32Array. If {@link channels} > 1, it will
   * return an array of Float32Arrays where each index in the array
   * represents the analysis done on a channel.
   */
  getValue() {
    return this._analysers.forEach((t, e) => {
      const s = this._buffers[e];
      this._type === "fft" ? t.getFloatFrequencyData(s) : this._type === "waveform" && t.getFloatTimeDomainData(s);
    }), this.channels === 1 ? this._buffers[0] : this._buffers;
  }
  /**
   * The size of analysis. This must be a power of two in the range 16 to 16384.
   */
  get size() {
    return this._analysers[0].frequencyBinCount;
  }
  set size(t) {
    this._analysers.forEach((e, s) => {
      e.fftSize = t * 2, this._buffers[s] = new Float32Array(t);
    });
  }
  /**
   * The number of channels the analyser does the analysis on. Channel
   * separation is done using {@link Split}
   */
  get channels() {
    return this._analysers.length;
  }
  /**
   * The analysis function returned by analyser.getValue(), either "fft" or "waveform".
   */
  get type() {
    return this._type;
  }
  set type(t) {
    X(t === "waveform" || t === "fft", `Analyser: invalid type: ${t}`), this._type = t;
  }
  /**
   * 0 represents no time averaging with the last analysis frame.
   */
  get smoothing() {
    return this._analysers[0].smoothingTimeConstant;
  }
  set smoothing(t) {
    this._analysers.forEach((e) => e.smoothingTimeConstant = t);
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), this._analysers.forEach((t) => t.disconnect()), this._split.dispose(), this._gain.dispose(), this;
  }
}
class Ks extends B {
  constructor() {
    super(L(Ks.getDefaults(), arguments)), this.name = "MeterBase", this.input = this.output = this._analyser = new Dr({
      context: this.context,
      size: 256,
      type: "waveform"
    });
  }
  dispose() {
    return super.dispose(), this._analyser.dispose(), this;
  }
}
class wh extends Ks {
  constructor() {
    const t = L(wh.getDefaults(), arguments, [
      "smoothing"
    ]);
    super(t), this.name = "Meter", this.input = this.output = this._analyser = new Dr({
      context: this.context,
      size: 256,
      type: "waveform",
      channels: t.channelCount
    }), this.smoothing = t.smoothing, this.normalRange = t.normalRange, this._rms = new Array(t.channelCount), this._rms.fill(0);
  }
  static getDefaults() {
    return Object.assign(Ks.getDefaults(), {
      smoothing: 0.8,
      normalRange: !1,
      channelCount: 1
    });
  }
  /**
   * Use {@link getValue} instead. For the previous getValue behavior, use DCMeter.
   * @deprecated
   */
  getLevel() {
    return mi("'getLevel' has been changed to 'getValue'"), this.getValue();
  }
  /**
   * Get the current value of the incoming signal.
   * Output is in decibels when {@link normalRange} is `false`.
   * If {@link channels} = 1, then the output is a single number
   * representing the value of the input signal. When {@link channels} > 1,
   * then each channel is returned as a value in a number array.
   */
  getValue() {
    const t = this._analyser.getValue(), s = (this.channels === 1 ? [t] : t).map((i, r) => {
      const o = i.reduce((l, c) => l + c * c, 0), a = Math.sqrt(o / i.length);
      return this._rms[r] = Math.max(a, this._rms[r] * this.smoothing), this.normalRange ? this._rms[r] : br(this._rms[r]);
    });
    return this.channels === 1 ? s[0] : s;
  }
  /**
   * The number of channels of analysis.
   */
  get channels() {
    return this._analyser.channels;
  }
  dispose() {
    return super.dispose(), this._analyser.dispose(), this;
  }
}
class Sh extends Ks {
  constructor() {
    const t = L(Sh.getDefaults(), arguments, [
      "size"
    ]);
    super(t), this.name = "FFT", this.normalRange = t.normalRange, this._analyser.type = "fft", this.size = t.size;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      normalRange: !1,
      size: 1024,
      smoothing: 0.8
    });
  }
  /**
   * Gets the current frequency data from the connected audio source.
   * Returns the frequency data of length {@link size} as a Float32Array of decibel values.
   */
  getValue() {
    return this._analyser.getValue().map((e) => this.normalRange ? ni(e) : e);
  }
  /**
   * The size of analysis. This must be a power of two in the range 16 to 16384.
   * Determines the size of the array returned by {@link getValue} (i.e. the number of
   * frequency bins). Large FFT sizes may be costly to compute.
   */
  get size() {
    return this._analyser.size;
  }
  set size(t) {
    this._analyser.size = t;
  }
  /**
   * 0 represents no time averaging with the last analysis frame.
   */
  get smoothing() {
    return this._analyser.smoothing;
  }
  set smoothing(t) {
    this._analyser.smoothing = t;
  }
  /**
   * Returns the frequency value in hertz of each of the indices of the FFT's {@link getValue} response.
   * @example
   * const fft = new Tone.FFT(32);
   * console.log([0, 1, 2, 3, 4].map(index => fft.getFrequencyOfIndex(index)));
   */
  getFrequencyOfIndex(t) {
    return X(0 <= t && t < this.size, `index must be greater than or equal to 0 and less than ${this.size}`), t * this.context.sampleRate / (this.size * 2);
  }
}
class Th extends Ks {
  constructor() {
    super(L(Th.getDefaults(), arguments)), this.name = "DCMeter", this._analyser.type = "waveform", this._analyser.size = 256;
  }
  /**
   * Get the signal value of the incoming signal
   */
  getValue() {
    return this._analyser.getValue()[0];
  }
}
class Mh extends Ks {
  constructor() {
    const t = L(Mh.getDefaults(), arguments, ["size"]);
    super(t), this.name = "Waveform", this._analyser.type = "waveform", this.size = t.size;
  }
  static getDefaults() {
    return Object.assign(Ks.getDefaults(), {
      size: 1024
    });
  }
  /**
   * Return the waveform for the current time as a Float32Array where each value in the array
   * represents a sample in the waveform.
   */
  getValue() {
    return this._analyser.getValue();
  }
  /**
   * The size of analysis. This must be a power of two in the range 16 to 16384.
   * Determines the size of the array returned by {@link getValue}.
   */
  get size() {
    return this._analyser.size;
  }
  set size(t) {
    this._analyser.size = t;
  }
}
class Rt extends B {
  constructor() {
    const t = L(Rt.getDefaults(), arguments, [
      "solo"
    ]);
    super(t), this.name = "Solo", this.input = this.output = new j({
      context: this.context
    }), Rt._allSolos.has(this.context) || Rt._allSolos.set(this.context, /* @__PURE__ */ new Set()), Rt._allSolos.get(this.context).add(this), this.solo = t.solo;
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      solo: !1
    });
  }
  /**
   * Isolates this instance and mutes all other instances of Solo.
   * Only one instance can be soloed at a time. A soloed
   * instance will report `solo=false` when another instance is soloed.
   */
  get solo() {
    return this._isSoloed();
  }
  set solo(t) {
    t ? this._addSolo() : this._removeSolo(), Rt._allSolos.get(this.context).forEach((e) => e._updateSolo());
  }
  /**
   * If the current instance is muted, i.e. another instance is soloed
   */
  get muted() {
    return this.input.gain.value === 0;
  }
  /**
   * Add this to the soloed array
   */
  _addSolo() {
    Rt._soloed.has(this.context) || Rt._soloed.set(this.context, /* @__PURE__ */ new Set()), Rt._soloed.get(this.context).add(this);
  }
  /**
   * Remove this from the soloed array
   */
  _removeSolo() {
    Rt._soloed.has(this.context) && Rt._soloed.get(this.context).delete(this);
  }
  /**
   * Is this on the soloed array
   */
  _isSoloed() {
    return Rt._soloed.has(this.context) && Rt._soloed.get(this.context).has(this);
  }
  /**
   * Returns true if no one is soloed
   */
  _noSolos() {
    return !Rt._soloed.has(this.context) || // or has a solo set but doesn't include any items
    Rt._soloed.has(this.context) && Rt._soloed.get(this.context).size === 0;
  }
  /**
   * Solo the current instance and unsolo all other instances.
   */
  _updateSolo() {
    this._isSoloed() ? this.input.gain.value = 1 : this._noSolos() ? this.input.gain.value = 1 : this.input.gain.value = 0;
  }
  dispose() {
    return super.dispose(), Rt._allSolos.get(this.context).delete(this), this._removeSolo(), this;
  }
}
Rt._allSolos = /* @__PURE__ */ new Map();
Rt._soloed = /* @__PURE__ */ new Map();
class ma extends B {
  constructor() {
    const t = L(ma.getDefaults(), arguments, [
      "pan",
      "volume"
    ]);
    super(t), this.name = "PanVol", this._panner = this.input = new Dn({
      context: this.context,
      pan: t.pan,
      channelCount: t.channelCount
    }), this.pan = this._panner.pan, this._volume = this.output = new Os({
      context: this.context,
      volume: t.volume
    }), this.volume = this._volume.volume, this._panner.connect(this._volume), this.mute = t.mute, Z(this, ["pan", "volume"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      mute: !1,
      pan: 0,
      volume: 0,
      channelCount: 1
    });
  }
  /**
   * Mute/unmute the volume
   */
  get mute() {
    return this._volume.mute;
  }
  set mute(t) {
    this._volume.mute = t;
  }
  dispose() {
    return super.dispose(), this._panner.dispose(), this.pan.dispose(), this._volume.dispose(), this.volume.dispose(), this;
  }
}
class vn extends B {
  constructor() {
    const t = L(vn.getDefaults(), arguments, [
      "volume",
      "pan"
    ]);
    super(t), this.name = "Channel", this._solo = this.input = new Rt({
      solo: t.solo,
      context: this.context
    }), this._panVol = this.output = new ma({
      context: this.context,
      pan: t.pan,
      volume: t.volume,
      mute: t.mute,
      channelCount: t.channelCount
    }), this.pan = this._panVol.pan, this.volume = this._panVol.volume, this._solo.connect(this._panVol), Z(this, ["pan", "volume"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      pan: 0,
      volume: 0,
      mute: !1,
      solo: !1,
      channelCount: 1
    });
  }
  /**
   * Solo/unsolo the channel. Soloing is only relative to other {@link Channel}s and {@link Solo} instances
   */
  get solo() {
    return this._solo.solo;
  }
  set solo(t) {
    this._solo.solo = t;
  }
  /**
   * If the current instance is muted, i.e. another instance is soloed,
   * or the channel is muted
   */
  get muted() {
    return this._solo.muted || this.mute;
  }
  /**
   * Mute/unmute the volume
   */
  get mute() {
    return this._panVol.mute;
  }
  set mute(t) {
    this._panVol.mute = t;
  }
  /**
   * Get the gain node belonging to the bus name. Create it if
   * it doesn't exist
   * @param name The bus name
   */
  _getBus(t) {
    return vn.buses.has(t) || vn.buses.set(t, new j({ context: this.context })), vn.buses.get(t);
  }
  /**
   * Send audio to another channel using a string. `send` is a lot like
   * {@link connect}, except it uses a string instead of an object. This can
   * be useful in large applications to decouple sections since {@link send}
   * and {@link receive} can be invoked separately in order to connect an object
   * @param name The channel name to send the audio
   * @param volume The amount of the signal to send.
   * 	Defaults to 0db, i.e. send the entire signal
   * @returns Returns the gain node of this connection.
   */
  send(t, e = 0) {
    const s = this._getBus(t), i = new j({
      context: this.context,
      units: "decibels",
      gain: e
    });
    return this.connect(i), i.connect(s), i;
  }
  /**
   * Receive audio from a channel which was connected with {@link send}.
   * @param name The channel name to receive audio from.
   */
  receive(t) {
    return this._getBus(t).connect(this), this;
  }
  dispose() {
    return super.dispose(), this._panVol.dispose(), this.pan.dispose(), this.volume.dispose(), this._solo.dispose(), this;
  }
}
vn.buses = /* @__PURE__ */ new Map();
class kh extends B {
  constructor() {
    super(L(kh.getDefaults(), arguments)), this.name = "Mono", this.input = new j({ context: this.context }), this._merge = this.output = new en({
      channels: 2,
      context: this.context
    }), this.input.connect(this._merge, 0, 0), this.input.connect(this._merge, 0, 1);
  }
  dispose() {
    return super.dispose(), this._merge.dispose(), this.input.dispose(), this;
  }
}
class Or extends B {
  constructor() {
    const t = L(Or.getDefaults(), arguments, ["lowFrequency", "highFrequency"]);
    super(t), this.name = "MultibandSplit", this.input = new j({ context: this.context }), this.output = void 0, this.low = new Ce({
      context: this.context,
      frequency: 0,
      type: "lowpass"
    }), this._lowMidFilter = new Ce({
      context: this.context,
      frequency: 0,
      type: "highpass"
    }), this.mid = new Ce({
      context: this.context,
      frequency: 0,
      type: "lowpass"
    }), this.high = new Ce({
      context: this.context,
      frequency: 0,
      type: "highpass"
    }), this._internalChannels = [this.low, this.mid, this.high], this.lowFrequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.lowFrequency
    }), this.highFrequency = new Q({
      context: this.context,
      units: "frequency",
      value: t.highFrequency
    }), this.Q = new Q({
      context: this.context,
      units: "positive",
      value: t.Q
    }), this.input.fan(this.low, this.high), this.input.chain(this._lowMidFilter, this.mid), this.lowFrequency.fan(this.low.frequency, this._lowMidFilter.frequency), this.highFrequency.fan(this.mid.frequency, this.high.frequency), this.Q.connect(this.low.Q), this.Q.connect(this._lowMidFilter.Q), this.Q.connect(this.mid.Q), this.Q.connect(this.high.Q), Z(this, ["high", "mid", "low", "highFrequency", "lowFrequency"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      Q: 1,
      highFrequency: 2500,
      lowFrequency: 400
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), vr(this, ["high", "mid", "low", "highFrequency", "lowFrequency"]), this.low.dispose(), this._lowMidFilter.dispose(), this.mid.dispose(), this.high.dispose(), this.lowFrequency.dispose(), this.highFrequency.dispose(), this.Q.dispose(), this;
  }
}
class Ch extends B {
  constructor() {
    const t = L(Ch.getDefaults(), arguments, ["positionX", "positionY", "positionZ"]);
    super(t), this.name = "Panner3D", this._panner = this.input = this.output = this.context.createPanner(), this.panningModel = t.panningModel, this.maxDistance = t.maxDistance, this.distanceModel = t.distanceModel, this.coneOuterGain = t.coneOuterGain, this.coneOuterAngle = t.coneOuterAngle, this.coneInnerAngle = t.coneInnerAngle, this.refDistance = t.refDistance, this.rolloffFactor = t.rolloffFactor, this.positionX = new tt({
      context: this.context,
      param: this._panner.positionX,
      value: t.positionX
    }), this.positionY = new tt({
      context: this.context,
      param: this._panner.positionY,
      value: t.positionY
    }), this.positionZ = new tt({
      context: this.context,
      param: this._panner.positionZ,
      value: t.positionZ
    }), this.orientationX = new tt({
      context: this.context,
      param: this._panner.orientationX,
      value: t.orientationX
    }), this.orientationY = new tt({
      context: this.context,
      param: this._panner.orientationY,
      value: t.orientationY
    }), this.orientationZ = new tt({
      context: this.context,
      param: this._panner.orientationZ,
      value: t.orientationZ
    });
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      coneInnerAngle: 360,
      coneOuterAngle: 360,
      coneOuterGain: 0,
      distanceModel: "inverse",
      maxDistance: 1e4,
      orientationX: 0,
      orientationY: 0,
      orientationZ: 0,
      panningModel: "equalpower",
      positionX: 0,
      positionY: 0,
      positionZ: 0,
      refDistance: 1,
      rolloffFactor: 1
    });
  }
  /**
   * Sets the position of the source in 3d space.
   */
  setPosition(t, e, s) {
    return this.positionX.value = t, this.positionY.value = e, this.positionZ.value = s, this;
  }
  /**
   * Sets the orientation of the source in 3d space.
   */
  setOrientation(t, e, s) {
    return this.orientationX.value = t, this.orientationY.value = e, this.orientationZ.value = s, this;
  }
  /**
   * The panning model. Either "equalpower" or "HRTF".
   */
  get panningModel() {
    return this._panner.panningModel;
  }
  set panningModel(t) {
    this._panner.panningModel = t;
  }
  /**
   * A reference distance for reducing volume as source move further from the listener
   */
  get refDistance() {
    return this._panner.refDistance;
  }
  set refDistance(t) {
    this._panner.refDistance = t;
  }
  /**
   * Describes how quickly the volume is reduced as source moves away from listener.
   */
  get rolloffFactor() {
    return this._panner.rolloffFactor;
  }
  set rolloffFactor(t) {
    this._panner.rolloffFactor = t;
  }
  /**
   * The distance model used by,  "linear", "inverse", or "exponential".
   */
  get distanceModel() {
    return this._panner.distanceModel;
  }
  set distanceModel(t) {
    this._panner.distanceModel = t;
  }
  /**
   * The angle, in degrees, inside of which there will be no volume reduction
   */
  get coneInnerAngle() {
    return this._panner.coneInnerAngle;
  }
  set coneInnerAngle(t) {
    this._panner.coneInnerAngle = t;
  }
  /**
   * The angle, in degrees, outside of which the volume will be reduced
   * to a constant value of coneOuterGain
   */
  get coneOuterAngle() {
    return this._panner.coneOuterAngle;
  }
  set coneOuterAngle(t) {
    this._panner.coneOuterAngle = t;
  }
  /**
   * The gain outside of the coneOuterAngle
   */
  get coneOuterGain() {
    return this._panner.coneOuterGain;
  }
  set coneOuterGain(t) {
    this._panner.coneOuterGain = t;
  }
  /**
   * The maximum distance between source and listener,
   * after which the volume will not be reduced any further.
   */
  get maxDistance() {
    return this._panner.maxDistance;
  }
  set maxDistance(t) {
    this._panner.maxDistance = t;
  }
  dispose() {
    return super.dispose(), this._panner.disconnect(), this.orientationX.dispose(), this.orientationY.dispose(), this.orientationZ.dispose(), this.positionX.dispose(), this.positionY.dispose(), this.positionZ.dispose(), this;
  }
}
class Go extends B {
  constructor() {
    const t = L(Go.getDefaults(), arguments);
    super(t), this.name = "Recorder", this.input = new j({
      context: this.context
    }), X(Go.supported, "Media Recorder API is not available"), this._stream = this.context.createMediaStreamDestination(), this.input.connect(this._stream), this._recorder = new MediaRecorder(this._stream.stream, {
      mimeType: t.mimeType
    });
  }
  static getDefaults() {
    return B.getDefaults();
  }
  /**
   * The mime type is the format that the audio is encoded in. For Chrome
   * that is typically webm encoded as "vorbis".
   */
  get mimeType() {
    return this._recorder.mimeType;
  }
  /**
   * Test if your platform supports the Media Recorder API. If it's not available,
   * try installing this (polyfill)[https://www.npmjs.com/package/audio-recorder-polyfill].
   */
  static get supported() {
    return oe !== null && Reflect.has(oe, "MediaRecorder");
  }
  /**
   * Get the playback state of the Recorder, either "started", "stopped" or "paused"
   */
  get state() {
    return this._recorder.state === "inactive" ? "stopped" : this._recorder.state === "paused" ? "paused" : "started";
  }
  /**
   * Start/Resume the Recorder. Returns a promise which resolves
   * when the recorder has started.
   */
  start() {
    return yt(this, void 0, void 0, function* () {
      X(this.state !== "started", "Recorder is already started");
      const t = new Promise((e) => {
        const s = () => {
          this._recorder.removeEventListener("start", s, !1), e();
        };
        this._recorder.addEventListener("start", s, !1);
      });
      return this.state === "stopped" ? this._recorder.start() : this._recorder.resume(), yield t;
    });
  }
  /**
   * Stop the recorder. Returns a promise with the recorded content until this point
   * encoded as {@link mimeType}
   */
  stop() {
    return yt(this, void 0, void 0, function* () {
      X(this.state !== "stopped", "Recorder is not started");
      const t = new Promise((e) => {
        const s = (i) => {
          this._recorder.removeEventListener("dataavailable", s, !1), e(i.data);
        };
        this._recorder.addEventListener("dataavailable", s, !1);
      });
      return this._recorder.stop(), yield t;
    });
  }
  /**
   * Pause the recorder
   */
  pause() {
    return X(this.state === "started", "Recorder must be started"), this._recorder.pause(), this;
  }
  dispose() {
    return super.dispose(), this.input.dispose(), this._stream.disconnect(), this;
  }
}
class Ps extends B {
  constructor() {
    const t = L(Ps.getDefaults(), arguments, ["threshold", "ratio"]);
    super(t), this.name = "Compressor", this._compressor = this.context.createDynamicsCompressor(), this.input = this._compressor, this.output = this._compressor, this.threshold = new tt({
      minValue: this._compressor.threshold.minValue,
      maxValue: this._compressor.threshold.maxValue,
      context: this.context,
      convert: !1,
      param: this._compressor.threshold,
      units: "decibels",
      value: t.threshold
    }), this.attack = new tt({
      minValue: this._compressor.attack.minValue,
      maxValue: this._compressor.attack.maxValue,
      context: this.context,
      param: this._compressor.attack,
      units: "time",
      value: t.attack
    }), this.release = new tt({
      minValue: this._compressor.release.minValue,
      maxValue: this._compressor.release.maxValue,
      context: this.context,
      param: this._compressor.release,
      units: "time",
      value: t.release
    }), this.knee = new tt({
      minValue: this._compressor.knee.minValue,
      maxValue: this._compressor.knee.maxValue,
      context: this.context,
      convert: !1,
      param: this._compressor.knee,
      units: "decibels",
      value: t.knee
    }), this.ratio = new tt({
      minValue: this._compressor.ratio.minValue,
      maxValue: this._compressor.ratio.maxValue,
      context: this.context,
      convert: !1,
      param: this._compressor.ratio,
      units: "positive",
      value: t.ratio
    }), Z(this, ["knee", "release", "attack", "ratio", "threshold"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      attack: 3e-3,
      knee: 30,
      ratio: 12,
      release: 0.25,
      threshold: -24
    });
  }
  /**
   * A read-only decibel value for metering purposes, representing the current amount of gain
   * reduction that the compressor is applying to the signal. If fed no signal the value will be 0 (no gain reduction).
   */
  get reduction() {
    return this._compressor.reduction;
  }
  dispose() {
    return super.dispose(), this._compressor.disconnect(), this.attack.dispose(), this.release.dispose(), this.threshold.dispose(), this.ratio.dispose(), this.knee.dispose(), this;
  }
}
class Ah extends B {
  constructor() {
    const t = L(Ah.getDefaults(), arguments, [
      "threshold",
      "smoothing"
    ]);
    super(t), this.name = "Gate", this._follower = new Ir({
      context: this.context,
      smoothing: t.smoothing
    }), this._gt = new da({
      context: this.context,
      value: ni(t.threshold)
    }), this.input = new j({ context: this.context }), this._gate = this.output = new j({ context: this.context }), this.input.connect(this._gate), this.input.chain(this._follower, this._gt, this._gate.gain);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      smoothing: 0.1,
      threshold: -40
    });
  }
  /**
   * The threshold of the gate in decibels
   */
  get threshold() {
    return br(this._gt.value);
  }
  set threshold(t) {
    this._gt.value = ni(t);
  }
  /**
   * The attack/decay speed of the gate.
   * @see {@link Follower.smoothing}
   */
  get smoothing() {
    return this._follower.smoothing;
  }
  set smoothing(t) {
    this._follower.smoothing = t;
  }
  dispose() {
    return super.dispose(), this.input.dispose(), this._follower.dispose(), this._gt.dispose(), this._gate.dispose(), this;
  }
}
class Eh extends B {
  constructor() {
    const t = L(Eh.getDefaults(), arguments, [
      "threshold"
    ]);
    super(t), this.name = "Limiter", this._compressor = this.input = this.output = new Ps({
      context: this.context,
      ratio: 20,
      attack: 3e-3,
      release: 0.01,
      threshold: t.threshold
    }), this.threshold = this._compressor.threshold, Z(this, "threshold");
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      threshold: -12
    });
  }
  /**
   * A read-only decibel value for metering purposes, representing the current amount of gain
   * reduction that the compressor is applying to the signal.
   */
  get reduction() {
    return this._compressor.reduction;
  }
  dispose() {
    return super.dispose(), this._compressor.dispose(), this.threshold.dispose(), this;
  }
}
class Ph extends B {
  constructor() {
    const t = L(Ph.getDefaults(), arguments);
    super(t), this.name = "MidSideCompressor", this._midSideSplit = this.input = new Fr({
      context: this.context
    }), this._midSideMerge = this.output = new Rr({
      context: this.context
    }), this.mid = new Ps(Object.assign(t.mid, { context: this.context })), this.side = new Ps(Object.assign(t.side, { context: this.context })), this._midSideSplit.mid.chain(this.mid, this._midSideMerge.mid), this._midSideSplit.side.chain(this.side, this._midSideMerge.side), Z(this, ["mid", "side"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      mid: {
        ratio: 3,
        threshold: -24,
        release: 0.03,
        attack: 0.02,
        knee: 16
      },
      side: {
        ratio: 6,
        threshold: -30,
        release: 0.25,
        attack: 0.03,
        knee: 10
      }
    });
  }
  dispose() {
    return super.dispose(), this.mid.dispose(), this.side.dispose(), this._midSideSplit.dispose(), this._midSideMerge.dispose(), this;
  }
}
class Ih extends B {
  constructor() {
    const t = L(Ih.getDefaults(), arguments);
    super(t), this.name = "MultibandCompressor", this._splitter = this.input = new Or({
      context: this.context,
      lowFrequency: t.lowFrequency,
      highFrequency: t.highFrequency
    }), this.lowFrequency = this._splitter.lowFrequency, this.highFrequency = this._splitter.highFrequency, this.output = new j({ context: this.context }), this.low = new Ps(Object.assign(t.low, { context: this.context })), this.mid = new Ps(Object.assign(t.mid, { context: this.context })), this.high = new Ps(Object.assign(t.high, { context: this.context })), this._splitter.low.chain(this.low, this.output), this._splitter.mid.chain(this.mid, this.output), this._splitter.high.chain(this.high, this.output), Z(this, ["high", "mid", "low", "highFrequency", "lowFrequency"]);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      lowFrequency: 250,
      highFrequency: 2e3,
      low: {
        ratio: 6,
        threshold: -30,
        release: 0.25,
        attack: 0.03,
        knee: 10
      },
      mid: {
        ratio: 3,
        threshold: -24,
        release: 0.03,
        attack: 0.02,
        knee: 16
      },
      high: {
        ratio: 3,
        threshold: -24,
        release: 0.03,
        attack: 0.02,
        knee: 16
      }
    });
  }
  dispose() {
    return super.dispose(), this._splitter.dispose(), this.low.dispose(), this.mid.dispose(), this.high.dispose(), this.output.dispose(), this;
  }
}
class Fh extends B {
  constructor() {
    const t = L(Fh.getDefaults(), arguments, [
      "low",
      "mid",
      "high"
    ]);
    super(t), this.name = "EQ3", this.output = new j({ context: this.context }), this._internalChannels = [], this.input = this._multibandSplit = new Or({
      context: this.context,
      highFrequency: t.highFrequency,
      lowFrequency: t.lowFrequency
    }), this._lowGain = new j({
      context: this.context,
      gain: t.low,
      units: "decibels"
    }), this._midGain = new j({
      context: this.context,
      gain: t.mid,
      units: "decibels"
    }), this._highGain = new j({
      context: this.context,
      gain: t.high,
      units: "decibels"
    }), this.low = this._lowGain.gain, this.mid = this._midGain.gain, this.high = this._highGain.gain, this.Q = this._multibandSplit.Q, this.lowFrequency = this._multibandSplit.lowFrequency, this.highFrequency = this._multibandSplit.highFrequency, this._multibandSplit.low.chain(this._lowGain, this.output), this._multibandSplit.mid.chain(this._midGain, this.output), this._multibandSplit.high.chain(this._highGain, this.output), Z(this, ["low", "mid", "high", "lowFrequency", "highFrequency"]), this._internalChannels = [this._multibandSplit];
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      high: 0,
      highFrequency: 2500,
      low: 0,
      lowFrequency: 400,
      mid: 0
    });
  }
  /**
   * Clean up.
   */
  dispose() {
    return super.dispose(), vr(this, ["low", "mid", "high", "lowFrequency", "highFrequency"]), this._multibandSplit.dispose(), this.lowFrequency.dispose(), this.highFrequency.dispose(), this._lowGain.dispose(), this._midGain.dispose(), this._highGain.dispose(), this.low.dispose(), this.mid.dispose(), this.high.dispose(), this.Q.dispose(), this;
  }
}
class Rh extends B {
  constructor() {
    const t = L(Rh.getDefaults(), arguments, ["url", "onload"]);
    super(t), this.name = "Convolver", this._convolver = this.context.createConvolver(), this._buffer = new ot(t.url, (e) => {
      this.buffer = e, t.onload();
    }), this.input = new j({ context: this.context }), this.output = new j({ context: this.context }), this._buffer.loaded && (this.buffer = this._buffer), this.normalize = t.normalize, this.input.chain(this._convolver, this.output);
  }
  static getDefaults() {
    return Object.assign(B.getDefaults(), {
      normalize: !0,
      onload: st
    });
  }
  /**
   * Load an impulse response url as an audio buffer.
   * Decodes the audio asynchronously and invokes
   * the callback once the audio buffer loads.
   * @param url The url of the buffer to load. filetype support depends on the browser.
   */
  load(t) {
    return yt(this, void 0, void 0, function* () {
      this.buffer = yield this._buffer.load(t);
    });
  }
  /**
   * The convolver's buffer
   */
  get buffer() {
    return this._buffer.length ? this._buffer : null;
  }
  set buffer(t) {
    t && this._buffer.set(t), this._convolver.buffer && (this.input.disconnect(), this._convolver.disconnect(), this._convolver = this.context.createConvolver(), this.input.chain(this._convolver, this.output));
    const e = this._buffer.get();
    this._convolver.buffer = e || null;
  }
  /**
   * The normalize property of the ConvolverNode interface is a boolean that
   * controls whether the impulse response from the buffer will be scaled by
   * an equal-power normalization when the buffer attribute is set, or not.
   */
  get normalize() {
    return this._convolver.normalize;
  }
  set normalize(t) {
    this._convolver.normalize = t;
  }
  dispose() {
    return super.dispose(), this._buffer.dispose(), this._convolver.disconnect(), this;
  }
}
function jn() {
  return ut().now();
}
function kC() {
  return ut().immediate();
}
const CC = ut().transport;
function je() {
  return ut().transport;
}
const AC = ut().destination, EC = ut().destination;
function PC() {
  return ut().destination;
}
const IC = ut().listener;
function FC() {
  return ut().listener;
}
const RC = ut().draw;
function DC() {
  return ut().draw;
}
const Xe = ut();
function OC() {
  return ot.loaded();
}
const NC = ot, LC = bi, VC = tn, BC = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  AMOscillator: Tr,
  AMSynth: jc,
  Abs: Sg,
  Add: In,
  AmplitudeEnvelope: Mi,
  Analyser: Dr,
  AudioToGain: ca,
  AutoFilter: ih,
  AutoPanner: rh,
  AutoWah: oh,
  BaseContext: Dc,
  BiquadFilter: lr,
  BitCrusher: ah,
  Buffer: NC,
  BufferSource: VC,
  Buffers: LC,
  Channel: vn,
  Chebyshev: ch,
  Chorus: hh,
  Clock: vi,
  Compressor: Ps,
  Context: yi,
  Convolver: Rh,
  CrossFade: ki,
  DCMeter: Th,
  Delay: Pe,
  Destination: AC,
  Distortion: uh,
  Draw: RC,
  DuoSynth: Xc,
  EQ3: Fh,
  Emitter: gi,
  Envelope: Qt,
  FFT: Sh,
  FMOscillator: Si,
  FMSynth: Yc,
  FatOscillator: Mr,
  FeedbackCombFilter: Ar,
  FeedbackDelay: dh,
  Filter: Ce,
  Follower: Ir,
  Freeverb: ph,
  Frequency: Qk,
  FrequencyClass: ce,
  FrequencyEnvelope: cr,
  FrequencyShifter: fh,
  Gain: j,
  GainToAudio: Tg,
  Gate: Ah,
  GrainPlayer: $c,
  GreaterThan: da,
  GreaterThanZero: ua,
  IntervalTimeline: bg,
  JCReverb: mh,
  LFO: he,
  Limiter: Eh,
  Listener: IC,
  Loop: hr,
  LowpassCombFilter: Pr,
  Master: EC,
  MembraneSynth: Cr,
  Merge: en,
  MetalSynth: Zc,
  Meter: wh,
  MidSideCompressor: Ph,
  MidSideMerge: Rr,
  MidSideSplit: Fr,
  Midi: nC,
  MidiClass: oi,
  Mono: kh,
  MonoSynth: _n,
  MultibandCompressor: Ih,
  MultibandSplit: Or,
  Multiply: Mt,
  Negate: Hc,
  Noise: Ys,
  NoiseSynth: Kc,
  Offline: sC,
  OfflineContext: xi,
  OmniOscillator: Fs,
  OnePoleFilter: Er,
  Oscillator: Tt,
  PWMOscillator: kr,
  PanVol: ma,
  Panner: Dn,
  Panner3D: Ch,
  Param: tt,
  Part: ai,
  Pattern: sh,
  Phaser: yh,
  PingPongDelay: gh,
  PitchShift: pa,
  Player: Fn,
  Players: Wc,
  PluckSynth: th,
  PolySynth: eh,
  Pow: wi,
  PulseOscillator: Ti,
  Recorder: Go,
  Reverb: xh,
  Sampler: kn,
  Scale: Rs,
  ScaleExp: fa,
  Sequence: nh,
  Signal: Q,
  Solo: Rt,
  Split: On,
  StateTimeline: _i,
  StereoWidener: _h,
  Subtract: Rn,
  SyncedSignal: cC,
  Synth: Zs,
  Ticks: iC,
  TicksClass: St,
  Time: Yk,
  TimeClass: ke,
  Timeline: Ee,
  ToneAudioBuffer: ot,
  ToneAudioBuffers: bi,
  ToneAudioNode: B,
  ToneBufferSource: tn,
  ToneEvent: ls,
  ToneOscillatorNode: Sr,
  Transport: CC,
  TransportTime: Jk,
  TransportTimeClass: Lt,
  Tremolo: vh,
  Unit: aC,
  UserMedia: Xi,
  Vibrato: bh,
  Volume: Os,
  WaveShaper: ss,
  Waveform: Mh,
  Zero: ha,
  connect: ue,
  connectSeries: Fe,
  connectSignal: wr,
  context: Xe,
  dbToGain: ni,
  debug: Dk,
  defaultArg: Ve,
  disconnect: Vc,
  fanIn: tC,
  ftom: Us,
  gainToDb: br,
  getContext: ut,
  getDestination: PC,
  getDraw: DC,
  getListener: FC,
  getTransport: je,
  immediate: kC,
  intervalToFrequencyRatio: ii,
  isArray: Kt,
  isBoolean: Pc,
  isDefined: et,
  isFunction: fg,
  isNote: Ui,
  isNumber: Ie,
  isObject: Es,
  isString: Qe,
  isUndef: ve,
  loaded: OC,
  mtof: Nc,
  now: jn,
  optionsFromArguments: L,
  setContext: zo,
  start: Oc,
  supported: Fk,
  version: uc
}, Symbol.toStringTag, { value: "Module" }));
class zC {
  constructor() {
    this.masterTime = 0, this.startTime = 0, this.isRunning = !1, this.audioContextStartTime = 0, this.toneTransportStartTime = 0, this.seekLookaheadOverride = null, this.state = {
      nowTime: 0,
      // Current playback position
      totalTime: 0,
      // Total duration
      isPlaying: !1,
      // Playing state
      tempo: 120,
      // Tempo (BPM)
      originalTempo: 120,
      // Baseline tempo for scaling
      masterVolume: 1,
      // Master volume
      // Loop control
      loopMode: "off",
      globalRepeat: !1,
      markerA: null,
      // A marker
      markerB: null,
      // B marker
      // Generation token to prevent ghost audio
      generation: 0,
      playbackGeneration: 0
      // Legacy compatibility
    }, this.playerGroups = [];
  }
  /**
   * Get current master time
   */
  getCurrentTime() {
    if (!this.isRunning)
      return this.masterTime;
    const e = Xe.currentTime - this.audioContextStartTime;
    if (e < 0)
      return this.startTime;
    const s = this.state.originalTempo > 0 ? this.state.originalTempo : 120, i = Math.max(0.1, this.state.tempo / s);
    return this.startTime + e * i;
  }
  /**
   * Convert master time to AudioContext time
   */
  toAudioContextTime(t, e = 0) {
    const s = Xe.currentTime;
    if (!isFinite(s) || isNaN(s))
      return console.warn("[AudioMasterClock] Invalid Tone.context.currentTime:", s), 0;
    const i = this.getCurrentTime();
    return !isFinite(i) || isNaN(i) ? (console.warn("[AudioMasterClock] Invalid getCurrentTime():", i), s + e) : s + e + (t - i);
  }
  /**
   * Convert master time to Tone.js Transport time
   */
  toToneTransportTime(t) {
    return t;
  }
  /**
   * Register player group
   */
  registerPlayerGroup(t) {
    this.playerGroups.push(t);
  }
  /**
   * Start unified playback - synchronize all player groups perfectly
   */
  async startPlayback(t = 0, e = 0.1) {
    this.state.generation += 1, this.state.playbackGeneration += 1;
    const s = this.state.generation, r = t === 0 && this.masterTime > 0 ? this.masterTime : t;
    this.masterTime = r, this.startTime = r;
    const o = Math.max(0.15, e);
    this.audioContextStartTime = Xe.currentTime + o, this.toneTransportStartTime = this.audioContextStartTime, this.state.nowTime = r, this.state.isPlaying = !0;
    const a = je();
    a.seconds = r;
    const l = this.toAudioContextTime(r, o), c = 0, h = this.playerGroups.map(async (u) => {
      if (this.state.generation === s)
        try {
          await u.startSynchronized({
            audioContextTime: l,
            toneTransportTime: c,
            masterTime: r,
            generation: s,
            mode: "play"
          });
        } catch (d) {
          console.error("[AudioMasterClock] Failed to start group:", u.constructor.name, d);
        }
    });
    a.seconds = r, a.start(l), Promise.allSettled(h).catch(() => {
    }), this.state.generation === s && (this.isRunning = !0);
  }
  /**
   * Stop playback
   */
  stopPlayback() {
    this.isRunning = !1, this.state.isPlaying = !1, this.state.generation += 1, je().stop(), this.playerGroups.forEach((e) => {
      try {
        e.stopSynchronized();
      } catch (s) {
        console.error("[AudioMasterClock] Failed to stop group:", e.constructor.name, s);
      }
    });
  }
  pausePlayback() {
    if (this.isRunning) {
      const e = this.getCurrentTime();
      this.masterTime = e, this.state.nowTime = e;
    }
    this.isRunning = !1, this.state.isPlaying = !1, je().pause(), this.playerGroups.forEach((e) => {
      try {
        e.stopSynchronized();
      } catch (s) {
        console.error("[AudioMasterClock] Failed to pause group:", e.constructor.name, s);
      }
    });
  }
  /**
   * Seek to specific time
   */
  seekTo(t) {
    this.masterTime = t, this.state.nowTime = t, this.state.generation += 1;
    const e = this.state.generation, s = je();
    if (!this.isRunning) {
      s.seconds = t, this.playerGroups.forEach((a) => {
        try {
          a.seekTo(t);
        } catch (l) {
          console.error("[AudioMasterClock] Failed to seek group:", a.constructor.name, l);
        }
      });
      return;
    }
    const r = this.seekLookaheadOverride ?? 0.2;
    this.seekLookaheadOverride = null, this.audioContextStartTime = Xe.currentTime + r, this.toneTransportStartTime = 0, this.startTime = t, this.playerGroups.forEach((a) => {
      try {
        a.stopSynchronized();
      } catch (l) {
        console.error("[AudioMasterClock] Failed to stop group before seek restart:", a.constructor.name, l);
      }
    }), s.stop(), s.seconds = t;
    const o = this.playerGroups.map(async (a) => {
      try {
        await a.startSynchronized({
          audioContextTime: this.audioContextStartTime,
          // align exactly with Transport.start anchor
          toneTransportTime: 0,
          masterTime: t,
          generation: e,
          mode: "seek"
        });
      } catch (l) {
        console.error("[AudioMasterClock] Failed to restart group on seek:", a.constructor.name, l);
      }
    });
    s.start(this.audioContextStartTime), this.isRunning = !0, Promise.allSettled(o).catch(() => {
    });
  }
  /**
   * Seek with a custom lookahead, used for seamless retime (e.g., live tempo changes).
   */
  seekToWithLookahead(t, e) {
    (!Number.isFinite(e) || e < 0) && (e = 0.05), this.seekLookaheadOverride = e, this.seekTo(t);
  }
  /**
   * Set tempo
   */
  setTempo(t) {
    this.state.tempo, this.state.tempo = t, this.state.generation += 1;
    const e = je();
    e.bpm.value = t, this.playerGroups.forEach((s) => {
      try {
        s.setTempo(t);
      } catch (i) {
        console.error("[AudioMasterClock] Failed to set tempo for group:", s.constructor.name, i);
      }
    });
  }
  /**
   * Set baseline/original tempo. Does not start/stop playback.
   */
  setOriginalTempo(t) {
    !Number.isFinite(t) || t <= 0 || (this.state.originalTempo = t);
  }
  /**
   * Set master volume
   */
  setMasterVolume(t) {
    this.state.masterVolume = Math.max(0, Math.min(1, t)), this.playerGroups.forEach((e) => {
      try {
        e.setMasterVolume(this.state.masterVolume);
      } catch (s) {
        console.error("[AudioMasterClock] Failed to set master volume for group:", e.constructor.name, s);
      }
    });
  }
  /**
   * Set loop mode
   */
  setLoopMode(t, e, s) {
    this.state.loopMode = t, e !== void 0 && (this.state.markerA = e), s !== void 0 && (this.state.markerB = s), this.playerGroups.forEach((i) => {
      try {
        i.setLoop(t, this.state.markerA, this.state.markerB);
      } catch (r) {
        console.error("[AudioMasterClock] Failed to set loop for group:", i.constructor.name, r);
      }
    });
  }
}
class qC {
  constructor() {
    this.audioPlayers = /* @__PURE__ */ new Map(), this.bufferLoadPromise = null, this.notifyBufferReady = null, this.activeAudioId = null, this.lastStartGen = null, this.masterVolume = 1, this.mixGain = 0.8, this.originalTempoBase = 120;
  }
  /**
   * Set buffer ready state callback
   */
  setBufferReadyCallback(t) {
    this.notifyBufferReady = t;
  }
  /**
   * Setup audio players
   */
  async setupAudioPlayersFromRegistry(t = {}) {
    const e = globalThis._waveRollAudio;
    if (!e?.getFiles)
      return;
    const s = e.getFiles();
    for (const i of s)
      this.audioPlayers.has(i.id) || await this.createPlayerEntry(i);
    this.startBufferMonitoring();
  }
  /**
   * Create individual player
   */
  async createPlayerEntry(t) {
    try {
      const e = new Fn({
        url: t.url,
        onload: () => {
          this.notifyBufferReady && this.notifyBufferReady();
        },
        onerror: (a) => {
          console.error("[WavPlayerGroup] Buffer load failed for", t.id, ":", a);
        }
      }), s = new pa({ pitch: 0 });
      try {
        s.windowSize = 0.03;
      } catch {
      }
      const i = new j(1), r = new Dn(t.pan ?? 0);
      e.connect(s), s.connect(i), i.connect(r), r.toDestination();
      const o = {
        player: e,
        pitchShift: s,
        gate: i,
        panner: r,
        effectLatencySec: 0.03,
        isStarted: !1,
        muted: t.isMuted || !1,
        startToken: 0,
        volume: 1,
        pan: t.pan ?? 0
      };
      this.audioPlayers.set(t.id, o);
      try {
        o.panner.pan.value = o.pan;
      } catch {
      }
      if (t.audioBuffer && ot)
        try {
          o.player.buffer = new ot(t.audioBuffer);
        } catch (a) {
          console.warn("[WavPlayerGroup] Failed to use pre-decoded buffer for", t.id, ":", a);
        }
    } catch (e) {
      console.error("[WavPlayerGroup] Failed to create player for", t.id, ":", e);
    }
  }
  /**
   * Start buffer monitoring
   */
  startBufferMonitoring() {
    this.bufferLoadPromise || (this.bufferLoadPromise = new Promise((t) => {
      const e = () => {
        this.areAllBuffersReady() ? (t(), this.notifyBufferReady && this.notifyBufferReady()) : setTimeout(e, 100);
      };
      e();
    }));
  }
  /**
   * Wait until all WAV buffers are ready (or resolve immediately if none).
   */
  async waitUntilReady() {
    if (this.startBufferMonitoring(), !!this.bufferLoadPromise)
      try {
        await this.bufferLoadPromise;
      } catch {
      }
  }
  /**
   * Check if all buffers are ready
   */
  areAllBuffersReady() {
    try {
      const e = globalThis._waveRollAudio?.getFiles?.();
      for (const [s, i] of this.audioPlayers) {
        const o = !!e?.find((l) => l.id === s)?.audioBuffer, a = !!i.player.buffer && i.player.buffer?.loaded !== !1;
        if (!o && !a) return !1;
      }
      return !0;
    } catch {
      for (const [, t] of this.audioPlayers)
        if (!t.player.buffer || t.player.buffer?.loaded === !1)
          return !1;
      return !0;
    }
  }
  /**
   * PlayerGroup interface implementation: Synchronized start
   */
  async startSynchronized(t) {
    const e = t.generation;
    if (typeof e == "number") {
      if (this.lastStartGen === e)
        return;
      this.lastStartGen = e;
    }
    try {
      await this.setupAudioPlayersFromRegistry({});
    } catch (o) {
      console.error("[WavPlayerGroup] Setup failed:", o);
      return;
    }
    if (typeof e == "number" && this.lastStartGen !== e)
      return;
    if (this.bufferLoadPromise)
      try {
        await this.bufferLoadPromise;
      } catch (o) {
        console.error("[WavPlayerGroup] Buffer loading failed:", o);
      }
    if (typeof e == "number" && this.lastStartGen !== e)
      return;
    const s = globalThis._waveRollAudio;
    if (!s?.getFiles) {
      console.warn("[WavPlayerGroup] Audio API not available");
      return;
    }
    const i = s.getFiles();
    let r = 0;
    for (const o of i) {
      const a = this.audioPlayers.get(o.id);
      if (!a) {
        console.warn("[WavPlayerGroup] No player entry for", o.id);
        continue;
      }
      if (o.isVisible && (a.startToken = (a.startToken || 0) + 1, a.startToken, a.scheduledTimer && (clearTimeout(a.scheduledTimer), a.scheduledTimer = null), !!a.player.buffer?.loaded))
        try {
          a.isStarted && (a.player.stop(), a.isStarted = !1);
          const l = a.muted, c = this.masterVolume * this.mixGain * a.volume * (l ? 0 : 1);
          a.gate.gain.value = c;
          const h = a.player.buffer?.duration ?? o.audioBuffer?.duration ?? 0;
          let u = t.masterTime;
          h && (u < 0 || u > h - 1e-3) && (u = Math.max(0, Math.min(h - 1e-3, u)));
          const d = Math.max(0, Math.min(
            h > 0 ? h - 1e-3 : Number.POSITIVE_INFINITY,
            u
          ));
          a.player.start(t.audioContextTime, d), a.isStarted = !0, r++;
        } catch (l) {
          console.error("[WavPlayerGroup] Failed to start", o.id, ":", l);
        }
    }
  }
  /**
   * PlayerGroup interface implementation: Synchronized stop
   */
  stopSynchronized() {
    for (const [t, e] of this.audioPlayers)
      try {
        e.scheduledTimer && (clearTimeout(e.scheduledTimer), e.scheduledTimer = null), e.isStarted && (e.player.stop(), e.isStarted = !1), e.gate.gain.value = 0;
      } catch (s) {
        console.error("[WavPlayerGroup] Failed to stop", t, ":", s);
      }
  }
  /**
   * PlayerGroup interface implementation: Seek to time
   */
  seekTo(t) {
    this.stopSynchronized();
  }
  /**
   * PlayerGroup interface implementation: Set tempo
   */
  setTempo(t) {
    const e = this.originalTempoBase || 120, s = t / e, i = Math.max(1e-6, s), r = 12 * Math.log2(i);
    for (const [o, a] of this.audioPlayers)
      try {
        a.player.playbackRate = i, a.pitchShift.pitch = -r, a.effectLatencySec = 0.03;
      } catch (l) {
        console.error("[WavPlayerGroup] Failed to set tempo for", o, ":", l);
      }
  }
  /** Set baseline tempo used to compute playbackRate. */
  setOriginalTempoBase(t) {
    Number.isFinite(t) && t > 0 && (this.originalTempoBase = t);
  }
  /**
   * PlayerGroup interface implementation: Set master volume
   */
  setMasterVolume(t) {
    this.masterVolume = t;
    for (const [e, s] of this.audioPlayers)
      try {
        s.gate.gain.value = this.masterVolume * this.mixGain * s.volume * (s.muted ? 0 : 1);
      } catch (i) {
        console.error("[WavPlayerGroup] Failed to set master volume for", e, ":", i);
      }
  }
  /**
   * PlayerGroup interface implementation: Set loop
   */
  setLoop(t, e, s) {
  }
  // === Individual player control methods (user requirements) ===
  /**
   * Set individual WAV player volume
   */
  setPlayerVolume(t, e) {
    const s = this.audioPlayers.get(t);
    if (!s) {
      console.warn("[WavPlayerGroup] Player not found:", t, "→ attempting setup and retry");
      try {
        this.setupAudioPlayersFromRegistry({}).then(() => {
          const i = this.audioPlayers.get(t);
          i && (i.volume = Math.max(0, Math.min(1, e)), i.gate.gain.value = this.masterVolume * this.mixGain * i.volume * (i.muted ? 0 : 1));
        }).catch(() => {
        });
      } catch {
      }
      return;
    }
    s.volume = Math.max(0, Math.min(1, e)), s.gate.gain.value = this.masterVolume * this.mixGain * s.volume * (s.muted ? 0 : 1);
  }
  /**
   * Set individual WAV player pan
   */
  setPlayerPan(t, e) {
    const s = this.audioPlayers.get(t);
    if (!s) {
      console.warn("[WavPlayerGroup] Player not found:", t, "→ attempting setup and retry");
      try {
        this.setupAudioPlayersFromRegistry({}).then(() => {
          const i = this.audioPlayers.get(t);
          if (i) {
            i.pan = Math.max(-1, Math.min(1, e));
            try {
              i.panner.pan.value = i.pan;
            } catch {
            }
          }
        }).catch(() => {
        });
      } catch {
      }
      return;
    }
    s.pan = Math.max(-1, Math.min(1, e));
    try {
      s.panner.pan.value = s.pan;
    } catch {
    }
  }
  /**
   * Set individual WAV player mute
   */
  setPlayerMute(t, e) {
    const s = this.audioPlayers.get(t);
    if (!s) {
      console.warn("[WavPlayerGroup] Player not found:", t, "→ attempting setup and retry");
      try {
        this.setupAudioPlayersFromRegistry({}).then(() => {
          const i = this.audioPlayers.get(t);
          i && (i.muted = e, i.gate.gain.value = this.masterVolume * this.mixGain * i.volume * (i.muted ? 0 : 1));
        }).catch(() => {
        });
      } catch {
      }
      return;
    }
    s.muted = e, s.gate.gain.value = this.masterVolume * this.mixGain * s.volume * (s.muted ? 0 : 1);
  }
  /**
   * Adjust WAV group mix gain (0-1) to balance against MIDI group
   */
  setGroupMixGain(t) {
    this.mixGain = Math.max(0, Math.min(1, t));
    for (const [, e] of this.audioPlayers)
      e.gate.gain.value = this.masterVolume * this.mixGain * e.volume * (e.muted ? 0 : 1);
  }
  /**
   * Ensure a specific WAV player is started and aligned to the given master time.
   * Used when a track is unmuted or made visible during ongoing playback.
   */
  syncStartIfNeeded(t, e, s = 0.03) {
    const i = this.audioPlayers.get(t);
    if (i)
      try {
        const o = globalThis._waveRollAudio?.getFiles?.()?.find((l) => l.id === t);
        if (!o || !(!!o.isVisible && !i.muted) || !i.player.buffer?.loaded) return;
        if (!i.isStarted) {
          const l = jn() + s, c = this.masterVolume * i.volume;
          i.gate.gain.value = c, i.player.start(l, e), i.isStarted = !0;
        }
      } catch {
      }
  }
  /**
   * Iterate over all players and start any pending unmuted+visible players at the current master time.
   * Lightweight O(N) check, safe to call from a visual update loop.
   */
  syncPendingPlayers(t, e = 0.03) {
    try {
      const i = globalThis._waveRollAudio?.getFiles?.() || [];
      for (const [r, o] of this.audioPlayers) {
        const a = i.find((u) => u.id === r);
        if (!a || !(!!a.isVisible && !o.muted) || o.isStarted || !o.player.buffer?.loaded) continue;
        const c = jn() + e, h = this.masterVolume * o.volume;
        o.gate.gain.value = h, o.player.start(c, t), o.isStarted = !0;
      }
    } catch {
    }
  }
  /**
   * Get individual player states
   */
  getPlayerStates() {
    const t = {};
    for (const [e, s] of this.audioPlayers)
      t[e] = {
        volume: s.volume,
        pan: s.pan,
        muted: s.muted
      };
    return t;
  }
  /**
   * Resource cleanup
   */
  destroy() {
    this.stopSynchronized();
    for (const [t, e] of this.audioPlayers)
      try {
        e.player.dispose();
        try {
          e.pitchShift.dispose();
        } catch {
        }
        e.gate.dispose();
      } catch (s) {
        console.error("[WavPlayerGroup] Failed to dispose", t, ":", s);
      }
    this.audioPlayers.clear();
  }
}
const UC = {
  C3: "C3.mp3",
  "D#3": "Ds3.mp3",
  "F#3": "Fs3.mp3",
  A3: "A3.mp3",
  C4: "C4.mp3",
  "D#4": "Ds4.mp3",
  "F#4": "Fs4.mp3",
  A4: "A4.mp3"
}, $o = class $o {
  constructor() {
    this.players = /* @__PURE__ */ new Map(), this.part = null, this.notes = [], this.applyZeroEps = !1, this.tempoScale = 1, this.originalTempoBase = 120, this.lastStartGen = null, this.masterVolume = 1, this.midiManager = null, this.programSamplers = /* @__PURE__ */ new Map(), this.programSamplerLoading = /* @__PURE__ */ new Map(), this.pendingPlayerStates = /* @__PURE__ */ new Map(), this.errorStats = {
      totalNoteAttempts: 0,
      failedNotes: 0,
      invalidDataErrors: 0,
      synthErrors: 0,
      lastResetTime: Date.now()
    };
  }
  // --- Program Number-based Sampler Methods ---
  /**
   * Get or create a sampler for a specific MIDI Program Number (lazy loading).
   */
  getOrCreateProgramSampler(t) {
    const e = this.programSamplers.get(t);
    if (e)
      return Promise.resolve(e);
    const s = this.programSamplerLoading.get(t);
    if (s)
      return s;
    const i = new Promise((r, o) => {
      const a = Yb(t), l = new kn({
        urls: Zb,
        // Use flat notation for paulrosen soundfonts
        baseUrl: a,
        onload: () => {
          this.programSamplers.set(t, l), this.programSamplerLoading.delete(t), r(l);
        },
        onerror: (c) => {
          console.error(`[MidiPlayerGroup] Failed to load sampler for program ${t}:`, c), this.programSamplerLoading.delete(t), o(c);
        }
      }).toDestination();
    });
    return this.programSamplerLoading.set(t, i), i;
  }
  /**
   * Get the program sampler synchronously if already loaded.
   */
  getProgramSamplerSync(t) {
    return this.programSamplers.get(t) ?? null;
  }
  /**
   * Check if a program sampler is already loaded or currently loading.
   */
  isProgramLoadedOrLoading(t) {
    return this.programSamplers.has(t) || this.programSamplerLoading.has(t);
  }
  /**
   * Preload samplers for specific MIDI Program Numbers.
   * Useful for loading all programs used in a MIDI file at initialization.
   * @param programs - Array of MIDI Program Numbers to preload
   */
  async preloadProgramSamplers(t) {
    const s = [...new Set(t)].map(
      (i) => this.getOrCreateProgramSampler(i).catch((r) => (console.warn(`[MidiPlayerGroup] Failed to preload sampler for program ${i}:`, r), null))
    );
    await Promise.allSettled(s);
  }
  /**
   * Set MIDI manager (compatibility with existing code)
   */
  setMidiManager(t) {
    this.midiManager = t, t?.notes && (this.notes = t.notes);
  }
  /**
   * Initialize MIDI samplers
   */
  async initialize() {
    if (!this.notes.length) {
      console.warn("[MidiPlayerGroup] No notes available");
      return;
    }
    const t = new Set(this.notes.map((s) => s.fileId).filter(Boolean)), e = Array.from(t).map(async (s) => {
      if (s && !this.players.has(s))
        return this.createSamplerForFile(s);
    }).filter(Boolean);
    e.length > 0 && await Promise.all(e);
  }
  /**
   * Wait until all MIDI samplers are ready.
   */
  async waitUntilReady() {
    this.players.size > 0 || await this.initialize();
  }
  /**
   * Create sampler for file
   */
  async createSamplerForFile(t) {
    try {
      const s = await new Promise((l, c) => {
        const h = new kn({
          urls: UC,
          baseUrl: "https://tonejs.github.io/audio/salamander/",
          onload: () => {
            l(h);
          },
          onerror: (u) => {
            console.error("[MidiPlayerGroup] Failed to load sampler for", t, ":", u), c(u);
          }
        });
      }), i = new j(1), r = new Dn(0);
      s.connect(i), i.connect(r), r.toDestination();
      const o = {
        fileId: t,
        sampler: s,
        gate: i,
        panner: r,
        volume: 1,
        pan: 0,
        muted: !1
      };
      this.players.set(t, o);
      const a = this.pendingPlayerStates.get(t);
      a && (a.volume !== void 0 && this.setPlayerVolume(t, a.volume), a.pan !== void 0 && this.setPlayerPan(t, a.pan), a.muted !== void 0 && this.setPlayerMute(t, a.muted), this.pendingPlayerStates.delete(t));
    } catch (e) {
      throw console.error("[MidiPlayerGroup] Failed to create sampler for", t, ":", e), e;
    }
  }
  /**
   * Create MIDI Part
   */
  /**
   * Validate MIDI note data
   */
  validateMidiNote(t) {
    if (typeof t.time != "number" || !isFinite(t.time) || t.time < 0 || typeof t.duration != "number" || !isFinite(t.duration) || t.duration <= 0)
      return !1;
    if (typeof t.pitch == "number") {
      if (!isFinite(t.pitch) || t.pitch < 0 || t.pitch > 127)
        return !1;
    } else if (typeof t.pitch == "string") {
      if (!this.isValidNoteName(t.pitch))
        return !1;
    } else
      return !1;
    return !(typeof t.velocity != "number" || !isFinite(t.velocity) || t.velocity < 0 || t.velocity > 1);
  }
  /**
   * Validate note name format (supports standard notation like "C4", "C#4", "Bb3")
   */
  isValidNoteName(t) {
    return !t || typeof t != "string" ? !1 : /^[A-G][#b]?(?:-?[0-9])?$/.test(t);
  }
  /**
   * Normalize pitch input to consistent note name format
   * Handles both numeric MIDI notes (0-127) and string note names ('C#4', 'Db3', etc.)
   */
  normalizeNoteName(t) {
    return typeof t == "string" ? this.isValidNoteName(t) ? /[0-9]/.test(t) ? t : (console.warn(`[MidiPlayerGroup] Note missing octave information: ${t}. Original MIDI data may have been corrupted.`), "C4") : (console.warn(`[MidiPlayerGroup] Invalid note name: ${t}`), "C4") : this.midiNoteNumberToName(t);
  }
  /**
   * Sanitize and filter MIDI notes
   */
  /**
   * Update error statistics
   */
  updateErrorStats(t) {
    switch (t) {
      case "noteAttempt":
        this.errorStats.totalNoteAttempts++;
        break;
      case "failedNote":
        this.errorStats.failedNotes++;
        break;
      case "invalidData":
        this.errorStats.invalidDataErrors++;
        break;
      case "synthError":
        this.errorStats.synthErrors++;
        break;
    }
  }
  /**
   * Get error statistics
   */
  getErrorStats() {
    const t = Date.now() - this.errorStats.lastResetTime, e = this.errorStats.totalNoteAttempts > 0 ? (this.errorStats.totalNoteAttempts - this.errorStats.failedNotes) / this.errorStats.totalNoteAttempts * 100 : 100;
    return {
      ...this.errorStats,
      uptimeMs: t,
      successRate: parseFloat(e.toFixed(2))
    };
  }
  /**
   * Reset error statistics
   */
  resetErrorStats() {
    this.errorStats = {
      totalNoteAttempts: 0,
      failedNotes: 0,
      invalidDataErrors: 0,
      synthErrors: 0,
      lastResetTime: Date.now()
    };
  }
  /**
   * Comprehensive MIDI data quality analysis
   */
  analyzeMidiDataQuality() {
    const t = {
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      totalNotes: this.notes.length,
      fileIds: Array.from(new Set(this.notes.map((s) => s.fileId).filter(Boolean))),
      dataQuality: {
        validNotes: 0,
        invalidNotes: 0,
        pitchRange: { min: 1 / 0, max: -1 / 0 },
        velocityRange: { min: 1 / 0, max: -1 / 0 },
        durationRange: { min: 1 / 0, max: -1 / 0 },
        timeRange: { min: 1 / 0, max: -1 / 0 }
      },
      issues: [],
      recommendations: []
    };
    for (const s of this.notes)
      this.validateMidiNote(s) ? (t.dataQuality.validNotes++, t.dataQuality.pitchRange.min = Math.min(
        t.dataQuality.pitchRange.min,
        typeof s.pitch == "number" ? s.pitch : Number(s.pitch) || 0
      ), t.dataQuality.pitchRange.max = Math.max(
        t.dataQuality.pitchRange.max,
        typeof s.pitch == "number" ? s.pitch : Number(s.pitch) || 0
      ), t.dataQuality.velocityRange.min = Math.min(t.dataQuality.velocityRange.min, s.velocity), t.dataQuality.velocityRange.max = Math.max(t.dataQuality.velocityRange.max, s.velocity), t.dataQuality.durationRange.min = Math.min(t.dataQuality.durationRange.min, s.duration), t.dataQuality.durationRange.max = Math.max(t.dataQuality.durationRange.max, s.duration), t.dataQuality.timeRange.min = Math.min(t.dataQuality.timeRange.min, s.time), t.dataQuality.timeRange.max = Math.max(t.dataQuality.timeRange.max, s.time)) : t.dataQuality.invalidNotes++;
    const e = t.totalNotes > 0 ? t.dataQuality.validNotes / t.totalNotes * 100 : 100;
    return e < 95 && (t.issues.push(`Low data quality: ${e.toFixed(1)}% valid notes`), t.recommendations.push("Check MIDI file source and parsing quality")), t.dataQuality.invalidNotes > 0 && (t.issues.push(`${t.dataQuality.invalidNotes} invalid notes detected`), t.recommendations.push("Verify MIDI data integrity and consider data cleaning")), (t.dataQuality.pitchRange.min < 0 || t.dataQuality.pitchRange.max > 127) && (t.issues.push("MIDI pitch values outside valid range (0-127)"), t.recommendations.push("Sanitize pitch values to MIDI specification")), t.dataQuality.velocityRange.max > 1 && (t.issues.push("Velocity values above 1.0 detected"), t.recommendations.push("Normalize velocity values to 0.0-1.0 range")), t.dataQuality.durationRange.min <= 0 && (t.issues.push("Zero or negative duration notes detected"), t.recommendations.push("Filter out or correct invalid durations")), t;
  }
  /**
   * Get comprehensive performance report
   */
  getPerformanceReport() {
    const t = this.getErrorStats(), e = this.analyzeMidiDataQuality();
    return {
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      playbackPerformance: {
        ...t,
        isHealthy: t.successRate >= 95,
        healthStatus: t.successRate >= 99 ? "excellent" : t.successRate >= 95 ? "good" : t.successRate >= 80 ? "fair" : "poor"
      },
      dataQuality: e,
      systemStatus: {
        activePlayers: this.players.size,
        totalNotes: this.notes.length,
        partActive: this.part !== null,
        masterVolume: this.masterVolume
      },
      recommendations: this.generateRecommendations(t, e)
    };
  }
  /**
   * Generate system recommendations based on performance and data quality
   */
  generateRecommendations(t, e) {
    const s = [];
    return t.successRate < 95 && s.push("Consider reducing MIDI data complexity or checking for corrupted files"), t.synthErrors > 0 && s.push("Synthesizer errors detected - check audio system configuration"), e.dataQuality.invalidNotes > e.totalNotes * 0.05 && s.push("High invalid note rate - consider implementing stricter data validation"), this.players.size === 0 && s.push("No active synthesizers - check MIDI file loading and player initialization"), e.dataQuality.validNotes === 0 && s.push("No valid notes found - verify MIDI data source and format"), s;
  }
  /**
   * Log comprehensive health status to console
   */
  logHealthStatus() {
    const t = this.getPerformanceReport();
    console.group("[MidiPlayerGroup] Health Status Report"), t.dataQuality.issues.length > 0 && console.warn("Issues:", t.dataQuality.issues), t.recommendations.length > 0, console.groupEnd();
  }
  sanitizeMidiNotes(t) {
    const e = [];
    let s = 0;
    for (const r of t)
      this.validateMidiNote(r) ? e.push(r) : (s++, this.updateErrorStats("invalidData"), $o.DEBUG && console.warn("[MidiPlayerGroup] Invalid MIDI note filtered out:", {
        time: r.time,
        pitch: r.pitch,
        velocity: r.velocity,
        duration: r.duration,
        fileId: r.fileId
      }));
    const i = {
      total: t.length,
      valid: e.length,
      invalid: s
    };
    return s > 0 && console.warn(`[MidiPlayerGroup] Filtered out ${s}/${t.length} invalid notes (${(s / t.length * 100).toFixed(1)}%)`), { validNotes: e, stats: i };
  }
  createMidiPart(t = 0, e) {
    if (this.part && (this.part.dispose(), this.part = null), !this.notes || this.notes.length === 0)
      return;
    const { validNotes: s, stats: i } = this.sanitizeMidiNotes(this.notes), r = 0, o = s.length > 0 ? Math.max(...s.map((y) => y.time)) : 0;
    let a = Math.max(r, Math.min(t, o));
    const l = s.filter((y) => !(y.time < a || e && y.time > e)), c = je(), h = Number(c?.bpm?.value) || this.originalTempoBase || 120, u = this.originalTempoBase || 120, d = u > 0 && h > 0 ? u / h : 1, f = e === void 0;
    let p = [];
    f && (p = s.filter((x) => {
      const v = x.time + x.duration;
      return x.time < a && v > a;
    }).map((x) => {
      const v = Math.max(0.01, x.time + x.duration - a), _ = Math.max(0.01, v * d);
      return {
        time: 0,
        note: x.name || this.normalizeNoteName(typeof x.pitch == "number" ? x.pitch : Number(x.pitch) || 60),
        velocity: x.velocity,
        duration: _,
        fileId: x.fileId,
        trackId: x.trackId
      };
    }));
    let g = l;
    if (g.length === 0 && s.length > 0) {
      const x = s.map((v) => v.time).filter((v) => v <= a);
      if (x.length > 0) {
        const v = Math.max(...x);
        a = Math.max(0, v - 0.2), g = s.filter((b) => !(b.time < a || e && b.time > e));
      }
    }
    let m = g.map((y) => ({
      time: Math.max(0, y.time - a) * d,
      note: y.name || this.normalizeNoteName(typeof y.pitch == "number" ? y.pitch : Number(y.pitch) || 60),
      velocity: y.velocity,
      duration: Math.max(0.01, y.duration * d),
      fileId: y.fileId,
      trackId: y.trackId
    }));
    p.length > 0 && (m = [...p.map((x) => ({
      time: x.time,
      // keep 0 offset for carry-over retrigger
      note: x.note,
      velocity: x.velocity,
      duration: Math.max(0.01, x.duration),
      fileId: x.fileId,
      trackId: x.trackId
    })), ...m]), i.invalid > 0, this.part = new ai((y, x) => {
      this.updateErrorStats("noteAttempt");
      const v = this.players.get(x.fileId ?? "");
      if (!v) {
        console.warn("[MidiPlayerGroup] No player for fileId:", x.fileId);
        return;
      }
      if (v.muted)
        return;
      const _ = globalThis._waveRollMidiManager, b = x.fileId ?? "", w = x.trackId;
      if (!(w !== void 0 && _?.isTrackMuted?.(b, w)))
        try {
          if (!x.note || typeof x.note != "string") {
            this.updateErrorStats("failedNote"), console.warn("[MidiPlayerGroup] Runtime note validation failed:", x);
            return;
          }
          if (!Number.isFinite(x.duration) || x.duration <= 0) {
            this.updateErrorStats("failedNote"), console.warn("[MidiPlayerGroup] Runtime duration validation failed:", x);
            return;
          }
          let S = 1;
          w !== void 0 && _?.getTrackVolume && (S = _.getTrackVolume(b, w));
          const T = this.masterVolume * v.volume * S * x.velocity;
          let k = v.sampler;
          if (w !== void 0 && _?.isTrackAutoInstrument?.(b, w) && _?.getTrackProgram) {
            const M = _.getTrackProgram(b, w), A = this.getProgramSamplerSync(M);
            A?.loaded ? k = A : this.getOrCreateProgramSampler(M).catch(() => {
            });
          }
          k.triggerAttackRelease(
            x.note,
            x.duration,
            y,
            T
          );
        } catch (S) {
          this.updateErrorStats("failedNote"), this.updateErrorStats("synthError"), console.error("[MidiPlayerGroup] Failed to trigger note:", S, {
            note: x.note,
            duration: x.duration,
            velocity: x.velocity,
            fileId: x.fileId,
            finalVolume: this.masterVolume * v.volume * x.velocity
          });
          try {
            v.sampler.triggerAttackRelease(
              "C4",
              0.5,
              // Fallback duration
              y,
              0.1
              // Safe volume
            );
          } catch (T) {
            console.error("[MidiPlayerGroup] Recovery attempt also failed:", T);
          }
        }
    }, m), this.part.loop = !1;
  }
  /**
   * Convert MIDI note number to note name
   */
  midiNoteNumberToName(t) {
    (!Number.isFinite(t) || t < 0 || t > 127) && (console.warn(`[MidiPlayerGroup] Invalid MIDI note number: ${t}, using C4 as fallback`), t = 60), t = Math.round(t);
    const e = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"], s = Math.floor(t / 12) - 1, i = t % 12;
    return (e[i] || "C") + s;
  }
  /**
   * PlayerGroup interface implementation: Synchronized start
   */
  async startSynchronized(t) {
    const e = t.generation;
    if (typeof e == "number") {
      if (this.lastStartGen === e)
        return;
      this.lastStartGen = e;
    }
    if (await this.initialize(), typeof e == "number" && this.lastStartGen !== e || this.players.size === 0)
      return;
    je();
    for (const r of this.players.values())
      r.muted || (r.gate.gain.value = this.masterVolume * r.volume);
    const s = t.audioContextTime - Xe.currentTime;
    this.applyZeroEps = t.mode === "seek" && s > 0.05;
    const i = t.masterTime;
    if (this.createMidiPart(i), this.part)
      try {
        this.part.state === "started" ? (this.part.stop(0), this.part.cancel(0)) : this.part.state === "stopped" ? this.part.cancel(0) : (this.part.stop(0), this.part.cancel(0)), t.mode === "seek" ? this.part.start(t.masterTime, 0) : this.part.start(t.masterTime, 0);
      } catch (r) {
        console.error("[MidiPlayerGroup] ERROR in Part start process:", r instanceof Error ? r.message : String(r));
      }
  }
  /**
   * PlayerGroup interface implementation: Synchronized stop
   */
  stopSynchronized() {
    if (this.part)
      try {
        this.part.stop(0), this.part.cancel(0);
      } catch (t) {
        console.error("[MidiPlayerGroup] Failed to stop Part:", t);
      }
    for (const t of this.players.values())
      try {
        t.gate.gain.value = 0;
      } catch (e) {
        console.error("[MidiPlayerGroup] Failed to mute synthesizer:", e);
      }
    for (const t of this.players.values())
      try {
        t.sampler.releaseAll();
      } catch (e) {
        console.error("[MidiPlayerGroup] Failed to release synthesizer:", e);
      }
  }
  /**
   * PlayerGroup interface implementation: Seek to time
   */
  seekTo(t) {
    this.stopSynchronized();
    const e = je();
    e.seconds = t, this.createMidiPart(t);
    for (const [s, i] of this.players.entries())
      i.muted || (i.gate.gain.value = this.masterVolume * i.volume);
  }
  /**
   * PlayerGroup interface implementation: Set tempo
   */
  setTempo(t) {
    const e = this.originalTempoBase || 120, s = e > 0 ? t / e : 1;
    this.tempoScale = s;
  }
  /** Set baseline tempo used to compute MIDI scheduling scale. */
  setOriginalTempoBase(t) {
    Number.isFinite(t) && t > 0 && (this.originalTempoBase = t);
  }
  /**
   * PlayerGroup interface implementation: Set master volume
   */
  setMasterVolume(t) {
    this.masterVolume = t;
    for (const e of this.players.values())
      e.muted || (e.gate.gain.value = this.masterVolume * e.volume);
  }
  /**
   * PlayerGroup interface implementation: Set loop
   */
  setLoop(t, e, s) {
    if (t === "ab" && e !== null && s !== null)
      this.createMidiPart(e, s), this.part && (this.part.loop = !0, this.part.loopEnd = s - e);
    else if (t === "repeat") {
      if (this.part) {
        this.part.loop = !1;
        try {
          this.part.loopEnd = void 0;
        } catch {
        }
      }
    } else
      this.part && (this.part.loop = !1);
  }
  // === Individual player control methods (user requirements) ===
  /**
   * Set individual MIDI player volume
   */
  setPlayerVolume(t, e) {
    const s = this.players.get(t);
    if (!s) {
      const i = this.pendingPlayerStates.get(t) || {};
      i.volume = Math.max(0, Math.min(1, e)), this.pendingPlayerStates.set(t, i);
      return;
    }
    s.volume = Math.max(0, Math.min(1, e)), s.muted || (s.gate.gain.value = this.masterVolume * s.volume);
  }
  /**
   * Set individual MIDI player pan
   */
  setPlayerPan(t, e) {
    const s = this.players.get(t);
    if (!s) {
      const i = this.pendingPlayerStates.get(t) || {};
      i.pan = Math.max(-1, Math.min(1, e)), this.pendingPlayerStates.set(t, i);
      return;
    }
    s.pan = Math.max(-1, Math.min(1, e)), s.panner.pan.value = s.pan;
  }
  /**
   * Set individual MIDI player mute
   */
  setPlayerMute(t, e) {
    const s = this.players.get(t);
    if (!s) {
      const i = this.pendingPlayerStates.get(t) || {};
      i.muted = e, this.pendingPlayerStates.set(t, i);
      return;
    }
    s.muted = e, s.muted ? (s.gate.gain.value = 0, s.sampler.releaseAll()) : s.gate.gain.value = this.masterVolume * s.volume;
  }
  /**
   * Get individual player states
   */
  getPlayerStates() {
    const t = {};
    for (const [e, s] of this.players)
      t[e] = {
        volume: s.volume,
        pan: s.pan,
        muted: s.muted
      };
    return t;
  }
  /**
   * Resource cleanup
   */
  destroy() {
    this.part && (this.part.dispose(), this.part = null);
    for (const t of this.players.values())
      try {
        t.sampler.dispose(), t.gate.dispose(), t.panner.dispose();
      } catch (e) {
        console.error("[MidiPlayerGroup] Failed to dispose synthesizer:", e);
      }
    this.players.clear(), this.pendingPlayerStates.clear();
  }
};
$o.DEBUG = !1;
let Wl = $o;
class GC {
  constructor() {
    this.isInitialized = !1, this.initPromise = null, this._prevTime = 0, this._lastLoopJumpAtGen = -1, this._lastRepeatWrapAtGen = -1, this.lastJoinRequestTs = /* @__PURE__ */ new Map(), this.handleWavVisibilityChange = (t) => {
      const e = t.detail;
      e && e.isVisible && this.alignWavJoin(e.id);
    }, this.handleWavMuteChange = (t) => {
      const e = t.detail;
      if (e)
        try {
          this.setWavPlayerMute(e.id, e.isMuted), !e.isMuted && this.masterClock.state.isPlaying && this.alignWavJoin(e.id);
        } catch {
        }
    }, this.masterClock = new zC(), this.wavPlayerGroup = new qC(), this.midiPlayerGroup = new Wl(), this.masterClock.registerPlayerGroup(this.wavPlayerGroup), this.masterClock.registerPlayerGroup(this.midiPlayerGroup), typeof window < "u" && (window.addEventListener(
      "wr-wav-visibility-changed",
      this.handleWavVisibilityChange
    ), window.addEventListener(
      "wr-wav-mute-changed",
      this.handleWavMuteChange
    ));
  }
  /**
   * Compute effective total duration considering both MIDI and audible WAV sources.
   * Falls back to master clock's totalTime when registry is unavailable.
   */
  getEffectiveTotalTime() {
    let t = this.masterClock.state.totalTime || 0;
    try {
      const s = globalThis._waveRollAudio?.getFiles?.();
      if (s && Array.isArray(s)) {
        const i = s.filter(
          (r) => r && r.isVisible !== !1 && r.isMuted !== !0 && (r.volume === void 0 || r.volume > 0)
        ).map((r) => r?.audioBuffer?.duration ?? 0).filter((r) => typeof r == "number" && r > 0);
        i.length > 0 && (t = Math.max(t, ...i));
      }
    } catch {
    }
    return t;
  }
  /**
   * Initialize (async)
   */
  async initialize() {
    if (!this.isInitialized) {
      if (this.initPromise)
        return this.initPromise;
      this.initPromise = this.performInitialization(), await this.initPromise;
    }
  }
  async performInitialization() {
    try {
      Xe && Xe.state !== "running" && (await Oc(), Xe.state !== "running" && (console.warn(
        "[UnifiedAudioController] AudioContext still not running after Tone.start()"
      ), Xe.resume && await Xe.resume()));
      const t = globalThis._waveRollAudio;
      if (t?.getFiles) {
        const e = t.getFiles();
      }
      await this.midiPlayerGroup.initialize(), await this.wavPlayerGroup.setupAudioPlayersFromRegistry(), this.isInitialized = !0;
    } catch (t) {
      throw console.error("[UnifiedAudioController] Initialization failed:", t), t;
    }
  }
  // === Upper-level unified control methods (user requirements) ===
  /**
   * Start unified playback
   */
  async play() {
    await this.initialize();
    try {
      await this.midiPlayerGroup.waitUntilReady(), await this.wavPlayerGroup.waitUntilReady(), await this.preloadAutoInstrumentSamplers();
      const t = jn(), e = this._lastPlayAnchor;
      e && t > e - 0.01 && (this.masterClock.state.nowTime = this.masterClock.getCurrentTime()), await this.masterClock.startPlayback(this.masterClock.state.nowTime, 0.1), this._lastPlayAnchor = jn() + 0.1, this.startVisualUpdateLoop();
    } catch (t) {
      throw console.error(
        "[UnifiedAudioController] Failed to start playback:",
        t
      ), t;
    }
  }
  /**
   * Preload soundfonts for tracks with auto-instrument enabled.
   * Called after AudioContext is active to ensure successful loading.
   */
  async preloadAutoInstrumentSamplers() {
    try {
      const t = globalThis._waveRollMidiManager;
      if (!t?.getState || !t?.isTrackAutoInstrument || !t?.getTrackProgram)
        return;
      const e = [], s = t.getState();
      for (const o of s.files)
        if (o.parsedData?.tracks) {
          for (const a of o.parsedData.tracks)
            if (t.isTrackAutoInstrument(
              o.id,
              a.id
            )) {
              const c = t.getTrackProgram(o.id, a.id);
              e.push(c);
            }
        }
      const r = [...new Set(e)].filter(
        (o) => !this.midiPlayerGroup.isProgramLoadedOrLoading(o)
      );
      r.length > 0 && await this.preloadProgramSamplers(r);
    } catch (t) {
      console.warn(
        "[UnifiedAudioController] Error during soundfont preload:",
        t
      );
    }
  }
  /**
   * Pause unified playback
   */
  pause() {
    this.masterClock.pausePlayback(), this.stopVisualUpdateLoop();
  }
  /**
   * Stop unified playback (rewind to start)
   */
  stop() {
    this.masterClock.stopPlayback(), this.stopVisualUpdateLoop();
  }
  /**
   * Seek to a specific time
   */
  seek(t) {
    try {
      this.wavPlayerGroup.stopSynchronized();
    } catch {
    }
    this.masterClock.seekTo(t);
    try {
      const e = je();
    } catch {
    }
  }
  /**
   * Get current playback time
   */
  getCurrentTime() {
    return this.masterClock.getCurrentTime();
  }
  /**
   * Check playing state
   */
  get isPlaying() {
    return this.masterClock.state.isPlaying;
  }
  /**
   * Current nowTime (user requirements)
   */
  get nowTime() {
    return this.masterClock.state.nowTime;
  }
  set nowTime(t) {
    this.masterClock.seekTo(t);
  }
  /**
   * Set/get total time
   */
  get totalTime() {
    return this.masterClock.state.totalTime;
  }
  set totalTime(t) {
    this.masterClock.state.totalTime = t;
  }
  /**
   * Set/get tempo (user requirements)
   */
  get tempo() {
    return this.masterClock.state.tempo;
  }
  set tempo(t) {
    const e = this.masterClock.state.tempo;
    if (t === e) return;
    const s = this.masterClock.state.isPlaying, i = this.masterClock.getCurrentTime();
    this.masterClock.setTempo(t), s && this.masterClock.seekToWithLookahead(i, 0.2);
  }
  /**
   * Update baseline/original tempo (used as 100%).
   */
  setOriginalTempo(t) {
    this.masterClock.setOriginalTempo(t), this.wavPlayerGroup.setOriginalTempoBase(t), this.midiPlayerGroup.setOriginalTempoBase(t);
  }
  /**
   * Set/get master volume (user requirements)
   */
  get masterVolume() {
    return this.masterClock.state.masterVolume;
  }
  set masterVolume(t) {
    this.masterClock.setMasterVolume(t);
  }
  /**
   * Set/get loop mode (user requirements)
   */
  get loopMode() {
    return this.masterClock.state.loopMode;
  }
  set loopMode(t) {
    this.masterClock.setLoopMode(
      t,
      this.masterClock.state.markerA ?? void 0,
      this.masterClock.state.markerB ?? void 0
    );
  }
  /**
   * Independent global repeat flag (separate from AB loop mode)
   */
  get isGlobalRepeat() {
    return !!this.masterClock.state.globalRepeat;
  }
  set isGlobalRepeat(t) {
    this.masterClock.state.globalRepeat = !!t;
  }
  /**
   * Set/get marker A (user requirements)
   */
  get markerA() {
    return this.masterClock.state.markerA;
  }
  set markerA(t) {
    this.masterClock.state.markerA = t, this.masterClock.setLoopMode(
      this.masterClock.state.loopMode,
      t ?? void 0,
      this.masterClock.state.markerB ?? void 0
    );
  }
  /**
   * Set/get marker B (user requirements)
   */
  get markerB() {
    return this.masterClock.state.markerB;
  }
  set markerB(t) {
    this.masterClock.state.markerB = t, this.masterClock.setLoopMode(
      this.masterClock.state.loopMode,
      this.masterClock.state.markerA ?? void 0,
      t ?? void 0
    );
  }
  /**
   * Configure A–B loop
   */
  setABLoop(t, e) {
    this.masterClock.setLoopMode("ab", t, e);
  }
  // === Lower-level per-player control methods (user requirements) ===
  // Per-WAV-player controls
  /**
   * Set WAV player volume
   */
  setWavPlayerVolume(t, e) {
    this.wavPlayerGroup.setPlayerVolume(t, e);
    try {
      this.masterClock.state.isPlaying && e > 0 && this.alignWavJoin(t);
    } catch {
    }
  }
  /**
   * Adjust WAV group mix vs MIDI (0-1)
   */
  setWavGroupMix(t) {
    try {
      this.wavPlayerGroup.setGroupMixGain?.(t);
    } catch {
    }
  }
  /**
   * Set WAV player pan
   */
  setWavPlayerPan(t, e) {
    this.wavPlayerGroup.setPlayerPan(t, e);
  }
  /**
   * Set WAV player mute
   */
  setWavPlayerMute(t, e) {
    this.wavPlayerGroup.setPlayerMute(t, e);
  }
  /**
   * Get all WAV player states
   */
  getWavPlayerStates() {
    return this.wavPlayerGroup.getPlayerStates();
  }
  // Per-MIDI-player controls
  /**
   * Set MIDI player volume
   */
  setMidiPlayerVolume(t, e) {
    this.midiPlayerGroup.setPlayerVolume(t, e);
  }
  /**
   * Set MIDI player pan
   */
  setMidiPlayerPan(t, e) {
    this.midiPlayerGroup.setPlayerPan(t, e);
  }
  /**
   * Set MIDI player mute
   */
  setMidiPlayerMute(t, e) {
    this.midiPlayerGroup.setPlayerMute(t, e);
  }
  /**
   * Get all MIDI player states
   */
  getMidiPlayerStates() {
    return this.midiPlayerGroup.getPlayerStates();
  }
  // === Compatibility methods with existing system ===
  /**
   * Set MIDI manager (compatibility with existing code)
   */
  setMidiManager(t) {
    this.midiPlayerGroup.setMidiManager(t);
  }
  /**
   * Return state object (compatibility with existing code)
   */
  getState() {
    const t = this.masterClock.state, e = this.masterClock.getCurrentTime();
    return {
      ...t,
      currentTime: e,
      // Use real-time current time instead of cached nowTime
      duration: t.totalTime,
      // Alias for legacy compatibility
      // Include per-player states as well
      wavPlayers: this.getWavPlayerStates(),
      midiPlayers: this.getMidiPlayerStates()
    };
  }
  /**
   * Set visual update callback (compatibility with existing code)
   */
  setOnVisualUpdate(t) {
    this.visualUpdateCallback = t;
    try {
      const e = this.masterClock.getCurrentTime();
      this.visualUpdateCallback?.(e);
    } catch {
    }
  }
  startVisualUpdateLoop() {
    this.stopVisualUpdateLoop();
    const t = () => {
      if (this.masterClock.state.isPlaying && this.visualUpdateCallback)
        try {
          const s = this.masterClock.getCurrentTime(), i = this.masterClock.state, r = this.getEffectiveTotalTime(), o = this.masterClock.state.globalRepeat === !0 || i.loopMode === "repeat";
          if (!o && r > 0 && s >= r) {
            const l = r;
            this.masterClock.state.nowTime = l;
            try {
              this.visualUpdateCallback(l);
            } catch {
            }
            this.masterClock.pausePlayback(), this.masterClock.seekTo(l);
            return;
          }
          const a = this._prevTime < r && s >= r;
          if (o && r > 0 && a && this._lastRepeatWrapAtGen !== i.generation) {
            this._lastRepeatWrapAtGen = i.generation, this.seek(0);
            return;
          }
          if (this.masterClock.state.nowTime = s, this.visualUpdateCallback(s), i.loopMode === "ab" && i.markerA !== null && i.markerB !== null) {
            const l = Math.max(0, i.markerA), c = Math.max(l, i.markerB);
            if (this._prevTime < c && s >= c) {
              const h = i.generation;
              this._lastLoopJumpAtGen !== h && (this._lastLoopJumpAtGen = h, this.seek(l));
            }
          }
          this._prevTime = s;
        } catch (s) {
          console.error("[UnifiedAudioController] Visual update error:", s);
        }
      try {
        this.masterClock.state.isPlaying && this.wavPlayerGroup.syncPendingPlayers(
          this.masterClock.getCurrentTime()
        );
      } catch {
      }
      if (this.masterClock.state.isPlaying) {
        const s = typeof requestAnimationFrame < "u" ? requestAnimationFrame : (i) => setTimeout(
          () => i(performance.now?.() ?? Date.now()),
          16
        );
        this.visualUpdateLoop = s(t);
      }
    }, e = typeof requestAnimationFrame < "u" ? requestAnimationFrame : (s) => setTimeout(
      () => s(performance.now?.() ?? Date.now()),
      16
    );
    this.visualUpdateLoop = e(t);
  }
  stopVisualUpdateLoop() {
    this.visualUpdateLoop && ((typeof cancelAnimationFrame < "u" ? cancelAnimationFrame : (e) => clearTimeout(e))(this.visualUpdateLoop), this.visualUpdateLoop = void 0);
  }
  /**
   * Resource cleanup
   */
  destroy() {
    this.stopVisualUpdateLoop(), this.masterClock.stopPlayback(), this.wavPlayerGroup.destroy(), this.midiPlayerGroup.destroy(), typeof window < "u" && (window.removeEventListener(
      "wr-wav-visibility-changed",
      this.handleWavVisibilityChange
    ), window.removeEventListener(
      "wr-wav-mute-changed",
      this.handleWavMuteChange
    )), this.isInitialized = !1, this.initPromise = null, this.visualUpdateCallback = void 0;
  }
  /**
   * Public: Align a WAV track to join playback at the exact master time, if appropriate.
   */
  alignWavJoin(t, e = 0.03) {
    try {
      if (!this.masterClock.state.isPlaying) return;
      const s = jn(), i = this.lastJoinRequestTs.get(t) || 0;
      if (s - i < 0.05) return;
      this.lastJoinRequestTs.set(t, s);
      const r = this.masterClock.getCurrentTime();
      this.wavPlayerGroup.syncStartIfNeeded(t, r, e);
    } catch {
    }
  }
  /**
   * Preload samplers for specific MIDI Program Numbers.
   * @param programs - Array of MIDI Program Numbers to preload
   */
  async preloadProgramSamplers(t) {
    return this.midiPlayerGroup.preloadProgramSamplers(t);
  }
}
class WC {
  constructor(t, e, s) {
    if (this.notes = [], this.originalTempo = 120, this.isInitialized = !1, this.initPromise = null, this.visualUpdateCallback = null, this.operationState = {
      lastOperation: "none",
      lastOperationTime: 0,
      isOperationLocked: !1,
      currentGeneration: 0
    }, this.isHandlingLoop = !1, this.handleTransportStop = () => {
    }, this.handleTransportPause = () => {
    }, this.handleTransportLoop = () => {
    }, this.notes = t, this.options = e, this.pianoRoll = s, this.unifiedController = new GC(), this.notes && this.notes.length > 0) {
      this.unifiedController.setMidiManager({ notes: this.notes });
      const i = this.notes.reduce((r, o) => {
        const a = (o.time || 0) + (o.duration || 0);
        return Math.max(r, a);
      }, 0);
      i > 0 && (this.unifiedController.totalTime = i);
    }
    this.state = this.createStateProxy(), this.createLegacyManagers();
  }
  /**
   * Create state proxy for compatibility
   */
  createStateProxy() {
    const t = this;
    return new Proxy({}, {
      get(e, s) {
        const i = t.unifiedController.getState();
        switch (s) {
          case "currentTime":
            return i.nowTime;
          case "isPlaying":
            return i.isPlaying;
          case "tempo":
            return i.tempo;
          case "volume":
          case "masterVolume":
            return i.masterVolume;
          case "duration":
          case "totalTime":
            return i.totalTime;
          case "nowTime":
            return i.nowTime;
          default:
            return i[s];
        }
      },
      set(e, s, i) {
        switch (s) {
          case "currentTime":
            t.unifiedController.nowTime = i;
            break;
          case "tempo":
            t.unifiedController.tempo = i;
            break;
          case "volume":
          case "masterVolume":
            t.unifiedController.masterVolume = i;
            break;
          case "duration":
          case "totalTime":
            t.unifiedController.totalTime = i;
            break;
          case "nowTime":
            t.unifiedController.nowTime = i;
            break;
          default:
            e[s] = i;
            break;
        }
        return !0;
      }
    });
  }
  /**
   * Create legacy manager proxies for compatibility
   */
  createLegacyManagers() {
    this.samplerManager = {
      initialize: () => Promise.resolve(),
      destroy: () => {
      },
      setFileMute: (t, e) => this.unifiedController.setMidiPlayerMute(t, e),
      setFileVolume: (t, e) => this.unifiedController.setMidiPlayerVolume(t, e),
      setFilePan: (t, e) => this.unifiedController.setMidiPlayerPan(t, e)
    }, this.wavPlayerManager = {
      setTransportSyncManager: () => {
      },
      refreshAudioPlayers: () => {
      },
      isAudioActive: () => !0,
      setFileMute: (t, e) => this.unifiedController.setWavPlayerMute(t, e),
      setFileVolume: (t, e) => this.unifiedController.setWavPlayerVolume(t, e),
      setFilePan: (t, e) => this.unifiedController.setWavPlayerPan(t, e)
    }, this.transportSyncManager = {
      startSyncScheduler: () => {
      },
      stopSyncScheduler: () => {
      },
      updateSeekTimestamp: () => {
      },
      enableSyncInspector: () => {
      },
      disableSyncInspector: () => {
      }
    }, this.loopManager = {
      loopStartVisual: 0,
      loopEndVisual: 0,
      getPartOffset: () => 0
    }, this.playbackController = {
      play: () => this.play(),
      pause: () => this.pause(),
      seek: (t) => this.seek(t)
    }, this.audioSettingsController = {}, this.fileAudioController = {}, this.autoPauseController = {};
  }
  /**
   * Initialize - delegate to unified controller
   */
  async initialize() {
    if (!this.isInitialized) {
      if (this.initPromise)
        return this.initPromise;
      this.initPromise = this.performInitialization(), await this.initPromise;
    }
  }
  async performInitialization() {
    try {
      await this.unifiedController.initialize(), this.isInitialized = !0;
    } catch (t) {
      throw console.error("[AudioPlayer] V2 initialization failed:", t), t;
    }
  }
  // === Public API Methods (compatibility with existing AudioPlayer) ===
  /**
   * Start playbook
   */
  async play() {
    await this.initialize();
    try {
      try {
        const t = this.unifiedController.getState(), e = Number.isFinite(t.totalTime) ? t.totalTime : t.duration, s = Number.isFinite(t.nowTime) ? t.nowTime : 0, i = !t.loopMode || t.loopMode === "off", r = e && s > e + 0.05;
        i && r && this.unifiedController.seek(0);
      } catch {
      }
      await this.unifiedController.play();
    } catch (t) {
      throw console.error("[AudioPlayer] V2 failed to start playback:", t), t;
    }
  }
  /**
   * Pause playback
   */
  pause() {
    this.unifiedController.pause();
  }
  /**
   * Restart playback
   */
  restart() {
    this.unifiedController.stop();
  }
  /**
   * Seek to specific time
   */
  seek(t) {
    this.unifiedController.seek(t);
  }
  /**
   * Set tempo
   */
  setTempo(t) {
    this.unifiedController.tempo = t;
  }
  /**
   * Set master volume
   */
  setVolume(t) {
    this.unifiedController.masterVolume = t;
  }
  /**
   * Set playback rate
   */
  setPlaybackRate(t) {
    const s = Math.max(10, Math.min(200, t)) / 100, i = this.unifiedController.getState(), o = (Number.isFinite(i.originalTempo) && i.originalTempo > 0 ? i.originalTempo : this.originalTempo) * s;
    this.setTempo(o);
  }
  /**
   * Update baseline/original tempo used as 100% reference.
   */
  setOriginalTempo(t) {
    try {
      this.unifiedController.setOriginalTempo(t);
    } catch {
    }
  }
  /**
   * Set loop points (A-B) with optional position preservation.
   * - Passing null,null clears loop and (optionally) preserves position.
   * - Passing null,B sets [0,B) as loop window.
   * - Passing A,null stores A only (does NOT activate loop by policy).
   * - Passing A,B activates AB loop; when preservePosition=false, jumps to A.
   */
  setLoopPoints(t, e, s = !1) {
    try {
      const i = this.unifiedController.getState(), r = Number.isFinite(i.totalTime) && i.totalTime > 0 ? i.totalTime : Number.isFinite(i.duration) ? i.duration : 0, o = Number.isFinite(i.nowTime) ? i.nowTime : 0;
      if (t === null && e === null) {
        this.unifiedController.markerA = null, this.unifiedController.markerB = null, this.unifiedController.loopMode = "off", s || this.seek(0);
        return;
      }
      if (t !== null && e !== null && t > e) {
        const a = t;
        t = e, e = a;
      }
      if (t === null && e !== null) {
        const a = r > 0 ? Math.max(0, Math.min(e, r)) : Math.max(0, e);
        this.unifiedController.markerA = 0, this.unifiedController.markerB = a, this.unifiedController.loopMode = "ab", s ? o >= 0 && o <= a || this.seek(0) : this.seek(0);
        return;
      }
      if (t !== null && e === null) {
        this.unifiedController.markerA = Math.max(0, t);
        return;
      }
      if (t !== null && e !== null) {
        const a = Math.max(0, t), l = r > 0 ? Math.max(0, Math.min(e, r)) : Math.max(0, e);
        if (a >= l) {
          console.warn("[AudioPlayer] Ignoring invalid loop points (start >= end):", { start: t, end: e });
          return;
        }
        this.unifiedController.markerA = a, this.unifiedController.markerB = l, this.unifiedController.loopMode = "ab", s ? o >= a && o <= l || this.seek(a) : this.seek(a);
        return;
      }
    } catch (i) {
      console.error("[AudioPlayer] setLoopPoints failed:", i);
    }
  }
  /**
   * Toggle or explicitly set repeat mode.
   * - When enabled is provided: true → on, false → off.
   * - Without argument: toggle current state.
   * If AB markers are present and enabled=true, subsequent setLoopPoints will switch to 'ab'.
   */
  toggleRepeat(t) {
    try {
      if (typeof t == "boolean") {
        this.unifiedController.isGlobalRepeat = !!t;
        return;
      }
      const e = this.unifiedController.isGlobalRepeat === !0;
      this.unifiedController.isGlobalRepeat = !e;
    } catch (e) {
      console.error("[AudioPlayer] toggleRepeat failed:", e);
    }
  }
  // Global pan control removed in v2. Use setFilePan for per-file control.
  /**
   * Set file mute
   */
  setFileMute(t, e) {
    this.isWavFileId(t) ? this.unifiedController.setWavPlayerMute(t, e) : this.unifiedController.setMidiPlayerMute(t, e);
  }
  /**
   * Set file pan
   */
  setFilePan(t, e) {
    this.isWavFileId(t) ? this.unifiedController.setWavPlayerPan(t, e) : this.unifiedController.setMidiPlayerPan(t, e);
  }
  /**
   * Set file volume
   */
  setFileVolume(t, e) {
    this.isWavFileId(t) ? this.unifiedController.setWavPlayerVolume(t, e) : this.unifiedController.setMidiPlayerVolume(t, e);
  }
  /**
   * Set WAV volume
   */
  setWavVolume(t, e) {
    this.unifiedController.setWavPlayerVolume(t, e);
  }
  /** Determine if the given id belongs to WAV registry */
  isWavFileId(t) {
    try {
      const i = (globalThis._waveRollAudio?.getFiles?.() || []).find((r) => r.id === t);
      return i ? i.type ? i.type === "audio" || i.type === "wav" : !0 : t.includes("audio") || t.includes(".mp3") || t.includes(".wav");
    } catch {
      return t.includes("audio") || t.includes(".mp3") || t.includes(".wav");
    }
  }
  /**
   * Get current state
   */
  getState() {
    const t = this.unifiedController.getState(), e = t.loopMode && t.loopMode !== "off";
    return { ...t, isRepeating: e };
  }
  /**
   * Set visual update callback
   */
  setOnVisualUpdate(t) {
    this.visualUpdateCallback = t, this.unifiedController.setOnVisualUpdate((e) => {
      if (this.visualUpdateCallback)
        try {
          if (typeof e == "number") {
            const s = this.unifiedController.getState();
            this.visualUpdateCallback({
              currentTime: e,
              duration: s.duration,
              isPlaying: s.isPlaying
            });
          } else
            this.visualUpdateCallback(e);
        } catch (s) {
          console.error("[AudioPlayer] Visual update callback error:", s);
        }
    });
  }
  /**
   * Refresh audio players (compatibility)
   */
  refreshAudioPlayers() {
  }
  // === Legacy compatibility methods ===
  cleanup() {
  }
  setupTransportCallbacks() {
  }
  removeTransportCallbacks() {
  }
  updateAllUI() {
  }
  handleFileSettingsChange() {
  }
  handlePlaybackEnd() {
  }
  maybeAutoPauseIfSilent() {
  }
  /**
   * Destroy and cleanup
   */
  destroy() {
    this.unifiedController.destroy(), this.isInitialized = !1, this.initPromise = null, this.visualUpdateCallback = null;
  }
}
function $C(n, t, e) {
  return new WC(n, t, e);
}
const zs = {
  /**
   * Clamp volume to valid range [0, 1]
   */
  clampVolume(n) {
    return hs(n, 0, 1);
  },
  /**
   * Clamp tempo to specified range
   */
  clampTempo(n, t = 30, e = 300) {
    return hs(n, t, e);
  },
  /**
   * Clamp pan value to stereo range [-1, 1]
   */
  clampPan(n) {
    return hs(n, -1, 1);
  },
  /**
   * Convert time to percentage of duration
   */
  timeToPercent(n, t) {
    return t === 0 ? 0 : n / t * 100;
  },
  /**
   * Convert percentage to time based on duration
   */
  percentToTime(n, t) {
    return n / 100 * t;
  },
  /**
   * Check if volume is effectively silent
   */
  isSilent(n, t = 1e-3) {
    return n < t;
  },
  /**
   * Convert decibels to linear volume
   */
  dbToLinear(n) {
    return Math.pow(10, n / 20);
  },
  /**
   * Convert linear volume to decibels
   */
  linearToDb(n) {
    return 20 * Math.log10(Math.max(1e-3, n));
  },
  /**
   * Normalize tempo to playback rate
   */
  tempoToPlaybackRate(n, t = 120) {
    return n / t;
  },
  /**
   * Convert playback rate to tempo
   */
  playbackRateToTempo(n, t = 120) {
    return n * t;
  }
};
function io(n, t) {
  return (e) => {
    const s = n();
    e();
    const i = n();
    s !== i && t(s, i);
  };
}
class mf {
  constructor(t) {
    this.onStateChange = t, this.volumes = /* @__PURE__ */ new Map(), this.mutes = /* @__PURE__ */ new Map(), this.masterVolume = 1, this.masterMuted = !1;
  }
  /**
   * Set volume for a specific source
   */
  setVolume(t, e) {
    io(
      () => this.isAllSilent(),
      (i, r) => {
        this.onStateChange && i !== r && this.onStateChange(i, r);
      }
    )(() => {
      const i = zs.clampVolume(e);
      this.volumes.set(t, i);
    });
  }
  /**
   * Get volume for a specific source
   */
  getVolume(t) {
    return this.volumes.get(t) ?? 1;
  }
  /**
   * Set mute state for a specific source
   */
  setMuted(t, e) {
    io(
      () => this.isAllSilent(),
      (i, r) => {
        this.onStateChange && i !== r && this.onStateChange(i, r);
      }
    )(() => {
      this.mutes.set(t, e);
    });
  }
  /**
   * Get mute state for a specific source
   */
  isMuted(t) {
    return this.mutes.get(t) ?? !1;
  }
  /**
   * Set master volume
   */
  setMasterVolume(t) {
    io(
      () => this.isAllSilent(),
      (s, i) => {
        this.onStateChange && s !== i && this.onStateChange(s, i);
      }
    )(() => {
      this.masterVolume = zs.clampVolume(t);
    });
  }
  /**
   * Get master volume
   */
  getMasterVolume() {
    return this.masterVolume;
  }
  /**
   * Set master mute state
   */
  setMasterMuted(t) {
    io(
      () => this.isAllSilent(),
      (s, i) => {
        this.onStateChange && s !== i && this.onStateChange(s, i);
      }
    )(() => {
      this.masterMuted = t;
    });
  }
  /**
   * Check if master is muted
   */
  isMasterMuted() {
    return this.masterMuted;
  }
  /**
   * Get effective volume for a source (considering mute states and master)
   */
  getEffectiveVolume(t) {
    return this.masterMuted || this.isMuted(t) ? 0 : this.getVolume(t) * this.masterVolume;
  }
  /**
   * Check if all sources are effectively silent
   */
  isAllSilent() {
    if (this.masterMuted || zs.isSilent(this.masterVolume))
      return !0;
    if (this.volumes.size === 0)
      return !1;
    for (const [t, e] of this.volumes)
      if (!this.mutes.get(t) && !zs.isSilent(e))
        return !1;
    return !0;
  }
  /**
   * Check if a specific source is silent
   */
  isSilent(t) {
    return this.getEffectiveVolume(t) === 0;
  }
  /**
   * Get all sources that are currently audible
   */
  getAudibleSources() {
    const t = [];
    if (this.masterMuted || zs.isSilent(this.masterVolume))
      return t;
    for (const [e, s] of this.volumes)
      !this.mutes.get(e) && !zs.isSilent(s) && t.push(e);
    return t;
  }
  /**
   * Clear all volume and mute states
   */
  clear() {
    this.volumes.clear(), this.mutes.clear();
  }
  /**
   * Get state summary
   */
  getState() {
    const t = /* @__PURE__ */ new Map();
    for (const [e, s] of this.volumes)
      t.set(e, {
        volume: s,
        muted: this.mutes.get(e) ?? !1
      });
    return {
      sources: t,
      master: {
        volume: this.masterVolume,
        muted: this.masterMuted
      }
    };
  }
}
const HC = {
  defaultVolume: 1,
  defaultTempo: 120,
  minTempo: 20,
  maxTempo: 300,
  updateInterval: 150,
  // Reduced to 150ms (6.7fps) to avoid conflicts with requestAnimationFrame while maintaining sync
  enableStateSync: !0
};
class jC {
  constructor(t, e = {}) {
    this.audioPlayer = null, this.pianoRollManager = null, this.stateManager = null, this.updateLoopId = null, this.visualUpdateCallbacks = [], this.loopPoints = {
      a: null,
      b: null
    }, this.seeking = !1, this.muteDueNoLR = !1, this.lastVolumeBeforeMute = 0.7, this.lastAudioSignature = "", this.lastKnownState = null, this.pendingOriginalTempo = null, this.config = { ...HC, ...e }, this.stateManager = t || null;
  }
  /**
   * Master volume property (0-1).
   * Getter reads from current audio player state,
   * setter delegates to setVolume() for consistent propagation.
   */
  get masterVolume() {
    return this.audioPlayer?.getState()?.volume ?? this.config.defaultVolume;
  }
  set masterVolume(t) {
    this.setVolume(t);
  }
  /**
   * Initialize the engine with PianoRoll manager
   */
  async initialize(t) {
    this.pianoRollManager = t;
    const e = t.getPianoRollInstance();
    e?.onTimeChange && e.onTimeChange((s) => {
      this.seek(s, !1);
    });
  }
  /**
   * Update audio with new notes
   */
  async updateAudio(t) {
    const e = /* @__PURE__ */ new Set();
    t.forEach((i) => {
      i.fileId && e.add(i.fileId);
    });
    const s = Array.from(e).sort().join(",");
    s === this.lastAudioSignature && this.audioPlayer || (await this.recreateAudioPlayer(t), this.lastAudioSignature = s);
  }
  /**
   * Recreate audio player with new notes
   */
  async recreateAudioPlayer(t) {
    if (!this.pianoRollManager)
      throw new Error("PianoRollManager not initialized");
    const e = this.audioPlayer?.getState(), s = e?.isPlaying || !1;
    e && (this.lastKnownState = e), this.audioPlayer && (this.audioPlayer.destroy(), this.audioPlayer = null);
    const i = this.pianoRollManager.getPianoRollInstance();
    if (!i)
      throw new Error("PianoRoll instance not available");
    this.audioPlayer = await $C(
      t,
      {
        tempo: e?.tempo || this.config.defaultTempo,
        volume: e?.volume || this.config.defaultVolume,
        repeat: e?.isRepeating || !1
      },
      i
    );
    const r = this.pendingOriginalTempo ?? e?.originalTempo;
    if (r && Number.isFinite(r) && r > 0) {
      this.audioPlayer?.setOriginalTempo?.(r), (!e || e.tempo === e.originalTempo) && this.audioPlayer.setTempo(r);
      try {
        document.dispatchEvent(new CustomEvent("wr-force-ui-refresh"));
      } catch {
      }
    }
    if (e && (e.currentTime >= 0 && this.audioPlayer.seek(e.currentTime, !1), (this.loopPoints.a !== null || this.loopPoints.b !== null) && this.audioPlayer.setLoopPoints(
      this.loopPoints.a,
      this.loopPoints.b,
      !0
    ), s))
      try {
        await this.audioPlayer.play();
      } catch (a) {
        console.error("Failed to resume playback after recreation:", a);
      }
    if (this.stateManager) {
      const a = this.stateManager.getFilePanValuesRef();
      Object.entries(a).forEach(([c, h]) => {
        this.audioPlayer?.setFilePan(c, h);
      });
      const l = this.stateManager.getFileMuteStatesRef();
      Object.entries(l).forEach(([c, h]) => {
        this.audioPlayer?.setFileMute(c, h);
      });
    }
    const o = /* @__PURE__ */ new Map();
    t.forEach((a) => {
      a.fileId && !o.has(a.fileId) && a.muted === !0 && o.set(a.fileId, !0);
    }), o.forEach((a, l) => {
      this.audioPlayer?.setFileMute(l, a), this.stateManager && this.stateManager.setFileMuteState(l, a);
    }), this.config.enableStateSync && this.stateManager && this.syncWithStateManager();
  }
  /**
   * AudioPlayerContainer implementation
   */
  async play() {
    if (!this.audioPlayer) {
      console.error("[CorePlaybackEngine] audioPlayer is null, cannot play");
      return;
    }
    const t = this.audioPlayer.getState(), e = t.currentTime === 0;
    if (await this.audioPlayer.play(), this.startUpdateLoop(), e && this.pianoRollManager) {
      this.pianoRollManager.setTime(0);
      const s = {
        currentTime: 0,
        duration: t.duration,
        isPlaying: !0,
        volume: t.volume,
        tempo: t.tempo,
        pan: t.pan
      };
      this.visualUpdateCallbacks.forEach((i) => {
        try {
          i(s);
        } catch (r) {
          console.error("Error in visual update callback:", r);
        }
      });
    }
    setTimeout(() => {
      if (this.audioPlayer && this.pianoRollManager) {
        const s = this.audioPlayer.getState();
        this.pianoRollManager.setTime(s.currentTime), this.dispatchVisualUpdateFromState(s);
      }
    }, 50);
  }
  pause() {
    this.audioPlayer?.pause(), this.stopUpdateLoop();
  }
  restart() {
    this.audioPlayer?.restart();
  }
  toggleRepeat(t) {
    this.audioPlayer?.toggleRepeat(t);
  }
  seek(t, e = !0) {
    this.audioPlayer && (this.seeking = !0, this.audioPlayer.seek(t, e), e && this.pianoRollManager && this.pianoRollManager.setTime(t), setTimeout(() => {
      this.seeking = !1;
    }, 50));
  }
  setVolume(t) {
    const e = zs.clampVolume(t);
    this.audioPlayer?.setVolume(e), this.config.enableStateSync && this.stateManager && this.stateManager.updatePlaybackState({ volume: e });
  }
  setTempo(t) {
    const e = zs.clampTempo(
      t,
      this.config.minTempo,
      this.config.maxTempo
    );
    this.audioPlayer?.setTempo(e);
  }
  /**
   * Legacy compatibility: global pan setter (no-op in v2)
   * Exposed to satisfy older call sites that expect setPan on the engine.
   */
  setPan(t) {
  }
  /**
   * Set baseline/original tempo used as 100% reference for percent-based rate.
   */
  setOriginalTempo(t) {
    !Number.isFinite(t) || t <= 0 || (this.pendingOriginalTempo = t, this.audioPlayer?.setOriginalTempo?.(t));
  }
  setLoopPoints(t, e, s = !1) {
    this.loopPoints = { a: t, b: e }, this.audioPlayer?.setLoopPoints(t, e, s), this.config.enableStateSync && this.stateManager && this.stateManager.setLoopPoints(t, e);
  }
  // Global pan control removed; use per-file setFilePan instead
  /**
   * Set pan for a specific file track.
   */
  setFilePan(t, e) {
    this.audioPlayer?.setFilePan(t, e), this.config.enableStateSync && this.stateManager && this.stateManager.setFilePanValue(t, e);
  }
  /**
   * Set mute state for a specific file track.
   */
  setFileMute(t, e) {
    this.audioPlayer?.setFileMute(t, e), this.config.enableStateSync && this.stateManager && this.stateManager.setFileMuteState(t, e);
  }
  /**
   * Set playback rate as percentage (10-200, 100 = normal speed)
   */
  setPlaybackRate(t) {
    this.audioPlayer?.setPlaybackRate(t);
    const e = this.audioPlayer?.getState();
    e && this.dispatchVisualUpdateFromState(e);
  }
  /**
   * Set volume for a specific MIDI file
   */
  setFileVolume(t, e) {
    this.audioPlayer?.setFileVolume(t, e);
  }
  /**
   * Set volume for a specific WAV file
   */
  setWavVolume(t, e) {
    this.audioPlayer?.setWavVolume(t, e);
  }
  /**
   * Refresh WAV/audio players from registry (for mute state updates)
   */
  refreshAudioPlayers() {
    this.audioPlayer?.refreshAudioPlayers?.();
  }
  getState() {
    if (!this.audioPlayer)
      return this.lastKnownState ? {
        ...this.lastKnownState,
        isPlaying: !1
      } : {
        isPlaying: !1,
        currentTime: 0,
        duration: 0,
        volume: this.config.defaultVolume,
        tempo: this.config.defaultTempo,
        originalTempo: this.config.defaultTempo,
        pan: 0,
        isRepeating: !1,
        // New unified state management fields
        masterVolume: this.config.defaultVolume,
        loopMode: "off",
        markerA: null,
        markerB: null,
        nowTime: 0,
        totalTime: 0
      };
    const t = this.audioPlayer.getState();
    return this.lastKnownState = t, t;
  }
  destroy() {
    this.stopUpdateLoop(), this.visualUpdateCallbacks = [], this.audioPlayer && (this.audioPlayer.destroy(), this.audioPlayer = null), this.pianoRollManager = null, this.stateManager = null;
  }
  /**
   * Additional methods for UI integration
   */
  /**
   * Register visual update callback
   */
  onVisualUpdate(t) {
    this.visualUpdateCallbacks.push(t);
  }
  /**
   * Remove visual update callback
   */
  offVisualUpdate(t) {
    const e = this.visualUpdateCallbacks.indexOf(t);
    e > -1 && this.visualUpdateCallbacks.splice(e, 1);
  }
  /**
   * Handle channel mute for L/R controls
   */
  handleChannelMute(t) {
    this.audioPlayer && (t ? this.muteDueNoLR || (this.lastVolumeBeforeMute = this.audioPlayer.getState().volume, this.audioPlayer.setVolume(0), this.muteDueNoLR = !0) : this.muteDueNoLR && (this.audioPlayer.setVolume(this.lastVolumeBeforeMute), this.muteDueNoLR = !1));
  }
  /**
   * Get PianoRollManager instance
   */
  getPianoRollManager() {
    return this.pianoRollManager;
  }
  /**
   * Check if engine is initialized
   */
  isInitialized() {
    return this.audioPlayer !== null && this.pianoRollManager !== null;
  }
  /**
   * Private helper methods
   */
  getNotesSignature(t) {
    if (t.length === 0) return "0";
    const e = /* @__PURE__ */ new Set();
    return t.forEach((s) => {
      s.fileId && e.add(s.fileId);
    }), Array.from(e).sort().join(",") + ":" + t.length;
  }
  /**
   * Dispatch a visual update event to all registered callbacks.
   */
  dispatchVisualUpdate(t) {
    this.visualUpdateCallbacks.forEach((e) => {
      try {
        e(t);
      } catch (s) {
        console.error("Error in visual update callback:", s);
      }
    });
  }
  /**
   * Helper: build `VisualUpdateParams` from an `AudioPlayerState` and dispatch.
   */
  dispatchVisualUpdateFromState(t) {
    const e = {
      currentTime: t.currentTime,
      duration: t.duration,
      isPlaying: t.isPlaying,
      volume: t.volume,
      tempo: t.tempo,
      pan: t.pan
    };
    this.dispatchVisualUpdate(e);
  }
  startUpdateLoop() {
    if (this.updateLoopId !== null) return;
    const t = () => {
      if (!this.audioPlayer || this.seeking) return;
      const e = this.audioPlayer.getState();
      this.pianoRollManager && this.pianoRollManager.setTime(e.currentTime), this.config.enableStateSync && this.stateManager && this.stateManager.updatePlaybackState({
        currentTime: e.currentTime,
        duration: e.duration,
        isPlaying: e.isPlaying,
        volume: e.volume
      }), this.dispatchVisualUpdateFromState(e);
    };
    t(), this.updateLoopId = window.setInterval(
      t,
      this.config.updateInterval
    );
  }
  stopUpdateLoop() {
    this.updateLoopId !== null && (clearInterval(this.updateLoopId), this.updateLoopId = null);
  }
  syncWithStateManager() {
    if (!this.stateManager || !this.audioPlayer) return;
    const t = this.audioPlayer.getState();
    this.stateManager.updatePlaybackState({
      currentTime: t.currentTime,
      duration: t.duration,
      isPlaying: t.isPlaying,
      volume: t.volume
    });
  }
}
let ro = null;
function XC(n, t) {
  if (ro) {
    try {
      ro.destroy();
    } catch {
    }
    ro = null;
  }
  const e = new jC(n, t);
  return ro = e, e;
}
const Dh = {
  width: 800,
  height: 400,
  backgroundColor: 16777215,
  playheadColor: 1982639,
  showPianoKeys: !0,
  noteRange: { min: 21, max: 108 },
  minorTimeStep: 4
};
class YC {
  constructor(t = {}, e = {}) {
    this.pianoRollInstance = null, this.pianoRollContainer = null, this.currentNoteColors = [], this.config = { ...Dh, ...t }, this.enableOverlapDetection = e.enableOverlapDetection ?? !0, this.overlapColor = e.overlapColor ?? 8388736;
  }
  /**
   * Initialize piano roll with container
   */
  async initialize(t, e = []) {
    this.pianoRollContainer = t;
    const s = {
      ...this.config,
      width: t.clientWidth || this.config.width,
      noteRenderer: (i, r) => this.currentNoteColors[r] || 6710886
    };
    this.pianoRollInstance = await Eb(t, e, s), this.pianoRollInstance.setMinorTimeStep && this.pianoRollInstance.setMinorTimeStep(this.config.minorTimeStep);
  }
  /**
   * Update visualization with colored notes
   */
  async updateVisualization(t) {
    if (!this.pianoRollInstance)
      throw new Error("PianoRoll not initialized");
    if (t.length === 0) {
      this.currentNoteColors = [], this.pianoRollInstance.setNotes([]);
      return;
    }
    const { notes: e, noteColors: s } = this.processNotesWithColors(t);
    this.currentNoteColors = s, this.pianoRollInstance.setNotes(e);
  }
  /**
   * Process notes with color handling and overlap detection
   */
  processNotesWithColors(t) {
    const e = [], s = [];
    return t.forEach((i) => {
      e.push(i.note), s.push(i.color);
    }), { notes: e, noteColors: s };
  }
  /**
   * Set playhead time position
   */
  setTime(t) {
    this.pianoRollInstance?.setTime(t);
  }
  /**
   * Set zoom level
   */
  setZoom(t) {
    this.pianoRollInstance?.zoomX && this.pianoRollInstance.zoomX(t);
  }
  /**
   * Get current zoom level
   */
  getZoom() {
    return this.pianoRollInstance?.getState && this.pianoRollInstance.getState().zoomX || 1;
  }
  /**
   * Update piano roll configuration
   */
  updateConfig(t) {
    this.config = { ...this.config, ...t }, t.minorTimeStep !== void 0 && this.pianoRollInstance?.setMinorTimeStep && this.pianoRollInstance.setMinorTimeStep(t.minorTimeStep);
  }
  /**
   * Get piano roll instance for direct access
   */
  getPianoRollInstance() {
    return this.pianoRollInstance;
  }
  /**
   * Get piano roll container element
   */
  getContainer() {
    return this.pianoRollContainer;
  }
  /**
   * Check if piano roll is initialized
   */
  isInitialized() {
    return this.pianoRollInstance !== null;
  }
  /**
   * Recreate piano roll with new configuration
   */
  async recreate(t = []) {
    if (!this.pianoRollContainer)
      throw new Error("Container not set");
    const e = this.getZoom();
    this.pianoRollContainer.innerHTML = "";
    const s = document.createElement("div");
    s.style.cssText = `
      width: 100%;
      height: ${this.config.height}px;
      border: 1px solid #ddd;
      border-radius: 8px;
      margin-bottom: 20px;
      background: #ffffff;
    `, this.pianoRollContainer.appendChild(s), await this.initialize(s, t), e !== 1 && this.setZoom(e);
  }
  /**
   * Destroy piano roll and cleanup
   */
  destroy() {
    this.pianoRollInstance?.destroy && this.pianoRollInstance.destroy(), this.pianoRollInstance = null, this.pianoRollContainer = null, this.currentNoteColors = [];
  }
}
function Ag(n, t) {
  return new YC(n, t);
}
const Ho = class Ho {
  constructor(t = {}) {
    this.masterVolume = 1, this.wasPausedBySilence = !1, this.midiManager = null, this.pendingPauseTimer = null, this.options = t, this.fileVolumeManager = new mf(), this.wavVolumeManager = new mf();
  }
  /**
   * Attach MIDI manager so WAV mute/volume updates can consider current MIDI state.
   * This prevents false "all silent" detections when only WAV is muted.
   */
  attachMidiManager(t) {
    this.midiManager = t, this.syncFromMidiManagerIfAvailable();
  }
  /**
   * Set per-file volume (0-1)
   */
  setFileVolume(t, e) {
    const s = this.isAllSilent();
    this.fileVolumeManager.setVolume(t, e);
    const i = this.isAllSilent();
    this.handleSilenceChange(s, i);
  }
  /**
   * Set WAV file volume (0-1)
   */
  setWavVolume(t, e) {
    this.syncFromMidiManagerIfAvailable();
    const s = this.isAllSilent();
    this.wavVolumeManager.setVolume(t, e), this.syncFromMidiManagerIfAvailable();
    const i = this.isAllSilent();
    this.handleSilenceChange(s, i);
  }
  /**
   * Set file mute state
   */
  setFileMute(t, e) {
    const s = this.isAllSilent();
    this.fileVolumeManager.setMuted(t, e);
    const i = this.isAllSilent();
    this.handleSilenceChange(s, i);
  }
  /**
   * Set WAV mute state
   */
  setWavMute(t, e) {
    this.syncFromMidiManagerIfAvailable();
    const s = this.isAllSilent();
    this.wavVolumeManager.setMuted(t, e), this.syncFromMidiManagerIfAvailable();
    const i = this.isAllSilent();
    this.handleSilenceChange(s, i);
  }
  /**
   * Set master volume
   */
  setMasterVolume(t) {
    const e = this.isAllSilent();
    this.masterVolume = t, this.fileVolumeManager.setMasterVolume(t), this.wavVolumeManager.setMasterVolume(t);
    const s = this.isAllSilent();
    this.handleSilenceChange(e, s);
  }
  /**
   * Check current silence state and update if needed
   * This is called when volumes are changed via UI
   */
  checkSilence(t) {
    const e = this.isAllSilent();
    t ? this.syncFromMidiManager(t) : this.syncFromMidiManagerIfAvailable();
    const s = globalThis._waveRollAudio;
    s?.getFiles && (s.getFiles() || []).forEach((o) => {
      const a = this.wavVolumeManager.getVolume(o.id), l = a === 0 || o.isMuted === !0;
      this.wavVolumeManager.setMuted(o.id, l), a === void 0 && this.wavVolumeManager.setVolume(o.id, l ? 0 : 1);
    });
    const i = this.isAllSilent();
    this.handleSilenceChange(e, i);
  }
  /**
   * Sync MIDI file mute/volume status into the internal file manager.
   */
  syncFromMidiManager(t) {
    try {
      (t?.getState?.()?.files || []).forEach((i) => {
        const r = this.fileVolumeManager.getVolume(i.id), o = r === 0 || i.isMuted === !0;
        this.fileVolumeManager.setMuted(i.id, o), r === void 0 && this.fileVolumeManager.setVolume(i.id, o ? 0 : 1);
      });
    } catch {
    }
  }
  syncFromMidiManagerIfAvailable() {
    this.midiManager && this.syncFromMidiManager(this.midiManager);
  }
  /**
   * Check if all audio sources are effectively silent
   */
  isAllSilent() {
    try {
      if (this.midiManager?.getState) {
        const l = this.midiManager.getState();
        if (Array.isArray(l?.files) && l.files.some((c) => c && c.isMuted === !1))
          return !1;
      }
    } catch {
    }
    const t = this.fileVolumeManager.getState(), e = this.wavVolumeManager.getState();
    if (!(t.sources.size > 0 || e.sources.size > 0))
      return !1;
    const i = this.fileVolumeManager.isAllSilent(), r = this.wavVolumeManager.isAllSilent(), o = t.sources.size > 0, a = e.sources.size > 0;
    return o && a ? i && r : o ? i : a ? r : !1;
  }
  /**
   * Handle silence state changes
   */
  handleSilenceChange(t, e) {
    try {
      typeof window < "u" && window.dispatchEvent(new CustomEvent("wr-silence-changed", { detail: { isAllSilent: e } }));
    } catch {
    }
    if (!t && e) {
      if (this.pendingPauseTimer !== null && (clearTimeout(this.pendingPauseTimer), this.pendingPauseTimer = null), this.hasAnyExternalAudible())
        return;
      this.pendingPauseTimer = setTimeout(() => {
        if (this.pendingPauseTimer = null, !!this.isAllSilent()) {
          try {
            if (je().state === "started")
              return;
          } catch {
          }
          this.wasPausedBySilence = !0, this.options.onSilenceDetected && this.options.onSilenceDetected();
        }
      }, Ho.PAUSE_DEBOUNCE_MS);
    } else t && !e && (this.pendingPauseTimer !== null && (clearTimeout(this.pendingPauseTimer), this.pendingPauseTimer = null), this.options.onSoundDetected && this.options.onSoundDetected(), this.wasPausedBySilence && this.options.autoResumeOnUnmute && (this.wasPausedBySilence = !1));
  }
  /** Public accessor for effective silence state (for initial UI sync) */
  isEffectivelySilent() {
    return this.isAllSilent();
  }
  /**
   * External sanity check: detect any audible sources directly from providers.
   * Returns true if at least one source (MIDI or WAV) is currently unmuted/visible.
   */
  hasAnyExternalAudible() {
    try {
      if (this.midiManager?.getState) {
        const e = this.midiManager.getState();
        if (Array.isArray(e?.files) && e.files.some((i) => i && i.isMuted === !1))
          return !0;
      }
      const t = globalThis._waveRollAudio;
      if (t?.getFiles && (t.getFiles() || []).some((i) => i && i.isVisible && i.isMuted === !1))
        return !0;
    } catch {
    }
    return !1;
  }
  /**
   * Reset the silence detector state
   */
  reset() {
    this.fileVolumeManager.clear(), this.wavVolumeManager.clear(), this.masterVolume = 1, this.wasPausedBySilence = !1;
  }
};
Ho.PAUSE_DEBOUNCE_MS = 400;
let $l = Ho;
function ZC(n) {
  const t = [];
  for (const r of n)
    if (r.visible !== !1)
      for (const { start: o, end: a } of r.intervals)
        a <= o || (t.push({ time: o, delta: 1 }), t.push({ time: a, delta: -1 }));
  if (t.length === 0) return [];
  t.sort(
    (r, o) => r.time === o.time ? r.delta - o.delta : r.time - o.time
  );
  const e = [];
  let s = 0, i = null;
  for (const { time: r, delta: o } of t) {
    const a = s;
    s += o, a < 2 && s >= 2 ? i = r : a >= 2 && s < 2 && i !== null && (r > i && e.push({ start: i, end: r }), i = null);
  }
  return e;
}
const KC = {
  defaultPianoRollConfig: Dh,
  updateInterval: 50,
  enableOverlapDetection: !0,
  overlapColor: parseInt(nm.replace("#", ""), 16)
};
class QC {
  constructor(t = {}) {
    this.visualUpdateCallbacks = [], this.unsubscribeBaselineEvent = null, this.config = { ...KC, ...t }, this.coreEngine = XC(void 0, {
      updateInterval: this.config.updateInterval,
      enableStateSync: !1
    }), this.pianoRollManager = Ag(
      this.config.defaultPianoRollConfig,
      {
        enableOverlapDetection: this.config.enableOverlapDetection,
        overlapColor: this.config.overlapColor
      }
    ), this.coreEngine.onVisualUpdate((e) => {
      const s = {
        ...e,
        zoomLevel: this.pianoRollManager.getZoom()
      };
      this.notifyVisualUpdateCallbacks(s);
    }), this.unsubscribeBaselineEvent = ho.subscribeBaseline((e, s) => {
      try {
        this.coreEngine.setOriginalTempo?.(e);
      } catch {
      }
      this.setTempo(e);
    });
  }
  /**
   * Initialize piano roll with a container element
   */
  async initializePianoRoll(t, e, s = {}) {
    const i = {
      ...this.config.defaultPianoRollConfig,
      ...s
    };
    this.pianoRollManager.updateConfig(i), await this.pianoRollManager.initialize(t, e), await this.coreEngine.initialize(this.pianoRollManager);
    try {
      window._waveRollViz = {
        setOriginalTempo: (r) => {
          try {
            this.coreEngine.setOriginalTempo?.(r);
          } catch {
          }
        },
        setTempo: (r) => this.setTempo(r),
        getState: () => this.getState()
      };
    } catch {
    }
  }
  /**
   * Update visualization with new note data
   */
  async updateVisualization(t, e) {
    let s = t;
    if (this.config.enableOverlapDetection) {
      const r = {};
      t.forEach(({ note: a, fileId: l }) => {
        if (!l) return;
        const c = a.time + a.duration;
        (r[l] = r[l] || []).push({
          start: a.time,
          end: c
        });
      });
      const o = ZC(
        Object.values(r).map((a) => ({
          id: "overlap",
          intervals: a
        }))
      );
      s = t.map((a) => {
        const l = a.note.time, c = l + a.note.duration;
        return o.some(
          (u) => u.start < c && u.end > l
        ) ? { ...a, color: this.config.overlapColor } : a;
      });
    }
    await this.pianoRollManager.updateVisualization(s);
    const i = e ?? s.filter((r) => !r.isMuted).map((r) => r.note);
    await this.coreEngine.updateAudio(i);
  }
  /**
   * Get piano roll instance
   */
  getPianoRollInstance() {
    return this.pianoRollManager.getPianoRollInstance();
  }
  /**
   * Set minor time step
   */
  setMinorTimeStep(t) {
    this.pianoRollManager.updateConfig({ minorTimeStep: t });
  }
  /**
   * Get current zoom level
   */
  getZoomLevel() {
    return this.pianoRollManager.getZoom();
  }
  /**
   * Set zoom level
   */
  setZoomLevel(t) {
    this.pianoRollManager.setZoom(t);
  }
  /**
   * Set playhead time
   */
  setTime(t) {
    this.pianoRollManager.setTime(t);
  }
  /**
   * Get current audio player state
   */
  getAudioPlayerState() {
    return this.coreEngine.getState();
  }
  /**
   * Control audio playback - Delegate to core engine
   */
  async play() {
    await this.coreEngine.play();
  }
  pause() {
    this.coreEngine.pause();
  }
  seek(t, e = !0) {
    this.coreEngine.seek(t, e);
  }
  setVolume(t) {
    this.coreEngine.setVolume(t);
  }
  /** Master volume proxy for v2 engine */
  get masterVolume() {
    return this.coreEngine.getState().volume;
  }
  set masterVolume(t) {
    this.coreEngine.setVolume(t);
  }
  // Global pan control removed in v2 player
  /**
   * Set pan for a specific MIDI file track.
   */
  setFilePan(t, e) {
    this.coreEngine.setFilePan(t, e);
  }
  /**
   * Set mute state for a specific MIDI file track.
   */
  setFileMute(t, e) {
    this.coreEngine.setFileMute(t, e);
  }
  /**
   * Refresh WAV/audio players from registry (for mute state updates)
   */
  refreshAudioPlayers() {
    this.coreEngine.refreshAudioPlayers();
  }
  /** Set per-file MIDI volume */
  setFileVolume(t, e) {
    this.coreEngine.setFileVolume(t, e);
  }
  /** Set per-file WAV volume */
  setWavVolume(t, e) {
    this.coreEngine.setWavVolume(t, e);
  }
  setTempo(t) {
    this.coreEngine.setTempo(t);
    const e = this.coreEngine.getState();
    this.notifyVisualUpdateCallbacks({
      currentTime: e.currentTime,
      duration: e.duration,
      zoomLevel: this.pianoRollManager.getZoom(),
      isPlaying: e.isPlaying,
      volume: e.volume,
      tempo: e.tempo,
      pan: e.pan || 0
    });
  }
  /**
   * Set playback rate as percentage (10-200, 100 = normal speed)
   */
  setPlaybackRate(t) {
    this.coreEngine.setPlaybackRate(t);
    const e = this.coreEngine.getState();
    this.notifyVisualUpdateCallbacks({
      currentTime: e.currentTime,
      duration: e.duration,
      zoomLevel: 1,
      // Default zoom level
      isPlaying: e.isPlaying,
      volume: e.volume,
      tempo: e.tempo,
      pan: e.pan || 0
    });
  }
  /**
   * Register visual update callback
   */
  onVisualUpdate(t) {
    this.visualUpdateCallbacks.push(t);
  }
  /**
   * Start visual update loop
   */
  startVisualUpdateLoop() {
  }
  /**
   * Stop visual update loop
   */
  stopVisualUpdateLoop() {
  }
  /**
   * Clean up resources
   */
  destroy() {
    this.unsubscribeBaselineEvent && (this.unsubscribeBaselineEvent(), this.unsubscribeBaselineEvent = null), this.coreEngine.destroy(), this.pianoRollManager.destroy(), this.visualUpdateCallbacks = [];
  }
  /**
   * Check if visualization is initialized
   */
  isInitialized() {
    return this.coreEngine.isInitialized();
  }
  /**
   * Get engine info
   */
  getEngineInfo() {
    return {
      width: this.config.defaultPianoRollConfig.width,
      height: this.config.defaultPianoRollConfig.height,
      fps: Math.round(1e3 / this.config.updateInterval)
    };
  }
  /**
   * Proxy - enable UI to access underlying player state
   */
  getState() {
    return this.coreEngine.getState();
  }
  /**
   * Proxy repeat toggle to underlying audio player
   */
  toggleRepeat(t) {
    this.coreEngine.toggleRepeat(t);
  }
  /**
   * Proxy custom loop points (A-B) to underlying audio player
   */
  setLoopPoints(t, e, s = !1) {
    this.coreEngine.setLoopPoints(t, e, s);
  }
  /**
   * Notify visual update callbacks
   */
  notifyVisualUpdateCallbacks(t) {
    this.visualUpdateCallbacks.forEach((e) => {
      try {
        e(t);
      } catch (s) {
        console.error("Error in visual update callback:", s);
      }
    });
  }
}
const li = {
  defaultVolume: 1,
  defaultMinorTimeStep: 0.1,
  defaultZoomLevel: 1,
  updateInterval: 50
  // 50ms update interval
}, JC = {
  seeking: !1,
  isBatchLoading: !1,
  updateLoopId: null,
  muteDueNoLR: !1,
  lastVolumeBeforeMute: li.defaultVolume,
  minorTimeStep: li.defaultMinorTimeStep
}, t2 = {
  currentTime: 0,
  duration: 0,
  isPlaying: !1,
  volume: li.defaultVolume,
  playbackGeneration: 0,
  nowTime: 0,
  masterVolume: li.defaultVolume,
  tempo: 120,
  loopMode: "off",
  markerA: null,
  markerB: null
}, e2 = {
  visibleFileIds: /* @__PURE__ */ new Set(),
  totalFiles: 0
}, s2 = {
  a: null,
  b: null
}, n2 = {
  filePanValues: {},
  filePanStateHandlers: {},
  fileMuteStates: {}
}, i2 = {
  currentNoteColors: [],
  zoomLevel: li.defaultZoomLevel,
  highlightMode: "eval-tp-only-gray",
  minOffsetTolerance: 0.05,
  pedalElongate: !0,
  pedalThreshold: 64,
  showOnsetMarkers: !0,
  fileOnsetMarkers: {},
  uniformTrackColor: !1
}, r2 = {
  refId: null,
  estIds: [],
  onsetTolerance: 0.05,
  pitchTolerance: 0.5,
  offsetRatioTolerance: 0.2,
  offsetMinTolerance: 0.05,
  anchor: "intersection",
  showLoopOnlyMetrics: !1,
  refOnTop: !1
}, o2 = {
  ui: JC,
  playback: t2,
  fileVisibility: e2,
  loopPoints: s2,
  panVolume: n2,
  visual: i2,
  evaluation: r2
};
function a2(n, t, e) {
  const s = n.ui.isBatchLoading;
  n.ui.isBatchLoading = !0;
  try {
    return e();
  } finally {
    n.ui.isBatchLoading = s, s || t();
  }
}
function Hl(n) {
  if (n == null || typeof n != "object") return n;
  if (n instanceof Set)
    return new Set(n);
  if (n instanceof Map)
    return new Map(n);
  if (Array.isArray(n))
    return n.map((e) => Hl(e));
  const t = {};
  for (const e in n)
    n.hasOwnProperty(e) && (t[e] = Hl(n[e]));
  return t;
}
class l2 {
  constructor(t = /* @__PURE__ */ new Set(), e) {
    this.set = new Set(t), this.onUpdate = e || (() => {
    });
  }
  add(t) {
    this.set.add(t), this.onUpdate(this.set);
  }
  remove(t) {
    this.set.delete(t), this.onUpdate(this.set);
  }
  toggle(t) {
    const e = this.set.has(t);
    return e ? this.remove(t) : this.add(t), !e;
  }
  has(t) {
    return this.set.has(t);
  }
  clear() {
    this.set.clear(), this.onUpdate(this.set);
  }
  sync(t) {
    this.set = new Set(t), this.onUpdate(this.set);
  }
  get size() {
    return this.set.size;
  }
  get values() {
    return new Set(this.set);
  }
}
class c2 {
  constructor() {
    this.listeners = [];
  }
  /**
   * Add a listener
   */
  add(t) {
    this.listeners.push(t);
  }
  /**
   * Remove a listener
   */
  remove(t) {
    const e = this.listeners.indexOf(t);
    e !== -1 && this.listeners.splice(e, 1);
  }
  /**
   * Notify all listeners with error handling
   */
  notify(...t) {
    this.listeners.forEach((e) => {
      try {
        e(...t);
      } catch (s) {
        console.error("Error in listener callback:", s);
      }
    });
  }
  /**
   * Clear all listeners
   */
  clear() {
    this.listeners = [];
  }
  /**
   * Get listener count
   */
  get count() {
    return this.listeners.length;
  }
}
function gf(n, t) {
  return n === null || t === 0 ? null : n / 100 * t;
}
function h2(n, t) {
  return n !== null && t !== null && n > t ? [t, n] : [n, t];
}
function is(n, ...t) {
  return Object.assign({}, n, ...t);
}
class u2 {
  constructor(t = {}, e) {
    this.record = { ...t }, this.onUpdate = e;
  }
  /**
   * Set a value in the record
   */
  set(t, e) {
    this.record[t] = e, this.notifyUpdate();
  }
  /**
   * Get a value from the record
   */
  get(t) {
    return this.record[t];
  }
  /**
   * Remove a key from the record
   */
  remove(t) {
    delete this.record[t], this.notifyUpdate();
  }
  /**
   * Check if a key exists
   */
  has(t) {
    return t in this.record;
  }
  /**
   * Clear all entries
   */
  clear() {
    this.record = {}, this.notifyUpdate();
  }
  /**
   * Get all keys
   */
  keys() {
    return Object.keys(this.record);
  }
  /**
   * Get all values
   */
  values() {
    return Object.values(this.record);
  }
  /**
   * Get all entries
   */
  entries() {
    return Object.entries(this.record);
  }
  /**
   * Iterate over all values
   */
  forEach(t) {
    Object.entries(this.record).forEach(([e, s]) => {
      t(s, e);
    });
  }
  /**
   * Apply a function to all values
   */
  mapValues(t) {
    const e = {};
    return this.forEach((s, i) => {
      e[i] = t(s, i);
    }), e;
  }
  /**
   * Filter entries
   */
  filter(t) {
    const e = {};
    return this.forEach((s, i) => {
      t(s, i) && (e[i] = s);
    }), e;
  }
  /**
   * Get the underlying record (immutable copy)
   */
  toRecord() {
    return { ...this.record };
  }
  /**
   * Get the number of entries
   */
  get size() {
    return this.keys().length;
  }
  notifyUpdate() {
    this.onUpdate && this.onUpdate(this.toRecord());
  }
}
class d2 {
  constructor(t = {}) {
    this.listeners = new c2(), this.config = is(li, t), this.state = this.createInitialState(), this.fileVisibilityManager = new l2(
      this.state.fileVisibility.visibleFileIds || /* @__PURE__ */ new Set(),
      (e) => {
        this.state.fileVisibility.visibleFileIds = e, this.state.fileVisibility.totalFiles = e.size, this.notify();
      }
    ), this.panHandlersManager = new u2(
      this.state.panVolume.filePanStateHandlers,
      (e) => {
        this.state.panVolume.filePanStateHandlers = e;
      }
    );
  }
  /* ====== state creation  ====== */
  createInitialState() {
    return Hl(o2);
  }
  /* ====== state getters  ====== */
  getUIState() {
    return this.state.ui;
  }
  getState() {
    return this.state;
  }
  getConfig() {
    return is(this.config);
  }
  getFilePanValuesRef() {
    return this.state.panVolume.filePanValues;
  }
  getFilePanStateHandlersRef() {
    return this.state.panVolume.filePanStateHandlers;
  }
  getFileMuteStatesRef() {
    return this.state.panVolume.fileMuteStates;
  }
  /* ====== state setters  ====== */
  /**
   * Update UI state
   */
  updateUIState(t) {
    this.state.ui = is(this.state.ui, t), this.notify();
  }
  /**
   * Update playback state
   */
  updatePlaybackState(t) {
    this.state.playback = is(this.state.playback, t), this.notify();
  }
  /**
   * Update file visibility state
   */
  updateFileVisibilityState(t) {
    this.state.fileVisibility = is(this.state.fileVisibility, t), this.notify();
  }
  /**
   * Update loop points state
   */
  updateLoopPointsState(t) {
    this.state.loopPoints = is(this.state.loopPoints, t), this.notify();
  }
  /**
   * Update pan/volume state
   */
  updatePanVolumeState(t) {
    this.state.panVolume = is(this.state.panVolume, t), this.notify();
  }
  /**
   * Update visual state
   */
  updateVisualState(t) {
    this.state.visual = is(this.state.visual, t), this.notify();
  }
  /**
   * Update evaluation state
   */
  updateEvaluationState(t) {
    this.state.evaluation = is(this.state.evaluation, t), this.notify();
  }
  /* ====== Onset Marker Mapping ====== */
  /** Assign or update the onset marker style for a file. */
  setOnsetMarkerForFile(t, e) {
    this.state.visual.fileOnsetMarkers[t] = e, this.notify();
  }
  /** Get the onset marker style for a file, if any. */
  getOnsetMarkerForFile(t) {
    return this.state.visual.fileOnsetMarkers[t];
  }
  /** Ensure a unique onset marker is assigned to the file if missing. */
  ensureOnsetMarkerForFile(t) {
    const e = this.state.visual.fileOnsetMarkers[t];
    if (e) return e;
    const s = new Set(
      Object.values(this.state.visual.fileOnsetMarkers).map((r) => `${r.shape}:${r.variant}`)
    );
    let i = null;
    for (const r of as) {
      const o = `${r}:filled`;
      if (!s.has(o)) {
        i = { shape: r, variant: "filled", size: 12, strokeWidth: 2 };
        break;
      }
    }
    if (!i)
      for (const r of as) {
        const o = `${r}:outlined`;
        if (!s.has(o)) {
          i = { shape: r, variant: "outlined", size: 12, strokeWidth: 2 };
          break;
        }
      }
    return i || (i = { shape: as[Object.keys(this.state.visual.fileOnsetMarkers).length % as.length], variant: "outlined", size: 12, strokeWidth: 2 }), this.state.visual.fileOnsetMarkers[t] = i, this.notify(), i;
  }
  /**
   * Assign the next available unique onset marker to the file, even if it already has one.
   * Cycles shapes (filled first, then outlined) and skips the current style when possible.
   */
  assignNextUniqueOnsetMarker(t) {
    const e = this.state.visual.fileOnsetMarkers[t], s = [
      ...as.map((c) => ({ shape: c, variant: "filled", size: 12, strokeWidth: 2 })),
      ...as.map((c) => ({ shape: c, variant: "outlined", size: 12, strokeWidth: 2 }))
    ], i = new Set(
      Object.entries(this.state.visual.fileOnsetMarkers).filter(([c]) => c !== t).map(([, c]) => `${c.shape}:${c.variant}`)
    ), r = s.filter((c) => !i.has(`${c.shape}:${c.variant}`));
    if (r.length === 0)
      return e || this.ensureOnsetMarkerForFile(t);
    const o = e ? r.findIndex((c) => c.shape === e.shape && c.variant === e.variant) : -1, l = { ...r[(o + 1) % r.length] };
    return this.state.visual.fileOnsetMarkers[t] = l, this.notify(), l;
  }
  /* ====== state synchronization utilities  ====== */
  /**
   * Preserve state during updates (batch operations)
   */
  preserveStateForBatch(t) {
    return a2(this.state, () => this.notify(), t);
  }
  /**
   * Synchronize file visibility with a set of file IDs
   */
  syncFileVisibility(t) {
    this.fileVisibilityManager.sync(t);
  }
  /**
   * Add file to visibility tracking
   */
  addFileToVisibility(t) {
    this.fileVisibilityManager.add(t);
  }
  /**
   * Remove file from visibility tracking
   */
  removeFileFromVisibility(t) {
    this.fileVisibilityManager.remove(t);
  }
  /**
   * Toggle file visibility
   */
  toggleFileVisibility(t) {
    return this.fileVisibilityManager.toggle(t);
  }
  /* ====== Pan / volume  ====== */
  /**
   * Set pan value for a file
   */
  setFilePanValue(t, e) {
    this.state.panVolume.filePanValues[t] = e, this.notify();
  }
  /**
   * Register pan state handler for a file
   */
  registerFilePanHandler(t, e) {
    this.panHandlersManager.set(t, e);
  }
  /**
   * Unregister pan state handler for a file
   */
  unregisterFilePanHandler(t) {
    this.panHandlersManager.remove(t);
  }
  /**
   * Synchronize pan values across all files
   */
  syncPanValues(t) {
    this.panHandlersManager.forEach((e) => {
      e(t);
    });
  }
  /**
   * Set mute state for a file
   */
  setFileMuteState(t, e) {
    this.state.panVolume.fileMuteStates[t] = e, this.notify();
  }
  /**
   * Get mute state for a file
   */
  getFileMuteState(t) {
    return this.state.panVolume.fileMuteStates[t] || !1;
  }
  /* ====== loop points  ====== */
  /**
   * Set loop points with validation
   */
  setLoopPoints(t, e) {
    const [s, i] = h2(t, e);
    this.state.loopPoints = { a: s, b: i }, this.notify();
  }
  /**
   * Clear loop points
   */
  clearLoopPoints() {
    this.setLoopPoints(null, null);
  }
  /**
   * Set loop points from percentages
   */
  setLoopPointsFromPercentages(t, e) {
    const { duration: s } = this.state.playback;
    s !== 0 && this.setLoopPoints(
      gf(t, s),
      gf(e, s)
    );
  }
  /* ====== config & reset  ====== */
  /**
   * Update configuration
   */
  updateConfig(t) {
    this.config = is(this.config, t);
  }
  /**
   * Reset state to initial values
   */
  resetState() {
    this.state = this.createInitialState(), this.notify();
  }
  /* ====== helpers  ====== */
  /**
   * Register state change callback
   */
  onStateChange(t) {
    this.listeners.add(t);
  }
  /**
   * Unregister state change callback
   */
  offStateChange(t) {
    this.listeners.remove(t);
  }
  /**
   * Notify all registered callbacks of state change
   */
  notify() {
    this.state.ui.isBatchLoading || this.listeners.notify();
  }
}
const Eg = [];
function f2() {
  const n = globalThis;
  if (!n._waveRollAudio) {
    const t = { items: [] }, e = {
      getFiles() {
        return t.items.slice();
      },
      getVisiblePeaks() {
        const s = [];
        for (const i of t.items) {
          if (!i.isVisible || !i.peaks || !i.audioBuffer) continue;
          const { min: r, max: o } = i.peaks, a = i.audioBuffer.duration;
          for (let l = 0; l < o.length; l++) {
            const c = l / o.length * a;
            s.push({ time: c, min: r[l], max: o[l], color: i.color });
          }
        }
        return s;
      },
      sampleAtTime(s) {
        let i = null;
        for (const r of t.items) {
          if (!r.isVisible || !r.peaks || !r.audioBuffer) continue;
          const o = r.audioBuffer.duration;
          if (o <= 0) continue;
          const a = Math.max(0, Math.min(r.peaks.max.length - 1, Math.floor(s / o * r.peaks.max.length))), l = {
            min: r.peaks.min[a],
            max: r.peaks.max[a],
            color: r.color
          };
          (!i || l.max > i.max) && (i = l);
        }
        return i;
      },
      toggleVisibility(s) {
        const i = t.items.find((r) => r.id === s);
        i && (i.isVisible = !i.isVisible);
      },
      setVisibility(s, i) {
        const r = t.items.find((o) => o.id === s);
        r && (r.isVisible = !!i);
      },
      toggleMute(s) {
        const i = t.items.find((r) => r.id === s);
        i && (i.isMuted = !i.isMuted);
      },
      setMute(s, i) {
        const r = t.items.find((o) => o.id === s);
        r && (r.isMuted = !!i);
      },
      setPan(s, i) {
        const r = t.items.find((o) => o.id === s);
        r && (r.pan = Math.max(-1, Math.min(1, i)));
      },
      updateName(s, i) {
        const r = t.items.find((o) => o.id === s);
        r && (r.name = i);
      },
      updateColor(s, i) {
        const r = t.items.find((o) => o.id === s);
        r && (r.color = i >>> 0);
      },
      remove(s) {
        const i = t.items.findIndex((r) => r.id === s);
        if (i !== -1) {
          t.items.splice(i, 1);
          try {
            window.dispatchEvent(new CustomEvent("wr-audio-files-changed"));
          } catch {
          }
        }
      },
      _store: t
    };
    n._waveRollAudio = e;
  }
  return globalThis._waveRollAudio;
}
async function Oh(n, t, e, s) {
  const i = f2(), r = i.getFiles();
  for (const l of r)
    i.remove?.(l.id);
  const o = Ib(), a = {
    id: o,
    name: e || t.split("/").pop() || "Audio",
    url: t,
    // Default neutral, high-contrast waveform stroke
    color: s ?? parseInt(hb.replace("#", ""), 16),
    isVisible: !0,
    isMuted: !1,
    pan: 0
  };
  i._store.items.push(a);
  try {
    window.dispatchEvent(new CustomEvent("wr-audio-files-changed"));
  } catch {
  }
  try {
    const l = window.AudioContext || window.webkitAudioContext;
    if (!l) throw new Error("AudioContext not available");
    const c = new l(), u = await (await fetch(t)).arrayBuffer(), d = await c.decodeAudioData(u);
    a.audioBuffer = d;
    const f = Math.min(4e3, Math.max(1e3, Math.floor(d.duration * 200))), { getPeaksFromAudioBuffer: p } = await import("./peaks-CMRd2e3C.js");
    a.peaks = p(d, f);
  } catch (l) {
    console.warn("Audio decode failed", l);
  }
  return o;
}
const p2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  addAudioFileFromUrl: Oh
}, Symbol.toStringTag, { value: "Module" }));
async function m2(n, t = []) {
  n.isBatchLoading = !0;
  const e = t.length > 0 ? t : Eg, s = n.stateManager?.getState(), i = s?.visual.pedalElongate ?? !0, r = s?.visual.pedalThreshold ?? 64;
  for (const o of e)
    try {
      const a = await ci(o.path, {
        applyPedalElongate: i,
        pedalThreshold: r
      }), l = n.midiManager.addMidiFile(
        o.path,
        a,
        o.name,
        o.path
      );
      try {
        n.stateManager?.ensureOnsetMarkerForFile?.(l);
      } catch {
      }
    } catch (a) {
      console.error(`Failed to load ${o.path}:`, a);
    }
  n.isBatchLoading = !1;
}
async function g2(n, t, e = {}) {
  try {
    const s = n.stateManager?.getState(), i = s?.visual.pedalElongate ?? !0, r = s?.visual.pedalThreshold ?? 64, o = await ci(t, {
      applyPedalElongate: i,
      pedalThreshold: r
    }), a = typeof t == "string" ? t : t.name, l = e.name ?? a, c = n.midiManager.addMidiFile(
      a,
      o,
      l,
      t
    );
    try {
      n.stateManager?.ensureOnsetMarkerForFile?.(c);
    } catch {
    }
    return c;
  } catch (s) {
    return console.error("Failed to load file:", s), null;
  }
}
async function y2(n, t, e = {}) {
  const s = n.isBatchLoading;
  !s && !e.suppressBatchLoading && (n.isBatchLoading = !0);
  const i = [], r = n.stateManager?.getState(), o = r?.visual.pedalElongate ?? !0, a = r?.visual.pedalThreshold ?? 64;
  for (const l of t)
    try {
      const c = await ci(l, {
        applyPedalElongate: o,
        pedalThreshold: a
      }), h = e.name ?? l.name, u = n.midiManager.addMidiFile(
        l.name,
        c,
        h,
        l
      );
      i.push(u);
      try {
        n.stateManager?.ensureOnsetMarkerForFile?.(u);
      } catch {
      }
    } catch (c) {
      console.error(`Failed to load ${l.name}:`, c);
    }
  return !s && !e.suppressBatchLoading && (n.isBatchLoading = !1), i;
}
async function Pg(n, t, e = {}) {
  try {
    const s = typeof t == "string" ? t : URL.createObjectURL(t), i = e.name ?? (typeof t == "string" ? t : t.name);
    return await Oh(n, s, i, e.color);
  } catch (s) {
    return console.error("Failed to load audio file:", s), null;
  }
}
async function x2(n, t = []) {
  n.isBatchLoading = !0;
  const e = t.length > 0 ? t : [];
  for (const s of e)
    await Pg(n, s.path, { name: s.name, color: s.color });
  n.isBatchLoading = !1;
}
class _2 {
  constructor(t, e) {
    this.isBatchLoading = !1, this.midiManager = t, this.stateManager = e;
  }
  /** Load default or custom sample files. */
  async loadSampleFiles(t = []) {
    return m2(this, t);
  }
  /** Load a single MIDI file (local File object or URL). */
  async loadFile(t, e = {}) {
    return g2(this, t, e);
  }
  /** Load multiple local files at once. */
  async loadMultipleFiles(t, e = {}) {
    return y2(this, t, e);
  }
  /** Load a single audio file (wav/mp3) */
  async loadAudioFile(t, e = {}) {
    return Pg(this, t, e);
  }
  /** Load sample audio files */
  async loadSampleAudioFiles(t = []) {
    return x2(this, t);
  }
  /* ==READ-ONLY== */
  /**
   * Get all files
   * @returns Array of file entries
   */
  getAllFiles() {
    return this.midiManager.getState().files;
  }
  /**
   * Get a specific file by ID
   * @param fileId - ID of the file
   * @returns File entry or null if not found
   */
  getFile(t) {
    return this.getAllFiles().find((s) => s.id === t) || null;
  }
  /**
   * Get visible files
   * @returns Array of visible file entries
   */
  getVisibleFiles() {
    return this.getAllFiles().filter((t) => t.isPianoRollVisible);
  }
  /**
   * Get file count
   * @returns Number of loaded files
   */
  getFileCount() {
    return this.getAllFiles().length;
  }
  /**
   * Get visible file count
   * @returns Number of visible files
   */
  getVisibleFileCount() {
    return this.getVisibleFiles().length;
  }
  /* ==MUTATE== */
  /**
   * Remove a file from the manager
   * @param fileId - ID of the file to remove
   */
  removeFile(t) {
    this.midiManager.removeMidiFile(t);
  }
  /**
   * Toggle file visibility
   * @param fileId - ID of the file to toggle
   */
  toggleFileVisibility(t) {
    this.midiManager.toggleVisibility(t);
  }
  /**
   * Set file visibility
   * @param fileId - ID of the file
   * @param isVisible - Whether the file should be visible
   */
  setFileVisibility(t, e) {
    const s = this.midiManager.getState().files.find((i) => i.id === t);
    s && s.isPianoRollVisible !== e && this.midiManager.toggleVisibility(t);
  }
  /**
   * Update file name
   * @param fileId - ID of the file
   * @param name - New name
   */
  updateFileName(t, e) {
    this.midiManager.updateName(t, e);
  }
  /**
   * Update file color
   * @param fileId - ID of the file
   * @param color - New color (PixiJS hex color)
   */
  updateFileColor(t, e) {
    this.midiManager.updateColor(t, e);
  }
  /**
   * Check if currently in batch loading mode
   * @returns Whether batch loading is active
   */
  isBatchLoadingActive() {
    return this.isBatchLoading;
  }
  /**
   * Set batch loading mode
   * @param isBatching - Whether to enable batch loading
   */
  setBatchLoading(t) {
    this.isBatchLoading = t;
  }
  /**
   * Clear all files
   */
  clearAllFiles() {
    this.getAllFiles().forEach((e) => this.removeFile(e.id));
  }
  /**
   * Check if a file exists
   * @param fileId - ID of the file to check
   * @returns Whether the file exists
   */
  hasFile(t) {
    return this.getFile(t) !== null;
  }
}
async function v2(n) {
  if (typeof n == "string") {
    const t = await fetch(n);
    if (!t.ok)
      throw new Error(`Failed to fetch MIDI file: ${t.status} ${t.statusText}`);
    return t.arrayBuffer();
  }
  return n.arrayBuffer();
}
function Ig(n, t) {
  const e = URL.createObjectURL(n), s = document.createElement("a");
  s.href = e, s.download = t, document.body.appendChild(s), s.click(), document.body.removeChild(s), URL.revokeObjectURL(e);
}
function b2() {
  return "showSaveFilePicker" in window;
}
async function w2(n, t) {
  if (!b2()) {
    Ig(n, t);
    return;
  }
  try {
    const s = await (await window.showSaveFilePicker({
      suggestedName: t,
      types: [
        {
          description: "MIDI Files",
          accept: {
            "audio/midi": [".mid", ".midi"]
          }
        }
      ]
    })).createWritable();
    await s.write(n), await s.close();
  } catch (e) {
    if (e instanceof Error && e.name === "AbortError")
      return;
    throw e;
  }
}
function Fg(n, t) {
  return `${n ? n.replace(/\.midi?$/i, "") : "exported"}_${Math.round(t)}bpm.mid`;
}
function S2(n) {
  return typeof n == "string" ? n.split("/").pop() : n.name;
}
async function T2(n, t, e = {}, s) {
  const { mode: i = "download", onExport: r } = e, o = await M2(n, t), a = S2(n), l = s ?? Fg(a, t);
  switch (i) {
    case "saveAs":
      await w2(o, l);
      break;
    case "custom":
      if (!r)
        throw new Error("Custom export mode requires onExport handler");
      await r(o, l);
      break;
    case "download":
    default:
      Ig(o, l);
      break;
  }
}
async function M2(n, t) {
  if (!Number.isFinite(t) || t <= 0)
    throw new Error(`Invalid tempo: ${t}. Tempo must be a positive number.`);
  const e = await v2(n), s = new gm.Midi(e);
  s.header.tempos = [
    {
      bpm: t,
      ticks: 0,
      time: 0
    }
  ];
  const i = s.toArray();
  return new Blob([new Uint8Array(i)], { type: "audio/midi" });
}
function k2() {
  const n = "wr-accessible-theme";
  if (document.getElementById(n)) return;
  const t = document.createElement("style");
  t.id = n, t.textContent = `
    :root {
      /* Surfaces */
      --surface: #ffffff; /* Base surface: pure white */
      --surface-alt: #ffffff; /* Keep sections flat on white background */
      --panel-bg: #ffffff; /* Panels also pure white; rely on border/shadow for separation */

      /* Text */
      --text-primary: #0f172a; /* slate-900 – AA on white */
      --text-muted: #475569; /* slate-600 – AA on white for labels */

      /* UI Borders / Tracks (>= 3:1 vs surfaces) */
      --ui-border: #cbd5e1; /* slate-300 */
      --track-bg: #e5e7eb; /* gray-200 – visible track on white */

      /* Accent (ensure white-on-accent >= 4.5:1) */
      --accent: #2563eb; /* blue-600 */
      --accent-strong: #1e40af; /* blue-800 for stronger contrast */
      --on-accent: #ffffff; /* text/icon on accent */

      /* Interaction */
      --hover-surface: #e5e7eb; /* gray-200 hover fill, clearly visible on white */
      --focus-ring: #4f46e5; /* indigo-600 – strong, distinct outline */

      /* Loop region stripes (non-text graphics, >= 3:1 vs track) */
      --loop-stripe-a: rgba(234, 179, 8, 0.8); /* amber-500 @ 0.8 */
      --loop-stripe-b: rgba(217, 119, 6, 0.6);  /* orange-600 @ 0.6 */
      --loop-stripe-border: rgba(234, 179, 8, 0.95);

      /* Shadows */
      --shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
      --shadow-md: 0 4px 10px rgba(0,0,0,0.08);
    }

    /* Focus-visible: thick and obvious for keyboard users */
    .wr-focusable:focus-visible {
      outline-style: solid;
      outline-color: var(--focus-ring);
      outline-width: calc(3px / var(--wr-outline-scale, 1));
      outline-offset: 2px;
    }

    /* Range inputs: show focus via outline on container */
    .wr-slider:focus-visible {
      outline-style: solid;
      outline-color: var(--focus-ring);
      outline-width: calc(3px / var(--wr-outline-scale, 1));
      outline-offset: 2px;
      border-radius: 6px;
    }
  `, document.head.appendChild(t);
}
function Wo(n, t = "var(--hover-surface)", e = "transparent") {
  n.addEventListener("mouseenter", () => {
    n.dataset.active || (n.style.background = t);
  }), n.addEventListener("mouseleave", () => {
    n.dataset.active || (n.style.background = e);
  });
}
function C2(n, t = 1.05, e = 0.95, s = 1) {
  n.addEventListener("mouseenter", () => {
    n.style.transform = `scale(${t})`;
  }), n.addEventListener("mouseleave", () => {
    n.style.transform = `scale(${s})`;
  }), n.addEventListener("mousedown", () => {
    n.style.transform = `scale(${e})`;
  }), n.addEventListener("mouseup", () => {
    n.style.transform = `scale(${t})`;
  });
}
function A2(n) {
  const {
    playBtn: t,
    audioPlayer: e,
    wavPlayerManager: s,
    prePlay: i,
    postPlay: r,
    postPause: o,
    playingColor: a = "#28a745",
    idleColor: l = Me,
    loadingColor: c = "#999999"
  } = n, h = () => {
    const d = !!e?.getState()?.isPlaying, f = s ? s.areAllBuffersReady() : !0;
    d ? (t.innerHTML = lt.pause, t.style.background = a, t.style.opacity = "1", t.style.cursor = "pointer", t.disabled = !1, t.onclick = () => {
      e?.pause(), o?.(), h();
    }) : (t.innerHTML = f ? lt.play : "⏳", t.style.background = f ? l : c, t.style.opacity = f ? "1" : "0.6", t.style.cursor = f ? "pointer" : "not-allowed", t.disabled = !f, f ? t.onclick = async () => {
      try {
        await i?.();
      } catch (p) {
        console.warn("[setupPlayButton] prePlay() failed", p);
      }
      try {
        await e?.play(), r?.(), h();
      } catch (p) {
        console.error("Failed to play:", p), alert(
          `Failed to start playback: ${p instanceof Error ? p.message : "Unknown error"}`
        );
      }
    } : t.onclick = () => {
    });
  };
  return h;
}
function E2(n, t, e = Me) {
  if (!n) return;
  const s = (i) => {
    i ? (n.dataset.active = "true", n.style.background = "rgba(0, 123, 255, 0.1)", n.style.color = e) : (delete n.dataset.active, n.style.background = "transparent", n.style.color = "#495057");
  };
  n.onclick = () => {
    const r = !t?.getState()?.isRepeating;
    t?.toggleRepeat(r), s(r);
  }, s(!!t?.getState()?.isRepeating);
}
async function P2() {
  ut().state !== "running" && await Oc();
  const n = ut();
  if (n.lookAhead = 0.1, n.updateInterval = 0.02, ut().rawContext) {
    const t = ut().rawContext;
    t && t.baseLatency !== void 0 && (t.latencyHint = "playback");
  }
}
async function Rg() {
  try {
    const n = BC;
    if (!n.getContext) {
      if (n.start)
        try {
          await n.start();
        } catch {
        }
      return;
    }
    const t = n.getContext();
    t?.state === "suspended" && typeof t.resume == "function" && await t.resume(), t?.state !== "running" && n.start && await n.start();
    try {
      await P2();
    } catch {
    }
  } catch {
  }
}
function I2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    display: flex;
    gap: 4px;
    align-items: center;
    height: 48px;
    background: var(--panel-bg);
    color: var(--text-primary);
    padding: 4px 8px;
    border-radius: 8px;
    position: relative;
    z-index: 10;
    box-shadow: var(--shadow-sm);
  `;
  const e = document.createElement("button");
  e.innerHTML = lt.play, e.style.cssText = `
    width: 32px;
    height: 32px;
    padding: 0;
    border: none;
    border-radius: 8px;
    background: var(--accent-strong);
    color: var(--on-accent);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
    position: relative;
  `, e.classList.add("wr-focusable");
  const s = async (h, u = 2e3, d = 50) => {
    const f = Date.now();
    for (; !h() && !(Date.now() - f > u); )
      await new Promise((p) => setTimeout(p, d));
  }, i = A2({
    playBtn: e,
    audioPlayer: n.audioPlayer,
    prePlay: async () => {
      try {
        await Rg();
      } catch {
      }
      await s(() => !!n.audioPlayer?.isInitialized?.());
    },
    postPlay: () => n.updateSeekBar?.()
  });
  C2(e), i(), n.updatePlayButton = i;
  const r = (h) => {
    e.disabled = !h, e.style.opacity = h ? "1" : "0.6", e.style.cursor = h ? "pointer" : "default";
  }, o = () => {
    try {
      return !!n.audioPlayer?.isInitialized?.();
    } catch {
      return !1;
    }
  };
  r(o());
  let a = null;
  o() || (a = window.setInterval(() => {
    o() && (r(!0), i(), a && (clearInterval(a), a = null));
  }, 100));
  const l = js(lt.restart, () => {
    n.audioPlayer?.seek(0), n.audioPlayer?.getState().isPlaying || n.audioPlayer?.play(), i();
  });
  Wo(l);
  const c = js(lt.repeat, () => {
  });
  return E2(c, n.audioPlayer), Wo(c), t.appendChild(l), t.appendChild(e), t.appendChild(c), t;
}
function yf(n) {
  const t = n.replace("#", "");
  if (t.length !== 6) return !1;
  const e = parseInt(t.substring(0, 2), 16) / 255, s = parseInt(t.substring(2, 4), 16) / 255, i = parseInt(t.substring(4, 6), 16) / 255, r = [e, s, i].map(
    (a) => a <= 0.03928 ? a / 12.92 : Math.pow((a + 0.055) / 1.055, 2.4)
  );
  return 0.2126 * r[0] + 0.7152 * r[1] + 0.0722 * r[2] > 0.5;
}
function F2(n) {
  const { audioPlayer: t, pianoRoll: e } = n, s = document.createElement("div");
  s.style.cssText = `
    display: flex;
    gap: 6px;
    align-items: center;
    height: 48px;
    background: var(--panel-bg);
    padding: 4px 12px;
    border-radius: 8px;
    box-shadow: var(--shadow-sm);
  `;
  let i = null, r = null, o = !1;
  function a(m, y) {
    return m !== null && y !== null && y > m;
  }
  const l = (m, y, x = !1) => {
    const v = document.createElement("button");
    return v.textContent = m, v.onclick = y, v.style.cssText = `
      width: 32px;
      height: 32px;
      padding: 0;
      border: none;
      border-radius: 8px;
      background: ${x ? "rgba(37, 99, 235, 0.12)" : "transparent"};
      color: ${x ? "var(--accent)" : "var(--text-muted)"};
      cursor: pointer;
      font-size: 13px;
      font-weight: 600;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.15s ease;
    `, v.classList.add("wr-focusable"), Wo(v), x && (v.dataset.active = "true"), v;
  }, c = document.createElement("button");
  c.innerHTML = lt.loop_start, c.title = "Toggle A-B Loop Mode", c.style.cssText = `
    width: 32px;
    height: 32px;
    padding: 0;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s ease;
  `, c.classList.add("wr-focusable");
  const h = () => {
    const m = a(i, r);
    c.disabled = !m, c.setAttribute("aria-disabled", String(!m)), m ? (c.style.opacity = "1", c.style.cursor = "pointer") : (c.style.opacity = "0.5", c.style.cursor = "not-allowed");
  }, u = () => {
    o ? (c.dataset.active = "true", c.style.background = "rgba(37, 99, 235, 0.12)", c.style.color = "var(--accent)", c.setAttribute("aria-pressed", "true")) : (delete c.dataset.active, c.style.background = "transparent", c.style.color = "var(--text-muted)", c.setAttribute("aria-pressed", "false"));
  };
  Wo(c), c.onclick = () => {
    if (a(i, r)) {
      if (o = !o, u(), o) {
        if (i !== null || r !== null) {
          const m = t?.getState();
          t?.setLoopPoints(i, r, !1), i !== null && m && !m.isPlaying && t?.play();
        }
      } else
        t?.setLoopPoints(null, null, !0);
      g();
    }
  };
  const d = l("A", () => {
    const m = t?.getState();
    m && (i = m.currentTime, r !== null && i !== null && i > r && ([i, r] = [r, i]), d.dataset.active = "true", d.setAttribute("aria-pressed", "true"), d.style.background = Wn, d.style.color = yf(Wn) ? "black" : "white", d.style.fontWeight = "800", d.style.border = "none", r === null && (f.dataset.active = "", f.setAttribute("aria-pressed", "false"), f.style.background = "transparent", f.style.color = "var(--text-muted)", f.style.border = `2px solid ${mn}`), h(), g());
  });
  d.style.border = `2px solid ${Wn}`;
  const f = l("B", () => {
    const m = t?.getState();
    m && (r = m.currentTime, i !== null && r !== null && i > r && ([i, r] = [r, i]), f.dataset.active = "true", f.setAttribute("aria-pressed", "true"), f.style.background = mn, f.style.color = yf(mn) ? "black" : "white", f.style.fontWeight = "800", f.style.border = "none", h(), g());
  });
  f.style.border = `2px solid ${mn}`;
  const p = l("✕", () => {
    if (i = null, r = null, d.dataset.active = "", f.dataset.active = "", d.setAttribute("aria-pressed", "false"), f.setAttribute("aria-pressed", "false"), d.style.background = "transparent", d.style.color = "var(--text-muted)", d.style.border = `2px solid ${Wn}`, f.style.background = "transparent", f.style.color = "var(--text-muted)", f.style.border = `2px solid ${mn}`, o) {
      o = !1, u();
      try {
        t?.toggleRepeat?.(!1);
      } catch {
      }
    }
    t?.setLoopPoints(null, null, !0), e?.setLoopWindow?.(null, null);
    const m = t?.getState();
    m?.isPlaying && t?.seek(m.currentTime, !0), h(), g();
  });
  p.style.fontSize = "16px", p.title = "Clear A-B Loop";
  const g = () => {
    const m = t?.getState();
    if (!m) return;
    const x = (m.playbackRate ?? 100) / 100, v = m.duration || 0;
    let _ = 0;
    try {
      const M = (globalThis._waveRollAudio?.getFiles?.() || []).map((A) => A.audioBuffer?.duration || 0).filter((A) => A > 0);
      _ = M.length > 0 ? Math.max(...M) : 0;
    } catch {
    }
    const b = Math.max(v, _), w = x > 0 ? b > 0 ? b / x : 0 : b;
    if (w <= 0) return;
    const S = {
      a: null,
      b: null
    };
    if (i !== null) {
      let k = i, C = r;
      C !== null && k > C && ([k, C] = [C, k]);
      const M = Math.min(Math.max(0, k), w), A = C !== null ? Math.min(Math.max(0, C), w) : null;
      S.a = M / w * 100, S.b = A !== null ? A / w * 100 : null, e?.setLoopWindow?.(M, A);
    } else if (r !== null) {
      const k = Math.min(Math.max(0, r), w);
      S.b = k / w * 100, e?.setLoopWindow?.(null, k);
    } else
      e?.setLoopWindow?.(null, null);
    const T = S.a === null && S.b === null ? null : { prev: S.a, next: S.b };
    s.dispatchEvent(
      new CustomEvent("wr-loop-update", {
        detail: { loopWindow: T },
        bubbles: !0,
        composed: !0
      })
    );
  };
  return u(), s.appendChild(c), s.appendChild(d), s.appendChild(f), s.appendChild(p), h(), setTimeout(() => {
    h(), g();
  }, 100), { element: s, updateSeekBar: g };
}
function R2(n) {
  if (!n.audioPlayer || !n.pianoRoll)
    throw new Error("Audio player and piano roll are required");
  const { element: t } = F2({
    audioPlayer: n.audioPlayer,
    pianoRoll: n.pianoRoll
  });
  return t;
}
function D2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 48px;
    background: var(--panel-bg);
    padding: 4px 8px;
    border-radius: 8px;
    box-shadow: var(--shadow-sm);
  `;
  const e = document.createElement("button");
  e.innerHTML = lt.volume, e.style.cssText = `
    background: transparent;
    border: 1px solid var(--ui-border);
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
    color: var(--text-muted);
  `, e.classList.add("wr-focusable"), e.setAttribute("aria-label", "Master volume: 100%"), e.title = "Master Volume", e.addEventListener("mouseenter", () => {
    e.style.transform = "translateY(-1px)", e.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)";
  }), e.addEventListener("mouseleave", () => {
    e.style.transform = "translateY(0)", e.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.05)";
  }), e.addEventListener("mousedown", () => {
    e.style.transform = "translateY(0) scale(0.96)";
  }), e.addEventListener("mouseup", () => {
    e.style.transform = "translateY(-1px) scale(1)";
  });
  const s = document.createElement("div");
  s.style.cssText = `
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 4px;
    background: var(--surface);
    border: 1px solid var(--ui-border);
    border-radius: 8px;
    padding: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    z-index: 9999;
    width: 50px;
    height: 160px;
  `;
  const i = document.createElement("div");
  i.textContent = "Master", i.style.cssText = `
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 4px;
    user-select: none;
  `;
  const r = document.createElement("span");
  r.textContent = "100%", r.style.cssText = `
    font-size: 10px;
    color: var(--text-muted);
    font-weight: 600;
    user-select: none;
    margin-bottom: 4px;
  `;
  const o = document.createElement("div");
  o.style.cssText = `
    width: 24px;
    height: 80px;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  `;
  const a = document.createElement("input");
  a.type = "range", a.min = "0", a.max = "100", a.value = "100", a.setAttribute("aria-label", "Master volume slider"), a.setAttribute("aria-orientation", "vertical"), a.style.cssText = `
    width: 80px;
    height: 4px;
    transform: rotate(-90deg);
    transform-origin: center;
    position: absolute;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    background: var(--ui-border);
    outline: none;
    border-radius: 2px;
  `;
  const l = `master-volume-slider-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  a.className = l;
  const c = document.createElement("style");
  c.textContent = `
    .${l}::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 12px;
      height: 12px;
      background: #0d6efd;
      cursor: pointer;
      border-radius: 50%;
      border: 2px solid white;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    }
    .${l}::-moz-range-thumb {
      width: 12px;
      height: 12px;
      background: #0d6efd;
      cursor: pointer;
      border-radius: 50%;
      border: 2px solid white;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    }
  `, document.head.appendChild(c), o.appendChild(a), s.appendChild(i), s.appendChild(r), s.appendChild(o), t.appendChild(e), t.appendChild(s);
  let h = 1, u = 1, d = null;
  function f(_, b) {
    try {
      window.dispatchEvent(
        new CustomEvent("wr-master-mirror", { detail: { mode: _, volume: b } })
      );
    } catch {
    }
  }
  const p = () => {
    const _ = h * 100;
    a.style.background = `linear-gradient(to right, var(--accent) 0%, var(--accent) ${_}%, var(--ui-border) ${_}%, var(--ui-border) 100%)`;
  }, g = (_) => {
    h = Math.max(0, Math.min(1, _));
    try {
      const b = n.audioPlayer;
      b && typeof b.masterVolume == "number" ? b.masterVolume = h : n.audioPlayer?.setVolume(h);
    } catch {
      n.audioPlayer?.setVolume(h);
    }
    a.value = String(h * 100), r.textContent = `${Math.round(h * 100)}%`, e.innerHTML = h === 0 ? lt.mute : lt.volume, e.style.color = h > 0 ? "var(--text-muted)" : "rgba(71,85,105,0.5)", e.setAttribute(
      "aria-label",
      `Master volume: ${Math.round(h * 100)}%`
    ), p(), h > 0 && (u = h), n.silenceDetector?.setMasterVolume?.(h), h === 0 && f("mirror-mute");
  }, m = () => {
    d !== null && (clearTimeout(d), d = null), s.style.display = "flex";
  }, y = () => {
    s.style.display = "none";
  }, x = () => {
    d !== null && clearTimeout(d), d = window.setTimeout(() => {
      y();
    }, 300);
  };
  e.addEventListener("mouseenter", m), e.addEventListener("focus", m), s.addEventListener("mouseenter", () => {
    d !== null && (clearTimeout(d), d = null);
  }), s.addEventListener("mouseleave", x), t.addEventListener("mouseleave", x), a.addEventListener("input", () => {
    g(parseFloat(a.value) / 100);
  });
  try {
    const _ = n.audioPlayer;
    if (_ && typeof _.masterVolume == "number") {
      const b = _.masterVolume;
      b > 0 && (u = b), h = b, g(b);
    }
  } catch {
  }
  p();
  try {
    const _ = (S) => {
      e.innerHTML = S ? lt.mute : lt.volume, e.style.color = S ? "rgba(71,85,105,0.5)" : "var(--text-muted)";
    }, b = () => h === 0, w = () => {
      try {
        const S = n.midiManager?.getState?.()?.files || [], k = globalThis._waveRollAudio?.getFiles?.() || [], C = S.length > 0 && S.every((A) => A?.isMuted === !0), M = k.length > 0 && k.every((A) => A?.isMuted === !0);
        return C && M;
      } catch {
        return !1;
      }
    };
    _(b() || w()), window.addEventListener("wr-silence-changed", () => {
      const S = w();
      _(b() || S), S && h > 0 && (u = h, g(0));
    });
  } catch {
  }
  e.addEventListener("click", () => {
    if (h > 0)
      u = h, g(0), f("mirror-mute");
    else {
      const _ = u > 0 ? u : 1;
      g(_), f("mirror-restore");
    }
  });
  let v = null;
  return window.addEventListener("wr-master-mirror", (_) => {
    const b = _.detail;
    if (!(!b || !b.mode)) {
      if (b.mode === "mirror-mute") {
        const w = {}, S = Array.from(
          document.querySelectorAll('[data-role="file-volume"][data-file-id]')
        );
        for (const C of S) {
          const M = C?.getAttribute?.("data-file-id"), A = C?.__controlInstance;
          if (!M || !A?.getLastNonZeroVolume) continue;
          const I = A.getLastNonZeroVolume(), F = typeof I == "number" ? Math.max(0, Math.min(1, I)) : 1;
          w[M] = { volume: F };
        }
        const T = {}, k = Array.from(
          document.querySelectorAll('[data-role="wav-volume"][data-file-id]')
        );
        for (const C of k) {
          const M = C?.getAttribute?.("data-file-id"), A = C?.__controlInstance;
          if (!M || !A?.getLastNonZeroVolume) continue;
          const I = A.getLastNonZeroVolume(), F = typeof I == "number" ? Math.max(0, Math.min(1, I)) : 1;
          T[M] = { volume: F };
        }
        v = { midi: w, wav: T };
      } else if (b.mode === "mirror-restore") {
        if (!v) return;
        const w = Array.from(
          document.querySelectorAll('[data-role="file-volume"][data-file-id]')
        );
        for (const T of w) {
          const k = T?.getAttribute?.("data-file-id"), C = T?.__controlInstance, M = k && v.midi[k]?.volume;
          C?.setVolume && typeof M == "number" && C.setVolume(M);
        }
        const S = Array.from(
          document.querySelectorAll('[data-role="wav-volume"][data-file-id]')
        );
        for (const T of S) {
          const k = T?.getAttribute?.("data-file-id"), C = T?.__controlInstance, M = k && v.wav[k]?.volume;
          C?.setVolume && typeof M == "number" && C.setVolume(M);
        }
      }
    }
  }), t.addEventListener("keydown", (_) => {
    _.key === "Escape" ? (y(), e.focus()) : _.key === "ArrowUp" || _.key === "ArrowRight" ? (_.preventDefault(), g(Math.min(1, h + 0.05))) : (_.key === "ArrowDown" || _.key === "ArrowLeft") && (_.preventDefault(), g(Math.max(0, h - 0.05)));
  }), t;
}
const O2 = 120, xf = 20, _f = 300;
function N2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 48px;
    background: var(--panel-bg);
    padding: 4px 8px;
    border-radius: 8px;
    box-shadow: var(--shadow-sm);
  `;
  const e = () => {
    const w = n.audioPlayer?.getState(), S = w?.originalTempo ?? O2, T = w?.tempo ?? S;
    return { originalTempo: S, currentTempo: T };
  }, { currentTempo: s } = e(), i = document.createElement("button");
  i.textContent = `${Math.round(s)} BPM`, i.title = "Playback Tempo", i.style.cssText = `
    background: transparent;
    border: 1px solid var(--ui-border);
    padding: 0 10px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    border-radius: 8px;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 600;
    min-width: 70px;
  `, i.classList.add("wr-focusable"), i.setAttribute(
    "aria-label",
    `Playback tempo: ${Math.round(s)} BPM`
  ), i.addEventListener("mouseenter", () => {
    i.style.transform = "translateY(-1px)", i.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)";
  }), i.addEventListener("mouseleave", () => {
    i.style.transform = "translateY(0)", i.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.05)";
  }), i.addEventListener("mousedown", () => {
    i.style.transform = "translateY(0) scale(0.96)";
  }), i.addEventListener("mouseup", () => {
    i.style.transform = "translateY(-1px) scale(1)";
  });
  const r = document.createElement("div");
  r.style.cssText = `
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 4px;
    background: var(--surface);
    border: 1px solid var(--ui-border);
    border-radius: 8px;
    padding: 10px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    z-index: 9999;
    min-width: 100px;
  `;
  const o = document.createElement("div");
  o.textContent = "Tempo", o.style.cssText = `
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    user-select: none;
  `;
  const a = document.createElement("div");
  a.style.cssText = `
    display: flex;
    align-items: center;
    gap: 4px;
  `;
  const l = document.createElement("button");
  l.textContent = "−", l.title = "Decrease tempo", l.style.cssText = `
    width: 24px;
    height: 24px;
    border: 1px solid var(--ui-border);
    border-radius: 4px;
    background: var(--surface);
    color: var(--text-muted);
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.1s ease;
  `, l.addEventListener("mouseenter", () => {
    l.style.background = "var(--surface-alt)";
  }), l.addEventListener("mouseleave", () => {
    l.style.background = "var(--surface)";
  });
  const c = document.createElement("input");
  c.type = "number", c.min = String(xf), c.max = String(_f), c.step = "1", c.value = String(Math.round(s)), c.style.cssText = `
    width: 50px;
    padding: 4px 6px;
    border: 1px solid var(--ui-border);
    border-radius: 4px;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent);
    background: var(--surface);
    text-align: center;
    outline: none;
  `, c.classList.add("wr-focusable");
  const h = document.createElement("button");
  h.textContent = "+", h.title = "Increase tempo", h.style.cssText = `
    width: 24px;
    height: 24px;
    border: 1px solid var(--ui-border);
    border-radius: 4px;
    background: var(--surface);
    color: var(--text-muted);
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.1s ease;
  `, h.addEventListener("mouseenter", () => {
    h.style.background = "var(--surface-alt)";
  }), h.addEventListener("mouseleave", () => {
    h.style.background = "var(--surface)";
  });
  const u = document.createElement("span");
  u.textContent = "BPM", u.style.cssText = `
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
    user-select: none;
  `, a.appendChild(l), a.appendChild(c), a.appendChild(h), r.appendChild(o), r.appendChild(a), r.appendChild(u), t.appendChild(i), t.appendChild(r);
  let d = s, f = !1, p = null;
  const g = (w) => {
    const S = Math.max(
      xf,
      Math.min(_f, Math.round(w))
    );
    d = S, c.value = String(S), i.textContent = `${S} BPM`, i.setAttribute("aria-label", `Playback tempo: ${S} BPM`), n.audioPlayer?.setTempo(S);
    const T = n.audioPlayer?.getState();
    T && n.updateSeekBar && n.updateSeekBar({
      currentTime: T.currentTime,
      duration: T.duration
    });
  }, m = () => {
    p !== null && (clearTimeout(p), p = null), r.style.display = "flex", f = !0;
  }, y = () => {
    r.style.display = "none", f = !1;
  }, x = () => {
    p !== null && clearTimeout(p), p = window.setTimeout(() => {
      y();
    }, 300);
  };
  i.addEventListener("mouseenter", m), i.addEventListener("focus", m), r.addEventListener("mouseenter", () => {
    p !== null && (clearTimeout(p), p = null);
  }), r.addEventListener("mouseleave", x), t.addEventListener("mouseleave", x), c.addEventListener("focus", () => {
    c.style.borderColor = "var(--accent)", c.style.boxShadow = "0 0 0 2px rgba(37, 99, 235, 0.1)";
  }), c.addEventListener("blur", () => {
    c.style.borderColor = "var(--ui-border)", c.style.boxShadow = "none";
    const w = parseFloat(c.value);
    isNaN(w) || g(w);
  }), c.addEventListener("change", () => {
    const w = parseFloat(c.value);
    isNaN(w) || g(w);
  }), c.addEventListener("keydown", (w) => {
    if (w.key === "Enter") {
      const S = parseFloat(c.value);
      isNaN(S) || g(S), c.blur();
    } else w.key === "Escape" && (y(), i.focus());
  }), l.addEventListener("click", () => {
    g(d - 5);
  }), h.addEventListener("click", () => {
    g(d + 5);
  }), i.addEventListener("click", () => {
    f ? y() : (m(), c.focus(), c.select());
  });
  const v = () => {
    const { currentTempo: w } = e();
    d = w, i.textContent = `${Math.round(w)} BPM`, i.setAttribute(
      "aria-label",
      `Playback tempo: ${Math.round(w)} BPM`
    ), document.activeElement !== c && (c.value = String(Math.round(w)));
  }, _ = () => v();
  document.addEventListener("wr-force-ui-refresh", _);
  const b = new MutationObserver((w) => {
    for (const S of w)
      for (const T of S.removedNodes)
        if (T === t || T instanceof Element && T.contains(t)) {
          document.removeEventListener("wr-force-ui-refresh", _), b.disconnect();
          return;
        }
  });
  return requestAnimationFrame(() => {
    t.parentElement && b.observe(t.parentElement, {
      childList: !0,
      subtree: !0
    });
  }), t.addEventListener("keydown", (w) => {
    w.key === "Escape" ? (y(), i.focus()) : w.key === "ArrowUp" ? (w.preventDefault(), g(d + 1)) : w.key === "ArrowDown" && (w.preventDefault(), g(d - 1));
  }), t;
}
function L2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
      display: flex;
      align-items: center;
      gap: 6px;
      height: 48px;
      background: var(--panel-bg);
      padding: 4px 8px;
      border-radius: 8px;
      box-shadow: var(--shadow-sm);
    `;
  const e = document.createElement("input");
  e.type = "number", e.min = "0.1", e.max = "10", e.step = "0.1";
  const s = n.pianoRoll?.getState?.().zoomX ?? 1;
  e.value = s.toFixed(1), e.style.cssText = `
      width: 56px;
      padding: 4px 6px;
      border: 1px solid var(--ui-border);
      border-radius: 6px;
      font-size: 12px;
      text-align: center;
      color: var(--accent);
      background: var(--surface);
    `, e.classList.add("wr-focusable");
  const i = (l) => hs(l, 0.1, 10), r = () => {
    const l = parseFloat(e.value);
    if (isNaN(l)) return;
    const c = i(l), h = n.pianoRoll?.getState?.().zoomX ?? 1, u = c / h;
    n.pianoRoll?.zoomX?.(u), e.value = c.toFixed(1);
  };
  e.addEventListener("change", r), e.addEventListener("blur", r), e.addEventListener("keydown", (l) => {
    l.key === "Enter" && (r(), e.blur());
  }), e.addEventListener(
    "wheel",
    (l) => {
      l.preventDefault();
      const c = l.deltaY < 0 ? 0.1 : -0.1, h = parseFloat(e.value) || s;
      e.value = (h + c).toFixed(1), r();
    },
    { passive: !1 }
  );
  const o = document.createElement("span");
  o.textContent = "x", o.style.cssText = `
      font-size: 12px;
      font-weight: 600;
      color: var(--text-muted);
    `;
  const a = js(lt.zoom_reset, () => {
    n.pianoRoll?.resetView?.(), e.value = "1.0";
  });
  return a.title = "Reset Zoom", t.appendChild(e), t.appendChild(o), t.appendChild(a), n.zoomInput = e, t;
}
function V2({
  loopPoints: n,
  loopRegion: t,
  markerA: e,
  markerB: s
}) {
  !t || !e || !s || (n && (n.a !== null || n.b !== null) ? (n.a !== null ? (e.style.display = "block", e.style.left = `${n.a}%`) : e.style.display = "none", n.b !== null ? (s.style.display = "block", s.style.left = `${n.b}%`) : s.style.display = "none", n.a !== null && n.b !== null ? (t.style.display = "block", t.style.left = `${n.a}%`, t.style.width = `${n.b - n.a}%`) : t.style.display = "none") : (t.style.display = "none", e.style.display = "none", s.style.display = "none"));
}
const vf = "wr-marker-css";
function B2() {
  if (document.getElementById(vf)) return;
  const n = document.createElement("style");
  n.id = vf, n.textContent = `
    .wr-marker {
      position: absolute;
      top: -24px;
      transform: translateX(-50%);
      font-family: monospace;
      font-size: 11px;
      font-weight: 600;
      padding: 2px 4px;
      border-radius: 4px 4px 0 0;
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      pointer-events: none;
      z-index: 3;
      width: auto;
      min-width: 16px;
    }
  `, document.head.appendChild(n);
}
function bf(n, t, e, s = 30) {
  B2();
  const i = document.createElement("div");
  i.id = e, i.className = "wr-marker", i.style.position = "absolute", i.style.top = "-24px", i.style.left = "0", i.style.transform = "translateX(-50%)", i.style.fontFamily = "monospace", i.style.fontSize = "11px", i.style.fontWeight = "600", i.style.padding = "2px 4px", i.style.borderRadius = "4px 4px 0 0", i.style.pointerEvents = "none", i.style.zIndex = "3", i.style.width = "auto", i.style.minWidth = "16px", i.style.maxWidth = "30px", i.style.textAlign = "center", i.style.boxSizing = "border-box", i.style.background = t;
  const r = (() => {
    const l = t.replace("#", ""), c = parseInt(l.substring(0, 2), 16) / 255, h = parseInt(l.substring(2, 4), 16) / 255, u = parseInt(l.substring(4, 6), 16) / 255, d = [c, h, u].map(
      (p) => p <= 0.03928 ? p / 12.92 : Math.pow((p + 0.055) / 1.055, 2.4)
    );
    return 0.2126 * d[0] + 0.7152 * d[1] + 0.0722 * d[2] > 0.5 ? "#000000" : "#ffffff";
  })();
  i.style.display = "none";
  const o = document.createElement("span");
  o.textContent = n, o.style.color = r, o.style.display = "block", i.appendChild(o);
  const a = document.createElement("div");
  return a.className = "wr-marker-stem", a.style.cssText = `
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    width: 2px;
    height: ${s}px;
    background: ${t};
    pointer-events: none;
  `, i.appendChild(a), i;
}
function z2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
      display: flex;
      align-items: center;
      gap: 12px;
      background: var(--surface);
      color: var(--text-primary);
      padding: 14px 14px 10px 14px;
      border-radius: 8px;
      margin-top: 4px;
      box-shadow: var(--shadow-sm);
    `;
  const e = document.createElement("span");
  e.style.cssText = `
      font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
      font-size: 12px;
      font-weight: 500;
      color: var(--text-muted);
      min-width: 45px;
      text-align: right;
    `, e.textContent = "00:00";
  const s = document.createElement("div");
  s.style.cssText = `
      flex: 1;
      position: relative;
      height: 6px;
      background: var(--track-bg);
      border-radius: 8px;
      cursor: pointer;
    `;
  const i = document.createElement("div");
  i.style.cssText = `
      position: absolute;
      top: 0;
      height: 100%;
      background: repeating-linear-gradient(
        -45deg,
        var(--loop-stripe-a) 0px,
        var(--loop-stripe-a) 4px,
        var(--loop-stripe-b) 4px,
        var(--loop-stripe-b) 8px
      );
      border-top: 2px solid var(--loop-stripe-border);
      border-bottom: 2px solid var(--loop-stripe-border);
      border-left: 2px solid var(--loop-stripe-border);
      border-right: 2px solid var(--loop-stripe-border);
      display: none;
      pointer-events: none;
      z-index: 1;
      border-radius: 8px;
    `, s.appendChild(i);
  const r = "wr-marker-css";
  if (!document.getElementById(r)) {
    const w = document.createElement("style");
    w.id = r, w.textContent = `
      .wr-marker {
        position: absolute;
        top: -24px;
        transform: translateX(-50%);
        font-family: monospace;
        font-size: 11px;
        font-weight: 600;
        padding: 2px 4px;
        border-radius: 4px 4px 0 0;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        pointer-events: none;
        z-index: 3;
      }
      /* stem is now created as a real DOM element (.wr-marker-stem) in marker.ts */
    `, document.head.appendChild(w);
  }
  const o = bf("A", Wn, "wr-seekbar-marker-a", 14), a = bf("B", mn, "wr-seekbar-marker-b", 14);
  o.style.pointerEvents = "auto", a.style.pointerEvents = "auto";
  const l = (w, S) => (T) => {
    T.stopPropagation(), (() => {
      const k = n.loopPoints, C = w === "A" ? k?.a : k?.b;
      if (typeof C == "number") return C;
      const M = (S.style.left || "0%").replace("%", ""), A = Number(M);
      return Number.isFinite(A) ? A : 0;
    })();
  };
  o.addEventListener("click", l("A", o)), a.addEventListener("click", l("B", a));
  const c = document.createElement("div");
  c.style.cssText = `
      height: 100%;
      background: linear-gradient(90deg, var(--accent-strong), var(--accent));
      border-radius: 8px;
      width: 0%;
    `;
  const h = document.createElement("div");
  h.style.cssText = `
      position: absolute;
      top: 50%;
      /* Center the handle both horizontally and vertically so the midpoint
         aligns with the progress bar edge. */
      transform: translate(-50%, -50%);
      width: 16px;
      height: 16px;
      background: var(--accent-strong);
      border-radius: 50%;
      cursor: pointer;
      left: 0%;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
      z-index: 4;
    `;
  const u = document.createElement("span");
  u.style.cssText = `
      font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
      font-size: 12px;
      font-weight: 500;
      color: var(--text-muted);
      min-width: 45px;
    `, u.textContent = "00:00", s.appendChild(c), s.appendChild(i), s.appendChild(h), s.appendChild(o), s.appendChild(a), t.appendChild(e), t.appendChild(s), t.appendChild(u);
  let d = 0, f = 0;
  const p = (w) => {
    const S = w ?? n.audioPlayer?.getState();
    if (new Error().stack?.split(`
`)[2]?.trim(), Math.abs((S?.currentTime || 0) - d) > 0.1 || S?.currentTime, !S)
      return;
    if (S.currentTime === 0 && d > 0.1 && (!w && n.audioPlayer?.getState()?.isPlaying) && (S.currentTime = d), S.currentTime > 0 && (d = S.currentTime), e.textContent = n.formatTime(S.currentTime), w)
      f = Math.max(0, w.duration || 0), u.textContent = n.formatTime(f);
    else {
      const F = n.audioPlayer?.getState().playbackRate ?? 100, E = (S.duration || 0) * (100 / F);
      f = E, u.textContent = n.formatTime(E);
    }
    if ((w ? w.duration : S.duration) === 0) {
      c.style.width = "0%", h.style.left = "0%";
      return;
    }
    const T = Math.max(w ? w.duration : f || S.duration, 1e-6), k = Math.min(Math.max(S.currentTime, 0), T), C = Math.min(Math.max(k / T * 100, 0), 100);
    c.style.width = `${C}%`;
    const M = Math.max(C, 0);
    h.style.left = `${Math.min(M, 100)}%`;
    const I = (w ? w.duration : f || S.duration || 0) > 0;
    V2({
      loopPoints: I ? n.loopPoints ?? null : null,
      loopRegion: i,
      markerA: o,
      markerB: a
    });
  };
  n.updateSeekBar = p, p();
  let g = !1;
  const m = (w) => {
    if (g) {
      g = !1;
      return;
    }
    const S = s.getBoundingClientRect(), T = (w.clientX - S.left) / S.width, k = n.audioPlayer?.getState(), C = f || k?.duration || 0;
    if (!k || C === 0)
      return;
    const M = hs(C * T, 0, C);
    n.audioPlayer?.seek(M, !0), p();
  };
  s.addEventListener("click", m);
  let y = !1, x = null;
  const v = (w) => {
    if (!y) return;
    g = !0;
    const S = s.getBoundingClientRect(), T = hs((w.clientX - S.left) / S.width, 0, 1), k = n.audioPlayer?.getState(), C = f || k?.duration || 0, M = C * T;
    x = M, p({ currentTime: M, duration: C });
  }, _ = () => {
    y && (y = !1, window.removeEventListener("pointermove", v), window.removeEventListener("pointerup", _), x !== null && (n.audioPlayer?.seek(x, !0), x = null));
  }, b = (w) => {
    y = !0, v(w), window.addEventListener("pointermove", v), window.addEventListener("pointerup", _, { once: !0 });
  };
  return h.addEventListener("pointerdown", b), s.addEventListener("pointerdown", b), t;
}
function Dg(n, t) {
  const e = parseFloat(t.toString());
  isNaN(e) || !Number.isFinite(e) || e <= 0 || !n || n?.(e);
}
function q2(n) {
  const t = document.createElement("div");
  t.style.cssText = "display:flex;align-items:center;gap:6px;font-size:12px;";
  const e = document.createElement("span");
  e.textContent = "Minor step:", e.style.cssText = "font-weight:600;";
  const s = document.createElement("input");
  s.type = "number", s.min = "0.05", s.step = "0.05", s.value = n.pianoRoll?.getMinorTimeStep?.()?.toString() ?? n.minorTimeStep.toString(), s.style.cssText = "width:64px;padding:4px 6px;border:1px solid var(--ui-border);border-radius:6px;text-align:center;background:var(--surface);color:var(--text-primary);";
  const i = document.createElement("span");
  i.textContent = "s", i.style.cssText = e.style.cssText;
  const r = () => Dg(n.pianoRoll?.setMinorTimeStep, s.value);
  return s.addEventListener("change", r), s.addEventListener("blur", r), t.append(e, s, i), t;
}
function U2(n) {
  const t = document.createElement("div");
  t.style.cssText = "display:flex;align-items:center;gap:6px;";
  const e = document.createElement("span");
  e.textContent = "Grid step:", e.style.cssText = "font-size:12px;font-weight:600;";
  const s = document.createElement("input");
  s.type = "number", s.min = "0.1", s.step = "0.1";
  const i = n.pianoRoll?.getTimeStep?.() ?? 1;
  s.value = i.toString(), s.style.cssText = "width:64px;padding:4px 6px;border:1px solid var(--ui-border);border-radius:6px;font-size:12px;text-align:center;background:var(--surface);color:var(--text-primary);";
  const r = document.createElement("span");
  r.textContent = "s", r.style.cssText = e.style.cssText;
  const o = () => Dg(n.pianoRoll?.setTimeStep, parseFloat(s.value));
  return s.addEventListener("change", o), s.addEventListener("blur", o), t.appendChild(e), t.appendChild(s), t.appendChild(r), t;
}
function Og(n, t) {
  const e = t?.withWrapper ?? !1, s = document.createElement("div"), i = `display:flex;
    align-items:center;
    gap:8px;
    font-size:12px;
    max-width: 100%;
    overflow: hidden;`, r = e ? `height: 48px;
    background: var(--panel-bg);
    padding: 4px 8px;
    border-radius: 8px;
    box-shadow: var(--shadow-sm);` : "";
  s.style.cssText = i + r;
  const o = document.createElement("span");
  o.textContent = "Show notes:", o.style.cssText = "font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;";
  const a = document.createElement("select");
  a.style.cssText = "flex:1;min-width:0;padding:4px 6px;border:1px solid var(--ui-border);border-radius:6px;background:var(--surface);color:var(--text-primary);";
  const l = {
    file: "Show each file in its own color (no evaluation highlight).",
    // Legacy non-evaluation highlight modes (hidden in UI)
    "highlight-simple": "Basic overlap highlight: overlapping segments are slightly brightened.",
    "highlight-blend": "Additive blend: overlapping segments keep file colors and use additive blending.",
    "highlight-exclusive": "Exclusive emphasis: non-overlapping segments are emphasized; overlaps are muted/neutral.",
    // Evaluation presets (detailed tooltips)
    "eval-match-intersection-gray": "Matched overlap is emphasized. Overlapping segments are shown in neutral gray.",
    "eval-match-intersection-own": "Matched overlap is emphasized. Overlapping segments keep their file colors.",
    "eval-exclusive-intersection-gray": "Exclusive (non-overlapping) parts are emphasized. Overlaps are shown in neutral gray.",
    "eval-exclusive-intersection-own": "Exclusive (non-overlapping) parts are emphasized. Overlaps keep their file colors.",
    "eval-gt-missed-only-own": "Reference missed only: matched overlap is highlighted; missed (REF-only) segments are shown in gray.",
    "eval-gt-missed-only-gray": "Reference missed only: matched overlap is shown in gray; missed (REF-only) segments keep the reference color.",
    // Performance analysis modes
    "eval-tp-only-own": "Highlight True Positive (TP) segments, mute others",
    "eval-tp-only-gray": "Mute True Positive (TP) segments, keep others normal",
    "eval-fp-only-own": "Highlight False Positive (FP) segments, mute others",
    "eval-fp-only-gray": "Mute False Positive (FP) segments, keep others normal",
    "eval-fn-only-own": "Highlight False Negative (FN) segments, mute others",
    "eval-fn-only-gray": "Mute False Negative (FN) segments, keep others normal"
  }, c = {
    file: "File colors",
    // Legacy non-evaluation modes (hidden)
    "highlight-simple": "Overlap highlight (simple)",
    "highlight-blend": "Overlap blend (additive)",
    "highlight-exclusive": "Exclusive highlight",
    "eval-match-intersection-gray": "Match (overlap gray)",
    "eval-match-intersection-own": "Match (overlap own)",
    "eval-exclusive-intersection-gray": "Exclusive (overlap gray)",
    "eval-exclusive-intersection-own": "Exclusive (overlap own)",
    "eval-gt-missed-only-own": "Ref missed only (match highlight)",
    "eval-gt-missed-only-gray": "Ref missed only (match gray)",
    "eval-tp-only-own": "Highlight True Positive (TP)",
    "eval-tp-only-gray": "Mute True Positive (TP)",
    "eval-fp-only-own": "Highlight False Positive (FP)",
    "eval-fp-only-gray": "Mute False Positive (FP)",
    "eval-fn-only-own": "Highlight False Negative (FN)",
    "eval-fn-only-gray": "Mute False Negative (FN)"
  }, h = /* @__PURE__ */ new Set([
    "eval-match-intersection-own",
    "eval-match-intersection-gray",
    "eval-exclusive-intersection-own",
    "eval-exclusive-intersection-gray",
    "highlight-simple",
    "highlight-blend",
    "highlight-exclusive"
  ]);
  function u(x) {
    switch (x) {
      case "file":
        return "file";
      case "eval-match-intersection-own":
        return "eval-tp-only-own";
      case "eval-match-intersection-gray":
        return "eval-tp-only-gray";
      case "eval-exclusive-intersection-own":
        return "eval-fn-only-own";
      case "eval-exclusive-intersection-gray":
        return "eval-fn-only-gray";
      default:
        return x;
    }
  }
  function d(x) {
    return h.has(x) ? u(x) : x;
  }
  [
    { label: "Basic", items: ["file"] },
    {
      label: "Performance analysis",
      items: [
        "eval-tp-only-own",
        "eval-tp-only-gray",
        "eval-fp-only-own",
        "eval-fp-only-gray",
        "eval-fn-only-own",
        "eval-fn-only-gray"
      ]
    },
    {
      label: "Reference missed only",
      items: ["eval-gt-missed-only-own", "eval-gt-missed-only-gray"]
    }
  ].forEach((x) => {
    const v = document.createElement("optgroup");
    v.label = x.label, x.items.forEach((_) => {
      const b = document.createElement("option");
      b.value = _, b.textContent = c[_] ?? _, b.title = l[_] ?? "", v.appendChild(b);
    }), a.appendChild(v);
  }), a.value = d(
    n.stateManager.getState().visual.highlightMode
  ), a.title = l[a.value] ?? "", s.style.position = s.style.position || "relative";
  const p = document.createElement("div");
  p.style.cssText = "position:absolute;left:12px;right:12px;bottom:52px;z-index:50;padding:8px 10px;border:1px solid var(--ui-border);border-radius:8px;background:var(--surface);color:var(--text-primary);font-size:12px;box-shadow:var(--shadow-sm);display:none;", s.appendChild(p);
  let g = null;
  function m(x) {
    p.textContent = x, p.style.display = "block", g && (clearTimeout(g), g = null);
    const v = n.uiOptions?.highlightToast;
    (v?.position ?? "bottom") === "top" ? (p.style.bottom = "", p.style.top = "52px") : (p.style.top = "", p.style.bottom = "52px");
    const b = v?.style;
    b && Object.assign(p.style, b);
    const w = Math.max(800, Math.min(8e3, v?.durationMs ?? 2600));
    g = setTimeout(() => {
      p.style.display = "none", g = null;
    }, w);
  }
  function y(x) {
    if (x.startsWith("eval-")) {
      const v = n.stateManager.getState().evaluation, _ = n.midiManager.getState().files;
      (!v.refId || v.estIds.length === 0) && _.length >= 2 && n.stateManager.updateEvaluationState({
        refId: v.refId ?? _[0].id,
        estIds: v.estIds.length > 0 ? v.estIds : [_[1].id]
      });
    }
    n.stateManager.updateVisualState({ highlightMode: x }), a.value = x, a.title = l[x] ?? "", m(l[x] ?? "");
  }
  return a.addEventListener("change", () => {
    const x = a.value;
    y(x);
  }), a.addEventListener("touchstart", () => {
    const x = a.value;
    m(l[x] ?? "");
  }), a.addEventListener("focus", () => {
    const x = a.value;
    m(l[x] ?? "");
  }), s.append(o, a), s;
}
function G2(n) {
  const t = document.createElement("div");
  t.style.cssText = "display:flex;align-items:center;gap:6px;font-size:12px;";
  const e = document.createElement("span");
  e.textContent = "Min Offset Tolerance (s):", e.style.cssText = "font-weight:600;min-width:120px;";
  const s = document.createElement("input");
  s.type = "number", s.min = "0", s.step = "0.01", s.style.cssText = "flex:1;padding:4px 6px;border:1px solid var(--ui-border);border-radius:6px;background:var(--surface);color:var(--text-primary);";
  const i = n.stateManager.getState().visual;
  return s.value = String(i.minOffsetTolerance), s.addEventListener("change", () => {
    const r = parseFloat(s.value);
    !isNaN(r) && r >= 0 && n.stateManager.updateVisualState({
      minOffsetTolerance: r
    });
  }), n.stateManager.onStateChange(() => {
    const r = n.stateManager.getState().visual.minOffsetTolerance;
    parseFloat(s.value) !== r && (s.value = String(r));
  }), t.append(e, s), t;
}
function W2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    padding: 12px 0;
    border-top: 1px solid var(--ui-border);
    position: relative;
  `;
  const e = document.createElement("label");
  e.style.cssText = `
    display: flex;
    align-items: center;
    cursor: pointer;
    user-select: none;
  `;
  const s = document.createElement("input");
  s.type = "checkbox", s.style.cssText = `
    margin-right: 8px;
    cursor: pointer;
  `;
  const i = n.stateManager?.getState().visual.pedalElongate ?? !1;
  s.checked = i;
  const r = document.createElement("span");
  r.textContent = "Apply Sustain Pedal Elongation", r.style.cssText = `
    font-size: 14px;
    font-weight: 500;
    color: var(--text-primary);
  `;
  const o = document.createElement("div");
  o.style.cssText = `
    display: none;
    position: absolute;
    top: 12px;
    right: 0;
    font-size: 12px;
    color: var(--accent);
    font-style: italic;
  `, o.textContent = "Reprocessing files...";
  const a = document.createElement("div");
  return a.style.cssText = `
    margin-top: 8px;
    margin-left: 24px;
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.4;
  `, a.textContent = "When enabled, notes will be elongated based on sustain pedal (CC64) events in the MIDI file. Changing this setting will reprocess all loaded files.", s.addEventListener("change", async () => {
    const l = s.checked;
    n.stateManager?.updateVisualState({ pedalElongate: l }), o.style.display = "block", s.disabled = !0;
    try {
      if (n.midiManager) {
        const c = n.stateManager?.getState().visual.pedalThreshold ?? 64;
        await n.midiManager.reparseAllFiles(
          {
            applyPedalElongate: l,
            pedalThreshold: c
          },
          (h, u) => {
            o.textContent = `Reprocessing files... (${h}/${u})`;
          }
        );
      }
    } catch (c) {
      console.error("Failed to reprocess files:", c), s.checked = !l, n.stateManager?.updateVisualState({ pedalElongate: !l });
    } finally {
      o.style.display = "none", o.textContent = "Reprocessing files...", s.disabled = !1;
    }
  }), e.appendChild(s), e.appendChild(r), t.appendChild(e), t.appendChild(o), t.appendChild(a), t;
}
function $2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    padding: 12px 0;
  `;
  const e = document.createElement("div");
  e.style.cssText = `
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  `;
  const s = document.createElement("label");
  s.textContent = "Pedal Threshold", s.style.cssText = `
    font-size: 14px;
    font-weight: 500;
    color: var(--text-primary);
  `;
  const i = document.createElement("span");
  i.style.cssText = `
    font-size: 14px;
    color: var(--text-muted);
    min-width: 35px;
    text-align: right;
  `;
  const r = document.createElement("div");
  r.style.cssText = `
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: 24px;
  `;
  const o = document.createElement("input");
  o.type = "range", o.min = "0", o.max = "127", o.step = "1", o.style.cssText = `
    flex: 1;
    cursor: pointer;
  `;
  const a = n.stateManager?.getState().visual.pedalThreshold ?? 64;
  o.value = String(a), i.textContent = String(a);
  const l = document.createElement("span");
  l.textContent = "0", l.style.cssText = `
    font-size: 12px;
    color: var(--text-muted);
  `;
  const c = document.createElement("span");
  c.textContent = "127", c.style.cssText = `
    font-size: 12px;
    color: var(--text-muted);
  `;
  const h = document.createElement("div");
  h.style.cssText = `
    margin-top: 8px;
    margin-left: 24px;
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.4;
  `, h.textContent = "MIDI CC64 value threshold for sustain pedal activation. Standard value is 64. Lower values make the pedal more sensitive.";
  const u = document.createElement("div");
  u.style.cssText = `
    display: none;
    margin-top: 8px;
    margin-left: 24px;
    font-size: 12px;
    color: var(--accent);
    font-style: italic;
  `, u.textContent = "Reprocessing files...";
  let d = null;
  const f = async () => {
    const p = parseInt(o.value);
    i.textContent = String(p), n.stateManager?.updateVisualState({ pedalThreshold: p }), d !== null && clearTimeout(d), d = window.setTimeout(async () => {
      if (n.stateManager?.getState()?.visual.pedalElongate) {
        u.style.display = "block", o.disabled = !0;
        try {
          n.midiManager && await n.midiManager.reparseAllFiles(
            {
              applyPedalElongate: !0,
              pedalThreshold: p
            },
            (m, y) => {
              u.textContent = `Reprocessing files... (${m}/${y})`;
            }
          );
        } catch (m) {
          console.error("Failed to reprocess files:", m);
        } finally {
          u.style.display = "none", u.textContent = "Reprocessing files...", o.disabled = !1, d = null;
        }
      }
    }, 500);
  };
  return o.addEventListener("input", () => {
    i.textContent = o.value;
  }), o.addEventListener("change", f), e.appendChild(s), e.appendChild(i), r.appendChild(l), r.appendChild(o), r.appendChild(c), t.appendChild(e), t.appendChild(r), t.appendChild(h), t.appendChild(u), t;
}
const H2 = 120, wf = 20, Sf = 300;
function j2(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    padding: 12px 0;
    border-top: 1px solid var(--ui-border);
  `;
  const e = document.createElement("div");
  e.textContent = "MIDI Export", e.style.cssText = `
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 12px;
  `;
  const s = document.createElement("div");
  s.style.cssText = `
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
  `;
  const i = document.createElement("label");
  i.textContent = "Export tempo:", i.style.cssText = `
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
  `;
  const r = document.createElement("input");
  r.type = "number", r.min = String(wf), r.max = String(Sf), r.step = "1", r.style.cssText = `
    width: 64px;
    padding: 4px 6px;
    border: 1px solid var(--ui-border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--text-primary);
    font-size: 12px;
    font-weight: 600;
    text-align: center;
  `, r.classList.add("wr-focusable");
  const o = document.createElement("span");
  o.textContent = "BPM", o.style.cssText = `
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
  `;
  let l = Math.round((() => {
    const x = n.audioPlayer?.getState(), v = x?.originalTempo ?? H2, _ = x?.tempo ?? v;
    return { originalTempo: v, currentTempo: _ };
  })().currentTempo);
  r.value = String(l);
  const c = () => {
    const x = parseFloat(r.value);
    if (isNaN(x) || x <= 0) {
      r.value = String(l);
      return;
    }
    const v = Math.max(wf, Math.min(Sf, Math.round(x)));
    l = v, r.value = String(v);
  };
  r.addEventListener("blur", c), r.addEventListener("keydown", (x) => {
    x.key === "Enter" && (c(), r.blur());
  });
  const h = () => {
  };
  document.addEventListener("wr-force-ui-refresh", h), s.appendChild(i), s.appendChild(r), s.appendChild(o);
  let u = null;
  const d = n.midiManager.getState().files;
  if (!n.soloMode && d.length > 1) {
    const x = document.createElement("div");
    x.style.cssText = `
      display: flex;
      align-items: center;
      gap: 8px;
      margin-bottom: 12px;
    `;
    const v = document.createElement("label");
    v.textContent = "File:", v.style.cssText = `
      font-size: 13px;
      color: var(--text-secondary);
    `, u = document.createElement("select"), u.style.cssText = `
      flex: 1;
      padding: 6px 8px;
      border: 1px solid var(--ui-border);
      border-radius: 4px;
      background: var(--panel-bg);
      color: var(--text-primary);
      font-size: 13px;
      cursor: pointer;
    `, d.forEach((_, b) => {
      const w = document.createElement("option");
      w.value = _.id, w.textContent = _.name || `File ${b + 1}`, u.appendChild(w);
    }), x.appendChild(v), x.appendChild(u), t.appendChild(e), t.appendChild(s), t.appendChild(x);
  } else
    t.appendChild(e), t.appendChild(s);
  const f = document.createElement("div");
  f.style.cssText = `
    display: flex;
    align-items: center;
    gap: 8px;
  `;
  const p = document.createElement("button");
  p.textContent = "Export MIDI", p.style.cssText = `
    padding: 8px 16px;
    border: none;
    border-radius: 6px;
    background: var(--accent);
    color: white;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s;
  `, p.addEventListener("mouseenter", () => {
    p.style.opacity = "0.9";
  }), p.addEventListener("mouseleave", () => {
    p.style.opacity = "1";
  });
  const g = document.createElement("span");
  g.style.cssText = `
    font-size: 12px;
    color: var(--text-muted);
  `, p.addEventListener("click", async () => {
    let x = d[0];
    if (u && u.value && (x = d.find((_) => _.id === u.value) ?? d[0]), !x) {
      g.textContent = "No file available to export", g.style.color = "var(--error, #ef4444)";
      return;
    }
    const v = x.originalInput;
    if (!v) {
      g.textContent = "Original file data not available", g.style.color = "var(--error, #ef4444)";
      return;
    }
    p.disabled = !0, p.style.opacity = "0.6", g.textContent = "Exporting...", g.style.color = "var(--text-muted)";
    try {
      const _ = Fg(x.name, l), b = n.midiExport ?? { mode: "saveAs" };
      await T2(v, l, b, _), g.textContent = "Export complete!", g.style.color = "var(--success, #22c55e)", setTimeout(() => {
        g.textContent = "";
      }, 3e3);
    } catch (_) {
      console.error("MIDI export failed:", _), g.textContent = "Export failed", g.style.color = "var(--error, #ef4444)";
    } finally {
      p.disabled = !1, p.style.opacity = "1";
    }
  }), f.appendChild(p), f.appendChild(g), t.appendChild(f);
  const m = document.createElement("div");
  m.style.cssText = `
    margin-top: 10px;
    font-size: 11px;
    color: var(--text-muted);
    line-height: 1.4;
  `, m.textContent = "Downloads the MIDI file with the specified tempo applied. Note positions remain unchanged; only the tempo metadata is modified.", t.appendChild(m);
  const y = new MutationObserver((x) => {
    for (const v of x)
      for (const _ of v.removedNodes)
        if (_ === t || _ instanceof Element && _.contains(t)) {
          document.removeEventListener("wr-force-ui-refresh", h), y.disconnect();
          return;
        }
  });
  return requestAnimationFrame(() => {
    t.parentElement && y.observe(t.parentElement, { childList: !0, subtree: !0 });
  }), t;
}
function Nh(n = "multi-midi-settings-modal") {
  const t = document.getElementById(n);
  if (t)
    return {
      overlay: t,
      modal: t.firstElementChild
    };
  const e = document.createElement("div");
  e.id = n, e.style.cssText = `
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 2000;
  `;
  const s = document.createElement("div");
  return s.style.cssText = `
    width: 600px;
    max-width: 95%;
    max-height: 80vh;
    overflow-y: auto;
    background: var(--panel-bg);
    border-radius: 12px;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 24px;
  `, e.appendChild(s), { overlay: e, modal: s };
}
function Ng(n, t) {
  const e = document.createElement("div");
  e.style.cssText = "display:flex;justify-content:space-between;align-items:center;";
  const s = document.createElement("h2");
  s.textContent = n, s.style.cssText = "margin:0;font-size:20px;font-weight:700;color:var(--text-primary);";
  const i = document.createElement("button");
  return i.textContent = "✕", i.style.cssText = "border:none;background:transparent;font-size:24px;cursor:pointer;color:var(--text-muted);", i.onclick = t, e.appendChild(s), e.appendChild(i), e;
}
function sl(n, t) {
  const e = document.createElement("div");
  e.style.cssText = "display:flex;flex-direction:column;gap:8px;";
  const s = document.createElement("h3");
  return s.textContent = n, s.style.cssText = "margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text-primary);", e.appendChild(s), t.forEach((i, r) => {
    r === 0 && i.style.borderTop && (i.style.borderTop = "none", i.style.paddingTop = "0"), e.appendChild(i);
  }), e;
}
function X2(n) {
  const { overlay: t, modal: e } = Nh(
    "zoom-settings-overlay"
  );
  if (e.childElementCount > 0) {
    t.parentElement || document.body.appendChild(t);
    return;
  }
  const s = Ng("Settings", () => t.remove());
  e.appendChild(s);
  const i = document.createElement("div");
  i.style.cssText = "display:flex;align-items:center;gap:8px;";
  const r = document.createElement("input");
  r.type = "checkbox", r.checked = n.stateManager.getState().visual.showOnsetMarkers ?? !0, r.addEventListener("change", () => {
    n.stateManager.updateVisualState({
      showOnsetMarkers: r.checked
    });
  });
  const o = document.createElement("label");
  o.textContent = "Show onset markers", o.style.cssText = "font-size:14px;font-weight:500;color:var(--text-primary);", i.append(r, o), e.appendChild(i);
  const a = U2(n), l = q2(n), c = sl("Grid & Display", [a, l]);
  if (e.appendChild(c), !n.soloMode) {
    const v = G2(n), _ = Og(n), b = sl("Evaluation", [v, _]);
    e.appendChild(b);
  }
  const h = W2(n), u = document.createElement("div");
  u.style.cssText = "display:flex;align-items:center;gap:8px;";
  const d = document.createElement("input");
  d.type = "checkbox";
  const f = n.midiManager.getState().files, p = f.length > 0 ? f[0].isSustainVisible ?? !0 : !0;
  d.checked = p, d.addEventListener("change", () => {
    f.forEach((v) => {
      n.midiManager.toggleSustainVisibility(v.id);
    });
  });
  const g = document.createElement("label");
  g.textContent = "Show Sustain Pedal Regions", g.style.cssText = "font-size:14px;font-weight:500;color:var(--text-primary);", u.append(d, g);
  const m = $2(n), y = sl("Sustain Pedal", [
    h,
    u,
    m
  ]);
  e.appendChild(y);
  const x = j2(n);
  e.appendChild(x), t.addEventListener("click", (v) => {
    v.target === t && t.remove();
  }), document.body.appendChild(t);
}
function Y2(n, t, e, s) {
  const i = document.getElementById("wr-onset-picker-overlay");
  i && i.remove();
  const r = document.createElement("div");
  r.id = "wr-onset-picker-overlay", r.style.cssText = `
    position: fixed; inset: 0; z-index: 3000; background: transparent; 
  `;
  const o = document.createElement("div");
  o.setAttribute("role", "dialog"), o.setAttribute("aria-label", "Onset marker picker"), o.style.cssText = `
    position: absolute; min-width: 240px; max-width: 420px; 
    background: var(--surface); border: 1px solid var(--ui-border);
    border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    padding: 10px; display: flex; flex-direction: column; gap: 10px;
  `;
  function a() {
    const G = e.getBoundingClientRect(), H = o.offsetHeight, q = o.offsetWidth, W = window.innerHeight - G.bottom - 8, K = G.top - 8;
    let U;
    H <= W || W >= K ? U = Math.min(G.bottom + 6, window.innerHeight - H - 8) : U = Math.max(8, G.top - H - 6);
    let at = Math.max(8, Math.min(window.innerWidth - q - 8, G.left));
    o.style.top = `${Math.round(U)}px`, o.style.left = `${Math.round(at)}px`;
  }
  const l = document.createElement("div");
  l.textContent = "Choose color & marker", l.style.cssText = "font-size:12px;color:var(--text-muted);margin-bottom:2px;";
  const { activePaletteId: c, customPalettes: h } = n.midiManager.getState(), d = [...Cs, ...h].find((O) => O.id === c) || Cs[0], f = n.midiManager.getState().files.find((O) => O.id === t), p = Ne(f?.color ?? 0), g = n.stateManager.getOnsetMarkerForFile(t) || n.stateManager.ensureOnsetMarkerForFile(t), m = document.createElement("div");
  m.setAttribute("role", "listbox"), m.style.cssText = "display:flex;gap:6px;flex-wrap:wrap;";
  const y = [];
  let x = p;
  const v = () => {
    y.forEach((O) => {
      const V = (O.dataset.hex || "").toLowerCase() === x.toLowerCase();
      O.style.outline = V ? "2px solid var(--focus-ring)" : "none", O.setAttribute("aria-selected", String(V)), O.tabIndex = V ? 0 : -1;
    });
  };
  d.colors.forEach((O, V) => {
    const G = Ne(O), H = document.createElement("button");
    H.type = "button", H.dataset.hex = G, H.setAttribute("aria-label", `Select color ${G}`), H.style.cssText = `width:22px;height:22px;border-radius:4px;border:1px solid var(--ui-border);background:${G};cursor:pointer;`, H.onclick = () => {
      n.midiManager.updateColor(t, O), x = G, v(), s && s(g, G);
    }, V === 0 && (H.tabIndex = 0), y.push(H), m.appendChild(H);
  }), v();
  const _ = document.createElement("div");
  _.style.cssText = "height:1px;background:var(--ui-border);margin:2px 0;";
  const b = document.createElement("div");
  b.style.cssText = "display:flex;flex-direction:column;gap:6px;";
  const w = ["filled", "outlined"], S = [];
  let T = { ...g }, k = g.variant;
  const C = document.createElement("div");
  C.style.cssText = "display:flex;gap:2px;margin-bottom:6px;background:var(--ui-border);border-radius:6px;padding:2px;";
  const M = [], A = () => {
    M.forEach((O) => {
      const V = O.dataset.variant === k;
      O.style.background = V ? "var(--surface)" : "transparent", O.style.color = V ? "var(--text-primary)" : "var(--text-muted)", O.style.fontWeight = V ? "600" : "400", O.style.boxShadow = V ? "0 1px 2px rgba(0,0,0,0.1)" : "none";
    });
  };
  w.forEach((O) => {
    const V = document.createElement("button");
    V.type = "button", V.textContent = O === "filled" ? "Filled" : "Outlined", V.dataset.variant = O, V.style.cssText = `
      flex:1;padding:4px 8px;border:none;border-radius:4px;
      font-size:11px;cursor:pointer;transition:all 0.15s ease;
    `, V.onclick = () => {
      k = O, A(), R();
    }, M.push(V), C.appendChild(V);
  });
  const I = document.createElement("div");
  I.style.cssText = "display:grid;grid-template-columns:repeat(7,28px);gap:6px;";
  const F = () => {
    S.forEach((O) => {
      const V = O.dataset.shape === T.shape && O.dataset.variant === T.variant;
      O.style.outline = V ? "2px solid var(--focus-ring)" : "none", O.setAttribute("aria-pressed", String(V)), V && (O.tabIndex = 0);
    });
  }, R = () => {
    I.innerHTML = "", S.length = 0, as.forEach((O) => {
      const V = { shape: O, variant: k, size: 12, strokeWidth: 2 }, G = document.createElement("button");
      G.type = "button", G.setAttribute("aria-label", `${O} ${k}`), G.dataset.shape = String(O), G.dataset.variant = String(k), G.dataset.index = String(S.length), G.style.cssText = "width:28px;height:28px;border:1px solid var(--ui-border);border-radius:6px;background:var(--surface);display:flex;align-items:center;justify-content:center;cursor:pointer;", G.innerHTML = ir(V, p, 16), G.onclick = () => {
        n.stateManager.setOnsetMarkerForFile(t, V);
        const H = n.midiManager.getState().files.find((W) => W.id === t), q = Ne(H?.color ?? 0);
        T = V, F(), s && s(V, q);
      }, I.appendChild(G), S.push(G);
    }), F();
  };
  A(), R(), b.appendChild(C), b.appendChild(I);
  const E = document.createElement("div");
  E.style.cssText = "display:flex;gap:8px;justify-content:flex-end;";
  const P = document.createElement("button");
  P.type = "button", P.textContent = "Auto assign", P.style.cssText = "padding:4px 8px;border:1px solid var(--ui-border);border-radius:4px;background:var(--surface);cursor:pointer;", P.onclick = () => {
    const O = n.stateManager.assignNextUniqueOnsetMarker ? n.stateManager.assignNextUniqueOnsetMarker(t) : n.stateManager.ensureOnsetMarkerForFile(t), V = n.midiManager.getState().files.find((H) => H.id === t), G = Ne(V?.color ?? 0);
    T = O, F(), s && s(O, G);
  };
  const N = document.createElement("button");
  N.type = "button", N.textContent = "Close", N.style.cssText = "padding:4px 8px;border:1px solid var(--ui-border);border-radius:4px;background:var(--surface);cursor:pointer;", N.onclick = () => r.remove(), E.appendChild(P), E.appendChild(N), o.appendChild(l), o.appendChild(m), o.appendChild(_), o.appendChild(b), o.appendChild(E), r.appendChild(o), r.addEventListener("click", (O) => {
    O.target === r && r.remove();
  }), r.addEventListener("keydown", (O) => {
    O.key === "Escape" && r.remove();
  }), r.addEventListener("keydown", (O) => {
    const V = O, G = V.target;
    if (G && G.tagName.toLowerCase() === "button") {
      if (G.hasAttribute("data-index")) {
        const q = Number(G.getAttribute("data-index") || "0");
        let W = q;
        if (V.key === "ArrowRight") W = Math.min(S.length - 1, q + 1);
        else if (V.key === "ArrowLeft") W = Math.max(0, q - 1);
        else if (V.key === "ArrowDown") W = Math.min(S.length - 1, q + 7);
        else if (V.key === "ArrowUp") W = Math.max(0, q - 7);
        else if (V.key === "Enter" || V.key === " ") {
          G.click(), V.preventDefault();
          return;
        }
        W !== q && (V.preventDefault(), S[W]?.focus());
      } else if (m.contains(G)) {
        const q = y.indexOf(G);
        if (q >= 0) {
          let W = q;
          if (V.key === "ArrowRight") W = Math.min(y.length - 1, q + 1);
          else if (V.key === "ArrowLeft") W = Math.max(0, q - 1);
          else if (V.key === "Enter" || V.key === " ") {
            G.click(), V.preventDefault();
            return;
          }
          W !== q && (V.preventDefault(), y[W]?.focus());
        }
      }
    }
  }), document.body.appendChild(r), o.style.visibility = "hidden", requestAnimationFrame(() => {
    o.style.visibility = "visible", a();
  });
  const D = () => a();
  window.addEventListener("resize", D), window.addEventListener("scroll", D, { passive: !0 });
  const z = () => {
    window.removeEventListener("resize", D), window.removeEventListener("scroll", D);
  };
  r.addEventListener("remove", z), setTimeout(() => {
    o.querySelector("button")?.focus?.();
  }, 0);
}
const Z2 = [".mid", ".midi"], Tf = /* @__PURE__ */ new Map();
function K2(n) {
  const t = document.createElement("div"), e = document.createElement("div");
  e.style.cssText = "display:flex;align-items:center;justify-content:space-between;margin:0 0 12px;";
  const s = document.createElement("h3");
  s.textContent = "MIDI Files", s.style.cssText = "margin:0;font-size:16px;font-weight:600;", e.appendChild(s);
  const i = document.createElement("label");
  i.style.cssText = "display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-muted);cursor:pointer;";
  const r = document.createElement("input");
  r.type = "checkbox", r.checked = n.stateManager.getState().visual.uniformTrackColor ?? !1, r.style.cssText = "cursor:pointer;", r.onchange = () => {
    n.stateManager.updateVisualState({
      uniformTrackColor: r.checked
    }), l();
  };
  const o = document.createElement("span");
  o.textContent = "Uniform Track Color", i.appendChild(r), i.appendChild(o), e.appendChild(i), t.appendChild(e);
  const a = document.createElement("div");
  a.style.cssText = "display:flex;flex-direction:column;gap:8px;", t.appendChild(a);
  const l = () => {
    a.innerHTML = "";
    const c = n.midiManager.getState().files, h = n.permissions?.canRemoveFiles !== !1, u = (w) => {
      w.dataTransfer?.types.includes("Files") || w.preventDefault();
    }, d = (w) => {
      if (w.dataTransfer?.types.includes("Files"))
        return;
      w.preventDefault();
      const S = parseInt(
        w.dataTransfer.getData("text/plain"),
        10
      );
      if (Number.isNaN(S)) return;
      const T = c.length - 1;
      S !== T && (n.midiManager.reorderFiles(S, T), l());
    };
    a.removeEventListener("dragover", u), a.removeEventListener("drop", d), a.addEventListener("dragover", u), a.addEventListener("drop", d), c.forEach((w, S) => {
      const T = document.createElement("div");
      T.style.cssText = "display:flex;align-items:center;gap:8px;background:var(--surface-alt);padding:8px;border-radius:6px;";
      const k = document.createElement("span");
      k.id = `file-list-handle-${w.id}`, k.draggable = !0, k.innerHTML = lt.menu, k.style.cssText = "cursor:grab;color:var(--text-muted);display:flex;align-items:center;justify-content:center;width:18px;user-select:none;";
      const C = (W) => {
        W.stopPropagation();
      }, M = Ne(w.color), A = document.createElement("div");
      A.style.cssText = "position:relative;display:flex;align-items:center;";
      const I = document.createElement("button");
      I.type = "button", I.title = "Click to change color", I.style.cssText = "width:24px;height:24px;border-radius:4px;border:1px solid var(--ui-border);cursor:pointer;background:transparent;position:relative;padding:0;display:flex;align-items:center;justify-content:center;";
      const F = document.createElement("div");
      F.style.cssText = "width:18px;height:18px;display:flex;align-items:center;justify-content:center;";
      const R = (W, K) => ir(W, K, 16), E = n.stateManager.ensureOnsetMarkerForFile(
        w.id
      );
      F.innerHTML = R(E, M), I.appendChild(F);
      const P = document.createElement("input");
      P.type = "color", P.value = M, P.style.cssText = "position:absolute;opacity:0;width:0;height:0;border:0;padding:0;", I.onclick = (W) => {
        Y2(n, w.id, I, (K, U) => {
          F.innerHTML = R(K, U);
        });
      }, P.onchange = (W) => {
        const K = W.target.value;
        n.midiManager.updateColor(
          w.id,
          parseInt(K.substring(1), 16)
        );
        const U = n.stateManager.getOnsetMarkerForFile(w.id) || E;
        F.innerHTML = R(U, K);
      }, I.appendChild(P), A.appendChild(I);
      const N = document.createElement("input");
      N.type = "text", N.value = w.name, N.onchange = (W) => {
        n.midiManager.updateName(
          w.id,
          W.target.value
        );
      }, N.style.cssText = "flex:1;padding:4px 6px;border:1px solid var(--ui-border);border-radius:4px;background:var(--surface);color:var(--text-primary);";
      const D = document.createElement("button");
      D.setAttribute("aria-label", "Delete MIDI file"), D.innerHTML = lt.trash, D.style.cssText = "border:none;background:transparent;cursor:pointer;width:24px;height:24px;display:flex;align-items:center;justify-content:center;color:var(--text-muted);", D.onclick = () => {
        h && confirm(`Delete ${w.name}?`) && (n.midiManager.removeMidiFile(w.id), l());
      }, T.dataset.index = S.toString(), k.addEventListener("dragstart", (W) => {
        W.dataTransfer.effectAllowed = "move", W.dataTransfer.setData(
          "text/plain",
          (T.dataset.index || "0").toString()
        ), T.style.opacity = "0.6", k.style.cursor = "grabbing";
      }), k.addEventListener("dragend", () => {
        T.style.opacity = "1", k.style.cursor = "grab", T.style.outline = "none";
      }), T.draggable = !1, [I, N, D].forEach((W) => {
        W.addEventListener("mousedown", C), W.addEventListener("touchstart", C);
      }), T.addEventListener("dragover", (W) => {
        W.dataTransfer?.types.includes("Files") || (W.preventDefault(), W.stopPropagation(), T.style.outline = "2px dashed var(--focus-ring)");
      }), T.addEventListener("dragleave", () => {
        T.style.outline = "none";
      }), k.addEventListener("dragover", (W) => {
        W.dataTransfer?.types.includes("Files") || (W.preventDefault(), W.stopPropagation(), T.style.outline = "2px dashed var(--focus-ring)");
      });
      const z = (W) => (K) => {
        if (K.dataTransfer?.types.includes("Files"))
          return;
        K.preventDefault(), K.stopPropagation();
        const U = parseInt(
          K.dataTransfer.getData("text/plain"),
          10
        );
        !Number.isNaN(U) && U !== W && (n.midiManager.reorderFiles(U, W), l()), T.style.outline = "none";
      };
      T.addEventListener("drop", z(S)), k.addEventListener("drop", z(S));
      const O = w.parsedData?.tracks, V = O && O.length > 1;
      let G = null, H = Tf.get(w.id) ?? !1;
      const q = document.createElement("span");
      q.style.cssText = "display:flex;align-items:center;width:16px;min-width:16px;", V && (q.innerHTML = H ? Ao : Eo, q.style.cursor = "pointer", q.style.color = "var(--text-muted)", q.style.transition = "transform 0.2s", q.title = `${O.length} tracks`), T.appendChild(k), T.appendChild(q), T.appendChild(A), T.appendChild(N), h && T.appendChild(D), a.appendChild(T), V && (G = document.createElement("div"), G.style.cssText = `display:${H ? "flex" : "none"};flex-direction:column;gap:1px;padding:4px 8px;background:var(--surface);border-radius:4px;margin-left:60px;margin-top:2px;`, [...O].sort((K, U) => K.isDrum && !U.isDrum ? 1 : !K.isDrum && U.isDrum ? -1 : (K.program ?? 0) - (U.program ?? 0)).forEach((K) => {
        const U = document.createElement("div");
        U.style.cssText = "display:flex;align-items:center;gap:16px;padding:2px 0;";
        const at = document.createElement("span");
        at.innerHTML = uo(K.instrumentFamily), at.style.cssText = "display:flex;align-items:center;justify-content:center;width:18px;height:18px;color:var(--text-muted);", at.title = K.instrumentFamily;
        const At = document.createElement("span");
        At.textContent = K.name, At.style.cssText = "flex:1;font-size:12px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";
        const te = document.createElement("span");
        te.textContent = `${K.noteCount} notes`, te.style.cssText = "font-size:10px;color:var(--text-muted);padding:2px 6px;background:var(--surface-alt);border-radius:10px;text-align:right;", U.appendChild(at), U.appendChild(At), U.appendChild(te), G.appendChild(U);
      }), a.appendChild(G), q.onclick = (K) => {
        K.stopPropagation(), H = !H, Tf.set(w.id, H), G && (G.style.display = H ? "flex" : "none"), q.innerHTML = H ? Ao : Eo;
      });
    });
    const f = n.permissions?.canAddFiles !== !1, p = n.allowFileDrop !== !1, g = document.createElement("div");
    g.style.cssText = `
      margin-top:12px;
      padding:16px;
      border:2px dashed var(--ui-border);
      border-radius:8px;
      background:var(--surface);
      cursor:pointer;
      text-align:center;
      transition:all 0.2s ease;
    `;
    const m = document.createElement("div");
    m.style.cssText = "pointer-events:none;";
    const y = document.createElement("div");
    y.textContent = "+ Add MIDI Files", y.style.cssText = "font-size:14px;font-weight:500;color:var(--text-primary);margin-bottom:4px;";
    const x = document.createElement("div");
    x.textContent = p ? "Click or drag & drop MIDI files" : "Click to choose MIDI files", x.style.cssText = "font-size:12px;color:var(--text-muted);margin-bottom:2px;";
    const v = document.createElement("div");
    v.textContent = ".mid, .midi", v.style.cssText = "font-size:10px;color:var(--text-muted);opacity:0.7;", m.appendChild(y), m.appendChild(x), m.appendChild(v), g.appendChild(m);
    const _ = document.createElement("input");
    _.type = "file", _.accept = ".mid,.midi", _.multiple = !0, _.style.display = "none";
    const b = async (w) => {
      if (!f || w.length === 0) return;
      for (const T of w) {
        const k = T.name.toLowerCase().match(/\.[^.]+$/)?.[0] || "";
        if (Z2.includes(k))
          try {
            const C = n.stateManager?.getState(), M = C?.visual.pedalElongate ?? !0, A = C?.visual.pedalThreshold ?? 64, I = await ci(T, {
              applyPedalElongate: M,
              pedalThreshold: A
            });
            n.midiManager.addMidiFile(
              T.name,
              I,
              void 0,
              T
            );
          } catch (C) {
            console.error("Failed to parse MIDI:", C);
          }
      }
      l();
      const S = document.querySelector(
        '[data-role="file-toggle"]'
      );
      if (S) {
        const T = window.FileToggleManager;
        T && T.updateFileToggleSection(
          S,
          n
        );
      }
    };
    if (g.onclick = () => {
      f && (n.onFileAddRequest ? n.onFileAddRequest() : _.click());
    }, _.onchange = async (w) => {
      const S = Array.from(w.target.files || []);
      await b(S), _.value = "";
    }, p) {
      const w = (S) => {
        S ? (g.style.borderColor = "var(--focus-ring)", g.style.background = "var(--surface-alt)", y.textContent = "Drop MIDI files here") : (g.style.borderColor = "var(--ui-border)", g.style.background = "var(--surface)", y.textContent = "+ Add MIDI Files");
      };
      g.addEventListener("dragenter", (S) => {
        S.preventDefault(), S.stopPropagation(), S.dataTransfer?.types.includes("Files") && w(!0);
      }), g.addEventListener("dragover", (S) => {
        S.preventDefault(), S.stopPropagation(), S.dataTransfer?.types.includes("Files") && (S.dataTransfer.dropEffect = "copy");
      }), g.addEventListener("dragleave", (S) => {
        S.preventDefault(), S.stopPropagation(), w(!1);
      }), g.addEventListener("drop", async (S) => {
        if (S.preventDefault(), S.stopPropagation(), w(!1), !S.dataTransfer?.types.includes("Files"))
          return;
        const T = Array.from(S.dataTransfer.files);
        await b(T);
      });
    }
    f && (g.appendChild(_), a.appendChild(g));
  };
  return l(), typeof n.midiManager.subscribe == "function" && n.midiManager.subscribe(l), t;
}
function nl(n, t, e, s = t ? "edit" : "create") {
  const { overlay: i, modal: r } = Nh(
    "palette-editor-modal"
  );
  for (; r.firstChild; ) r.removeChild(r.firstChild);
  const o = s === "edit", a = o && t ? t.id : Date.now().toString(), l = s === "clone" && t ? `${t.name} Copy` : t?.name ?? "";
  function c() {
    if (t) return t.colors;
    const v = n.midiManager.getState().files.map((_) => _.color);
    return v.filter((_, b) => v.indexOf(_) === b);
  }
  const h = c().length > 0 ? c().map((v) => Ne(v)) : [Ne(0)], u = document.createElement("label");
  u.textContent = "Palette name", u.style.cssText = "font-weight:600;font-size:14px;display:block;margin-bottom:4px;";
  const d = document.createElement("input");
  d.type = "text", d.value = l, d.placeholder = "My palette", d.style.cssText = "width:100%;padding:6px 8px;border:1px solid var(--ui-border);border-radius:6px;margin-bottom:12px;background:var(--surface);color:var(--text-primary);";
  const f = document.createElement("div");
  f.style.cssText = "display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px;";
  const p = () => {
    for (; f.firstChild; ) f.removeChild(f.firstChild);
    h.forEach((v, _) => {
      const b = document.createElement("div");
      b.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:4px;";
      const w = document.createElement("button");
      w.type = "button", w.title = "Click to change color, right-click to remove", w.style.cssText = `width:32px;height:32px;border-radius:4px;border:1px solid var(--ui-border);background:${v};cursor:pointer;position:relative;`;
      const S = document.createElement("input");
      S.type = "text", S.maxLength = 7, S.placeholder = "#000000", S.value = v, S.style.cssText = "width:70px;padding:2px 4px;font-size:10px;font-family:monospace;text-align:center;border:1px solid var(--ui-border);border-radius:4px;background:var(--surface);color:var(--text-primary);";
      const T = document.createElement("input");
      T.type = "color", T.value = v, T.style.cssText = "position:absolute;opacity:0;width:0;height:0;border:0;padding:0;", T.onchange = () => {
        h[_] = T.value, w.style.background = T.value, S.value = T.value.replace("#", "");
      }, w.onclick = () => T.click(), w.oncontextmenu = (k) => {
        k.preventDefault(), h.length > 1 && (h.splice(_, 1), p());
      }, w.appendChild(T), S.oninput = () => {
        const k = S.value.trim();
        /^#[0-9a-fA-F]{0,6}$/.test(k) && k.length === 7 && (h[_] = k, w.style.background = k, T.value = k);
      }, b.appendChild(w), b.appendChild(S), f.appendChild(b);
    });
  };
  p();
  const g = document.createElement("button");
  g.type = "button", g.textContent = "+ Add color", g.style.cssText = "padding:6px 8px;border:1px dashed var(--ui-border);border-radius:6px;background:var(--surface);font-size:12px;cursor:pointer;margin-bottom:16px;color:var(--text-primary);", g.onclick = () => {
    h.push("#000000"), p();
  };
  const m = document.createElement("div");
  m.style.cssText = "display:flex;justify-content:flex-end;gap:8px;";
  const y = document.createElement("button");
  y.type = "button", y.textContent = "Cancel", y.style.cssText = "padding:6px 12px;border:1px solid var(--ui-border);border-radius:6px;background:var(--surface);cursor:pointer;color:var(--text-primary);", y.onclick = () => i.remove();
  const x = document.createElement("button");
  x.type = "button", x.textContent = o ? "Update" : "Create", x.style.cssText = "padding:6px 12px;border:1px solid var(--accent-strong);border-radius:6px;background:var(--accent-strong);color:var(--on-accent);cursor:pointer;", x.onclick = () => {
    const v = d.value.trim();
    if (!v) {
      alert("Palette name is required");
      return;
    }
    const _ = h.map((b) => b.replace("#", "")).filter((b) => /^([0-9a-fA-F]{6})$/.test(b)).map((b) => parseInt(b, 16));
    if (_.length === 0) {
      alert("At least one valid color is required");
      return;
    }
    o ? n.midiManager.updateCustomPalette(a, {
      name: v,
      colors: _
    }) : n.midiManager.addCustomPalette({
      id: a,
      name: v,
      colors: _
    }), i.remove(), e();
  }, m.append(y, x), r.append(u, d, f, g, m), document.body.appendChild(i);
}
function Gi(n) {
  const t = document.createElement("div");
  t.setAttribute("data-palette-selector", "true");
  const e = document.createElement("h3");
  e.id = "palette-title", e.textContent = "Color Palette", e.style.cssText = "margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text-primary);";
  const s = document.createElement("div");
  s.id = "palette-grid", s.style.cssText = "display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:12px;";
  const { customPalettes: i, activePaletteId: r } = n.midiManager.getState(), o = [...Cs, ...i], a = document.createElement("div");
  a.style.cssText = "margin-top:12px;padding:8px;border:1px solid var(--ui-border);border-radius:6px;background:var(--surface-alt);display:none;flex-wrap:wrap;gap:12px;align-items:center;";
  let l = "";
  const c = (p) => {
    if (l === p.id) {
      a.style.display = "none", a.innerHTML = "", l = "";
      return;
    }
    l = p.id, a.innerHTML = "";
    const g = document.createElement("div");
    g.style.cssText = "display:flex;gap:4px;flex-wrap:wrap;", p.colors.forEach((_) => {
      const b = document.createElement("div");
      b.style.cssText = `width:20px;height:20px;border-radius:3px;background:${Ne(
        _
      )}`, g.appendChild(b);
    });
    const m = document.createElement("span");
    m.textContent = p.name, m.style.cssText = "font-size:14px;font-weight:600;color:var(--text-primary);";
    const y = document.createElement("div");
    y.style.cssText = "display:flex;gap:8px;margin-left:auto;";
    const x = (_, b, w) => {
      const S = document.createElement("button");
      return S.type = "button", S.title = b, S.innerHTML = _, S.style.cssText = "width:24px;height:24px;display:flex;align-items:center;justify-content:center;border:none;background:none;cursor:pointer;color:var(--text-muted);", S.onclick = (T) => {
        T.stopPropagation(), w();
      }, S;
    };
    y.appendChild(
      x(lt.duplicate, "Duplicate", () => {
        nl(
          n,
          p,
          () => {
            const _ = Gi(n);
            t.replaceWith(_);
          },
          "clone"
        );
      })
    ), i.some((_) => _.id === p.id) && (y.appendChild(
      x(lt.edit, "Edit", () => {
        nl(
          n,
          p,
          () => {
            const _ = Gi(n);
            t.replaceWith(_);
          },
          "edit"
        );
      })
    ), y.appendChild(
      x(lt.trash, "Delete", () => {
        if (confirm(
          `Delete palette "${p.name}"? This action cannot be undone.`
        )) {
          n.midiManager.removeCustomPalette(p.id);
          const _ = Gi(n);
          t.replaceWith(_);
        }
      })
    )), a.append(g, m, y), a.style.display = "flex";
  };
  o.forEach((p) => {
    const g = document.createElement("button");
    g.type = "button", g.style.cssText = `display:flex;flex-direction:column;align-items:center;padding:6px 4px;border:1px solid var(--ui-border);border-radius:6px;cursor:pointer;background:${p.id === r ? "var(--surface-alt)" : "var(--surface)"};transition:background 0.2s;`;
    const m = document.createElement("div");
    m.style.cssText = "display:flex;gap:2px;margin-bottom:4px;", p.colors.slice(0, 8).forEach((b) => {
      const w = document.createElement("div");
      w.style.cssText = `width:12px;height:12px;border-radius:2px;background:${Ne(
        b
      )}`, m.appendChild(w);
    });
    const y = document.createElement("span");
    y.textContent = p.name, y.style.cssText = "font-size:12px;color:var(--text-muted);";
    const x = document.createElement("div");
    x.style.cssText = "display:flex;gap:4px;position:absolute;top:4px;right:4px;opacity:0;transition:opacity 0.15s;";
    const v = () => x.style.opacity = "1", _ = () => x.style.opacity = "0";
    g.addEventListener("mouseenter", v), g.addEventListener("mouseleave", _), g.addEventListener("focus", v), g.addEventListener("blur", _), g.onclick = () => {
      n.midiManager.getState().activePaletteId !== p.id && n.midiManager.setActivePalette(p.id), [...s.children].forEach(
        (b) => b instanceof HTMLElement && (b.style.background = "var(--surface)")
      ), g.style.background = "var(--surface-alt)", c(p);
    }, g.style.position = "relative", g.append(m, y), s.appendChild(g);
  });
  const h = document.createElement("button");
  h.type = "button", h.style.cssText = "display:flex;flex-direction:column;align-items:center;justify-content:center;padding:6px 4px;border:1px dashed var(--ui-border);border-radius:6px;cursor:pointer;background:var(--surface);gap:4px;transition:background 0.2s;";
  const u = document.createElement("span");
  u.textContent = "+", u.style.cssText = "font-size:20px;line-height:1;color:var(--text-muted);";
  const d = document.createElement("span");
  d.textContent = "New Palette", d.style.cssText = "font-size:12px;color:var(--text-muted);", h.append(u, d), h.onclick = () => {
    nl(n, null, () => {
      const p = Gi(n);
      t.replaceWith(p);
    });
  }, s.appendChild(h);
  const f = o.find((p) => p.id === r) ?? o[0];
  return c(f), t.append(e, s, a), t;
}
const Mf = [".wav", ".mp3", ".m4a", ".ogg"];
function Q2(n) {
  const t = document.createElement("div"), e = document.createElement("h3");
  e.textContent = "WAV File", e.style.cssText = "margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text-primary);", t.appendChild(e);
  const s = document.createElement("div");
  s.style.cssText = "display:flex;flex-direction:column;gap:8px;", t.appendChild(s);
  const i = () => globalThis._waveRollAudio, r = () => {
    s.innerHTML = "";
    const o = i(), a = o?.getFiles?.() ?? [];
    a.forEach((y) => {
      const x = document.createElement("div");
      x.style.cssText = "display:flex;align-items:center;gap:8px;background:var(--surface-alt);padding:8px;border-radius:6px;border:1px solid var(--ui-border);";
      const v = document.createElement("button");
      v.type = "button";
      const _ = `#${(y.color >>> 0).toString(16).padStart(6, "0")}`;
      v.style.cssText = `width:20px;height:20px;border-radius:3px;border:1px solid var(--ui-border);background:${_};cursor:pointer;position:relative;padding:0;`;
      const b = document.createElement("input");
      b.type = "color", b.value = _, b.style.cssText = "position:absolute;opacity:0;width:0;height:0;border:0;padding:0;", b.addEventListener("change", () => {
        const T = b.value, k = parseInt(T.replace("#", ""), 16);
        o?.updateColor?.(y.id, k), v.style.background = T;
      }), v.addEventListener("click", () => b.click()), v.appendChild(b);
      const w = document.createElement("input");
      if (w.type = "text", w.value = y.name, w.style.cssText = "flex:1;padding:4px 6px;border:1px solid var(--ui-border);border-radius:4px;background:var(--surface);color:var(--text-primary);", w.addEventListener("change", () => {
        o?.updateName?.(y.id, w.value.trim());
      }), x.appendChild(v), x.appendChild(w), n.permissions?.canRemoveFiles !== !1) {
        const T = document.createElement("button");
        T.type = "button", T.innerHTML = lt.trash, T.style.cssText = "width:24px;height:24px;padding:0;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-muted);opacity:0.7;", T.title = "Remove audio file", T.addEventListener("mouseenter", () => {
          T.style.opacity = "1", T.style.color = "var(--danger, #dc3545)";
        }), T.addEventListener("mouseleave", () => {
          T.style.opacity = "0.7", T.style.color = "var(--text-muted)";
        }), T.addEventListener("click", () => {
          o?.remove?.(y.id);
          try {
            n.audioPlayer?.pause?.();
          } catch {
          }
          r();
          const k = document.querySelector(
            '[data-role="file-toggle"]'
          );
          if (k) {
            const C = window.FileToggleManager;
            C && C.updateFileToggleSection(
              k,
              n
            );
          }
        }), x.appendChild(T);
      }
      s.appendChild(x);
    });
    const l = n.permissions?.canAddFiles !== !1, c = n.allowFileDrop !== !1, h = document.createElement("div");
    h.style.cssText = `
      margin-top:12px;
      padding:16px;
      border:2px dashed var(--ui-border);
      border-radius:8px;
      background:var(--surface);
      cursor:pointer;
      text-align:center;
      transition:all 0.2s ease;
    `;
    const u = document.createElement("div");
    u.style.cssText = "pointer-events:none;";
    const d = document.createElement("div");
    d.textContent = a.length > 0 ? "Change Audio File" : "+ Add Audio File", d.style.cssText = "font-size:14px;font-weight:500;color:var(--text-primary);margin-bottom:4px;";
    const f = document.createElement("div");
    f.textContent = c ? "Click or drag & drop audio file" : "Click to choose an audio file", f.style.cssText = "font-size:12px;color:var(--text-muted);margin-bottom:2px;";
    const p = document.createElement("div");
    p.textContent = ".wav, .mp3, .m4a, .ogg", p.style.cssText = "font-size:10px;color:var(--text-muted);opacity:0.7;", u.appendChild(d), u.appendChild(f), u.appendChild(p), h.appendChild(u);
    const g = document.createElement("input");
    g.type = "file", g.accept = ".wav,.mp3,.m4a,.ogg", g.style.display = "none";
    const m = async (y) => {
      if (!l) return;
      const x = y.name.toLowerCase().match(/\.[^.]+$/)?.[0] || "";
      if (!Mf.includes(x)) {
        console.warn(`Unsupported audio format: ${x}`);
        return;
      }
      try {
        const v = URL.createObjectURL(y);
        await Oh(null, v, y.name), r();
        const _ = document.querySelector(
          '[data-role="file-toggle"]'
        );
        if (_) {
          const b = window.FileToggleManager;
          b && b.updateFileToggleSection(
            _,
            n
          );
        }
      } catch (v) {
        console.error("Failed to load audio file:", v);
      }
    };
    if (h.onclick = () => {
      l && (n.onAudioFileAddRequest ? n.onAudioFileAddRequest() : g.click());
    }, g.onchange = async (y) => {
      if (!l) return;
      const x = y.target.files;
      !x || x.length === 0 || (await m(x[0]), g.value = "");
    }, c) {
      const y = (x) => {
        x ? (h.style.borderColor = "var(--focus-ring)", h.style.background = "var(--surface-alt)", d.textContent = "Drop audio file here") : (h.style.borderColor = "var(--ui-border)", h.style.background = "var(--surface)", d.textContent = a.length > 0 ? "Change Audio File" : "+ Add Audio File");
      };
      h.addEventListener("dragenter", (x) => {
        x.preventDefault(), x.stopPropagation(), x.dataTransfer?.types.includes("Files") && y(!0);
      }), h.addEventListener("dragover", (x) => {
        x.preventDefault(), x.stopPropagation(), x.dataTransfer?.types.includes("Files") && (x.dataTransfer.dropEffect = "copy");
      }), h.addEventListener("dragleave", (x) => {
        x.preventDefault(), x.stopPropagation(), y(!1);
      }), h.addEventListener("drop", async (x) => {
        if (x.preventDefault(), x.stopPropagation(), y(!1), !x.dataTransfer?.types.includes("Files"))
          return;
        const v = Array.from(x.dataTransfer.files);
        for (const _ of v) {
          const b = _.name.toLowerCase().match(/\.[^.]+$/)?.[0] || "";
          if (Mf.includes(b)) {
            await m(_);
            break;
          }
        }
      });
    }
    l && (h.appendChild(g), s.appendChild(h));
  };
  return r(), t;
}
function J2(n) {
  const t = document.createElement("div");
  t.style.cssText = "margin-top:16px;";
  const e = n.midiManager.getState().files;
  if (e.length === 0) {
    const R = document.createElement("p");
    return R.textContent = "No MIDI file loaded.", R.style.cssText = "color:var(--text-muted);font-size:14px;", t.appendChild(R), t;
  }
  const s = e[0], i = s.id, r = document.createElement("h3");
  r.textContent = "Note Appearance", r.style.cssText = "margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text-primary);", t.appendChild(r);
  let o = Ne(s.color), a = n.stateManager.getOnsetMarkerForFile(i) || n.stateManager.ensureOnsetMarkerForFile(i), l = () => {
  }, c = () => {
  };
  const h = document.createElement("div");
  h.style.cssText = "margin-bottom:16px;";
  const u = document.createElement("div");
  u.textContent = "Note Color", u.style.cssText = "font-size:13px;color:var(--text-muted);margin-bottom:8px;", h.appendChild(u);
  const d = document.createElement("div");
  d.style.cssText = "display:flex;gap:8px;flex-wrap:wrap;";
  const f = [], p = () => {
    f.forEach((R) => {
      const E = (R.dataset.hex || "").toLowerCase() === o.toLowerCase();
      R.style.outline = E ? "2px solid var(--focus-ring)" : "none", R.style.outlineOffset = E ? "2px" : "0";
    });
  }, g = () => {
    const R = n.midiManager.getState(), P = [...Cs, ...R.customPalettes].find((D) => D.id === R.activePaletteId) || Cs[0], N = R.files.find((D) => D.id === i);
    N && (o = Ne(N.color)), d.innerHTML = "", f.length = 0, P.colors.forEach((D) => {
      const z = Ne(D), O = document.createElement("button");
      O.type = "button", O.dataset.hex = z, O.setAttribute("aria-label", `Select color ${z}`), O.style.cssText = `
        width:28px;height:28px;border-radius:6px;
        border:1px solid var(--ui-border);background:${z};
        cursor:pointer;transition:transform 0.1s;
      `, O.onmouseenter = () => {
        O.style.transform = "scale(1.1)";
      }, O.onmouseleave = () => {
        O.style.transform = "scale(1)";
      }, O.onclick = () => {
        n.midiManager.updateColor(i, D), o = z, p(), l(), c();
      }, f.push(O), d.appendChild(O);
    }), p(), l();
  };
  h.appendChild(d), t.appendChild(h);
  const m = document.createElement("div"), y = document.createElement("div");
  y.textContent = "Onset Marker", y.style.cssText = "font-size:13px;color:var(--text-muted);margin-bottom:8px;", m.appendChild(y);
  const x = document.createElement("div");
  x.style.cssText = "display:flex;flex-direction:column;gap:8px;";
  const v = ["filled", "outlined"], _ = [];
  let b = a.variant;
  const w = document.createElement("div");
  w.style.cssText = "display:flex;gap:2px;background:var(--ui-border);border-radius:6px;padding:2px;";
  const S = [], T = () => {
    S.forEach((R) => {
      const E = R.dataset.variant === b;
      R.style.background = E ? "var(--surface)" : "transparent", R.style.color = E ? "var(--text-primary)" : "var(--text-muted)", R.style.fontWeight = E ? "600" : "400", R.style.boxShadow = E ? "0 1px 2px rgba(0,0,0,0.1)" : "none";
    });
  };
  v.forEach((R) => {
    const E = document.createElement("button");
    E.type = "button", E.textContent = R === "filled" ? "Filled" : "Outlined", E.dataset.variant = R, E.style.cssText = `
      flex:1;padding:6px 12px;border:none;border-radius:4px;
      font-size:12px;cursor:pointer;transition:all 0.15s ease;
    `, E.onclick = () => {
      b = R, T(), M();
    }, S.push(E), w.appendChild(E);
  }), x.appendChild(w);
  const k = document.createElement("div");
  k.style.cssText = "display:grid;grid-template-columns:repeat(7,32px);gap:6px;";
  const C = () => {
    _.forEach((R) => {
      const E = R.dataset.shape === a.shape && R.dataset.variant === a.variant;
      R.style.outline = E ? "2px solid var(--focus-ring)" : "none", R.style.outlineOffset = E ? "1px" : "0";
    });
  };
  l = () => {
    _.forEach((R) => {
      const E = R.dataset.shape, P = R.dataset.variant, N = {
        shape: E,
        variant: P,
        strokeWidth: 2
      };
      R.innerHTML = ir(N, o, 18);
    });
  };
  const M = () => {
    k.innerHTML = "", _.length = 0, as.forEach((R) => {
      const E = {
        shape: R,
        variant: b,
        size: 12,
        strokeWidth: 2
      }, P = document.createElement("button");
      P.type = "button", P.setAttribute("aria-label", `${R} ${b}`), P.dataset.shape = R, P.dataset.variant = b, P.style.cssText = `
        width:32px;height:32px;
        border:1px solid var(--ui-border);border-radius:6px;
        background:var(--surface);
        display:flex;align-items:center;justify-content:center;
        cursor:pointer;transition:background 0.1s;
      `, P.innerHTML = ir(E, o, 18), P.onmouseenter = () => {
        P.style.background = "var(--hover-surface)";
      }, P.onmouseleave = () => {
        P.style.background = "var(--surface)";
      }, P.onclick = () => {
        n.stateManager.setOnsetMarkerForFile(i, E), a = E, C(), c();
      }, _.push(P), k.appendChild(P);
    }), C();
  };
  c = () => {
    const R = n.midiManager.getState(), E = new CustomEvent("wr-appearance-change", {
      bubbles: !0,
      detail: {
        paletteId: R.activePaletteId,
        noteColor: parseInt(o.replace("#", ""), 16),
        onsetMarker: {
          shape: a.shape,
          variant: a.variant
        }
      }
    });
    t.dispatchEvent(E);
  }, g(), T(), M(), x.appendChild(k), m.appendChild(x), t.appendChild(m);
  let A = n.midiManager.getState().activePaletteId;
  const I = n.midiManager.subscribe((R) => {
    R.activePaletteId !== A && (A = R.activePaletteId, g());
  }), F = new MutationObserver((R) => {
    for (const E of R)
      for (const P of E.removedNodes)
        if (P === t || P instanceof Element && P.contains(t)) {
          I(), F.disconnect();
          return;
        }
  });
  return F.observe(document.body, { childList: !0, subtree: !0 }), t;
}
function Lg(n) {
  const { overlay: t, modal: e } = Nh();
  if (e.childElementCount > 0) {
    t.parentElement || document.body.appendChild(t);
    return;
  }
  const s = n.soloMode === !0, r = Ng(s ? "Appearance" : "Files & Appearance", () => t.remove());
  e.appendChild(r);
  const o = Gi(n);
  if (e.appendChild(o), s) {
    const a = J2(n);
    e.appendChild(a);
  } else {
    const a = Q2(n), l = K2(n);
    e.appendChild(a), e.appendChild(l);
  }
  t.addEventListener("click", (a) => {
    a.target === t && t.remove();
  }), document.body.appendChild(t);
}
const Vg = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  openSettingsModal: Lg
}, Symbol.toStringTag, { value: "Module" }));
function tA(n) {
  const t = document.createElement("div");
  t.style.cssText = `
    display: flex;
    align-items: center;
    gap: 4px;
    height: 48px;
    background: var(--panel-bg);
    padding: 4px 8px;
    border-radius: 8px;
    box-shadow: var(--shadow-sm);
  `;
  const e = js(lt.settings, () => {
    X2(n);
  });
  if (e.title = "Settings", t.appendChild(e), n.soloMode) {
    const s = js(lt.palette, () => {
      Lg(n);
    });
    s.title = "Appearance", t.appendChild(s);
  }
  return t;
}
function eA(n, t, e) {
  n.innerHTML = "", n.style.cssText = `
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    box-sizing: border-box;
    background: var(--surface-alt);
    color: var(--text-primary);
    padding: 12px;
    border-radius: 8px;
    box-shadow: var(--shadow-sm);
    position: relative;
    z-index: 10;
  `;
  const s = document.createElement("div");
  s.style.cssText = `
    display: flex;
    align-items: center;
    gap: 12px;
    justify-content: flex-start;
    flex-wrap: wrap;
    overflow: visible;
  `, s.appendChild(I2(e)), s.appendChild(D2(e)), s.appendChild(R2(e)), s.appendChild(N2(e)), s.appendChild(L2(e)), e.soloMode || s.appendChild(Og(e, { withWrapper: !0 })), s.appendChild(tA(e)), n.appendChild(s), n.appendChild(z2(e)), t.appendChild(n);
}
const Bg = {
  onsetTolerance: 0.05,
  // 50 ms
  pitchTolerance: 0.5,
  // 50 cents -> 0.5 semitone
  offsetRatioTolerance: 0.2,
  offsetMinTolerance: 0.05
  // 50 ms
};
function sA(n) {
  const t = [], e = [];
  for (const s of n) {
    const i = s.time, r = s.time + s.duration;
    t.push([i, r]), e.push(s.midi);
  }
  return { intervals: t, pitches: e };
}
const kf = 120;
function nA(n) {
  if (!n || n.length === 0)
    return kf;
  const t = 1e-3, e = n.filter((r) => Math.abs(r.time || 0) <= t), i = (e.length > 0 ? e : n).sort(
    (r, o) => (r.time || 0) - (o.time || 0)
  )[0];
  return Math.max(20, Math.min(300, i?.bpm || kf));
}
function iA(n, t, e) {
  if (t <= 0 || e <= 0)
    return n;
  const s = e / t;
  return Math.abs(s - 1) < 1e-6 ? n : n.map(([i, r]) => [i * s, r * s]);
}
function Cf(n) {
  const { intervals: t, pitches: e } = sA(n.notes), s = nA(n.header?.tempos);
  return { intervals: t, pitches: e, bpm: s };
}
function rA(n, t, e, s, i, r, o, a) {
  const l = Array.from({ length: n.length }, () => []);
  for (let c = 0; c < n.length; c++) {
    const [h, u] = n[c], d = t[c], f = u - h, p = Math.max(
      a,
      o * Math.max(0, f)
    );
    for (let g = 0; g < e.length; g++) {
      const [m, y] = e[g], x = s[g], v = Math.abs(m - h), _ = Math.abs(x - d), b = Math.abs(y - u);
      v <= i && _ <= r && b <= p && l[c].push(g);
    }
  }
  return l;
}
function oA(n, t, e) {
  const s = Number.POSITIVE_INFINITY, i = Array(t).fill(-1), r = Array(e).fill(-1), o = Array(t).fill(0);
  function a() {
    const h = [];
    for (let d = 0; d < t; d++)
      i[d] === -1 ? (o[d] = 0, h.push(d)) : o[d] = s;
    let u = !1;
    for (; h.length > 0; ) {
      const d = h.shift();
      for (const f of n[d]) {
        const p = r[f];
        p !== -1 ? o[p] === s && (o[p] = o[d] + 1, h.push(p)) : u = !0;
      }
    }
    return u;
  }
  function l(h) {
    for (const u of n[h]) {
      const d = r[u];
      if (d === -1 || o[d] === o[h] + 1 && l(d))
        return i[h] = u, r[u] = h, !0;
    }
    return o[h] = Number.POSITIVE_INFINITY, !1;
  }
  let c = 0;
  for (; a(); )
    for (let h = 0; h < t; h++)
      i[h] === -1 && l(h) && (c += 1);
  return { pairU: i, pairV: r, matchingSize: c };
}
function zg(n, t, e = {}, s = {}) {
  const {
    onsetTolerance: i,
    pitchTolerance: r,
    offsetRatioTolerance: o,
    offsetMinTolerance: a
  } = {
    ...Bg,
    ...e
  }, { scaleBpmToReference: l = !1 } = s, c = Cf(n), h = Cf(t);
  let u = h.intervals;
  l && h.bpm !== c.bpm && (u = iA(
    h.intervals,
    h.bpm,
    c.bpm
  ));
  const d = rA(
    c.intervals,
    c.pitches,
    u,
    h.pitches,
    i,
    r,
    o,
    a
  ), { pairU: f, pairV: p } = oA(
    d,
    c.intervals.length,
    u.length
  ), g = [];
  for (let x = 0; x < f.length; x++) {
    const v = f[x];
    if (v !== -1) {
      const [_, b] = c.intervals[x], [w, S] = u[v], [T] = h.intervals[v], k = n.notes[x]?.velocity, C = t.notes[v]?.velocity, M = Math.max(
        0,
        Math.min(b, S) - Math.max(_, w)
      ), A = Math.max(b, S) - Math.min(_, w);
      g.push({
        ref: x,
        est: v,
        refPitch: c.pitches[x],
        estPitch: h.pitches[v],
        refTime: _,
        estTime: T,
        // Report original (unscaled) estimated time
        onsetDiff: Math.abs(w - _),
        // Diff using scaled time
        offsetDiff: Math.abs(S - b),
        // Diff using scaled time
        pitchDiff: Math.abs(h.pitches[v] - c.pitches[x]),
        overlapRatio: A > 0 ? M / A : 0,
        refVelocity: typeof k == "number" ? k : void 0,
        estVelocity: typeof C == "number" ? C : void 0,
        velocityDiff: typeof k == "number" && typeof C == "number" ? Math.abs(C - k) : void 0
      });
    }
  }
  const m = [];
  for (let x = 0; x < f.length; x++)
    f[x] === -1 && m.push(x);
  const y = [];
  for (let x = 0; x < p.length; x++)
    p[x] === -1 && y.push(x);
  return { matches: g, falseNegatives: m, falsePositives: y };
}
function aA(n, t, e = {}) {
  const s = zg(
    n,
    t,
    e
  ), i = s.matches.length, r = n.notes.length, o = t.notes.length, a = o > 0 ? i / o : 0, l = r > 0 ? i / r : 0, c = a + l > 0 ? 2 * a * l / (a + l) : 0;
  let h = 0;
  if (s.matches.length > 0) {
    const u = s.matches.map((d) => {
      const f = n.notes[d.ref], p = t.notes[d.est], g = f.time, m = f.time + f.duration, y = p.time, x = p.time + p.duration, v = Math.max(
        0,
        Math.min(m, x) - Math.max(g, y)
      ), _ = Math.max(m, x) - Math.min(g, y);
      return _ > 0 ? v / _ : 0;
    });
    h = u.reduce((d, f) => d + f, 0) / u.length;
  }
  return {
    precision: a,
    recall: l,
    f1: c,
    f_measure: c,
    avgOverlapRatio: h,
    numCorrect: i,
    numRef: r,
    numEst: o,
    matches: s.matches,
    falseNegatives: s.falseNegatives,
    falsePositives: s.falsePositives
  };
}
function sE(n, t, e = {}) {
  const s = aA(n, t, e);
  return {
    precision: s.precision,
    recall: s.recall,
    f1: s.f1,
    f_measure: s.f_measure,
    avgOverlapRatio: s.avgOverlapRatio
  };
}
function lA(n) {
  const t = /* @__PURE__ */ new Map();
  for (let e = 0; e < n.length; e++) {
    const s = n[e].note;
    for (let i = e + 1; i < n.length; i++) {
      const r = n[i].note;
      if (n[e].fileId === n[i].fileId || s.midi !== r.midi)
        continue;
      const o = Math.max(s.time, r.time), a = Math.min(
        s.time + s.duration,
        r.time + r.duration
      );
      if (a <= o)
        continue;
      const l = (c, h, u) => {
        const d = t.get(c) ?? [];
        d.push({ start: h, end: u }), t.set(c, d);
      };
      l(e, o, a), l(i, o, a);
    }
  }
  return t.forEach((e, s) => {
    if (e.length <= 1) return;
    e.sort((o, a) => o.start - a.start);
    const i = [];
    let r = { ...e[0] };
    for (let o = 1; o < e.length; o++) {
      const a = e[o];
      a.start < r.end ? r.end = Math.max(r.end, a.end) : (i.push(r), r = { ...a });
    }
    i.push(r), t.set(s, i);
  }), t;
}
function xe(n) {
  return typeof n == "number" ? n : parseInt(n.replace("#", ""), 16);
}
function cA(n) {
  const t = "#" + n.toString(16).padStart(6, "0"), e = xb(t, 3.5);
  return parseInt(e.replace("#", ""), 16);
}
const hA = 4473924, us = xe(Al), ds = xe(im), Vt = 0.75;
function qg(n) {
  if (n.length === 0) return n;
  n.sort((s, i) => s.start - i.start);
  const t = [];
  let e = { ...n[0] };
  for (let s = 1; s < n.length; s++) {
    const i = n[s];
    i.start <= e.end ? e.end = Math.max(e.end, i.end) : (t.push(e), e = { ...i });
  }
  return t.push(e), t;
}
function uA(n, t, e) {
  const s = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
  for (const r of t) {
    const o = r.id, a = zg(
      n.parsedData,
      r.parsedData,
      e
    );
    i.has(o) || i.set(o, /* @__PURE__ */ new Map());
    const l = i.get(o);
    a.matches.forEach((c) => {
      s.has(c.ref) || s.set(c.ref, []), s.get(c.ref).push({ estId: o, estIdx: c.est }), l.set(c.est, c.ref);
    });
  }
  return { byRef: s, byEst: i };
}
function dA(n, t, e) {
  const s = /* @__PURE__ */ new Map(), i = t?.parsedData?.notes || [];
  for (let r = 0; r < i.length; r++) {
    const o = i[r], a = o.time, l = o.time + o.duration, c = [], h = n.get(r) || [];
    if (h.length > 0)
      for (const { estId: u, estIdx: d } of h) {
        const f = e.find((v) => v.id === u);
        if (!f) continue;
        const p = f.parsedData.notes[d], g = p.time, m = p.time + p.duration, y = Math.max(a, g), x = Math.min(l, m);
        x > y && c.push({ start: y, end: x });
      }
    if (c.length === 0)
      for (const u of e) {
        const d = u.parsedData.notes;
        for (let f = 0; f < d.length; f++) {
          const p = d[f];
          if (typeof p?.midi == "number" && p.midi !== o.midi) continue;
          const g = p.time, m = p.time + p.duration, y = Math.max(a, g), x = Math.min(l, m);
          x > y && c.push({ start: y, end: x });
        }
      }
    s.set(r, qg(c));
  }
  return s;
}
function fA(n, t, e, s, i) {
  const r = /* @__PURE__ */ new Set([...e.keys()]), o = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map();
  for (const c of t) {
    const h = c.id, u = s.get(h) ?? /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Set();
    for (let f = 0; f < c.parsedData.notes.length; f++)
      u.has(f) || d.add(f);
    l.set(h, d), a.set(h, /* @__PURE__ */ new Map());
  }
  for (let c = 0; c < n.parsedData.notes.length; c++) {
    if (r.has(c)) continue;
    const h = n.parsedData.notes[c], u = h.time, d = h.time + h.duration;
    for (const f of t) {
      const p = f.id, g = l.get(p);
      for (const m of g) {
        const y = f.parsedData.notes[m];
        if (y.midi !== h.midi) continue;
        const x = y.time, v = y.time + y.duration, _ = Math.max(u, x), b = Math.min(d, v);
        if (b <= _) continue;
        const w = Math.max(0, Math.min(d, v) - Math.max(u, x)), S = Math.max(d, v) - Math.min(u, x), T = S > 0 ? w / S : 0, k = Math.abs(x - u), C = d - u, M = Math.max(
          i.offsetMinTolerance,
          i.offsetRatioTolerance * Math.max(0, C)
        ), A = Math.abs(v - d), I = k <= i.onsetTolerance * 1.25, F = A <= M * 1.25;
        if (T >= 0.25 && (I || F)) {
          const R = o.get(c) ?? [];
          R.push({ start: _, end: b, estId: p, estIdx: m }), o.set(c, R);
          const E = a.get(p), P = E.get(m) ?? [];
          P.push({ start: _, end: b, refIdx: c }), E.set(m, P);
        }
      }
    }
  }
  return { ambiguousByRef: o, ambiguousByEst: a };
}
function pA(n, t) {
  const e = n.includes("-gray"), s = n.includes("exclusive"), i = n.includes("-own"), r = n.startsWith("eval-tp-only-"), o = n.startsWith("eval-fp-only-"), a = n.startsWith("eval-fn-only-"), l = r || o || a, c = t <= 1 ? "pair" : "or";
  return {
    useGrayGlobal: e,
    isExclusiveGlobal: s,
    isIntersectionOwn: i,
    isTpOnly: r,
    isFpOnly: o,
    isFnOnly: a,
    isOnlyMode: l,
    aggregationMode: c
  };
}
function mA(n) {
  const {
    highlightMode: t,
    isRef: e,
    coloredNote: s,
    note: i,
    sourceIdx: r,
    fileColor: o,
    state: a,
    evalState: l,
    estFiles: c,
    byRef: h,
    unionRangesByRef: u,
    result: d
  } = n;
  if (t !== "eval-gt-missed-only-own" && t !== "eval-gt-missed-only-gray")
    return !1;
  const f = a.files.find((x) => x.id === l.refId), p = xe(f?.color ?? Me), g = cA(p), m = t === "eval-gt-missed-only-gray", y = m ? p : g;
  if (e) {
    const x = (u.get(r) || []).slice().sort((w, S) => w.start - S.start), v = i.time, _ = i.time + i.duration;
    if (x.length === 0)
      return d.push({
        note: { ...i, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
        color: y,
        fileId: s.fileId,
        isMuted: s.isMuted
      }), !0;
    let b = v;
    for (const w of x) {
      const S = Math.max(v, w.start), T = Math.min(_, w.end);
      if (S < _ && T > v && S < T) {
        b < S && d.push({
          note: { ...i, time: b, duration: S - b, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
          color: y,
          fileId: s.fileId,
          isMuted: s.isMuted
        });
        const k = Math.max(S, v), C = Math.min(_, T);
        let M = g;
        if (!m) {
          let A = null;
          const I = h.get(r);
          if (I && I.length > 0) {
            const F = c.find((R) => R.id === I[0].estId);
            A = F ? xe(F.color ?? Me) : p;
          } else
            t: for (const F of c) {
              const R = F.parsedData?.notes || [];
              for (let E = 0; E < R.length; E++) {
                const P = R[E];
                if (P?.midi !== i.midi) continue;
                const N = P.time, D = P.time + P.duration;
                if (N < C && D > k) {
                  A = xe(F.color ?? Me);
                  break t;
                }
              }
            }
          if (A != null) {
            const F = ht(p, us, Vt), R = ht(A, ds, Vt), E = Hs([F, R]);
            M = ht(E, 16777215, 0.2);
          } else
            M = ht(p, 16777215, 0.15);
        }
        d.push({
          note: { ...i, time: k, duration: C - k, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
          color: M,
          fileId: s.fileId,
          isMuted: s.isMuted
        }), b = Math.max(b, T);
      }
    }
    b < _ && d.push({
      note: { ...i, time: b, duration: _ - b, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
      color: y,
      fileId: s.fileId,
      isMuted: s.isMuted
    });
  } else {
    const x = f?.parsedData?.notes || [], v = i.time, _ = i.time + i.duration, b = [];
    for (const k of x) {
      if (k?.midi !== i.midi) continue;
      const C = Math.max(v, k.time), M = Math.min(_, k.time + k.duration);
      M > C && b.push({ start: C, end: M });
    }
    const w = qg(b), S = g;
    if (w.length === 0)
      return d.push({
        note: { ...i, noOverlay: !0, isEvalHighlightSegment: !1 },
        color: S,
        fileId: s.fileId,
        isMuted: s.isMuted
      }), !0;
    let T = v;
    for (const k of w) {
      const C = Math.max(v, k.start), M = Math.min(_, k.end);
      if (T < C && d.push({
        note: { ...i, time: T, duration: C - T, isEvalHighlightSegment: !1 },
        color: S,
        fileId: s.fileId,
        isMuted: s.isMuted
      }), C < M) {
        let A = g;
        if (!m) {
          const I = o, R = ht(p, us, Vt), E = ht(I, ds, Vt), P = Hs([R, E]);
          A = ht(P, 16777215, 0.2);
        }
        d.push({
          note: { ...i, time: C, duration: M - C, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
          color: A,
          fileId: s.fileId,
          isMuted: s.isMuted
        });
      }
      T = Math.max(T, M);
    }
    T < _ && d.push({
      note: { ...i, time: T, duration: _ - T, isEvalHighlightSegment: !1 },
      color: S,
      fileId: s.fileId,
      isMuted: s.isMuted
    });
  }
  return !0;
}
function gA(n) {
  const e = (k, C, M) => Math.abs(k - C) <= 1e-9 ? C : Math.abs(k - M) <= 1e-9 ? M : k, {
    isOnlyMode: s,
    isTpOnly: i,
    isFpOnly: r,
    isFnOnly: o,
    useGrayGlobal: a,
    isRef: l,
    isEst: c,
    fileColor: h,
    coloredNote: u,
    note: d,
    sourceIdx: f,
    state: p,
    evalState: g,
    estFiles: m,
    byRef: y,
    byEst: x,
    unionRangesByRef: v,
    result: _
  } = n;
  if (!s) return !1;
  const b = 8947848, w = 5592405, S = (k, C) => {
    if (a)
      return w;
    const M = ht(k, us, Vt), A = ht(C, ds, Vt), I = Hs([M, A]);
    return ht(I, 16777215, 0.2);
  }, T = (k, C = !1) => {
    if (a) {
      if (C) {
        const M = xe(p.files.find((E) => E.id === g.refId)?.color ?? Me), A = k ? h : xe(p.files.find((E) => E.id === g.refId)?.color ?? Me), I = ht(M, us, Vt), F = ht(A, ds, Vt), R = Hs([I, F]);
        return ht(R, 16777215, 0.2);
      }
      return h;
    }
    return b;
  };
  if (l) {
    const k = (v.get(f) || []).slice(), C = d.time, M = d.time + d.duration, A = h;
    if (i) {
      if (k.length === 0)
        return _.push({
          note: { ...d, isEvalHighlightSegment: !1 },
          color: T(!0),
          fileId: u.fileId,
          isMuted: u.isMuted
        }), !0;
      let I = A;
      const F = y.get(f);
      if (F && F.length > 0) {
        const P = m.find((N) => N.id === F[0].estId);
        P && (I = xe(P.color ?? Me));
      }
      const R = S(A, I);
      k.sort((P, N) => P.start - N.start);
      let E = C;
      for (const P of k) {
        const N = e(Math.max(C, P.start), C, M), D = e(Math.min(M, P.end), C, M);
        E + 1e-9 < N && _.push({
          note: { ...d, time: E, duration: N - E, isEvalHighlightSegment: !1 },
          color: T(!0),
          fileId: u.fileId,
          isMuted: u.isMuted
        }), N + 1e-9 < D && _.push({
          note: { ...d, time: N, duration: D - N, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
          color: R,
          fileId: u.fileId,
          isMuted: u.isMuted
        }), E = Math.max(E, D), Math.abs(E - M) <= 1e-9 && (E = M), Math.abs(E - C) <= 1e-9 && (E = C);
      }
      return E + 1e-9 < M && _.push({
        note: { ...d, time: E, duration: M - E, isEvalHighlightSegment: !1 },
        color: T(!0),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), !0;
    }
    if (o) {
      const I = a ? w : A, F = a ? A : b;
      if (k.length === 0)
        return _.push({
          note: { ...d, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
          color: I,
          fileId: u.fileId,
          isMuted: u.isMuted
        }), !0;
      let R = C;
      k.sort((E, P) => E.start - P.start);
      for (const E of k) {
        const P = e(Math.max(C, E.start), C, M), N = e(Math.min(M, E.end), C, M);
        R + 1e-9 < P && _.push({
          note: { ...d, time: R, duration: P - R, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
          color: I,
          fileId: u.fileId,
          isMuted: u.isMuted
        }), P + 1e-9 < N && _.push({
          note: { ...d, time: P, duration: N - P, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
          color: a ? T(!0, !0) : F,
          fileId: u.fileId,
          isMuted: u.isMuted
        }), R = Math.max(R, N), Math.abs(R - M) <= 1e-9 && (R = M), Math.abs(R - C) <= 1e-9 && (R = C);
      }
      return R + 1e-9 < M && _.push({
        note: { ...d, time: R, duration: M - R, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
        color: I,
        fileId: u.fileId,
        isMuted: u.isMuted
      }), !0;
    }
    if (r) {
      const I = (v.get(f) || []).slice().sort((P, N) => P.start - N.start), F = d.time, R = d.time + d.duration;
      if (I.length === 0)
        return _.push({
          note: { ...d, isEvalHighlightSegment: !1 },
          color: T(!0),
          fileId: u.fileId,
          isMuted: u.isMuted
        }), !0;
      let E = F;
      for (const P of I) {
        const N = e(Math.max(F, P.start), F, R), D = e(Math.min(R, P.end), F, R);
        E + 1e-9 < N && _.push({
          note: { ...d, time: E, duration: N - E, isEvalHighlightSegment: !1 },
          color: T(!0),
          fileId: u.fileId,
          isMuted: u.isMuted
        }), N + 1e-9 < D && _.push({
          note: { ...d, time: N, duration: D - N, isEvalHighlightSegment: !1 },
          color: T(!0, !0),
          fileId: u.fileId,
          isMuted: u.isMuted
        }), E = Math.max(E, D), Math.abs(E - R) <= 1e-9 && (E = R), Math.abs(E - F) <= 1e-9 && (E = F);
      }
      return E + 1e-9 < R && _.push({
        note: { ...d, time: E, duration: R - E, isEvalHighlightSegment: !1 },
        color: T(!0),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), !0;
    }
  }
  if (c) {
    const k = x.get(u.fileId)?.get(f), C = h;
    if (i) {
      if (k === void 0) {
        const E = p.files.find((H) => H.id === g.refId), P = E?.parsedData?.notes || [], N = d.time, D = d.time + d.duration, z = [];
        for (const H of P) {
          if (H?.midi !== d.midi) continue;
          const q = e(Math.max(H.time, N), N, D), W = e(Math.min(H.time + H.duration, D), N, D);
          q + 1e-9 < W && z.push({ start: q, end: W });
        }
        if (z.sort((H, q) => H.start - q.start), z.length === 0)
          return _.push({
            note: { ...d, isEvalHighlightSegment: !1 },
            color: T(!1),
            fileId: u.fileId,
            isMuted: u.isMuted
          }), !0;
        let O = N;
        const V = xe(E?.color ?? Me), G = S(V, C);
        for (const H of z) {
          const q = H.start, W = H.end;
          O + 1e-9 < q && _.push({
            note: { ...d, time: O, duration: q - O, isEvalHighlightSegment: !1 },
            color: T(!1),
            fileId: u.fileId,
            isMuted: u.isMuted
          }), _.push({
            note: { ...d, time: q, duration: W - q, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
            color: G,
            fileId: u.fileId,
            isMuted: u.isMuted
          }), O = Math.max(O, W);
        }
        return O + 1e-9 < D && _.push({
          note: { ...d, time: O, duration: D - O, isEvalHighlightSegment: !1 },
          color: T(!1),
          fileId: u.fileId,
          isMuted: u.isMuted
        }), !0;
      }
      const M = p.files.find((E) => E.id === g.refId) ? p.files.find((E) => E.id === g.refId).parsedData.notes[k] : null, A = d.time, I = d.time + d.duration, F = e(Math.max(M.time, A), A, I), R = e(Math.min(M.time + M.duration, I), A, I);
      if (A + 1e-9 < F && _.push({
        note: { ...d, time: A, duration: F - A, isEvalHighlightSegment: !1 },
        color: T(!1),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), F + 1e-9 < R) {
        const E = xe(p.files.find((N) => N.id === g.refId)?.color ?? Me), P = S(E, C);
        _.push({
          note: { ...d, time: F, duration: R - F, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
          color: P,
          fileId: u.fileId,
          isMuted: u.isMuted
        });
      }
      return R + 1e-9 < I && _.push({
        note: { ...d, time: R, duration: I - R, isEvalHighlightSegment: !1 },
        color: T(!1),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), !0;
    }
    if (r) {
      const M = a ? w : C;
      if (k === void 0) {
        const N = p.files.find((G) => G.id === g.refId)?.parsedData?.notes || [], D = d.time, z = d.time + d.duration, O = [];
        for (const G of N) {
          if (G?.midi !== d.midi) continue;
          const H = e(Math.max(G.time, D), D, z), q = e(Math.min(G.time + G.duration, z), D, z);
          H + 1e-9 < q && O.push({ start: H, end: q });
        }
        if (O.sort((G, H) => G.start - H.start), O.length === 0)
          return _.push({
            note: { ...d, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
            color: M,
            fileId: u.fileId,
            isMuted: u.isMuted
          }), !0;
        let V = D;
        for (const G of O) {
          const H = G.start, q = G.end;
          V + 1e-9 < H && _.push({
            note: { ...d, time: V, duration: H - V, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
            color: M,
            fileId: u.fileId,
            isMuted: u.isMuted
          }), _.push({
            note: { ...d, time: H, duration: q - H, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
            color: T(!1, !0),
            fileId: u.fileId,
            isMuted: u.isMuted
          }), V = Math.max(V, q);
        }
        return V + 1e-9 < z && _.push({
          note: { ...d, time: V, duration: z - V, isEvalHighlightSegment: !0, evalSegmentKind: "exclusive" },
          color: M,
          fileId: u.fileId,
          isMuted: u.isMuted
        }), !0;
      }
      const A = p.files.find((P) => P.id === g.refId).parsedData.notes[k], I = d.time, F = d.time + d.duration, R = e(Math.max(A.time, I), I, F), E = e(Math.min(A.time + A.duration, F), I, F);
      return I + 1e-9 < R && _.push({
        note: { ...d, time: I, duration: R - I, isEvalHighlightSegment: !1 },
        color: T(!1),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), R + 1e-9 < E && _.push({
        note: { ...d, time: R, duration: E - R, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
        color: T(!1, !0),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), E + 1e-9 < F && _.push({
        note: { ...d, time: E, duration: F - E, isEvalHighlightSegment: !1 },
        color: T(!1),
        fileId: u.fileId,
        isMuted: u.isMuted
      }), !0;
    }
    if (o) {
      if (a) {
        const A = p.files.find((P) => P.id === g.refId)?.parsedData?.notes || [], I = d.time, F = d.time + d.duration, R = [];
        for (const P of A) {
          if (P?.midi !== d.midi) continue;
          const N = e(Math.max(P.time, I), I, F), D = e(Math.min(P.time + P.duration, F), I, F);
          N + 1e-9 < D && R.push({ start: N, end: D });
        }
        if (R.sort((P, N) => P.start - N.start), R.length === 0)
          return _.push({
            note: { ...d, isEvalHighlightSegment: !1 },
            color: C,
            fileId: u.fileId,
            isMuted: u.isMuted
          }), !0;
        let E = I;
        for (const P of R) {
          const N = P.start, D = P.end;
          E + 1e-9 < N && _.push({
            note: { ...d, time: E, duration: N - E, isEvalHighlightSegment: !1 },
            color: C,
            fileId: u.fileId,
            isMuted: u.isMuted
          }), _.push({
            note: { ...d, time: N, duration: D - N, isEvalHighlightSegment: !0, evalSegmentKind: "intersection" },
            color: T(!1, !0),
            fileId: u.fileId,
            isMuted: u.isMuted
          }), E = Math.max(E, D);
        }
        return E + 1e-9 < F && _.push({
          note: { ...d, time: E, duration: F - E, isEvalHighlightSegment: !1 },
          color: C,
          fileId: u.fileId,
          isMuted: u.isMuted
        }), !0;
      }
      return !0;
    }
  }
  return !1;
}
function yA(n) {
  const {
    isRef: t,
    isEst: e,
    coloredNote: s,
    note: i,
    sourceIdx: r,
    fileColor: o,
    nonIntersectColor: a,
    ownHighlightColor: l,
    useGrayGlobal: c,
    isExclusive: h,
    isExclusiveGlobal: u,
    isIntersectionOwn: d,
    state: f,
    evalState: p,
    estFiles: g,
    byRef: m,
    byEst: y,
    unionRangesByRef: x,
    ambiguousByRef: v,
    ambiguousByEst: _,
    pushSegment: b,
    result: w
  } = n;
  if (t) {
    const S = (x.get(r) || []).slice(), T = i.time, k = i.time + i.duration;
    (v.get(r) || []).map((A) => ({ start: A.start, end: A.end }));
    let C = a;
    if (c)
      C = parseInt(To.replace("#", ""), 16);
    else if (u && d)
      C = ht(
        o,
        us,
        Vt
      );
    else if (g.length >= 1 && m.has(r)) {
      const A = m.get(r)[0], I = g.find((F) => F.id === A.estId);
      if (I) {
        const F = xe(I.color ?? 0), R = ht(o, us, Vt), E = ht(F, ds, Vt), P = Hs([R, E]);
        C = ht(P, 16777215, 0.2);
      }
    }
    if (S.length === 0)
      return !1;
    S.sort((A, I) => A.start - I.start);
    let M = T;
    for (const A of S) {
      const I = Math.max(T, A.start), F = Math.min(k, A.end);
      I < k && F > T && I < F && (M < I && b(
        M,
        I,
        h ? l : a,
        h ? { isEval: !0, kind: "exclusive" } : { kind: "exclusive" }
      ), b(
        Math.max(I, T),
        Math.min(F, k),
        h ? a : C,
        h ? void 0 : { isEval: !0, kind: "intersection" }
      ), M = Math.max(M, F));
    }
    return M < k && b(
      M,
      k,
      h ? l : a,
      h ? { isEval: !0, kind: "exclusive" } : { kind: "exclusive" }
    ), !0;
  }
  if (e) {
    const S = y.get(s.fileId)?.get(r);
    if (S === void 0)
      return !1;
    const T = f.files.find((E) => E.id === p.refId).parsedData.notes[S], k = T.time, C = T.time + T.duration, M = i.time, A = i.time + i.duration, I = Math.max(k, M), F = Math.min(C, A);
    let R = a;
    if (c)
      R = parseInt(To.replace("#", ""), 16);
    else if (u && d)
      R = ht(
        o,
        ds,
        Vt
      );
    else {
      const E = xe(
        f.files.find((O) => O.id === p.refId)?.color ?? 0
      ), P = o, N = ht(E, us, Vt), D = ht(P, ds, Vt), z = Hs([N, D]);
      R = ht(z, 16777215, 0.2);
    }
    if (I < F)
      M < I && b(
        M,
        I,
        h ? l : a,
        h ? { isEval: !0, kind: "exclusive" } : { kind: "exclusive" }
      ), b(
        I,
        F,
        h ? a : R,
        h ? void 0 : { isEval: !0, kind: "intersection" }
      ), F < A && b(
        F,
        A,
        h ? l : a,
        h ? { isEval: !0, kind: "exclusive" } : { kind: "exclusive" }
      );
    else
      return !1;
    return !0;
  }
  return !1;
}
class xA {
  constructor(t) {
    this.stateManager = t;
  }
  /**
   * Get evaluation-based colored notes
   */
  getEvaluationColoredNotes(t, e, s) {
    const i = this.stateManager.getState().evaluation;
    if (!i.refId || i.estIds.length === 0)
      return e;
    const r = t.files.find((b) => b.id === i.refId), o = (i.estIds || []).map((b) => t.files.find((w) => w.id === b)).filter((b) => b && b.parsedData);
    if (!r?.parsedData || o.length === 0)
      return e;
    const a = {
      onsetTolerance: i.onsetTolerance,
      pitchTolerance: i.pitchTolerance,
      offsetRatioTolerance: i.offsetRatioTolerance,
      offsetMinTolerance: i.offsetMinTolerance
    }, { byRef: l, byEst: c } = uA(r, o, a), h = dA(l, r, o), { ambiguousByRef: u, ambiguousByEst: d } = fA(r, o, l, c, a), f = [], {
      useGrayGlobal: p,
      isExclusiveGlobal: g,
      isIntersectionOwn: m,
      isTpOnly: y,
      isFpOnly: x,
      isFnOnly: v,
      isOnlyMode: _
    } = pA(s, o.length);
    if (e.forEach((b) => {
      const { note: w, fileId: S } = b, T = w.sourceIndex ?? 0, k = S === i.refId, C = i.estIds.includes(S);
      if (!k && !C) {
        _ || f.push(b);
        return;
      }
      const M = xe(
        t.files.find((P) => P.id === S)?.color ?? Me
      ), A = k ? ht(M, us, Vt) : C ? ht(M, ds, Vt) : M;
      if (mA({
        highlightMode: s,
        isRef: k,
        coloredNote: b,
        note: w,
        sourceIdx: T,
        fileColor: M,
        state: t,
        evalState: i,
        estFiles: o,
        byRef: l,
        unionRangesByRef: h,
        result: f
      }) || gA({
        isOnlyMode: _,
        isTpOnly: y,
        isFpOnly: x,
        isFnOnly: v,
        useGrayGlobal: p,
        isRef: k,
        isEst: C,
        fileColor: M,
        coloredNote: b,
        note: w,
        sourceIdx: T,
        state: t,
        evalState: i,
        estFiles: o,
        byRef: l,
        byEst: c,
        unionRangesByRef: h,
        result: f
      }))
        return;
      const I = M;
      let F;
      g ? p ? F = parseInt(To.replace("#", ""), 16) : m ? F = I : F = ht(I, hA, 0.75) : F = I;
      const R = g, E = (P, N, D, z) => {
        const O = N - P;
        O <= 0 || f.push({
          note: {
            ...w,
            time: P,
            duration: O,
            isEvalHighlightSegment: z?.isEval ?? !1,
            evalSegmentKind: z?.kind
          },
          color: D,
          fileId: b.fileId,
          isMuted: b.isMuted
        });
      };
      if (!yA({
        isRef: k,
        isEst: C,
        coloredNote: b,
        note: w,
        sourceIdx: T,
        fileColor: M,
        nonIntersectColor: F,
        ownHighlightColor: A,
        useGrayGlobal: p,
        isExclusive: R,
        isExclusiveGlobal: g,
        isIntersectionOwn: m,
        state: t,
        evalState: i,
        estFiles: o,
        byRef: l,
        byEst: c,
        unionRangesByRef: h,
        ambiguousByRef: u,
        ambiguousByEst: d,
        pushSegment: E,
        result: f
      }) && C && c.get(S)?.get(T) === void 0) {
        const D = (d.get(S).get(T) || []).map((V) => ({ start: V.start, end: V.end })), z = w.time, O = w.time + w.duration;
        if (D.length > 0) {
          const V = xe(
            t.files.find((U) => U.id === i.refId)?.color ?? Me
          ), G = ht(V, us, Vt), H = ht(M, ds, Vt);
          Hs([G, H]);
          let q;
          if (p)
            q = parseInt(rm.replace("#", ""), 16);
          else {
            const U = ht(V, us, Vt), at = ht(M, ds, Vt), At = "#" + U.toString(16).padStart(6, "0"), te = "#" + at.toString(16).padStart(6, "0"), ee = _b(At, te, "color");
            q = parseInt(ee.replace("#", ""), 16);
            const Ue = Hs([U, at]), we = ht(Ue, 16777215, 0.2), [$, J, bt] = [we >> 16 & 255, we >> 8 & 255, we & 255], pt = (Gt, pe, me) => Math.max(0, Math.min(255, Math.round(Gt))) << 16 | Math.max(0, Math.min(255, Math.round(pe))) << 8 | Math.max(0, Math.min(255, Math.round(me))), it = (Gt, pe) => {
              const me = Math.abs(Gt - pe) % 360;
              return me > 180 ? 360 - me : me;
            }, { rgbToHsv: _t, hsvToRgb: fe } = { rgbToHsv: (Gt, pe, me) => {
              const De = Math.max(Gt, pe, me), _s = De - Math.min(Gt, pe, me), Ls = _s && (De == Gt ? (pe - me) / _s : De == pe ? 2 + (me - Gt) / _s : 4 + (Gt - pe) / _s);
              return [Math.round(60 * (Ls < 0 ? Ls + 6 : Ls)), De && _s / De, De / 255];
            }, hsvToRgb: (Gt, pe, me) => {
              const De = (_s, Ls = (_s + Gt / 60) % 6) => me * 255 * (1 - pe * Math.max(0, Math.min(Ls, 4 - Ls, 1)));
              return [De(5), De(3), De(1)];
            } }, ns = (Gt) => [
              Gt >> 16 & 255,
              Gt >> 8 & 255,
              Gt & 255
            ], [sn, Ci, ga] = ns(q);
            let [nn, Ug, Gg] = _t(sn, Ci, ga);
            const [ya] = _t($, J, bt);
            if (it(nn, ya) < 55) {
              const Gt = (nn + 90) % 360, pe = (nn + 270) % 360, me = it(Gt, ya), De = it(pe, ya);
              nn = me >= De ? Gt : pe;
              const [_s, Ls, Wg] = fe(nn, Ug, Math.min(0.9, Math.max(0.55, Gg)));
              q = pt(_s, Ls, Wg);
            }
          }
          const W = D.sort((U, at) => U.start - at.start);
          let K = z;
          for (const U of W) {
            const at = Math.max(z, U.start), At = Math.min(O, U.end);
            at < At && (K < at && E(K, at, F), E(at, At, q, { isEval: !0, kind: "ambiguous" }), K = At);
          }
          K < O && E(K, O, F);
          return;
        }
        f.push({ ...b, color: F });
        return;
      }
    }), f.sort((b, w) => b.note.time - w.note.time), i.refOnTop && i.refId) {
      const b = i.refId, w = f.filter((T) => T.fileId !== b), S = f.filter((T) => T.fileId === b);
      return [...w, ...S];
    }
    return f;
  }
}
class _A {
  constructor(t, e, s) {
    this.midiManager = t, this.stateManager = e, this.visualizationEngine = s, this.evaluationHandler = new xA(e);
  }
  /**
   * Update visualization
   */
  updateVisualization() {
    if (!this.visualizationEngine?.getPianoRollInstance())
      return;
    const t = this.midiManager.getState(), e = this.getColoredNotes(t), s = t.files.filter(
      (l) => l.parsedData
    ).length, i = 1 / Math.max(1, s), r = [];
    t.files.forEach((l) => {
      l.parsedData && l.parsedData.notes.forEach((c) => {
        const h = Math.min(1, c.velocity * i);
        r.push({
          ...c,
          velocity: h,
          fileId: l.id
        });
      });
    });
    const o = [];
    t.files.forEach((l) => {
      const c = l.isSustainVisible ?? !0;
      !l.isPianoRollVisible || !c || !l.parsedData?.controlChanges || l.parsedData.controlChanges.forEach((h) => {
        h.trackId !== void 0 && !(l.trackSustainVisibility?.[h.trackId] ?? !0) || o.push({ ...h, fileId: l.id });
      });
    }), o.sort(
      (l, c) => l.time - c.time
    ), this.visualizationEngine.updateVisualization(
      e,
      r
    );
    const a = this.visualizationEngine.getPianoRollInstance();
    if (a) {
      const l = a._instance, c = {};
      t.files.forEach((d) => {
        d.color !== void 0 && (c[d.id] = typeof d.color == "number" ? d.color : parseInt(String(d.color).replace("#", ""), 16));
      }), l && (l.fileColors = c);
      const h = this.stateManager.getState().evaluation, u = {};
      if (t.files.forEach((d) => {
        const f = d.name || d.fileName || d.id, p = h?.refId === d.id, g = Array.isArray(h?.estIds) ? h.estIds.includes(d.id) : !1, m = p ? "Reference" : g ? "Comparison" : "MIDI", y = c[d.id] ?? (typeof d.color == "number" ? d.color : parseInt(String(d.color ?? 0).replace("#", ""), 16)), x = d.parsedData?.tracks?.map((v) => ({
          id: v.id,
          name: v.name
        }));
        u[d.id] = {
          name: f,
          fileName: d.fileName ?? "",
          kind: m,
          color: y,
          tracks: x
        };
      }), l && (l.fileInfoMap = u), l) {
        const d = this.stateManager.getState().visual;
        l.highlightMode = d.highlightMode, l.showOnsetMarkers = d.showOnsetMarkers;
        const f = {};
        t.files.forEach((g) => {
          const m = this.stateManager.ensureOnsetMarkerForFile(g.id);
          f[g.id] = m;
        }), l.onsetStyles = f;
        const p = {};
        t.files.forEach((g) => {
          if (!g.isPianoRollVisible || !g.parsedData?.notes) return;
          const m = g.id;
          g.parsedData.notes.forEach((y, x) => {
            p[`${m}#${x}`] = y.time;
          });
        }), l.originalOnsetMap = p, l.onlyOriginalOnsets = !0;
      }
      a.setControlChanges?.(o);
    }
  }
  /**
   * Get colored notes from MIDI state
   */
  getColoredNotes(t) {
    const e = [Me, Wn, mn], s = (g) => typeof g == "number" ? g : parseInt(g.replace("#", ""), 16), i = this.stateManager.getState().visual, r = i.highlightMode ?? "file", o = i.uniformTrackColor ?? !1, a = r === "file" && !o, l = [];
    if (t.files.forEach((g, m) => {
      if (!g.isPianoRollVisible || !g.parsedData?.notes) return;
      const y = g.color ?? e[m % e.length], x = s(y), v = g.parsedData.tracks?.length ?? 1, _ = {};
      g.parsedData.notes.forEach((b, w) => {
        const S = b.trackId;
        if (!(S === void 0 || g.trackVisibility?.[S] !== !1)) return;
        const k = S !== void 0 && g.trackMuted?.[S] === !0, C = S !== void 0 ? g.trackVolume?.[S] ?? 1 : 1, M = b.velocity * C;
        let A = x;
        a && S !== void 0 && v > 1 && (_[S] === void 0 && (_[S] = Gs.getTrackVariantColor(
          x,
          S,
          v
        )), A = _[S]), l.push({
          note: {
            ...b,
            velocity: M,
            fileId: g.id,
            sourceIndex: w
          },
          color: A,
          fileId: g.id,
          isMuted: (g.isMuted ?? !1) || k
        });
      });
    }), l.length === 0) return [];
    if (r === "file")
      return l;
    if (r.startsWith("eval-"))
      return this.evaluationHandler.getEvaluationColoredNotes(
        t,
        l,
        r
      );
    const c = lA(l), h = 4473924, u = s(nm), d = (g) => {
      switch (r) {
        case "highlight-simple":
          return ht(g, 16777113, 0.85);
        case "highlight-blend":
          return g;
        case "highlight-exclusive":
          return ht(g, u, 0.8);
        default:
          return g;
      }
    }, f = (g) => r === "highlight-exclusive" ? h : g, p = [];
    return l.forEach((g, m) => {
      const y = c.get(m) ?? [];
      if (y.length === 0) {
        p.push({ ...g, color: f(g.color) });
        return;
      }
      const x = [...y].sort((w, S) => w.start - S.start);
      let v = g.note.time;
      const _ = g.note.time + g.note.duration, b = (w, S, T) => {
        S <= 0 || p.push({
          note: { ...g.note, time: w, duration: S },
          color: T,
          fileId: g.fileId,
          isMuted: g.isMuted
        });
      };
      x.forEach(({ start: w, end: S }) => {
        b(v, w - v, f(g.color)), b(w, S - w, d(g.color)), v = Math.max(v, S);
      }), b(v, _ - v, f(g.color));
    }), p.sort((g, m) => g.note.time - m.note.time), p;
  }
  /**
   * Update piano roll time position
   */
  updatePianoRoll() {
    const t = this.visualizationEngine.getPianoRollInstance();
    t && t.setTime(
      this.visualizationEngine.getState().currentTime
    );
  }
}
class vA {
  constructor(t, e, s, i) {
    this.stateManager = t, this.visualizationEngine = e, this.midiManager = s, this.config = i, this.updateLoopId = null, this.hasSeenNonZeroTime = !1, this.lastKnownDurationSec = 0;
  }
  /**
   * Compute total duration for UI (seekbar/time labels) in raw content seconds.
   * Takes the maximum of MIDI duration and registered WAV duration.
   * Tempo/playback rate does NOT scale this value to avoid seek mismatches.
   */
  computeEffectiveDuration() {
    const t = this.visualizationEngine.getState();
    if (!t) return 0;
    const e = t.duration || 0;
    let s = 0;
    try {
      const a = (globalThis._waveRollAudio?.getFiles?.() || []).filter((l) => l?.isVisible !== !1 && l?.isMuted !== !0 && (l?.volume === void 0 || l.volume > 0)).map((l) => l.audioBuffer?.duration || 0).filter((l) => l > 0);
      s = a.length > 0 ? Math.max(...a) : 0;
    } catch {
    }
    return Math.max(e, s);
  }
  /**
   * Get UI dependencies object for UIComponents
   */
  getUIDependencies(t) {
    const e = this.stateManager.getUIState();
    this.stateManager.getState().playback;
    const s = this.stateManager.getState().loopPoints, i = this.stateManager.getFilePanValuesRef(), r = this.stateManager.getFilePanStateHandlersRef();
    if (t) {
      t.midiManager = this.midiManager, t.audioPlayer = this.visualizationEngine, t.pianoRoll = this.visualizationEngine.getPianoRollInstance(), t.stateManager = this.stateManager, t.filePanStateHandlers = r, t.filePanValues = i, t.muteDueNoLR = e.muteDueNoLR, t.lastVolumeBeforeMute = e.lastVolumeBeforeMute, t.minorTimeStep = e.minorTimeStep;
      const o = this.computeEffectiveDuration();
      o > 0 && (s.a !== null || s.b !== null) && (t.loopPoints = {
        a: s.a !== null ? s.a / o * 100 : null,
        b: s.b !== null ? s.b / o * 100 : null
      }), t.seeking = e.seeking;
    } else {
      t = {
        midiManager: this.midiManager,
        audioPlayer: this.visualizationEngine,
        pianoRoll: this.visualizationEngine.getPianoRollInstance(),
        stateManager: this.stateManager,
        filePanStateHandlers: r,
        filePanValues: i,
        muteDueNoLR: e.muteDueNoLR,
        lastVolumeBeforeMute: e.lastVolumeBeforeMute,
        minorTimeStep: e.minorTimeStep,
        loopPoints: null,
        seeking: e.seeking,
        updateSeekBar: () => this.updateSeekBar(t),
        updatePlayButton: () => this.updatePlayButton(t),
        updateMuteState: (a) => this.updateMuteState(a),
        openSettingsModal: () => this.openSettingsModal(t),
        openEvaluationResultsModal: () => this.openEvaluationResultsModal(t),
        formatTime: (a) => Cl(a),
        silenceDetector: null
      };
      const o = this.computeEffectiveDuration();
      o > 0 && (s.a !== null || s.b !== null) && (t.loopPoints = {
        a: s.a !== null ? s.a / o * 100 : null,
        b: s.b !== null ? s.b / o * 100 : null
      });
    }
    return t;
  }
  /**
   * Start the update loop for UI synchronization
   */
  startUpdateLoop(t) {
    const e = this.config.updateInterval, s = () => {
      t && (t.audioPlayer = this.visualizationEngine);
      const o = this.visualizationEngine.getState();
      if (o) {
        if ((!Number.isFinite(o.currentTime) || o.currentTime < 0) && (o.currentTime = 0), o.currentTime > 0 && (this.hasSeenNonZeroTime = !0), o.isPlaying || (this.hasSeenNonZeroTime = !1), this.updatePianoRoll(), t?.updateSeekBar) {
          const a = this.computeEffectiveDuration(), l = a > 0 ? a : this.lastKnownDurationSec > 0 ? this.lastKnownDurationSec : o.duration || 0;
          l > 0 && (this.lastKnownDurationSec = l), t.updateSeekBar({
            currentTime: o.currentTime,
            duration: l
          });
        }
        this.updateTimeDisplay(o.currentTime);
        try {
          const a = this.visualizationEngine.getZoomLevel?.() ?? 1;
          document.documentElement.style.setProperty(
            "--wr-outline-scale",
            String(Math.min(10, Math.max(0.1, a)))
          );
          const l = t?.zoomInput;
          if (l && document.activeElement !== l) {
            const c = a.toFixed(1);
            l.value !== c && (l.value = c);
          }
        } catch {
        }
      } else
        this.updateSeekBar(t), this.updateTimeDisplay();
      t?.updatePlayButton && typeof t.updatePlayButton == "function" && t.updatePlayButton();
    };
    s();
    const i = this.stateManager.getUIState().updateLoopId;
    i && clearInterval(i);
    const r = setInterval(s, e);
    this.stateManager.updateUIState({ updateLoopId: r }), this.updateLoopId = r;
  }
  /**
   * Stop update loop
   */
  stopUpdateLoop() {
    this.updateLoopId && (clearInterval(this.updateLoopId), this.updateLoopId = null);
  }
  /**
   * Update piano roll
   */
  updatePianoRoll() {
    const t = this.visualizationEngine.getState();
    if (!t?.isPlaying) {
      const e = this.visualizationEngine.getPianoRollInstance();
      e && e.setTime(t?.currentTime ?? 0);
    }
  }
  /**
   * Update seek bar
   */
  updateSeekBar(t) {
    if (!t?.updateSeekBar || typeof t.updateSeekBar != "function")
      return;
    const e = this.visualizationEngine.getState();
    if (e) {
      (!Number.isFinite(e.currentTime) || e.currentTime < 0) && (e.currentTime = 0);
      const s = this.computeEffectiveDuration(), i = s > 0 ? s : this.lastKnownDurationSec > 0 ? this.lastKnownDurationSec : e.duration || 0;
      if (i > 0 && (this.lastKnownDurationSec = i), t.updateSeekBar({
        currentTime: e.currentTime,
        duration: i
      }), !e.isPlaying) {
        const r = this.visualizationEngine.getPianoRollInstance();
        if (r) {
          const o = Number.isFinite(e.currentTime) && e.currentTime >= 0 ? e.currentTime : 0;
          r.setTime(o);
        }
      }
    } else
      t.updateSeekBar();
  }
  /**
   * Update play button
   */
  updatePlayButton(t) {
    t?.updatePlayButton?.(), t?.updateSeekBar?.();
  }
  /**
   * Update time display
   */
  updateTimeDisplay(t, e) {
    const s = t !== void 0 ? t : this.stateManager.getState().playback.currentTime;
    e && (e.textContent = Cl(s));
  }
  /**
   * Update mute state
   */
  updateMuteState(t) {
  }
  /**
   * Open settings modal
   */
  async openSettingsModal(t) {
    if (t) {
      const { openSettingsModal: e } = await Promise.resolve().then(() => Vg);
      e(t);
    }
  }
  /**
   * Open evaluation results modal
   */
  async openEvaluationResultsModal(t) {
    if (t) {
      const { openEvaluationResultsModal: e } = await import("./evaluation-results-4Bd55CsR.js");
      e(t);
    }
  }
  /**
   * Update sidebar with current files
   */
  updateSidebar(t) {
    Co.updateSidebar(t, this.midiManager);
  }
  /**
   * Update file toggle section
   */
  updateFileToggleSection(t, e) {
    t && dr.updateFileToggleSection(t, e);
  }
}
class bA {
  constructor() {
    this.isTogglingPlayback = !1, this.boundHandleKeyDown = null, this.handleKeyDown = (t, e, s) => {
      if (t.repeat) return;
      const i = t.target;
      if (i instanceof HTMLInputElement || i instanceof HTMLTextAreaElement || i instanceof HTMLSelectElement || i instanceof HTMLAnchorElement || i?.getAttribute("role") === "button" || i?.isContentEditable || !(t.code === "Space" || t.key === " ") || (t.preventDefault(), t.stopPropagation(), this.isTogglingPlayback)) return;
      this.isTogglingPlayback = !0;
      const r = e(), o = r.audioPlayer;
      if (!o) {
        this.isTogglingPlayback = !1;
        return;
      }
      if (o.getState()?.isPlaying)
        r.audioPlayer?.pause(), setTimeout(() => {
          this.isTogglingPlayback = !1;
        }, 100);
      else {
        const l = o.wavPlayerManager;
        if (l && typeof l.areAllBuffersReady == "function" && !l.areAllBuffersReady()) {
          this.isTogglingPlayback = !1;
          return;
        }
        const c = async (h, u = 2e3, d = 50) => {
          const f = Date.now();
          for (; !h() && !(Date.now() - f > u); )
            await new Promise((p) => setTimeout(p, d));
        };
        (async () => {
          try {
            try {
              await Rg();
            } catch {
            }
            await c(() => !!r.audioPlayer?.isInitialized?.()), await o.play(), s(), r.updatePlayButton?.(), r.updateSeekBar?.();
          } catch (h) {
            console.error("Failed to play:", h);
          } finally {
            setTimeout(() => {
              this.isTogglingPlayback = !1;
            }, 100);
          }
        })();
      }
    };
  }
  /**
   * Setup keyboard listener
   */
  setupKeyboardListener(t, e) {
    const s = "_waveRollSpaceHandler";
    this.boundHandleKeyDown = (r) => this.handleKeyDown(r, t, e), !Reflect.get(window, s) && this.boundHandleKeyDown && (Reflect.set(window, s, this.boundHandleKeyDown), document.addEventListener("keydown", this.boundHandleKeyDown));
  }
  /**
   * Cleanup keyboard listener
   */
  cleanup() {
    const t = "_waveRollSpaceHandler", e = Reflect.get(window, t);
    e && e === this.boundHandleKeyDown && (document.removeEventListener("keydown", e), Reflect.deleteProperty(window, t));
  }
  /**
   * Reset toggling state
   */
  resetTogglingState() {
    setTimeout(() => {
      this.isTogglingPlayback = !1;
    }, 100);
  }
}
class wA {
  constructor(t, e) {
    this.stateManager = t, this.fileManager = e;
  }
  /**
   * Load sample MIDI files
   */
  async loadSampleFiles(t = [], e) {
    this.stateManager.updateUIState({ isBatchLoading: !0 });
    const s = t.length > 0 ? t : Eg, i = s.filter((o) => !o.type || o.type === "midi"), r = s.filter((o) => o.type === "audio");
    try {
      if (i.length > 0) {
        await this.fileManager.loadSampleFiles(i);
        const o = this.fileManager.midiManager.getState();
      }
      if (r.length > 0) {
        await this.fileManager.loadSampleAudioFiles(r);
        const o = globalThis._waveRollAudio;
        if (o?.getFiles) {
          const a = o.getFiles();
        }
      }
      e?.onComplete?.();
    } catch (o) {
      console.error("Error loading sample files:", o), e?.onError?.(o);
    } finally {
      this.stateManager.updateUIState({ isBatchLoading: !1 });
    }
  }
}
class SA {
  constructor(t, e = [], s) {
    this.pianoRollManager = null, this.corePlaybackEngine = null, this.audioPlayerContainer = null, this.progressBar = null, this.seekHandle = null, this.currentTimeLabel = null, this.totalTimeLabel = null, this.seekBarContainer = null, this.loopRegion = null, this.markerA = null, this.markerB = null, this.progressIndicator = null, this.markerATimeLabel = null, this.markerBTimeLabel = null, this.zoomInput = null, this.fileToggleContainer = null, this.initialFileItemList = [], this.uiDeps = null, this.pausedBySilence = !1, this.lastHookedAudioPlayer = null, this.audioVisualHooked = !1, this.permissions = {
      canAddFiles: !0,
      canRemoveFiles: !0
    }, this.soloMode = !1, this.pianoRollConfigOverrides = {}, this.fileAddRequestCallback = null, this.audioFileAddRequestCallback = null, this.allowFileDrop = !0, this.container = t, this.midiManager = new i1(), this.initialFileItemList = e, globalThis._waveRollMidiManager = this.midiManager, s?.soloMode && (this.soloMode = !0, this.pianoRollConfigOverrides.showWaveformBand = !1, this.pianoRollConfigOverrides.backgroundColor = 16777215), s?.midiExport && (this.midiExportOptions = s.midiExport), s?.pianoRoll && (this.pianoRollConfigOverrides = {
      ...this.pianoRollConfigOverrides,
      ...s.pianoRoll
    }), s?.allowFileDrop !== void 0 && (this.allowFileDrop = s.allowFileDrop), this.defaultHighlightMode = s?.defaultHighlightMode, this.config = l1(), k2(), this.createUIContainers(), this.initializeModules();
  }
  // Compute effective UI duration considering tempo and WAV length
  getEffectiveDuration() {
    try {
      const t = this.visualizationEngine.getState(), s = (t.playbackRate ?? 100) / 100, i = t.duration || 0;
      let r = 0;
      try {
        const c = (globalThis._waveRollAudio?.getFiles?.() || []).map((h) => h.audioBuffer?.duration || 0).filter((h) => h > 0);
        r = c.length > 0 ? Math.max(...c) : 0;
      } catch {
      }
      const o = Math.max(i, r);
      return s > 0 ? o / s : o;
    } catch {
      return 0;
    }
  }
  /**
   * Create default configuration
   */
  /**
   * Create UI containers
   */
  createUIContainers() {
    this.mainContainer = document.createElement("div"), this.sidebarContainer = document.createElement("div"), this.playerContainer = document.createElement("div"), this.controlsContainer = document.createElement("div"), this.timeDisplay = document.createElement("div"), this.pianoRollContainer = document.createElement("div");
  }
  /**
   * Initialize all modules
   */
  initializeModules() {
    this.stateManager = new d2(), this.defaultHighlightMode && this.stateManager.updateVisualState({
      highlightMode: this.defaultHighlightMode
    }), this.fileManager = new _2(this.midiManager, this.stateManager);
    const t = {
      ...Dh,
      ...this.config.pianoRoll,
      ...this.pianoRollConfigOverrides
    };
    this.visualizationEngine = new QC({
      defaultPianoRollConfig: t,
      updateInterval: this.config.ui.updateInterval,
      // Sync interval
      enableOverlapDetection: !1
      // We handle overlap coloring manually
    }), this.visualizationEngine.onVisualUpdate(
      ({ currentTime: s, duration: i, isPlaying: r }) => {
        const o = this.getUIDependencies(), a = this.getEffectiveDuration();
        o.updateSeekBar?.({ currentTime: s, duration: a }), this.updateTimeDisplay(s);
        try {
          const c = this.visualizationEngine.coreEngine?.audioPlayer;
          c && c !== this.lastHookedAudioPlayer && typeof c.setOnVisualUpdate == "function" && (c.setOnVisualUpdate(
            ({
              currentTime: h
            }) => {
              const u = this.getUIDependencies(), d = this.getEffectiveDuration();
              u.updateSeekBar?.({ currentTime: h, duration: d }), this.updateTimeDisplay(h);
            }
          ), this.lastHookedAudioPlayer = c);
        } catch {
        }
      }
    ), this.pianoRollManager = Ag(), this.pianoRollManager.initialize(this.pianoRollContainer, []), this.silenceDetector = new $l({
      autoResumeOnUnmute: !1,
      onSilenceDetected: () => {
        this.visualizationEngine.getState().isPlaying && (this.pausedBySilence = !0, this.visualizationEngine.pause(), this.updatePlayButton());
      },
      onSoundDetected: () => {
        this.pausedBySilence = !1;
      }
    }), this.silenceDetector.attachMidiManager(this.midiManager), this.visualizationHandler = new _A(
      this.midiManager,
      this.stateManager,
      this.visualizationEngine
    ), this.uiUpdater = new vA(
      this.stateManager,
      this.visualizationEngine,
      this.midiManager,
      { updateInterval: this.config.ui.updateInterval }
    ), this.keyboardHandler = new bA(), this.fileLoader = new wA(this.stateManager, this.fileManager), this.keyboardHandler.setupKeyboardListener(
      () => this.getUIDependencies(),
      () => this.startUpdateLoop()
    );
    const e = /* @__PURE__ */ new Map();
    this.midiManager.setOnStateChange(() => {
      if (this.stateManager.getUIState().isBatchLoading) return;
      this.midiManager.getState().files.forEach((i) => {
        const r = e.get(i.id) || !1, o = i.isMuted || !1;
        r !== o && (this.visualizationEngine.setFileMute(i.id, o), e.set(i.id, o));
      }), this.silenceDetector && this.silenceDetector.checkSilence(this.midiManager), this.updateVisualization(), this.updateSidebar(), this.updateFileToggleSection();
    }), this.stateManager.onStateChange(() => {
      this.stateManager.getUIState().isBatchLoading || (this.updateVisualization(), this.updateSidebar(), this.updateFileToggleSection());
    });
  }
  /**
   * Get UI dependencies object for UIComponents
   */
  getUIDependencies() {
    const t = this.stateManager.getUIState();
    this.stateManager.getState().playback;
    const e = this.stateManager.getState().loopPoints;
    this.stateManager.getState().panVolume;
    const s = this.stateManager.getFilePanValuesRef(), i = this.stateManager.getFilePanStateHandlersRef();
    if (this.uiDeps) {
      this.uiDeps.midiManager = this.midiManager, this.uiDeps.audioPlayer = this.visualizationEngine, this.uiDeps.pianoRoll = this.visualizationEngine.getPianoRollInstance(), this.uiDeps.stateManager = this.stateManager, this.uiDeps.filePanStateHandlers = i, this.uiDeps.filePanValues = s, this.uiDeps.muteDueNoLR = t.muteDueNoLR, this.uiDeps.lastVolumeBeforeMute = t.lastVolumeBeforeMute, this.uiDeps.minorTimeStep = t.minorTimeStep;
      const r = this.getEffectiveDuration();
      r > 0 && (e.a !== null || e.b !== null) && (this.uiDeps.loopPoints = {
        a: e.a !== null ? e.a / r * 100 : null,
        b: e.b !== null ? e.b / r * 100 : null
      }), this.uiDeps.seeking = t.seeking, this.uiDeps.permissions = { ...this.permissions };
    } else {
      this.uiDeps = {
        midiManager: this.midiManager,
        // Use VisualizationEngine itself as the audio player proxy so that
        // keyboard shortcuts (Space bar), seek-bar, and other controls
        // interact with the actual underlying AudioPlayer instance managed
        // by the engine. This prevents “Audio player not initialized” errors
        // that occurred when the controls referenced the bare AudioController
        // before it had created its internal AudioPlayer.
        audioPlayer: this.visualizationEngine,
        pianoRoll: this.visualizationEngine.getPianoRollInstance(),
        stateManager: this.stateManager,
        filePanStateHandlers: i,
        filePanValues: s,
        muteDueNoLR: t.muteDueNoLR,
        lastVolumeBeforeMute: t.lastVolumeBeforeMute,
        minorTimeStep: t.minorTimeStep,
        loopPoints: null,
        seeking: t.seeking,
        updateSeekBar: () => this.updateSeekBar(),
        updatePlayButton: () => this.updatePlayButton(),
        updateMuteState: (o) => this.updateMuteState(o),
        openSettingsModal: () => this.openSettingsModal(),
        openEvaluationResultsModal: () => this.openEvaluationResultsModal(),
        formatTime: (o) => Cl(o),
        silenceDetector: this.silenceDetector,
        permissions: { ...this.permissions },
        soloMode: this.soloMode,
        midiExport: this.midiExportOptions,
        allowFileDrop: this.allowFileDrop,
        onFileAddRequest: this.fileAddRequestCallback ? () => this.triggerFileAddRequest() : void 0,
        onAudioFileAddRequest: this.audioFileAddRequestCallback ? () => this.triggerAudioFileAddRequest() : void 0,
        addFileFromData: (o, a) => this.addFileFromData(o, a)
      };
      const r = this.getEffectiveDuration();
      r > 0 && (e.a !== null || e.b !== null) && (this.uiDeps.loopPoints = {
        a: e.a !== null ? e.a / r * 100 : null,
        b: e.b !== null ? e.b / r * 100 : null
      });
    }
    return this.uiDeps;
  }
  /**
   * Get UI elements object for UIComponents
   */
  getUIElements() {
    return {
      mainContainer: this.mainContainer,
      sidebarContainer: this.sidebarContainer,
      playerContainer: this.playerContainer,
      controlsContainer: this.controlsContainer,
      timeDisplay: this.timeDisplay,
      progressBar: this.progressBar,
      seekHandle: this.seekHandle,
      currentTimeLabel: this.currentTimeLabel,
      totalTimeLabel: this.totalTimeLabel,
      seekBarContainer: this.seekBarContainer,
      loopRegion: this.loopRegion,
      markerA: this.markerA,
      markerB: this.markerB,
      progressIndicator: this.progressIndicator,
      markerATimeLabel: this.markerATimeLabel,
      markerBTimeLabel: this.markerBTimeLabel,
      zoomInput: this.zoomInput,
      fileToggleContainer: this.fileToggleContainer
    };
  }
  /**
   * Initialize the demo
   */
  async initialize() {
    const t = this.getUIElements();
    a1(
      this.container,
      t,
      this.getUIDependencies(),
      this.pianoRollContainer
    ), await this.visualizationEngine.initializePianoRoll(
      this.pianoRollContainer,
      [],
      this.config.pianoRoll
    );
    const e = this.getUIDependencies();
    eA(
      t.controlsContainer,
      t.playerContainer,
      e
    ), t.controlsContainer.addEventListener(
      "wr-loop-update",
      (i) => {
        const { loopWindow: r } = i.detail, o = r ? { a: r.prev, b: r.next } : null, a = this.getUIDependencies();
        a.loopPoints = o;
        try {
          const u = this.getEffectiveDuration();
          if (!o)
            this.stateManager.setLoopPoints(null, null);
          else {
            const d = o.a !== null && u > 0 ? o.a / 100 * u : null, f = o.b !== null && u > 0 ? o.b / 100 * u : null;
            this.stateManager.setLoopPoints(d, f);
          }
        } catch {
        }
        const l = this.getEffectiveDuration(), c = o?.a, h = c != null && l > 0 ? c / 100 * l : this.visualizationEngine.getState().currentTime;
        a.updateSeekBar?.({
          currentTime: h,
          duration: l
        });
      }
    ), this.soloMode || (this.fileToggleContainer = c1(
      t.playerContainer,
      e
    ), t.fileToggleContainer = this.fileToggleContainer), this.initialFileItemList.length > 0 ? (await this.loadSampleFiles(this.initialFileItemList), this.updateSidebar(), this.updateFileToggleSection()) : (this.updateSidebar(), this.updateFileToggleSection());
    const s = this.midiManager.getState().files;
    s.length >= 2 && ({ ...Bg }, s[0].parsedData, s[1].parsedData), this.startUpdateLoop();
  }
  /**
   * Set up the sidebar
   */
  setupSidebar() {
    Co.setupSidebar(
      this.sidebarContainer,
      this.getUIDependencies()
    );
  }
  /**
   * Update sidebar with current files
   */
  updateSidebar() {
    this.uiUpdater.updateSidebar(this.sidebarContainer);
  }
  /**
   * Load sample MIDI files
   */
  async loadSampleFiles(t = []) {
    await this.fileLoader.loadSampleFiles(t, {
      onComplete: () => {
        this.updateVisualization(), this.updateSidebar(), this.updateFileToggleSection(), this.silenceDetector && this.silenceDetector.checkSilence(this.midiManager);
        try {
          const s = this.visualizationEngine.coreEngine?.audioPlayer;
          s && typeof s.setOnVisualUpdate == "function" && s.setOnVisualUpdate(
            ({
              currentTime: i
            }) => {
              const r = this.getEffectiveDuration();
              this.getUIDependencies().updateSeekBar?.({
                currentTime: i,
                duration: r
              }), this.updateTimeDisplay(i);
            }
          );
        } catch {
        }
        setTimeout(() => {
          const e = this.getEffectiveDuration(), s = this.visualizationEngine.getState().currentTime;
          this.getUIDependencies().updateSeekBar?.({ currentTime: s, duration: e });
        }, 100);
      }
    });
  }
  /**
   * Update visualization
   */
  updateVisualization() {
    this.visualizationHandler && this.visualizationHandler.updateVisualization();
  }
  /**
   * Set up file toggle section
   */
  setupFileToggleSection() {
    this.fileToggleContainer = dr.setupFileToggleSection(
      this.playerContainer,
      this.getUIDependencies()
    );
  }
  /**
   * Update file toggle section
   */
  updateFileToggleSection() {
    this.uiUpdater.updateFileToggleSection(
      this.fileToggleContainer,
      this.getUIDependencies()
    );
  }
  /**
   * Start the update loop for UI synchronization
   */
  startUpdateLoop() {
    this.uiUpdater.startUpdateLoop(this.uiDeps);
  }
  /**
   * Update seek bar
   */
  updateSeekBar() {
    this.uiUpdater.updateSeekBar(this.uiDeps);
  }
  /**
   * Update play button
   */
  updatePlayButton() {
    const t = this.getUIDependencies();
    this.uiUpdater.updatePlayButton(t), this.keyboardHandler.resetTogglingState();
  }
  /**
   * Update time display
   */
  updateTimeDisplay(t) {
    this.uiUpdater.updateTimeDisplay(t, this.timeDisplay);
  }
  /**
   * Update mute state
   */
  updateMuteState(t) {
  }
  /**
   * Open settings modal
   */
  async openSettingsModal() {
    const t = this.getUIDependencies();
    t && (await Promise.resolve().then(() => Vg)).openSettingsModal(t);
  }
  /**
   * Open evaluation results modal
   */
  async openEvaluationResultsModal() {
    const t = this.getUIDependencies();
    t && (await import("./evaluation-results-4Bd55CsR.js")).openEvaluationResultsModal(t);
  }
  /**
   * Cleanup resources
   */
  dispose() {
    const t = this.stateManager.getUIState();
    t.updateLoopId && clearInterval(t.updateLoopId), this.keyboardHandler.cleanup(), this.visualizationEngine.destroy();
  }
  // --- Public control API (used by Web Component/tests) ---
  async play() {
    await this.visualizationEngine.play(), this.updatePlayButton();
  }
  pause() {
    this.visualizationEngine.pause(), this.updatePlayButton();
  }
  get isPlaying() {
    try {
      return !!this.visualizationEngine.getState().isPlaying;
    } catch {
      return !1;
    }
  }
  /**
   * Seek to a specific time position
   */
  seek(t) {
    this.visualizationEngine.seek(t, !0);
  }
  /**
   * Update UI permissions at runtime (e.g., readonly mode)
   */
  setPermissions(t) {
    this.permissions = { ...this.permissions, ...t }, this.uiDeps && (this.uiDeps.permissions = { ...this.permissions });
    try {
      this.updateSidebar(), this.updateFileToggleSection();
    } catch {
    }
  }
  // --- Appearance API (for solo mode / external integrations) ---
  /**
   * Set the active color palette by ID.
   * This will reassign colors to all loaded files.
   */
  setActivePalette(t) {
    this.midiManager.setActivePalette(t);
  }
  /**
   * Get the list of available color palettes (built-in + custom).
   */
  getAvailablePalettes() {
    const t = this.midiManager.getState();
    return [...Cs, ...t.customPalettes];
  }
  /**
   * Get the currently active palette ID.
   */
  getActivePaletteId() {
    return this.midiManager.getState().activePaletteId;
  }
  /**
   * Set the note color for the first loaded file (useful in solo mode).
   * @param color - Hex color as number (e.g., 0x4e79a7)
   */
  setNoteColor(t) {
    const e = this.midiManager.getState().files;
    e.length > 0 && this.midiManager.updateColor(e[0].id, t);
  }
  /**
   * Get the note color of the first loaded file.
   * @returns Color as hex number, or 0x666666 if no file is loaded.
   */
  getNoteColor() {
    const t = this.midiManager.getState().files;
    return t.length > 0 ? t[0].color : 6710886;
  }
  /**
   * Set the onset marker style for the first loaded file.
   */
  setOnsetMarkerStyle(t) {
    const e = this.midiManager.getState().files;
    e.length > 0 && this.stateManager.setOnsetMarkerForFile(e[0].id, t);
  }
  /**
   * Get the onset marker style for the first loaded file.
   */
  getOnsetMarkerStyle() {
    const t = this.midiManager.getState().files;
    return t.length > 0 && this.stateManager.getOnsetMarkerForFile(t[0].id) || null;
  }
  /**
   * Get the list of available onset marker shapes.
   */
  getAvailableOnsetMarkerShapes() {
    return [...as];
  }
  /**
   * Get current appearance settings (for persistence).
   */
  getAppearanceSettings() {
    const t = this.getActivePaletteId(), e = this.getNoteColor(), s = this.getOnsetMarkerStyle();
    return {
      paletteId: t,
      noteColor: e,
      onsetMarker: s ? {
        shape: s.shape,
        variant: s.variant
      } : void 0
    };
  }
  /**
   * Apply appearance settings (for restoration from persistence).
   */
  applyAppearanceSettings(t) {
    if (t.paletteId && this.setActivePalette(t.paletteId), t.noteColor !== void 0 && this.setNoteColor(t.noteColor), t.onsetMarker) {
      const e = {
        shape: t.onsetMarker.shape,
        variant: t.onsetMarker.variant,
        size: 12,
        strokeWidth: 2
      };
      this.setOnsetMarkerStyle(e);
    }
  }
  /**
   * Subscribe to appearance changes.
   * Returns an unsubscribe function.
   */
  onAppearanceChange(t) {
    const e = this.midiManager.subscribe(() => {
      t(this.getAppearanceSettings());
    }), s = () => {
      t(this.getAppearanceSettings());
    };
    return this.stateManager.onStateChange(s), () => {
      e(), this.stateManager.offStateChange(s);
    };
  }
  // --- File Add API (for VS Code integration) ---
  /**
   * Register a callback to be invoked when the user clicks "Add Files" button.
   * This allows VS Code extension to intercept the file add request and show
   * a native file dialog instead of relying on HTML5 file input.
   * Returns an unsubscribe function.
   */
  onFileAddRequest(t) {
    return this.fileAddRequestCallback = t, () => {
      this.fileAddRequestCallback = null;
    };
  }
  /**
   * Check if there's a file add request callback registered.
   * Used by UI components to decide whether to trigger callback or use default behavior.
   */
  hasFileAddRequestCallback() {
    return this.fileAddRequestCallback !== null;
  }
  /**
   * Trigger the file add request callback (called by UI components).
   */
  triggerFileAddRequest() {
    this.fileAddRequestCallback && this.fileAddRequestCallback();
  }
  /**
   * Register a callback to be invoked when the user clicks "Add Audio File" button.
   * This allows VS Code extension to intercept the audio file add request and show
   * a native file dialog with audio file filters.
   * Returns an unsubscribe function.
   */
  onAudioFileAddRequest(t) {
    return this.audioFileAddRequestCallback = t, () => {
      this.audioFileAddRequestCallback = null;
    };
  }
  /**
   * Trigger the audio file add request callback (called by UI components).
   */
  triggerAudioFileAddRequest() {
    this.audioFileAddRequestCallback && this.audioFileAddRequestCallback();
  }
  /**
   * Add a file from raw data (ArrayBuffer or Base64 string).
   * This is useful for VS Code integration where files are passed via postMessage.
   * @param data - File data as ArrayBuffer or Base64 string
   * @param filename - Original filename (used to determine file type)
   */
  async addFileFromData(t, e) {
    const s = [".mid", ".midi"], i = [".wav", ".mp3", ".m4a", ".ogg"], r = e.toLowerCase().match(/\.[^.]+$/)?.[0] || "";
    let o;
    if (typeof t == "string") {
      const a = atob(t), l = new Uint8Array(a.length);
      for (let c = 0; c < a.length; c++)
        l[c] = a.charCodeAt(c);
      o = l.buffer;
    } else
      o = t;
    if (s.includes(r))
      try {
        const a = new Blob([o], { type: "audio/midi" }), l = new File([a], e, { type: "audio/midi" }), { parseMidi: c } = await Promise.resolve().then(() => s1), h = this.stateManager?.getState(), u = h?.visual.pedalElongate ?? !0, d = h?.visual.pedalThreshold ?? 64, f = await c(l, {
          applyPedalElongate: u,
          pedalThreshold: d
        }), p = typeof globalThis.acquireVsCodeApi == "function", g = this.midiManager.addMidiFile(
          e,
          f,
          // Keep file extension visible for VS Code integration
          e,
          l
        );
        p && this.midiManager.updateName(g, e);
      } catch (a) {
        throw console.error("Failed to parse MIDI:", a), a;
      }
    else if (i.includes(r))
      try {
        const a = new Blob([o], { type: `audio/${r.slice(1)}` }), l = URL.createObjectURL(a), { addAudioFileFromUrl: c } = await Promise.resolve().then(() => p2);
        await c(null, l, e);
      } catch (a) {
        throw console.error("Failed to load audio file:", a), a;
      }
    else
      throw new Error(`Unsupported file type: ${r}`);
    this.updateVisualization(), this.updateSidebar(), this.updateFileToggleSection();
  }
}
async function TA(n, t = [], e) {
  const s = new SA(n, t, e);
  return await s.initialize(), s;
}
class MA extends HTMLElement {
  constructor() {
    super(), this.player = null, this.container = null, this.attachShadow({ mode: "open" });
  }
  connectedCallback() {
    this.render(), this.initializePlayer();
  }
  disconnectedCallback() {
    this.player && typeof this.player.destroy == "function" && this.player.destroy();
  }
  static get observedAttributes() {
    return ["files", "readonly"];
  }
  attributeChangedCallback(t, e, s) {
    if (t === "files" && e !== s) {
      this.initializePlayer();
      return;
    }
    if (t === "readonly" && this.player && e !== s) {
      const i = typeof this.hasAttribute == "function" ? this.hasAttribute("readonly") : !!s;
      try {
        this.player.setPermissions?.({ canAddFiles: !i, canRemoveFiles: !i });
      } catch {
      }
    }
  }
  render() {
    if (!this.shadowRoot) return;
    const t = document.createElement("style");
    t.textContent = `
      :host {
        display: block;
        width: 100%;
        height: 100%;
      }
      .wave-roll-container {
        width: 100%;
        height: 100%;
        position: relative;
      }
    `, this.container = document.createElement("div"), this.container.className = "wave-roll-container", this.shadowRoot.innerHTML = "", this.shadowRoot.appendChild(t), this.shadowRoot.appendChild(this.container);
  }
  async initializePlayer() {
    if (!this.container) return;
    this.player && (typeof this.player.destroy == "function" && this.player.destroy(), this.player = null);
    const t = this.getAttribute("files");
    let e = [];
    if (t)
      try {
        e = JSON.parse(t);
      } catch (s) {
        console.error("Invalid files attribute:", s);
        return;
      }
    try {
      const s = (Array.isArray(e) ? e : []).map((i) => {
        const r = { path: i.path };
        return typeof i?.name == "string" && (r.name = i.name), i && typeof i.type == "string" && (r.type = i.type), i && typeof i.color < "u" && (r.color = i.color), r;
      });
      this.player = await TA(this.container, s), (typeof this.hasAttribute != "function" || this.hasAttribute("readonly")) && this.player.setPermissions?.({ canAddFiles: !1, canRemoveFiles: !1 }), this.dispatchEvent(new Event("load"));
    } catch (s) {
      console.error("Failed to initialize WaveRoll player:", s);
    }
  }
  // Expose minimal control API for tests/integration
  async play() {
    this.player?.play && await this.player.play();
  }
  pause() {
    this.player?.pause && this.player.pause();
  }
  get isPlaying() {
    return !!this.player?.isPlaying;
  }
  /**
   * Seek to a specific time (seconds).
   * Provided for E2E/manual testing via index.html.
   */
  seek(t) {
    try {
      if (typeof this.player?.seek == "function") {
        this.player.seek(t);
        return;
      }
      this.player?.visualizationEngine?.seek?.(t, !0);
    } catch (e) {
      console.error("WaveRollElement.seek failed:", e);
    }
  }
  /**
   * Return lightweight state for assertions in tests.
   */
  getState() {
    try {
      return typeof this.player?.getState == "function" ? this.player.getState() : this.player?.visualizationEngine?.getState?.();
    } catch (t) {
      return console.error("WaveRollElement.getState failed:", t), null;
    }
  }
}
customElements.get("wave-roll") || customElements.define("wave-roll", MA);
export {
  Uf as $,
  bp as A,
  ge as B,
  Te as C,
  Ae as D,
  dt as E,
  Ye as F,
  Yo as G,
  Oy as H,
  Kh as I,
  wn as J,
  a0 as K,
  g0 as L,
  nt as M,
  Ot as N,
  Dt as O,
  se as P,
  D0 as Q,
  dl as R,
  Q0 as S,
  Ur as T,
  cl as U,
  Jh as V,
  Ca as W,
  tu as X,
  Vy as Y,
  mo as Z,
  Bt as _,
  ps as a,
  wp as a0,
  ct as a1,
  kt as a2,
  B0 as a3,
  lx as a4,
  ex as a5,
  Cx as a6,
  Ex as a7,
  Dx as a8,
  Nx as a9,
  Lx as aa,
  kp as ab,
  Bn as ac,
  go as ad,
  Uu as ae,
  Hp as af,
  pn as ag,
  Lp as ah,
  yu as ai,
  mu as aj,
  ie as ak,
  ry as al,
  ju as am,
  zp as an,
  Eb as ao,
  TA as ap,
  SA as aq,
  Cs as ar,
  as,
  aA as at,
  Bg as au,
  MA as av,
  Ji as b,
  ao as c,
  Zl as d,
  ze as e,
  gu as f,
  Y0 as g,
  xp as h,
  Qf as i,
  Je as j,
  fp as k,
  zu as l,
  kx as m,
  Ax as n,
  Fx as o,
  sE as p,
  Ox as q,
  xy as r,
  Kl as s,
  rt as t,
  cp as u,
  iy as v,
  Ht as w,
  Bx as x,
  Ms as y,
  Bf as z
};