Monster Logo
Monster
  • Support
  • Gitlab
  • Introduction
    • Why Components?
    • Getting Started
      • Using Monster in the browser
      • Using Monster with NPM
  • Data
    • Pathfinder
    • Transformer
    • Pipe
  • Internationalisierung
    • Locale
    • Formatter & Translations
    • Translation
      • Document Translation
    • Provider
      • Fetch Provider
  • DOM
    • Replace
    • Attributes
    • Remove
    • Insert
    • Form Handling
  • Web Component
    • Create your own web component
    • Form component
      • Create form
      • Custom button
      • Confirm button
      • Searchable select
      • Searchable tree select
      • Tabs
      • Tabs with label and icon
      • Reload
      • Message State button
    • State component
      • Usage
    • Layout
    • Notify Component
      • Message
      • Notify
  • Style
    • Color
      • Theme colors
      • Special colors
      • Border colors
      • References
    • Badge
    • Button
    • Typography
    • Table
    • Form
    • Build
      • References
  • Extra Topics
    • Compatibility
    • Polifyll
      • References
API
  • Monster
  • Form
  • Notify
  • State

Introduction

Monster is a lightweight, robust and easy-to-use library with modest ambitions.
Monster integrates easily with your existing websites without taking over everything.

Here’s what Monster is all about. In section Getting Started you can read how to integrate Monster into your own web projects.

Monster has a free license, and therefore you are free to customize Monster to your needs.

Monster is a collection of functions and classes that can help in the daily work
with Javascript to get faster to the goal. Monster does not require you to be the
only library, nor does it require you to use only Monster.

Monster itself has no dependencies and works perfectly with other frameworks
like jQuery or Bootstrap.

The design goals of Monster’s core library are:

  • Easy integration with existing user interfaces.
  • Robust interfaces
  • Tested code and good code coverage.
  • No dependencies on other libraries

Why Components?

JavaScript web components are useful for creating reusable, modular and maintainable web applications. Below are some of the reasons why developers should choose to use a JavaScript web component framework such as MonsterJS:

Reusability: web components are self-contained entities that can be easily reused in different parts of an application, reducing the amount of duplicate code and increasing maintainability.

Modularity: Web components can be assembled from other web components, allowing developers to create complex user interfaces from small, modular building blocks.

Interoperability: Web components are developed based on web standards and are therefore compatible with other web technologies and frameworks. This allows developers to easily integrate web components into their existing applications.

Performance: Web components are lightweight and powerful, they can be rendered and updated quickly, which can improve the overall performance of web applications.

Acceptability: web components are increasingly used by browsers and developers and are part of the web platform, making it easy to find support and guidance online.

Flexible: web components are not tied to a specific framework, so developers can choose the tools that best suit their needs.

Overall, MonsterJS and its web components offer a great way to improve the scalability, maintainability and performance of web applications.


Getting Started

To use Monster, you must have a foundation in HTML, CSS, and JavaScript. If you are just starting out in frontend development, it is recommended that you have a beginner’s guide open while working through this guide.

You can also ask for help on Stack Overflow by tagging your questions with “javascript” and “monster”.

Using Monster in the browser

To get started with Monster, all you need is a text editor and a browser. The best way to begin is to copy the following example into a file and save it as index.html.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Unleash your inner monster!</title>
</head>
<body>

<div>Your version is:
    <span id="version"></span>
</div>

<script type="module">
    import { Version } from 'https://cdn.skypack.dev/@schukai/[email protected]/source/types/version.js';
    document.getElementById('version').innerText = new Version('1.0.0').toString();
</script>

</body>
</html>

Then, open this file in your browser. You have now used the ‘Version’ class from Monster to create a Version object, which is output in a span.

Congratulations!

As shown in the version example, each Monster class or function can be used independently. Alternatively, Monster can be used as a collection of many useful classes and functions via the Monster namespace as a single JavaScript file.

In addition to being available on CDN providers like jsDelivr and Skypack, Monster can also be obtained via NPM or the git repos.

Monster itself has no dependencies and does not impose any specific requirements, so you can use it with Bootstrap, jQuery, or other frameworks.

Using Monster with NPM

To install Monster using npm, you will need to have Node.js and npm (which comes with Node.js) installed on your system.

  • Open a terminal or command prompt on your computer.
  • Run the following command: npm install @schukai/monster

This will install the latest version of Monster from the npm registry. If you want to install a specific version of Monster, you can specify the version number after the package name, like this: npm install @schukai/[email protected].

Once the installation is complete, you can import the modules in your JavaScript file like this:

import {Version} from '@schukai/monster/source/types/version.js';
console.log(new Version('1.0.0').toString());

Instead of npm you can of course also use yarn or pnpm.


Data

Functions and classes in this section are used to handle data.


Pathfinder

The Pathfinder class is used to access a specific path in a data object.

import {Pathfinder} from '@schukai/monster/source/data/pathfinder.mjs';
new Pathfinder({
    a: {
        b: {
            f: [
                {
                    g: false,
                }
            ],
        }
    }
}).getVia("a.b.f.0.g"); // ↦ false

The Pathfinder class is used to access a specific path in a data object. The path is defined as a string. The path is separated by a dot. The path can also be an array of strings. The path can also be a combination of both.

import {Pathfinder} from '@schukai/monster/source/data/pathfinder.mjs';
new Pathfinder({
    a: {
        b: {
            f: [
                {
                    g: false,
                }
            ],
        }
    }
}).getVia(["a", "b", "f", 0, "g"]); // ↦ false

Transformer

The Transformer class is used to transform data. The transformation is defined as a string.

import {Transformer} from '@schukai/monster/source/data/transformer.mjs';
const transformer = new Transformer("tolower")
console.log(transformer.run("HELLO"))
// ↦ hello

The following transformations are available:

commandparameteraliasdescription
to-base64base64, btobConverts the value to base64
from-base64atobConverts the value from base64
callfunction:param1:param2:…Calling a callback function. The function can be defined in three places: either globally, in the context addCallback or in the passed object
defaultvalue:type??If the value is undefined the first argument is returned, otherwise the value. The third optional parameter specifies the desired type. If no type is specified, string is used. Valid types are bool, string, int, float, undefined and object. An object default value must be specified as a base64 encoded json string. (since 1.12.0)
debugthe passed value is output (console) and returned
emptyReturn empty String ""
first-keydefaultCan be applied to objects and returns the value of the first key. All keys of the object are fetched and sorted. (since 1.23.0)
fromjsonType conversion from a JSON string (since 1.12.0)
ifstatement1:statement2?Is the ternary operator, the first parameter is the valid statement, the second is the false part. To use the current value in the queue, you can set the value keyword. On the other hand, if you want to have the static string “value”, you have to put one backslash \ in front of it and write value. the follow values are true: ‘on’, true, ’true’. If you want to have a space, you also have to write \ in front of the space.
indexkey:defaultproperty, keyFetches a value from an object, an array, a map or a set
last-keydefaultCan be applied to objects and returns the value of the last key. All keys of the object are fetched and sorted. (since 1.23.0)
lengthcountLength of the string or entries of an array or object
nopDo nothing
nth-keyindex:defaultCan be applied to objects and returns the value of the nth key. All keys of the object are fetched and sorted. (since 1.23.0)
nth-last-keyindex:defaultCan be applied to objects and returns the value of the nth key from behind. All keys of the object are fetched and sorted. (since 1.23.0)
pathpathThe access to an object is done via a Pathfinder object
path-existspathCheck if the specified path is available in the value (since 1.24.0)
plaintextplainAll HTML tags are removed (*)
element-by-idplainAll HTML tags are removed (*)
prefixtextAdds a prefix
rawurlencodeURL coding
staticnoneThe Arguments value is used and passed to the value. Special characters \ and : can be quotet by a preceding .
substringstart:lengthReturns a substring
suffixtextAdds a suffix
translationkey:defaulti18nTranslations can be applied. The translations must be stored in the DOM. (*) To use the current value as key the first parameter must be set to undefined.
tointegerType conversion to an integer value
tojsonType conversion to a JSON string (since 1.8.0)
tolowerstrtolower, tolowercaseThe input value is converted to lowercase letters
tostringType conversion to a string.
toupperstrtoupper, touppercaseThe input value is converted to uppercase letters
trimRemove spaces at the beginning and end
ucfirstFirst character large
ucwordsAny word beginning large
undefinedReturn undefined
uniqidCreates a string with a unique value (**)

(*) for this functionality the extension jsdom must be loaded in the nodejs context.

 // polyfill
 if (typeof window !== "object") {
    const {window} = new JSDOM('', {
        url: 'http://example.com/',
        pretendToBeVisual: true
    });

    [
        'self',
        'document',
        'Node',
        'Element',
        'HTMLElement',
        'DocumentFragment',
        'DOMParser',
        'XMLSerializer',
        'NodeFilter',
        'InputEvent',
        'CustomEvent'
    ].forEach(key => (global[key] = window[key]));
}

(**) for this command the crypt library is necessary in the nodejs context.

import * as Crypto from "@peculiar/webcrypto";
global['crypto'] = new Crypto.Crypto();

With the method setCallback(name, callback, context) you can define your own transformation functions.

The context parameter is optional and can be used to define the context in which the callback function is called. If no context is specified, the global context is used. In the pipe the name of the callback function is used by prefixing it with a call:.

import { Transformer } from '@schukai/monster/source/data/transformer.mjs';
const transformer = new Transformer("call:myCallback");
transformer.setCallback("myCallback", function (value) {
    return value + " world";
});
console.log(transformer.run("hello")); // hello world

Pipe

A Pipe is a class that is used to process data. The data is processed in a chain of functions. The functions are called in the order in which they were added to the pipe. The data is passed from one function to the next.

import {Pipe} from '@schukai/monster/source/data/pipe.mjs';
import {Pipe} from '@schukai/monster/source/data/pipe.mjs';

let obj = {
    a: {
        b: {
            c: {
                d: "world"
            }
        }
    }
}

console.log(new Pipe('path:a.b.c.d | toupper | prefix:Hello\\ ').run(obj));
// ↦ Hello WORLD

The Pipe class use the Pathfinder class to access the data and the Transformer class to transform the data.


Internationalisierung

The localization classes and functions support you in dealing with
translations and country-specific settings.

Locale

The Locale class is used to determine the language and country settings.

The method parseLocale() parses a locale string and returns a Locale object.

import {parseLocale} from '@schukai/monster/source/i18n/locale.mjs';
var locale = parseLocale("en-US");
console.log(locale.language); // "en"
console.log(locale.country); // "US"

The Method getLocaleOfDocument() returns the Locale object of the current document.

import {getLocaleOfDocument} from '@schukai/monster/source/dom/locale.mjs';
var locale = getLocaleOfDocument();
console.log(locale.language); // "en"
console.log(locale.country); // "US"

In an HTML document you can set the language and country with the lang attribute.

<html lang="en-US">

The method getLocaleOfDocument() checks for the lang attribute first and takes the browser locale as fallback. If no locale is available, English is taken.


Formatter & Translations

We need the Formatter and Translations class and the parseLocale() function to handle translations.
In the context of the DOM we can also use the getLocaleOfDocument() method.

import {Translations} from '@schukai/monster/source/i18n/translations.js';
import {Formatter} from '@schukai/monster/source/text/formatter.js';
import {parseLocale} from '@schukai/monster/source/i18n/locale.js';
import {getLocaleOfDocument} from '@schukai/monster/source/dom/locale.js';

Let’s start with the function parseLocale(). This function can create a Locale object from a string.

So we can create the corresponding Locale object from the string en_GB.

const locale = parseLocale('en_GB')
// ↦ Locale {}

If we move in the browser, so we can also use the function getLocaleOfDocument().
This function returns a locale object as a result.

This function looks if the HTML tag <html lang="en"> has a lang attribute.
If no locale is defined, the default value is assumed to be en.

We now need an object with the translations. For this, we use the Translations class.

We can either define the translations ourselves or load them via an API.

// define translations
const translation = new Translations(parseLocale('en-GB'));
translation.assignTranslations({
           text1: 'hello world!',
           text2: {
             'one': 'click once',
             'other': 'click ${n | tostring} times' // this is where the pipe comes in
           }
        });

// fetch from API
const translation = new Fetch('https://example.com/${language}.json').getTranslation('en-GB');
// ↦ https://example.com/en.json 

If we now have a translation, we can now read the desired strings. For this
we use the method Translation.getText() or the method Translation.getPluralRuleText()
for texts with more than one number.

const message = translation.getText('text1');
// -> hello world

To translate texts with number references, enter the desired number.

let n=1;
const message1 = translation.getPluralRuleText('text2', n);
// -> click once

n=2
const message2 = translation.getPluralRuleText('text2', n);
// -> click ${n} times

To replace the placeholder now, the formatter is used.

const text = new Formatter({n}).format(message2); 
console.log(text)
// ↦ click 2 times

Finally, let’s take a look at the formatter class from the i18n module.

import {Formatter} from 
    'https://cdn.skypack.dev/@schukai/[email protected]/source/i18n/formatter.js';

A tranlate object can be passed directly to this class.

There is also the possibility to pass values in the format string.

// define translation
const translations = new Translations('en')
    .assignTranslations({
        // text with placeholder
        message: "${animal} has eaten the ${food}!"
    });

// without marker and inline values
new Formatter({}, translations).format("message::animal=dog::food=cake")
// ↦ dog has eaten the cake!     

Translation

The Translation class encapsulates strings for a specific locale. It is used to translate strings into a specific language and country.

import {Translation} from '@schukai/monster/source/i18n/translation.mjs';

const translation = new Translation("en-US");
translation.set("hello", "Hello World!");

// plural rules
translation.setText("text6", {
    "zero": "There are no files on Disk.",
        "one": "There is one file on Disk.",
        "other": "There are files on Disk.",
    "default": "There are files on Disk."
});

If you want to assign a complete translation object, you can use the assignTranslations() method.

translation.assignTranslations({
    "hello": "Hello World!",
    "text6": {
        "zero": "There are no files on Disk.",
        "one": "There is one file on Disk.",
        "other": "There are files on Disk.",
        "default": "There are files on Disk."
    }
});

The getText() method returns the translated string for a given key.

translation.getText("hello"); // "Hello World!"

There are also methods for plural rules. The getPluralRuleText() method returns the translated string for a given key and a given number.

translation.getPluralRuleText("text6", 0); // "There are no files on Disk."
translation.getPluralRuleText("text6", 1); // "There is one file on Disk."
translation.getPluralRuleText("text6", 2); // "There are files on Disk."

Document Translation

First, you have to create a new script element with the data-monster-role="translations" and the type="application/json" attribute. The content of the element must be a JSON object.

<script type="application/json" data-monster-role="translations">
    {
        "key1": "translation1",
        "key2": {
            "other": "translation2"
        }
    }
</script> 

Then you have to assign the translations to the document. This can be done with the assignTranslationsToDocument() method. This static method returns a promise. Than you can use the getDocumentTranslations() method to get the translations. Finally, you can use the getText() method to get the translated string.

import { Embed } from "@schukai/monster/source/i18n/providers/embed.mjs";
import { getDocumentTranslations } from "@schukai/monster/source/i18n/translations.mjs";

Embed.assignTranslationsToElement().then(() => {

    const translations = getDocumentTranslations();

    translations.getText('no-key','with-default')
    // ↦ with-default

    translations.getText('key1')
    // ↦ translation1

}).catch((e) => {
// ...
})

Provider

The abstract Provider class is used to provide translations to the application.

import {Provider} from '@schukai/monster/source/i18n/provider.mjs';

Fetch Provider

The FetchProvider class is used to provide translations from a remote server.

import {Fetch} from '@schukai/monster/source/i18n/providers/fetch.mjs';
const provider = new Fetch(
    'https://example.com/translations${language}.json',
    {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    }
);
provider.getTranslations('en-US').then(translations => {
    console.log(translations);
});

The URL can contain the placeholder ${language}, ${script}, ${region}, ${variants}, ${extlang} and ${privateUse}. The placeholders will be replaced with the language, country and locale of the current document.

import {Fetch} from '@schukai/monster/source/i18n/providers/fetch.mjs';

const provider = new Fetch(
    'https://example.com/translations/${language}/${region}.json',
    {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    }
);
provider.getTranslations('en-US').then(translations => {
    console.log(translations);
});

Embed Provider

The EmbedProvider class is used to provide translations from a local tag.

You must add a script tag with the type application/json. This Tag must contain a JSON object with the translations.

<script id="mmylocale" type="application/json">
{
        "key": "translation"
}
</script>

Now you can use the EmbedProvider to get the translations.

import {Embed} from '@schukai/monster/source/i18n/providers/embed.mjs';

const provider = new Embed('mmylocale');
provider.getTranslations('en-US').then(translations => {
    console.log(translations);
});

DOM

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the structure of a document as a tree-like structure, where each node in the tree represents an element, attribute, or text content in the document.

JavaScript provides a set of functions and classes for working with the DOM, including methods for creating, modifying, and querying elements, as well as handling events.

JavaScript’s DOM functions and classes can be divided into several categories:

  • Document: this includes the Document object, which represents the entire HTML or XML document and provides methods for manipulating the structure and content of the document.
  • Element: This includes classes such as HTMLElement, which represent an HTML element and provide methods for manipulating the attributes, content, and style of the element.
  • Event: This includes classes such as Event and EventTarget, which provide methods for processing and responding to events such as clicks, mouse movements, and keystrokes.
  • Node: This includes classes such as Node, which represent a node in the DOM tree and provide methods for processing the node’s parent and child nodes.
  • Selector: These include functions such as document.getElementById(), document.querySelector(), and document.querySelectorAll(), which are used to select elements from the DOM by their ID, class, or tag name.

By using these functions and classes, developers can create dynamic and interactive web pages and develop a variety of web applications.

In this section, we will delve deeper into the functions and classes provided by Monster and provide examples of their usage for manipulating the DOM and handling events.


Monster’s updater uses a DOM-based approach. The configuration and the template system are valid and parsable HTML.

The configuration is done via some special attributes with a data-monster- prefix.

Code is always the most informative. So let’s take a look at a complete example right away.

// The first thing to do is to include the Updater class.
import {Updater} from 'https://cdn.skypack.dev/@schukai/[email protected]/source/dom/updater.js';

// Now we prepare the html document.
// This is done here via script, but can also be inserted into the document as pure html. 
// To do this, simply insert the tag <h1 data-monster-replace="path:headline"></h1>.
const body = document.querySelector('body');
const headline = document.createElement('h1');
headline.setAttribute('data-monster-replace','path:headline')
body.appendChild(headline);

// the data structure
let obj = {
    headline: "Go!",
};

// Now comes the real magic. we pass the updater the parent HTMLElement
// and the desired data structure.
const updater = new Updater(body, obj);

// now we get the used data structure. why can't we take the original structure? 
// the updater puts a proxy over the data structure and thus allows to monitor changes.
// We would not see changes to the original object.
const subject = updater.getSubject();

// now start the updater
updater.run();

// Now you can change the data structure and the HTML will follow these changes.
// to illustrate, let's put the change into a timer call.
setTimeout(function(){
    console.log(obj);
    subject['headline'] = "Hello!"

},1000);

We have seen how we can change the content of an htm element. now let’s look at what options are available.

Replace

The simplest manipulation is to replace the content of a HTMLElement.
To do this, simply use the data-monster-replace attribute (see example).

The syntax is quite simple. The result of the attribute pipe is inserted as content of the
HTMLElement. For the processing the Pipe and Transformer class
is used.

If, for example, you have an object x with the structure listed below and want to insert the value of the key b, you write: path:a.b.

The pipe can then be used to apply operators. For example, tolower can be used to convert everything to lowercase.

let x = {
   a: {
      b: "EXAMPLE"
   }
}

