@tsparticles/engine 3.8.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -197,6 +197,9 @@ export class Canvas {
197
197
  this._safeMutationObserver(observer => observer.disconnect());
198
198
  this._initStyle();
199
199
  this.initBackground();
200
+ const pointerEvents = this._pointerEvents;
201
+ element.style.pointerEvents = pointerEvents;
202
+ element.setAttribute("pointer-events", pointerEvents);
200
203
  this._safeMutationObserver(observer => {
201
204
  if (!element || !(element instanceof Node)) {
202
205
  return;
@@ -240,6 +243,7 @@ export class Canvas {
240
243
  this._postDrawUpdaters = [];
241
244
  this._resizePlugins = [];
242
245
  this._colorPlugins = [];
246
+ this._pointerEvents = "none";
243
247
  }
244
248
  get _fullScreen() {
245
249
  return this.container.actualOptions.fullScreen.enable;
@@ -491,6 +495,14 @@ export class Canvas {
491
495
  }
492
496
  return true;
493
497
  }
498
+ setPointerEvents(type) {
499
+ const element = this.element;
500
+ if (!element) {
501
+ return;
502
+ }
503
+ this._pointerEvents = type;
504
+ this._repairStyle();
505
+ }
494
506
  stop() {
495
507
  this._safeMutationObserver(obs => obs.disconnect());
496
508
  this._mutationObserver = undefined;
@@ -96,7 +96,7 @@ export class Engine {
96
96
  return this._domArray;
97
97
  }
98
98
  get version() {
99
- return "3.8.0";
99
+ return "3.9.0";
100
100
  }
101
101
  async addColorManager(manager, refresh = true) {
102
102
  this.colorManagers.set(manager.key, manager);
@@ -241,8 +241,7 @@ export class Engine {
241
241
  return item;
242
242
  }
243
243
  async load(params) {
244
- const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options;
245
- const currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container(this, id, currentOptions);
244
+ const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container(this, id, currentOptions);
246
245
  if (oldIndex >= loadMinIndex) {
247
246
  const old = this.item(oldIndex), deleteCount = old ? one : none;
248
247
  if (old && !old.destroyed) {
@@ -246,11 +246,11 @@ export class Particle {
246
246
  }
247
247
  if (this.effect === randomColorValue) {
248
248
  const availableEffects = [...this.container.effectDrawers.keys()];
249
- this.effect = availableEffects[Math.floor(Math.random() * availableEffects.length)];
249
+ this.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
250
250
  }
251
251
  if (this.shape === randomColorValue) {
252
252
  const availableShapes = [...this.container.shapeDrawers.keys()];
253
- this.shape = availableShapes[Math.floor(Math.random() * availableShapes.length)];
253
+ this.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
254
254
  }
255
255
  this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
256
256
  this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
@@ -1,4 +1,4 @@
1
- import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, errorPrefix, lengthOffset, manualCount, minCount, minIndex, minLimit, posOffset, qTreeCapacity, sizeFactor, squareExp, } from "./Utils/Constants.js";
1
+ import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, errorPrefix, lengthOffset, minCount, minIndex, minLimit, posOffset, qTreeCapacity, sizeFactor, squareExp, } from "./Utils/Constants.js";
2
2
  import { getLogger, getPosition } from "../Utils/Utils.js";
3
3
  import { EventType } from "../Enums/Types/EventType.js";
4
4
  import { InteractionManager } from "./Utils/InteractionManager.js";
@@ -16,14 +16,14 @@ export class Particles {
16
16
  this._addToPool = (...particles) => {
17
17
  this._pool.push(...particles);
18
18
  };
19
- this._applyDensity = (options, manualCount, group) => {
19
+ this._applyDensity = (options, manualCount, group, groupOptions) => {
20
20
  const numberOptions = options.number;
21
21
  if (!options.number.density?.enable) {
22
22
  if (group === undefined) {
23
23
  this._limit = numberOptions.limit.value;
24
24
  }
25
- else if (numberOptions.limit) {
26
- this._groupLimits.set(group, numberOptions.limit.value);
25
+ else if (groupOptions?.number.limit?.value ?? numberOptions.limit.value) {
26
+ this._groupLimits.set(group, groupOptions?.number.limit?.value ?? numberOptions.limit.value);
27
27
  }
28
28
  return;
29
29
  }
@@ -241,11 +241,11 @@ export class Particles {
241
241
  this.removeAt(minIndex, quantity, group);
242
242
  }
243
243
  setDensity() {
244
- const options = this._container.actualOptions, groups = options.particles.groups;
244
+ const options = this._container.actualOptions, groups = options.particles.groups, manualCount = options.manualParticles.length;
245
245
  for (const group in groups) {
246
246
  this._applyDensity(groups[group], manualCount, group);
247
247
  }
248
- this._applyDensity(options.particles, options.manualParticles.length);
248
+ this._applyDensity(options.particles, manualCount);
249
249
  }
250
250
  setLastZIndex(zIndex) {
251
251
  this._lastZIndex = zIndex;
@@ -9,7 +9,7 @@ export class Retina {
9
9
  }
10
10
  init() {
11
11
  const container = this.container, options = container.actualOptions;
12
- this.pixelRatio = !options.detectRetina || isSsr() ? defaultRatio : window.devicePixelRatio;
12
+ this.pixelRatio = !options.detectRetina || isSsr() ? defaultRatio : devicePixelRatio;
13
13
  this.reduceFactor = defaultReduceFactor;
14
14
  const ratio = this.pixelRatio, canvas = container.canvas;
15
15
  if (canvas.element) {
@@ -79,10 +79,8 @@ export class EventListeners {
79
79
  if (!interactivityEl) {
80
80
  return;
81
81
  }
82
- const html = interactivityEl, canvasEl = container.canvas.element;
83
- if (canvasEl) {
84
- canvasEl.style.pointerEvents = html === canvasEl ? "initial" : "none";
85
- }
82
+ const html = interactivityEl, canvas = container.canvas;
83
+ canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
86
84
  if (!(options.interactivity.events.onHover.enable || options.interactivity.events.onClick.enable)) {
87
85
  return;
88
86
  }
@@ -459,6 +459,7 @@ function computeFullScreenStyle(zIndex) {
459
459
  borderWidth: "0",
460
460
  position: "fixed",
461
461
  zIndex: zIndex.toString(radix),
462
+ "z-index": zIndex.toString(radix),
462
463
  top: "0",
463
464
  left: "0",
464
465
  };
@@ -200,6 +200,9 @@ class Canvas {
200
200
  this._safeMutationObserver(observer => observer.disconnect());
201
201
  this._initStyle();
202
202
  this.initBackground();
203
+ const pointerEvents = this._pointerEvents;
204
+ element.style.pointerEvents = pointerEvents;
205
+ element.setAttribute("pointer-events", pointerEvents);
203
206
  this._safeMutationObserver(observer => {
204
207
  if (!element || !(element instanceof Node)) {
205
208
  return;
@@ -243,6 +246,7 @@ class Canvas {
243
246
  this._postDrawUpdaters = [];
244
247
  this._resizePlugins = [];
245
248
  this._colorPlugins = [];
249
+ this._pointerEvents = "none";
246
250
  }
247
251
  get _fullScreen() {
248
252
  return this.container.actualOptions.fullScreen.enable;
@@ -494,6 +498,14 @@ class Canvas {
494
498
  }
495
499
  return true;
496
500
  }
501
+ setPointerEvents(type) {
502
+ const element = this.element;
503
+ if (!element) {
504
+ return;
505
+ }
506
+ this._pointerEvents = type;
507
+ this._repairStyle();
508
+ }
497
509
  stop() {
498
510
  this._safeMutationObserver(obs => obs.disconnect());
499
511
  this._mutationObserver = undefined;
@@ -99,7 +99,7 @@ class Engine {
99
99
  return this._domArray;
100
100
  }
101
101
  get version() {
102
- return "3.8.0";
102
+ return "3.9.0";
103
103
  }
104
104
  async addColorManager(manager, refresh = true) {
105
105
  this.colorManagers.set(manager.key, manager);
@@ -244,8 +244,7 @@ class Engine {
244
244
  return item;
245
245
  }
246
246
  async load(params) {
247
- const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor((0, NumberUtils_js_1.getRandom)() * Constants_js_1.loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options;
248
- const currentOptions = (0, Utils_js_1.itemFromSingleOrMultiple)(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container_js_1.Container(this, id, currentOptions);
247
+ const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor((0, NumberUtils_js_1.getRandom)() * Constants_js_1.loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = (0, Utils_js_1.itemFromSingleOrMultiple)(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container_js_1.Container(this, id, currentOptions);
249
248
  if (oldIndex >= Constants_js_1.loadMinIndex) {
250
249
  const old = this.item(oldIndex), deleteCount = old ? Constants_js_1.one : Constants_js_1.none;
251
250
  if (old && !old.destroyed) {
@@ -249,11 +249,11 @@ class Particle {
249
249
  }
250
250
  if (this.effect === Constants_js_1.randomColorValue) {
251
251
  const availableEffects = [...this.container.effectDrawers.keys()];
252
- this.effect = availableEffects[Math.floor(Math.random() * availableEffects.length)];
252
+ this.effect = availableEffects[Math.floor((0, NumberUtils_js_1.getRandom)() * availableEffects.length)];
253
253
  }
254
254
  if (this.shape === Constants_js_1.randomColorValue) {
255
255
  const availableShapes = [...this.container.shapeDrawers.keys()];
256
- this.shape = availableShapes[Math.floor(Math.random() * availableShapes.length)];
256
+ this.shape = availableShapes[Math.floor((0, NumberUtils_js_1.getRandom)() * availableShapes.length)];
257
257
  }
258
258
  this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
259
259
  this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
@@ -19,14 +19,14 @@ class Particles {
19
19
  this._addToPool = (...particles) => {
20
20
  this._pool.push(...particles);
21
21
  };
22
- this._applyDensity = (options, manualCount, group) => {
22
+ this._applyDensity = (options, manualCount, group, groupOptions) => {
23
23
  const numberOptions = options.number;
24
24
  if (!options.number.density?.enable) {
25
25
  if (group === undefined) {
26
26
  this._limit = numberOptions.limit.value;
27
27
  }
28
- else if (numberOptions.limit) {
29
- this._groupLimits.set(group, numberOptions.limit.value);
28
+ else if (groupOptions?.number.limit?.value ?? numberOptions.limit.value) {
29
+ this._groupLimits.set(group, groupOptions?.number.limit?.value ?? numberOptions.limit.value);
30
30
  }
31
31
  return;
32
32
  }
@@ -244,11 +244,11 @@ class Particles {
244
244
  this.removeAt(Constants_js_1.minIndex, quantity, group);
245
245
  }
246
246
  setDensity() {
247
- const options = this._container.actualOptions, groups = options.particles.groups;
247
+ const options = this._container.actualOptions, groups = options.particles.groups, manualCount = options.manualParticles.length;
248
248
  for (const group in groups) {
249
- this._applyDensity(groups[group], Constants_js_1.manualCount, group);
249
+ this._applyDensity(groups[group], manualCount, group);
250
250
  }
251
- this._applyDensity(options.particles, options.manualParticles.length);
251
+ this._applyDensity(options.particles, manualCount);
252
252
  }
253
253
  setLastZIndex(zIndex) {
254
254
  this._lastZIndex = zIndex;
@@ -12,7 +12,7 @@ class Retina {
12
12
  }
13
13
  init() {
14
14
  const container = this.container, options = container.actualOptions;
15
- this.pixelRatio = !options.detectRetina || (0, Utils_js_1.isSsr)() ? Constants_js_1.defaultRatio : window.devicePixelRatio;
15
+ this.pixelRatio = !options.detectRetina || (0, Utils_js_1.isSsr)() ? Constants_js_1.defaultRatio : devicePixelRatio;
16
16
  this.reduceFactor = Constants_js_1.defaultReduceFactor;
17
17
  const ratio = this.pixelRatio, canvas = container.canvas;
18
18
  if (canvas.element) {
@@ -82,10 +82,8 @@ class EventListeners {
82
82
  if (!interactivityEl) {
83
83
  return;
84
84
  }
85
- const html = interactivityEl, canvasEl = container.canvas.element;
86
- if (canvasEl) {
87
- canvasEl.style.pointerEvents = html === canvasEl ? "initial" : "none";
88
- }
85
+ const html = interactivityEl, canvas = container.canvas;
86
+ canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
89
87
  if (!(options.interactivity.events.onHover.enable || options.interactivity.events.onClick.enable)) {
90
88
  return;
91
89
  }
@@ -492,6 +492,7 @@ function computeFullScreenStyle(zIndex) {
492
492
  borderWidth: "0",
493
493
  position: "fixed",
494
494
  zIndex: zIndex.toString(radix),
495
+ "z-index": zIndex.toString(radix),
495
496
  top: "0",
496
497
  left: "0",
497
498
  };
@@ -197,6 +197,9 @@ export class Canvas {
197
197
  this._safeMutationObserver(observer => observer.disconnect());
198
198
  this._initStyle();
199
199
  this.initBackground();
200
+ const pointerEvents = this._pointerEvents;
201
+ element.style.pointerEvents = pointerEvents;
202
+ element.setAttribute("pointer-events", pointerEvents);
200
203
  this._safeMutationObserver(observer => {
201
204
  if (!element || !(element instanceof Node)) {
202
205
  return;
@@ -240,6 +243,7 @@ export class Canvas {
240
243
  this._postDrawUpdaters = [];
241
244
  this._resizePlugins = [];
242
245
  this._colorPlugins = [];
246
+ this._pointerEvents = "none";
243
247
  }
244
248
  get _fullScreen() {
245
249
  return this.container.actualOptions.fullScreen.enable;
@@ -491,6 +495,14 @@ export class Canvas {
491
495
  }
492
496
  return true;
493
497
  }
498
+ setPointerEvents(type) {
499
+ const element = this.element;
500
+ if (!element) {
501
+ return;
502
+ }
503
+ this._pointerEvents = type;
504
+ this._repairStyle();
505
+ }
494
506
  stop() {
495
507
  this._safeMutationObserver(obs => obs.disconnect());
496
508
  this._mutationObserver = undefined;
@@ -96,7 +96,7 @@ export class Engine {
96
96
  return this._domArray;
97
97
  }
98
98
  get version() {
99
- return "3.8.0";
99
+ return "3.9.0";
100
100
  }
101
101
  async addColorManager(manager, refresh = true) {
102
102
  this.colorManagers.set(manager.key, manager);
@@ -241,8 +241,7 @@ export class Engine {
241
241
  return item;
242
242
  }
243
243
  async load(params) {
244
- const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options;
245
- const currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container(this, id, currentOptions);
244
+ const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container(this, id, currentOptions);
246
245
  if (oldIndex >= loadMinIndex) {
247
246
  const old = this.item(oldIndex), deleteCount = old ? one : none;
248
247
  if (old && !old.destroyed) {
@@ -246,11 +246,11 @@ export class Particle {
246
246
  }
247
247
  if (this.effect === randomColorValue) {
248
248
  const availableEffects = [...this.container.effectDrawers.keys()];
249
- this.effect = availableEffects[Math.floor(Math.random() * availableEffects.length)];
249
+ this.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
250
250
  }
251
251
  if (this.shape === randomColorValue) {
252
252
  const availableShapes = [...this.container.shapeDrawers.keys()];
253
- this.shape = availableShapes[Math.floor(Math.random() * availableShapes.length)];
253
+ this.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
254
254
  }
255
255
  this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
256
256
  this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
@@ -1,4 +1,4 @@
1
- import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, errorPrefix, lengthOffset, manualCount, minCount, minIndex, minLimit, posOffset, qTreeCapacity, sizeFactor, squareExp, } from "./Utils/Constants.js";
1
+ import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, errorPrefix, lengthOffset, minCount, minIndex, minLimit, posOffset, qTreeCapacity, sizeFactor, squareExp, } from "./Utils/Constants.js";
2
2
  import { getLogger, getPosition } from "../Utils/Utils.js";
3
3
  import { EventType } from "../Enums/Types/EventType.js";
4
4
  import { InteractionManager } from "./Utils/InteractionManager.js";
@@ -16,14 +16,14 @@ export class Particles {
16
16
  this._addToPool = (...particles) => {
17
17
  this._pool.push(...particles);
18
18
  };
19
- this._applyDensity = (options, manualCount, group) => {
19
+ this._applyDensity = (options, manualCount, group, groupOptions) => {
20
20
  const numberOptions = options.number;
21
21
  if (!options.number.density?.enable) {
22
22
  if (group === undefined) {
23
23
  this._limit = numberOptions.limit.value;
24
24
  }
25
- else if (numberOptions.limit) {
26
- this._groupLimits.set(group, numberOptions.limit.value);
25
+ else if (groupOptions?.number.limit?.value ?? numberOptions.limit.value) {
26
+ this._groupLimits.set(group, groupOptions?.number.limit?.value ?? numberOptions.limit.value);
27
27
  }
28
28
  return;
29
29
  }
@@ -241,11 +241,11 @@ export class Particles {
241
241
  this.removeAt(minIndex, quantity, group);
242
242
  }
243
243
  setDensity() {
244
- const options = this._container.actualOptions, groups = options.particles.groups;
244
+ const options = this._container.actualOptions, groups = options.particles.groups, manualCount = options.manualParticles.length;
245
245
  for (const group in groups) {
246
246
  this._applyDensity(groups[group], manualCount, group);
247
247
  }
248
- this._applyDensity(options.particles, options.manualParticles.length);
248
+ this._applyDensity(options.particles, manualCount);
249
249
  }
250
250
  setLastZIndex(zIndex) {
251
251
  this._lastZIndex = zIndex;
@@ -9,7 +9,7 @@ export class Retina {
9
9
  }
10
10
  init() {
11
11
  const container = this.container, options = container.actualOptions;
12
- this.pixelRatio = !options.detectRetina || isSsr() ? defaultRatio : window.devicePixelRatio;
12
+ this.pixelRatio = !options.detectRetina || isSsr() ? defaultRatio : devicePixelRatio;
13
13
  this.reduceFactor = defaultReduceFactor;
14
14
  const ratio = this.pixelRatio, canvas = container.canvas;
15
15
  if (canvas.element) {
@@ -79,10 +79,8 @@ export class EventListeners {
79
79
  if (!interactivityEl) {
80
80
  return;
81
81
  }
82
- const html = interactivityEl, canvasEl = container.canvas.element;
83
- if (canvasEl) {
84
- canvasEl.style.pointerEvents = html === canvasEl ? "initial" : "none";
85
- }
82
+ const html = interactivityEl, canvas = container.canvas;
83
+ canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
86
84
  if (!(options.interactivity.events.onHover.enable || options.interactivity.events.onClick.enable)) {
87
85
  return;
88
86
  }
@@ -459,6 +459,7 @@ function computeFullScreenStyle(zIndex) {
459
459
  borderWidth: "0",
460
460
  position: "fixed",
461
461
  zIndex: zIndex.toString(radix),
462
+ "z-index": zIndex.toString(radix),
462
463
  top: "0",
463
464
  left: "0",
464
465
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/engine",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "Easily create highly customizable particle, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.",
5
5
  "homepage": "https://particles.js.org",
6
6
  "scripts": {
package/report.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8"/>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
6
- <title>@tsparticles/engine [23 Jan 2025 at 08:54]</title>
6
+ <title>@tsparticles/engine [1 Aug 2025 at 08:39]</title>
7
7
  <link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
8
8
 
9
9
  <script>