From 0bb342a92c644a25ca11b549c7a94c996c591279 Mon Sep 17 00:00:00 2001
From: Lucas Brandstaetter <lucas@brandstaetter.tech>
Date: Wed, 30 Oct 2024 01:42:03 +0100
Subject: [PATCH] Update formatting with prettier

Run current prettier configuration on all files.
---
 .gitlab-ci.yml                                |   53 +-
 .pre-commit-config.yaml                       |   90 +-
 Development.md                                |   64 +-
 README.md                                     |   34 +-
 deployment/README.md                          |    6 +-
 src/api/tests/wa_mapservice_import.json       |   57 +-
 src/backoffice/static/backoffice.css          |   62 +-
 src/backoffice/static/backoffice/modal.js     |   49 +-
 src/core/fixtures/anhalter.json               |  360 ++---
 src/core/fixtures/bootstrap_auth_groups.json  |  199 +--
 src/core/tests/import_data/basic.json         |   32 +-
 src/core/tests/import_data/frab.speakers.json |    2 +-
 src/core/tests/import_data/schedule-2021.json |  173 ++-
 src/core/tests/import_data/wildcard.json      |   52 +-
 src/plainui/static/plainui/js/animations.js   | 1207 ++++++++---------
 src/plainui/static/plainui/js/modal.js        |  106 +-
 src/plainui/static/plainui/js/tools.js        |   59 +-
 src/plainui/styles/_bootstrap.scss            |    1 -
 src/plainui/styles/_fonts.scss                |    4 +-
 src/plainui/styles/_grid.scss                 |   22 +-
 src/plainui/styles/_helpers.scss              |    2 +-
 src/plainui/styles/_layout.scss               |    4 +-
 src/plainui/styles/_nav.scss                  |  112 +-
 src/plainui/styles/_typography.scss           |   10 +-
 src/plainui/styles/_util-classes.scss         | 1077 +++++++--------
 src/plainui/styles/_variables.scss            |   21 +-
 src/plainui/styles/components/_avatar.scss    |   71 +-
 src/plainui/styles/components/_badges.scss    |    6 +-
 src/plainui/styles/components/_card.scss      |    8 +-
 src/plainui/styles/components/_event.scss     |  224 +--
 src/plainui/styles/components/_fahrplan.scss  |  210 +--
 src/plainui/styles/components/_header.scss    |   59 +-
 src/plainui/styles/components/_image.scss     |   46 +-
 .../styles/components/_landingpage.scss       |   76 +-
 src/plainui/styles/components/_logo.scss      |    8 +-
 src/plainui/styles/components/_markdown.scss  |  106 +-
 src/plainui/styles/components/_player.scss    |    4 +-
 src/plainui/styles/components/_slider.scss    |   20 +-
 .../styles/components/_static-pages.scss      |   14 +-
 .../styles/components/_syntaxhilite.scss      |  315 ++++-
 src/plainui/styles/components/_tags.scss      |   89 +-
 .../styles/components/_tile-board.scss        |   44 +-
 .../styles/components/_tile-message.scss      |   60 +-
 src/plainui/styles/design/_variables.scss     |    4 +-
 src/plainui/styles/hub.scss                   |   28 +-
 src/plainui/styles/sections/_fahrplan.scss    |  252 ++--
 src/version.json                              |    2 +-
 tests/README.md                               |    8 +-
 48 files changed, 2748 insertions(+), 2764 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 12aff3116..97c64b4ee 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -69,15 +69,13 @@ default:
     name: gcr.io/kaniko-project/executor:debug
     entrypoint: [""]
   variables:
-    KANIKO_CACHE_ARGS:
-      --cache=true
+    KANIKO_CACHE_ARGS: --cache=true
       --cache-copy-layers=true
       --cache-run-layers=true
       --cache-ttl=24h
       --cache-dir=$CI_PROJECT_DIR/.cache/kaniko
       --cache-repo=$CI_REGISTRY_IMAGE/cache
-    KANIKO_ARGS:
-      --skip-unused-stages=true
+    KANIKO_ARGS: --skip-unused-stages=true
       --context $CI_PROJECT_DIR
       --build-arg REGISTRY=git.cccv.de/crews/hub/dependency_proxy/containers/
   before_script:
@@ -106,7 +104,6 @@ default:
       }
       EOF
 
-
 generate_css:
   extends:
     - .default-rules
@@ -130,11 +127,11 @@ meta_build:
     PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
   script:
     - /kaniko/executor
-        $KANIKO_ARGS
-        $KANIKO_CACHE_ARGS
-        --dockerfile $CI_PROJECT_DIR/Dockerfile
-        --target base
-        --destination $CI_REGISTRY_IMAGE/build_image:$CI_PIPELINE_ID
+      $KANIKO_ARGS
+      $KANIKO_CACHE_ARGS
+      --dockerfile $CI_PROJECT_DIR/Dockerfile
+      --target base
+      --destination $CI_REGISTRY_IMAGE/build_image:$CI_PIPELINE_ID
   rules:
     - when: always
 
@@ -219,10 +216,10 @@ requirements_export:
     - git diff --exit-code -- . ':!src/version.json'
   rules:
     - changes:
-      - requirements.txt
-      - requirements.dev.txt
-      - project.toml
-      - pdm.lock
+        - requirements.txt
+        - requirements.dev.txt
+        - project.toml
+        - pdm.lock
 
 django-tests:
   stage: test
@@ -258,11 +255,11 @@ build_nginx:
     - django-tests
   script:
     - /kaniko/executor
-        $KANIKO_ARGS
-        $KANIKO_CACHE_ARGS
-        --dockerfile $CI_PROJECT_DIR/Dockerfile
-        --target nginx
-        --destination $CI_REGISTRY_IMAGE/ci/nginx:ci-$CI_PIPELINE_ID
+      $KANIKO_ARGS
+      $KANIKO_CACHE_ARGS
+      --dockerfile $CI_PROJECT_DIR/Dockerfile
+      --target nginx
+      --destination $CI_REGISTRY_IMAGE/ci/nginx:ci-$CI_PIPELINE_ID
 
 build_release:
   stage: build
@@ -274,11 +271,11 @@ build_release:
     - django-tests
   script:
     - /kaniko/executor
-        $KANIKO_ARGS
-        $KANIKO_CACHE_ARGS
-        --dockerfile $CI_PROJECT_DIR/Dockerfile
-        --target webworker
-        --destination $CI_REGISTRY_IMAGE/ci/hub:ci-$CI_PIPELINE_ID
+      $KANIKO_ARGS
+      $KANIKO_CACHE_ARGS
+      --dockerfile $CI_PROJECT_DIR/Dockerfile
+      --target webworker
+      --destination $CI_REGISTRY_IMAGE/ci/hub:ci-$CI_PIPELINE_ID
 
 build_test:
   stage: build
@@ -294,10 +291,10 @@ build_test:
         EXPOSE 8000
       EOF
     - /kaniko/executor
-        --destination $CI_REGISTRY_IMAGE/ci/hub:ci-$CI_PIPELINE_ID-test
-        $KANIKO_ARGS
-        $KANIKO_CACHE_ARGS
-        --dockerfile Dockerfile_Test
+      --destination $CI_REGISTRY_IMAGE/ci/hub:ci-$CI_PIPELINE_ID-test
+      $KANIKO_ARGS
+      $KANIKO_CACHE_ARGS
+      --dockerfile Dockerfile_Test
 
 .test_image:
   extends:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a9b46b7bb..323013537 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,48 +1,48 @@
 exclude: ^.*.min.*|migrations|yarn.lock|venv$
 
 repos:
-    - repo: https://github.com/pre-commit/pre-commit-hooks
-      rev: v2.3.0
-      hooks:
-          - id: check-yaml
-          - id: check-toml
-          - id: check-merge-conflict
-          - id: check-ast
-    - repo: https://github.com/astral-sh/ruff-pre-commit
-      rev: v0.1.5
-      hooks:
-          - id: ruff
-            args: [ --fix ]
-          - id: ruff-format
-    - repo: https://gitlab.com/bmares/check-json5
-      rev: v1.0.0
-      hooks:
-          - id: check-json5
-    - repo: https://github.com/pdm-project/pdm
-      rev: 2.19.2
-      hooks:
-          - name: check production requirements
-            id: pdm-export
-            args: ['-o', 'requirements.txt', '--without-hashes', '--prod']
-            files: ^pdm.lock$
-    - repo: https://github.com/pdm-project/pdm
-      rev: 2.19.2
-      hooks:
-          - name: check development requirements
-            id: pdm-export
-            args: ['-o', 'requirements.dev.txt', '--without-hashes', '--dev']
-            files: ^pdm.lock$
-    - repo: https://github.com/pdm-project/pdm
-      rev: 2.19.2
-      hooks:
-           - id: pdm-lock-check
-    - repo: local
-      hooks:
-          - name: Check for uncreated migrations.
-            id: migrations-check
-            language: system
-            entry: sh -c "src/manage.py makemigrations --check --dry-run"
-            files: "models/.*.py$"
-            types:
-              - python
-            stages: [pre-commit]
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v2.3.0
+    hooks:
+      - id: check-yaml
+      - id: check-toml
+      - id: check-merge-conflict
+      - id: check-ast
+  - repo: https://github.com/astral-sh/ruff-pre-commit
+    rev: v0.1.5
+    hooks:
+      - id: ruff
+        args: [--fix]
+      - id: ruff-format
+  - repo: https://gitlab.com/bmares/check-json5
+    rev: v1.0.0
+    hooks:
+      - id: check-json5
+  - repo: https://github.com/pdm-project/pdm
+    rev: 2.19.2
+    hooks:
+      - name: check production requirements
+        id: pdm-export
+        args: ["-o", "requirements.txt", "--without-hashes", "--prod"]
+        files: ^pdm.lock$
+  - repo: https://github.com/pdm-project/pdm
+    rev: 2.19.2
+    hooks:
+      - name: check development requirements
+        id: pdm-export
+        args: ["-o", "requirements.dev.txt", "--without-hashes", "--dev"]
+        files: ^pdm.lock$
+  - repo: https://github.com/pdm-project/pdm
+    rev: 2.19.2
+    hooks:
+      - id: pdm-lock-check
+  - repo: local
+    hooks:
+      - name: Check for uncreated migrations.
+        id: migrations-check
+        language: system
+        entry: sh -c "src/manage.py makemigrations --check --dry-run"
+        files: "models/.*.py$"
+        types:
+          - python
+        stages: [pre-commit]
diff --git a/Development.md b/Development.md
index 10a17bb48..168ed9d2b 100644
--- a/Development.md
+++ b/Development.md
@@ -12,14 +12,14 @@ Das Docker development image vereinfacht die initiale Einrichtung und sperrt all
    Unter Windows getestet mit WSL 2.
 2. Klonen dieses Repositories an beliebigen Ort.
 3. Image erzeugen: `docker compose build`