this is how it looks as an attribute:

<div data-monster-replace="static:HELLO | tolower"></div>

The result is then the following html:

<div data-monster-replace="static:hello">hello</div>

A full example looks like this:

import {Updater} from 'https://cdn.skypack.dev/@schukai/[email protected]/source/dom/updater.js';
const body = document.querySelector('body');
const headline = document.createElement('h1');
headline.setAttribute('data-monster-replace','static:hello')
body.appendChild(headline);
// result in ↦ <div data-monster-replace="static:hello"></div>

new Updater(body).run(); 

Attributes

Attributes can be added via the data-monster-attributes attribute. The syntax is attribute name followed by
a space and the desired pipe definition.

<div data-monster-attributes="id static:myid">hello</div>

The result is then the following html:

<div id="myid" data-monster-attributes="id static:myid">hello</div>

Multiple attributes can be separated by commas.

<div data-monster-attributes="id static:myid, class static:myclass">hello</div>

Remove

The data-monster-remove attribute can be used to remove html elements. it is important to
note that this cannot be undone. Once removed, nodes will not be reinserted.

This tag is removed via the updater

<div data-monster-remove></div>

Insert

The strongest feature is adding elements to a node.

For this feature you need a template and the data-monster-insert attribute.

The syntax of the attribute is first an id followed by a space. This is then followed by the pipe command.

<ol data-monster-insert="myid path:a"></ol>

Furthermore, you need a template. The template must have the same string as id.

<template id="myid">
   <li data-monster-replace="path:myid | index:id | tostring | prefix:x"></li>
</template>

In this template, we define the structure of the new elements. In this case, the id is taken
from the dataset index:id, converted to a string tostring, and an x is placed in front of it prefix:x.

The values for the corresponding data must be available as an array.

let obj = {
    a: [
        {"id": 1},
        {"id": 2},
        {"id": 3},
        {"id": 4}
    ]
};

Below we have a complete example. Instead of specifying the template <template /> in HTML, it is constructed via
javascript document.createElement('template'). But it is essentially the same.

const body = document.querySelector('body');
const li = document.createElement('li');
li.innerHTML="-/-";
li.setAttribute('data-monster-replace','path:myid | index:id | tostring | prefix:x');

const template = document.createElement('template');
template.setAttribute('id','myid');
template.content.appendChild(li);

body.appendChild(template);

const list = document.createElement('ul');
list.setAttribute('data-monster-insert', 'myid path:a')

body.appendChild(list);

let obj = {
    a: [
        {"id": 1},
        {"id": 2},
        {"id": 3},
        {"id": 4}
    ]
};

const updater = new Updater(body, obj)
updater.run();

The result will be

<ul data-monster-insert="myid path:a">
  <li data-monster-replace="path:a.0 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-0">x1</li>
  <li data-monster-replace="path:a.1 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-1">x2</li>
  <li data-monster-replace="path:a.2 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-2">x3</li>
  <li data-monster-replace="path:a.3 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-3">x4</li>
</ul>

You can easily add and delete values to the array. The DOM will be adjusted accordingly.
The attribute data-monster-insert-reference identifies if the entry already exists.


Form Handling

Forms can be bound to a structure just like other structures via the updater class.

Suppose we have an html form with some controls.

<div>
    <form id="form1">
        <input type="checkbox" name="checkbox">
        <input type="text" name="text">
        <input type="radio" name="radio">

        <select name="select">
            <option>value1</option>
            <option>value2</option>
        </select>

        <textarea name="textarea">
        </textarea>

        <input type="button" name="button">

    </form>
</div>

A new updater is created in this case via the following call.

const updater = new Updater(document.getElementById('form1'));

With the method Updater.getSubject() you can get the structure of the updater. If you want to use an already defined structure, you can pass it to the updater as a second parameter.

let subject =  updater.getSubject();
console.log(subject);

Now we want a click on the checkbox to be mapped in the data structure.

To do this we need to extend the html with the data-monster-bind attribute.

The values or states of controls are mapped to the data structure via this binding.

<div>
    <form id="form1">
        <!-- data-monster-bind added -->
        <input type="checkbox" name="checkbox" data-monster-bind="path:state">
    </form>
</div>

In this case the status of the checkbox is mapped to the key state. If the checkbox is selected the field state contains the value on , otherwise state is undefined.

If you want to use another value instead of on, you can set the attribute value.

<input type="checkbox" name="checkbox" value="checked" data-monster-bind="path:state">

To see the magic the handling must still be switched on.

updater.enableEventProcessing()

Web Component

Web Components are a set of technologies that allow developers to create custom, reusable elements for use in web pages and web applications. These elements, known as Custom Elements, can be created using JavaScript, HTML, and CSS and are fully-featured and can be used just like any other standard HTML element.

Web Components are a key aspect of web development, as they enable developers to create reusable, modular code that can be easily shared and integrated with other projects. Additionally, because Web Components are part of the web platform and not tied to a specific framework or library, they are highly portable and can be used in a wide variety of environments. Overall, Web Components provide a powerful and flexible way to build web applications and create custom, reusable elements for web pages.


Create your own web component

This section is about how to create your own
Web Component.

Using classes and functions from Monster.

First, we create a class derived from CustomControl. The parent class
CustomControl already implements some functions that will make life in the following
easier.

class Button extends CustomControl {
}

The next step determines which tag the control should get in the HTML.

class Button extends CustomControl {
    static getTag() {
        return "monster-button";
        
    }
}

To be able to configure the control later, we have to create the possibility,
to be able to create options. We can use the structures of the class
CustomControl and only need to create a separate property default.

class Button extends CustomControl {

    // ..... other implementations
    
    get defaults() {
        return Object.assign({}, super.defaults, {})
    }

}

The templates of the control are also defined via this structure. In this way one can the control with a standard and give the user of the control the possibility to adapt the templates. Customize the templates.

So, now let’s get to work on the appearance of the control and create a template for it. We want the button to use a simple HTML5 button.

<button>Hello!</button>

The main template of the button is maintained via the templates.main option.

So, we have to insert the HTML into the default structure introduced above. We can
specify the HTML directly here.

return Object.assign({}, super.defaults, {
    templates: {
        main: `<button>Hello!</button>`
    },
})

To maintain an overview of larger templates, you can alternatively
template into a function and only call up the function here.

return Object.assign({}, super.defaults, {
    templates: {
        main: getTemplate()
    },
})

If we now insert the HTML tag <monster-button></monster-button> into an HTML file we get so far so unspectacular a button.

Screenshot

Now comes the magic. In the DOM there are two important methods that are called when a control is included and removed. When a control is removed.

If a control is hooked into the DOM, the method
connectedCallback is called.

When a control is removed from the DOM, on the other hand, the method disconnectedCallback is called

We implement both methods in our new class.

class Button extends CustomControl {

    // ..... other implementations

    connectedCallback() {
        super.connectedCallback();
    }

    disconnectedCallback() {
        super.disconnectedCallback();
    }
} 

Within these two methods, we can now initialize structures or add and remove event handlers. Adding and removing event handlers.

The CustomControl has two other important methods that can be overridden to initialize, they can be overridden to initialize the control. These two methods have no direct method name, but are hidden behind a symbol key. symbol key.

import {
    assembleMethodSymbol,
    initMethodSymbol,
} from "@schukai/monster/dist/modules/dom/customelement.js";

class Button extends CustomControl {

    // ..... other implementations

    [initMethodSymbol]() {
        super[initMethodSymbol]();
    }

    [assembleMethodSymbol]() {
        super[assembleMethodSymbol]();
    }
} 

The method initMethodSymbol is called directly from the constructor and is used for one-time initialization of internal structures. internal structures.

The method assembleMethodSymbol is called the first time the control is included in the
DOM. If the control is removed and re-included, the assembleMethodSymbol method is called. assembleMethodSymbol` is not called again.


Form component

Web forms are a way for users to enter and submit data on a web page. They are created using HTML and can include a variety of input elements such as text fields, checkboxes, radio buttons, and more.

Web forms are a crucial aspect of many websites, as they allow users to interact with the site and provide information such as login credentials, contact information, and more.


Create form

Usage

The Form component allows the user to create a form and in interaction with a datasource to change data.

// create element
const form = document.createElement('monster-form');
Input controls

A form needs input fields. These can be easily defined within the tag. Either via Javascript directly or via the markup.

const input = document.createElement('input')
input.setAttribute('name','field');
form.appendChild(input);

via markup

<monster-form>
    <input name="field">
</monster-form>

The formula field ➊ are included as slotted elements in the shadow root ➋.

Datasource

One of the more interesting features of the form is the ability to connect the form to a data source. A datasource has a simple API to read and write an object (see Monster Framework under Datasources).

In this example we use a RestAPI datasource, but other datasources work as well. The example url httpbin.org is a service that provides a simple api with data. This is for this example only. You can of course specify your own api here.

const datasource =  new RestAPI({
  url: 'https://httpbin.org/get'
},{
  url: 'https://httpbin.org/post'
});
form.setOption('datasource', datasource)

In order to see the data as a value in the input field, we must specify the attribute data-monster-attributes.

const input = document.createElement('input')
input.setAttribute('name','field');
input.setAttribute('data-monster-attributes','value path:headers.Host');
form.appendChild(input);

Now we have to report the data back to the datasource. For this we use the attribute data-monster-bind. In this example we write the value in the same field, but we can also choose another field if for example the POST api has a different structure.

input.setAttribute('data-monster-bind','path:headers.Host');
Actions

What is a form without action? To be able to send the changed data we can add a button.

const button = document.createElement('monster-state-button');
// let's give the button a text
button.setOption('labels.button','click!')
// this attribute ensures that the form sets an action handler in the button.
button.setAttribute('data-monster-datasource-handler','write')

button.setOption('actions.click', undefined);

form.appendChild(button);

If we now click on the button, the modified dataset will be sent to the url previously specified in the RestAPI datasource.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#select1::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.


Custom button

Usage

The button control encapsulates a button and serves as a basis for derived controls.

// create element
const button = document.createElement('monster-button');

// insert element into the DOM
document.getElementById('body').appendChild(button);
<monster-button></monster-button>
Slotted Button

The text of the button can be defined either by the option labels.button.

// create element
const button = document.createElement('monster-button');

// insert element into the DOM
document.getElementById('body').appendChild(button);

// Label
button.setOption('labels.button','My Button');

Or by a slot.

<monster-button>My Button</monster-button>
Action

Standard HTML buttons can listen to different events. Since the standard button sits in a shadowRoot the click event is accessible via an option. The component button uses a callback to listen for click events.

To do this, you must pass a callback to the actions.click option.

const button = document.querySelector('monster-button');
button.setOption('actions.click',(event)=>{
  console.log('clicked!');
});
State-Button

The status button is a special form of the button and has an icon to display the status.

You can also define your own statuses. these must be specified in the options.

// create element
const button = document.createElement('monster-state-button');

// insert element into the DOM
document.getElementById('body').appendChild(button);

// Label
button.setOption('labels.button','My Button');

// set state: successful, activity or failed
button.setState('successful');

Or by a slot.

<monster-state-button>My Button</monster-state-button>

Layout

The button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-button::part(button) {
    background-color: white;
}

The color scheme of the button can be set using CSS class via the options. You should always use a light color scheme for the status button, so that the icon is the icon is clearly visible. When using the standard design, you should always use the Outline variant should always be used.

const button = document.querySelector('monster-button');
button.setOption('classes.button','monster-button-outline-secondary');

if you want to use the standard classes, you have to include the properties, this can be done for example with postcss.

import  "@schukai/component-style/source/style/color.pcss";
import  "@schukai/component-style/source/style/theme.pcss";
import  "@schukai/component-style/source/style/property.pcss";

The individual parts and slots are shown in the following picture.


Confirm button

Usage

The ConfirmButton component enables the display of a confirmation prompt before the final execution of an action.

// create element
const button = document.createElement('monster-confirm-button');
// set label
button.setOption('labels.button', 'click me!');

// insert element into the DOM
document.getElementById('body').appendChild(button);
Add confirm action

The confirm button can be given a function via the actions.confirm option.

button.setOption('actions.confirm', function (event) {
    console.log('confirm');
    button.hideDialog();
});
Add confirm action with state

The state is realized via a process queue.

button.setOption('actions.confirm', function (event) {

    const self = this;
    new Processing(() => {
        self.setState('activity'); // set state
        button.setOption('disabled', true);
    }, 2000, () => { // delay 2000 milliseconds 
        button.hideDialog();
    }).run().then(() => {
        button.setOption('disabled', undefined); // remove state
    });

});
Layout

The confirm-button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-confirm-button::part(popper) {
    background-color: white;
}

The nested parts can each be addressed via the part name and the subpart name. So the part button is addressable from the confirm button via confirm-button.

monster-confirm-button::part(confirm-button) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


Searchable select

Usage

Select component allows user to pick any amount of option from the given data:

// create element
const select = document.createElement('monster-select');

// set multiselect
select.setOption('type', 'checkbox');

// set options
select.setOption('options', [
        {value: 'en', label: 'United Kingdom &lt;img width=20
                                           src="https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/gb.svg"&gt;'},
        {value: 'se', label: 'Sverige &lt;img width=20
                                           src="https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/se.svg"&gt;'},
        {value: 'de', label: 'Deutschland &lt;img width=20
                                               src="https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/de.svg"&gt;'}
    ]);

// insert element into the DOM
document.getElementById('body').appendChild(select);
Single select

Radios are used for the single selection.

select.setOption('type', 'radio');
Multiselect

Checkboxes are used for multiple selection.

select.setOption('type', 'checkbox');
Import data

The options can be imported from an object. The object can be read in either directly via Select.importOptions() or indirectly via a URL. In the example, a json file is imported via https://monsterjs.org/assets/world.json`.

select.setOption('url','https://monsterjs.org/assets/world.json')

Alternatively, the data can also be imported from an object.

select.importOptions([
    {
        "name": "United Kingdom",
        "alpha-2": "GB",
        "country-code": "826",
    },
    {
        "name": "Sweden",
        "alpha-2": "SE",
        "country-code": "752",

    },
    {
        "name": "Germany",
        "alpha-2": "DE",
        "country-code": "276",
    }
]);

The mapping of the data to the options is done using the values defined in the mappings key.

select.setOption('mapping.labelTemplate', '${name} (${alpha-2})')
select.setOption('mapping.valueTemplate', '${country-code}')

If you want to specify a deeper structure, you can do so via selector`.

{
    a: {
        b: {
            c: [
                ....
            ]
        }
    }
}

select.setOption('mapping.selector', 'a.b.c')

It is also possible to filter values. This is done via the filter parameter. Further details on the structure of the map can be found in the Monster documentation.

There is also an example.

select.setOption('mapping.filter',  function (value, key) {
               return (value['id'] >= 20) ? true : false
           })
Events

The following events are fired by the component.

  • monster-options-set
  • monster-selected
  • monster-change
  • monster-changed
I18n

The component can be translated into different languages. For this you simply have to translate the corresponding labels. This can be done using the Select.setOption() method.

select.setOption('labels', {
  'cannot-be-loaded': 'The data cannot be loaded',
    'no-options-available': 'No options available'
});

You can also use the translation function. Therefore, the component can be translated via the Select.updateI18n() methods.

const selects = document.querySelector('monster-select')
select.updateI18n();

To see the keys of the translations, you can look at the default values under the labels key.

selects.getOption('labels')
// ↦ { .... }
Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-select::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.


Searchable tree select

Usage

The TreeSelect control is derived from Select and therefore inherits all properties and functions. It extends the control by the display of hierarchical data.

const treeselect = document.createElement('monster-tree-select');

// URL
treeselect.setOption('url', 'https://monsterjs.org/assets/14-forms-treeselect-data.json');

// Multiselect
treeselect.setOption('type', 'checkbox');

// search for data in dataset
treeselect.setOption('mapping.selector', 'dataset.*');

// define label and key
treeselect.setOption('mapping.labelTemplate', '${localeLabel | index:en}');
treeselect.setOption('mapping.valueTemplate', '${cid | tostring }');

// wich field is the parent ID?
treeselect.setOption('mapping.parentTemplate', 'parentCID');
treeselect.setOption('mapping.idTemplate', 'cid');

// append
document.getElementById('container').appendChild(treeselect);            
Events

The following events are fired by the component.

  • monster-options-set
  • monster-selected
  • monster-change
  • monster-changed

Layout

The tree select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#tab::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.


Tabs

Usage

The Tabs component allows the user to switch between multiple contents based on a navigation bar. The text for the buttons is formed from the content of the divs. No tab is active.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tabs.appendChild(tab2)

// append to document
document.getElementById('example-tzxoiPwe').appendChild(tabs);
<monster-tabs>
    <div>this is tab 1</div>
    <div>this is tab 2</div>
</monster-tabs>
Active Tab

To set a tab active, you need to give the desired div the css class active`.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
// this tab should be active
tab1.classList.add('active')
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
  <div class=&quot;active&quot;>this is tab 1</div>
  <div>this is tab 2</div>
</monster-tabs>

Tabs with label and icon

To use an explicit text for the button, you can use the data-monster-button-label attribute. If you also want to specify an icon, the attribute data-monster-button-iocon` is available.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tab2.setAttribute('data-monster-button-icon','https://monsterjs.org/monster.png');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot; data-monster-button-label=&quot;FIRST&quot;>this is tab 1</div>
    <div data-monster-button-label=&quot;SECOND&quot; 
            data-monster-button-icon=&quot;https://monsterjs.org/monster.png&quot;>this is tab 2</div>
</monster-tabs>
Prefix and suffix

If you want to add content before or after the navigation buttons, you can do so using the start and end slots.

// tabs        
const tabs = document.createElement('monster-tabs');

// prefix
const prefix = document.createElement('div');
prefix.innerHTML='this is a <b>prefix</b>';
prefix.setAttribute('slot','start')
tabs.appendChild(prefix);
            
// suffix
const suffix = document.createElement('div');
suffix.innerHTML='this is a <b>suffix</b>';
suffix.setAttribute('slot','end')
tabs.appendChild(suffix);

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot; data-monster-button-label=&quot;FIRST&quot;>this is tab 1</div>
    <div data-monster-button-label=&quot;SECOND&quot;>this is tab 2</div>
    <div slot=&quot;start&quot;>this is a <b>prefix</b></div>
    <div slot=&quot;end&quot;>this is a <b>suffix</b></div>
</monster-tabs>
Remove tabs

Tabs can be removed from the DOM. To do this, the desired content must have the attribute data-monster-removable. If you add multiple tabs and there is no space for newer tabs, they will be moved to a popup. You can see this by the ⋮ sign.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tab1.setAttribute('data-monster-removable','true');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tab2.setAttribute('data-monster-removable','true');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot; 
         data-monster-button-label=&quot;FIRST&quot; 
         data-monster-removable=&quot;true&quot;>this is tab 1</div>
    <div data-monster-button-label=&quot;SECOND&quot; 
         data-monster-removable=&quot;true&quot;>this is tab 2</div>
</monster-tabs>
Fetch tab content

The content of a tab can also be fetched by specifying the attribute data-monster-url with the url of the desired content. The tab is loaded only once. If you want to load the tab fresh from the server for each show, you can specify the attribute data-monster-reload.

It is important to follow the CORS guidelines.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this tab will be reloaded';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tab1.setAttribute('data-monster-url','https://monsterjs.org/assets/15-forms-tabs-content1.html');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tab2.setAttribute('data-monster-removable','true');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot;
         data-monster-button-label=&quot;FIRST&quot;
         data-monster-url=&quot;https://monsterjs.org/assets/15-forms-tabs-content1.html&quot;>this tab will be reloaded</div>
    <div data-monster-button-label=&quot;SECOND&quot;
         data-monster-removable=&quot;true&quot;>this is tab 2</div>
</monster-tabs>
Events

The following events are fired by the component.

  • monster-fetched
Layout

The tabs control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#select1::part(popper) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


Reload

Usage

The Reload component allows the user to reload a content via URL. The content is reloaded only when the element is in the viewport. The IntersectionObserver API is used.

Im Standard wird der Inhalt nur einmal geladen. Möchte man den Inhalt immer wieder neu Laden, so muss die Option data-monster-reload auf “always” gesetzt werden.

It is important to follow the CORS guidelines.

// reload element
const reload = document.createElement('monster-reload');

// loader content
const defaultContent = document.createElement('div');
defaultContent.setAttribute('data-monster-role','container');
defaultContent.innerHTML='load'
reload.appendChild(defaultContent);

// fetch follow url
reload.setAttribute('data-monster-url','https://monsterjs.org/assets/16-forms-reload-content.html')

// append element 
document.getElementById('example').appendChild(reload);


<monster-reload>
  <div data-monster-role="container">
    LOADER ...
  </div>
</monster-reload>

If the child element has the attribute data-monster-role="container", then the content is replaced with the fetched content.

Events

The following events are fired by the component.

  • monster-fetched
Layout

The tabs control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS.

By default, the Shadow DOM is disabled for this component. You can enable it by setting the option shadowMode: false, to open or closed.

Since the internals of the component are optionally encapsulated in a shadow tree, access is via css pseudo-element parts.

#reload::part(container) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


Message State button

Usage

The MessageStateButton button can be used to display a button with a message. The message is displayed when the method showMessage() is called. The message is hidden when the method hideMessage() is called.

// create element
const button = document.createElement('monster-message-state-button');
// set label
button.setOption('labels.button', 'click me!');

Set Message

The message can be set via the method setMessage(). The message can be a string or an HTML element.

// create element
const button = document.createElement('monster-message-state-button');
// set label
button.setOption('labels.button', 'click me!');
// set message
button.setMessage('This is a message');
// show message
button.showMessage();
Layout

The message-state-button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-message-state-button::part(popper) {
    background-color: white;
}

The nested parts can each be addressed via the part name and the subpart name. So the part button is addressable from the confirm button via message-state-button.

monster-message-state-button::part(message-state-button) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


State component

The state component is a simple state display component. It is used to display the current state of the application.

Usage

The status component is a simple graphical display that specifies a structure of elements. The aim of this component is to enable a uniform representation of such displays.

The component is composed of a visual, a heading and a text. Actions (buttons) can also be displayed.

import  '@schukai/[email protected]/source/button.mjs';
import  '@schukai/component-state/source/state.mjs';

// state element
const state = document.createElement('monster-state');
state.innerHTML = `  
<svg slot="visual" version="1.1" viewBox="0 0 612.41 583.39" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="clipPath18"><path d="m0 500h500v-500h-500z"/></clipPath><clipPath id="clipPath26"><path d="m45.178 442.22h434.25v-377.14h-434.25z"/></clipPath><clipPath id="clipPath42"><path d="m204.22 467.91h26.586v-26.586h-26.586z"/></clipPath><clipPath id="clipPath58"><path d="m390.28 469.58h13.717v-13.718h-13.717z"/></clipPath><clipPath id="clipPath74"><path d="m145.82 434.05h18.382v-18.382h-18.382z"/></clipPath><clipPath id="clipPath90"><path d="m28.108 112.45h41.854v-41.854h-41.854z"/></clipPath><clipPath id="clipPath106"><path d="m422.16 453.67h53.968v-49.906h-53.968z"/></clipPath><clipPath id="clipPath122"><path d="m413.19 98.497h38.944v-40.498h-38.944z"/></clipPath><clipPath id="clipPath138"><path d="m37.65 477.47h50.732v-48.756h-50.732z"/></clipPath><clipPath id="clipPath154"><path d="m20.124 443.07h442.71v-328.26h-442.71z"/></clipPath><clipPath id="clipPath170"><path d="m40.299 424.66h403.77v-345.77h-403.77z"/></clipPath><clipPath id="clipPath186"><path d="m463.15 122.92h9v-9h-9z"/></clipPath><clipPath id="clipPath202"><path d="m255.28 473.64h9v-9h-9z"/></clipPath><clipPath id="clipPath218"><path d="m92.708 81.422h9.0005v-9h-9.0005z"/></clipPath><clipPath id="clipPath234"><path d="m377.74 61.499h7v-7h-7z"/></clipPath><clipPath id="clipPath250"><path d="m75.842 394h3v-3h-3z"/></clipPath><clipPath id="clipPath266"><path d="m386.17 443.78h10.81v-10.81h-10.81z"/></clipPath><clipPath id="clipPath282"><path d="m103.88 464.64h4.24v-4.24h-4.24z"/></clipPath><clipPath id="clipPath298"><path d="m442.27 473.16h3.604v-3.603h-3.604z"/></clipPath><clipPath id="clipPath314"><path d="m61.215 43.533h3.6033v-3.6033h-3.6033z"/></clipPath><clipPath id="clipPath330"><path d="m0 500h500v-500h-500z"/></clipPath><clipPath id="clipPath338"><path d="m89.761 362.35h386.54v-276.52h-386.54z"/></clipPath><clipPath id="clipPath362"><path d="m173.59 147.49h132.29v-71.271h-132.29z"/></clipPath><clipPath id="clipPath366"><path d="m173.59 147.49h132.29v-71.271h-132.29z"/></clipPath><clipPath id="clipPath422"><path d="m47.677 233.4h148.44v-79.857h-148.44z"/></clipPath><clipPath id="clipPath426"><path d="m47.677 233.4h148.44v-79.857h-148.44z"/></clipPath><clipPath id="clipPath482"><path d="m249.66 330.43h201.45v-217.56h-201.45z"/></clipPath><clipPath id="clipPath502"><path d="m261.96 317.99h160.2v-197.09h-160.2z"/></clipPath><clipPath id="clipPath522"><path d="m259.29 322.78h160.2v-197.09h-160.2z"/></clipPath><clipPath id="clipPath550"><path d="m292.72 320.3h68.297v-71.599h-68.297z"/></clipPath><clipPath id="clipPath570"><path d="m302.4 320.13h56.096v-16.961h-56.096z"/></clipPath><clipPath id="clipPath626"><path d="m348.24 363.49h91.426v-34.284h-91.426z"/></clipPath><clipPath id="clipPath658"><path d="m145.77 405.2h138.9v-208.72h-138.9z"/></clipPath><clipPath id="clipPath674"><path d="m158.11 405.2h126.57v-208.72h-126.57z"/></clipPath><clipPath id="clipPath694"><path d="m192.28 228.57h120.03v-32.083h-120.03z"/></clipPath><clipPath id="clipPath758"><path d="m262.8 344.9h126.58v-126.58h-126.58z"/></clipPath><clipPath id="clipPath774"><path d="m272.5 338.96h61.904v-61.904h-61.904z"/></clipPath><clipPath id="clipPath790"><path d="m260.8 346.9h130.58v-130.58h-130.58z"/></clipPath><clipPath id="clipPath822"><path d="m378.75 237.08h12.84v-12.369h-12.84z"/></clipPath><clipPath id="clipPath842"><path d="m381.24 233.61h67.907v-72.32h-67.907z"/></clipPath><clipPath id="clipPath882"><path d="m89.344 237.56h166.92v-133.24h-166.92z"/></clipPath><clipPath id="clipPath898"><path d="m89.344 237.56h143.94v-133.24h-143.94z"/></clipPath></defs><g transform="matrix(1.3333 0 0 -1.3333 -26.831 636.63)"><g clip-path="url(#clipPath18)"><g clip-path="url(#clipPath26)" opacity=".41"><g transform="translate(479.21 201.52)"><path d="m0 0c0.428 7.37 0.236 14.775-0.595 22.107-3.903 34.45-21.577 66.935-47.59 89.856-9.28 8.178-19.839 15.503-25.878 26.297-10.172 18.178-9.402 39.07-22.025 57.018-12.638 17.969-31.055 31.982-51.824 39.179-61.926 21.457-148.62-13.48-140.82-88.091 0.027-0.268 0.058-0.657 0.091-1.15 1.037-15.498-11.126-28.528-26.608-28.896-57.135-1.356-106.32-45.406-116.84-101.21-6.768-35.885 4.314-75.218 30.564-100.6 19.594-18.95 45.885-29.361 72.188-36.514 52.739-14.343 108.24-17.35 162.62-11.865 50.902 5.134 104.59 19.767 137.51 58.929 17.56 20.89 27.621 47.68 29.205 74.94" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath42)" opacity=".31"><g transform="translate(230.81 454.61)"><path d="m0 0c0-7.341-5.951-13.293-13.292-13.293-7.342 0-13.293 5.952-13.293 13.293 0 7.342 5.951 13.293 13.293 13.293 7.341 0 13.292-5.951 13.292-13.293" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath58)" opacity=".31"><g transform="translate(404 462.72)"><path d="m0 0c0-3.788-3.07-6.859-6.858-6.859s-6.86 3.071-6.86 6.859 3.072 6.858 6.86 6.858 6.858-3.07 6.858-6.858" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath74)" opacity=".31"><g transform="translate(164.21 424.86)"><path d="m0 0c0-5.076-4.115-9.19-9.19-9.19-5.077 0-9.191 4.114-9.191 9.19s4.114 9.191 9.191 9.191c5.075 0 9.19-4.115 9.19-9.191" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath90)" opacity=".31"><g transform="translate(69.961 91.524)"><path d="m0 0c0-11.558-9.37-20.927-20.927-20.927-11.558 0-20.927 9.369-20.927 20.927s9.369 20.928 20.927 20.928c11.557 0 20.927-9.37 20.927-20.928" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath106)" opacity=".47"><g transform="translate(473.51 418.05)"><path d="m0 0c5.966 11.621 1.381 25.877-10.239 31.842-11.62 5.966-33.95 5.526-39.915-6.094-5.966-11.621 11.918-21.593 19.211-32.43 10.171-15.113 24.977-4.938 30.943 6.682" fill="#ecf1f7"/></g></g><g clip-path="url(#clipPath122)" opacity=".47"><g transform="translate(422.7 60.898)"><path d="m0 0c8.408-5.429 19.624-3.013 25.052 5.395 5.427 8.407 6.783 25.464-1.624 30.892s-17.365-7.451-26.179-12.191c-12.292-6.61-5.656-18.668 2.751-24.096" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath138)" opacity=".47"><g transform="translate(79.536 471.37)"><path d="m0 0c-9.248 8.588-23.706 8.053-32.294-1.195-8.588-9.247-14.019-30.131-4.772-38.719 9.248-8.588 23.201 5.438 35.187 9.386 16.718 5.507 11.127 21.94 1.879 30.528" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath154)" opacity=".47"><g transform="translate(28.561 371.54)"><path d="m0 0c-8.244-17.898-10.496-38.532-6.54-57.822 4.65-22.678 18.769-40.101 13.87-64.294-2.984-14.736-3.731-28.387-5.244-42.967-3.107-29.941 16.332-56.322 40.448-70.567 19.586-11.571 42.549-15.912 65.069-15.602 20.267 0.277 40.5 4.02 60.139 9.052 18.927 4.85 37.432 11.241 57.271 9.224 16.499-1.676 31.36-8.81 46.726-14.129 36.685-12.698 81.124-14.489 114.67 4.842 21.528 12.407 36.597 32.555 43.281 54.218 5.341 17.311 6.018 33.501 2.015 51.174-4.111 18.147-11.05 36.44-8.895 55.348 1.502 13.175 7.528 25.893 6.424 39.108-0.734 8.78-4.6 17.019-9.327 24.454-17.262 27.149-46.166 45.326-76.74 55.341-28.773 9.426-58.446 16.251-88.402 13.983-61.936-4.688-74.562 5.15-137.86 18.688-40.863 8.74-86.572-22.416-110.48-58.508-2.439-3.681-4.58-7.543-6.423-11.543" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath170)" opacity=".81"><g transform="translate(71.173 343.64)"><path d="m0 0c-1.271-14.292 3.55-29.02-0.479-43.174-4.824-16.946-18.788-29.639-24.48-46.276-8.411-24.583-8.007-52.131 2.208-76.086 4.922-11.546 12.113-22.275 21.934-29.695 15.138-11.439 34.975-13.948 53.63-12.497 27.764 2.16 57.06 14.179 84.975 10.901 15.404-1.809 20.108-18.482 28.063-29.479 8.998-12.438 21.252-22.209 34.799-28.712 24.952-11.978 54.898-13.112 80.4-2.251 27.227 11.596 50.957 39.914 49.398 71.938-0.722 14.815-6.653 29.53-3.906 44.088 3.445 18.268 17.21 34.917 27.185 49.802 11.017 16.439 17.686 36.043 18.993 56.043 0.015 0.227 0.03 0.454 0.043 0.68 2.045 34.503-19.718 65.971-52.551 76.769 0 0-69.859 22.976-69.862 22.976-70.886 23.313-141.71 22.543-206.89-11.672-14.104-7.403-37.068-29.463-41.798-44.674-0.893-2.869-1.405-5.766-1.664-8.681" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath186)" opacity=".58"><g transform="translate(472.15 118.42)"><path d="m0 0c0-2.485-2.015-4.5-4.5-4.5s-4.5 2.015-4.5 4.5 2.015 4.5 4.5 4.5 4.5-2.015 4.5-4.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath202)" opacity=".58"><g transform="translate(264.27 469.14)"><path d="m0 0c0-2.485-2.015-4.5-4.5-4.5s-4.5 2.015-4.5 4.5 2.015 4.5 4.5 4.5 4.5-2.015 4.5-4.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath218)" opacity=".58"><g transform="translate(101.71 76.922)"><path d="m0 0c0-2.485-2.015-4.5-4.5-4.5s-4.5 2.015-4.5 4.5 2.015 4.5 4.5 4.5 4.5-2.015 4.5-4.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath234)" opacity=".58"><g transform="translate(384.74 57.999)"><path d="m0 0c0-1.933-1.567-3.5-3.5-3.5s-3.5 1.567-3.5 3.5 1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5" fill="#ef929c"/></g></g><g clip-path="url(#clipPath250)" opacity=".58"><g transform="translate(78.842 392.5)"><path d="m0 0c0-0.829-0.671-1.5-1.5-1.5-0.828 0-1.5 0.671-1.5 1.5s0.672 1.5 1.5 1.5c0.829 0 1.5-0.671 1.5-1.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath266)" opacity=".58"><g transform="translate(396.86 437.24)"><path d="m0 0c-0.623-2.919-3.494-4.779-6.413-4.156s-4.779 3.494-4.156 6.413c0.624 2.919 3.495 4.78 6.414 4.156 2.918-0.623 4.779-3.495 4.155-6.413" fill="#ef929c"/></g></g><g clip-path="url(#clipPath282)" opacity=".58"><g transform="translate(108.07 462.08)"><path d="m0 0c-0.244-1.145-1.37-1.875-2.515-1.63-1.145 0.244-1.874 1.371-1.63 2.515 0.245 1.145 1.371 1.874 2.515 1.63 1.145-0.244 1.875-1.37 1.63-2.515" fill="#ef929c"/></g></g><g clip-path="url(#clipPath298)" opacity=".58"><g transform="translate(445.83 470.98)"><path d="m0 0c-0.207-0.973-1.164-1.593-2.138-1.385-0.972 0.207-1.592 1.164-1.384 2.137 0.207 0.973 1.165 1.594 2.137 1.386 0.973-0.208 1.593-1.165 1.385-2.138" fill="#3e479b"/></g></g><g clip-path="url(#clipPath314)" opacity=".58"><g transform="translate(64.778 41.356)"><path d="m0 0c-0.208-0.973-1.165-1.593-2.138-1.386-0.972 0.208-1.592 1.165-1.385 2.138 0.208 0.974 1.165 1.594 2.138 1.386s1.593-1.165 1.385-2.138" fill="#3e479b"/></g></g></g><g clip-path="url(#clipPath330)"><g clip-path="url(#clipPath338)" opacity=".66"><g transform="translate(143.2 276.91)"><path d="m0 0c-16.422 1.254-28.719 15.583-27.465 32.005s15.583 28.719 32.005 27.465 28.719-15.583 27.465-32.005c-1.254-16.423-15.583-28.719-32.005-27.465m51.214 33.339-7.958 0.608c-0.609 5.993-2.511 11.642-5.449 16.638l6.057 5.198c3.068 2.633 3.421 7.254 0.788 10.321-2.633 3.068-7.254 3.421-10.322 0.789l-6.057-5.198c-4.492 3.662-9.787 6.4-15.618 7.912l0.608 7.958c0.307 4.031-2.711 7.548-6.742 7.855-4.031 0.309-7.548-2.71-7.855-6.741l-0.608-7.958c-5.993-0.609-11.641-2.512-16.638-5.449l-5.198 6.057c-2.633 3.067-7.254 3.421-10.322 0.788-3.067-2.633-3.42-7.254-0.788-10.322l5.198-6.057c-3.662-4.492-6.4-9.787-7.912-15.618l-7.958 0.608c-4.031 0.308-7.548-2.711-7.856-6.742-0.307-4.03 2.711-7.548 6.742-7.856l7.958-0.607c0.609-5.993 2.511-11.642 5.449-16.638l-6.057-5.197c-3.068-2.633-3.421-7.254-0.788-10.323 2.633-3.068 7.254-3.42 10.322-0.787l6.057 5.197c4.492-3.662 9.787-6.4 15.618-7.912l-0.608-7.958c-0.307-4.03 2.711-7.548 6.742-7.856 4.03-0.307 7.548 2.711 7.856 6.742l0.607 7.958c5.993 0.609 11.642 2.511 16.638 5.449l5.198-6.057c2.633-3.068 7.254-3.42 10.322-0.788 3.068 2.633 3.42 7.254 0.787 10.322l-5.197 6.056c3.662 4.493 6.4 9.788 7.912 15.619l7.958-0.608c4.031-0.307 7.548 2.711 7.856 6.741 0.307 4.032-2.711 7.549-6.742 7.856" fill="#fff"/></g><g transform="translate(354.27 143.95)"><path d="m0 0c-2.008 0-4.024-0.309-5.992-0.932-5.036-1.594-9.15-5.054-11.582-9.743-2.434-4.687-2.896-10.043-1.301-15.078 1.595-5.036 5.055-9.149 9.743-11.582 4.69-2.435 10.046-2.894 15.078-1.301 5.036 1.595 9.15 5.055 11.582 9.743 2.434 4.688 2.896 10.043 1.301 15.079s-5.055 9.149-9.743 11.582c-2.856 1.482-5.959 2.232-9.086 2.232m-0.048-41.568c-3.444 0-6.86 0.826-10.006 2.458-5.162 2.679-8.971 7.208-10.727 12.753s-1.247 11.441 1.431 16.604c2.68 5.162 7.208 8.972 12.753 10.728 5.546 1.756 11.441 1.247 16.605-1.432 5.162-2.68 8.972-7.209 10.728-12.753 1.756-5.545 1.247-11.442-1.432-16.604-2.68-5.163-7.208-8.972-12.753-10.728-2.167-0.687-4.389-1.026-6.599-1.026m4.392-5.583 1.93-6.099c0.331-1.044 1.048-1.896 2.02-2.4 0.972-0.505 2.081-0.6 3.126-0.27 1.044 0.331 1.896 1.048 2.401 2.02 0.505 0.971 0.6 2.082 0.27 3.126l-1.932 6.097 0.74 0.39c3.539 1.862 6.57 4.411 9.008 7.576l0.51 0.662 5.678-2.945c0.971-0.505 2.081-0.601 3.126-0.271 1.044 0.331 1.896 1.048 2.4 2.021 1.041 2.005 0.256 4.484-1.75 5.526l-5.678 2.947 0.248 0.798c1.186 3.816 1.526 7.761 1.012 11.726l-0.108 0.83 6.098 1.931c2.155 0.682 3.353 2.991 2.671 5.145-0.331 1.044-1.048 1.897-2.02 2.402-0.97 0.504-2.081 0.599-3.125 0.269l-6.098-1.932-0.39 0.741c-1.862 3.539-4.411 6.57-7.577 9.007l-0.663 0.51 2.947 5.678c1.041 2.006 0.256 4.485-1.75 5.526-2.008 1.044-4.486 0.256-5.526-1.75l-2.947-5.677-0.799 0.248c-3.815 1.185-7.76 1.523-11.726 1.011l-0.83-0.108-1.93 6.099c-0.33 1.044-1.048 1.896-2.02 2.4-0.972 0.505-2.079 0.601-3.126 0.271-2.154-0.683-3.352-2.992-2.671-5.147l1.932-6.097-0.74-0.389c-3.539-1.864-6.57-4.412-9.007-7.577l-0.51-0.664-5.679 2.948c-0.97 0.505-2.081 0.599-3.125 0.269-1.044-0.331-1.896-1.048-2.4-2.02-0.505-0.972-0.601-2.081-0.271-3.125 0.332-1.044 1.048-1.897 2.021-2.401l5.677-2.947-0.248-0.799c-1.186-3.815-1.526-7.76-1.012-11.725l0.108-0.83-6.098-1.931c-1.044-0.33-1.897-1.048-2.401-2.02-0.505-0.971-0.599-2.082-0.269-3.126 0.682-2.154 2.991-3.354 5.145-2.67l6.098 1.931 0.39-0.74c1.862-3.539 4.411-6.569 7.576-9.007l0.662-0.51-2.945-5.678c-0.505-0.972-0.601-2.081-0.271-3.125 0.331-1.044 1.048-1.897 2.021-2.401 2.005-1.042 4.485-0.255 5.526 1.75l2.947 5.677 0.799-0.248c3.815-1.186 7.763-1.523 11.725-1.012zm5.831-10.963c-0.964 0-1.921 0.231-2.802 0.688-1.445 0.75-2.513 2.019-3.005 3.572l-1.43 4.515c-3.695-0.377-7.366-0.059-10.938 0.943l-2.182-4.203c-1.549-2.984-5.239-4.152-8.223-2.603-1.447 0.75-2.513 2.018-3.005 3.572-0.492 1.553-0.35 3.204 0.401 4.651l2.181 4.203c-2.876 2.343-5.248 5.165-7.068 8.402l-4.514-1.43c-3.207-1.015-6.641 0.768-7.655 3.974-0.493 1.553-0.35 3.204 0.4 4.65 0.751 1.447 2.019 2.514 3.572 3.005l4.515 1.43c-0.376 3.694-0.06 7.366 0.943 10.939l-4.203 2.182c-1.446 0.75-2.513 2.019-3.005 3.572s-0.349 3.204 0.402 4.651c0.75 1.445 2.018 2.512 3.572 3.005 1.552 0.491 3.204 0.349 4.65-0.401l4.203-2.182c2.344 2.875 5.165 5.249 8.403 7.069l-1.43 4.514c-1.015 3.206 0.768 6.64 3.974 7.656 1.55 0.492 3.204 0.348 4.65-0.402 1.446-0.751 2.514-2.019 3.005-3.572l1.43-4.515c3.695 0.378 7.366 0.06 10.939-0.943l2.182 4.204c1.549 2.985 5.235 4.154 8.223 2.604 2.984-1.55 4.152-5.239 2.604-8.224l-2.182-4.202c2.876-2.345 5.249-5.166 7.069-8.403l4.514 1.429c1.554 0.492 3.204 0.35 4.651-0.4 1.446-0.751 2.512-2.02 3.005-3.573 1.014-3.206-0.768-6.64-3.974-7.656l-4.515-1.429c0.376-3.695 0.06-7.366-0.943-10.94l4.204-2.18c2.984-1.55 4.152-5.24 2.603-8.224-0.75-1.446-2.018-2.514-3.572-3.005-1.552-0.492-3.203-0.349-4.651 0.401l-4.202 2.181c-2.346-2.876-5.166-5.248-8.404-7.067l1.43-4.515c0.492-1.553 0.35-3.205-0.4-4.65-0.751-1.447-2.02-2.514-3.574-3.005-0.607-0.193-1.229-0.288-1.848-0.288" fill="#fff"/></g><g transform="translate(440.19 153.6)"><path d="m0 0h0.01zm-16.757 49.302c-5.761 0-11.345-1.844-16.045-5.352-11.895-8.878-14.35-25.78-5.472-37.677 8.878-11.895 25.779-14.347 37.676-5.471 5.762 4.301 9.505 10.588 10.538 17.704 1.035 7.116-0.765 14.209-5.066 19.972-4.301 5.762-10.588 9.505-17.704 10.539-1.313 0.19-2.624 0.285-3.927 0.285m0.093-55.835c-8.824 0-17.542 4.012-23.214 11.61-9.537 12.781-6.899 30.939 5.881 40.477 6.191 4.619 13.813 6.554 21.454 5.442 7.646-1.11 14.4-5.132 19.021-11.323 4.62-6.191 6.552-13.81 5.442-21.454-1.11-7.646-5.131-14.401-11.322-19.021-5.181-3.866-11.246-5.731-17.262-5.731m-26.288 2.012 0.611-0.571c3.956-3.702 8.572-6.449 13.718-8.167l0.793-0.264-1.194-8.222c-0.464-3.193 1.757-6.17 4.951-6.635 3.194-0.463 6.171 1.757 6.635 4.951l1.194 8.224 0.836 0.027c5.422 0.182 10.629 1.503 15.474 3.926l0.748 0.374 4.97-6.659c0.935-1.253 2.302-2.067 3.85-2.291 1.549-0.228 3.089 0.166 4.343 1.101 2.585 1.931 3.12 5.606 1.188 8.192l-4.969 6.659 0.572 0.611c3.701 3.955 6.449 8.571 8.167 13.718l0.264 0.793 8.222-1.194c3.198-0.461 6.169 1.758 6.635 4.951 0.463 3.193-1.758 6.17-4.952 6.635l-8.223 1.194-0.027 0.836c-0.182 5.423-1.503 10.629-3.926 15.474l-0.374 0.748 6.658 4.97c2.587 1.93 3.121 5.605 1.19 8.192-0.934 1.253-2.301 2.066-3.849 2.291-1.547 0.226-3.089-0.167-4.343-1.102h1e-3l-6.659-4.97-0.612 0.572c-3.956 3.703-8.572 6.45-13.717 8.167l-0.793 0.264 1.194 8.223c0.225 1.547-0.167 3.089-1.102 4.342s-2.302 2.067-3.849 2.292c-3.203 0.466-6.17-1.758-6.635-4.951l-1.194-8.223-0.836-0.027c-5.421-0.182-10.627-1.503-15.474-3.926l-0.748-0.374-4.971 6.658c-0.934 1.254-2.301 2.067-3.848 2.292-1.546 0.223-3.089-0.167-4.342-1.102-1.254-0.935-2.067-2.302-2.292-3.849-0.225-1.548 0.166-3.09 1.102-4.343l4.969-6.658-0.571-0.611c-3.703-3.956-6.45-8.573-8.167-13.718l-0.265-0.793-8.222 1.194c-1.545 0.222-3.089-0.168-4.342-1.102-1.253-0.935-2.067-2.302-2.292-3.849-0.464-3.194 1.758-6.171 4.951-6.635l8.223-1.194 0.027-0.836c0.182-5.421 1.503-10.627 3.927-15.475l0.374-0.748-6.66-4.969c-1.252-0.935-2.067-2.302-2.291-3.85-0.225-1.547 0.167-3.089 1.102-4.343 0.935-1.252 2.302-2.066 3.849-2.291 1.546-0.223 3.089 0.167 4.343 1.103zm19.725-25.92c-0.374 0-0.752 0.027-1.133 0.083-4.286 0.623-7.266 4.616-6.643 8.9l0.955 6.576c-4.841 1.728-9.221 4.335-13.042 7.763l-5.325-3.974c-1.682-1.255-3.749-1.78-5.825-1.477-2.076 0.3-3.91 1.392-5.165 3.074-2.59 3.471-1.874 8.401 1.596 10.991l5.326 3.974c-2.201 4.639-3.455 9.58-3.733 14.711l-6.575 0.956c-4.285 0.622-7.266 4.615-6.643 8.9 0.301 2.076 1.393 3.91 3.075 5.165 1.681 1.254 3.75 1.778 5.825 1.478l6.577-0.955c1.727 4.84 4.334 9.22 7.763 13.042l-3.975 5.324c-1.254 1.681-1.779 3.751-1.477 5.826 0.301 2.076 1.393 3.91 3.075 5.165 1.68 1.255 3.749 1.779 5.825 1.479 2.076-0.302 3.91-1.394 5.165-3.076l3.975-5.324c4.638 2.199 9.58 3.453 14.71 3.732l0.956 6.575c0.623 4.286 4.627 7.268 8.9 6.642 2.076-0.3 3.91-1.392 5.165-3.074 1.255-1.681 1.779-3.75 1.478-5.825l-0.956-6.577c4.841-1.727 9.221-4.334 13.042-7.763l5.326 3.975c3.467 2.589 8.399 1.875 10.991-1.598 2.59-3.47 1.873-8.4-1.598-10.99l-5.324-3.975c2.199-4.637 3.453-9.578 3.731-14.71l6.577-0.956c4.285-0.623 7.264-4.616 6.642-8.9-0.623-4.286-4.625-7.27-8.9-6.643l-6.576 0.955c-1.728-4.841-4.335-9.221-7.763-13.042l3.974-5.325c2.589-3.469 1.874-8.399-1.596-10.991-1.682-1.254-3.751-1.778-5.827-1.478-2.076 0.302-3.91 1.394-5.165 3.076l-3.974 5.324c-4.639-2.199-9.579-3.453-14.711-3.732l-0.956-6.576c-0.566-3.904-3.932-6.724-7.767-6.725" fill="#fff"/></g></g><g clip-path="url(#clipPath362)" opacity=".81"><g transform="translate(287.66 119.14)"><path d="m0 0h-20.542c-0.553 0-1 0.447-1 1s0.447 1 1 1h20.542c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(287.66 97.783)"><path d="m0 0h-20.542c-0.553 0-1 0.447-1 1s0.447 1 1 1h20.542c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(176.3 145.49)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-65.849c0-0.391 0.319-0.71 0.711-0.71h126.87c0.392 0 0.712 0.319 0.712 0.71v65.849c0 0.393-0.32 0.712-0.712 0.712zm126.87-69.271h-126.87c-1.495 0-2.711 1.215-2.711 2.71v65.849c0 1.495 1.216 2.712 2.711 2.712h126.87c1.495 0 2.712-1.217 2.712-2.712v-65.849c0-1.495-1.217-2.71-2.712-2.71" fill="#fff"/></g><g clip-path="url(#clipPath366)" opacity=".66"><g transform="translate(176.3 145.49)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-65.849c0-0.391 0.319-0.71 0.711-0.71h126.87c0.392 0 0.712 0.319 0.712 0.71v65.849c0 0.393-0.32 0.712-0.712 0.712zm126.87-69.271h-126.87c-1.495 0-2.711 1.215-2.711 2.71v65.849c0 1.495 1.216 2.712 2.711 2.712h126.87c1.495 0 2.712-1.217 2.712-2.712v-65.849c0-1.495-1.217-2.71-2.712-2.71" fill="#fff"/></g></g><g transform="translate(287.66 129.5)"><path d="m0 0h-97.889c-0.552 0-1 0.447-1 1s0.448 1 1 1h97.889c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(287.66 108.77)"><path d="m0 0h-97.889c-0.552 0-1 0.447-1 1s0.448 1 1 1h97.889c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(242.55 119.14)"><path d="m0 0h-52.776c-0.552 0-1 0.447-1 1s0.448 1 1 1h52.776c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(242.55 97.783)"><path d="m0 0h-52.776c-0.552 0-1 0.447-1 1s0.448 1 1 1h52.776c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(225.36 87.891)"><path d="m0 0h-35.592c-0.552 0-1 0.447-1 1s0.448 1 1 1h35.592c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g></g><g clip-path="url(#clipPath422)" opacity=".81"><g transform="translate(91.118 183.16)"><path d="m0 0h-23.088c-0.553 0-1 0.447-1 1s0.447 1 1 1h23.088c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(91.118 207.16)"><path d="m0 0h-23.088c-0.553 0-1 0.447-1 1s0.447 1 1 1h23.088c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(50.389 231.4)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-74.434c0-0.392 0.319-0.711 0.711-0.711h143.02c0.392 0 0.711 0.319 0.711 0.711v74.434c0 0.393-0.319 0.712-0.711 0.712zm143.02-77.857h-143.02c-1.495 0-2.711 1.216-2.711 2.711v74.434c0 1.495 1.216 2.712 2.711 2.712h143.02c1.495 0 2.711-1.217 2.711-2.712v-74.434c0-1.495-1.216-2.711-2.711-2.711" fill="#fff"/></g><g clip-path="url(#clipPath426)" opacity=".66"><g transform="translate(50.389 231.4)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-74.434c0-0.392 0.319-0.711 0.711-0.711h143.02c0.392 0 0.711 0.319 0.711 0.711v74.434c0 0.393-0.319 0.712-0.711 0.712zm143.02-77.857h-143.02c-1.495 0-2.711 1.216-2.711 2.711v74.434c0 1.495 1.216 2.712 2.711 2.712h143.02c1.495 0 2.711-1.217 2.711-2.712v-74.434c0-1.495-1.216-2.711-2.711-2.711" fill="#fff"/></g></g><g transform="translate(178.05 171.52)"><path d="m0 0h-110.02c-0.552 0-1 0.447-1 1s0.448 1 1 1h110.02c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 194.81)"><path d="m0 0h-110.02c-0.552 0-1 0.447-1 1s0.448 1 1 1h110.02c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 183.16)"><path d="m0 0h-59.316c-0.553 0-1 0.447-1 1s0.447 1 1 1h59.316c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 207.16)"><path d="m0 0h-59.316c-0.553 0-1 0.447-1 1s0.447 1 1 1h59.316c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 218.28)"><path d="m0 0h-40.003c-0.552 0-1 0.447-1 1s0.448 1 1 1h40.003c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g></g><g clip-path="url(#clipPath482)" opacity=".14"><g transform="translate(359.99 113.13)"><path d="m0 0-109.42 64.872c-0.879 0.522-1.17 1.657-0.648 2.537l88.33 148.98c0.521 0.879 1.656 1.17 2.536 0.648l109.42-64.873c0.88-0.521 1.17-1.657 0.648-2.537l-88.329-148.98c-0.521-0.878-1.657-1.168-2.537-0.647" fill="#3e479b"/></g></g><g transform="translate(357.14 119.1)"><path d="m0 0-109.42 64.873c-0.879 0.522-1.17 1.657-0.648 2.537l88.329 148.98c0.521 0.879 1.657 1.169 2.537 0.648l109.42-64.873c0.88-0.522 1.17-1.657 0.648-2.537l-88.329-148.98c-0.521-0.878-1.657-1.169-2.537-0.648" fill="#f7a9b4"/></g><g clip-path="url(#clipPath502)" opacity=".14"><g transform="translate(388.57 120.93)"><path d="m0 0-125.1 23.06c-1.005 0.185-1.67 1.15-1.484 2.156l31.396 170.33c0.186 1.006 1.152 1.671 2.157 1.485l125.1-23.059c1.005-0.185 1.67-1.151 1.485-2.156l-31.397-170.33c-0.185-1.006-1.151-1.671-2.156-1.485" fill="#3e479b"/></g></g><g transform="translate(387.72 125.38)"><path d="m0 0-128.74 23.73 32.068 173.97 128.74-23.73z" fill="#fff"/></g><g clip-path="url(#clipPath522)" opacity=".39"><g transform="translate(385.9 125.72)"><path d="m0 0-125.1 23.06c-1.005 0.185-1.67 1.15-1.484 2.156l31.396 170.33c0.186 1.006 1.151 1.671 2.157 1.485l125.1-23.059c1.006-0.185 1.671-1.151 1.486-2.156l-31.397-170.33c-0.185-1.006-1.151-1.671-2.156-1.485" fill="#f7a9b4"/></g></g><g transform="translate(400.31 278.86)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-31.314 5.772c-0.543 0.1-0.902 0.621-0.802 1.164 0.101 0.543 0.615 0.901 1.165 0.802l31.315-5.772c0.543-0.1 0.902-0.621 0.801-1.164-0.088-0.482-0.508-0.819-0.982-0.819" fill="#fff"/></g><g transform="translate(398.46 268.86)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-31.314 5.772c-0.543 0.1-0.902 0.622-0.802 1.165 0.101 0.542 0.616 0.901 1.165 0.802l31.315-5.773c0.543-0.1 0.902-0.621 0.801-1.164-0.088-0.482-0.508-0.819-0.982-0.819" fill="#fff"/></g><g transform="translate(396.46 257.98)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-31.314 5.772c-0.543 0.1-0.902 0.621-0.802 1.164s0.614 0.901 1.165 0.802l31.315-5.772c0.543-0.1 0.902-0.621 0.801-1.164-0.088-0.482-0.509-0.819-0.982-0.819" fill="#fff"/></g><g clip-path="url(#clipPath550)" opacity=".14"><g transform="translate(348.01 248.74)"><path d="m0 0-53.652 9.89c-1.089 0.2-1.809 1.245-1.609 2.334l10.636 57.7c0.201 1.088 1.246 1.808 2.335 1.608l53.652-9.89c1.089-0.201 1.809-1.246 1.608-2.334l-10.636-57.701c-0.2-1.088-1.246-1.808-2.334-1.607" fill="#3e479b"/></g></g><g transform="translate(346.04 252.09)"><path d="m0 0-51.148 9.428c-1.089 0.201-1.809 1.246-1.609 2.335l10.07 54.628c0.201 1.088 1.247 1.808 2.334 1.608l51.149-9.429c1.089-0.2 1.808-1.245 1.608-2.334l-10.07-54.628c-0.2-1.088-1.245-1.809-2.334-1.608" fill="#599af2"/></g><g clip-path="url(#clipPath570)" opacity=".070007"><g transform="translate(357.49 303.17)"><path d="m0 0-55.091 10.155 0.961 5.213c0.194 1.056 1.209 1.755 2.266 1.56l51.333-9.462c1.018-0.188 1.692-1.166 1.505-2.184z" fill="#ecf1f7"/></g></g><g transform="translate(317.82 286.15)"><path d="m0 0c-0.388 0-0.781 0.035-1.176 0.108l-0.762 0.141c-4.05 0.746-6.739 4.649-5.993 8.7l1.924 10.439c0.151 0.815 0.939 1.355 1.747 1.203 0.816-0.15 1.354-0.932 1.204-1.747l-1.923-10.439c-0.448-2.424 1.161-4.759 3.584-5.206l0.763-0.141c1.885-0.35 3.699 0.903 4.046 2.788l4.871 26.422c0.359 1.944-0.931 3.818-2.876 4.177l-1.305 0.24c-2.072 0.381-4.053-0.99-4.435-3.054l-0.119-0.652c-0.152-0.815-0.943-1.353-1.747-1.203-0.815 0.15-1.354 0.932-1.204 1.746l0.12 0.653c0.682 3.692 4.24 6.142 7.928 5.46l1.305-0.24c3.571-0.658 5.942-4.099 5.284-7.67l-4.871-26.423c-0.575-3.116-3.304-5.302-6.365-5.302" fill="#3e479b"/></g><g transform="translate(323.02 308.34)"><path d="m0 0c-0.03 0-0.061 2e-3 -0.092 8e-3l-19.989 3.685c-0.272 0.05-0.451 0.31-0.401 0.582s0.307 0.455 0.583 0.401l19.989-3.684c0.271-0.05 0.451-0.311 0.401-0.583-0.045-0.241-0.255-0.409-0.491-0.409" fill="#fff"/></g><g transform="translate(384.14 205)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-95.683 17.637c-0.543 0.1-0.903 0.621-0.802 1.165 0.101 0.542 0.614 0.905 1.165 0.802l95.684-17.638c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.508-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(377.3 167.89)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-95.684 17.636c-0.543 0.1-0.903 0.621-0.802 1.165 0.1 0.542 0.615 0.907 1.165 0.802l95.685-17.637c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.509-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(330.27 195.75)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-45.232 8.337c-0.543 0.1-0.902 0.622-0.802 1.166 0.101 0.542 0.615 0.907 1.165 0.801l45.233-8.338c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.509-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(336.5 229.56)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-45.232 8.337c-0.543 0.1-0.902 0.622-0.802 1.165 0.101 0.542 0.616 0.9 1.165 0.801l45.233-8.337c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.508-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(380.75 186.59)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-43.096 7.944c-0.543 0.1-0.903 0.621-0.802 1.165 0.1 0.542 0.614 0.904 1.165 0.802l43.097-7.945c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.508-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(370.62 383.15)"><path d="m0 0h-53.181c-1.84 0-3.333 1.492-3.333 3.333v17.787c0 1.84 1.493 3.333 3.333 3.333h53.181c1.841 0 3.333-1.493 3.333-3.333v-17.787c0-1.841-1.492-3.333-3.333-3.333" fill="#599af2"/></g><g transform="translate(410.68 356.49)"><path d="m0 0h-74.39c-1.84 0-3.333 1.492-3.333 3.333v26.453c0 1.84 1.493 3.333 3.333 3.333h74.39c1.841 0 3.333-1.493 3.333-3.333v-26.453c0-1.841-1.492-3.333-3.333-3.333" fill="#f7a9b4"/></g><g transform="translate(352.77 363.49)"><path d="m0 0h82.375c2.489 0 4.525-2.036 4.525-4.525v-25.235c0-2.488-2.036-4.524-4.525-4.524h-82.375c-2.489 0-4.525 2.036-4.525 4.524v25.235c0 2.489 2.036 4.525 4.525 4.525" fill="#fff"/></g><g clip-path="url(#clipPath626)" opacity=".74"><g transform="translate(352.77 363.49)"><path d="m0 0h82.375c2.489 0 4.525-2.036 4.525-4.525v-25.235c0-2.488-2.036-4.524-4.525-4.524h-82.375c-2.489 0-4.525 2.036-4.525 4.524v25.235c0 2.489 2.036 4.525 4.525 4.525" fill="#6d6cd4"/></g></g><g transform="translate(410.65 349.28)"><path d="m0 0c-1.639 0-2.972-1.333-2.972-2.972 0-1.638 1.333-2.971 2.972-2.971s2.972 1.333 2.972 2.971c0 1.639-1.333 2.972-2.972 2.972m0-6.943c-2.19 0-3.972 1.781-3.972 3.971s1.782 3.972 3.972 3.972 3.972-1.782 3.972-3.972-1.782-3.971-3.972-3.971" fill="#fff"/></g><g transform="translate(394.26 349.28)"><path d="m0 0c-1.639 0-2.972-1.333-2.972-2.972 0-1.638 1.333-2.971 2.972-2.971s2.972 1.333 2.972 2.971c0 1.639-1.333 2.972-2.972 2.972m0-6.943c-2.19 0-3.972 1.781-3.972 3.971s1.782 3.972 3.972 3.972 3.972-1.782 3.972-3.972-1.782-3.971-3.972-3.971" fill="#fff"/></g><g transform="translate(378.99 349.28)"><path d="m0 0c-1.639 0-2.972-1.333-2.972-2.972 0-1.638 1.333-2.971 2.972-2.971s2.972 1.333 2.972 2.971c0 1.639-1.333 2.972-2.972 2.972m0-6.943c-2.19 0-3.972 1.781-3.972 3.971s1.782 3.972 3.972 3.972 3.972-1.782 3.972-3.972-1.782-3.971-3.972-3.971" fill="#fff"/></g><g transform="translate(152.38 405.2)"><path d="m0 0h127.64c2.571 0 4.655-2.084 4.655-4.655v-188c0-8.869-7.189-16.058-16.058-16.058h-88.627c-18.899 0-34.219 15.32-34.219 34.218v167.89c0 3.65 2.958 6.608 6.607 6.608" fill="#fff"/></g><g clip-path="url(#clipPath658)" opacity=".39"><g transform="translate(147.39 405.2)"><path d="m0 0h134.78c1.379 0 2.496-1.117 2.496-2.496v-190.91c0-8.456-6.855-15.31-15.311-15.31h-92.416c-17.219 0-31.178 13.958-31.178 31.176v175.92c0 0.897 0.728 1.625 1.625 1.625" fill="#6d6cd4"/></g></g><g clip-path="url(#clipPath674)" opacity=".39"><g transform="translate(159.21 405.2)"><path d="m0 0h123.49c1.09 0 1.973-0.884 1.973-1.974v-191.96c0-8.167-6.621-14.788-14.789-14.788h-81.122c-16.93 0-30.656 13.724-30.656 30.655v176.96c0 0.609 0.494 1.103 1.103 1.103" fill="#3e479b"/></g></g><g transform="translate(177.49 196.52)"><path d="m0 0v-0.036h111.57c12.841 0 23.251 10.41 23.251 23.251v8.832h-112.83v-8.832c0-12.417-9.735-22.56-21.989-23.215" fill="#6161b5"/></g><g clip-path="url(#clipPath694)" opacity=".28"><g transform="translate(192.28 196.52)"><path d="m0 0v-0.036h99.328c11.432 0 20.7 10.41 20.7 23.251v8.832h-100.45v-8.832c0-12.417-8.667-22.56-19.577-23.215" fill="#3e479b"/></g></g><g transform="translate(263.59 252.63)"><path d="m0 0h-80.219c-0.552 0-1 0.448-1 1s0.448 1 1 1h80.219c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(265.27 286.4)"><path d="m0 0h-83.401c-0.553 0-1 0.448-1 1s0.447 1 1 1h83.401c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(223.48 269.53)"><path d="m0 0h-42.616c-0.552 0-1 0.448-1 1s0.448 1 1 1h42.616c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(220.25 269.53)"><path d="m0 0h-36.159c-0.552 0-1 0.448-1 1s0.448 1 1 1h36.159c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(237.35 322.52)"><path d="m0 0h-54.901c-0.552 0-1 0.448-1 1s0.448 1 1 1h54.901c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(262.8 322.52)"><path d="m0 0h-16.724c-0.552 0-1 0.448-1 1s0.448 1 1 1h16.724c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(265.27 305.64)"><path d="m0 0h-59.45c-0.552 0-1 0.448-1 1s0.448 1 1 1h59.45c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(199.95 305.64)"><path d="m0 0h-18.08c-0.552 0-1 0.448-1 1s0.448 1 1 1h18.08c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(263.59 336.8)"><path d="m0 0h-80.219c-0.552 0-1 0.448-1 1s0.448 1 1 1h80.219c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(263.59 370.58)"><path d="m0 0h-80.219c-0.552 0-1 0.448-1 1s0.448 1 1 1h80.219c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(212.81 353.71)"><path d="m0 0h-30.361c-0.553 0-1 0.448-1 1s0.447 1 1 1h30.361c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(262.98 353.71)"><path d="m0 0h-36.159c-0.552 0-1 0.448-1 1s0.448 1 1 1h36.159c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g clip-path="url(#clipPath758)" opacity=".21001"><g transform="translate(326.1 344.9)"><path d="m0 0c-34.955 0-63.292-28.336-63.292-63.292 0-34.955 28.337-63.291 63.292-63.291s63.292 28.336 63.292 63.291c0 34.956-28.337 63.292-63.292 63.292" fill="#fff"/></g></g><g clip-path="url(#clipPath774)" opacity=".76"><g transform="translate(276.5 277.06)"><path d="m0 0c-2.209 0-4 1.791-4 4 0 31.929 25.976 57.904 57.904 57.904 2.209 0 4-1.791 4-4s-1.791-4-4-4c-27.517 0-49.904-22.387-49.904-49.904 0-2.209-1.791-4-4-4" fill="#fff"/></g></g><g clip-path="url(#clipPath790)" opacity=".58"><g transform="translate(326.1 342.9)"><path d="m0 0c-33.797 0-61.292-27.496-61.292-61.292 0-33.797 27.495-61.292 61.292-61.292s61.292 27.495 61.292 61.292c0 33.796-27.495 61.292-61.292 61.292m0-126.58c-36.002 0-65.292 29.29-65.292 65.292s29.29 65.292 65.292 65.292 65.292-29.29 65.292-65.292-29.29-65.292-65.292-65.292" fill="#3e479b"/></g></g><g transform="translate(326.1 218.31)"><path d="m0 0c-34.955 0-63.292 28.337-63.292 63.292s28.337 63.291 63.292 63.291 63.292-28.336 63.292-63.291-28.337-63.292-63.292-63.292m58.175 17.943c0.093 0.094 0.197 0.168 0.3 0.245 9.638 12.478 15.383 28.117 15.383 45.104 0 40.791-33.067 73.858-73.858 73.858s-73.858-33.067-73.858-73.858 33.067-73.858 73.858-73.858c16.916 0 32.487 5.708 44.939 15.274l8.544 8.545z" fill="#3e479b"/></g><g transform="translate(326.1 343.9)"><path d="m0 0c-34.348 0-62.292-27.944-62.292-62.292 0-34.349 27.944-62.292 62.292-62.292s62.292 27.943 62.292 62.292c0 34.348-27.944 62.292-62.292 62.292m0-126.58c-35.451 0-64.292 28.841-64.292 64.292s28.841 64.292 64.292 64.292 64.292-28.841 64.292-64.292-28.841-64.292-64.292-64.292m0 137.15c-40.174 0-72.858-32.684-72.858-72.858 0-40.175 32.684-72.858 72.858-72.858 16.149 0 31.459 5.196 44.278 15.028l13.19 13.188c0.094 0.095 0.194 0.177 0.297 0.255 9.875 12.831 15.093 28.176 15.093 44.387 0 40.174-32.684 72.858-72.858 72.858m0-147.72c-41.277 0-74.858 33.581-74.858 74.858s33.581 74.858 74.858 74.858 74.858-33.581 74.858-74.858c0-16.702-5.391-32.51-15.592-45.715l-0.188-0.185c-0.099-0.075-0.15-0.109-0.194-0.154l-13.335-13.322c-13.183-10.129-28.934-15.482-45.549-15.482" fill="#3e479b"/></g><g transform="translate(382.45 224.71)"><path d="m0 0-2.865 2.864c-1.103 1.103-1.103 2.891 0 3.993l-8.544-8.544-0.14-0.139c-1.102-1.103-1.102-2.891 0-3.993l3.477-3.477c1.147 1.922 4.501 5.685 8.072 9.296" fill="#4c65ba"/></g><g transform="translate(379.58 231.57)"><path d="m0 0c-1.103-1.103-1.103-2.891 0-3.993l2.865-2.864c3.455 3.494 7.102 6.832 9.148 8.218l-3.329 3.329c-1.009 1.01-2.586 1.084-3.693 0.246-0.102-0.078-0.207-0.152-0.3-0.246z" fill="#4c65ba"/></g><g clip-path="url(#clipPath822)" opacity=".42999"><g transform="translate(379.58 231.57)"><path d="m0 0c-1.103-1.103-1.103-2.891 0-3.993l2.865-2.864c3.455 3.494 7.102 6.832 9.148 8.218l-3.329 3.329c-1.009 1.01-2.586 1.084-3.693 0.246-0.102-0.078-0.207-0.152-0.3-0.246z" fill="#3e479b"/></g></g><g transform="translate(445.18 180.97)"><path d="m0 0-52.012 52.577c-0.187 0.19-0.757-0.061-1.575-0.617-2.046-1.387-5.692-4.725-9.147-8.219-3.572-3.611-6.925-7.374-8.073-9.296-0.373-0.625-0.517-1.059-0.353-1.224l52.012-52.578c5.287-5.346 13.86-5.346 19.148 0 5.287 5.345 5.287 14.011 0 19.357" fill="#599af2"/></g><g clip-path="url(#clipPath842)" opacity=".14"><g transform="translate(445.18 180.97)"><path d="m0 0-52.012 52.577c-0.7 0.708-6.627-4.601-11.716-9.848-4.33-4.464 58.44-67.432 63.728-62.086 5.287 5.345 5.287 14.011 0 19.357" fill="#3e479b"/></g></g><g transform="translate(253.12 246.25)"><path d="m0 0h-170.97c-9.988 0-18.085 8.097-18.085 18.085s8.097 18.085 18.085 18.085h170.97c9.988 0 18.086-8.097 18.086-18.085s-8.098-18.085-18.086-18.085" fill="#fff"/><path d="m0 0h-27.807l-0.134 36.17h27.941c9.988 0 18.086-8.097 18.086-18.085s-8.098-18.085-18.086-18.085" fill="#599af2"/></g><g transform="translate(246.08 271.82)"><path d="m0 0c-3.259 0-5.911-2.651-5.911-5.911 0-3.259 2.652-5.91 5.911-5.91 1.579 0 3.063 0.614 4.18 1.731 1.116 1.116 1.731 2.6 1.731 4.179 0 3.26-2.652 5.911-5.911 5.911m0-13.821c-4.362 0-7.911 3.549-7.911 7.91 0 4.362 3.549 7.911 7.911 7.911s7.911-3.549 7.911-7.911c0-2.113-0.823-4.1-2.317-5.593-1.494-1.495-3.481-2.317-5.594-2.317" fill="#fff"/></g><g transform="translate(257.21 253.71)"><path d="m0 0c-0.256 0-0.512 0.098-0.707 0.293l-6.276 6.276c-0.391 0.39-0.391 1.023 0 1.414s1.024 0.39 1.415 0l6.275-6.276c0.391-0.391 0.391-1.023 0-1.414-0.195-0.195-0.451-0.293-0.707-0.293" fill="#fff"/></g><g transform="translate(255.56 208.88)"><path d="m0 0h-85.1c-5.955 0-10.783 4.828-10.783 10.784v7.071c0 5.978-4.846 10.824-10.824 10.824h-39.306c-5.977 0-10.823-4.846-10.823-10.824v-112.33c0-5.567 4.513-10.08 10.081-10.08h146.76c5.567 0 10.08 4.513 10.08 10.08v84.396c0 5.567-4.513 10.081-10.08 10.081" fill="#f28393"/></g><g transform="translate(246.18 208.88)"><path d="m0 0h-85.099c-5.956 0-10.784 4.828-10.784 10.784v7.071c0 5.978-4.846 10.824-10.823 10.824h-39.307c-5.977 0-10.823-4.846-10.823-10.824v-112.33c0-5.567 4.513-10.08 10.081-10.08h146.76c5.567 0 10.081 4.513 10.081 10.08v84.396c0 5.567-4.514 10.081-10.081 10.081" fill="#f28393"/></g><g clip-path="url(#clipPath882)" opacity=".12"><g transform="translate(246.18 208.88)"><path d="m0 0h-85.099c-5.956 0-10.784 4.828-10.784 10.784v7.071c0 5.978-4.846 10.824-10.823 10.824h-39.307c-5.977 0-10.823-4.846-10.823-10.824v-112.33c0-5.567 4.513-10.08 10.081-10.08h146.76c5.567 0 10.081 4.513 10.081 10.08v84.396c0 5.567-4.514 10.081-10.081 10.081" fill="#fff"/></g></g><g clip-path="url(#clipPath898)" opacity=".12"><g transform="translate(224.6 208.88)"><path d="m0 0h-73.387c-5.136 0-9.3 4.828-9.3 10.784v7.071c0 5.978-4.179 10.824-9.334 10.824h-33.896c-5.155 0-9.334-4.846-9.334-10.824v-112.33c0-5.567 3.892-10.08 8.693-10.08h126.56c4.801 0 8.693 4.513 8.693 10.08v84.396c0 5.567-3.892 10.081-8.693 10.081" fill="#fff"/></g></g><g transform="translate(97.208 197.65)"><path d="m0 0c-0.552 0-1 0.447-1 1v24.539c0 3.801 3.092 6.893 6.892 6.893h28.965c0.552 0 1-0.448 1-1 0-0.553-0.448-1-1-1h-28.965c-2.697 0-4.892-2.195-4.892-4.893v-24.539c0-0.553-0.448-1-1-1" fill="#fff"/></g></g></g></svg>
<h1>This is a headline</h1>
<p>loreLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo</p>
<monster-button slot="action" class="monster-button-primary">Button</monster-button>
<monster-button slot="action">Button</monster-button>`;

<monster-state>
    <svg slot="visual" version="1.1" viewBox="0 0 612.41 583.39" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="clipPath18"><path d="m0 500h500v-500h-500z"/></clipPath><clipPath id="clipPath26"><path d="m45.178 442.22h434.25v-377.14h-434.25z"/></clipPath><clipPath id="clipPath42"><path d="m204.22 467.91h26.586v-26.586h-26.586z"/></clipPath><clipPath id="clipPath58"><path d="m390.28 469.58h13.717v-13.718h-13.717z"/></clipPath><clipPath id="clipPath74"><path d="m145.82 434.05h18.382v-18.382h-18.382z"/></clipPath><clipPath id="clipPath90"><path d="m28.108 112.45h41.854v-41.854h-41.854z"/></clipPath><clipPath id="clipPath106"><path d="m422.16 453.67h53.968v-49.906h-53.968z"/></clipPath><clipPath id="clipPath122"><path d="m413.19 98.497h38.944v-40.498h-38.944z"/></clipPath><clipPath id="clipPath138"><path d="m37.65 477.47h50.732v-48.756h-50.732z"/></clipPath><clipPath id="clipPath154"><path d="m20.124 443.07h442.71v-328.26h-442.71z"/></clipPath><clipPath id="clipPath170"><path d="m40.299 424.66h403.77v-345.77h-403.77z"/></clipPath><clipPath id="clipPath186"><path d="m463.15 122.92h9v-9h-9z"/></clipPath><clipPath id="clipPath202"><path d="m255.28 473.64h9v-9h-9z"/></clipPath><clipPath id="clipPath218"><path d="m92.708 81.422h9.0005v-9h-9.0005z"/></clipPath><clipPath id="clipPath234"><path d="m377.74 61.499h7v-7h-7z"/></clipPath><clipPath id="clipPath250"><path d="m75.842 394h3v-3h-3z"/></clipPath><clipPath id="clipPath266"><path d="m386.17 443.78h10.81v-10.81h-10.81z"/></clipPath><clipPath id="clipPath282"><path d="m103.88 464.64h4.24v-4.24h-4.24z"/></clipPath><clipPath id="clipPath298"><path d="m442.27 473.16h3.604v-3.603h-3.604z"/></clipPath><clipPath id="clipPath314"><path d="m61.215 43.533h3.6033v-3.6033h-3.6033z"/></clipPath><clipPath id="clipPath330"><path d="m0 500h500v-500h-500z"/></clipPath><clipPath id="clipPath338"><path d="m89.761 362.35h386.54v-276.52h-386.54z"/></clipPath><clipPath id="clipPath362"><path d="m173.59 147.49h132.29v-71.271h-132.29z"/></clipPath><clipPath id="clipPath366"><path d="m173.59 147.49h132.29v-71.271h-132.29z"/></clipPath><clipPath id="clipPath422"><path d="m47.677 233.4h148.44v-79.857h-148.44z"/></clipPath><clipPath id="clipPath426"><path d="m47.677 233.4h148.44v-79.857h-148.44z"/></clipPath><clipPath id="clipPath482"><path d="m249.66 330.43h201.45v-217.56h-201.45z"/></clipPath><clipPath id="clipPath502"><path d="m261.96 317.99h160.2v-197.09h-160.2z"/></clipPath><clipPath id="clipPath522"><path d="m259.29 322.78h160.2v-197.09h-160.2z"/></clipPath><clipPath id="clipPath550"><path d="m292.72 320.3h68.297v-71.599h-68.297z"/></clipPath><clipPath id="clipPath570"><path d="m302.4 320.13h56.096v-16.961h-56.096z"/></clipPath><clipPath id="clipPath626"><path d="m348.24 363.49h91.426v-34.284h-91.426z"/></clipPath><clipPath id="clipPath658"><path d="m145.77 405.2h138.9v-208.72h-138.9z"/></clipPath><clipPath id="clipPath674"><path d="m158.11 405.2h126.57v-208.72h-126.57z"/></clipPath><clipPath id="clipPath694"><path d="m192.28 228.57h120.03v-32.083h-120.03z"/></clipPath><clipPath id="clipPath758"><path d="m262.8 344.9h126.58v-126.58h-126.58z"/></clipPath><clipPath id="clipPath774"><path d="m272.5 338.96h61.904v-61.904h-61.904z"/></clipPath><clipPath id="clipPath790"><path d="m260.8 346.9h130.58v-130.58h-130.58z"/></clipPath><clipPath id="clipPath822"><path d="m378.75 237.08h12.84v-12.369h-12.84z"/></clipPath><clipPath id="clipPath842"><path d="m381.24 233.61h67.907v-72.32h-67.907z"/></clipPath><clipPath id="clipPath882"><path d="m89.344 237.56h166.92v-133.24h-166.92z"/></clipPath><clipPath id="clipPath898"><path d="m89.344 237.56h143.94v-133.24h-143.94z"/></clipPath></defs><g transform="matrix(1.3333 0 0 -1.3333 -26.831 636.63)"><g clip-path="url(#clipPath18)"><g clip-path="url(#clipPath26)" opacity=".41"><g transform="translate(479.21 201.52)"><path d="m0 0c0.428 7.37 0.236 14.775-0.595 22.107-3.903 34.45-21.577 66.935-47.59 89.856-9.28 8.178-19.839 15.503-25.878 26.297-10.172 18.178-9.402 39.07-22.025 57.018-12.638 17.969-31.055 31.982-51.824 39.179-61.926 21.457-148.62-13.48-140.82-88.091 0.027-0.268 0.058-0.657 0.091-1.15 1.037-15.498-11.126-28.528-26.608-28.896-57.135-1.356-106.32-45.406-116.84-101.21-6.768-35.885 4.314-75.218 30.564-100.6 19.594-18.95 45.885-29.361 72.188-36.514 52.739-14.343 108.24-17.35 162.62-11.865 50.902 5.134 104.59 19.767 137.51 58.929 17.56 20.89 27.621 47.68 29.205 74.94" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath42)" opacity=".31"><g transform="translate(230.81 454.61)"><path d="m0 0c0-7.341-5.951-13.293-13.292-13.293-7.342 0-13.293 5.952-13.293 13.293 0 7.342 5.951 13.293 13.293 13.293 7.341 0 13.292-5.951 13.292-13.293" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath58)" opacity=".31"><g transform="translate(404 462.72)"><path d="m0 0c0-3.788-3.07-6.859-6.858-6.859s-6.86 3.071-6.86 6.859 3.072 6.858 6.86 6.858 6.858-3.07 6.858-6.858" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath74)" opacity=".31"><g transform="translate(164.21 424.86)"><path d="m0 0c0-5.076-4.115-9.19-9.19-9.19-5.077 0-9.191 4.114-9.191 9.19s4.114 9.191 9.191 9.191c5.075 0 9.19-4.115 9.19-9.191" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath90)" opacity=".31"><g transform="translate(69.961 91.524)"><path d="m0 0c0-11.558-9.37-20.927-20.927-20.927-11.558 0-20.927 9.369-20.927 20.927s9.369 20.928 20.927 20.928c11.557 0 20.927-9.37 20.927-20.928" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath106)" opacity=".47"><g transform="translate(473.51 418.05)"><path d="m0 0c5.966 11.621 1.381 25.877-10.239 31.842-11.62 5.966-33.95 5.526-39.915-6.094-5.966-11.621 11.918-21.593 19.211-32.43 10.171-15.113 24.977-4.938 30.943 6.682" fill="#ecf1f7"/></g></g><g clip-path="url(#clipPath122)" opacity=".47"><g transform="translate(422.7 60.898)"><path d="m0 0c8.408-5.429 19.624-3.013 25.052 5.395 5.427 8.407 6.783 25.464-1.624 30.892s-17.365-7.451-26.179-12.191c-12.292-6.61-5.656-18.668 2.751-24.096" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath138)" opacity=".47"><g transform="translate(79.536 471.37)"><path d="m0 0c-9.248 8.588-23.706 8.053-32.294-1.195-8.588-9.247-14.019-30.131-4.772-38.719 9.248-8.588 23.201 5.438 35.187 9.386 16.718 5.507 11.127 21.94 1.879 30.528" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath154)" opacity=".47"><g transform="translate(28.561 371.54)"><path d="m0 0c-8.244-17.898-10.496-38.532-6.54-57.822 4.65-22.678 18.769-40.101 13.87-64.294-2.984-14.736-3.731-28.387-5.244-42.967-3.107-29.941 16.332-56.322 40.448-70.567 19.586-11.571 42.549-15.912 65.069-15.602 20.267 0.277 40.5 4.02 60.139 9.052 18.927 4.85 37.432 11.241 57.271 9.224 16.499-1.676 31.36-8.81 46.726-14.129 36.685-12.698 81.124-14.489 114.67 4.842 21.528 12.407 36.597 32.555 43.281 54.218 5.341 17.311 6.018 33.501 2.015 51.174-4.111 18.147-11.05 36.44-8.895 55.348 1.502 13.175 7.528 25.893 6.424 39.108-0.734 8.78-4.6 17.019-9.327 24.454-17.262 27.149-46.166 45.326-76.74 55.341-28.773 9.426-58.446 16.251-88.402 13.983-61.936-4.688-74.562 5.15-137.86 18.688-40.863 8.74-86.572-22.416-110.48-58.508-2.439-3.681-4.58-7.543-6.423-11.543" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath170)" opacity=".81"><g transform="translate(71.173 343.64)"><path d="m0 0c-1.271-14.292 3.55-29.02-0.479-43.174-4.824-16.946-18.788-29.639-24.48-46.276-8.411-24.583-8.007-52.131 2.208-76.086 4.922-11.546 12.113-22.275 21.934-29.695 15.138-11.439 34.975-13.948 53.63-12.497 27.764 2.16 57.06 14.179 84.975 10.901 15.404-1.809 20.108-18.482 28.063-29.479 8.998-12.438 21.252-22.209 34.799-28.712 24.952-11.978 54.898-13.112 80.4-2.251 27.227 11.596 50.957 39.914 49.398 71.938-0.722 14.815-6.653 29.53-3.906 44.088 3.445 18.268 17.21 34.917 27.185 49.802 11.017 16.439 17.686 36.043 18.993 56.043 0.015 0.227 0.03 0.454 0.043 0.68 2.045 34.503-19.718 65.971-52.551 76.769 0 0-69.859 22.976-69.862 22.976-70.886 23.313-141.71 22.543-206.89-11.672-14.104-7.403-37.068-29.463-41.798-44.674-0.893-2.869-1.405-5.766-1.664-8.681" fill="#e1e2fe"/></g></g><g clip-path="url(#clipPath186)" opacity=".58"><g transform="translate(472.15 118.42)"><path d="m0 0c0-2.485-2.015-4.5-4.5-4.5s-4.5 2.015-4.5 4.5 2.015 4.5 4.5 4.5 4.5-2.015 4.5-4.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath202)" opacity=".58"><g transform="translate(264.27 469.14)"><path d="m0 0c0-2.485-2.015-4.5-4.5-4.5s-4.5 2.015-4.5 4.5 2.015 4.5 4.5 4.5 4.5-2.015 4.5-4.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath218)" opacity=".58"><g transform="translate(101.71 76.922)"><path d="m0 0c0-2.485-2.015-4.5-4.5-4.5s-4.5 2.015-4.5 4.5 2.015 4.5 4.5 4.5 4.5-2.015 4.5-4.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath234)" opacity=".58"><g transform="translate(384.74 57.999)"><path d="m0 0c0-1.933-1.567-3.5-3.5-3.5s-3.5 1.567-3.5 3.5 1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5" fill="#ef929c"/></g></g><g clip-path="url(#clipPath250)" opacity=".58"><g transform="translate(78.842 392.5)"><path d="m0 0c0-0.829-0.671-1.5-1.5-1.5-0.828 0-1.5 0.671-1.5 1.5s0.672 1.5 1.5 1.5c0.829 0 1.5-0.671 1.5-1.5" fill="#3e479b"/></g></g><g clip-path="url(#clipPath266)" opacity=".58"><g transform="translate(396.86 437.24)"><path d="m0 0c-0.623-2.919-3.494-4.779-6.413-4.156s-4.779 3.494-4.156 6.413c0.624 2.919 3.495 4.78 6.414 4.156 2.918-0.623 4.779-3.495 4.155-6.413" fill="#ef929c"/></g></g><g clip-path="url(#clipPath282)" opacity=".58"><g transform="translate(108.07 462.08)"><path d="m0 0c-0.244-1.145-1.37-1.875-2.515-1.63-1.145 0.244-1.874 1.371-1.63 2.515 0.245 1.145 1.371 1.874 2.515 1.63 1.145-0.244 1.875-1.37 1.63-2.515" fill="#ef929c"/></g></g><g clip-path="url(#clipPath298)" opacity=".58"><g transform="translate(445.83 470.98)"><path d="m0 0c-0.207-0.973-1.164-1.593-2.138-1.385-0.972 0.207-1.592 1.164-1.384 2.137 0.207 0.973 1.165 1.594 2.137 1.386 0.973-0.208 1.593-1.165 1.385-2.138" fill="#3e479b"/></g></g><g clip-path="url(#clipPath314)" opacity=".58"><g transform="translate(64.778 41.356)"><path d="m0 0c-0.208-0.973-1.165-1.593-2.138-1.386-0.972 0.208-1.592 1.165-1.385 2.138 0.208 0.974 1.165 1.594 2.138 1.386s1.593-1.165 1.385-2.138" fill="#3e479b"/></g></g></g><g clip-path="url(#clipPath330)"><g clip-path="url(#clipPath338)" opacity=".66"><g transform="translate(143.2 276.91)"><path d="m0 0c-16.422 1.254-28.719 15.583-27.465 32.005s15.583 28.719 32.005 27.465 28.719-15.583 27.465-32.005c-1.254-16.423-15.583-28.719-32.005-27.465m51.214 33.339-7.958 0.608c-0.609 5.993-2.511 11.642-5.449 16.638l6.057 5.198c3.068 2.633 3.421 7.254 0.788 10.321-2.633 3.068-7.254 3.421-10.322 0.789l-6.057-5.198c-4.492 3.662-9.787 6.4-15.618 7.912l0.608 7.958c0.307 4.031-2.711 7.548-6.742 7.855-4.031 0.309-7.548-2.71-7.855-6.741l-0.608-7.958c-5.993-0.609-11.641-2.512-16.638-5.449l-5.198 6.057c-2.633 3.067-7.254 3.421-10.322 0.788-3.067-2.633-3.42-7.254-0.788-10.322l5.198-6.057c-3.662-4.492-6.4-9.787-7.912-15.618l-7.958 0.608c-4.031 0.308-7.548-2.711-7.856-6.742-0.307-4.03 2.711-7.548 6.742-7.856l7.958-0.607c0.609-5.993 2.511-11.642 5.449-16.638l-6.057-5.197c-3.068-2.633-3.421-7.254-0.788-10.323 2.633-3.068 7.254-3.42 10.322-0.787l6.057 5.197c4.492-3.662 9.787-6.4 15.618-7.912l-0.608-7.958c-0.307-4.03 2.711-7.548 6.742-7.856 4.03-0.307 7.548 2.711 7.856 6.742l0.607 7.958c5.993 0.609 11.642 2.511 16.638 5.449l5.198-6.057c2.633-3.068 7.254-3.42 10.322-0.788 3.068 2.633 3.42 7.254 0.787 10.322l-5.197 6.056c3.662 4.493 6.4 9.788 7.912 15.619l7.958-0.608c4.031-0.307 7.548 2.711 7.856 6.741 0.307 4.032-2.711 7.549-6.742 7.856" fill="#fff"/></g><g transform="translate(354.27 143.95)"><path d="m0 0c-2.008 0-4.024-0.309-5.992-0.932-5.036-1.594-9.15-5.054-11.582-9.743-2.434-4.687-2.896-10.043-1.301-15.078 1.595-5.036 5.055-9.149 9.743-11.582 4.69-2.435 10.046-2.894 15.078-1.301 5.036 1.595 9.15 5.055 11.582 9.743 2.434 4.688 2.896 10.043 1.301 15.079s-5.055 9.149-9.743 11.582c-2.856 1.482-5.959 2.232-9.086 2.232m-0.048-41.568c-3.444 0-6.86 0.826-10.006 2.458-5.162 2.679-8.971 7.208-10.727 12.753s-1.247 11.441 1.431 16.604c2.68 5.162 7.208 8.972 12.753 10.728 5.546 1.756 11.441 1.247 16.605-1.432 5.162-2.68 8.972-7.209 10.728-12.753 1.756-5.545 1.247-11.442-1.432-16.604-2.68-5.163-7.208-8.972-12.753-10.728-2.167-0.687-4.389-1.026-6.599-1.026m4.392-5.583 1.93-6.099c0.331-1.044 1.048-1.896 2.02-2.4 0.972-0.505 2.081-0.6 3.126-0.27 1.044 0.331 1.896 1.048 2.401 2.02 0.505 0.971 0.6 2.082 0.27 3.126l-1.932 6.097 0.74 0.39c3.539 1.862 6.57 4.411 9.008 7.576l0.51 0.662 5.678-2.945c0.971-0.505 2.081-0.601 3.126-0.271 1.044 0.331 1.896 1.048 2.4 2.021 1.041 2.005 0.256 4.484-1.75 5.526l-5.678 2.947 0.248 0.798c1.186 3.816 1.526 7.761 1.012 11.726l-0.108 0.83 6.098 1.931c2.155 0.682 3.353 2.991 2.671 5.145-0.331 1.044-1.048 1.897-2.02 2.402-0.97 0.504-2.081 0.599-3.125 0.269l-6.098-1.932-0.39 0.741c-1.862 3.539-4.411 6.57-7.577 9.007l-0.663 0.51 2.947 5.678c1.041 2.006 0.256 4.485-1.75 5.526-2.008 1.044-4.486 0.256-5.526-1.75l-2.947-5.677-0.799 0.248c-3.815 1.185-7.76 1.523-11.726 1.011l-0.83-0.108-1.93 6.099c-0.33 1.044-1.048 1.896-2.02 2.4-0.972 0.505-2.079 0.601-3.126 0.271-2.154-0.683-3.352-2.992-2.671-5.147l1.932-6.097-0.74-0.389c-3.539-1.864-6.57-4.412-9.007-7.577l-0.51-0.664-5.679 2.948c-0.97 0.505-2.081 0.599-3.125 0.269-1.044-0.331-1.896-1.048-2.4-2.02-0.505-0.972-0.601-2.081-0.271-3.125 0.332-1.044 1.048-1.897 2.021-2.401l5.677-2.947-0.248-0.799c-1.186-3.815-1.526-7.76-1.012-11.725l0.108-0.83-6.098-1.931c-1.044-0.33-1.897-1.048-2.401-2.02-0.505-0.971-0.599-2.082-0.269-3.126 0.682-2.154 2.991-3.354 5.145-2.67l6.098 1.931 0.39-0.74c1.862-3.539 4.411-6.569 7.576-9.007l0.662-0.51-2.945-5.678c-0.505-0.972-0.601-2.081-0.271-3.125 0.331-1.044 1.048-1.897 2.021-2.401 2.005-1.042 4.485-0.255 5.526 1.75l2.947 5.677 0.799-0.248c3.815-1.186 7.763-1.523 11.725-1.012zm5.831-10.963c-0.964 0-1.921 0.231-2.802 0.688-1.445 0.75-2.513 2.019-3.005 3.572l-1.43 4.515c-3.695-0.377-7.366-0.059-10.938 0.943l-2.182-4.203c-1.549-2.984-5.239-4.152-8.223-2.603-1.447 0.75-2.513 2.018-3.005 3.572-0.492 1.553-0.35 3.204 0.401 4.651l2.181 4.203c-2.876 2.343-5.248 5.165-7.068 8.402l-4.514-1.43c-3.207-1.015-6.641 0.768-7.655 3.974-0.493 1.553-0.35 3.204 0.4 4.65 0.751 1.447 2.019 2.514 3.572 3.005l4.515 1.43c-0.376 3.694-0.06 7.366 0.943 10.939l-4.203 2.182c-1.446 0.75-2.513 2.019-3.005 3.572s-0.349 3.204 0.402 4.651c0.75 1.445 2.018 2.512 3.572 3.005 1.552 0.491 3.204 0.349 4.65-0.401l4.203-2.182c2.344 2.875 5.165 5.249 8.403 7.069l-1.43 4.514c-1.015 3.206 0.768 6.64 3.974 7.656 1.55 0.492 3.204 0.348 4.65-0.402 1.446-0.751 2.514-2.019 3.005-3.572l1.43-4.515c3.695 0.378 7.366 0.06 10.939-0.943l2.182 4.204c1.549 2.985 5.235 4.154 8.223 2.604 2.984-1.55 4.152-5.239 2.604-8.224l-2.182-4.202c2.876-2.345 5.249-5.166 7.069-8.403l4.514 1.429c1.554 0.492 3.204 0.35 4.651-0.4 1.446-0.751 2.512-2.02 3.005-3.573 1.014-3.206-0.768-6.64-3.974-7.656l-4.515-1.429c0.376-3.695 0.06-7.366-0.943-10.94l4.204-2.18c2.984-1.55 4.152-5.24 2.603-8.224-0.75-1.446-2.018-2.514-3.572-3.005-1.552-0.492-3.203-0.349-4.651 0.401l-4.202 2.181c-2.346-2.876-5.166-5.248-8.404-7.067l1.43-4.515c0.492-1.553 0.35-3.205-0.4-4.65-0.751-1.447-2.02-2.514-3.574-3.005-0.607-0.193-1.229-0.288-1.848-0.288" fill="#fff"/></g><g transform="translate(440.19 153.6)"><path d="m0 0h0.01zm-16.757 49.302c-5.761 0-11.345-1.844-16.045-5.352-11.895-8.878-14.35-25.78-5.472-37.677 8.878-11.895 25.779-14.347 37.676-5.471 5.762 4.301 9.505 10.588 10.538 17.704 1.035 7.116-0.765 14.209-5.066 19.972-4.301 5.762-10.588 9.505-17.704 10.539-1.313 0.19-2.624 0.285-3.927 0.285m0.093-55.835c-8.824 0-17.542 4.012-23.214 11.61-9.537 12.781-6.899 30.939 5.881 40.477 6.191 4.619 13.813 6.554 21.454 5.442 7.646-1.11 14.4-5.132 19.021-11.323 4.62-6.191 6.552-13.81 5.442-21.454-1.11-7.646-5.131-14.401-11.322-19.021-5.181-3.866-11.246-5.731-17.262-5.731m-26.288 2.012 0.611-0.571c3.956-3.702 8.572-6.449 13.718-8.167l0.793-0.264-1.194-8.222c-0.464-3.193 1.757-6.17 4.951-6.635 3.194-0.463 6.171 1.757 6.635 4.951l1.194 8.224 0.836 0.027c5.422 0.182 10.629 1.503 15.474 3.926l0.748 0.374 4.97-6.659c0.935-1.253 2.302-2.067 3.85-2.291 1.549-0.228 3.089 0.166 4.343 1.101 2.585 1.931 3.12 5.606 1.188 8.192l-4.969 6.659 0.572 0.611c3.701 3.955 6.449 8.571 8.167 13.718l0.264 0.793 8.222-1.194c3.198-0.461 6.169 1.758 6.635 4.951 0.463 3.193-1.758 6.17-4.952 6.635l-8.223 1.194-0.027 0.836c-0.182 5.423-1.503 10.629-3.926 15.474l-0.374 0.748 6.658 4.97c2.587 1.93 3.121 5.605 1.19 8.192-0.934 1.253-2.301 2.066-3.849 2.291-1.547 0.226-3.089-0.167-4.343-1.102h1e-3l-6.659-4.97-0.612 0.572c-3.956 3.703-8.572 6.45-13.717 8.167l-0.793 0.264 1.194 8.223c0.225 1.547-0.167 3.089-1.102 4.342s-2.302 2.067-3.849 2.292c-3.203 0.466-6.17-1.758-6.635-4.951l-1.194-8.223-0.836-0.027c-5.421-0.182-10.627-1.503-15.474-3.926l-0.748-0.374-4.971 6.658c-0.934 1.254-2.301 2.067-3.848 2.292-1.546 0.223-3.089-0.167-4.342-1.102-1.254-0.935-2.067-2.302-2.292-3.849-0.225-1.548 0.166-3.09 1.102-4.343l4.969-6.658-0.571-0.611c-3.703-3.956-6.45-8.573-8.167-13.718l-0.265-0.793-8.222 1.194c-1.545 0.222-3.089-0.168-4.342-1.102-1.253-0.935-2.067-2.302-2.292-3.849-0.464-3.194 1.758-6.171 4.951-6.635l8.223-1.194 0.027-0.836c0.182-5.421 1.503-10.627 3.927-15.475l0.374-0.748-6.66-4.969c-1.252-0.935-2.067-2.302-2.291-3.85-0.225-1.547 0.167-3.089 1.102-4.343 0.935-1.252 2.302-2.066 3.849-2.291 1.546-0.223 3.089 0.167 4.343 1.103zm19.725-25.92c-0.374 0-0.752 0.027-1.133 0.083-4.286 0.623-7.266 4.616-6.643 8.9l0.955 6.576c-4.841 1.728-9.221 4.335-13.042 7.763l-5.325-3.974c-1.682-1.255-3.749-1.78-5.825-1.477-2.076 0.3-3.91 1.392-5.165 3.074-2.59 3.471-1.874 8.401 1.596 10.991l5.326 3.974c-2.201 4.639-3.455 9.58-3.733 14.711l-6.575 0.956c-4.285 0.622-7.266 4.615-6.643 8.9 0.301 2.076 1.393 3.91 3.075 5.165 1.681 1.254 3.75 1.778 5.825 1.478l6.577-0.955c1.727 4.84 4.334 9.22 7.763 13.042l-3.975 5.324c-1.254 1.681-1.779 3.751-1.477 5.826 0.301 2.076 1.393 3.91 3.075 5.165 1.68 1.255 3.749 1.779 5.825 1.479 2.076-0.302 3.91-1.394 5.165-3.076l3.975-5.324c4.638 2.199 9.58 3.453 14.71 3.732l0.956 6.575c0.623 4.286 4.627 7.268 8.9 6.642 2.076-0.3 3.91-1.392 5.165-3.074 1.255-1.681 1.779-3.75 1.478-5.825l-0.956-6.577c4.841-1.727 9.221-4.334 13.042-7.763l5.326 3.975c3.467 2.589 8.399 1.875 10.991-1.598 2.59-3.47 1.873-8.4-1.598-10.99l-5.324-3.975c2.199-4.637 3.453-9.578 3.731-14.71l6.577-0.956c4.285-0.623 7.264-4.616 6.642-8.9-0.623-4.286-4.625-7.27-8.9-6.643l-6.576 0.955c-1.728-4.841-4.335-9.221-7.763-13.042l3.974-5.325c2.589-3.469 1.874-8.399-1.596-10.991-1.682-1.254-3.751-1.778-5.827-1.478-2.076 0.302-3.91 1.394-5.165 3.076l-3.974 5.324c-4.639-2.199-9.579-3.453-14.711-3.732l-0.956-6.576c-0.566-3.904-3.932-6.724-7.767-6.725" fill="#fff"/></g></g><g clip-path="url(#clipPath362)" opacity=".81"><g transform="translate(287.66 119.14)"><path d="m0 0h-20.542c-0.553 0-1 0.447-1 1s0.447 1 1 1h20.542c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(287.66 97.783)"><path d="m0 0h-20.542c-0.553 0-1 0.447-1 1s0.447 1 1 1h20.542c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(176.3 145.49)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-65.849c0-0.391 0.319-0.71 0.711-0.71h126.87c0.392 0 0.712 0.319 0.712 0.71v65.849c0 0.393-0.32 0.712-0.712 0.712zm126.87-69.271h-126.87c-1.495 0-2.711 1.215-2.711 2.71v65.849c0 1.495 1.216 2.712 2.711 2.712h126.87c1.495 0 2.712-1.217 2.712-2.712v-65.849c0-1.495-1.217-2.71-2.712-2.71" fill="#fff"/></g><g clip-path="url(#clipPath366)" opacity=".66"><g transform="translate(176.3 145.49)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-65.849c0-0.391 0.319-0.71 0.711-0.71h126.87c0.392 0 0.712 0.319 0.712 0.71v65.849c0 0.393-0.32 0.712-0.712 0.712zm126.87-69.271h-126.87c-1.495 0-2.711 1.215-2.711 2.71v65.849c0 1.495 1.216 2.712 2.711 2.712h126.87c1.495 0 2.712-1.217 2.712-2.712v-65.849c0-1.495-1.217-2.71-2.712-2.71" fill="#fff"/></g></g><g transform="translate(287.66 129.5)"><path d="m0 0h-97.889c-0.552 0-1 0.447-1 1s0.448 1 1 1h97.889c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(287.66 108.77)"><path d="m0 0h-97.889c-0.552 0-1 0.447-1 1s0.448 1 1 1h97.889c0.553 0 1-0.447 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(242.55 119.14)"><path d="m0 0h-52.776c-0.552 0-1 0.447-1 1s0.448 1 1 1h52.776c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(242.55 97.783)"><path d="m0 0h-52.776c-0.552 0-1 0.447-1 1s0.448 1 1 1h52.776c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(225.36 87.891)"><path d="m0 0h-35.592c-0.552 0-1 0.447-1 1s0.448 1 1 1h35.592c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g></g><g clip-path="url(#clipPath422)" opacity=".81"><g transform="translate(91.118 183.16)"><path d="m0 0h-23.088c-0.553 0-1 0.447-1 1s0.447 1 1 1h23.088c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(91.118 207.16)"><path d="m0 0h-23.088c-0.553 0-1 0.447-1 1s0.447 1 1 1h23.088c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(50.389 231.4)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-74.434c0-0.392 0.319-0.711 0.711-0.711h143.02c0.392 0 0.711 0.319 0.711 0.711v74.434c0 0.393-0.319 0.712-0.711 0.712zm143.02-77.857h-143.02c-1.495 0-2.711 1.216-2.711 2.711v74.434c0 1.495 1.216 2.712 2.711 2.712h143.02c1.495 0 2.711-1.217 2.711-2.712v-74.434c0-1.495-1.216-2.711-2.711-2.711" fill="#fff"/></g><g clip-path="url(#clipPath426)" opacity=".66"><g transform="translate(50.389 231.4)"><path d="m0 0c-0.392 0-0.711-0.319-0.711-0.712v-74.434c0-0.392 0.319-0.711 0.711-0.711h143.02c0.392 0 0.711 0.319 0.711 0.711v74.434c0 0.393-0.319 0.712-0.711 0.712zm143.02-77.857h-143.02c-1.495 0-2.711 1.216-2.711 2.711v74.434c0 1.495 1.216 2.712 2.711 2.712h143.02c1.495 0 2.711-1.217 2.711-2.712v-74.434c0-1.495-1.216-2.711-2.711-2.711" fill="#fff"/></g></g><g transform="translate(178.05 171.52)"><path d="m0 0h-110.02c-0.552 0-1 0.447-1 1s0.448 1 1 1h110.02c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 194.81)"><path d="m0 0h-110.02c-0.552 0-1 0.447-1 1s0.448 1 1 1h110.02c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 183.16)"><path d="m0 0h-59.316c-0.553 0-1 0.447-1 1s0.447 1 1 1h59.316c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 207.16)"><path d="m0 0h-59.316c-0.553 0-1 0.447-1 1s0.447 1 1 1h59.316c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(178.05 218.28)"><path d="m0 0h-40.003c-0.552 0-1 0.447-1 1s0.448 1 1 1h40.003c0.552 0 1-0.447 1-1s-0.448-1-1-1" fill="#fff"/></g></g><g clip-path="url(#clipPath482)" opacity=".14"><g transform="translate(359.99 113.13)"><path d="m0 0-109.42 64.872c-0.879 0.522-1.17 1.657-0.648 2.537l88.33 148.98c0.521 0.879 1.656 1.17 2.536 0.648l109.42-64.873c0.88-0.521 1.17-1.657 0.648-2.537l-88.329-148.98c-0.521-0.878-1.657-1.168-2.537-0.647" fill="#3e479b"/></g></g><g transform="translate(357.14 119.1)"><path d="m0 0-109.42 64.873c-0.879 0.522-1.17 1.657-0.648 2.537l88.329 148.98c0.521 0.879 1.657 1.169 2.537 0.648l109.42-64.873c0.88-0.522 1.17-1.657 0.648-2.537l-88.329-148.98c-0.521-0.878-1.657-1.169-2.537-0.648" fill="#f7a9b4"/></g><g clip-path="url(#clipPath502)" opacity=".14"><g transform="translate(388.57 120.93)"><path d="m0 0-125.1 23.06c-1.005 0.185-1.67 1.15-1.484 2.156l31.396 170.33c0.186 1.006 1.152 1.671 2.157 1.485l125.1-23.059c1.005-0.185 1.67-1.151 1.485-2.156l-31.397-170.33c-0.185-1.006-1.151-1.671-2.156-1.485" fill="#3e479b"/></g></g><g transform="translate(387.72 125.38)"><path d="m0 0-128.74 23.73 32.068 173.97 128.74-23.73z" fill="#fff"/></g><g clip-path="url(#clipPath522)" opacity=".39"><g transform="translate(385.9 125.72)"><path d="m0 0-125.1 23.06c-1.005 0.185-1.67 1.15-1.484 2.156l31.396 170.33c0.186 1.006 1.151 1.671 2.157 1.485l125.1-23.059c1.006-0.185 1.671-1.151 1.486-2.156l-31.397-170.33c-0.185-1.006-1.151-1.671-2.156-1.485" fill="#f7a9b4"/></g></g><g transform="translate(400.31 278.86)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-31.314 5.772c-0.543 0.1-0.902 0.621-0.802 1.164 0.101 0.543 0.615 0.901 1.165 0.802l31.315-5.772c0.543-0.1 0.902-0.621 0.801-1.164-0.088-0.482-0.508-0.819-0.982-0.819" fill="#fff"/></g><g transform="translate(398.46 268.86)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-31.314 5.772c-0.543 0.1-0.902 0.622-0.802 1.165 0.101 0.542 0.616 0.901 1.165 0.802l31.315-5.773c0.543-0.1 0.902-0.621 0.801-1.164-0.088-0.482-0.508-0.819-0.982-0.819" fill="#fff"/></g><g transform="translate(396.46 257.98)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-31.314 5.772c-0.543 0.1-0.902 0.621-0.802 1.164s0.614 0.901 1.165 0.802l31.315-5.772c0.543-0.1 0.902-0.621 0.801-1.164-0.088-0.482-0.509-0.819-0.982-0.819" fill="#fff"/></g><g clip-path="url(#clipPath550)" opacity=".14"><g transform="translate(348.01 248.74)"><path d="m0 0-53.652 9.89c-1.089 0.2-1.809 1.245-1.609 2.334l10.636 57.7c0.201 1.088 1.246 1.808 2.335 1.608l53.652-9.89c1.089-0.201 1.809-1.246 1.608-2.334l-10.636-57.701c-0.2-1.088-1.246-1.808-2.334-1.607" fill="#3e479b"/></g></g><g transform="translate(346.04 252.09)"><path d="m0 0-51.148 9.428c-1.089 0.201-1.809 1.246-1.609 2.335l10.07 54.628c0.201 1.088 1.247 1.808 2.334 1.608l51.149-9.429c1.089-0.2 1.808-1.245 1.608-2.334l-10.07-54.628c-0.2-1.088-1.245-1.809-2.334-1.608" fill="#599af2"/></g><g clip-path="url(#clipPath570)" opacity=".070007"><g transform="translate(357.49 303.17)"><path d="m0 0-55.091 10.155 0.961 5.213c0.194 1.056 1.209 1.755 2.266 1.56l51.333-9.462c1.018-0.188 1.692-1.166 1.505-2.184z" fill="#ecf1f7"/></g></g><g transform="translate(317.82 286.15)"><path d="m0 0c-0.388 0-0.781 0.035-1.176 0.108l-0.762 0.141c-4.05 0.746-6.739 4.649-5.993 8.7l1.924 10.439c0.151 0.815 0.939 1.355 1.747 1.203 0.816-0.15 1.354-0.932 1.204-1.747l-1.923-10.439c-0.448-2.424 1.161-4.759 3.584-5.206l0.763-0.141c1.885-0.35 3.699 0.903 4.046 2.788l4.871 26.422c0.359 1.944-0.931 3.818-2.876 4.177l-1.305 0.24c-2.072 0.381-4.053-0.99-4.435-3.054l-0.119-0.652c-0.152-0.815-0.943-1.353-1.747-1.203-0.815 0.15-1.354 0.932-1.204 1.746l0.12 0.653c0.682 3.692 4.24 6.142 7.928 5.46l1.305-0.24c3.571-0.658 5.942-4.099 5.284-7.67l-4.871-26.423c-0.575-3.116-3.304-5.302-6.365-5.302" fill="#3e479b"/></g><g transform="translate(323.02 308.34)"><path d="m0 0c-0.03 0-0.061 2e-3 -0.092 8e-3l-19.989 3.685c-0.272 0.05-0.451 0.31-0.401 0.582s0.307 0.455 0.583 0.401l19.989-3.684c0.271-0.05 0.451-0.311 0.401-0.583-0.045-0.241-0.255-0.409-0.491-0.409" fill="#fff"/></g><g transform="translate(384.14 205)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-95.683 17.637c-0.543 0.1-0.903 0.621-0.802 1.165 0.101 0.542 0.614 0.905 1.165 0.802l95.684-17.638c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.508-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(377.3 167.89)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-95.684 17.636c-0.543 0.1-0.903 0.621-0.802 1.165 0.1 0.542 0.615 0.907 1.165 0.802l95.685-17.637c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.509-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(330.27 195.75)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-45.232 8.337c-0.543 0.1-0.902 0.622-0.802 1.166 0.101 0.542 0.615 0.907 1.165 0.801l45.233-8.338c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.509-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(336.5 229.56)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-45.232 8.337c-0.543 0.1-0.902 0.622-0.802 1.165 0.101 0.542 0.616 0.9 1.165 0.801l45.233-8.337c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.508-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(380.75 186.59)"><path d="m0 0c-0.06 0-0.121 5e-3 -0.183 0.017l-43.096 7.944c-0.543 0.1-0.903 0.621-0.802 1.165 0.1 0.542 0.614 0.904 1.165 0.802l43.097-7.945c0.543-0.099 0.902-0.621 0.801-1.165-0.088-0.481-0.508-0.818-0.982-0.818" fill="#fff"/></g><g transform="translate(370.62 383.15)"><path d="m0 0h-53.181c-1.84 0-3.333 1.492-3.333 3.333v17.787c0 1.84 1.493 3.333 3.333 3.333h53.181c1.841 0 3.333-1.493 3.333-3.333v-17.787c0-1.841-1.492-3.333-3.333-3.333" fill="#599af2"/></g><g transform="translate(410.68 356.49)"><path d="m0 0h-74.39c-1.84 0-3.333 1.492-3.333 3.333v26.453c0 1.84 1.493 3.333 3.333 3.333h74.39c1.841 0 3.333-1.493 3.333-3.333v-26.453c0-1.841-1.492-3.333-3.333-3.333" fill="#f7a9b4"/></g><g transform="translate(352.77 363.49)"><path d="m0 0h82.375c2.489 0 4.525-2.036 4.525-4.525v-25.235c0-2.488-2.036-4.524-4.525-4.524h-82.375c-2.489 0-4.525 2.036-4.525 4.524v25.235c0 2.489 2.036 4.525 4.525 4.525" fill="#fff"/></g><g clip-path="url(#clipPath626)" opacity=".74"><g transform="translate(352.77 363.49)"><path d="m0 0h82.375c2.489 0 4.525-2.036 4.525-4.525v-25.235c0-2.488-2.036-4.524-4.525-4.524h-82.375c-2.489 0-4.525 2.036-4.525 4.524v25.235c0 2.489 2.036 4.525 4.525 4.525" fill="#6d6cd4"/></g></g><g transform="translate(410.65 349.28)"><path d="m0 0c-1.639 0-2.972-1.333-2.972-2.972 0-1.638 1.333-2.971 2.972-2.971s2.972 1.333 2.972 2.971c0 1.639-1.333 2.972-2.972 2.972m0-6.943c-2.19 0-3.972 1.781-3.972 3.971s1.782 3.972 3.972 3.972 3.972-1.782 3.972-3.972-1.782-3.971-3.972-3.971" fill="#fff"/></g><g transform="translate(394.26 349.28)"><path d="m0 0c-1.639 0-2.972-1.333-2.972-2.972 0-1.638 1.333-2.971 2.972-2.971s2.972 1.333 2.972 2.971c0 1.639-1.333 2.972-2.972 2.972m0-6.943c-2.19 0-3.972 1.781-3.972 3.971s1.782 3.972 3.972 3.972 3.972-1.782 3.972-3.972-1.782-3.971-3.972-3.971" fill="#fff"/></g><g transform="translate(378.99 349.28)"><path d="m0 0c-1.639 0-2.972-1.333-2.972-2.972 0-1.638 1.333-2.971 2.972-2.971s2.972 1.333 2.972 2.971c0 1.639-1.333 2.972-2.972 2.972m0-6.943c-2.19 0-3.972 1.781-3.972 3.971s1.782 3.972 3.972 3.972 3.972-1.782 3.972-3.972-1.782-3.971-3.972-3.971" fill="#fff"/></g><g transform="translate(152.38 405.2)"><path d="m0 0h127.64c2.571 0 4.655-2.084 4.655-4.655v-188c0-8.869-7.189-16.058-16.058-16.058h-88.627c-18.899 0-34.219 15.32-34.219 34.218v167.89c0 3.65 2.958 6.608 6.607 6.608" fill="#fff"/></g><g clip-path="url(#clipPath658)" opacity=".39"><g transform="translate(147.39 405.2)"><path d="m0 0h134.78c1.379 0 2.496-1.117 2.496-2.496v-190.91c0-8.456-6.855-15.31-15.311-15.31h-92.416c-17.219 0-31.178 13.958-31.178 31.176v175.92c0 0.897 0.728 1.625 1.625 1.625" fill="#6d6cd4"/></g></g><g clip-path="url(#clipPath674)" opacity=".39"><g transform="translate(159.21 405.2)"><path d="m0 0h123.49c1.09 0 1.973-0.884 1.973-1.974v-191.96c0-8.167-6.621-14.788-14.789-14.788h-81.122c-16.93 0-30.656 13.724-30.656 30.655v176.96c0 0.609 0.494 1.103 1.103 1.103" fill="#3e479b"/></g></g><g transform="translate(177.49 196.52)"><path d="m0 0v-0.036h111.57c12.841 0 23.251 10.41 23.251 23.251v8.832h-112.83v-8.832c0-12.417-9.735-22.56-21.989-23.215" fill="#6161b5"/></g><g clip-path="url(#clipPath694)" opacity=".28"><g transform="translate(192.28 196.52)"><path d="m0 0v-0.036h99.328c11.432 0 20.7 10.41 20.7 23.251v8.832h-100.45v-8.832c0-12.417-8.667-22.56-19.577-23.215" fill="#3e479b"/></g></g><g transform="translate(263.59 252.63)"><path d="m0 0h-80.219c-0.552 0-1 0.448-1 1s0.448 1 1 1h80.219c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(265.27 286.4)"><path d="m0 0h-83.401c-0.553 0-1 0.448-1 1s0.447 1 1 1h83.401c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(223.48 269.53)"><path d="m0 0h-42.616c-0.552 0-1 0.448-1 1s0.448 1 1 1h42.616c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(220.25 269.53)"><path d="m0 0h-36.159c-0.552 0-1 0.448-1 1s0.448 1 1 1h36.159c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(237.35 322.52)"><path d="m0 0h-54.901c-0.552 0-1 0.448-1 1s0.448 1 1 1h54.901c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(262.8 322.52)"><path d="m0 0h-16.724c-0.552 0-1 0.448-1 1s0.448 1 1 1h16.724c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(265.27 305.64)"><path d="m0 0h-59.45c-0.552 0-1 0.448-1 1s0.448 1 1 1h59.45c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(199.95 305.64)"><path d="m0 0h-18.08c-0.552 0-1 0.448-1 1s0.448 1 1 1h18.08c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(263.59 336.8)"><path d="m0 0h-80.219c-0.552 0-1 0.448-1 1s0.448 1 1 1h80.219c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(263.59 370.58)"><path d="m0 0h-80.219c-0.552 0-1 0.448-1 1s0.448 1 1 1h80.219c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g transform="translate(212.81 353.71)"><path d="m0 0h-30.361c-0.553 0-1 0.448-1 1s0.447 1 1 1h30.361c0.552 0 1-0.448 1-1s-0.448-1-1-1" fill="#fff"/></g><g transform="translate(262.98 353.71)"><path d="m0 0h-36.159c-0.552 0-1 0.448-1 1s0.448 1 1 1h36.159c0.553 0 1-0.448 1-1s-0.447-1-1-1" fill="#fff"/></g><g clip-path="url(#clipPath758)" opacity=".21001"><g transform="translate(326.1 344.9)"><path d="m0 0c-34.955 0-63.292-28.336-63.292-63.292 0-34.955 28.337-63.291 63.292-63.291s63.292 28.336 63.292 63.291c0 34.956-28.337 63.292-63.292 63.292" fill="#fff"/></g></g><g clip-path="url(#clipPath774)" opacity=".76"><g transform="translate(276.5 277.06)"><path d="m0 0c-2.209 0-4 1.791-4 4 0 31.929 25.976 57.904 57.904 57.904 2.209 0 4-1.791 4-4s-1.791-4-4-4c-27.517 0-49.904-22.387-49.904-49.904 0-2.209-1.791-4-4-4" fill="#fff"/></g></g><g clip-path="url(#clipPath790)" opacity=".58"><g transform="translate(326.1 342.9)"><path d="m0 0c-33.797 0-61.292-27.496-61.292-61.292 0-33.797 27.495-61.292 61.292-61.292s61.292 27.495 61.292 61.292c0 33.796-27.495 61.292-61.292 61.292m0-126.58c-36.002 0-65.292 29.29-65.292 65.292s29.29 65.292 65.292 65.292 65.292-29.29 65.292-65.292-29.29-65.292-65.292-65.292" fill="#3e479b"/></g></g><g transform="translate(326.1 218.31)"><path d="m0 0c-34.955 0-63.292 28.337-63.292 63.292s28.337 63.291 63.292 63.291 63.292-28.336 63.292-63.291-28.337-63.292-63.292-63.292m58.175 17.943c0.093 0.094 0.197 0.168 0.3 0.245 9.638 12.478 15.383 28.117 15.383 45.104 0 40.791-33.067 73.858-73.858 73.858s-73.858-33.067-73.858-73.858 33.067-73.858 73.858-73.858c16.916 0 32.487 5.708 44.939 15.274l8.544 8.545z" fill="#3e479b"/></g><g transform="translate(326.1 343.9)"><path d="m0 0c-34.348 0-62.292-27.944-62.292-62.292 0-34.349 27.944-62.292 62.292-62.292s62.292 27.943 62.292 62.292c0 34.348-27.944 62.292-62.292 62.292m0-126.58c-35.451 0-64.292 28.841-64.292 64.292s28.841 64.292 64.292 64.292 64.292-28.841 64.292-64.292-28.841-64.292-64.292-64.292m0 137.15c-40.174 0-72.858-32.684-72.858-72.858 0-40.175 32.684-72.858 72.858-72.858 16.149 0 31.459 5.196 44.278 15.028l13.19 13.188c0.094 0.095 0.194 0.177 0.297 0.255 9.875 12.831 15.093 28.176 15.093 44.387 0 40.174-32.684 72.858-72.858 72.858m0-147.72c-41.277 0-74.858 33.581-74.858 74.858s33.581 74.858 74.858 74.858 74.858-33.581 74.858-74.858c0-16.702-5.391-32.51-15.592-45.715l-0.188-0.185c-0.099-0.075-0.15-0.109-0.194-0.154l-13.335-13.322c-13.183-10.129-28.934-15.482-45.549-15.482" fill="#3e479b"/></g><g transform="translate(382.45 224.71)"><path d="m0 0-2.865 2.864c-1.103 1.103-1.103 2.891 0 3.993l-8.544-8.544-0.14-0.139c-1.102-1.103-1.102-2.891 0-3.993l3.477-3.477c1.147 1.922 4.501 5.685 8.072 9.296" fill="#4c65ba"/></g><g transform="translate(379.58 231.57)"><path d="m0 0c-1.103-1.103-1.103-2.891 0-3.993l2.865-2.864c3.455 3.494 7.102 6.832 9.148 8.218l-3.329 3.329c-1.009 1.01-2.586 1.084-3.693 0.246-0.102-0.078-0.207-0.152-0.3-0.246z" fill="#4c65ba"/></g><g clip-path="url(#clipPath822)" opacity=".42999"><g transform="translate(379.58 231.57)"><path d="m0 0c-1.103-1.103-1.103-2.891 0-3.993l2.865-2.864c3.455 3.494 7.102 6.832 9.148 8.218l-3.329 3.329c-1.009 1.01-2.586 1.084-3.693 0.246-0.102-0.078-0.207-0.152-0.3-0.246z" fill="#3e479b"/></g></g><g transform="translate(445.18 180.97)"><path d="m0 0-52.012 52.577c-0.187 0.19-0.757-0.061-1.575-0.617-2.046-1.387-5.692-4.725-9.147-8.219-3.572-3.611-6.925-7.374-8.073-9.296-0.373-0.625-0.517-1.059-0.353-1.224l52.012-52.578c5.287-5.346 13.86-5.346 19.148 0 5.287 5.345 5.287 14.011 0 19.357" fill="#599af2"/></g><g clip-path="url(#clipPath842)" opacity=".14"><g transform="translate(445.18 180.97)"><path d="m0 0-52.012 52.577c-0.7 0.708-6.627-4.601-11.716-9.848-4.33-4.464 58.44-67.432 63.728-62.086 5.287 5.345 5.287 14.011 0 19.357" fill="#3e479b"/></g></g><g transform="translate(253.12 246.25)"><path d="m0 0h-170.97c-9.988 0-18.085 8.097-18.085 18.085s8.097 18.085 18.085 18.085h170.97c9.988 0 18.086-8.097 18.086-18.085s-8.098-18.085-18.086-18.085" fill="#fff"/><path d="m0 0h-27.807l-0.134 36.17h27.941c9.988 0 18.086-8.097 18.086-18.085s-8.098-18.085-18.086-18.085" fill="#599af2"/></g><g transform="translate(246.08 271.82)"><path d="m0 0c-3.259 0-5.911-2.651-5.911-5.911 0-3.259 2.652-5.91 5.911-5.91 1.579 0 3.063 0.614 4.18 1.731 1.116 1.116 1.731 2.6 1.731 4.179 0 3.26-2.652 5.911-5.911 5.911m0-13.821c-4.362 0-7.911 3.549-7.911 7.91 0 4.362 3.549 7.911 7.911 7.911s7.911-3.549 7.911-7.911c0-2.113-0.823-4.1-2.317-5.593-1.494-1.495-3.481-2.317-5.594-2.317" fill="#fff"/></g><g transform="translate(257.21 253.71)"><path d="m0 0c-0.256 0-0.512 0.098-0.707 0.293l-6.276 6.276c-0.391 0.39-0.391 1.023 0 1.414s1.024 0.39 1.415 0l6.275-6.276c0.391-0.391 0.391-1.023 0-1.414-0.195-0.195-0.451-0.293-0.707-0.293" fill="#fff"/></g><g transform="translate(255.56 208.88)"><path d="m0 0h-85.1c-5.955 0-10.783 4.828-10.783 10.784v7.071c0 5.978-4.846 10.824-10.824 10.824h-39.306c-5.977 0-10.823-4.846-10.823-10.824v-112.33c0-5.567 4.513-10.08 10.081-10.08h146.76c5.567 0 10.08 4.513 10.08 10.08v84.396c0 5.567-4.513 10.081-10.08 10.081" fill="#f28393"/></g><g transform="translate(246.18 208.88)"><path d="m0 0h-85.099c-5.956 0-10.784 4.828-10.784 10.784v7.071c0 5.978-4.846 10.824-10.823 10.824h-39.307c-5.977 0-10.823-4.846-10.823-10.824v-112.33c0-5.567 4.513-10.08 10.081-10.08h146.76c5.567 0 10.081 4.513 10.081 10.08v84.396c0 5.567-4.514 10.081-10.081 10.081" fill="#f28393"/></g><g clip-path="url(#clipPath882)" opacity=".12"><g transform="translate(246.18 208.88)"><path d="m0 0h-85.099c-5.956 0-10.784 4.828-10.784 10.784v7.071c0 5.978-4.846 10.824-10.823 10.824h-39.307c-5.977 0-10.823-4.846-10.823-10.824v-112.33c0-5.567 4.513-10.08 10.081-10.08h146.76c5.567 0 10.081 4.513 10.081 10.08v84.396c0 5.567-4.514 10.081-10.081 10.081" fill="#fff"/></g></g><g clip-path="url(#clipPath898)" opacity=".12"><g transform="translate(224.6 208.88)"><path d="m0 0h-73.387c-5.136 0-9.3 4.828-9.3 10.784v7.071c0 5.978-4.179 10.824-9.334 10.824h-33.896c-5.155 0-9.334-4.846-9.334-10.824v-112.33c0-5.567 3.892-10.08 8.693-10.08h126.56c4.801 0 8.693 4.513 8.693 10.08v84.396c0 5.567-3.892 10.081-8.693 10.081" fill="#fff"/></g></g><g transform="translate(97.208 197.65)"><path d="m0 0c-0.552 0-1 0.447-1 1v24.539c0 3.801 3.092 6.893 6.892 6.893h28.965c0.552 0 1-0.448 1-1 0-0.553-0.448-1-1-1h-28.965c-2.697 0-4.892-2.195-4.892-4.893v-24.539c0-0.553-0.448-1-1-1" fill="#fff"/></g></g></g></svg>
    <h1>This is a headline</h1>
    <p>loreLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo</p>
    <monster-button slot="action" class="monster-button-primary">Button</monster-button>
    <monster-button slot="action">Button</monster-button>`;