-    - Für schnellere Builds kann [buildkit](https://docs.docker.com/build/buildkit/) verwendet werden:
-        ```bash
-        export DOCKER_BUILDKIT=1
-        ```
-    - Die Standardpasswöter für PostgreSQL und Hub Benutzer sind in der `docker-compose.yml` Datei festgelegt und können per Umgebungsvariable angepasst werden.
+   - Für schnellere Builds kann [buildkit](https://docs.docker.com/build/buildkit/) verwendet werden:
+     ```bash
+     export DOCKER_BUILDKIT=1
+     ```
+   - Die Standardpasswöter für PostgreSQL und Hub Benutzer sind in der `docker-compose.yml` Datei festgelegt und können per Umgebungsvariable angepasst werden.
 4. Container erzeugen: `docker compose up -d hub`
-    - Beim Start mittels `docker compose` wird kein HUB Admin Benutzer angelegt um ein ungewolltes anlegen von diesen Benutzern in der Produktivumgebung vorzubeugen.
-      Falls der `admin` Benutzer angelegt werden soll muss die Umgebungsvariable `DJANGO_CREATE_ADMIN_PASSWORD` für den Container gesetzt werden.
+   - Beim Start mittels `docker compose` wird kein HUB Admin Benutzer angelegt um ein ungewolltes anlegen von diesen Benutzern in der Produktivumgebung vorzubeugen.
+     Falls der `admin` Benutzer angelegt werden soll muss die Umgebungsvariable `DJANGO_CREATE_ADMIN_PASSWORD` für den Container gesetzt werden.
 5. Optional: Import von Demo-Daten: `docker compose exec -it hub python manage.py loaddata ./core/fixtures/anhalter.json`
 
 #### Debug Zugriff
@@ -36,9 +36,9 @@ Diese kann duch das anlegen einer localen compose Datei mit dem folgenden Inhalt
 version: "3.8"
 
 services:
-    hub:
-        env_file:
-            - dev.env
+  hub:
+    env_file:
+      - dev.env
 ```
 
 Diese kann durch das setzen der Umgebungsvariable `COMPOSE_FILE=docker-compose.yml:docker-compose.local.yml` automatisch beim allen `docker compose` Kommandos berücksichtigt werden.
@@ -47,18 +47,18 @@ Um eine andere Demo Datei zu laden kann die Umgebungsvariable `DJANGO_LOAD_FIXTU
 ### Lokale Einrichtung
 
 1. Installiere, falls noch nicht geschehen, Python in Version 3.13 (oder höher) und habe eine PostgreSQL-Datenbank zur Hand (z.B. aus dem docker mit exposed port). Außerdem wird unter Umständen [GNU gettext](https://www.gnu.org/software/gettext/) benötigt, wenn man Übersetzungen kompilieren will. Alternativ kann auch das [docker dev image](#docker-dev-image) verwendet werden.
-    - Linux: Pakete `python3`, `postgresql` und `gettext`
-    - Mac: `brew install python3 postgresql gettext` bzw. https://postgresapp.com/
-    - Windows: [latest stable Python 3 release](https://www.python.org/downloads/windows/) und [PostgreSQL Installer](https://www.postgresql.org/download/windows/) und [gettext binaries](https://mlocati.github.io/articles/gettext-iconv-windows.html)
-    - Python Paketmanager: `pdm`:
-      Kann mit OS Installationsmitteln oder mit `pip install pdm` installiert werden.
+   - Linux: Pakete `python3`, `postgresql` und `gettext`
+   - Mac: `brew install python3 postgresql gettext` bzw. https://postgresapp.com/
+   - Windows: [latest stable Python 3 release](https://www.python.org/downloads/windows/) und [PostgreSQL Installer](https://www.postgresql.org/download/windows/) und [gettext binaries](https://mlocati.github.io/articles/gettext-iconv-windows.html)
+   - Python Paketmanager: `pdm`:
+     Kann mit OS Installationsmitteln oder mit `pip install pdm` installiert werden.
 1. Klone dieses Repository an beliebigen Ort.
 1. Erstelle die virtuelle Umgebung mit `pdm info`
 1. Installiere die python dependencies mit `pdm install`
-6. (falls nicht bereits vorhanden) lege einen PostgreSQL-User an (`createuser -P hub_app`) sowie eine Datenbank (`createdb -O hub_app hub`) - unter Linux ggf. via `sudo -u postgres`
+1. (falls nicht bereits vorhanden) lege einen PostgreSQL-User an (`createuser -P hub_app`) sowie eine Datenbank (`createdb -O hub_app hub`) - unter Linux ggf. via `sudo -u postgres`
 1. Konfiguriere deine Instanz mittels:
-    - Umgebungsvariablen (z.B. direnv, oder env Datei)
-    - oder mittels einer `local_settings.py` in `src/hub/` an (Dokumentation zur Datenbankkonfiguration in der [Django-Dokumentation](https://docs.djangoproject.com/en/3.1/ref/settings/#databases)):
+   - Umgebungsvariablen (z.B. direnv, oder env Datei)
+   - oder mittels einer `local_settings.py` in `src/hub/` an (Dokumentation zur Datenbankkonfiguration in der [Django-Dokumentation](https://docs.djangoproject.com/en/3.1/ref/settings/#databases)):
 
 ```python
 DEBUG = True
@@ -121,7 +121,7 @@ Mittels diesem werden die `requirements.txt` und die `requirements.dev.txt` erze
 
 Um die aktuellen python Abhängigkeiten zu installieren kann das Kommando `pdm install` verwendet werden.
 Mit dem Kommando `pdm sync --clean` kann sichergestellt werden, dass genau die Versionen aus dem pdm lock file installiert werden.  
-*Achtung*: **Nicht in der Lock Datei enthaltene python Pakete werden deinstalliert!**
+_Achtung_: **Nicht in der Lock Datei enthaltene python Pakete werden deinstalliert!**
 
 #### Hinzufügen von neuen Abhängigkeiten
 
@@ -130,6 +130,7 @@ Um neue Abhängigkeiten hinzuzufügen kann das Kommando `pdm add` verwendet werd
 Anschließend müssen die `requirements.txt` und `requirements.dev.txt` angepasst werden.
 Wenn `pre-commit` verwendet wird, passiert dies automatisch beim commit.  
 Alternativ können die folgenden Kommandos verwendet werden
+
 ```bash
 pdm export --no-hashes -o requirements.txt --prod
 pdm export --no-hashes -o requirements.dev.txt --dev
@@ -154,27 +155,26 @@ oder:
 
 ### Übersetzungen extrahieren & compilieren
 
--   `pdm manage makemessages`
--   Die Übersetzungsdateien in `<app>/locale/<sprache>/LC_MESSAGES/django.po` wurden um alle neuen Übersetzungsstrings erweitert. Bearbeiten und jeweils bei `msgstr` die Übersetzungen einfügen!
--   `pdm manage compilemessages`
--   Zum Ausprobieren müsst ihr django neu starten um die neuen Übersetzungsdateien zu laden
+- `pdm manage makemessages`
+- Die Übersetzungsdateien in `<app>/locale/<sprache>/LC_MESSAGES/django.po` wurden um alle neuen Übersetzungsstrings erweitert. Bearbeiten und jeweils bei `msgstr` die Übersetzungen einfügen!
+- `pdm manage compilemessages`
+- Zum Ausprobieren müsst ihr django neu starten um die neuen Übersetzungsdateien zu laden
 
 ### Übersetzungen definineren
 
--   in Python: `gettext` wie üblich in Django, siehe [Doku](https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#internationalization-in-python-code)
--   in jinja2-Templates via `_`, bspw. `{{ _("Settings") }}` oder mit Platzhalter `{{ _("Hello, %(username)s", username=user.display_name) }}`
+- in Python: `gettext` wie üblich in Django, siehe [Doku](https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#internationalization-in-python-code)
+- in jinja2-Templates via `_`, bspw. `{{ _("Settings") }}` oder mit Platzhalter `{{ _("Hello, %(username)s", username=user.display_name) }}`
 
 ### Static Files einsammeln lassen
 
--   `pdm manage collectstatic`
--   ohne dies brechen u.a. Unittests mit Fehlern wie "Missing staticfiles manifest entry" ab
+- `pdm manage collectstatic`
+- ohne dies brechen u.a. Unittests mit Fehlern wie "Missing staticfiles manifest entry" ab
 
 ### Tests
 
 Es gibt Django (Unit-)Tests für die einzelnen Apps. Diese finden sich jeweils im `tests` Ordner der App.
 Außerdem gibt es im repository root unter [tests](tests) auch noch einfache Integrationstests.
 
-
 #### Test mit Übersetzten Inhalten
 
 Um sicherzustellen, dass Tests mit Übersetzungen in allen Umgebungen funktionieren,
@@ -182,6 +182,7 @@ müssen die Übersetzungsfunktionen gemocked werden.
 Dazu gibt es in `core.tests.utils` eine `mocktrans` Funktion die alle Text einfach mich `_trans` ergänzt (z.B. wird aus "Login" dann "Login_trans").
 
 Die Funktion kann dann wie folgt verwendet werden:
+
 ```python
 with patch('core.models.ticket._', side_effect=mocktrans):
     translation = funktions_aufruf()
@@ -218,8 +219,8 @@ Ab dann wird vor jedem commit ein Teil der checks (vor allem Format Tests) durch
 Um das Format und die Korrektheit der python Dateien im Hub sicherzustellen setzen wir das tool `ruff` ein.
 Dieses hat die folgenden Kommandos:
 
--   `ruff check`: Diess Kommando checkt auf häufige Fehler in python code und hat auch teilweise Möglichkeiten diese zu beheben
--   `ruff format`: Dieses Kommando re-formatiert alle python dateien nach einem voregebenen Code-Style
+- `ruff check`: Diess Kommando checkt auf häufige Fehler in python code und hat auch teilweise Möglichkeiten diese zu beheben
+- `ruff format`: Dieses Kommando re-formatiert alle python dateien nach einem voregebenen Code-Style
 
 ### djLink
 
@@ -227,7 +228,8 @@ Dieses hat die folgenden Kommandos:
 **Wenn eine Integration in einen Editor gewünscht ist, muss dies berücksichtigt werden!**
 
 Manuell kann es folgendermaßen ausgeführt werden:
-- `djlint --profile django --extension html --reformat .` um alle .html Dateien zu formatieren 
+
+- `djlint --profile django --extension html --reformat .` um alle .html Dateien zu formatieren
 - `djlint --profile jinja --extension j2 --reformat .` um alle .j2 Dateien zu formatieren
 - `djlint --lint .` um alle ein potenzielle Fehler per Linting zu finden
 
diff --git a/README.md b/README.md
index f41b0ab1a..2aef8db2d 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,12 @@
 
 Der Hub besteht aus mehreren Komponenten welche für unterschiedliche Funktionen gedacht sind
 
--   Backoffice: Erfassung und Verwaltung von Informationen inkl. Bearbeitung von Reports
--   PlainUI: Es handelt sich um eine Darstellung der Konferenz-Inhalte als simples Frontend ohne viel Schnick-Schnack.
-    -   Produktiv-Instanz: <https://events.ccc.de/congress/2024/hub/>
-    -   Test-Instanz: <https://plainui.staging.hub.c3events.de/>
--   Core: Beinhaltet die Datenmodelle und Funktionen, die sowohl im Backoffice als auch in der PlainUI verwendet werden.
--   Metanav/Navbar (not published yet): Bietet eine von allen Seiten gemeinsam einbindbare Navigationsleiste im jeweiligen Congress-Design.
+- Backoffice: Erfassung und Verwaltung von Informationen inkl. Bearbeitung von Reports
+- PlainUI: Es handelt sich um eine Darstellung der Konferenz-Inhalte als simples Frontend ohne viel Schnick-Schnack.
+  - Produktiv-Instanz: <https://events.ccc.de/congress/2024/hub/>
+  - Test-Instanz: <https://plainui.staging.hub.c3events.de/>
+- Core: Beinhaltet die Datenmodelle und Funktionen, die sowohl im Backoffice als auch in der PlainUI verwendet werden.
+- Metanav/Navbar (not published yet): Bietet eine von allen Seiten gemeinsam einbindbare Navigationsleiste im jeweiligen Congress-Design.
 
 ## Datenmodell
 
@@ -17,17 +17,17 @@ als PDF: [Grobes Datenmodell](docs/Grobes Datenmodell.pdf) und [automatisch expo
 
 ### PlainUi Structure
 
--   jinja2/plainui
-    -   components
-    -   tbd.
--   styles
-    -   components: components styles, die in `hub.scss` eingebunden werden
-    -   utils: settings, die selbst keinen output generieren (z.B. Variablen, Mixins), damit sie in unterschiedlichen files verwendet werden können
-    -   `hub.scss`: Hauptdatei, welche anschließend in CSS konvertiert wird
--   static/plainui
-    -   img: statische Bilder
-    -   fonts: importierte Schriften
-    -   das generierte CSS
+- jinja2/plainui
+  - components
+  - tbd.
+- styles
+  - components: components styles, die in `hub.scss` eingebunden werden
+  - utils: settings, die selbst keinen output generieren (z.B. Variablen, Mixins), damit sie in unterschiedlichen files verwendet werden können
+  - `hub.scss`: Hauptdatei, welche anschließend in CSS konvertiert wird
+- static/plainui
+  - img: statische Bilder
+  - fonts: importierte Schriften
+  - das generierte CSS
 
 ## REST API
 
diff --git a/deployment/README.md b/deployment/README.md
index e8ef2cd85..594421d61 100644
--- a/deployment/README.md
+++ b/deployment/README.md
@@ -1,5 +1,4 @@
-Deployment
-===========
+# Deployment
 
 # Überblick
 
@@ -12,6 +11,7 @@ Alternativ kann aich wie gehabt die Konfiguration mit einer `local_settings.py`
 Egal welche der Methden gewählt wir, muss zumindest angegeben werden welche Funktionen auszurollen sind und wie die Datenbank zu erreichen ist.
 Für die Umgebungsvariablen Konfiguration kann die `docker-compose.yml` als Beispiel zu rate gezogen werden.
 Beispiel einer `local_settings.py`:
+
 ```python
 IS_API = False
 IS_BACKOFFICE = False
@@ -30,7 +30,6 @@ DATABASES = {
 }
 ```
 
-
 # Tipps & Tricks
 
 ## Backup
@@ -40,6 +39,7 @@ Allgemein: für ein normales Backup sollte einfach die Datenbank über Bordmitte
 Django hat auch eine Funktion für den Export von Daten eingebaut, diese Variante ist allerdings nicht für den Produktiven Einsatz empfohlen.
 Das Problem liegt hier in der Struktur der Daten bei der Wiederherstellung. Diese ist mit `dumpdata`/`loadata` nicht garaniert.
 Grundsätzlich funktioniert es wie folgt:
+
 1. Docker Container mit "debug" Kommando starten
 2. `./manage.py dumpdata` mit natural keys und ohne Django-Interna laufen lassen
 
diff --git a/src/api/tests/wa_mapservice_import.json b/src/api/tests/wa_mapservice_import.json
index ce110b788..e20a522af 100644
--- a/src/api/tests/wa_mapservice_import.json
+++ b/src/api/tests/wa_mapservice_import.json
@@ -30,24 +30,15 @@
             "general": [],
             "layer": {
               "set property \"jitsiTrigger\" to onaction": {
-                "in": [
-                  "jitsi4",
-                  "jitsi5",
-                  "jitsi6"
-                ],
+                "in": ["jitsi4", "jitsi5", "jitsi6"],
                 "level": "Suggestion"
               },
               "set property \"openWebsiteTrigger\" to onaction": {
-                "in": [
-                  "URLtimetable",
-                  "URLchaospost"
-                ],
+                "in": ["URLtimetable", "URLchaospost"],
                 "level": "Suggestion"
               },
               "unknown property type \"inGameConsoleMessage\"": {
-                "in": [
-                  "silent"
-                ],
+                "in": ["silent"],
                 "level": "Error"
               }
             },
@@ -71,23 +62,17 @@
             "general": [],
             "layer": {
               "map links using /_/ are disallowed. Use world:// instead.": {
-                "in": [
-                  "exit_carl"
-                ],
+                "in": ["exit_carl"],
                 "level": "Error"
               },
               "set property \"jitsiTrigger\" to onaction": {
-                "in": [
-                  "jitsi1"
-                ],
+                "in": ["jitsi1"],
                 "level": "Suggestion"
               }
             },
             "tileset": {
               "Tilesets should not be larger than 4096Ã4096 pixels in total": {
-                "in": [
-                  "ZON_DiVOC_Animation_Tileset"
-                ],
+                "in": ["ZON_DiVOC_Animation_Tileset"],
                 "level": "Warning"
               },
               "property \"copyright\" is required": {
@@ -108,18 +93,13 @@
             "general": [],
             "layer": {
               "set \"jitsiTriggerMessage\" to a custom message to overwrite the default \"press SPACE to enter in jitsi meet room\"": {
-                "in": [
-                  "jitsi"
-                ],
+                "in": ["jitsi"],
                 "level": "Suggestion"
               }
             },
             "tileset": {
               "property \"copyright\" is required": {
-                "in": [
-                  "mapUtilities",
-                  "Theater_QuartierLapin"
-                ],
+                "in": ["mapUtilities", "Theater_QuartierLapin"],
                 "level": "Error"
               }
             }
@@ -137,9 +117,7 @@
     "violation": {
       "violationCheck": 1638128989,
       "severity": "Error",
-      "errors": [
-        "authentication required"
-      ]
+      "errors": ["authentication required"]
     }
   },
   "$ROOM_4A_ID": {
@@ -150,9 +128,7 @@
       "violationCheck": 1638128683,
       "violationCommitHash": "3d12520b3c0468d93c0ccfdb5658254d4437af23",
       "severity": "Error",
-      "errors": [
-        "No main.json Map file or error."
-      ]
+      "errors": ["No main.json Map file or error."]
     }
   },
   "$ROOM_5A_ID": {
@@ -198,18 +174,11 @@
                 "level": "Error"
               },
               "set property \"jitsiTrigger\" to onaction": {
-                "in": [
-                  "jitsiBreakfast",
-                  "jitsiWorkshop",
-                  "jitsiHeaven",
-                  "jitsiInfodesk"
-                ],
+                "in": ["jitsiBreakfast", "jitsiWorkshop", "jitsiHeaven", "jitsiInfodesk"],
                 "level": "Suggestion"
               },
               "set property \"openWebsiteTrigger\" to onaction": {
-                "in": [
-                  "openChaospost"
-                ],
+                "in": ["openChaospost"],
                 "level": "Suggestion"
               }
             },
@@ -241,4 +210,4 @@
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/src/backoffice/static/backoffice.css b/src/backoffice/static/backoffice.css
index 30c03316f..575f11386 100644
--- a/src/backoffice/static/backoffice.css
+++ b/src/backoffice/static/backoffice.css
@@ -1,63 +1,63 @@
 .wrapper {
-    display: flex;
-    width: 100%;
-    align-items: stretch;
-    min-height: calc(100vh - 56px);
-    margin-bottom: 32px;
+  display: flex;
+  width: 100%;
+  align-items: stretch;
+  min-height: calc(100vh - 56px);
+  margin-bottom: 32px;
 }
 
 .legal-footer {
-    position: fixed;
-    bottom: 0;
-    width: 100%;
-    left: 0;
-    text-align: center;
-    z-index: 1000;
-    font-size: 0.875rem;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  left: 0;
+  text-align: center;
+  z-index: 1000;
+  font-size: 0.875rem;
 }
 
 #sidebar {
-    background: #7386D5;
-    color: #fff;
-    flex: 0 0 250px;
+  background: #7386d5;
+  color: #fff;
+  flex: 0 0 250px;
 }
 
 #sidebar .list-group-item,
 #sidebar .list-group-item > a {
-    align-items: center;
-    background: #7386D5;
-    border: none;
-    color: #fff;
-    display: flex;
+  align-items: center;
+  background: #7386d5;
+  border: none;
+  color: #fff;
+  display: flex;
 }
 
 #sidebar .list-group-item.active,
 #sidebar .list-group-item.active a {
-    color: #ff0;
-    font-weight: bold;
+  color: #ff0;
+  font-weight: bold;
 }
 
 #sidebar .list-group-item.child,
 #sidebar .list-group-item.child a {
-    background: #6d7fcc;
+  background: #6d7fcc;
 }
 
 #sidebar .list-group-item:hover,
 #sidebar .list-group-item a:hover,
 #sidebar .list-group-item:hover a {
-    background: #fff;
-    color: #7386D5;
-    cursor: pointer;
+  background: #fff;
+  color: #7386d5;
+  cursor: pointer;
 }
 
 #sidebar .list-group-item.child {
-    border: none;
-    font-size: .9em !important;
-    padding-left: 3rem;
+  border: none;
+  font-size: 0.9em !important;
+  padding-left: 3rem;
 }
 
 #sidebar a.back {
-    font-size: .75em;
+  font-size: 0.75em;
 }
 
 #sidebar a.blocked {
@@ -65,5 +65,5 @@
 }
 
 .pb-10rem {
-    padding-bottom: 10rem;
+  padding-bottom: 10rem;
 }
diff --git a/src/backoffice/static/backoffice/modal.js b/src/backoffice/static/backoffice/modal.js
index b10568d4f..a372d509b 100644
--- a/src/backoffice/static/backoffice/modal.js
+++ b/src/backoffice/static/backoffice/modal.js
@@ -1,34 +1,21 @@
 function registerModal() {
-    const myModal = bootstrap.Modal.getOrCreateInstance("#confirmationModal");
-    const confirmationModalSubmit = document.getElementById(
-        "confirmationModalSubmit"
-    );
-    let modalFunction = () => {};
-    confirmationModalSubmit.addEventListener("click", () => {
-        modalFunction();
-    });
+  const myModal = bootstrap.Modal.getOrCreateInstance("#confirmationModal");
+  const confirmationModalSubmit = document.getElementById("confirmationModalSubmit");
+  let modalFunction = () => {};
+  confirmationModalSubmit.addEventListener("click", () => {
+    modalFunction();
+  });
 
-    function showModal(
-        submitFunction,
-        cssClass,
-        header_text,
-        body_text,
-        submit_text
-    ) {
-        document
-            .getElementById("confirmationModalHeader")
-            .classList.remove("bg-warning", "bg-danger");
-        document
-            .getElementById("confirmationModalHeader")
-            .classList.add(`text-bg-${cssClass}`);
-        document.getElementById("confirmationModalLabel").innerHTML =
-            header_text;
-        document.getElementById("confirmationModalBody").innerHTML = body_text;
-        confirmationModalSubmit.innerHTML = submit_text;
-        confirmationModalSubmit.classList.remove("btn-warning", "btn-danger");
-        confirmationModalSubmit.classList.add(`btn-${cssClass}`);
-        modalFunction = submitFunction;
-        myModal.show();
-    }
-    return showModal;
+  function showModal(submitFunction, cssClass, header_text, body_text, submit_text) {
+    document.getElementById("confirmationModalHeader").classList.remove("bg-warning", "bg-danger");
+    document.getElementById("confirmationModalHeader").classList.add(`text-bg-${cssClass}`);
+    document.getElementById("confirmationModalLabel").innerHTML = header_text;
+    document.getElementById("confirmationModalBody").innerHTML = body_text;
+    confirmationModalSubmit.innerHTML = submit_text;
+    confirmationModalSubmit.classList.remove("btn-warning", "btn-danger");
+    confirmationModalSubmit.classList.add(`btn-${cssClass}`);
+    modalFunction = submitFunction;
+    myModal.show();
+  }
+  return showModal;
 }
diff --git a/src/core/fixtures/anhalter.json b/src/core/fixtures/anhalter.json
index d30635a89..c34a24297 100644
--- a/src/core/fixtures/anhalter.json
+++ b/src/core/fixtures/anhalter.json
@@ -1,196 +1,196 @@
 [
-    {
-        "fields": {
-            "end": "2042-12-30T15:00:00Z",
-            "is_public": true,
-            "name": "Vogonischer Congress",
-            "registration_deadline": null,
-            "slug": "vogc",
-            "start": "2042-12-27T09:00:00Z"
-        },
-        "model": "core.conference",
-        "pk": "017c0749-a2ea-4f86-92cd-e60b4508dd98"
+  {
+    "fields": {
+      "end": "2042-12-30T15:00:00Z",
+      "is_public": true,
+      "name": "Vogonischer Congress",
+      "registration_deadline": null,
+      "slug": "vogc",
+      "start": "2042-12-27T09:00:00Z"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "is_public": true,
-            "last_update": "2000-02-20T23:42:00Z",
-            "name": "Universum-Highway-Bau",
-            "slug": "spaceway"
-        },
-        "model": "core.conferencetrack",
-        "pk": 1
+    "model": "core.conference",
+    "pk": "017c0749-a2ea-4f86-92cd-e60b4508dd98"
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "is_public": true,
+      "last_update": "2000-02-20T23:42:00Z",
+      "name": "Universum-Highway-Bau",
+      "slug": "spaceway"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "is_public": true,
-            "last_update": "2000-02-20T23:42:00Z",
-            "name": "Lyrik",
-            "slug": "poetry"
-        },
-        "model": "core.conferencetrack",
-        "pk": 2
+    "model": "core.conferencetrack",
+    "pk": 1
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "is_public": true,
+      "last_update": "2000-02-20T23:42:00Z",
+      "name": "Lyrik",
+      "slug": "poetry"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "is_public": true,
-            "last_update": "2000-02-20T23:42:00Z",
-            "name": "Sonstiges",
-            "slug": "misc"
-        },
-        "model": "core.conferencetrack",
-        "pk": 3
+    "model": "core.conferencetrack",
+    "pk": 2
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "is_public": true,
+      "last_update": "2000-02-20T23:42:00Z",
+      "name": "Sonstiges",
+      "slug": "misc"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "slug": "foo",
-            "value_type": "simple",
-            "is_public": true,
-            "description": null
-        },
-        "model": "core.conferencetag",
-        "pk": 1
+    "model": "core.conferencetrack",
+    "pk": 3
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "slug": "foo",
+      "value_type": "simple",
+      "is_public": true,
+      "description": null
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "slug": "bar",
-            "value_type": "simple",
-            "is_public": true,
-            "description": null
-        },
-        "model": "core.conferencetag",
-        "pk": 2
+    "model": "core.conferencetag",
+    "pk": 1
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "slug": "bar",
+      "value_type": "simple",
+      "is_public": true,
+      "description": null
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "slug": "michelinstars",
-            "value_type": "int",
-            "is_public": true,
-            "description": "Sterne im Guide Michelin"
-        },
-        "model": "core.conferencetag",
-        "pk": 3
+    "model": "core.conferencetag",
+    "pk": 2
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "slug": "michelinstars",
+      "value_type": "int",
+      "is_public": true,
+      "description": "Sterne im Guide Michelin"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "slug": "guter_geschmack",
-            "value_type": "boolean",
-            "is_public": true,
-            "description": null
-        },
-        "model": "core.conferencetag",
-        "pk": 4
+    "model": "core.conferencetag",
+    "pk": 3
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "slug": "guter_geschmack",
+      "value_type": "boolean",
+      "is_public": true,
+      "description": null
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "slug": "autor_des_besten_gedichts",
-            "value_type": "string",
-            "is_public": true,
-            "description": null
-        },
-        "model": "core.conferencetag",
-        "pk": 5
+    "model": "core.conferencetag",
+    "pk": 4
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "slug": "autor_des_besten_gedichts",
+      "value_type": "string",
+      "is_public": true,
+      "description": null
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "name": "Heart of Gold",
-            "parent": null,
-            "slug": "heart_of_gold",
-            "state_assembly": "confirmed",
-            "assembly_link": null,
-            "assembly_location": "",
-            "is_physical": true,
-            "created": "1978-03-08T20:00:00Z"
-        },
-        "model": "core.assembly",
-        "pk": "57d13f51-790b-4032-91f5-13138cbfe1dc"
+    "model": "core.conferencetag",
+    "pk": 5
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "name": "Heart of Gold",
+      "parent": null,
+      "slug": "heart_of_gold",
+      "state_assembly": "confirmed",
+      "assembly_link": null,
+      "assembly_location": "",
+      "is_physical": true,
+      "created": "1978-03-08T20:00:00Z"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "name": "Magrathea Planet",
-            "description": "Wir haben da einen Computer gebaut. Und Planeten.",
-            "parent": null,
-            "slug": "main",
-            "state_assembly": "accepted",
-            "assembly_link": null,
-            "assembly_location": "",
-            "is_physical": true,
-            "created": "1978-03-08T20:00:00Z"
-        },
-        "model": "core.assembly",
-        "pk": "98b4c68c-1dfc-4e2a-84ae-546ef682fcf2"
+    "model": "core.assembly",
+    "pk": "57d13f51-790b-4032-91f5-13138cbfe1dc"
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "name": "Magrathea Planet",
+      "description": "Wir haben da einen Computer gebaut. Und Planeten.",
+      "parent": null,
+      "slug": "main",
+      "state_assembly": "accepted",
+      "assembly_link": null,
+      "assembly_location": "",
+      "is_physical": true,
+      "created": "1978-03-08T20:00:00Z"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "name": "Streaming",
-            "parent": null,
-            "slug": "media",
-            "state_assembly": "accepted",
-            "assembly_link": "https://streaming.media.ccc.de/",
-            "assembly_location": "",
-            "is_virtual": true,
-            "created": "1981-09-12T23:42:00Z"
-        },
-        "model": "core.assembly",
-        "pk": "5387b521-d5ae-4988-af8e-2c297cd5d15b"
+    "model": "core.assembly",
+    "pk": "98b4c68c-1dfc-4e2a-84ae-546ef682fcf2"
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "name": "Streaming",
+      "parent": null,
+      "slug": "media",
+      "state_assembly": "accepted",
+      "assembly_link": "https://streaming.media.ccc.de/",
+      "assembly_location": "",
+      "is_virtual": true,
+      "created": "1981-09-12T23:42:00Z"
     },
-    {
-        "fields": {
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "name": "BigBlueButton",
-            "parent": null,
-            "slug": "bbb",
-            "state_assembly": "accepted",
-            "assembly_link": null,
-            "assembly_location": "",
-            "is_virtual": true,
-            "created": "2009-06-12T12:34:56Z"
-        },
-        "model": "core.assembly",
-        "pk": "6750a3e0-74df-490e-9fc6-d3d35b587dd5"
+    "model": "core.assembly",
+    "pk": "5387b521-d5ae-4988-af8e-2c297cd5d15b"
+  },
+  {
+    "fields": {
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "name": "BigBlueButton",
+      "parent": null,
+      "slug": "bbb",
+      "state_assembly": "accepted",
+      "assembly_link": null,
+      "assembly_location": "",
+      "is_virtual": true,
+      "created": "2009-06-12T12:34:56Z"
     },
-    {
-        "fields": {
-            "backend_link": null,
-            "capacity": null,
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "last_update": "2000-02-20T23:42:00Z",
-            "name": "Milliways",
-            "slug": "milliways",
-            "room_type": "bbb",
-            "assembly": "6750a3e0-74df-490e-9fc6-d3d35b587dd5"
-        },
-        "model": "core.room",
-        "pk": "b489b08e-ed5a-4820-94c1-26f7019770e3"
+    "model": "core.assembly",
+    "pk": "6750a3e0-74df-490e-9fc6-d3d35b587dd5"
+  },
+  {
+    "fields": {
+      "backend_link": null,
+      "capacity": null,
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "last_update": "2000-02-20T23:42:00Z",
+      "name": "Milliways",
+      "slug": "milliways",
+      "room_type": "bbb",
+      "assembly": "6750a3e0-74df-490e-9fc6-d3d35b587dd5"
     },
-    {
-        "fields": {
-            "additional_data": "{}",
-            "assembly": "6750a3e0-74df-490e-9fc6-d3d35b587dd5",
-            "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
-            "description": "Sehen Sie es live: das Ende des bekannten Universums. Mit Livekommentar von Zaphod Beeblebrox!",
-            "is_public": true,
-            "language": "de",
-            "last_update": "2000-02-20T23:42:00Z",
-            "slug": "ende",
-            "name": "Weltuntergang",
-            "room": "b489b08e-ed5a-4820-94c1-26f7019770e3",
-            "schedule_duration": "02:00:00",
-            "schedule_start": "2042-12-30T11:34:56Z",
-            "track": 3
-        },
-        "model": "core.event",
-        "pk": "35e10dfc-11c2-475b-b682-da1ddd291770"
-    }
+    "model": "core.room",
+    "pk": "b489b08e-ed5a-4820-94c1-26f7019770e3"
+  },
+  {
+    "fields": {
+      "additional_data": "{}",
+      "assembly": "6750a3e0-74df-490e-9fc6-d3d35b587dd5",
+      "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98",
+      "description": "Sehen Sie es live: das Ende des bekannten Universums. Mit Livekommentar von Zaphod Beeblebrox!",
+      "is_public": true,
+      "language": "de",
+      "last_update": "2000-02-20T23:42:00Z",
+      "slug": "ende",
+      "name": "Weltuntergang",
+      "room": "b489b08e-ed5a-4820-94c1-26f7019770e3",
+      "schedule_duration": "02:00:00",
+      "schedule_start": "2042-12-30T11:34:56Z",
+      "track": 3
+    },
+    "model": "core.event",
+    "pk": "35e10dfc-11c2-475b-b682-da1ddd291770"
+  }
 ]
diff --git a/src/core/fixtures/bootstrap_auth_groups.json b/src/core/fixtures/bootstrap_auth_groups.json
index bc1cb0775..f3d3f4ed3 100644
--- a/src/core/fixtures/bootstrap_auth_groups.json
+++ b/src/core/fixtures/bootstrap_auth_groups.json
@@ -1,143 +1,62 @@
 [
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "Assembly-Team",
-            "permissions": [
-                [
-                    "assembly_team",
-                    "core",
-                    "conferencemember"
-                ]
-            ]
-        }
-    },
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "Registration Admin",
-            "permissions": [
-                [
-                    "assembly_registration_admin",
-                    "core",
-                    "conferencemember"
-                ]
-            ]
-        }
-    },
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "Karten-Verwaltung",
-            "permissions": [
-                [
-                    "map_edit",
-                    "core",
-                    "conferencemember"
-                ]
-            ]
-        }
-    },
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "Schedule Supervisor",
-            "permissions": [
-                [
-                    "scheduleadmin",
-                    "core",
-                    "conferencemember"
-                ],
-                [
-                    "add_schedulesource",
-                    "core",
-                    "schedulesource"
-                ],
-                [
-                    "change_schedulesource",
-                    "core",
-                    "schedulesource"
-                ],
-                [
-                    "delete_schedulesource",
-                    "core",
-                    "schedulesource"
-                ],
-                [
-                    "view_schedulesource",
-                    "core",
-                    "schedulesource"
-                ],
-                [
-                    "view_schedulesourceimport",
-                    "core",
-                    "schedulesourceimport"
-                ],
-                [
-                    "add_schedulesourcemapping",
-                    "core",
-                    "schedulesourcemapping"
-                ],
-                [
-                    "change_schedulesourcemapping",
-                    "core",
-                    "schedulesourcemapping"
-                ],
-                [
-                    "delete_schedulesourcemapping",
-                    "core",
-                    "schedulesourcemapping"
-                ],
-                [
-                    "view_schedulesourcemapping",
-                    "core",
-                    "schedulesourcemapping"
-                ]
-            ]
-        }
-    },
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "PL",
-            "permissions": [
-                [
-                    "static_pages",
-                    "core",
-                    "conferencemember"
-                ],
-                [
-                    "conference_admin",
-                    "core",
-                    "conferencemember"
-                ]
-            ]
-        }
-    },
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "Wiki Team",
-            "permissions": [
-                [
-                    "static_pages",
-                    "core",
-                    "conferencemember"
-                ]
-            ]
-        }
-    },
-    {
-        "model": "auth.group",
-        "fields": {
-            "name": "Moderation",
-            "permissions": [
-                [
-                    "moderation",
-                    "core",
-                    "conferencemember"
-                ]
-            ]
-        }
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "Assembly-Team",
+      "permissions": [["assembly_team", "core", "conferencemember"]]
     }
+  },
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "Registration Admin",
+      "permissions": [["assembly_registration_admin", "core", "conferencemember"]]
+    }
+  },
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "Karten-Verwaltung",
+      "permissions": [["map_edit", "core", "conferencemember"]]
+    }
+  },
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "Schedule Supervisor",
+      "permissions": [
+        ["scheduleadmin", "core", "conferencemember"],
+        ["add_schedulesource", "core", "schedulesource"],
+        ["change_schedulesource", "core", "schedulesource"],
+        ["delete_schedulesource", "core", "schedulesource"],
+        ["view_schedulesource", "core", "schedulesource"],
+        ["view_schedulesourceimport", "core", "schedulesourceimport"],
+        ["add_schedulesourcemapping", "core", "schedulesourcemapping"],
+        ["change_schedulesourcemapping", "core", "schedulesourcemapping"],
+        ["delete_schedulesourcemapping", "core", "schedulesourcemapping"],
+        ["view_schedulesourcemapping", "core", "schedulesourcemapping"]
+      ]
+    }
+  },
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "PL",
+      "permissions": [["static_pages", "core", "conferencemember"]]
+    }
+  },
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "Wiki Team",
+      "permissions": [["static_pages", "core", "conferencemember"]]
+    }
+  },
+  {
+    "model": "auth.group",
+    "fields": {
+      "name": "Moderation",
+      "permissions": [["moderation", "core", "conferencemember"]]
+    }
+  }
 ]
diff --git a/src/core/tests/import_data/basic.json b/src/core/tests/import_data/basic.json
index e685becfe..d38abbe81 100644
--- a/src/core/tests/import_data/basic.json
+++ b/src/core/tests/import_data/basic.json
@@ -1,17 +1,17 @@
 {
-	"rooms": {
-		"eins": {
-			"name": "Saal 1",
-			"description": "Der größte Saal."
-		}
-	},
-	"events": {
-		"cej9dwoi": {
-			"slug": "minkorrekt",
-			"name": "Methodisch Inkorrekt",
-			"schedule_start": "2021-12-06T20:00:00+0100",
-			"schedule_end": "2021-12-06T21:30:00+0100",
-			"room": "eins"
-		}
-	}
-}
\ No newline at end of file
+  "rooms": {
+    "eins": {
+      "name": "Saal 1",
+      "description": "Der größte Saal."
+    }
+  },
+  "events": {
+    "cej9dwoi": {
+      "slug": "minkorrekt",
+      "name": "Methodisch Inkorrekt",
+      "schedule_start": "2021-12-06T20:00:00+0100",
+      "schedule_end": "2021-12-06T21:30:00+0100",
+      "room": "eins"
+    }
+  }
+}
diff --git a/src/core/tests/import_data/frab.speakers.json b/src/core/tests/import_data/frab.speakers.json
index 08a53c241..2bf6fbe98 100644
--- a/src/core/tests/import_data/frab.speakers.json
+++ b/src/core/tests/import_data/frab.speakers.json
@@ -1,7 +1,7 @@
 {
   "schedule_speakers": {
     "speakers": [
-    {
+      {
         "guid": "a57b4a91-0621-553c-a97d-6b47df0f3f0e",
         "id": 19387,
         "image": null,
diff --git a/src/core/tests/import_data/schedule-2021.json b/src/core/tests/import_data/schedule-2021.json
index 4ad4fc860..b35477be4 100644
--- a/src/core/tests/import_data/schedule-2021.json
+++ b/src/core/tests/import_data/schedule-2021.json
@@ -1,92 +1,91 @@
 {
-    "schedule": {
-        "version": "v1.3",
-        "base_url": "https://domain.tld/democon/schedule/",
-        "conference": {
-            "acronym": "democon",
-            "title": "DemoCon",
-            "start": "2021-12-14",
-            "end": "2021-12-16",
-            "daysCount": 3,
-            "timeslot_duration": "00:15",
-            "rooms": [
-                {
-                    "name": "Gray Room",
-                    "guid": "b379c473-93b9-4eae-9a09-d482e86cede3",
-                    "description": "foo bar baz",
-                    "capacity": 1000
-                },
-                {
-                    "name": "Tan Room",
-                    "guid": "b379c473-93b9-4eae-9a09-d482e86ceda3",
-                    "description": null,
-                    "capacity": 10
-                }
-            ],
-            "days": [
-                {
-                  "index": 1,
-                  "date": "2021-12-14",
-                  "day_start": "2021-12-14T09:00:00+01:00",
-                  "day_end": "2021-12-14T04:00:00+01:00",
-                  "rooms": {
-                    "Gray Room": [
-                      {
-                        "url": "https://fahrplan.events.ccc.de/democon/fahrplan/events/12345.html",
-                        "id": 12345,
-                        "guid": "a0a0fcfe-b7fb-46e3-84b6-97a5406016b4",
-                        "logo": null,
-                        "date": "2021-12-14T11:00:00+01:00",
-                        "start": "11:00",
-                        "duration": "00:30",
-                        "room": "Gray Room",
-                        "slug": "democon-12345-opening",
-                        "title": "Opening Ceremony",
-                        "subtitle": "",
-                        "track": "CCC",
-                        "type": "lecture",
-                        "language": "en",
-                        "abstract": "A hearty welcome me lasses and lads!",
-                        "description": "",
-                        "recording_license": "",
-                        "do_not_record": false,
-                        "persons": [
-                          { "id": 7797, "public_name": "Jinxx" },
-                          {
-                            "name": "Jane",
-                            "guid": "09ab9fae-5c45-55a1-ac3b-4cff3d94547d",
-                            "email": "jane.doe@example.net",
-                            "biography": "A speaker",
-                            "avatar": "https://domain.tld/img/avatar.png"
-                          }
-                        ],
-                        "links": [],
-                        "attachments": [],
-                        "answers": [
-                            {
-                              "id": 1,
-                              "question": {
-                                "id": 1,
-                                "question": {
-                                  "en": "How much do you like green, on a scale from 1-10?"
-                                },
-                                "required": false,
-                                "target": "submission",
-                                "options": []
-                              },
-                              "answer": "11",
-                              "answer_file": null,
-                              "submission": "ABCDE",
-                              "person": null,
-                              "options": []
-                            }
-                          ]
-                      }
-                    ]
-                }
-                }
+  "schedule": {
+    "version": "v1.3",
+    "base_url": "https://domain.tld/democon/schedule/",
+    "conference": {
+      "acronym": "democon",
+      "title": "DemoCon",
+      "start": "2021-12-14",
+      "end": "2021-12-16",
+      "daysCount": 3,
+      "timeslot_duration": "00:15",
+      "rooms": [
+        {
+          "name": "Gray Room",
+          "guid": "b379c473-93b9-4eae-9a09-d482e86cede3",
+          "description": "foo bar baz",
+          "capacity": 1000
+        },
+        {
+          "name": "Tan Room",
+          "guid": "b379c473-93b9-4eae-9a09-d482e86ceda3",
+          "description": null,
+          "capacity": 10
+        }
+      ],
+      "days": [
+        {
+          "index": 1,
+          "date": "2021-12-14",
+          "day_start": "2021-12-14T09:00:00+01:00",
+          "day_end": "2021-12-14T04:00:00+01:00",
+          "rooms": {
+            "Gray Room": [
+              {
+                "url": "https://fahrplan.events.ccc.de/democon/fahrplan/events/12345.html",
+                "id": 12345,
+                "guid": "a0a0fcfe-b7fb-46e3-84b6-97a5406016b4",
+                "logo": null,
+                "date": "2021-12-14T11:00:00+01:00",
+                "start": "11:00",
+                "duration": "00:30",
+                "room": "Gray Room",
+                "slug": "democon-12345-opening",
+                "title": "Opening Ceremony",
+                "subtitle": "",
+                "track": "CCC",
+                "type": "lecture",
+                "language": "en",
+                "abstract": "A hearty welcome me lasses and lads!",
+                "description": "",
+                "recording_license": "",
+                "do_not_record": false,
+                "persons": [
+                  { "id": 7797, "public_name": "Jinxx" },
+                  {
+                    "name": "Jane",
+                    "guid": "09ab9fae-5c45-55a1-ac3b-4cff3d94547d",
+                    "email": "jane.doe@example.net",
+                    "biography": "A speaker",
+                    "avatar": "https://domain.tld/img/avatar.png"
+                  }
+                ],
+                "links": [],
+                "attachments": [],
+                "answers": [
+                  {
+                    "id": 1,
+                    "question": {
+                      "id": 1,
+                      "question": {
+                        "en": "How much do you like green, on a scale from 1-10?"
+                      },
+                      "required": false,
+                      "target": "submission",
+                      "options": []
+                    },
+                    "answer": "11",
+                    "answer_file": null,
+                    "submission": "ABCDE",
+                    "person": null,
+                    "options": []
+                  }
+                ]
+              }
             ]
+          }
         }
+      ]
     }
+  }
 }
-    
\ No newline at end of file
diff --git a/src/core/tests/import_data/wildcard.json b/src/core/tests/import_data/wildcard.json
index 34e2c09c5..c3ac1b7f4 100644
--- a/src/core/tests/import_data/wildcard.json
+++ b/src/core/tests/import_data/wildcard.json
@@ -1,30 +1,30 @@
 {
-    "rooms": {
-        "alpha": {
-            "name": "Saal 1",
-            "guid": "f19b7ae0-5f2d-420c-ae4b-48e56a09ff15",
-            "description": "Der größte Saal."
-        },
-        "beta": {
-            "name": "Hackcenter",
-            "guid": "4f9c1df8-926a-49e6-aa64-515e63846c12",
-            "description": "ein anderer Saal"
-        }
+  "rooms": {
+    "alpha": {
+      "name": "Saal 1",
+      "guid": "f19b7ae0-5f2d-420c-ae4b-48e56a09ff15",
+      "description": "Der größte Saal."
     },
-    "events": {
-        "cej9dwoi": {
-            "slug": "minkorrekt",
-            "name": "Methodisch Inkorrekt",
-            "schedule_start": "2021-12-06T20:00:00+0100",
-            "schedule_end": "2021-12-06T21:30:00+0100",
-            "room": "alpha"
-        },
-        "a42fn0rd": {
-            "slug": "blubb",
-            "name": "Bla Bla",
-            "schedule_start": "2021-12-06T20:00:00+0100",
-            "schedule_end": "2021-12-06T21:30:00+0100",
-            "room": "beta"
-        }
+    "beta": {
+      "name": "Hackcenter",
+      "guid": "4f9c1df8-926a-49e6-aa64-515e63846c12",
+      "description": "ein anderer Saal"
     }
+  },
+  "events": {
+    "cej9dwoi": {
+      "slug": "minkorrekt",
+      "name": "Methodisch Inkorrekt",
+      "schedule_start": "2021-12-06T20:00:00+0100",
+      "schedule_end": "2021-12-06T21:30:00+0100",
+      "room": "alpha"
+    },
+    "a42fn0rd": {
+      "slug": "blubb",
+      "name": "Bla Bla",
+      "schedule_start": "2021-12-06T20:00:00+0100",
+      "schedule_end": "2021-12-06T21:30:00+0100",
+      "room": "beta"
+    }
+  }
 }
diff --git a/src/plainui/static/plainui/js/animations.js b/src/plainui/static/plainui/js/animations.js
index 7e84f6502..14a07f046 100644
--- a/src/plainui/static/plainui/js/animations.js
+++ b/src/plainui/static/plainui/js/animations.js
@@ -1,702 +1,621 @@
 var initParallax = (callback) => {
-    if (document.readyState != "loading") callback();
-    else document.addEventListener("DOMContentLoaded", callback);
-}
+  if (document.readyState != "loading") callback();
+  else document.addEventListener("DOMContentLoaded", callback);
+};
 
 initParallax(() => {
-    if (!('querySelector' in document)
-        || !('requestAnimationFrame' in window)) {
-        return;
+  if (!("querySelector" in document) || !("requestAnimationFrame" in window)) {
+    return;
+  }
+  const body = document.querySelector("body");
+  // Parallax only with some body classes
+  if (!body.classList.contains("eyecandy-deluxe")) {
+    return;
+  }
+
+  let lastPos;
+  const layer01 = document.querySelector(".rc3-bg-L01");
+  const layer05L = document.querySelector(".rc3-bg-L05-L");
+  const layer05R = document.querySelector(".rc3-bg-L05-R");
+  const layer06 = document.querySelector(".rc3-bg-L06");
+  const layer10 = document.querySelector(".rc3-bg-L10");
+  const main = document.querySelector(".rc3-main");
+
+  if (layer05R) {
+    layer05R.classList.add(`collage-r-` + Math.floor(Math.random() * 7 + 1));
+  }
+
+  if (layer05L) {
+    layer05L.classList.add(`collage-l-` + Math.floor(Math.random() * 6 + 1));
+  }
+
+  const setTransform = (el, factor, scale) => {
+    if (el) {
+      el.style.transform = `translate3D(0,${window.scrollY * factor}px,0) scale(${scale})`;
     }
-    const body = document.querySelector('body');
-    // Parallax only with some body classes
-    if (!body.classList.contains('eyecandy-deluxe')) {
-        return;
+  };
+  const setBgPosition = (el, factor) => {
+    if (el) {
+      el.style.backgroundPositionY = window.scrollY * factor + "px";
     }
-
-    let lastPos;
-    const layer01 = document.querySelector('.rc3-bg-L01');
-    const layer05L = document.querySelector('.rc3-bg-L05-L');
-    const layer05R = document.querySelector('.rc3-bg-L05-R');
-    const layer06 = document.querySelector('.rc3-bg-L06');
-    const layer10 = document.querySelector('.rc3-bg-L10');
-    const main = document.querySelector('.rc3-main');
-
-    if (layer05R) {
-        layer05R.classList.add(`collage-r-` + Math.floor((Math.random() * 7) + 1));
-    }
-
-    if (layer05L) {
-        layer05L.classList.add(`collage-l-` + Math.floor((Math.random() * 6) + 1));
-    }
-
-    const setTransform = (el, factor, scale) => {
-        if (el) {
-            el.style.transform = `translate3D(0,${window.scrollY * factor}px,0) scale(${scale})`;
-        }
-    }
-    const setBgPosition = (el, factor) => {
-        if (el) {
-            el.style.backgroundPositionY = window.scrollY * factor + "px"
-        }
-    }
-
-    function step() {
-        if (!lastPos)
-            lastPos = window.scrollY;
-
-        if (lastPos !== window.scrollY) {
-            setBgPosition(layer01, -1.2);
-            setTransform(layer05R, -0.1, "1");
-            setTransform(layer05L, -0.2, "1");
-            setBgPosition(layer06, 0.5);
-            setTransform(layer10, -0.02, "1");
-            // Move mask for header
-            if (main) {
-                main.style.maskPositionY = window.scrollY - 170 + "px";
-                main.style.webkitMaskPositionY = window.scrollY - 170 + "px";
-
-                if (window.scrollY < 10) {
-                    main.style.webkitMaskImage = 'none';
-                    main.style.maskImage = 'none';
-                } else {
-                    main.style.webkitMaskImage = 'linear-gradient(180deg, transparent 0em, transparent 80px, rgba(0, 0, 0, 1) 170px)';
-                    main.style.maskImage = 'linear-gradient(180deg, transparent 0em, transparent 80px, rgba(0, 0, 0, 1) 170px)';
-                }
-            }
-        }
-        lastPos = window.scrollY;
-        window.requestAnimationFrame(step);
+  };
+
+  function step() {
+    if (!lastPos) lastPos = window.scrollY;
+
+    if (lastPos !== window.scrollY) {
+      setBgPosition(layer01, -1.2);
+      setTransform(layer05R, -0.1, "1");
+      setTransform(layer05L, -0.2, "1");
+      setBgPosition(layer06, 0.5);
+      setTransform(layer10, -0.02, "1");
+      // Move mask for header
+      if (main) {
+        main.style.maskPositionY = window.scrollY - 170 + "px";
+        main.style.webkitMaskPositionY = window.scrollY - 170 + "px";
+
+        if (window.scrollY < 10) {
+          main.style.webkitMaskImage = "none";
+          main.style.maskImage = "none";
+        } else {
+          main.style.webkitMaskImage =
+            "linear-gradient(180deg, transparent 0em, transparent 80px, rgba(0, 0, 0, 1) 170px)";
+          main.style.maskImage = "linear-gradient(180deg, transparent 0em, transparent 80px, rgba(0, 0, 0, 1) 170px)";
+        }
+      }
     }
+    lastPos = window.scrollY;
     window.requestAnimationFrame(step);
+  }
+  window.requestAnimationFrame(step);
 });
 
 var initParticles = (callback) => {
-    if (document.readyState != "loading") callback();
-    else document.addEventListener("DOMContentLoaded", callback);
-}
+  if (document.readyState != "loading") callback();
+  else document.addEventListener("DOMContentLoaded", callback);
+};
 
 initParticles(() => {
-    /*
-    *  Particles.js
-    * 
-    *  Particle emitter and renderer.
-    * 
-    *  TODO: Gleichmäßige Particle verteilung
-    *  TODO: Pulse Animation anpassen (easing)
-    */
-
-    // The Fast-Memoize Library:
-    // https://github.com/caiogondim/fast-memoize.js
-    /*
-     *  Particles.js
-     * 
-     *  Particle emitter and renderer.
-     * 
-     *  TODO: Gleichmäßige Particle verteilung
-     *  TODO: Pulse Animation anpassen (easing)
-     */
-
-    // The Fast-Memoize Library:
-    // https://github.com/caiogondim/fast-memoize.js
-
-    var Memoize = (function () {
-        //
-        // Main
-        //
-
-        function memoize(fn, options) {
-            var cache = options && options.cache
-                ? options.cache
-                : cacheDefault
-
-            var serializer = options && options.serializer
-                ? options.serializer
-                : serializerDefault
-
-            var strategy = options && options.strategy
-                ? options.strategy
-                : strategyDefault
-
-            return strategy(fn, {
-                cache: cache,
-                serializer: serializer
-            })
-        }
-
-        //
-        // Strategy
-        //
-
-        function isPrimitive(value) {
-            return value == null || typeof value === 'number' || typeof value === 'boolean' // || typeof value === "string" 'unsafe' primitive for our needs
-        }
-
-        function monadic(fn, cache, serializer, arg) {
-            var cacheKey = isPrimitive(arg) ? arg : serializer(arg)
-
-            var computedValue = cache.get(cacheKey)
-            if (typeof computedValue === 'undefined') {
-                computedValue = fn.call(this, arg)
-                cache.set(cacheKey, computedValue)
-            }
-
-            return computedValue
-        }
-
-        function variadic(fn, cache, serializer) {
-            var args = Array.prototype.slice.call(arguments, 3)
-            var cacheKey = serializer(args)
-
-            var computedValue = cache.get(cacheKey)
-            if (typeof computedValue === 'undefined') {
-                computedValue = fn.apply(this, args)
-                cache.set(cacheKey, computedValue)
-            }
-
-            return computedValue
-        }
-
-        function assemble(fn, context, strategy, cache, serialize) {
-            return strategy.bind(
-                context,
-                fn,
-                cache,
-                serialize
-            )
-        }
-
-        function strategyDefault(fn, options) {
-            var strategy = fn.length === 1 ? monadic : variadic
-
-            return assemble(
-                fn,
-                this,
-                strategy,
-                options.cache.create(),
-                options.serializer
-            )
-        }
-
-        function strategyVariadic(fn, options) {
-            var strategy = variadic
-
-            return assemble(
-                fn,
-                this,
-                strategy,
-                options.cache.create(),
-                options.serializer
-            )
-        }
-
-        function strategyMonadic(fn, options) {
-            var strategy = monadic
-
-            return assemble(
-                fn,
-                this,
-                strategy,
-                options.cache.create(),
-                options.serializer
-            )
-        }
-
-        //
-        // Serializer
-        //
+  /*
+   *  Particles.js
+   *
+   *  Particle emitter and renderer.
+   *
+   *  TODO: Gleichmäßige Particle verteilung
+   *  TODO: Pulse Animation anpassen (easing)
+   */
+
+  // The Fast-Memoize Library:
+  // https://github.com/caiogondim/fast-memoize.js
+  /*
+   *  Particles.js
+   *
+   *  Particle emitter and renderer.
+   *
+   *  TODO: Gleichmäßige Particle verteilung
+   *  TODO: Pulse Animation anpassen (easing)
+   */
+
+  // The Fast-Memoize Library:
+  // https://github.com/caiogondim/fast-memoize.js
+
+  var Memoize = (function () {
+    //
+    // Main
+    //
+
+    function memoize(fn, options) {
+      var cache = options && options.cache ? options.cache : cacheDefault;
+
+      var serializer = options && options.serializer ? options.serializer : serializerDefault;
+
+      var strategy = options && options.strategy ? options.strategy : strategyDefault;
+
+      return strategy(fn, {
+        cache: cache,
+        serializer: serializer,
+      });
+    }
 
-        function serializerDefault() {
-            return JSON.stringify(arguments)
-        }
+    //
+    // Strategy
+    //
 
-        //
-        // Cache
-        //
+    function isPrimitive(value) {
+      return value == null || typeof value === "number" || typeof value === "boolean"; // || typeof value === "string" 'unsafe' primitive for our needs
+    }
 
-        function ObjectWithoutPrototypeCache() {
-            this.cache = Object.create(null)
-        }
+    function monadic(fn, cache, serializer, arg) {
+      var cacheKey = isPrimitive(arg) ? arg : serializer(arg);
 
-        ObjectWithoutPrototypeCache.prototype.has = function (key) {
-            return (key in this.cache)
-        }
+      var computedValue = cache.get(cacheKey);
+      if (typeof computedValue === "undefined") {
+        computedValue = fn.call(this, arg);
+        cache.set(cacheKey, computedValue);
+      }
 
-        ObjectWithoutPrototypeCache.prototype.get = function (key) {
-            return this.cache[key]
-        }
-
-        ObjectWithoutPrototypeCache.prototype.set = function (key, value) {
-            this.cache[key] = value
-        }
+      return computedValue;
+    }
 
-        var cacheDefault = {
-            create: function create() {
-                return new ObjectWithoutPrototypeCache()
-            }
-        }
+    function variadic(fn, cache, serializer) {
+      var args = Array.prototype.slice.call(arguments, 3);
+      var cacheKey = serializer(args);
 
-        //
-        // API
-        //
+      var computedValue = cache.get(cacheKey);
+      if (typeof computedValue === "undefined") {
+        computedValue = fn.apply(this, args);
+        cache.set(cacheKey, computedValue);
+      }
 
-        // Default export
-        var exports = memoize
-        exports.strategies = {
-            variadic: strategyVariadic,
-            monadic: strategyMonadic
-        }
+      return computedValue;
+    }
 
-        return exports
+    function assemble(fn, context, strategy, cache, serialize) {
+      return strategy.bind(context, fn, cache, serialize);
+    }
 
-    })()
+    function strategyDefault(fn, options) {
+      var strategy = fn.length === 1 ? monadic : variadic;
 
+      return assemble(fn, this, strategy, options.cache.create(), options.serializer);
+    }
 
+    function strategyVariadic(fn, options) {
+      var strategy = variadic;
 
-    // Create the Particles Module | Namespace.
-    var Particles = (function () {
+      return assemble(fn, this, strategy, options.cache.create(), options.serializer);
+    }
 
-        //
-        //  Helper
-        //
-        var MathRandom = Math.random
-        var MathAbs = Math.abs
-        var MathTrunc = Math.trunc
-        var MathPow = Math.pow
+    function strategyMonadic(fn, options) {
+      var strategy = monadic;
 
+      return assemble(fn, this, strategy, options.cache.create(), options.serializer);
+    }
 
-        function randomValue(min, max) {
-            var value = (MathRandom() * (+max - +min) + +min)
-            // Prevent values that can be possible boring
-            return (min !== 0 && max !== 0 && (value === 0 || value === 1))
-                ? randomValue(min, max)
-                : value
-        }
+    //
+    // Serializer
+    //
 
-        function getNodeYOffset(node) {
-            var dimensions = node.getBoundingClientRect()
-            return (dimensions) ? dimensions.y : 0
-        }
+    function serializerDefault() {
+      return JSON.stringify(arguments);
+    }
 
-        function getNodeHeight(node) {
-            var dimensions = node.getBoundingClientRect()
-            return (dimensions) ? dimensions.height : window.innerHeight
-        }
+    //
+    // Cache
+    //
 
-        function calcParticleCount(scene, particleDensity) {
-            var referenceArea = 100 * 100 // 100px * 100px => px^2
-            var sceneVolume = scene.width * scene.height
-            var scale = 100
-            var particleFactor = (sceneVolume / referenceArea) / scale
-            var particleCount = MathAbs(MathTrunc(
-                particleFactor * particleDensity
-            ))
-            return particleCount || 0
-        }
+    function ObjectWithoutPrototypeCache() {
+      this.cache = Object.create(null);
+    }
 
-        var normalize = Memoize(
-            function doNormalize(val) {
-                var min = 0
-                var max = 1
-                var delta = max - min
-                return (val - min) / delta
-            }
-        )
-
-        // Easing functions from: https://easings.net/
-
-        var easeOutQuint = Memoize(
-            function doEaseOutQuint(x) {
-                return 1 - MathPow(1 - x, 5);
-            }
-        )
-
-        var easeOutExpo = Memoize(
-            function easeOutExpo(x) {
-                return x >= 1 ? 1 : 1 - MathPow(2, -10 * x);
-            }
-        )
-
-
-        function easing(value) {
-            return (value < 0)
-                ? -easeOutExpo(-value)
-                : easeOutExpo(value)
-        }
+    ObjectWithoutPrototypeCache.prototype.has = function (key) {
+      return key in this.cache;
+    };
+
+    ObjectWithoutPrototypeCache.prototype.get = function (key) {
+      return this.cache[key];
+    };
+
+    ObjectWithoutPrototypeCache.prototype.set = function (key, value) {
+      this.cache[key] = value;
+    };
+
+    var cacheDefault = {
+      create: function create() {
+        return new ObjectWithoutPrototypeCache();
+      },
+    };
+
+    //
+    // API
+    //
+
+    // Default export
+    var exports = memoize;
+    exports.strategies = {
+      variadic: strategyVariadic,
+      monadic: strategyMonadic,
+    };
+
+    return exports;
+  })();
+
+  // Create the Particles Module | Namespace.
+  var Particles = (function () {
+    //
+    //  Helper
+    //
+    var MathRandom = Math.random;
+    var MathAbs = Math.abs;
+    var MathTrunc = Math.trunc;
+    var MathPow = Math.pow;
+
+    function randomValue(min, max) {
+      var value = MathRandom() * (+max - +min) + +min;
+      // Prevent values that can be possible boring
+      return min !== 0 && max !== 0 && (value === 0 || value === 1) ? randomValue(min, max) : value;
+    }
 
+    function getNodeYOffset(node) {
+      var dimensions = node.getBoundingClientRect();
+      return dimensions ? dimensions.y : 0;
+    }
 
-        //
-        //  Data
-        //
+    function getNodeHeight(node) {
+      var dimensions = node.getBoundingClientRect();
+      return dimensions ? dimensions.height : window.innerHeight;
+    }
 
+    function calcParticleCount(scene, particleDensity) {
+      var referenceArea = 100 * 100; // 100px * 100px => px^2
+      var sceneVolume = scene.width * scene.height;
+      var scale = 100;
+      var particleFactor = sceneVolume / referenceArea / scale;
+      var particleCount = MathAbs(MathTrunc(particleFactor * particleDensity));
+      return particleCount || 0;
+    }
 
-        function Point2D(x, y) {
-            return { x, y }
-        }
+    var normalize = Memoize(function doNormalize(val) {
+      var min = 0;
+      var max = 1;
+      var delta = max - min;
+      return (val - min) / delta;
+    });
 
-        function MinMax(min, max) {
-            return { min, max }
-        }
+    // Easing functions from: https://easings.net/
 
-        function RandomPoint2D(minMaxX, minMaxY) {
-            var x = randomValue(minMaxX.min, minMaxX.max)
-            var y = randomValue(minMaxY.min, minMaxY.max)
-            return Point2D(x, y)
-        }
+    var easeOutQuint = Memoize(function doEaseOutQuint(x) {
+      return 1 - MathPow(1 - x, 5);
+    });
 
+    var easeOutExpo = Memoize(function easeOutExpo(x) {
+      return x >= 1 ? 1 : 1 - MathPow(2, -10 * x);
+    });
 
-        //
-        //  Transformations | Actions
-        //
-
-
-        function Update(scene, particle) {
-            // Cache object access -> Performance
-            var width = scene.width
-            var height = scene.height
-            var color = particle.color
-            var particleSize = particle.size
-            var particleSizeStep = particleSize.step
-            var particleSizeAnimValue = particleSize.animValue
-            var particleSizeScale = particleSize.scale
-            var particleSizeDirection = particleSize.direction
-            var particlePosition = particle.position
-            var particlePositionX = particlePosition.x
-            var particlePositionY = particlePosition.y
-            var particleDirection = particle.direction
-            var particleDirectionX = particleDirection.x
-            var particleDirectionY = particleDirection.y
-
-            // Animate the pulse effect of the particle
-            //
-            // var absSizeAnimValue = particleSizeAnimValue * particleSizeDirection
-            var isMaxSize = particleSizeAnimValue > 1
-            var isMinSize = particleSizeAnimValue < -1
-            var sizeDirection =
-                (isMaxSize || isMinSize)
-                    ? -particleSizeDirection
-                    : particleSizeDirection
-            var animValue = particleSizeAnimValue + (particleSizeStep * sizeDirection)
-            // The operator ~~ is a more performant shorthand for Math.trunc()
-            var sizeValue = ~~(
-                easing(animValue) * particleSizeScale
-            )
-
-            // Animate the movement of the particle
-            // 
-            var sizeOffset = sizeValue * 0.5
-            var top = particlePositionY + sizeOffset
-            var bottom = particlePositionY - sizeOffset
-            var left = particlePositionX - sizeOffset
-            var right = particlePositionX + sizeOffset
-
-            var isRightEdge = (left > (width + 1))
-            var isLeftEdge = (right < -1)
-            var isTopEdge = (bottom < -1)
-            var isBottomEdge = (top > (height + 1))
-
-            var positionX =
-                (isRightEdge)
-                    ? -sizeOffset
-                    : (isLeftEdge)
-                        ? width + sizeOffset
-                        : particlePositionX + particleDirectionX
-            var positionY =
-                (isBottomEdge)
-                    ? -sizeOffset
-                    : (isTopEdge)
-                        ? height + sizeOffset
-                        : particlePositionY + particleDirectionY
-            return {
-                position: {
-                    x: positionX,
-                    y: positionY,
-                },
-                direction: particleDirection,
-                size: {
-                    value: sizeValue,
-                    animValue: animValue,
-                    step: particleSizeStep,
-                    scale: particleSizeScale,
-                    direction: sizeDirection,
-                    offset: sizeOffset
-                },
-                color: color
-            }
-        }
+    function easing(value) {
+      return value < 0 ? -easeOutExpo(-value) : easeOutExpo(value);
+    }
 
-        function Draw(scene, particle) {
-            // Cache object access
-            var particlePosition = particle.position
-            var particlePositionX = particlePosition.x
-            var particlePositionY = particlePosition.y
-            var particleSize = particle.size
-            var particleSizeValue = particleSize.value
-            var drawOffset = particleSize.offset
-
-            // Draw calculations -- 
-            var yOffset = scene.yOffset * scene.depthScale
-            var size = particleSizeValue
-            var x = particlePositionX - drawOffset
-            var y = yOffset + (particlePositionY - drawOffset)
-
-            var ctx = scene.ctx
-            // var isVisible = (size > 0 && y < window.innerHeight && y > 0)
-            var isVisible = (size > 0)
-
-            // Draw
-            if (isVisible) {
-                ctx.fillStyle = particle.color
-                // Round to full integer to prevent subpixel rendering
-                //  - The ~~ operator is equivalent to Math.trunc() but faster.
-                // ctx.fillRect(~~x, ~~y, size, size)
-                ctx.fillRect(x, y, size, size)
-            }
-        }
+    //
+    //  Data
+    //
 
-        function Clear(scene) {
-            scene.ctx.clearRect(0, 0, scene.width, scene.height)
-        }
+    function Point2D(x, y) {
+      return { x, y };
+    }
 
-        function Render(scene, particles) {
-            Clear(scene)
-            particles.forEach(
-                function doDraw(particle) {
-                    Draw(scene, particle)
-                }
-            )
-        }
+    function MinMax(min, max) {
+      return { min, max };
+    }
 
-        function Animate(scene, particles) {
-            var updatedParticles = [],
-                fpsInterval = scene.fpsInterval,
-                now = performance.now(),
-                then = scene.then,
-                elapsed = now - then,
-                tolerance = 0.1
-
-            // Just render when we're reaching the configured fps
-            if (elapsed >= (scene.fpsInterval - tolerance)) {
-                scene.yOffset = getNodeYOffset(scene.anchorNode)
-                scene.then = now - (elapsed % fpsInterval)
-                Render(scene, particles)
-            }
-
-            // Update particle positions for the next render call
-            updatedParticles = particles.map(function doUpdate(p) {
-                return Update(scene, p)
-            })
-
-            // Function to animate the next frame
-            return function nextFrame() {
-                return Animate(
-                    scene,
-                    updatedParticles
-                )
-            }
-        }
+    function RandomPoint2D(minMaxX, minMaxY) {
+      var x = randomValue(minMaxX.min, minMaxX.max);
+      var y = randomValue(minMaxY.min, minMaxY.max);
+      return Point2D(x, y);
+    }
 
-        function CreateScene(cfg) {
-            var canvasId = cfg.canvasId,
-                contentId = cfg.contentId,
-                depth = cfg.depth,
-                fps = cfg.fps
-
-            var contentNode = document.getElementById(contentId),
-                width = window.innerWidth,
-                fpsInterval = 1000 / fps,
-                yOffset = 0,
-                canvas = document.getElementById(canvasId),
-                height = getNodeHeight(canvas),
-                ctx = canvas.getContext('2d'),
-                depthScaledHeight = height * (depth + 1)
-
-            ctx.canvas.width = width
-            ctx.canvas.height = window.innerHeight
-
-            return {
-                width: width,
-                height: depthScaledHeight,
-                yOffset: yOffset,
-                depthScale: depth,
-                fps: fps,
-                fpsInterval: fpsInterval,
-                then: performance.now(),
-                anchorNode: contentNode,
-                ctx: ctx,
-            }
-        }
+    //
+    //  Transformations | Actions
+    //
+
+    function Update(scene, particle) {
+      // Cache object access -> Performance
+      var width = scene.width;
+      var height = scene.height;
+      var color = particle.color;
+      var particleSize = particle.size;
+      var particleSizeStep = particleSize.step;
+      var particleSizeAnimValue = particleSize.animValue;
+      var particleSizeScale = particleSize.scale;
+      var particleSizeDirection = particleSize.direction;
+      var particlePosition = particle.position;
+      var particlePositionX = particlePosition.x;
+      var particlePositionY = particlePosition.y;
+      var particleDirection = particle.direction;
+      var particleDirectionX = particleDirection.x;
+      var particleDirectionY = particleDirection.y;
+
+      // Animate the pulse effect of the particle
+      //
+      // var absSizeAnimValue = particleSizeAnimValue * particleSizeDirection
+      var isMaxSize = particleSizeAnimValue > 1;
+      var isMinSize = particleSizeAnimValue < -1;
+      var sizeDirection = isMaxSize || isMinSize ? -particleSizeDirection : particleSizeDirection;
+      var animValue = particleSizeAnimValue + particleSizeStep * sizeDirection;
+      // The operator ~~ is a more performant shorthand for Math.trunc()
+      var sizeValue = ~~(easing(animValue) * particleSizeScale);
+
+      // Animate the movement of the particle
+      //
+      var sizeOffset = sizeValue * 0.5;
+      var top = particlePositionY + sizeOffset;
+      var bottom = particlePositionY - sizeOffset;
+      var left = particlePositionX - sizeOffset;
+      var right = particlePositionX + sizeOffset;
+
+      var isRightEdge = left > width + 1;
+      var isLeftEdge = right < -1;
+      var isTopEdge = bottom < -1;
+      var isBottomEdge = top > height + 1;
+
+      var positionX = isRightEdge
+        ? -sizeOffset
+        : isLeftEdge
+          ? width + sizeOffset
+          : particlePositionX + particleDirectionX;
+      var positionY = isBottomEdge
+        ? -sizeOffset
+        : isTopEdge
+          ? height + sizeOffset
+          : particlePositionY + particleDirectionY;
+      return {
+        position: {
+          x: positionX,
+          y: positionY,
+        },
+        direction: particleDirection,
+        size: {
+          value: sizeValue,
+          animValue: animValue,
+          step: particleSizeStep,
+          scale: particleSizeScale,
+          direction: sizeDirection,
+          offset: sizeOffset,
+        },
+        color: color,
+      };
+    }
 
+    function Draw(scene, particle) {
+      // Cache object access
+      var particlePosition = particle.position;
+      var particlePositionX = particlePosition.x;
+      var particlePositionY = particlePosition.y;
+      var particleSize = particle.size;
+      var particleSizeValue = particleSize.value;
+      var drawOffset = particleSize.offset;
+
+      // Draw calculations --
+      var yOffset = scene.yOffset * scene.depthScale;
+      var size = particleSizeValue;
+      var x = particlePositionX - drawOffset;
+      var y = yOffset + (particlePositionY - drawOffset);
+
+      var ctx = scene.ctx;
+      // var isVisible = (size > 0 && y < window.innerHeight && y > 0)
+      var isVisible = size > 0;
+
+      // Draw
+      if (isVisible) {
+        ctx.fillStyle = particle.color;
+        // Round to full integer to prevent subpixel rendering
+        //  - The ~~ operator is equivalent to Math.trunc() but faster.
+        // ctx.fillRect(~~x, ~~y, size, size)
+        ctx.fillRect(x, y, size, size);
+      }
+    }
 
-        function CreateParticles(scene, cfg) {
-            var density = cfg.density,
-                color = cfg.color,
-                size = cfg.size,
-                speed = cfg.speed,
-                lifespan = cfg.lifespan
-
-            var initAnimValue = randomValue(-1, 1)
-
-            return Array.from(
-                {
-                    // length: 1
-                    length: calcParticleCount(scene, density)
-                },
-                function Particle() {
-                    const lifeLength = randomValue(lifespan.min, lifespan.max)
-                    return {
-                        position:
-                            RandomPoint2D(
-                                MinMax(0, (scene.width - (size * 2))),
-                                MinMax(0, (scene.height - (size * 2))),
-                            ),
-                        direction:
-                            RandomPoint2D(
-                                MinMax(-speed, speed),
-                                MinMax(-speed, speed)
-                            ),
-                        size: {
-                            animValue: initAnimValue,
-                            scale: size,
-                            value: size * initAnimValue,
-                            step: 1 / ((lifeLength) / scene.fps),
-                            direction:
-                                // 50% Chance for the particle floating in one
-                                // direction or the other.
-                                (randomValue(0, 100) < 50)
-                                    ? -1
-                                    : +1,
-                            // Offset is needed for boundary calculation and for
-                            // drawing the pixels. We cache it here, to prevent
-                            // double calculation of the same value.
-                            offset: size * initAnimValue * 0.5
-                        },
-                        color
-                    }
-                }
-            )
-        }
+    function Clear(scene) {
+      scene.ctx.clearRect(0, 0, scene.width, scene.height);
+    }
 
+    function Render(scene, particles) {
+      Clear(scene);
+      particles.forEach(function doDraw(particle) {
+        Draw(scene, particle);
+      });
+    }
 
-        //
-        //  Api
-        //
-
-
-        function Particles(configs) {
-
-            var particles = []
-            var isRunning = false
-            var throttled = false
-            var delay = 250 // ms
-            var rafId = undefined
-
-            function animate(rendererList) {
-                if (isRunning) {
-                    rafId = requestAnimationFrame(function doRaf() {
-                        animate(
-                            rendererList.map(function doRender(render) {
-                                return render()
-                            })
-                        )
-                    })
-                }
-            }
-
-            function init() {
-                particles = configs.map(function (particleConfig) {
-                    var scene = CreateScene(particleConfig.scene)
-                    var particles = CreateParticles(scene, particleConfig.particles)
-                    return Animate(scene, particles)
-                })
-                return particles
-            }
-
-            function run() {
-                if (particles.length === 0) {
-                    particles = init()
-                }
-                isRunning = true
-                animate(particles)
-            }
-
-            function stop() {
-                isRunning = false
-                cancelAnimationFrame(rafId)
-            }
-
-            return {
-                init: init,
-                run: run,
-                stop: stop,
-                onScreenSizeChange: function onResize() {
-                    stop()
-                    if (!throttled) {
-                        throttled = true
-                        setTimeout(function () {
-                            particles = init()
-                            run()
-                            throttled = false
-                        }, delay)
-                    }
-                }
-            }
-        }
+    function Animate(scene, particles) {
+      var updatedParticles = [],
+        fpsInterval = scene.fpsInterval,
+        now = performance.now(),
+        then = scene.then,
+        elapsed = now - then,
+        tolerance = 0.1;
+
+      // Just render when we're reaching the configured fps
+      if (elapsed >= scene.fpsInterval - tolerance) {
+        scene.yOffset = getNodeYOffset(scene.anchorNode);
+        scene.then = now - (elapsed % fpsInterval);
+        Render(scene, particles);
+      }
+
+      // Update particle positions for the next render call
+      updatedParticles = particles.map(function doUpdate(p) {
+        return Update(scene, p);
+      });
+
+      // Function to animate the next frame
+      return function nextFrame() {
+        return Animate(scene, updatedParticles);
+      };
+    }
 
+    function CreateScene(cfg) {
+      var canvasId = cfg.canvasId,
+        contentId = cfg.contentId,
+        depth = cfg.depth,
+        fps = cfg.fps;
+
+      var contentNode = document.getElementById(contentId),
+        width = window.innerWidth,
+        fpsInterval = 1000 / fps,
+        yOffset = 0,
+        canvas = document.getElementById(canvasId),
+        height = getNodeHeight(canvas),
+        ctx = canvas.getContext("2d"),
+        depthScaledHeight = height * (depth + 1);
+
+      ctx.canvas.width = width;
+      ctx.canvas.height = window.innerHeight;
+
+      return {
+        width: width,
+        height: depthScaledHeight,
+        yOffset: yOffset,
+        depthScale: depth,
+        fps: fps,
+        fpsInterval: fpsInterval,
+        then: performance.now(),
+        anchorNode: contentNode,
+        ctx: ctx,
+      };
+    }
 
-        // Default Export
-        return Particles
+    function CreateParticles(scene, cfg) {
+      var density = cfg.density,
+        color = cfg.color,
+        size = cfg.size,
+        speed = cfg.speed,
+        lifespan = cfg.lifespan;
 
-    })()
+      var initAnimValue = randomValue(-1, 1);
 
-    var fgParticleConfig = {
-        scene: {
-            // Id of the canvas to render to
-            canvasId: 'fg-particles',
-            // Id of the content container, we're using it to get the 
-            // rendering height and it's the anchor to get the y offset
-            // to simulate scrolling.
-            contentId: 'content',
-            fps: 24,
-            depth: 2.5,
+      return Array.from(
+        {
+          // length: 1
+          length: calcParticleCount(scene, density),
         },
-        particles: {
-            density: 8,
-            color: 'white',
-            size: 20,
-            speed: 0.7,
-            lifespan: { // in milliseconds
-                min: 3500,
-                max: 7000
-            }
-        }
+        function Particle() {
+          const lifeLength = randomValue(lifespan.min, lifespan.max);
+          return {
+            position: RandomPoint2D(MinMax(0, scene.width - size * 2), MinMax(0, scene.height - size * 2)),
+            direction: RandomPoint2D(MinMax(-speed, speed), MinMax(-speed, speed)),
+            size: {
+              animValue: initAnimValue,
+              scale: size,
+              value: size * initAnimValue,
+              step: 1 / (lifeLength / scene.fps),
+              direction:
+                // 50% Chance for the particle floating in one
+                // direction or the other.
+                randomValue(0, 100) < 50 ? -1 : +1,
+              // Offset is needed for boundary calculation and for
+              // drawing the pixels. We cache it here, to prevent
+              // double calculation of the same value.
+              offset: size * initAnimValue * 0.5,
+            },
+            color,
+          };
+        },
+      );
     }
-    var bgParticleConfig = {
-        scene: {
-            // Id of the canvas to render to
-            canvasId: 'bg-particles',
-            // Id of the content container, we're using it to get the 
-            // rendering height and it's the anchor to get the y offset
-            // to simulate scrolling.
-            contentId: 'content',
-            fps: 16,
-            depth: 0.08,
+
+    //
+    //  Api
+    //
+
+    function Particles(configs) {
+      var particles = [];
+      var isRunning = false;
+      var throttled = false;
+      var delay = 250; // ms
+      var rafId = undefined;
+
+      function animate(rendererList) {
+        if (isRunning) {
+          rafId = requestAnimationFrame(function doRaf() {
+            animate(
+              rendererList.map(function doRender(render) {
+                return render();
+              }),
+            );
+          });
+        }
+      }
+
+      function init() {
+        particles = configs.map(function (particleConfig) {
+          var scene = CreateScene(particleConfig.scene);
+          var particles = CreateParticles(scene, particleConfig.particles);
+          return Animate(scene, particles);
+        });
+        return particles;
+      }
+
+      function run() {
+        if (particles.length === 0) {
+          particles = init();
+        }
+        isRunning = true;
+        animate(particles);
+      }
+
+      function stop() {
+        isRunning = false;
+        cancelAnimationFrame(rafId);
+      }
+
+      return {
+        init: init,
+        run: run,
+        stop: stop,
+        onScreenSizeChange: function onResize() {
+          stop();
+          if (!throttled) {
+            throttled = true;
+            setTimeout(function () {
+              particles = init();
+              run();
+              throttled = false;
+            }, delay);
+          }
         },
-        particles: {
-            density: 110,
-            color: 'white',
-            size: 6,
-            speed: 0.4,
-            lifespan: { // in milliseconds
-                min: 2500,
-                max: 5000
-            }
-        }
+      };
     }
-    var animation = Particles([
-        fgParticleConfig,
-        bgParticleConfig,
-    ])
-    animation.run()
-    window.addEventListener('resize', animation.onScreenSizeChange)
+
+    // Default Export
+    return Particles;
+  })();
+
+  var fgParticleConfig = {
+    scene: {
+      // Id of the canvas to render to
+      canvasId: "fg-particles",
+      // Id of the content container, we're using it to get the
+      // rendering height and it's the anchor to get the y offset
+      // to simulate scrolling.
+      contentId: "content",
+      fps: 24,
+      depth: 2.5,
+    },
+    particles: {
+      density: 8,
+      color: "white",
+      size: 20,
+      speed: 0.7,
+      lifespan: {
+        // in milliseconds
+        min: 3500,
+        max: 7000,
+      },
+    },
+  };
+  var bgParticleConfig = {
+    scene: {
+      // Id of the canvas to render to
+      canvasId: "bg-particles",
+      // Id of the content container, we're using it to get the
+      // rendering height and it's the anchor to get the y offset
+      // to simulate scrolling.
+      contentId: "content",
+      fps: 16,
+      depth: 0.08,
+    },
+    particles: {
+      density: 110,
+      color: "white",
+      size: 6,
+      speed: 0.4,
+      lifespan: {
+        // in milliseconds
+        min: 2500,
+        max: 5000,
+      },
+    },
+  };
+  var animation = Particles([fgParticleConfig, bgParticleConfig]);
+  animation.run();
+  window.addEventListener("resize", animation.onScreenSizeChange);
 });
diff --git a/src/plainui/static/plainui/js/modal.js b/src/plainui/static/plainui/js/modal.js
index a27bc6259..05318badd 100644
--- a/src/plainui/static/plainui/js/modal.js
+++ b/src/plainui/static/plainui/js/modal.js
@@ -1,45 +1,45 @@
 // wait until document is loaded
 var fpReady = (callback) => {
-    if (document.readyState != "loading") callback();
-    else document.addEventListener("DOMContentLoaded", callback);
-}
+  if (document.readyState != "loading") callback();
+  else document.addEventListener("DOMContentLoaded", callback);
+};
 
 fpReady(() => {
-    // one click listener to rule them all :)
-    document.addEventListener('click', function onclicked(e) {
-        documentClicked(e);
-    });
-    // check for the URL hash and open modal if hash is present
-    if (window.location.hash) {
-        showModal2(window.location.hash.substr(1));
-    }
+  // one click listener to rule them all :)
+  document.addEventListener("click", function onclicked(e) {
+    documentClicked(e);
+  });
+  // check for the URL hash and open modal if hash is present
+  if (window.location.hash) {
+    showModal2(window.location.hash.substr(1));
+  }
 });
 
-
 function documentClicked(e) {
-
-    if (e.target.dataset.eventid) {
-        e.preventDefault();
-        showModal2(e.target.dataset.eventid);
-    }
-
-    if (e.target.classList.contains('modal-close')) {
-        e.preventDefault();
-        removeFahrplanModal();
-    }
+  if (e.target.dataset.eventid) {
+    e.preventDefault();
+    showModal2(e.target.dataset.eventid);
+  }
+
+  if (e.target.classList.contains("modal-close")) {
+    e.preventDefault();
+    removeFahrplanModal();
+  }
 }
 
 function showModal2(event_id) {
-    let data_el = document.getElementById(event_id);
-    if (!data_el) {
-        return;
-    }
-    let data = JSON.parse(data_el.innerText);
-    if (!data) { return; }
-    let modal = document.createElement('div');
-    window.location.hash = event_id;
-    modal.classList.add('rc3-fahrplan__modal-box');
-    modal.innerHTML = `
+  let data_el = document.getElementById(event_id);
+  if (!data_el) {
+    return;
+  }
+  let data = JSON.parse(data_el.innerText);
+  if (!data) {
+    return;
+  }
+  let modal = document.createElement("div");
+  window.location.hash = event_id;
+  modal.classList.add("rc3-fahrplan__modal-box");
+  modal.innerHTML = `
     <div class="modal show modal-close" tabindex="-1" style="display:block;">
         <div class="modal-dialog modal-lg">
           <div class="modal-content border p-5 rc3-fahrplan__modal-content">
@@ -55,11 +55,12 @@ function showModal2(event_id) {
         </div>
     </div>
     `;
-    document.body.appendChild(modal);
+  document.body.appendChild(modal);
 }
 
 function eventContent(data) {
-    let content = `
+  let content =
+    `
     <dl class="rc3-fahrplan__modal-data">
         <dt>Start:</dt>
         <dd class=""><time datetime="${data.schedule_start}">${data.schedule_start}</time></dd>
@@ -70,9 +71,13 @@ function eventContent(data) {
         <dt>Room:</dt>
         <dd class="">${data.room_name}</dd>
 
-    ` +  (data.track_name && data.track_name != 'None' ? `
+    ` +
+    (data.track_name && data.track_name != "None"
+      ? `
         <dt>Track:</dt>
-        <dd class="">${data.track_name}</dd>` : '') + `
+        <dd class="">${data.track_name}</dd>`
+      : "") +
+    `
 
         <dt>Language:</dt>
         <dd class="">${data.language}</dd>
@@ -87,33 +92,32 @@ function eventContent(data) {
             <a class="a" href="https://media.ccc.de/v/${data.id}" title="recording" target="_blank">recording</a>
         </dd>
         `;
-    if (data.link != null) {
-        content += `
+  if (data.link != null) {
+    content += `
         <dt>Origin:</dt>
         <dd class=""><a class="a" href="${data.link}" alt="Details" target="_blank">${data.link}</a></dd>`;
-    }
+  }
 
-    content += `
+  content += `
     </dl>`;
 
-    if (data.abstract) {
-        content += `
+  if (data.abstract) {
+    content += `
         <hr class="my-4">
         <p>${data.abstract}</p>`;
-    }
+  }
 
-    content += `
+  content += `
         <hr class="my-4">
         <div class="rc3-markdown">${data.description_html}</div>`;
 
-    return content;
+  return content;
 }
 
 function removeFahrplanModal() {
-    window.location.hash = '_';
-    document.querySelectorAll('.rc3-fahrplan__modal-box').forEach(function (el) {
-        console.log('should remove');
-        el.remove();
-    });
+  window.location.hash = "_";
+  document.querySelectorAll(".rc3-fahrplan__modal-box").forEach(function (el) {
+    console.log("should remove");
+    el.remove();
+  });
 }
-
diff --git a/src/plainui/static/plainui/js/tools.js b/src/plainui/static/plainui/js/tools.js
index 5580500b1..8b9b96897 100644
--- a/src/plainui/static/plainui/js/tools.js
+++ b/src/plainui/static/plainui/js/tools.js
@@ -1,42 +1,41 @@
 // wait until document is loaded
 var docReady = (callback) => {
-    if (document.readyState != "loading") callback();
-    else document.addEventListener("DOMContentLoaded", callback);
-}
+  if (document.readyState != "loading") callback();
+  else document.addEventListener("DOMContentLoaded", callback);
+};
 
 docReady(() => {
-    // one click listener to rule them all :)
-    document.addEventListener('click',function onclicked(e){
-        documentClicked(e);
-    });
+  // one click listener to rule them all :)
+  document.addEventListener("click", function onclicked(e) {
+    documentClicked(e);
+  });
 
-    // hide all possible toggle targets
-    document.querySelectorAll('[data-rc3-tog-target]').forEach(function(target){
-        target.classList.add('d-none');
-    });
+  // hide all possible toggle targets
+  document.querySelectorAll("[data-rc3-tog-target]").forEach(function (target) {
+    target.classList.add("d-none");
+  });
 
-    // show all toggle buttons
-    document.querySelectorAll('[data-rc3-tog-btn]').forEach(function(target){
-        target.classList.remove('d-none');
-    });
+  // show all toggle buttons
+  document.querySelectorAll("[data-rc3-tog-btn]").forEach(function (target) {
+    target.classList.remove("d-none");
+  });
 });
 
 // one click listener to rule them all
 function documentClicked(e) {
-
-    // toggle visibility of buttons
-    if (e.target.hasAttribute('data-rc3-tog-btn') && e.target.hasAttribute('data-rc3-tog-stat') ) {
-        e.preventDefault();
-        if (e.target.dataset.rc3TogStat == 0) {
-            document.querySelectorAll(`[data-rc3-tog-target="${e.target.dataset.rc3TogBtn}"]`).forEach(function(target){
-                target.classList.remove('d-none');
-            });
-            e.target.dataset.rc3TogStat = 1;
-        } else {
-            document.querySelectorAll(`[data-rc3-tog-target="${e.target.dataset.rc3TogBtn}"]`).forEach(function(target){
-                target.classList.add('d-none');
-            });
-            e.target.dataset.rc3TogStat = 0;
-        }
+  // toggle visibility of buttons
+  if (e.target.hasAttribute("data-rc3-tog-btn") && e.target.hasAttribute("data-rc3-tog-stat")) {
+    e.preventDefault();
+    if (e.target.dataset.rc3TogStat == 0) {
+      document.querySelectorAll(`[data-rc3-tog-target="${e.target.dataset.rc3TogBtn}"]`).forEach(function (target) {
+        target.classList.remove("d-none");
+      });
+      e.target.dataset.rc3TogStat = 1;
+    } else {
+      document.querySelectorAll(`[data-rc3-tog-target="${e.target.dataset.rc3TogBtn}"]`).forEach(function (target) {
+        target.classList.add("d-none");
+      });
+      e.target.dataset.rc3TogStat = 0;
     }
+  }
 }
diff --git a/src/plainui/styles/_bootstrap.scss b/src/plainui/styles/_bootstrap.scss
index f77c39a86..f8bc99ffd 100644
--- a/src/plainui/styles/_bootstrap.scss
+++ b/src/plainui/styles/_bootstrap.scss
@@ -3,7 +3,6 @@
 @import "bootstrap/scss/mixins/banner";
 @include bsBanner("");
 
-
 // scss-docs-start import-stack
 // Configuration
 @import "bootstrap/scss/functions";
diff --git a/src/plainui/styles/_fonts.scss b/src/plainui/styles/_fonts.scss
index 6bbae5d70..6f68e97f2 100644
--- a/src/plainui/styles/_fonts.scss
+++ b/src/plainui/styles/_fonts.scss
@@ -1,7 +1,6 @@
 @font-face {
   font-family: "Gabriella";
-  src:
-    url("fonts/GabriellaHeavy.otf") format("opentype");
+  src: url("fonts/GabriellaHeavy.otf") format("opentype");
   font-weight: 400;
 }
 
@@ -21,4 +20,3 @@
     url("fonts/VCROCDFaux.woff2") format("woff2");
   font-weight: 400;
 }
-
diff --git a/src/plainui/styles/_grid.scss b/src/plainui/styles/_grid.scss
index 0757eedc3..63fb893ca 100644
--- a/src/plainui/styles/_grid.scss
+++ b/src/plainui/styles/_grid.scss
@@ -1,7 +1,7 @@
 .hub-row {
-    display: flex;
-    flex-direction: column;
-    gap: map-get($spacers, 2);
+  display: flex;
+  flex-direction: column;
+  gap: map-get($spacers, 2);
 }
 
 .hub-row > * {
@@ -15,16 +15,16 @@
 
 /* colum that takes up the remaining space */
 .hub-col-remaining {
-    flex: 1;
+  flex: 1;
 }
 
 @include media-breakpoint-up(lg) {
-    .hub-row {
-        flex-direction: row;
-    }
+  .hub-row {
+    flex-direction: row;
+  }
 
-    /* fixed 325px width column */
-    .hub-col-325px {
-        width: 325px;
-    }
+  /* fixed 325px width column */
+  .hub-col-325px {
+    width: 325px;
+  }
 }
diff --git a/src/plainui/styles/_helpers.scss b/src/plainui/styles/_helpers.scss
index 381053503..bc64e5601 100644
--- a/src/plainui/styles/_helpers.scss
+++ b/src/plainui/styles/_helpers.scss
@@ -2,5 +2,5 @@
  * Gets the rgb components from a hex colour.
  */
 @function rgbc($color) {
-    @return red($color) + ", " + green($color) + ", " + blue($color);
+  @return red($color) + ", " + green($color) + ", " + blue($color);
 }
diff --git a/src/plainui/styles/_layout.scss b/src/plainui/styles/_layout.scss
index 80db3d6a8..700695c21 100644
--- a/src/plainui/styles/_layout.scss
+++ b/src/plainui/styles/_layout.scss
@@ -52,7 +52,6 @@
   min-width: 0;
 }
 
-
 .hub-vlayout,
 .hub-vlayout-l,
 .hub-hlayout,
@@ -99,7 +98,8 @@
 
 @include media-breakpoint-up("md") {
   .hub-grid-title-buttons {
-    grid-template-areas: "title buttons"
+    grid-template-areas:
+      "title buttons"
       "tags tags";
   }
 
diff --git a/src/plainui/styles/_nav.scss b/src/plainui/styles/_nav.scss
index fe1ab9453..5a3e96020 100644
--- a/src/plainui/styles/_nav.scss
+++ b/src/plainui/styles/_nav.scss
@@ -1,14 +1,14 @@
 .hub-main-navbar {
-    background-color: $body-bg-dark;
-    display: flex;
-    flex-direction: column;
-    height: 100vh;
-    left: -100%;
-    position: fixed;
-    top: $hub-mobile-navbar-height;
-    transition: left 100ms;
-    width: 100%;
-    z-index: 1000;
+  background-color: $body-bg-dark;
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  left: -100%;
+  position: fixed;
+  top: $hub-mobile-navbar-height;
+  transition: left 100ms;
+  width: 100%;
+  z-index: 1000;
 }
 
 .hub-main-navbar-items {
@@ -16,79 +16,79 @@
 }
 
 .hub-mobile-navbar {
-    background-color: $body-bg-dark;
-    left: 0;
-    padding: 1rem .75rem;
-    position: fixed;
-    top: 0;
-    z-index: 1100;
-    width: 100%;
+  background-color: $body-bg-dark;
+  left: 0;
+  padding: 1rem 0.75rem;
+  position: fixed;
+  top: 0;
+  z-index: 1100;
+  width: 100%;
 }
 
 .hub-mobile-nav-title {
-    font-size: 1.9375rem;
-    font-weight: 200;
-    line-height: 2.5225rem;
-    margin-bottom: 0;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: nowrap;
+  font-size: 1.9375rem;
+  font-weight: 200;
+  line-height: 2.5225rem;
+  margin-bottom: 0;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
 .hub-main-navbar__category {
-    color: var(--bs-secondary-color);
-    font-size: 0.9375rem;
-    font-weight: 300;
-    text-transform: uppercase;
+  color: var(--bs-secondary-color);
+  font-size: 0.9375rem;
+  font-weight: 300;
+  text-transform: uppercase;
 }
 
 .hub-main-navbar__items {
-    list-style: none;
-    margin-bottom: map-get($spacers, 4);
-    padding: 0;
+  list-style: none;
+  margin-bottom: map-get($spacers, 4);
+  padding: 0;
 }
 
 .hub-main-navbar__item {
-    align-items: center;
-    color: var(--bs-secondary-color) !important;
-    display: flex;
-    font-size: 0.9375rem;
-    gap: map-get($spacers, 2);
-    padding: 6px map-get($spacers, 2) 6px 0;
-    text-decoration: none;
+  align-items: center;
+  color: var(--bs-secondary-color) !important;
+  display: flex;
+  font-size: 0.9375rem;
+  gap: map-get($spacers, 2);
+  padding: 6px map-get($spacers, 2) 6px 0;
+  text-decoration: none;
 }
 
 .hub-main-navbar__item:hover {
-    color: var(--bs-tertiary-color) !important;
+  color: var(--bs-tertiary-color) !important;
 }
 
 .hub-main-navbar__item--active {
-    color: var(--bs-tertiary-color) !important;
-    font-weight: 700;
+  color: var(--bs-tertiary-color) !important;
+  font-weight: 700;
 }
 
 #hub-mobile-nav-toggle:checked ~ #hub-main-navbar {
-    left: 0;
+  left: 0;
 }
 
 .hub-mobile-nav-badge {
-    position: absolute;
-    transform: translate(25%, -25%);
-    top: 8px;
-    right: 8px;
+  position: absolute;
+  transform: translate(25%, -25%);
+  top: 8px;
+  right: 8px;
 }
 
 @include media-breakpoint-up(md) {
-    .hub-mobile-navbar {
-        display: none;
-    }
+  .hub-mobile-navbar {
+    display: none;
+  }
 
-    #hub-main-navbar {
-        position: static;
-        width: 300px;
-    }
+  #hub-main-navbar {
+    position: static;
+    width: 300px;
+  }
 
-    .hub-navbar-logo {
-        display: block;
-    }
+  .hub-navbar-logo {
+    display: block;
+  }
 }
diff --git a/src/plainui/styles/_typography.scss b/src/plainui/styles/_typography.scss
index 96555514b..4b12f173d 100644
--- a/src/plainui/styles/_typography.scss
+++ b/src/plainui/styles/_typography.scss
@@ -2,17 +2,17 @@
 
 .hub-head-category,
 .hub-head-main {
-    margin-bottom: 0;
+  margin-bottom: 0;
 }
 
 .hub-text {
-    font-size: .9375rem;
-    font-weight: 400
+  font-size: 0.9375rem;
+  font-weight: 400;
 }
 
 .hub-section-title {
-    color: var(--bs-secondary-color);
-    font: $hub-head-category-font;
+  color: var(--bs-secondary-color);
+  font: $hub-head-category-font;
 }
 
 .hub-text-list-item-title {
diff --git a/src/plainui/styles/_util-classes.scss b/src/plainui/styles/_util-classes.scss
index fd25e895e..661824296 100644
--- a/src/plainui/styles/_util-classes.scss
+++ b/src/plainui/styles/_util-classes.scss
@@ -1,67 +1,67 @@
 :root {
-    --headings-font-family: #{$headings-font-family};
+  --headings-font-family: #{$headings-font-family};
 }
 
 ::selection {
-    color: $gray-900;
-    background: $primary;
+  color: $gray-900;
+  background: $primary;
 }
 
 /* Works on Firefox */
 * {
-    scrollbar-width: thin;
-    scrollbar-color: $primary transparent;
+  scrollbar-width: thin;
+  scrollbar-color: $primary transparent;
 }
 
 /* Works on Chrome, Edge, and Safari */
 *::-webkit-scrollbar {
-    width: $spacer * 0.75;
+  width: $spacer * 0.75;
 }
 
 *::-webkit-scrollbar-track {
-    background: $secondary;
+  background: $secondary;
 }
 
 *::-webkit-scrollbar-thumb {
-    background-color: $primary;
+  background-color: $primary;
 }
 
 html {
-    scroll-behavior: smooth;
+  scroll-behavior: smooth;
 }
 
 body {
-    overflow-x: hidden;
-    position: relative;
+  overflow-x: hidden;
+  position: relative;
 }
 
 .a {
+  text-decoration: underline;
+  color: $primary;
+
+  &:hover,
+  &:focus {
     text-decoration: underline;
     color: $primary;
+    text-shadow: $btn-hover-text-shadow;
+  }
 
-    &:hover,
-    &:focus {
-        text-decoration: underline;
-        color: $primary;
-        text-shadow: $btn-hover-text-shadow;
-    }
-
-    &-bold {
-        font-weight: 700;
-    }
+  &-bold {
+    font-weight: 700;
+  }
 
-    &-ital {
-        font-style: italic;
-    }
+  &-ital {
+    font-style: italic;
+  }
 }
 
 .fw-bold {
-    font-weight: 700;
+  font-weight: 700;
 }
 
 // overwrite bootstrap styles
 ul {
-    list-style: square;
+  list-style: square;
 }
 
 h1,
@@ -76,698 +76,699 @@ h5,
 .h5,
 h6,
 .h6 {
-    letter-spacing: $letter-spacing;
-    text-transform: lowercase;
-    word-spacing: $word-spacing;
+  letter-spacing: $letter-spacing;
+  text-transform: lowercase;
+  word-spacing: $word-spacing;
 }
 
 .shadow-darkmorphism {
-    box-shadow: $box-shadow-morphism;
+  box-shadow: $box-shadow-morphism;
 }
 
 #footer .nav-link {
-    font-family: $headings-font-family;
-    font-weight: 600;
-    font-size: 1rem;
-    letter-spacing: $letter-spacing;
+  font-family: $headings-font-family;
+  font-weight: 600;
+  font-size: 1rem;
+  letter-spacing: $letter-spacing;
 }
 
 .bg-transparent {
-    backdrop-filter: none;
+  backdrop-filter: none;
 }
 
 .fs-medium {
-    font-size: $medium-font-size;
+  font-size: $medium-font-size;
 }
 
 .font-headings {
-    font-family: $headings-font-family;
-    font-weight: 600;
+  font-family: $headings-font-family;
+  font-weight: 600;
 }
 
 .font-sans-serif {
-    font-family: $font-family-sans-serif;
+  font-family: $font-family-sans-serif;
 }
 
 h6,
 .h6,
 .text-transform-none {
-    text-transform: none;
+  text-transform: none;
 }
 
 .mw-664 {
-    max-width: 41.5rem;
+  max-width: 41.5rem;
 }
 
 .mw-810 {
-    max-width: 50.625rem;
+  max-width: 50.625rem;
 }
 
 .external {
-    white-space: nowrap;
-    font-weight: 700;
-    font-style: italic;
-
-    // &::after {
-    //     content: "";
-    //     display: inline-block;
-    //     width: $spacer;
-    //     height: $spacer;
-    //     margin-left: map-get($spacers, 1);
-    //     background: currentColor;
-    //     mask-size: contain;
-    //     mask-repeat: no-repeat;
-    //     mask-image: url("img/box-arrow-up-right.svg");
-    //     -webkit-mask-image: url("img/box-arrow-up-right.svg");
-    // }
+  white-space: nowrap;
+  font-weight: 700;
+  font-style: italic;
+
+  // &::after {
+  //     content: "";
+  //     display: inline-block;
+  //     width: $spacer;
+  //     height: $spacer;
+  //     margin-left: map-get($spacers, 1);
+  //     background: currentColor;
+  //     mask-size: contain;
+  //     mask-repeat: no-repeat;
+  //     mask-image: url("img/box-arrow-up-right.svg");
+  //     -webkit-mask-image: url("img/box-arrow-up-right.svg");
+  // }
 }
 
 .grid-list {
-    display: grid;
-    grid-template: auto / auto;
-    grid-gap: 0;
-
-    &__item {
-        display: flex;
-        flex-flow: row nowrap;
-        font-family: $font-family-sans-serif;
-        padding: 0;
-
-        &--title {
-            &::before {
-                content: "//";
-                margin-right: 0.5rem;
-            }
-        }
+  display: grid;
+  grid-template: auto / auto;
+  grid-gap: 0;
 
-        &--text {
-            margin-bottom: map-get($spacers, 3);
-        }
+  &__item {
+    display: flex;
+    flex-flow: row nowrap;
+    font-family: $font-family-sans-serif;
+    padding: 0;
+
+    &--title {
+      &::before {
+        content: "//";
+        margin-right: 0.5rem;
+      }
     }
+
+    &--text {
+      margin-bottom: map-get($spacers, 3);
+    }
+  }
 }
 
 .no-js .d-js-only {
-    display: none !important;
+  display: none !important;
 }
 
 // Basic Bootstrap table - only use the basic table
 // - if you need another configuration update the bootstrap variables
 .table {
-    border-collapse: separate;
-    border-spacing: $spacer * 0.5;
+  border-collapse: separate;
+  border-spacing: $spacer * 0.5;
 
-    thead th {
-        background: $info;
-        font-family: $headings-font-family;
-    }
+  thead th {
+    background: $info;
+    font-family: $headings-font-family;
+  }
 
-    td {
-        box-shadow: $box-shadow-morphism;
-    }
+  td {
+    box-shadow: $box-shadow-morphism;
+  }
 }
 
 @include media-breakpoint-down(sm) {
-    .card-deck {
-        .card {
-            margin-bottom: map-get($spacers, 3);
-        }
+  .card-deck {
+    .card {
+      margin-bottom: map-get($spacers, 3);
     }
+  }
 }
 
 .card-footer {
-    border-top: none;
-    background-color: transparent;
+  border-top: none;
+  background-color: transparent;
 }
 
 .form-check {
-    padding-left: 1.75rem;
+  padding-left: 1.75rem;
 
-    &-input {
-        position: absolute;
-        top: 0;
-        left: -9999px;
-        opacity: 0;
+  &-input {
+    position: absolute;
+    top: 0;
+    left: -9999px;
+    opacity: 0;
 
-        &:checked+.form-check-label::after {
-            opacity: 1;
-        }
+    &:checked + .form-check-label::after {
+      opacity: 1;
+    }
 
-        &:focus,
-        &:focus-within {
-            +.form-check-label::before {
-                box-shadow: $input-btn-focus-box-shadow;
-                border-color: #fff;
-            }
-        }
+    &:focus,
+    &:focus-within {
+      + .form-check-label::before {
+        box-shadow: $input-btn-focus-box-shadow;
+        border-color: #fff;
+      }
+    }
 
-        &.is-invalid+.form-check-label::before {
-            border-color: $danger;
-        }
+    &.is-invalid + .form-check-label::before {
+      border-color: $danger;
     }
+  }
 
-    &-label {
-        cursor: pointer;
+  &-label {
+    cursor: pointer;
 
-        &::before {
-            content: "";
-            display: block;
-            position: absolute;
-            top: 0;
-            left: 0;
-            border: 1px solid $primary;
-            width: 1.25rem;
-            height: 1.25rem;
-            transition: border-color .3s linear, box-shadow .3s linear;
-        }
+    &::before {
+      content: "";
+      display: block;
+      position: absolute;
+      top: 0;
+      left: 0;
+      border: 1px solid $primary;
+      width: 1.25rem;
+      height: 1.25rem;
+      transition:
+        border-color 0.3s linear,
+        box-shadow 0.3s linear;
+    }
 
-        &::after {
-            content: "";
-            display: block;
-            position: absolute;
-            top: 0.25rem;
-            left: 0.25rem;
-            background: $primary;
-            width: 0.75rem;
-            height: 0.75rem;
-            opacity: 0;
-            transition: opacity .3s linear;
-        }
+    &::after {
+      content: "";
+      display: block;
+      position: absolute;
+      top: 0.25rem;
+      left: 0.25rem;
+      background: $primary;
+      width: 0.75rem;
+      height: 0.75rem;
+      opacity: 0;
+      transition: opacity 0.3s linear;
     }
+  }
 }
 
-
-
 .form-control-selectbox {
-    position: relative;
-    color: $dark;
+  position: relative;
+  color: $dark;
 
-    &::before {
-        content: "";
-        display: block;
-        position: absolute;
-        top: 1px;
-        right: 1px;
-        width: 2.5rem;
-        height: calc(100% - 2px);
-        background: $info;
-        color: $dark;
-    }
+  &::before {
+    content: "";
+    display: block;
+    position: absolute;
+    top: 1px;
+    right: 1px;
+    width: 2.5rem;
+    height: calc(100% - 2px);
+    background: $info;
+    color: $dark;
+  }
 
-    &__icon {
-        position: absolute;
-        right: 10px;
-        top: 50%;
-        transform: translate(0, -50%);
-        display: block;
-        width: 1.25rem;
-        height: 1.25rem;
-        color: $dark;
-    }
+  &__icon {
+    position: absolute;
+    right: 10px;
+    top: 50%;
+    transform: translate(0, -50%);
+    display: block;
+    width: 1.25rem;
+    height: 1.25rem;
+    color: $dark;
+  }
 }
 
 .form-control {
-    background-color: transparent;
+  background-color: transparent;
 
-    >option {
-        background-color: #000;
-        color: $primary;
-    }
+  > option {
+    background-color: #000;
+    color: $primary;
+  }
 
-    &:focus {
-        border-color: rgb(255, 255, 255, 1);
-        background-color: transparent;
-    }
+  &:focus {
+    border-color: rgb(255, 255, 255, 1);
+    background-color: transparent;
+  }
 }
 
 .hub-spacer {
-    border: 1px solid transparent;
-    margin-top: 2rem;
-    margin-bottom: 2rem;
+  border: 1px solid transparent;
+  margin-top: 2rem;
+  margin-bottom: 2rem;
 }
 
 // here comes the eyecandy
 
 .hub-bg-L04 {
-    z-index: 0;
+  z-index: 0;
 }
 
 .hub-bg {
-    display: none;
-    visibility: hidden;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    position: fixed;
-    background-repeat: no-repeat;
-    background-size: cover;
-    background-color: transparent;
-    pointer-events: none;
-    background-attachment: fixed;
+  display: none;
+  visibility: hidden;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  position: fixed;
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-color: transparent;
+  pointer-events: none;
+  background-attachment: fixed;
 }
 
 .free .hub-bg-L10 {
-    display: block;
-    visibility: visible;
+  display: block;
+  visibility: visible;
 
-    z-index: -10;
-    background-image: url($dark-bg-land);
+  z-index: -10;
+  background-image: url($dark-bg-land);
 
-    @media screen and (orientation:portrait) {
-        background-image: url($dark-bg-port);
-    }
+  @media screen and (orientation: portrait) {
+    background-image: url($dark-bg-port);
+  }
 }
 
 .eyecandy {
-    .hub-bg {
-        display: block;
-        visibility: visible;
+  .hub-bg {
+    display: block;
+    visibility: visible;
 
-        &-L03 {
-            z-index: 3;
-            background-image: url('img/03_Vignette/RC3_vignette.png');
-            background-size: 100% 100%;
-        }
+    &-L03 {
+      z-index: 3;
+      background-image: url("img/03_Vignette/RC3_vignette.png");
+      background-size: 100% 100%;
+    }
 
-        &-L07 {
-            z-index: -7;
-            background-image: url('img/07_Grid/07_Grid.png');
-            background-size: 100% 100%;
-        }
+    &-L07 {
+      z-index: -7;
+      background-image: url("img/07_Grid/07_Grid.png");
+      background-size: 100% 100%;
+    }
 
-        &-L08 {
-            z-index: -8;
-            background-image: url('img/08_VCR_Overlay/08_VCR_Overlay.png');
-            background-size: 100% 100%;
-        }
+    &-L08 {
+      z-index: -8;
+      background-image: url("img/08_VCR_Overlay/08_VCR_Overlay.png");
+      background-size: 100% 100%;
+    }
 
-        &-L09 {
-            z-index: -9;
-            background-image: linear-gradient(to bottom right, $L09-bd-start, $L09-bd-end);
-            mix-blend-mode: color;
-        }
+    &-L09 {
+      z-index: -9;
+      background-image: linear-gradient(to bottom right, $L09-bd-start, $L09-bd-end);
+      mix-blend-mode: color;
+    }
 
-        &-L10 {
-            z-index: -10;
-            background-image: url($L10-bg-land);
+    &-L10 {
+      z-index: -10;
+      background-image: url($L10-bg-land);
 
-            @media screen and (orientation:portrait) {
-                background-image: url($L10-bg-port);
-            }
-        }
+      @media screen and (orientation: portrait) {
+        background-image: url($L10-bg-port);
+      }
     }
+  }
 
-    .hub-spacer {
-        display: block;
-        border: 0px;
-        height: 120px;
-        width: 100%;
-        background-repeat: no-repeat;
-        background-position: center;
-        background-size: contain;
-        margin-top: 2rem;
-        margin-bottom: 2rem;
+  .hub-spacer {
+    display: block;
+    border: 0px;
+    height: 120px;
+    width: 100%;
+    background-repeat: no-repeat;
+    background-position: center;
+    background-size: contain;
+    margin-top: 2rem;
+    margin-bottom: 2rem;
 
-        &:nth-of-type(4n+1) {
-            background-image: url($icon-1);
-        }
+    &:nth-of-type(4n + 1) {
+      background-image: url($icon-1);
+    }
 
-        &:nth-of-type(4n+2) {
-            background-image: url($icon-2);
-        }
+    &:nth-of-type(4n + 2) {
+      background-image: url($icon-2);
+    }
 
-        &:nth-of-type(4n+3) {
-            background-image: url($icon-3);
-        }
+    &:nth-of-type(4n + 3) {
+      background-image: url($icon-3);
+    }
 
-        &:nth-of-type(4n+4) {
-            background-image: url($icon-4);
-        }
+    &:nth-of-type(4n + 4) {
+      background-image: url($icon-4);
     }
+  }
 }
 
 .hub-spacer {
-    border: 1px solid transparent;
-    margin-top: 2rem;
-    margin-bottom: 2rem;
+  border: 1px solid transparent;
+  margin-top: 2rem;
+  margin-bottom: 2rem;
 }
 
 // here comes the eyecandy
 
 .hub-bg-L04 {
-    z-index: 0;
+  z-index: 0;
 }
 
 .hub-bg {
-    display: none;
-    visibility: hidden;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    position: fixed;
-    background-repeat: no-repeat;
-    background-size: cover;
-    background-color: transparent;
-    pointer-events: none;
+  display: none;
+  visibility: hidden;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  position: fixed;
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-color: transparent;
+  pointer-events: none;
 }
 
 .free .hub-bg-L10 {
-    display: block;
-    visibility: visible;
+  display: block;
+  visibility: visible;
 
-    z-index: -10;
-    background-image: url($dark-bg-land);
+  z-index: -10;
+  background-image: url($dark-bg-land);
 
-    @media screen and (orientation:portrait) {
-        background-image: url($dark-bg-port);
-    }
+  @media screen and (orientation: portrait) {
+    background-image: url($dark-bg-port);
+  }
 }
 
 .eyecandy {
-    .hub-bg {
-        display: block;
-        visibility: visible;
+  .hub-bg {
+    display: block;
+    visibility: visible;
 
-        &-L03 {
-            z-index: 3;
-            background-image: url('img/03_Vignette/RC3_vignette.png');
-            background-size: 100% 100%;
-        }
+    &-L03 {
+      z-index: 3;
+      background-image: url("img/03_Vignette/RC3_vignette.png");
+      background-size: 100% 100%;
+    }
 
-        &-L07 {
-            z-index: -7;
-            background-image: url('img/07_Grid/07_Grid.png');
-            background-size: 100% 100%;
-        }
+    &-L07 {
+      z-index: -7;
+      background-image: url("img/07_Grid/07_Grid.png");
+      background-size: 100% 100%;
+    }
 
-        &-L08 {
-            z-index: -8;
-            background-image: url('img/08_VCR_Overlay/08_VCR_Overlay.png');
-            background-size: 100% 100%;
-        }
+    &-L08 {
+      z-index: -8;
+      background-image: url("img/08_VCR_Overlay/08_VCR_Overlay.png");
+      background-size: 100% 100%;
+    }
 
-        &-L09 {
-            z-index: -9;
-            background-image: linear-gradient(to bottom right, $L09-bd-start, $L09-bd-end);
-            mix-blend-mode: color;
-            position: absolute;
-            background-attachment: scroll;
-        }
+    &-L09 {
+      z-index: -9;
+      background-image: linear-gradient(to bottom right, $L09-bd-start, $L09-bd-end);
+      mix-blend-mode: color;
+      position: absolute;
+      background-attachment: scroll;
+    }
 
-        &-L10 {
-            z-index: -10;
-            background-image: url($L10-bg-land);
+    &-L10 {
+      z-index: -10;
+      background-image: url($L10-bg-land);
 
-            @media screen and (orientation:portrait) {
-                background-image: url($L10-bg-port);
-            }
-        }
+      @media screen and (orientation: portrait) {
+        background-image: url($L10-bg-port);
+      }
     }
+  }
 
-    .hub-spacer {
-        display: block;
-        border: 0px;
-        height: 120px;
-        width: 100%;
-        background-repeat: no-repeat;
-        background-position: center;
-        background-size: contain;
-        margin-top: 2rem;
-        margin-bottom: 2rem;
+  .hub-spacer {
+    display: block;
+    border: 0px;
+    height: 120px;
+    width: 100%;
+    background-repeat: no-repeat;
+    background-position: center;
+    background-size: contain;
+    margin-top: 2rem;
+    margin-bottom: 2rem;
 
-        &:nth-of-type(4n+1) {
-            background-image: url($icon-1);
-        }
+    &:nth-of-type(4n + 1) {
+      background-image: url($icon-1);
+    }
 
-        &:nth-of-type(4n+2) {
-            background-image: url($icon-2);
-        }
+    &:nth-of-type(4n + 2) {
+      background-image: url($icon-2);
+    }
 
-        &:nth-of-type(4n+3) {
-            background-image: url($icon-3);
-        }
+    &:nth-of-type(4n + 3) {
+      background-image: url($icon-3);
+    }
 
-        &:nth-of-type(4n+4) {
-            background-image: url($icon-4);
-        }
+    &:nth-of-type(4n + 4) {
+      background-image: url($icon-4);
     }
+  }
 }
 
-.hub-bg-L01, .hub-bg-L06 {
-    display: none;
-    visibility: hidden;
+.hub-bg-L01,
+.hub-bg-L06 {
+  display: none;
+  visibility: hidden;
 }
 
 .eyecandy-deluxe {
+  .hub-main {
+    -webkit-mask-position: top center;
+    -webkit-mask-image: none;
+    -webkit-mask-origin: margin-box;
+    -webkit-mask-repeat: no-repeat;
+    -webkit-mask-mode: alpha;
+    mask-position: top center;
+    mask-image: none;
+    mask-origin: margin-box;
+    mask-repeat: no-repeat;
+    mask-mode: alpha;
+  }
+
+  .hub-header {
+    position: sticky;
+    top: 0;
+  }
 
-    .hub-main {
-        -webkit-mask-position: top center;
-        -webkit-mask-image: none;
-        -webkit-mask-origin: margin-box;
-        -webkit-mask-repeat: no-repeat;
-        -webkit-mask-mode: alpha;
-        mask-position: top center;
-        mask-image: none;
-        mask-origin: margin-box;
-        mask-repeat: no-repeat;
-        mask-mode: alpha;
+  .hub-logo img {
+    content: url("img/02a_Logo_web_400px_ani.gif");
+  }
+
+  .hub-bg {
+    display: block;
+    visibility: visible;
+
+    &-L01,
+    &-L06 {
+      display: block;
+      visibility: visible;
+      width: 100%;
+      height: 100vh;
+      background-size: 100% 100%;
+      background-repeat: no-repeat;
+      background-position: center center;
+      content: "";
+      display: block;
+      visibility: visible;
+      position: fixed;
+      top: 0;
+      right: 0;
+      left: 0;
+      bottom: 0;
+      pointer-events: none;
+    }
+
+    &-L01 {
+      z-index: 20;
+      opacity: 0.2;
+      filter: blur(1px);
     }
 
-    .hub-header {
-        position: sticky;
-        top: 0;
+    &-L06 {
+      z-index: -6;
+      opacity: 0.35;
     }
 
-    .hub-logo img {
-        content: url('img/02a_Logo_web_400px_ani.gif');
+    &-L03 {
+      z-index: 3;
+      background-image: url("img/03_Vignette/RC3_vignette.png");
+      background-size: 100% 100%;
     }
 
-    .hub-bg {
+    &-L05 {
+      z-index: -5;
+      max-width: 1120px;
+      margin: 0 auto;
+      opacity: 0.6;
+
+      &-R,
+      &-L {
         display: block;
-        visibility: visible;
-
-        &-L01, &-L06 {
-            display: block;
-            visibility: visible;
-            width: 100%;
-            height: 100vh;
-            background-size: 100% 100%;
-            background-repeat: no-repeat;
-            background-position: center center;
-            content: "";
-            display: block;
-            visibility: visible;
-            position: fixed;
-            top: 0;
-            right: 0;
-            left: 0;
-            bottom: 0;
-            pointer-events: none;
-        }
+        content: "";
+        position: absolute;
+        background-repeat: no-repeat;
+        background-size: contain;
+        background-position: center;
+        transform: scale(1);
+      }
+
+      &-R {
+        top: 28vh;
 
-        &-L01 {
-            z-index: 20;
-            opacity: 0.2;
-            filter: blur(1px);
+        &.collage-r-1 {
+          background-image: url("img/05_Collage/05_collage_1_bust_vr-goggles_R_halfres_ani_V01.gif");
+          height: 250px;
+          width: 250px;
+          right: -125px;
         }
 
-        &-L06 {
-            z-index: -6;
-            opacity: 0.35;
+        &.collage-r-2 {
+          background-image: url("img/05_Collage/05_Collage_2_robothand_nib_R_halfres_ani_V01.gif");
+          height: 200px;
+          width: 300px;
+          right: -150px;
         }
 
-        &-L03 {
-            z-index: 3;
-            background-image: url('img/03_Vignette/RC3_vignette.png');
-            background-size: 100% 100%;
+        &.collage-r-3 {
+          background-image: url("img/05_Collage/05_Collage_3_baby_ethernet_R_halfres_ani_V01.gif");
+          height: 300px;
+          width: 300px;
+          right: -150px;
         }
 
-        &-L05 {
-            z-index: -5;
-            max-width: 1120px;
-            margin: 0 auto;
-            opacity: 0.6;
-
-            &-R,
-            &-L {
-                display: block;
-                content: "";
-                position: absolute;
-                background-repeat: no-repeat;
-                background-size: contain;
-                background-position: center;
-                transform: scale(1);
-            }
-
-            &-R {
-                top: 28vh;
-
-                &.collage-r-1 {
-                    background-image: url('img/05_Collage/05_collage_1_bust_vr-goggles_R_halfres_ani_V01.gif');
-                    height: 250px;
-                    width: 250px;
-                    right: -125px;
-                }
-
-                &.collage-r-2 {
-                    background-image: url('img/05_Collage/05_Collage_2_robothand_nib_R_halfres_ani_V01.gif');
-                    height: 200px;
-                    width: 300px;
-                    right: -150px;
-                }
-
-                &.collage-r-3 {
-                    background-image: url('img/05_Collage/05_Collage_3_baby_ethernet_R_halfres_ani_V01.gif');
-                    height: 300px;
-                    width: 300px;
-                    right: -150px;
-                }
-
-                &.collage-r-4 {
-                    background-image: url('img/05_Collage/05_Collage_4_sunflower_bitcoin_R_halfres_ani_V01.gif');
-                    height: 450px;
-                    width: 350px;
-                    right: -150px;
-                }
-
-                &.collage-r-5 {
-                    background-image: url('img/05_Collage/05_Collage_7_bird_cam_R_halfres_ani_V01.gif');
-                    height: 300px;
-                    width: 600px;
-                    right: -300px;
-                }
-
-                &.collage-r-6 {
-                    background-image: url('img/05_Collage/05_Collage_6_astronaut_c64_R_halfres_ani_V01.gif');
-                    height: 500px;
-                    width: 300px;
-                    right: -150px;
-                }
-
-                &.collage-r-7 {
-                    background-image: url('img/05_Collage/05_Collage_5_smartphone_tunnel_halfres_ani_V01.gif');
-                    height: 350px;
-                    width: 250px;
-                    right: -125px;
-                }
-            }
-
-            &-L {
-                left: 0;
-                bottom: -1vh;
-
-                &.collage-l-1 {
-                    background-image: url('img/05_Collage/05_Collage_5_smartphone_tunnel_halfres_ani_V01.gif');
-                    height: 350px;
-                    width: 250px;
-                    left: -125px;
-                }
-
-                &.collage-l-2 {
-                    background-image: url('img/05_Collage/05_collage_1_bust_vr-goggles_L_halfres_ani_V01.gif');
-                    height: 250px;
-                    width: 250px;
-                    left: -125px;
-                }
-
-                &.collage-l-3 {
-                    background-image: url('img/05_Collage/05_Collage_2_robothand_nib_L_halfres_ani_V01.gif');
-                    height: 200px;
-                    width: 300px;
-                    left: -150px;
-                }
-
-                &.collage-l-4 {
-                    background-image: url('img/05_Collage/05_Collage_3_baby_ethernet_L_halfres_ani_V01.gif');
-                    height: 300px;
-                    width: 300px;
-                    left: -150px;
-                }
-
-                &.collage-l-5 {
-                    background-image: url('img/05_Collage/05_Collage_6_astronaut_c64_L_halfres_ani_V01.gif');
-                    height: 500px;
-                    width: 300px;
-                    left: -150px;
-                }
-
-                &.collage-l-6 {
-                    background-image: url('img/05_Collage/05_Collage_7_bird_cam_L_halfres_ani_V01.gif');
-                    height: 300px;
-                    width: 600px;
-                    left: -300px;
-                }
-            }
+        &.collage-r-4 {
+          background-image: url("img/05_Collage/05_Collage_4_sunflower_bitcoin_R_halfres_ani_V01.gif");
+          height: 450px;
+          width: 350px;
+          right: -150px;
         }
 
-        &-L07 {
-            z-index: -7;
-            background-image: url('img/07_Grid/07_Grid.png');
-            background-size: 100% 100%;
+        &.collage-r-5 {
+          background-image: url("img/05_Collage/05_Collage_7_bird_cam_R_halfres_ani_V01.gif");
+          height: 300px;
+          width: 600px;
+          right: -300px;
         }
 
-        &-L08 {
-            z-index: -8;
-            background-image: url('img/08_VCR_Overlay/08_VCR_Overlay.png');
-            background-size: 100% 100%;
+        &.collage-r-6 {
+          background-image: url("img/05_Collage/05_Collage_6_astronaut_c64_R_halfres_ani_V01.gif");
+          height: 500px;
+          width: 300px;
+          right: -150px;
         }
 
-        &-L09 {
-            z-index: -9;
-            background-image: linear-gradient(to bottom right, $L09-bd-start, $L09-bd-end);
-            mix-blend-mode: color;
-            position: absolute;
-            background-attachment: scroll;
+        &.collage-r-7 {
+          background-image: url("img/05_Collage/05_Collage_5_smartphone_tunnel_halfres_ani_V01.gif");
+          height: 350px;
+          width: 250px;
+          right: -125px;
         }
+      }
 
-        &-L10 {
-            background-attachment: initial;
-            background-position-y: 0;
-            top: 0;
-            position: fixed;
-            height: 105%;
-            width: 100%;
-            z-index: -10;
-            background-image: url($L10-bg-land);
-
-            @media screen and (orientation:portrait) {
-                background-image: url($L10-bg-port);
-            }
+      &-L {
+        left: 0;
+        bottom: -1vh;
+
+        &.collage-l-1 {
+          background-image: url("img/05_Collage/05_Collage_5_smartphone_tunnel_halfres_ani_V01.gif");
+          height: 350px;
+          width: 250px;
+          left: -125px;
         }
-    }
 
-    .hub-spacer {
-        display: block;
-        border: 0px;
-        height: 120px;
-        width: 100%;
-        background-repeat: no-repeat;
-        background-position: center;
-        background-size: contain;
-        margin-top: 2rem;
-        margin-bottom: 2rem;
-        opacity: 0.75;
+        &.collage-l-2 {
+          background-image: url("img/05_Collage/05_collage_1_bust_vr-goggles_L_halfres_ani_V01.gif");
+          height: 250px;
+          width: 250px;
+          left: -125px;
+        }
 
-        &:nth-of-type(4n+1) {
-            background-image: url($icon-ani-1);
+        &.collage-l-3 {
+          background-image: url("img/05_Collage/05_Collage_2_robothand_nib_L_halfres_ani_V01.gif");
+          height: 200px;
+          width: 300px;
+          left: -150px;
         }
 
-        &:nth-of-type(4n+2) {
-            background-image: url($icon-ani-2);
+        &.collage-l-4 {
+          background-image: url("img/05_Collage/05_Collage_3_baby_ethernet_L_halfres_ani_V01.gif");
+          height: 300px;
+          width: 300px;
+          left: -150px;
         }
 
-        &:nth-of-type(4n+3) {
-            background-image: url($icon-ani-3);
+        &.collage-l-5 {
+          background-image: url("img/05_Collage/05_Collage_6_astronaut_c64_L_halfres_ani_V01.gif");
+          height: 500px;
+          width: 300px;
+          left: -150px;
         }
 
-        &:nth-of-type(4n+4) {
-            background-image: url($icon-ani-4);
+        &.collage-l-6 {
+          background-image: url("img/05_Collage/05_Collage_7_bird_cam_L_halfres_ani_V01.gif");
+          height: 300px;
+          width: 600px;
+          left: -300px;
         }
+      }
+    }
+
+    &-L07 {
+      z-index: -7;
+      background-image: url("img/07_Grid/07_Grid.png");
+      background-size: 100% 100%;
+    }
+
+    &-L08 {
+      z-index: -8;
+      background-image: url("img/08_VCR_Overlay/08_VCR_Overlay.png");
+      background-size: 100% 100%;
+    }
+
+    &-L09 {
+      z-index: -9;
+      background-image: linear-gradient(to bottom right, $L09-bd-start, $L09-bd-end);
+      mix-blend-mode: color;
+      position: absolute;
+      background-attachment: scroll;
+    }
+
+    &-L10 {
+      background-attachment: initial;
+      background-position-y: 0;
+      top: 0;
+      position: fixed;
+      height: 105%;
+      width: 100%;
+      z-index: -10;
+      background-image: url($L10-bg-land);
+
+      @media screen and (orientation: portrait) {
+        background-image: url($L10-bg-port);
+      }
+    }
+  }
+
+  .hub-spacer {
+    display: block;
+    border: 0px;
+    height: 120px;
+    width: 100%;
+    background-repeat: no-repeat;
+    background-position: center;
+    background-size: contain;
+    margin-top: 2rem;
+    margin-bottom: 2rem;
+    opacity: 0.75;
+
+    &:nth-of-type(4n + 1) {
+      background-image: url($icon-ani-1);
+    }
+
+    &:nth-of-type(4n + 2) {
+      background-image: url($icon-ani-2);
+    }
+
+    &:nth-of-type(4n + 3) {
+      background-image: url($icon-ani-3);
+    }
+
+    &:nth-of-type(4n + 4) {
+      background-image: url($icon-ani-4);
     }
+  }
 }
 
 .aspect-ratio-16by9 {
-    aspect-ratio: 1;
-    object-fit: contain;
+  aspect-ratio: 1;
+  object-fit: contain;
 }
diff --git a/src/plainui/styles/_variables.scss b/src/plainui/styles/_variables.scss
index 4e7d09ccf..a1258e88a 100644
--- a/src/plainui/styles/_variables.scss
+++ b/src/plainui/styles/_variables.scss
@@ -1,5 +1,20 @@
-$font-family-sans-serif: "Mona Sans", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
-$font-family-monospace: "VCR OCD Faux", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
+$font-family-sans-serif:
+  "Mona Sans",
+  system-ui,
+  -apple-system,
+  "Segoe UI",
+  Roboto,
+  "Helvetica Neue",
+  "Noto Sans",
+  "Liberation Sans",
+  Arial,
+  sans-serif,
+  "Apple Color Emoji",
+  "Segoe UI Emoji",
+  "Segoe UI Symbol",
+  "Noto Color Emoji";
+$font-family-monospace: "VCR OCD Faux", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
+  monospace !default;
 
 @import "./design/variables";
 
@@ -55,7 +70,7 @@ $signal-secondary-border: $signal-secondary-border-dark;
 $signal-muted-bg: $signal-muted-bg-dark;
 $signal-muted-border: $signal-muted-border-dark;
 $signal-muted-text: $signal-muted-text-dark;
-$alert-border-color: #6D8589;
+$alert-border-color: #6d8589;
 
 $hub-mobile-navbar-height: 73px;
 
diff --git a/src/plainui/styles/components/_avatar.scss b/src/plainui/styles/components/_avatar.scss
index 0a8dc9ede..353e543d0 100644
--- a/src/plainui/styles/components/_avatar.scss
+++ b/src/plainui/styles/components/_avatar.scss
@@ -1,42 +1,53 @@
 .hub-avatar {
+  padding: 0;
+  margin: 0;
+
+  &__none {
     padding: 0;
     margin: 0;
+    max-width: 100%;
+  }
 
-    &__none {
-        padding: 0;
-        margin: 0;
-        max-width: 100%;
-    }
+  &__wa-stacked {
+    position: relative;
+    width: 32px;
+    height: 32px;
+  }
 
-    &__wa-stacked {
-        position: relative;
-        width: 32px;
-        height: 32px;
-    }
+  &__wa-std,
+  &__wa-multi {
+    position: relative;
+    padding: 0;
+    margin: 0;
+    width: 32px;
+    height: 32px;
+    display: block;
+    animation:
+      hub-avatar-move-x 0.4s steps(3) infinite,
+      hub-avatar-move-y 5s steps(4) infinite;
+  }
 
-    &__wa-std, &__wa-multi {
-        position: relative;
-        padding: 0;
-        margin: 0;
-        width: 32px;
-        height: 32px;
-        display: block;
-        animation: hub-avatar-move-x 0.4s steps(3) infinite, hub-avatar-move-y 5s steps(4) infinite;
-    }
+  &__wa-multi:not(:first-child) {
+    position: absolute;
+    top: 0;
+    left: 0;
+  }
 
-    &__wa-multi:not(:first-child) {
-        position: absolute;
-        top: 0;
-        left: 0;
+  @keyframes hub-avatar-move-x {
+    from {
+      background-position-x: 0px;
     }
-
-    @keyframes hub-avatar-move-x{
-        from{background-position-x:0px;}
-        to{background-position-x:-96px;}
+    to {
+      background-position-x: -96px;
     }
+  }
 
-    @keyframes hub-avatar-move-y{
-        from{background-position-y:0px;}
-        to{background-position-y:-128px;}
+  @keyframes hub-avatar-move-y {
+    from {
+      background-position-y: 0px;
+    }
+    to {
+      background-position-y: -128px;
     }
+  }
 }
diff --git a/src/plainui/styles/components/_badges.scss b/src/plainui/styles/components/_badges.scss
index a872640a3..1745fbc93 100644
--- a/src/plainui/styles/components/_badges.scss
+++ b/src/plainui/styles/components/_badges.scss
@@ -54,7 +54,7 @@
 }
 
 .hub-badges-gallery {
-    display: flex;
-    flex-wrap: wrap;
-    gap: map-get($spacers, 2);
+  display: flex;
+  flex-wrap: wrap;
+  gap: map-get($spacers, 2);
 }
diff --git a/src/plainui/styles/components/_card.scss b/src/plainui/styles/components/_card.scss
index beba0fa25..a6095d9a1 100644
--- a/src/plainui/styles/components/_card.scss
+++ b/src/plainui/styles/components/_card.scss
@@ -2,8 +2,8 @@
  * Can be used to wrap hub-content.
  */
 .hub-card {
-    background-color: var(--bs-secondary-bg);
-    border-radius: var(--bs-border-radius);
-    border-top: 1px solid rgba(255, 255, 255, .03);
-    padding: map-get($spacers, 3) map-get($spacers, 4);
+  background-color: var(--bs-secondary-bg);
+  border-radius: var(--bs-border-radius);
+  border-top: 1px solid rgba(255, 255, 255, 0.03);
+  padding: map-get($spacers, 3) map-get($spacers, 4);
 }
diff --git a/src/plainui/styles/components/_event.scss b/src/plainui/styles/components/_event.scss
index 56c88f776..ae1398749 100644
--- a/src/plainui/styles/components/_event.scss
+++ b/src/plainui/styles/components/_event.scss
@@ -1,119 +1,119 @@
 .hub-event {
-    /* store current class for use in nested rules */
-    $g: &;
-
-    border: 1px solid $signal-secondary-bg;
-    color: var(--event-color);
-    column-gap: map-get($spacers, 3);
-    display: grid;
-    grid-template-areas:
-        "date date"
-        "name name"
-        "tags tags"
-        "buttons buttons";
-    grid-template-columns: auto 1fr;
-    line-height: 1;
-    row-gap: map-get($spacers, 2);
-    padding: map-get($spacers, 2) map-get($spacers, 4);
-
-    &.hub-event--now {
-        background-color: $signal-primary-fill;
-        border: none;
-        --event-color: #{$signal-invert-fill};
-    }
-
-    &.hub-event--past {
-        background-color: $signal-muted-bg;
-        border: none;
-        --event-color: #{$signal-muted-text};
-
-        .hub-tag {
-            /* make all tags look grey for past events */
-            background-color: $signal-muted-text !important;
-            border: none;
-            color: $signal-invert-text !important;
-        }
-    }
-
-    &.hub-event--upcoming {
-        --event-color: #{$signal-secondary-text};
-    }
-
-    &__tags {
-      grid-area: tags;
-    }
-
-    &__date {
-        grid-area: date;
-    }
-
-    &__time {
-        font-family: $font-family-monospace;
-        font-size: 1.5rem;
-        text-transform: uppercase;
-        white-space: nowrap;
-    }
-
-    &__day {
-        font-family: $font-family-monospace;
-        font-size: 0.9375rem;
-    }
-
-    &__name-container {
-        align-items: baseline;
-        display: flex;
-        font-size: 1.5rem;
-        gap: .5rem;
-        grid-area: name;
-        /* min-width for text overflow ellipsis */
-        min-width: 0;
-    }
-
-    &__name {
-        /* imporant to override link styles */
-        color: var(--event-color) !important;
-        /* imporant to override link styles */
-        text-decoration: none !important;
-    }
-
-    &__now {
-        color: $white;
-        font-family: Gabriella, sans-serif;
-        font-weight: 900;
+  /* store current class for use in nested rules */
+  $g: &;
+
+  border: 1px solid $signal-secondary-bg;
+  color: var(--event-color);
+  column-gap: map-get($spacers, 3);
+  display: grid;
+  grid-template-areas:
+    "date date"
+    "name name"
+    "tags tags"
+    "buttons buttons";
+  grid-template-columns: auto 1fr;
+  line-height: 1;
+  row-gap: map-get($spacers, 2);
+  padding: map-get($spacers, 2) map-get($spacers, 4);
+
+  &.hub-event--now {
+    background-color: $signal-primary-fill;
+    border: none;
+    --event-color: #{$signal-invert-fill};
+  }
+
+  &.hub-event--past {
+    background-color: $signal-muted-bg;
+    border: none;
+    --event-color: #{$signal-muted-text};
+
+    .hub-tag {
+      /* make all tags look grey for past events */
+      background-color: $signal-muted-text !important;
+      border: none;
+      color: $signal-invert-text !important;
     }
+  }
+
+  &.hub-event--upcoming {
+    --event-color: #{$signal-secondary-text};
+  }
+
+  &__tags {
+    grid-area: tags;
+  }
+
+  &__date {
+    grid-area: date;
+  }
+
+  &__time {
+    font-family: $font-family-monospace;
+    font-size: 1.5rem;
+    text-transform: uppercase;
+    white-space: nowrap;
+  }
+
+  &__day {
+    font-family: $font-family-monospace;
+    font-size: 0.9375rem;
+  }
+
+  &__name-container {
+    align-items: baseline;
+    display: flex;
+    font-size: 1.5rem;
+    gap: 0.5rem;
+    grid-area: name;
+    /* min-width for text overflow ellipsis */
+    min-width: 0;
+  }
+
+  &__name {
+    /* imporant to override link styles */
+    color: var(--event-color) !important;
+    /* imporant to override link styles */
+    text-decoration: none !important;
+  }
+
+  &__now {
+    color: $white;
+    font-family: Gabriella, sans-serif;
+    font-weight: 900;
+  }
+
+  &__buttons {
+    display: flex;
+    grid-area: buttons;
+    gap: 0.5rem;
+    justify-content: flex-start;
+  }
+
+  @include media-breakpoint-up("md") {
+    grid-template-areas:
+      "date name buttons"
+      "date tags buttons";
+    grid-template-columns: auto auto 1fr;
 
     &__buttons {
-        display: flex;
-        grid-area: buttons;
-        gap: .5rem;
-        justify-content: flex-start;
+      align-items: center;
+      justify-content: flex-end;
     }
 
-    @include media-breakpoint-up("md") {
-        grid-template-areas:
-            "date name buttons"
-            "date tags buttons";
-        grid-template-columns: auto auto 1fr;
-
-        &__buttons {
-            align-items: center;
-            justify-content: flex-end;
-        }
-
-        &__date,
-        &__day {
-          text-align: right;
-        }
+    &__date,
+    &__day {
+      text-align: right;
     }
+  }
 }
 
 .hub-event--small {
-    grid-template-areas:
-        "date date"
-        "name name"
-        "tags tags"
-        "buttons buttons";
-    grid-template-columns: auto 1fr;
+  grid-template-areas:
+    "date date"
+    "name name"
+    "tags tags"
+    "buttons buttons";
+  grid-template-columns: auto 1fr;
 }
 
 .hub-event--small .hub-event__date,
@@ -126,18 +126,18 @@
 }
 
 .hub-event-details-group {
-    margin-top: map-get($spacers, 4);
+  margin-top: map-get($spacers, 4);
 }
 
 .hub-event-details-group__label {
-    color: map-get($colors, 'gray');
-    margin-bottom: map-get($spacers, 2);
+  color: map-get($colors, "gray");
+  margin-bottom: map-get($spacers, 2);
 }
 
 .hub-event-details-group__value {
-    border-radius: 8px;
-    background-color: map-get($colors, 'black');
-    padding: map-get($spacers, 3);
+  border-radius: 8px;
+  background-color: map-get($colors, "black");
+  padding: map-get($spacers, 3);
 }
 
 .hub-event-details__time {
diff --git a/src/plainui/styles/components/_fahrplan.scss b/src/plainui/styles/components/_fahrplan.scss
index e208ee2d5..e00976b65 100644
--- a/src/plainui/styles/components/_fahrplan.scss
+++ b/src/plainui/styles/components/_fahrplan.scss
@@ -1,127 +1,127 @@
-$public-fahrplan-body-padding: .7rem;
+$public-fahrplan-body-padding: 0.7rem;
 
 .hub-fahrplan {
-    display: flex;
-    overflow: auto;
-    z-index: 5;
-    font-size: 0.9em;
-    max-height: 75vh;
-    position: relative;
-
-    &__timeline-title {
-        height: 50px;
-        display: block;
-        font-weight: 400;
-        margin: 0;
-        padding: 0 0 15px 0;
-        border: none;
-    }
-
-    &__timeline {
-        position: sticky;
-        left: 0;
-        z-index: 20;
-
-        > figure {
-            position: relative;
-        }
-    }
-
-    &__room {
-        z-index: 10;
-        min-width: 14rem;
-        max-width: 18rem;
-        position: relative;
-    }
-
-    &__room-event {
-        overflow-y: auto;
-
-        p {
-          margin-bottom: map-get($spacers, 2);
-        }
-    }
-
-    &__event_title {
-        background: $primary;
-        color: $light;
-        padding: map-get($spacers, 1);
-        text-transform: none;
-    }
-
-    &__room-space {
-        visibility: hidden;
-        padding: 0;
-        margin: 0;
-    }
-
-    &__modal-title {
-        text-transform: none;
+  display: flex;
+  overflow: auto;
+  z-index: 5;
+  font-size: 0.9em;
+  max-height: 75vh;
+  position: relative;
+
+  &__timeline-title {
+    height: 50px;
+    display: block;
+    font-weight: 400;
+    margin: 0;
+    padding: 0 0 15px 0;
+    border: none;
+  }
+
+  &__timeline {
+    position: sticky;
+    left: 0;
+    z-index: 20;
+
+    > figure {
+      position: relative;
     }
+  }
 
-    &__modal-content {
-        max-height: 90vh;
-        overflow: hidden;
-        background-color: rgba(0, 0, 0, 0.95);
-    }
-
-    &__modal-body {
-        max-height: 100%;
-        overflow-x: auto;
-    }
+  &__room {
+    z-index: 10;
+    min-width: 14rem;
+    max-width: 18rem;
+    position: relative;
+  }
 
-    &__modal-data {
-        display: grid;
-        grid: auto / 1fr 5fr;
-    }
+  &__room-event {
+    overflow-y: auto;
 
-    &__modal-close * {
-        pointer-events: none;
+    p {
+      margin-bottom: map-get($spacers, 2);
     }
+  }
+
+  &__event_title {
+    background: $primary;
+    color: $light;
+    padding: map-get($spacers, 1);
+    text-transform: none;
+  }
+
+  &__room-space {
+    visibility: hidden;
+    padding: 0;
+    margin: 0;
+  }
+
+  &__modal-title {
+    text-transform: none;
+  }
+
+  &__modal-content {
+    max-height: 90vh;
+    overflow: hidden;
+    background-color: rgba(0, 0, 0, 0.95);
+  }
+
+  &__modal-body {
+    max-height: 100%;
+    overflow-x: auto;
+  }
 
-    &__filter-block {
-        .btn-transparent {
-            &:hover,
-            &.active {
-                background-color: $primary;
-                color: $dark;
-            }
-        }
+  &__modal-data {
+    display: grid;
+    grid: auto / 1fr 5fr;
+  }
+
+  &__modal-close * {
+    pointer-events: none;
+  }
+
+  &__filter-block {
+    .btn-transparent {
+      &:hover,
+      &.active {
+        background-color: $primary;
+        color: $dark;
+      }
     }
+  }
 }
 
 .hub-fahrplan__pub-body {
-    overflow: hidden !important;
-    height: 100vh;
-    width: 100vw;
-    padding: $public-fahrplan-body-padding;
-
-    footer .nav-link {
-        padding: 0.25rem 0.5rem;
-    }
+  overflow: hidden !important;
+  height: 100vh;
+  width: 100vw;
+  padding: $public-fahrplan-body-padding;
+
+  footer .nav-link {
+    padding: 0.25rem 0.5rem;
+  }
 }
 
 .hub-fahrplan__pub-body .hub-fahrplan {
-    overflow: visible;
-    max-height: none;
+  overflow: visible;
+  max-height: none;
 }
 
 .hub-fahrplan__pub-content {
-    display: grid;
-    grid: 1fr auto 2fr / auto;
-    height: 100%;
-    width: 100%;
-
-    > .h2 {
-        margin-bottom: $public-fahrplan-body-padding;
-    }
-
-    > footer {
-        margin: $public-fahrplan-body-padding 0 0;
-    }
+  display: grid;
+  grid: 1fr auto 2fr / auto;
+  height: 100%;
+  width: 100%;
+
+  > .h2 {
+    margin-bottom: $public-fahrplan-body-padding;
+  }
+
+  > footer {
+    margin: $public-fahrplan-body-padding 0 0;
+  }
 }
 
 .hub-fahrplan__pub-box {
-    max-height: 100%;
-    overflow: scroll;
+  max-height: 100%;
+  overflow: scroll;
 }
diff --git a/src/plainui/styles/components/_header.scss b/src/plainui/styles/components/_header.scss
index 8fa173e20..634e930cb 100644
--- a/src/plainui/styles/components/_header.scss
+++ b/src/plainui/styles/components/_header.scss
@@ -1,13 +1,12 @@
 .hub-header {
-    &__badge {
-        font-family: $font-family-base;
-        bottom: .5rem;
-        font-size: .66rem;
-        position: relative;
-        background-color: $secondary;
-        padding: 0.25em 0.35em;
-    }
-
+  &__badge {
+    font-family: $font-family-base;
+    bottom: 0.5rem;
+    font-size: 0.66rem;
+    position: relative;
+    background-color: $secondary;
+    padding: 0.25em 0.35em;
+  }
 }
 
 .hub-search {
@@ -15,46 +14,46 @@
 }
 
 .hub-top-nav {
-    align-items: center;
-    display: none;
-    gap: 1rem;
-    margin-bottom: 2rem;
+  align-items: center;
+  display: none;
+  gap: 1rem;
+  margin-bottom: 2rem;
 }
 
 @include media-breakpoint-up(md) {
-    .hub-top-nav {
-        display: flex;
-    }
+  .hub-top-nav {
+    display: flex;
+  }
 }
 
 .hub-top-nav--breadcrumbs {
-    margin-bottom: .75rem;
+  margin-bottom: 0.75rem;
 }
 
 .hub-head-page {
-    flex: 1;
-    margin-bottom: 0;
+  flex: 1;
+  margin-bottom: 0;
 }
 
 .hub-top-nav__buttons {
-    align-items: center;
-    display: flex;
+  align-items: center;
+  display: flex;
 }
 
 .hub-top-nav__button {
-    align-items: center;
-    background: transparent;
-    color: $signal-secondary-border;
-    border: 0;
-    display: flex;
-    position: relative;
-    text-decoration: none;
+  align-items: center;
+  background: transparent;
+  color: $signal-secondary-border;
+  border: 0;
+  display: flex;
+  position: relative;
+  text-decoration: none;
 }
 
 .hub-top-nav__button-icon {
-    font-size: 1.5625rem;
+  font-size: 1.5625rem;
 }
 
 .hub-breadcrumbs {
-    margin-bottom: 1.5rem;
+  margin-bottom: 1.5rem;
 }
diff --git a/src/plainui/styles/components/_image.scss b/src/plainui/styles/components/_image.scss
index ece235379..b206fb6fb 100644
--- a/src/plainui/styles/components/_image.scss
+++ b/src/plainui/styles/components/_image.scss
@@ -1,28 +1,28 @@
 .hub-image {
-    &--cropped {
-        position: relative;
-        display: block;
-        padding-bottom: 56.25%;
-        height: 0;
-        overflow: hidden;
+  &--cropped {
+    position: relative;
+    display: block;
+    padding-bottom: 56.25%;
+    height: 0;
+    overflow: hidden;
 
-        .hub-image__img {
-            display: block;
-            position: absolute;
-            top: 50%;
-            left: 50%;
-            transform: translate(-50%, -50%);
-            width: 100%;
-            height: 100%;
-            object-fit: cover;
-        }
+    .hub-image__img {
+      display: block;
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+    }
 
-        .hub-image__img-caption {
-            display: block;
-            position: absolute;
-            bottom: 0;
-            left: 0;
-            width: 100%;
-        }
+    .hub-image__img-caption {
+      display: block;
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      width: 100%;
     }
+  }
 }
diff --git a/src/plainui/styles/components/_landingpage.scss b/src/plainui/styles/components/_landingpage.scss
index 272fcb3a5..8aa1dceb7 100644
--- a/src/plainui/styles/components/_landingpage.scss
+++ b/src/plainui/styles/components/_landingpage.scss
@@ -1,48 +1,48 @@
 .hub-landing {
-    position: relative;
-    overflow: hidden;
-    min-height: calc(100vh - 72px);
-    max-width: 51.875rem;
-    margin: 0 auto;
-    display: flex;
-    flex-flow: column nowrap;
-    justify-content: center;
-    align-items: center;
-    padding: 1rem;
+  position: relative;
+  overflow: hidden;
+  min-height: calc(100vh - 72px);
+  max-width: 51.875rem;
+  margin: 0 auto;
+  display: flex;
+  flex-flow: column nowrap;
+  justify-content: center;
+  align-items: center;
+  padding: 1rem;
 
-    &__logo {
-        .hub-logo {
-            max-width: none;
+  &__logo {
+    .hub-logo {
+      max-width: none;
 
-            img {
-                width: 12rem;
-            }
-        }
+      img {
+        width: 12rem;
+      }
     }
+  }
 
-    &__content {
-        position: absolute;
-        top: map-get($spacers, 10);
-        left: 50%;
-        width: 100%;
-        text-align: center;
-        padding: $spacer;
-        z-index: 6;
-        transform: translate(-50%, 0);
-    }
+  &__content {
+    position: absolute;
+    top: map-get($spacers, 10);
+    left: 50%;
+    width: 100%;
+    text-align: center;
+    padding: $spacer;
+    z-index: 6;
+    transform: translate(-50%, 0);
+  }
 
-    &__title {
-        font-size: 3.5rem;
-    }
+  &__title {
+    font-size: 3.5rem;
+  }
 
-    @include media-breakpoint-up('md') {
-        width: 90%;
-        &__title {
-            font-size: 7rem;
-        }
+  @include media-breakpoint-up("md") {
+    width: 90%;
+    &__title {
+      font-size: 7rem;
     }
+  }
 
-    @include media-breakpoint-up('xxl') {
-        max-width: 59.188rem;
-    }
+  @include media-breakpoint-up("xxl") {
+    max-width: 59.188rem;
+  }
 }
diff --git a/src/plainui/styles/components/_logo.scss b/src/plainui/styles/components/_logo.scss
index de2333b08..0860b9de0 100644
--- a/src/plainui/styles/components/_logo.scss
+++ b/src/plainui/styles/components/_logo.scss
@@ -1,7 +1,7 @@
 .hub-logo {
-    display: inline-block;
+  display: inline-block;
 
-    svg {
-        height: 100%;
-    }
+  svg {
+    height: 100%;
+  }
 }
diff --git a/src/plainui/styles/components/_markdown.scss b/src/plainui/styles/components/_markdown.scss
index 626f9c1f0..018979c5e 100644
--- a/src/plainui/styles/components/_markdown.scss
+++ b/src/plainui/styles/components/_markdown.scss
@@ -1,70 +1,70 @@
 .hub-markdown {
-    overflow-x: auto;
-    -webkit-overflow-scrolling: touch;
+  overflow-x: auto;
+  -webkit-overflow-scrolling: touch;
 
-    p,
-    ul,
-    ol,
-    dl,
-    table {
-        font-family: $font-family-sans-serif;
-        margin-bottom: $spacer;
+  p,
+  ul,
+  ol,
+  dl,
+  table {
+    font-family: $font-family-sans-serif;
+    margin-bottom: $spacer;
 
-        &:last-child {
-            margin-bottom: 0;
-        }
+    &:last-child {
+      margin-bottom: 0;
     }
+  }
 
-    h1,
-    h2,
-    h3,
-    h4,
-    h5,
-    h6 {
-        font-family: $font-family-sans-serif;
-        margin-bottom: $spacer / 2;
+  h1,
+  h2,
+  h3,
+  h4,
+  h5,
+  h6 {
+    font-family: $font-family-sans-serif;
+    margin-bottom: $spacer / 2;
 
-        &:last-child {
-            margin-bottom: 0;
-        }
+    &:last-child {
+      margin-bottom: 0;
     }
+  }
 
-    h1 {
-        font-size: 2rem;
-    }
+  h1 {
+    font-size: 2rem;
+  }
 
-    hr {
-        border-width: 1px;
-        margin: map-get($spacers, 4) 0;
-    }
+  hr {
+    border-width: 1px;
+    margin: map-get($spacers, 4) 0;
+  }
 
-    table {
-        border-collapse: collapse;
-        border-spacing: $spacer * 0.5;
-    }
+  table {
+    border-collapse: collapse;
+    border-spacing: $spacer * 0.5;
+  }
 
-    th,
-    td {
-        padding: ($spacer * 0.5) $spacer;
-    }
+  th,
+  td {
+    padding: ($spacer * 0.5) $spacer;
+  }
 
-    th {
-        background: $primary;
-        font-family: $headings-font-family;
-        font-weight: bold;
-        color: $black;
-    }
+  th {
+    background: $primary;
+    font-family: $headings-font-family;
+    font-weight: bold;
+    color: $black;
+  }
 
-    thead,
-    td {
-      border: 1px solid $gray-500;
-    }
+  thead,
+  td {
+    border: 1px solid $gray-500;
+  }
 
-    a.userprofile {
-        text-decoration: none;
+  a.userprofile {
+    text-decoration: none;
 
-        &::before {
-            content: "@";
-        }
+    &::before {
+      content: "@";
     }
+  }
 }
diff --git a/src/plainui/styles/components/_player.scss b/src/plainui/styles/components/_player.scss
index 1d5a5330b..fb4f772fb 100644
--- a/src/plainui/styles/components/_player.scss
+++ b/src/plainui/styles/components/_player.scss
@@ -1,6 +1,6 @@
 .hub_voc_player > [data-player] {
-    padding-bottom: 56.25%;
-    height: auto !important;
+  padding-bottom: 56.25%;
+  height: auto !important;
 }
 .hub_voc_player > .fullscreen[data-player] {
   padding-bottom: 0;
diff --git a/src/plainui/styles/components/_slider.scss b/src/plainui/styles/components/_slider.scss
index e0f33616d..625fda583 100644
--- a/src/plainui/styles/components/_slider.scss
+++ b/src/plainui/styles/components/_slider.scss
@@ -1,13 +1,13 @@
 .hub-slider {
-    &__container {
-        overflow-x: auto;
-        overflow-y: hidden;
-        -webkit-overflow-scrolling: touch;
-        scroll-snap-type: y mandatory;
-        scroll-padding: map-get($spacers, 2);
-    }
+  &__container {
+    overflow-x: auto;
+    overflow-y: hidden;
+    -webkit-overflow-scrolling: touch;
+    scroll-snap-type: y mandatory;
+    scroll-padding: map-get($spacers, 2);
+  }
 
-    &__item {
-        scroll-snap-align: start;
-    }
+  &__item {
+    scroll-snap-align: start;
+  }
 }
diff --git a/src/plainui/styles/components/_static-pages.scss b/src/plainui/styles/components/_static-pages.scss
index 42bf0d1f9..eb4db7822 100644
--- a/src/plainui/styles/components/_static-pages.scss
+++ b/src/plainui/styles/components/_static-pages.scss
@@ -1,5 +1,5 @@
 .staticpage {
-  input[type=radio] {
+  input[type="radio"] {
     margin: 0.2rem;
   }
 
@@ -13,7 +13,7 @@
 }
 
 table.diff {
-  background: rgba(26, 25, 25, .9);
+  background: rgba(26, 25, 25, 0.9);
   color: $white;
   td:nth-child(3) {
     width: 50%;
@@ -27,7 +27,7 @@ table.diff {
   background-color: $black;
   color: $white;
   min-width: 1rem;
-  text-align:right
+  text-align: right;
 }
 
 .diff_next {
@@ -37,22 +37,22 @@ table.diff {
 }
 
 .diff_add {
-  background-color:$green;
+  background-color: $green;
   color: $black;
 }
 
 .diff_chg {
-  background-color:$yellow;
+  background-color: $yellow;
 }
 
 .diff_sub {
-  background-color:$red;
+  background-color: $red;
 }
 
 .diff_content {
   overflow-wrap: break-word;
   word-break: break-all;
-  width: 50%!important;
+  width: 50% !important;
   padding-left: 0.5rem;
 }
 
diff --git a/src/plainui/styles/components/_syntaxhilite.scss b/src/plainui/styles/components/_syntaxhilite.scss
index 5b72af63f..0cc265750 100644
--- a/src/plainui/styles/components/_syntaxhilite.scss
+++ b/src/plainui/styles/components/_syntaxhilite.scss
@@ -1,75 +1,240 @@
-pre { line-height: 125%; margin: 0; }
-td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }
-span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }
-td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
-span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
-.codehilite .hll { background-color: #49483e }
-.codehilite  { background: #272822; color: #f8f8f2 }
-.codehilite .c { color: #75715e } /* Comment */
-.codehilite .err { color: #960050; background-color: #1e0010 } /* Error */
-.codehilite .k { color: #66d9ef } /* Keyword */
-.codehilite .l { color: #ae81ff } /* Literal */
-.codehilite .n { color: #f8f8f2 } /* Name */
-.codehilite .o { color: #f92672 } /* Operator */
-.codehilite .p { color: #f8f8f2 } /* Punctuation */
-.codehilite .ch { color: #75715e } /* Comment.Hashbang */
-.codehilite .cm { color: #75715e } /* Comment.Multiline */
-.codehilite .cp { color: #75715e } /* Comment.Preproc */
-.codehilite .cpf { color: #75715e } /* Comment.PreprocFile */
-.codehilite .c1 { color: #75715e } /* Comment.Single */
-.codehilite .cs { color: #75715e } /* Comment.Special */
-.codehilite .gd { color: #f92672 } /* Generic.Deleted */
-.codehilite .ge { font-style: italic } /* Generic.Emph */
-.codehilite .gi { color: #a6e22e } /* Generic.Inserted */
-.codehilite .gs { font-weight: bold } /* Generic.Strong */
-.codehilite .gu { color: #75715e } /* Generic.Subheading */
-.codehilite .kc { color: #66d9ef } /* Keyword.Constant */
-.codehilite .kd { color: #66d9ef } /* Keyword.Declaration */
-.codehilite .kn { color: #f92672 } /* Keyword.Namespace */
-.codehilite .kp { color: #66d9ef } /* Keyword.Pseudo */
-.codehilite .kr { color: #66d9ef } /* Keyword.Reserved */
-.codehilite .kt { color: #66d9ef } /* Keyword.Type */
-.codehilite .ld { color: #e6db74 } /* Literal.Date */
-.codehilite .m { color: #ae81ff } /* Literal.Number */
-.codehilite .s { color: #e6db74 } /* Literal.String */
-.codehilite .na { color: #a6e22e } /* Name.Attribute */
-.codehilite .nb { color: #f8f8f2 } /* Name.Builtin */
-.codehilite .nc { color: #a6e22e } /* Name.Class */
-.codehilite .no { color: #66d9ef } /* Name.Constant */
-.codehilite .nd { color: #a6e22e } /* Name.Decorator */
-.codehilite .ni { color: #f8f8f2 } /* Name.Entity */
-.codehilite .ne { color: #a6e22e } /* Name.Exception */
-.codehilite .nf { color: #a6e22e } /* Name.Function */
-.codehilite .nl { color: #f8f8f2 } /* Name.Label */
-.codehilite .nn { color: #f8f8f2 } /* Name.Namespace */
-.codehilite .nx { color: #a6e22e } /* Name.Other */
-.codehilite .py { color: #f8f8f2 } /* Name.Property */
-.codehilite .nt { color: #f92672 } /* Name.Tag */
-.codehilite .nv { color: #f8f8f2 } /* Name.Variable */
-.codehilite .ow { color: #f92672 } /* Operator.Word */
-.codehilite .w { color: #f8f8f2 } /* Text.Whitespace */
-.codehilite .mb { color: #ae81ff } /* Literal.Number.Bin */
-.codehilite .mf { color: #ae81ff } /* Literal.Number.Float */
-.codehilite .mh { color: #ae81ff } /* Literal.Number.Hex */
-.codehilite .mi { color: #ae81ff } /* Literal.Number.Integer */
-.codehilite .mo { color: #ae81ff } /* Literal.Number.Oct */
-.codehilite .sa { color: #e6db74 } /* Literal.String.Affix */
-.codehilite .sb { color: #e6db74 } /* Literal.String.Backtick */
-.codehilite .sc { color: #e6db74 } /* Literal.String.Char */
-.codehilite .dl { color: #e6db74 } /* Literal.String.Delimiter */
-.codehilite .sd { color: #e6db74 } /* Literal.String.Doc */
-.codehilite .s2 { color: #e6db74 } /* Literal.String.Double */
-.codehilite .se { color: #ae81ff } /* Literal.String.Escape */
-.codehilite .sh { color: #e6db74 } /* Literal.String.Heredoc */
-.codehilite .si { color: #e6db74 } /* Literal.String.Interpol */
-.codehilite .sx { color: #e6db74 } /* Literal.String.Other */
-.codehilite .sr { color: #e6db74 } /* Literal.String.Regex */
-.codehilite .s1 { color: #e6db74 } /* Literal.String.Single */
-.codehilite .ss { color: #e6db74 } /* Literal.String.Symbol */
-.codehilite .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
-.codehilite .fm { color: #a6e22e } /* Name.Function.Magic */
-.codehilite .vc { color: #f8f8f2 } /* Name.Variable.Class */
-.codehilite .vg { color: #f8f8f2 } /* Name.Variable.Global */
-.codehilite .vi { color: #f8f8f2 } /* Name.Variable.Instance */
-.codehilite .vm { color: #f8f8f2 } /* Name.Variable.Magic */
-.codehilite .il { color: #ae81ff } /* Literal.Number.Integer.Long */
+pre {
+  line-height: 125%;
+  margin: 0;
+}
+td.linenos pre {
+  color: #000000;
+  background-color: #f0f0f0;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+span.linenos {
+  color: #000000;
+  background-color: #f0f0f0;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+td.linenos pre.special {
+  color: #000000;
+  background-color: #ffffc0;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+span.linenos.special {
+  color: #000000;
+  background-color: #ffffc0;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+.codehilite .hll {
+  background-color: #49483e;
+}
+.codehilite {
+  background: #272822;
+  color: #f8f8f2;
+}
+.codehilite .c {
+  color: #75715e;
+} /* Comment */
+.codehilite .err {
+  color: #960050;
+  background-color: #1e0010;
+} /* Error */
+.codehilite .k {
+  color: #66d9ef;
+} /* Keyword */
+.codehilite .l {
+  color: #ae81ff;
+} /* Literal */
+.codehilite .n {
+  color: #f8f8f2;
+} /* Name */
+.codehilite .o {
+  color: #f92672;
+} /* Operator */
+.codehilite .p {
+  color: #f8f8f2;
+} /* Punctuation */
+.codehilite .ch {
+  color: #75715e;
+} /* Comment.Hashbang */
+.codehilite .cm {
+  color: #75715e;
+} /* Comment.Multiline */
+.codehilite .cp {
+  color: #75715e;
+} /* Comment.Preproc */
+.codehilite .cpf {
+  color: #75715e;
+} /* Comment.PreprocFile */
+.codehilite .c1 {
+  color: #75715e;
+} /* Comment.Single */
+.codehilite .cs {
+  color: #75715e;
+} /* Comment.Special */
+.codehilite .gd {
+  color: #f92672;
+} /* Generic.Deleted */
+.codehilite .ge {
+  font-style: italic;
+} /* Generic.Emph */
+.codehilite .gi {
+  color: #a6e22e;
+} /* Generic.Inserted */
+.codehilite .gs {
+  font-weight: bold;
+} /* Generic.Strong */
+.codehilite .gu {
+  color: #75715e;
+} /* Generic.Subheading */
+.codehilite .kc {
+  color: #66d9ef;
+} /* Keyword.Constant */
+.codehilite .kd {
+  color: #66d9ef;
+} /* Keyword.Declaration */
+.codehilite .kn {
+  color: #f92672;
+} /* Keyword.Namespace */
+.codehilite .kp {
+  color: #66d9ef;
+} /* Keyword.Pseudo */
+.codehilite .kr {
+  color: #66d9ef;
+} /* Keyword.Reserved */
+.codehilite .kt {
+  color: #66d9ef;
+} /* Keyword.Type */
+.codehilite .ld {
+  color: #e6db74;
+} /* Literal.Date */
+.codehilite .m {
+  color: #ae81ff;
+} /* Literal.Number */
+.codehilite .s {
+  color: #e6db74;
+} /* Literal.String */
+.codehilite .na {
+  color: #a6e22e;
+} /* Name.Attribute */
+.codehilite .nb {
+  color: #f8f8f2;
+} /* Name.Builtin */
+.codehilite .nc {
+  color: #a6e22e;
+} /* Name.Class */
+.codehilite .no {
+  color: #66d9ef;
+} /* Name.Constant */
+.codehilite .nd {
+  color: #a6e22e;
+} /* Name.Decorator */
+.codehilite .ni {
+  color: #f8f8f2;
+} /* Name.Entity */
+.codehilite .ne {
+  color: #a6e22e;
+} /* Name.Exception */
+.codehilite .nf {
+  color: #a6e22e;
+} /* Name.Function */
+.codehilite .nl {
+  color: #f8f8f2;
+} /* Name.Label */
+.codehilite .nn {
+  color: #f8f8f2;
+} /* Name.Namespace */
+.codehilite .nx {
+  color: #a6e22e;
+} /* Name.Other */
+.codehilite .py {
+  color: #f8f8f2;
+} /* Name.Property */
+.codehilite .nt {
+  color: #f92672;
+} /* Name.Tag */
+.codehilite .nv {
+  color: #f8f8f2;
+} /* Name.Variable */
+.codehilite .ow {
+  color: #f92672;
+} /* Operator.Word */
+.codehilite .w {
+  color: #f8f8f2;
+} /* Text.Whitespace */
+.codehilite .mb {
+  color: #ae81ff;
+} /* Literal.Number.Bin */
+.codehilite .mf {
+  color: #ae81ff;
+} /* Literal.Number.Float */
+.codehilite .mh {
+  color: #ae81ff;
+} /* Literal.Number.Hex */
+.codehilite .mi {
+  color: #ae81ff;
+} /* Literal.Number.Integer */
+.codehilite .mo {
+  color: #ae81ff;
+} /* Literal.Number.Oct */
+.codehilite .sa {
+  color: #e6db74;
+} /* Literal.String.Affix */
+.codehilite .sb {
+  color: #e6db74;
+} /* Literal.String.Backtick */
+.codehilite .sc {
+  color: #e6db74;
+} /* Literal.String.Char */
+.codehilite .dl {
+  color: #e6db74;
+} /* Literal.String.Delimiter */
+.codehilite .sd {
+  color: #e6db74;
+} /* Literal.String.Doc */
+.codehilite .s2 {
+  color: #e6db74;
+} /* Literal.String.Double */
+.codehilite .se {
+  color: #ae81ff;
+} /* Literal.String.Escape */
+.codehilite .sh {
+  color: #e6db74;
+} /* Literal.String.Heredoc */
+.codehilite .si {
+  color: #e6db74;
+} /* Literal.String.Interpol */
+.codehilite .sx {
+  color: #e6db74;
+} /* Literal.String.Other */
+.codehilite .sr {
+  color: #e6db74;
+} /* Literal.String.Regex */
+.codehilite .s1 {
+  color: #e6db74;
+} /* Literal.String.Single */
+.codehilite .ss {
+  color: #e6db74;
+} /* Literal.String.Symbol */
+.codehilite .bp {
+  color: #f8f8f2;
+} /* Name.Builtin.Pseudo */
+.codehilite .fm {
+  color: #a6e22e;
+} /* Name.Function.Magic */
+.codehilite .vc {
+  color: #f8f8f2;
+} /* Name.Variable.Class */
+.codehilite .vg {
+  color: #f8f8f2;
+} /* Name.Variable.Global */
+.codehilite .vi {
+  color: #f8f8f2;
+} /* Name.Variable.Instance */
+.codehilite .vm {
+  color: #f8f8f2;
+} /* Name.Variable.Magic */
+.codehilite .il {
+  color: #ae81ff;
+} /* Literal.Number.Integer.Long */
diff --git a/src/plainui/styles/components/_tags.scss b/src/plainui/styles/components/_tags.scss
index e6f5fb4e8..aeaf501d9 100644
--- a/src/plainui/styles/components/_tags.scss
+++ b/src/plainui/styles/components/_tags.scss
@@ -1,26 +1,26 @@
 .hub-tags {
-    align-items: center;
-    display: flex;
-    flex-wrap: wrap;
-    gap: map-get($spacers, 2);
-    /* to prevent overflow */
-    min-width: 0;
+  align-items: center;
+  display: flex;
+  flex-wrap: wrap;
+  gap: map-get($spacers, 2);
+  /* to prevent overflow */
+  min-width: 0;
 }
 
 .hub-tag {
-    background-color: var(--bs-tertiary-bg);
-    border-radius: var(--bs-border-radius) 0;
-    border: none;
-    color: var(--bs-white);
-    display: inline-flex;
-    gap: map-get($spacers, 1);
-    /* required for overflow texts */
-    min-width: 0;
-    overflow: hidden;
-    padding: 3px 5px 2px;
-    text-overflow: ellipsis;
-    text-transform: uppercase;
-    white-space: nowrap;
+  background-color: var(--bs-tertiary-bg);
+  border-radius: var(--bs-border-radius) 0;
+  border: none;
+  color: var(--bs-white);
+  display: inline-flex;
+  gap: map-get($spacers, 1);
+  /* required for overflow texts */
+  min-width: 0;
+  overflow: hidden;
+  padding: 3px 5px 2px;
+  text-overflow: ellipsis;
+  text-transform: uppercase;
+  white-space: nowrap;
 }
 
 .hub-tag--clear {
@@ -34,58 +34,58 @@
 }
 
 .hub-tag--outline {
-    background-color: transparent;
-    border: 1px solid var(--bs-tertiary-bg);
-    color: var(--bs-tertiary-bg);
+  background-color: transparent;
+  border: 1px solid var(--bs-tertiary-bg);
+  color: var(--bs-tertiary-bg);
 }
 
 .hub-tag--outline-danger {
-    background-color: transparent;
-    border: 1px solid $signal-danger-fill;
-    color: $signal-danger-text
+  background-color: transparent;
+  border: 1px solid $signal-danger-fill;
+  color: $signal-danger-text;
 }
 
 .hub-tag--secondary {
-    background-color: $signal-secondary-bg;
-    border: none;
-    color: var(--bs-white);
+  background-color: $signal-secondary-bg;
+  border: none;
+  color: var(--bs-white);
 }
 
 .hub-tag--success {
-    background-color: $signal-success-fill;
-    color: var(--bs-black);
+  background-color: $signal-success-fill;
+  color: var(--bs-black);
 }
 
 .hub-tag--danger {
-    background-color: $signal-danger-fill;
-    color: var(--bs-white);
+  background-color: $signal-danger-fill;
+  color: var(--bs-white);
 }
 
 .hub-tag--outline-danger {
-    background-color: transparent;
-    border: 1px solid $signal-danger-fill;
-    color: $signal-danger-text
+  background-color: transparent;
+  border: 1px solid $signal-danger-fill;
+  color: $signal-danger-text;
 }
 
 .hub-tag--disabled {
-    background-color: var(--bs-dark);
-    color: $signal-muted-text-dark;
+  background-color: var(--bs-dark);
+  color: $signal-muted-text-dark;
 }
 
 .hub-tag--user {
-    background-color: $secondary;
-    border-radius: 0;
-    color: $signal-invert-text;
+  background-color: $secondary;
+  border-radius: 0;
+  color: $signal-invert-text;
 }
 
 .hub-tag--secondary-outline {
-    background-color: transparent;
-    border: 1px solid $signal-secondary-border;
-    color: $signal-secondary-text;
+  background-color: transparent;
+  border: 1px solid $signal-secondary-border;
+  color: $signal-secondary-text;
 }
 
 a.hub-tag:hover {
-    text-decoration: none;
+  text-decoration: none;
 }
 
 .hub-tag__text {
@@ -98,4 +98,3 @@ a.hub-tag:hover {
   height: 1rem;
   width: 2px;
 }
-
diff --git a/src/plainui/styles/components/_tile-board.scss b/src/plainui/styles/components/_tile-board.scss
index f66408949..3c4072dc9 100644
--- a/src/plainui/styles/components/_tile-board.scss
+++ b/src/plainui/styles/components/_tile-board.scss
@@ -1,29 +1,29 @@
 .hub-tile-board {
-    &__body {
-        overflow: hidden;
-        max-height: 6.25rem;
-    }
+  &__body {
+    overflow: hidden;
+    max-height: 6.25rem;
+  }
 
-    &__footer {
-        position: relative;
-    }
+  &__footer {
+    position: relative;
+  }
 
-    &__btn {
-        position: absolute;
-        left: 50%;
-        transform: translate(-50%);
-        display: block;
-        padding: 0 map-get($spacers, 2);
+  &__btn {
+    position: absolute;
+    left: 50%;
+    transform: translate(-50%);
+    display: block;
+    padding: 0 map-get($spacers, 2);
 
-        &:hover:not(:focus) {
-            .hub-tile-board__btn-arrow {
-                transform: translate(0, 3px);
-            }
-        }
+    &:hover:not(:focus) {
+      .hub-tile-board__btn-arrow {
+        transform: translate(0, 3px);
+      }
+    }
 
-        &:focus,
-        &.focus {
-            box-shadow: $btn-focus-box-shadow;
-        }
+    &:focus,
+    &.focus {
+      box-shadow: $btn-focus-box-shadow;
     }
+  }
 }
diff --git a/src/plainui/styles/components/_tile-message.scss b/src/plainui/styles/components/_tile-message.scss
index 45d421264..496be8830 100644
--- a/src/plainui/styles/components/_tile-message.scss
+++ b/src/plainui/styles/components/_tile-message.scss
@@ -1,40 +1,40 @@
 .hub-tile-message {
-    &__icon-col {
-        width: 9.375rem;
-        flex: 0 0 9.375rem;
-    }
+  &__icon-col {
+    width: 9.375rem;
+    flex: 0 0 9.375rem;
+  }
 
-    &__icon-container {
-        position: relative;
-        width: 100%;
-        height: 100%;
-        display: flex;
-        flex-flow: column nowrap;
-        align-items: center;
-        justify-content: center;
+  &__icon-container {
+    position: relative;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-flow: column nowrap;
+    align-items: center;
+    justify-content: center;
 
-        margin-bottom: 0;
-        text-decoration: none;
-    }
+    margin-bottom: 0;
+    text-decoration: none;
+  }
 
-    &__icon {
-        &-flag {
-            margin-left: 2.5rem;
-        }
+  &__icon {
+    &-flag {
+      margin-left: 2.5rem;
     }
+  }
 
-    @include media-breakpoint-down('md') {
-        &__icon-col {
-            width: 5rem;
-            flex: 0 0 5rem;
-        }
+  @include media-breakpoint-down("md") {
+    &__icon-col {
+      width: 5rem;
+      flex: 0 0 5rem;
+    }
 
-        &__icon {
-            max-width: 2.5rem;
+    &__icon {
+      max-width: 2.5rem;
 
-            &-flag {
-                margin-left: 1.25rem;
-            }
-        }
+      &-flag {
+        margin-left: 1.25rem;
+      }
     }
+  }
 }
diff --git a/src/plainui/styles/design/_variables.scss b/src/plainui/styles/design/_variables.scss
index f10047172..f584dcff9 100644
--- a/src/plainui/styles/design/_variables.scss
+++ b/src/plainui/styles/design/_variables.scss
@@ -1,6 +1,6 @@
 /* Variables exported from design */
 
- /* Variables  */
+/* Variables  */
 $text-body-dark: rgba(255, 255, 255, 0.85);
 $text-body-lite: rgba(33, 37, 41, 1);
 $bg-body-dark: rgba(0, 0, 0, 1);
@@ -89,5 +89,5 @@ $signal-tertiary-border-lite: rgba(255, 255, 255, 1);
 $signal-tertiary-text-dark: rgba(222, 55, 255, 1);
 $signal-tertiary-text-lite: rgba(255, 255, 255, 1);
 
- /* Aliases  */
+/* Aliases  */
 $signal-primary-fill-lite: $ccc-orange-desktop;
diff --git a/src/plainui/styles/hub.scss b/src/plainui/styles/hub.scss
index d2265cbb2..577621cb6 100644
--- a/src/plainui/styles/hub.scss
+++ b/src/plainui/styles/hub.scss
@@ -36,14 +36,16 @@ body {
   word-wrap: break-word;
 }
 
-* {-webkit-font-smoothing: antialiased;}
+* {
+  -webkit-font-smoothing: antialiased;
+}
 
 .mw-320 {
-    max-width: 20rem;
+  max-width: 20rem;
 }
 
 .w-100px {
-    width: 6.25rem;
+  width: 6.25rem;
 }
 
 .custom-popover {
@@ -53,18 +55,18 @@ body {
 }
 
 .hub-content {
-    padding: map-get($spacers, 2) map-get($spacers, 3);
-    padding-top: $hub-mobile-navbar-height;
-    height: calc(100vh - $hub-mobile-navbar-height);
-    z-index: 100;
+  padding: map-get($spacers, 2) map-get($spacers, 3);
+  padding-top: $hub-mobile-navbar-height;
+  height: calc(100vh - $hub-mobile-navbar-height);
+  z-index: 100;
 }
 
 @include media-breakpoint-up(md) {
-    .hub-content {
-        padding: map-get($spacers, 3) map-get($spacers, 5);
-    }
+  .hub-content {
+    padding: map-get($spacers, 3) map-get($spacers, 5);
+  }
 
-    .hub-main {
-        height: 100vh;
-    }
+  .hub-main {
+    height: 100vh;
+  }
 }
diff --git a/src/plainui/styles/sections/_fahrplan.scss b/src/plainui/styles/sections/_fahrplan.scss
index 0d7cfb2c6..ee6b248ad 100644
--- a/src/plainui/styles/sections/_fahrplan.scss
+++ b/src/plainui/styles/sections/_fahrplan.scss
@@ -1,154 +1,154 @@
-$public-fahrplan-body-padding: .7rem;
+$public-fahrplan-body-padding: 0.7rem;
 
 .hub-fahrplan {
-    display: flex;
-    overflow: auto;
-    z-index: 5;
-    font-size: 0.9em;
-    max-height: 75vh;
-
-    &__title {
-        font-size: 2.1875rem; // 35px
-        text-overflow: ellipsis;
-        white-space: nowrap;
-
-        .active {
-            color: $signal-secondary-text;
-        }
-
-        .inactive {
-            color: $gray-600;
-
-            &:hover {
-                color: $primary;
-            }
-        }
-    }
-
-    &__timeline-title {
-        height: 50px;
-        display: block;
-        font-weight: 400;
-        margin: 0;
-        padding: 0 0 15px 0;
-        border: none;
-    }
+  display: flex;
+  overflow: auto;
+  z-index: 5;
+  font-size: 0.9em;
+  max-height: 75vh;
 
-    &__timeline {
-        position: sticky;
-        left: 0;
-        z-index: 20;
+  &__title {
+    font-size: 2.1875rem; // 35px
+    text-overflow: ellipsis;
+    white-space: nowrap;
 
-        >figure {
-            position: relative;
-        }
+    .active {
+      color: $signal-secondary-text;
     }
 
-    &__room {
-        z-index: 10;
-        min-width: 14rem;
-        position: relative;
-    }
+    .inactive {
+      color: $gray-600;
 
-    &__room-event {
-        border-style: solid;
-        border-width: 1px;
+      &:hover {
         color: $primary;
-        font-size: 0.875rem;
-        overflow-y: auto;
-    }
-
-    &__event-body {
-      padding: map-get($spacers, 1);
-    }
-
-    &__event_title {
-        text-transform: none;
-    }
-
-    &__room-space {
-        visibility: hidden;
-        padding: 0;
-        margin: 0;
-    }
-
-    &__modal-title {
-        text-transform: none;
-    }
-
-    &__modal-content {
-        max-height: 90vh;
-        overflow: hidden;
-        background-color: rgba(0, 0, 0, 0.95);
-    }
-
-    &__modal-body {
-        max-height: 100%;
-        overflow-x: auto;
-    }
-
-    &__modal-data {
-        display: grid;
-        grid: auto / 1fr 5fr;
-    }
-
-    &__modal-close * {
-        pointer-events: none;
-    }
+      }
+    }
+  }
+
+  &__timeline-title {
+    height: 50px;
+    display: block;
+    font-weight: 400;
+    margin: 0;
+    padding: 0 0 15px 0;
+    border: none;
+  }
+
+  &__timeline {
+    position: sticky;
+    left: 0;
+    z-index: 20;
+
+    > figure {
+      position: relative;
+    }
+  }
+
+  &__room {
+    z-index: 10;
+    min-width: 14rem;
+    position: relative;
+  }
+
+  &__room-event {
+    border-style: solid;
+    border-width: 1px;
+    color: $primary;
+    font-size: 0.875rem;
+    overflow-y: auto;
+  }
+
+  &__event-body {
+    padding: map-get($spacers, 1);
+  }
+
+  &__event_title {
+    text-transform: none;
+  }
+
+  &__room-space {
+    visibility: hidden;
+    padding: 0;
+    margin: 0;
+  }
+
+  &__modal-title {
+    text-transform: none;
+  }
+
+  &__modal-content {
+    max-height: 90vh;
+    overflow: hidden;
+    background-color: rgba(0, 0, 0, 0.95);
+  }
+
+  &__modal-body {
+    max-height: 100%;
+    overflow-x: auto;
+  }
 
-    &__filter-block {
-        .btn-transparent {
-            &:hover,
-            &.active {
-                background-color: $primary;
-                color: $dark;
-            }
-        }
-    }
+  &__modal-data {
+    display: grid;
+    grid: auto / 1fr 5fr;
+  }
+
+  &__modal-close * {
+    pointer-events: none;
+  }
+
+  &__filter-block {
+    .btn-transparent {
+      &:hover,
+      &.active {
+        background-color: $primary;
+        color: $dark;
+      }
+    }
+  }
 }
 
 .hub-fahrplan__pub-body {
-    overflow: hidden !important;
-    height: 100vh;
-    width: 100vw;
-    padding: $public-fahrplan-body-padding;
-
-    footer .nav-link {
-        padding: 0.25rem 0.5rem;
-    }
+  overflow: hidden !important;
+  height: 100vh;
+  width: 100vw;
+  padding: $public-fahrplan-body-padding;
+
+  footer .nav-link {
+    padding: 0.25rem 0.5rem;
+  }
 }
 
 .hub-fahrplan__pub-body .hub-fahrplan {
-    overflow: visible;
-    max-height: none;
+  overflow: visible;
+  max-height: none;
 }
 
 .hub-fahrplan__pub-content {
-    display: grid;
-    grid: 1fr auto / auto;
-    height: 100%;
-    width: 100%;
-
-    > .h2 {
-        margin-bottom: $public-fahrplan-body-padding;
-    }
-
-    > footer {
-        margin: $public-fahrplan-body-padding 0 0;
-    }
+  display: grid;
+  grid: 1fr auto / auto;
+  height: 100%;
+  width: 100%;
+
+  > .h2 {
+    margin-bottom: $public-fahrplan-body-padding;
+  }
+
+  > footer {
+    margin: $public-fahrplan-body-padding 0 0;
+  }
 }
 
 .hub-fahrplan__pub-box {
-    max-height: 100%;
-    overflow: auto;
+  max-height: 100%;
+  overflow: auto;
 }
 
 .hub-fahrplan__view-toggle {
-    background: none;
-    border: 0;
-    color: var(--bs-body-color);
+  background: none;
+  border: 0;
+  color: var(--bs-body-color);
 }
 
 .hub-fahrplan__view-toggle--active {
-    color: var(--bs-tertiary-color);
+  color: var(--bs-tertiary-color);
 }
diff --git a/src/version.json b/src/version.json
index 5e5f5153a..00cb46486 100644
--- a/src/version.json
+++ b/src/version.json
@@ -1 +1 @@
-{"tag": "DEV"}
+{ "tag": "DEV" }
diff --git a/tests/README.md b/tests/README.md
index 1698dd6e0..055f7ac67 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -6,9 +6,9 @@ There are more in-depth technical tests in the individual Django apps' tests fol
 The tests are done with Python's unittest framework and the requests library.
 You may assume the following environment variables:
 
-* `BASE_URL` with protocol and hostname of the testee's location, e.g. `http://hubapp`
-* `DJANGO_CREATE_ADMIN_USERNAME` with the username of a superuser
-* `DJANGO_CREATE_ADMIN_PASSWORD` with the corresponding password
-* `SERVE_API`, `SERVE_BACKOFFICE` and `SERVE_FRONTEND` as in the Docker environment (see [hub.settings.default](/src/hub/settings/default.py))
+- `BASE_URL` with protocol and hostname of the testee's location, e.g. `http://hubapp`
+- `DJANGO_CREATE_ADMIN_USERNAME` with the username of a superuser
+- `DJANGO_CREATE_ADMIN_PASSWORD` with the corresponding password
+- `SERVE_API`, `SERVE_BACKOFFICE` and `SERVE_FRONTEND` as in the Docker environment (see [hub.settings.default](/src/hub/settings/default.py))
 
 To run all tests execute `SERVE_API=yes SERVE_BACKOFFICE=yes SERVE_FRONTEND=yes python3 -m unittest -v` (in this directory).
-- 
GitLab