</monster-state>

Layout

The state control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-state::part(action) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


Notify Component

The notify component is a simple notification component.


Message

The notify message component is a simple notification message.

Usage

The notify component is a simple graphical display that specifies a notification.

Layout

The message control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-notify-message::part(remove) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


Notify

The notify component encapsulates the notify message component.

Usage

The notify component is a simple graphical display that specifies a notification.

Layout

The notify control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-notify::part(action) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.


Style

The CSS Style guide for Monster is a set of guidelines and best practices for writing and organizing CSS code. It is designed to help developers maintain a consistent and organized codebase, making it easier to read, understand, and modify. The style guide covers a wide range of topics, including naming conventions, code organization, and performance optimization. Following the guidelines in this style guide will help ensure that your CSS code is clean, maintainable, and efficient.

The following example shows how to include the stylesheets independently of the rest of the document.

<!-- here we define the desired content -->
<template id="contenttemplate">
    <p>this is an example</p>
</template>

<script type="module">

// here we import the stylesheets
import {NormalizeStyleSheet} from 'https://cdn.skypack.dev/@schukai/[email protected]/source/stylesheet/normalize.mjs';
import {PropertyStyleSheet} from 'https://cdn.skypack.dev/@schukai/[email protected]/source/stylesheet/property.mjs';
import {ColorStyleSheet} from 'https://cdn.skypack.dev/@schukai/[email protected]/source/stylesheet/color.mjs';
import {ThemeStyleSheet} from 'https://cdn.skypack.dev/@schukai/[email protected]/source/stylesheet/theme.mjs';

// we create a node
const node = document.createElement('div');

// we attach the shadow root to the node
const shadow = node.attachShadow({ mode: 'open' });

// we clone the template and attach it to the shadow root
const template = document.getElementById('contenttemplate');
shadow.appendChild(template.content.cloneNode(true));
 
// we attach the stylesheets to the shadow root
shadow.adoptedStyleSheets = [NormalizeStyleSheet, PropertyStyleSheet,ColorStyleSheet, ThemeStyleSheet];

// we attach the node to the body
document.body.appendChild(node);

</script>

Color


References

  • designsystem.digital.gov/design-tokens/color/overview/

Badge


Button


Typography

This page is a demonstration of the elements that can be formatted using Monster. It is not intended to be a comprehensive guide to typography, but rather a reference of the styles that are available.


Table


Form


Build

The styles are defined as PostCSS files. For this reason, you must parse these files with PostCSS to generate CSS or Javascript files from them.

The following tool is recommended for this purpose: PostCSS.

The following plugins are used in the build script:

#!/usr/bin/env node

import fs from 'fs';
import postcss from 'postcss'; // https://postcss.org/

// https://github.com/postcss/postcss-import
import importCss from 'postcss-import';

// https://github.com/postcss/postcss-mixins
import mixins from 'postcss-mixins';

// https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
import nesting from 'postcss-nesting';

// https://github.com/csstools/postcss-normalize
import normalize from 'postcss-normalize';

// https://github.com/notiv-nt/postcss-fluid
import fluid from 'postcss-fluid';

// https://github.com/antyakushev/postcss-for
import forStruct from 'postcss-for';

// https://github.com/madeleineostoja/postcss-responsive-type
import responsiveType from 'postcss-responsive-type';

// https://github.com/postcss/autoprefixer
import autoprefixer from 'autoprefixer';

// https://cssnano.co/
import cssnano from 'cssnano'; 

const sourceFile = 'source/main.pcss';

fs.readFile(sourceFile, (err, css) => {
    postcss([
        importCss(), // This plugin should probably 
                     // be used as the first plugin 
                     // of your list.
        mixins,
        nesting(),

        normalize,
        fluid,

        forStruct,
        responsiveType,
        autoprefixer,
        cssnano,
    ])
        .process(css, {from: sourceFile})
        .then(result => {
           console.log(result.css)
        }).catch(err => {
           console.log(err)
        })
})

The plugins do different things. For example, the postcss-normalize creates a CSS file that contains the CSS reset.

By using of the import plugin you can use the CSS instructions and mixin from monster.

@import "@schukai/component-style/source/style/mixin/button.pcss";

button {
    @mixin button;
}

Read the documentation for each plugin for more details.

You can also use postcss-cli.

npm i -D postcss postcss-cli
postcss src/app.css -o dest/app.css -m

References

  • https://github.com/postcss/postcss-cli
  • https://postcss.org/
  • https://github.com/postcss/postcss-import
  • https://github.com/postcss/postcss-mixins
  • https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
  • https://github.com/csstools/postcss-normalize
  • https://github.com/notiv-nt/postcss-fluid
  • https://github.com/antyakushev/postcss-for
  • https://github.com/madeleineostoja/postcss-responsive-type
  • https://github.com/postcss/autoprefixer
  • https://cssnano.co/

Extra Topics


Compatibility

In the monster library, we use current functions and objects for the implementation.
Some functions may not run on older runtimes.

There are several ways to increase compatibility.

One way is Babel and the @babel/preset-env preset.

More information about the browsers supported by Babel can be found in the browserslist project.


Polifyll

As a design decision, we decided against any kind of polyfill in our code. This not only benefits the codebase, but also makes testing easier.

A more effective way to compensate for incompatibilities is to add missing functionality via external polyfills.

To avoid having to search for and include every polyfill yourself, you can use services like polyfill.io. These can inject the missing functions and objects for each browser.

The URL builder can be used to compile the desired polyfills.

You can also automate the creation of the URL. For this you can install the tool create-polyfill-service-url.

With the following call the tool analyzes your script and throws out the desired URL.

npm i create-polyfill-service-url

With the following call the tool analyzes your script and throws out the desired URL.

npx create-polyfill-service-url analyse --file bundle.js

bundle.js is here the file that contains your code.

The result is a URL that you can easily paste into your HTML web page.

For Monster, the following code can currently be used in the header of an HTML page.

Firefox also needs the polyfill construct-style-sheets-polyfill for the monster components for the constructable stylesheets.


<script id="polyfill"
        src="https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.entries,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.map,document,Event,fetch,IntersectionObserver,JSON,Map,MutationObserver,Object.assign,Object.entries,Promise,ResizeObserver,Set,String.prototype.trim,Symbol,Symbol.iterator,URL,WeakMap,WeakSet"
        crossorigin="anonymous"
        referrerpolicy="no-referrer"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/es-module-shims.min.js"
        referrerpolicy="no-referrer"
        crossorigin="anonymous"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/adoptedStyleSheets.min.js"
        referrerpolicy="no-referrer"
        crossorigin="anonymous"></script>

References

  • URL builder
  • constructable stylesheets
  • construct-style-sheets-polyfill
  • create-polyfill-service-url

Logo schukai GmbH

[email protected]

+49-8141-5098888

Eichenstraße 26
88290 Landsberied

Impressum

Datenschutz

Bedigungen und Regeln

schukai - Twitter schukai - Instagram schukai - Linkedin schukai - Github schukai - Youtube
schukai GmbH

Eichenstraße 26
88290 Landsberied

[email protected]

+49-8141-5098888

about.schukai.com

© schukai GmbH- All rights reserved.