Compare commits

..

2 Commits

Author SHA1 Message Date
Raphael Michel
5d87f9a26f Bump to 2025.10.1 2025-12-19 13:06:58 +01:00
Raphael Michel
4b5651862c [SECURITY] Prevent access to arbitrary cached files by UUID (CVE-2025-14881) 2025-12-19 13:06:48 +01:00
46 changed files with 494 additions and 602 deletions

View File

@@ -35,7 +35,6 @@ dependencies = [
"cryptography>=44.0.0",
"css-inline==0.18.*",
"defusedcsv>=1.1.0",
"dnspython==2.*",
"Django[argon2]==4.2.*,>=4.2.26",
"django-bootstrap3==25.2",
"django-compressor==4.5.1",
@@ -82,7 +81,7 @@ dependencies = [
"pycountry",
"pycparser==2.23",
"pycryptodome==3.23.*",
"pypdf==6.4.*",
"pypdf==6.3.*",
"python-bidi==0.6.*", # Support for Arabic in reportlab
"python-dateutil==2.9.*",
"pytz",
@@ -92,7 +91,7 @@ dependencies = [
"redis==6.4.*",
"reportlab==4.4.*",
"requests==2.32.*",
"sentry-sdk==2.46.*",
"sentry-sdk==2.45.*",
"sepaxml==2.7.*",
"stripe==7.9.*",
"text-unidecode==1.*",

View File

@@ -19,4 +19,4 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
__version__ = "2025.11.0.dev0"
__version__ = "2025.10.1"

View File

@@ -74,6 +74,11 @@ class ExportersMixin:
@action(detail=True, methods=['GET'], url_name='download', url_path='download/(?P<asyncid>[^/]+)/(?P<cfid>[^/]+)')
def download(self, *args, **kwargs):
cf = get_object_or_404(CachedFile, id=kwargs['cfid'])
if not cf.allowed_for_session(self.request, "exporters-api"):
return Response(
{'status': 'failed', 'message': 'Unknown file ID or export failed'},
status=status.HTTP_410_GONE
)
if cf.file:
resp = ChunkBasedFileResponse(cf.file.file, content_type=cf.type)
resp['Content-Disposition'] = 'attachment; filename="{}"'.format(cf.filename).encode("ascii", "ignore")
@@ -109,7 +114,8 @@ class ExportersMixin:
serializer = JobRunSerializer(exporter=instance, data=self.request.data, **self.get_serializer_kwargs())
serializer.is_valid(raise_exception=True)
cf = CachedFile(web_download=False)
cf = CachedFile(web_download=True)
cf.bind_to_session(self.request, "exporters-api")
cf.date = now()
cf.expires = now() + timedelta(hours=24)
cf.save()

View File

@@ -43,7 +43,6 @@ from pretix.base.services.tasks import ProfiledTask, TransactionAwareTask
from pretix.base.signals import periodic_task
from pretix.celery_app import app
from pretix.helpers import OF_SELF
from pretix.helpers.celery import get_task_priority
logger = logging.getLogger(__name__)
_ALL_EVENTS = None
@@ -475,10 +474,7 @@ def notify_webhooks(logentry_ids: list):
)
for wh in webhooks:
send_webhook.apply_async(
args=(logentry.id, notification_type.action_type, wh.pk),
priority=get_task_priority("notifications", logentry.organizer_id),
)
send_webhook.apply_async(args=(logentry.id, notification_type.action_type, wh.pk))
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=60, acks_late=True, autoretry_for=(DatabaseError,),)

View File

@@ -19,11 +19,8 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import base64
import hashlib
import re
import dns.resolver
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _, pgettext
@@ -126,9 +123,6 @@ class PeppolIdValidator:
"9959": ".*",
}
def __init__(self, validate_online=False):
self.validate_online = validate_online
def __call__(self, value):
if ":" not in value:
raise ValidationError(_("A Peppol participant ID always starts with a prefix, followed by a colon (:)."))
@@ -142,28 +136,6 @@ class PeppolIdValidator:
raise ValidationError(_("The Peppol participant ID does not match the validation rules for the prefix "
"%(number)s. Please reach out to us if you are sure this ID is correct."),
params={"number": prefix})
if self.validate_online:
base_hostnames = ['edelivery.tech.ec.europa.eu', 'acc.edelivery.tech.ec.europa.eu']
smp_id = base64.b32encode(hashlib.sha256(value.lower().encode()).digest()).decode().rstrip("=")
for base_hostname in base_hostnames:
smp_domain = f'{smp_id}.iso6523-actorid-upis.{base_hostname}'
resolver = dns.resolver.Resolver()
try:
answers = resolver.resolve(smp_domain, 'NAPTR', lifetime=1.0)
if answers:
return value
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
# ID not registered, do not set found=True
pass
except Exception: # noqa
# Error likely on our end or infrastructure is down, allow user to proceed
return value
raise ValidationError(
_("The Peppol participant ID is not registered on the Peppol network."),
)
return value
@@ -183,9 +155,7 @@ class PeppolTransmissionType(TransmissionType):
"transmission_peppol_participant_id": forms.CharField(
label=_("Peppol participant ID"),
validators=[
PeppolIdValidator(
validate_online=True,
),
PeppolIdValidator(),
]
),
}

View File

@@ -47,19 +47,6 @@ class DataImportError(LazyLocaleException):
super().__init__(msg)
def rename_duplicates(values):
used = set()
had_duplicates = False
for i, value in enumerate(values):
c = 0
while values[i] in used:
c += 1
values[i] = f'{value}__{c}'
had_duplicates = True
used.add(values[i])
return had_duplicates
def parse_csv(file, length=None, mode="strict", charset=None):
file.seek(0)
data = file.read(length)
@@ -83,7 +70,6 @@ def parse_csv(file, length=None, mode="strict", charset=None):
return None
reader = csv.DictReader(io.StringIO(data), dialect=dialect)
reader._had_duplicates = rename_duplicates(reader.fieldnames)
return reader

View File

@@ -31,7 +31,6 @@ from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from pretix.helpers.celery import get_task_priority
from pretix.helpers.json import CustomJSONEncoder
@@ -59,6 +58,37 @@ class CachedFile(models.Model):
web_download = models.BooleanField(default=True) # allow web download, True for backwards compatibility in plugins
session_key = models.TextField(null=True, blank=True) # only allow download in this session
def session_key_for_request(self, request, salt=None):
from ...api.models import OAuthAccessToken, OAuthApplication
from .devices import Device
from .organizer import TeamAPIToken
if hasattr(request, "auth") and isinstance(request.auth, OAuthAccessToken):
k = f'app:{request.auth.application.pk}'
elif hasattr(request, "auth") and isinstance(request.auth, OAuthApplication):
k = f'app:{request.auth.pk}'
elif hasattr(request, "auth") and isinstance(request.auth, TeamAPIToken):
k = f'token:{request.auth.pk}'
elif hasattr(request, "auth") and isinstance(request.auth, Device):
k = f'device:{request.auth.pk}'
elif request.session.session_key:
k = request.session.session_key
else:
raise ValueError("No auth method found to bind to")
if salt:
k = f"{k}!{salt}"
return k
def allowed_for_session(self, request, salt=None):
return (
not self.session_key or
self.session_key_for_request(request, salt) == self.session_key
)
def bind_to_session(self, request, salt=None):
self.session_key = self.session_key_for_request(request, salt)
@receiver(post_delete, sender=CachedFile)
def cached_file_delete(sender, instance, **kwargs):
@@ -132,15 +162,9 @@ class LoggingMixin:
logentry.save()
if logentry.notification_type:
notify.apply_async(
args=(logentry.pk,),
priority=get_task_priority("notifications", logentry.organizer_id),
)
notify.apply_async(args=(logentry.pk,))
if logentry.webhook_type:
notify_webhooks.apply_async(
args=(logentry.pk,),
priority=get_task_priority("notifications", logentry.organizer_id),
)
notify_webhooks.apply_async(args=(logentry.pk,))
return logentry

View File

@@ -35,14 +35,11 @@
import json
import logging
from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import connections, models
from django.utils.functional import cached_property
from pretix.helpers.celery import get_task_priority
class VisibleOnlyManager(models.Manager):
def get_queryset(self):
@@ -189,19 +186,7 @@ class LogEntry(models.Model):
to_notify = [o.id for o in objects if o.notification_type]
if to_notify:
organizer_ids = set(o.organizer_id for o in objects if o.notification_type)
notify.apply_async(
args=(to_notify,),
priority=settings.PRIORITY_CELERY_HIGHEST_FUNC(
get_task_priority("notifications", oid) for oid in organizer_ids
),
)
notify.apply_async(args=(to_notify,))
to_wh = [o.id for o in objects if o.webhook_type]
if to_wh:
organizer_ids = set(o.organizer_id for o in objects if o.webhook_type)
notify_webhooks.apply_async(
args=(to_wh,),
priority=settings.PRIORITY_CELERY_HIGHEST_FUNC(
get_task_priority("notifications", oid) for oid in organizer_ids
),
)
notify_webhooks.apply_async(args=(to_wh,))

View File

@@ -32,7 +32,6 @@ from pretix.base.services.mail import mail_send_task
from pretix.base.services.tasks import ProfiledTask, TransactionAwareTask
from pretix.base.signals import notification
from pretix.celery_app import app
from pretix.helpers.celery import get_task_priority
from pretix.helpers.urls import build_absolute_uri
@@ -89,18 +88,12 @@ def notify(logentry_ids: list):
for um, enabled in notify_specific.items():
user, method = um
if enabled:
send_notification.apply_async(
args=(logentry.id, notification_type.action_type, user.pk, method),
priority=get_task_priority("notifications", logentry.organizer_id),
)
send_notification.apply_async(args=(logentry.id, notification_type.action_type, user.pk, method))
for um, enabled in notify_global.items():
user, method = um
if enabled and um not in notify_specific:
send_notification.apply_async(
args=(logentry.id, notification_type.action_type, user.pk, method),
priority=get_task_priority("notifications", logentry.organizer_id),
)
send_notification.apply_async(args=(logentry.id, notification_type.action_type, user.pk, method))
notification.send(logentry.event, logentry_id=logentry.id, notification_type=notification_type.action_type)

View File

@@ -36,9 +36,8 @@ class DownloadView(TemplateView):
def object(self) -> CachedFile:
try:
o = get_object_or_404(CachedFile, id=self.kwargs['id'], web_download=True)
if o.session_key:
if o.session_key != self.request.session.session_key:
raise Http404()
if not o.allowed_for_session(self.request):
raise Http404()
return o
except (ValueError, ValidationError): # Invalid URLs
raise Http404()

View File

@@ -126,9 +126,7 @@
{% endif %}
<a class="navbar-brand" href="{% url "control:index" %}">
<img src="{% static "pretixbase/img/pretix-icon-white-mini.svg" %}" />
<span>
{{ settings.PRETIX_INSTANCE_NAME }}
</span>
{{ settings.PRETIX_INSTANCE_NAME }}
</a>
</div>
<ul class="nav navbar-nav navbar-top-links navbar-left flip hidden-xs">

View File

@@ -38,6 +38,7 @@ from datetime import timedelta
from django.conf import settings
from django.contrib import messages
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.functional import cached_property
@@ -85,6 +86,7 @@ class BaseImportView(TemplateView):
filename='import.csv',
type='text/csv',
)
cf.bind_to_session(request, "modelimport")
cf.file.save('import.csv', request.FILES['file'])
if self.request.POST.get("charset") in ENCODINGS:
@@ -137,7 +139,10 @@ class BaseProcessView(AsyncAction, FormView):
@cached_property
def file(self):
return get_object_or_404(CachedFile, pk=self.kwargs.get("file"), filename="import.csv")
cf = get_object_or_404(CachedFile, pk=self.kwargs.get("file"), filename="import.csv")
if not cf.allowed_for_session(self.request, "modelimport"):
raise Http404()
return cf
@cached_property
def parsed(self):
@@ -146,7 +151,7 @@ class BaseProcessView(AsyncAction, FormView):
else:
charset = None
try:
reader = parse_csv(self.file.file, 1024 * 1024, charset=charset)
return parse_csv(self.file.file, 1024 * 1024, charset=charset)
except UnicodeDecodeError:
messages.warning(
self.request,
@@ -155,16 +160,7 @@ class BaseProcessView(AsyncAction, FormView):
"Some characters were replaced with a placeholder."
)
)
reader = parse_csv(self.file.file, 1024 * 1024, "replace", charset=charset)
if reader._had_duplicates:
messages.warning(
self.request,
_(
"Multiple columns of the CSV file have the same name and were renamed automatically. We "
"recommend that you rename these in your source file to avoid problems during import."
)
)
return reader
return parse_csv(self.file.file, 1024 * 1024, "replace", charset=charset)
@cached_property
def parsed_list(self):

View File

@@ -247,7 +247,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
cf = None
if request.POST.get("background", "").strip():
try:
cf = CachedFile.objects.get(id=request.POST.get("background"))
cf = CachedFile.objects.get(id=request.POST.get("background"), web_download=True)
except CachedFile.DoesNotExist:
pass

View File

@@ -38,7 +38,8 @@ from collections import OrderedDict
from zipfile import ZipFile
from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect
from django.http import Http404
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import get_language, gettext_lazy as _
@@ -94,6 +95,8 @@ class ShredDownloadView(RecentAuthenticationRequiredMixin, EventPermissionRequir
cf = CachedFile.objects.get(pk=kwargs['file'])
except CachedFile.DoesNotExist:
raise ShredError(_("The download file could no longer be found on the server, please try to start again."))
if not cf.allowed_for_session(self.request):
raise Http404()
with ZipFile(cf.file.file, 'r') as zipfile:
indexdata = json.loads(zipfile.read('index.json').decode())
@@ -111,7 +114,7 @@ class ShredDownloadView(RecentAuthenticationRequiredMixin, EventPermissionRequir
ctx = super().get_context_data(**kwargs)
ctx['shredders'] = self.shredders
ctx['download_on_shred'] = any(shredder.require_download_confirmation for shredder in shredders)
ctx['file'] = get_object_or_404(CachedFile, pk=kwargs.get("file"))
ctx['file'] = cf
return ctx

View File

@@ -1,62 +0,0 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-today pretix GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from django.conf import settings
THRESHOLD_DOWNGRADE_TO_MID = 50
THRESHOLD_DOWNGRADE_TO_LOW = 250
def get_task_priority(shard, organizer_id):
"""
This is an attempt to build a simple "fair-use" policy for webhooks and notifications. The problem is that when
one organizer creates e.g. 20,000 orders through the API, that might schedule 20,000 webhooks and every other
organizer will need to wait for these webhooks to go through.
We try to fix that by building three queues: high-prio, mid-prio, and low-prio. Every organizer starts in the
high-prio queue, and all their tasks are routed immediately. Once an organizer submits more than X jobs of a
certain type per minute, they get downgraded to the mid-prio queue, and then if they submit even more to the
low-prio queue. That way, if another organizer has "regular usage", they are prioritized over the organizer with
high load.
"""
from django_redis import get_redis_connection
if not settings.HAS_REDIS:
return settings.PRIORITY_CELERY_HIGH
# We use redis directly instead of the Django cache API since the Django cache API does not support INCR for
# nonexistant keys
rc = get_redis_connection("redis")
cache_key = f"pretix:task_priority:{shard}:{organizer_id}"
# Make sure counters expire after a while when not used
p = rc.pipeline()
p.incr(cache_key)
p.expire(cache_key, 60)
new_counter = p.execute()[0]
if new_counter >= THRESHOLD_DOWNGRADE_TO_LOW:
return settings.PRIORITY_CELERY_LOW
elif new_counter >= THRESHOLD_DOWNGRADE_TO_MID:
return settings.PRIORITY_CELERY_MID
else:
return settings.PRIORITY_CELERY_HIGH

File diff suppressed because it is too large Load Diff

View File

@@ -438,6 +438,9 @@ def get_grouped_items(event, *, channel: SalesChannel, subevent=None, voucher=No
base_price_is='net' if event.settings.display_net_prices else 'gross') # backwards-compat
) if var.original_price or item.original_price else None
if not display_add_to_cart:
display_add_to_cart = not item.requires_seat and var.order_max > 0
var.current_unavailability_reason = var.unavailability_reason(has_voucher=voucher, subevent=subevent)
item.original_price = (
@@ -468,8 +471,6 @@ def get_grouped_items(event, *, channel: SalesChannel, subevent=None, voucher=No
item.best_variation_availability = max([v.cached_availability[0] for v in item.available_variations])
item._remove = not bool(item.available_variations)
if not item._remove and not display_add_to_cart:
display_add_to_cart = not item.requires_seat and any(v.order_max > 0 for v in item.available_variations)
if not quota_cache_existed and not voucher and not allow_addons and not base_qs_set and not filter_items and not filter_categories:
event.cache.set(quota_cache_key, quota_cache, 5)

View File

@@ -347,53 +347,11 @@ if HAS_CELERY:
CELERY_RESULT_BACKEND = config.get('celery', 'backend')
if HAS_CELERY_BROKER_TRANSPORT_OPTS:
CELERY_BROKER_TRANSPORT_OPTIONS = loads(config.get('celery', 'broker_transport_options'))
else:
CELERY_BROKER_TRANSPORT_OPTIONS = {}
if HAS_CELERY_BACKEND_TRANSPORT_OPTS:
CELERY_RESULT_BACKEND_TRANSPORT_OPTIONS = loads(config.get('celery', 'backend_transport_options'))
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
if CELERY_BROKER_URL.startswith("amqp://"):
# https://docs.celeryq.dev/en/latest/userguide/routing.html#routing-options-rabbitmq-priorities
# Enable priorities for all queues
CELERY_TASK_QUEUE_MAX_PRIORITY = 3
# On RabbitMQ, higher number is higher priority, and having less levels makes rabbitmq use less CPU and RAM
PRIORITY_CELERY_LOW = 1
PRIORITY_CELERY_MID = 2
PRIORITY_CELERY_HIGH = 3
PRIORITY_CELERY_LOWEST_FUNC = min
PRIORITY_CELERY_HIGHEST_FUNC = max
# Set default
CELERY_TASK_DEFAULT_PRIORITY = PRIORITY_CELERY_MID
elif CELERY_BROKER_URL.startswith("redis://"):
# https://docs.celeryq.dev/en/latest/userguide/routing.html#redis-message-priorities
CELERY_BROKER_TRANSPORT_OPTIONS.update({
"queue_order_strategy": "priority",
"sep": ":",
"priority_steps": [0, 4, 8]
})
# On redis, lower number is higher priority, and it appears that there are always levels 0-9 even though it
# is only really executed based on the 3 steps listed above.
PRIORITY_CELERY_LOW = 9
PRIORITY_CELERY_MID = 5
PRIORITY_CELERY_HIGH = 0
PRIORITY_CELERY_LOWEST_FUNC = max
PRIORITY_CELERY_HIGHEST_FUNC = min
CELERY_TASK_DEFAULT_PRIORITY = PRIORITY_CELERY_MID
else:
# No priority support assumed
PRIORITY_CELERY_LOW = 0
PRIORITY_CELERY_MID = 0
PRIORITY_CELERY_HIGH = 0
PRIORITY_CELERY_LOWEST_FUNC = min
PRIORITY_CELERY_HIGHEST_FUNC = max
else:
CELERY_TASK_ALWAYS_EAGER = True
PRIORITY_CELERY_LOW = 0
PRIORITY_CELERY_MID = 0
PRIORITY_CELERY_HIGH = 0
PRIORITY_CELERY_LOWEST_FUNC = min
PRIORITY_CELERY_HIGHEST_FUNC = max
CACHE_TICKETS_HOURS = config.getint('cache', 'tickets', fallback=24 * 3)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Ebene_1"
viewBox="0 0 128 128"
version="1.1"
sodipodi:docname="mstile.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="4.125"
inkscape:cx="28.242424"
inkscape:cy="53.090909"
inkscape:window-width="2556"
inkscape:window-height="1239"
inkscape:window-x="0"
inkscape:window-y="180"
inkscape:window-maximized="1"
inkscape:current-layer="Ebene_1" />
<defs
id="defs1">
<style
id="style1">.cls-1{fill:#f8f8f8;}</style>
</defs>
<g
id="g2"
transform="matrix(0.47350597,0,0,0.47350597,11.541278,11.202115)">
<path
class="cls-1"
d="M 97.457879,82.258482 C 96.737879,82.358482 96.237879,82.558482 95.797879,82.758482 L 98.177879,99.668482 C 98.587879,99.748482 99.127879,99.798482 99.777879,99.708482 103.29788,99.208482 104.38788,96.068482 103.58788,90.318482 102.75788,84.448482 101.05788,81.758482 97.467879,82.258482 Z"
id="path1" />
<path
class="cls-1"
d="M 162.82788,60.358482 C 163.53788,60.188482 163.98788,59.598482 163.88788,58.878482 L 159.32788,26.438482 C 159.22788,25.718482 158.55788,25.218482 157.83788,25.318482 L 121.58788,30.408482 122.97788,40.298482 C 123.22788,42.048482 121.90788,43.788482 120.15788,44.038482 118.40788,44.288482 116.66788,42.968482 116.41788,41.218482 L 115.02788,31.328482 47.917879,40.768482 C 47.197879,40.868482 46.697879,41.538482 46.797879,42.258482 L 51.357879,74.698482 C 51.457879,75.418482 52.057879,75.868482 52.777879,75.828482 64.027879,74.908482 74.207879,82.928482 75.807879,94.288482 77.407879,105.64848 69.817879,116.09848 58.737879,118.24848 58.027879,118.41848 57.577879,119.00848 57.677879,119.72848 L 62.237879,152.16848 C 62.337879,152.88848 63.007879,153.38848 63.727879,153.28848 L 130.84788,143.85848 129.43788,133.83848 C 129.18788,132.02848 130.44788,130.35848 132.25788,130.09848 134.06788,129.83848 135.74788,131.16848 135.99788,132.91848 L 137.40788,142.93848 173.65788,137.84848 C 174.37788,137.74848 174.87788,137.07848 174.77788,136.35848 L 170.21788,103.91848 C 170.11788,103.19848 169.51788,102.74848 168.79788,102.78848 157.54788,103.70848 147.37788,95.748482 145.77788,84.388482 144.17788,73.028482 151.75788,62.518482 162.83788,60.358482 Z M 102.98788,105.10848 C 101.22788,105.35848 99.697879,105.36848 98.947879,105.27848 L 100.53788,116.56848 90.617879,117.95848 85.317879,80.228482 C 87.817879,78.608482 91.277879,77.198482 96.697879,76.428482 105.37788,75.208482 111.96788,79.008482 113.35788,88.868482 114.60788,97.748482 110.23788,104.07848 102.99788,105.09848 Z M 133.22788,113.24848 C 133.47788,114.99848 132.15788,116.73848 130.40788,116.98848 128.65788,117.23848 126.91788,115.91848 126.66788,114.16848 L 124.28788,97.248482 C 124.02788,95.378482 125.23788,93.768482 127.10788,93.508482 128.97788,93.248482 130.58788,94.518482 130.84788,96.328482 Z M 128.11788,76.878482 C 128.36788,78.688482 127.10788,80.358482 125.29788,80.618482 123.48788,80.878482 121.81788,79.608482 121.55788,77.798482 L 119.17788,60.878482 C 118.92788,59.068482 120.18788,57.398482 121.99788,57.138482 123.74788,56.888482 125.48788,58.208482 125.73788,59.958482 Z"
id="path2" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Ebene_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><defs><style>.cls-1{fill:#492267;}</style></defs><path class="cls-1" d="m50.67,56.95c-.72.1-1.22.3-1.66.5l2.38,16.91c.41.08.95.13,1.6.04,3.52-.5,4.61-3.64,3.81-9.39-.83-5.87-2.53-8.56-6.12-8.06Z"/><path class="cls-1" d="m116.04,35.05c.71-.17,1.16-.76,1.06-1.48L112.54,1.13c-.1-.72-.77-1.22-1.49-1.12l-37.5,5.27.73,5.22c.16,1.12-.62,2.15-1.74,2.31s-2.15-.62-2.31-1.74l-.73-5.22L1.13,15.46c-.72.1-1.22.77-1.12,1.49l4.56,32.44c.1.72.7,1.17,1.42,1.13,11.25-.92,21.43,7.1,23.03,18.46,1.6,11.36-5.99,21.81-17.07,23.96-.71.17-1.16.76-1.06,1.48l4.56,32.44c.1.72.77,1.22,1.49,1.12l68.37-9.61-.73-5.22c-.16-1.15.59-2.15,1.74-2.31s2.15.62,2.31,1.74l.73,5.22,37.5-5.27c.72-.1,1.22-.77,1.12-1.49l-4.56-32.44c-.1-.72-.7-1.17-1.42-1.13-11.25.92-21.42-7.04-23.02-18.4-1.6-11.36,5.98-21.87,17.06-24.03Zm-59.84,44.75c-1.76.25-3.29.26-4.04.17l1.59,11.29-9.92,1.39-5.3-37.73c2.5-1.62,5.96-3.03,11.38-3.8,8.68-1.22,15.27,2.58,16.66,12.44,1.25,8.88-3.12,15.21-10.36,16.23Zm30.73,20.71c.16,1.12-.62,2.15-1.74,2.31-1.12.16-2.15-.62-2.31-1.74l-1.47-10.44c-.16-1.12.62-2.15,1.74-2.31s2.16.66,2.31,1.74l1.47,10.44Zm-3.17-22.58c.15,1.08-.66,2.16-1.74,2.31s-2.16-.66-2.31-1.74l-1.47-10.44c-.16-1.15.59-2.15,1.74-2.31,1.12-.16,2.15.62,2.31,1.74l1.47,10.44Zm-3.16-22.45c.16,1.12-.62,2.15-1.74,2.31-1.12.16-2.15-.62-2.31-1.74l-1.47-10.44c-.16-1.12.62-2.15,1.74-2.31s2.16.66,2.31,1.74l1.47,10.44Zm-3.17-22.58c.15,1.08-.66,2.16-1.74,2.31s-2.16-.66-2.31-1.74l-1.47-10.44c-.16-1.15.59-2.15,1.74-2.31s2.15.62,2.31,1.74l1.47,10.44Z"/></svg>
<svg version="1" xmlns="http://www.w3.org/2000/svg" width="933.333" height="933.333" viewBox="0 0 700.000000 700.000000"><path d="M0 109v109l4.3.1c33 .5 65.2 14.8 90 40.1 31.8 32.5 43.6 76.6 33.3 124.3-1.2 5.4-5.7 17.8-9 24.8-12.2 25.6-36.1 49.6-61.6 61.9-15.9 7.6-35.2 12.4-51.7 12.7L0 482v218h436.5v-60.5l9.2-.1c6-.1 9.3.3 9.6 1 .2.6.3 14.3.3 30.3l-.1 29.3H700V482l-4.7-.1c-32.5-.4-64.9-14.7-88.9-39.2-25.5-26.1-38.6-58.6-37.9-94.4.6-27.9 7.6-50 23.4-73.8 6.4-9.8 23.8-27 34.1-33.7 15.6-10.3 33.3-17.9 47.5-20.4 10-1.7 15.9-2.4 20.8-2.4h5.7V0H455.5v58h-19V.5L218.3.2 0 0v109zm454-6.1c1.3.1 1.5 5.7 1.5 44.6 0 43.8 0 44.5-2 44.6-7.9.3-15.7 0-16.3-.6-.4-.3-.7-20.3-.7-44.3v-43.7l4.5-.5c2.5-.3 6.1-.4 8-.3 1.9.1 4.2.2 5 .2zm1.5 178.6c0 24.5-.2 44.5-.5 44.6-.3.1-4.6.2-9.5.2l-9 .2V237h19v44.5zM287 256.4c37.8 3.1 65.2 23.6 75 55.9 3.6 12 4.4 18.2 4.4 34.2.1 18.9-.5 24-3.9 35.9-8.2 28.5-26.2 47.7-52 55.6-7.1 2.2-9.8 2.5-24 2.5-8.8-.1-17.8-.4-20.1-.9l-4-.8V510.5l-31.7.3-31.7.2V269.3l6.8-2.6c9.8-3.8 18.7-6.4 27.2-7.7 4.1-.7 8.2-1.4 9.1-1.5.9-.2 6.3-.7 12-1 5.7-.4 10.5-.8 10.6-.9.4-.3 14.8.2 22.3.8zm168.5 159.1c0 24.5-.2 44.6-.5 44.6-1.9.4-18 .4-18.1-.1-.4-1.5-.5-86.7-.1-87.8.3-.8 3.1-1.2 9.6-1.2h9.1v44.5zm-.1 133.7c-.1 24.4-.2 44.6-.3 44.9-.1.7-18.1.7-18.2 0-.4-1.6-.5-86.8-.1-87.9.3-.8 3.1-1.2 9.6-1.2h9.1l-.1 44.2z"/><path d="M264.5 293.9c-2 .8-2 1.8-2.1 54.5v53.8l2.5 1c1.4.5 5.8.8 9.8.5 20.6-1.5 29.5-18.2 29.6-55.7.2-37.8-9.2-54.5-30.5-54.8-4-.1-8.2.3-9.3.7z"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100%" height="100%" version="1.1" viewBox="0 0 109.594 109.594"><g transform="scale(.94461)"><path d="M45.52 48.98c-.74 0-1.28.13-1.75.27v17.43c.4.13.94.27 1.61.27 3.63 0 5.18-3.03 5.18-8.95s-1.35-9.02-5.05-9.02z" fill="#3b1c4a"/><path d="M114.72 36.13c.74-.07 1.28-.61 1.28-1.35V1.35c0-.74-.61-1.35-1.35-1.35H75.99v5.38c0 1.15-.94 2.09-2.09 2.09s-2.09-.94-2.09-2.09V0H1.35C.61 0 0 .61 0 1.35v33.44c0 .74.54 1.28 1.28 1.35 11.51.67 20.66 10.23 20.66 21.94s-9.15 21.2-20.66 21.8c-.74.07-1.28.61-1.28 1.35v33.44c0 .74.61 1.35 1.35 1.35h70.48v-5.38c0-1.19.9-2.09 2.09-2.09s2.09.94 2.09 2.09v5.38h38.66c.74 0 1.35-.61 1.35-1.35V81.23c0-.74-.54-1.28-1.28-1.35-11.51-.67-20.66-10.16-20.66-21.87s9.15-21.26 20.66-21.87zM47.87 72.87c-1.82 0-3.36-.2-4.1-.4v11.64H33.54V45.22C36.3 43.94 40 43 45.58 43c8.95 0 15.07 4.78 15.07 14.94 0 9.15-5.32 14.94-12.78 14.94zm28.12 25.3c0 1.15-.94 2.09-2.09 2.09s-2.09-.94-2.09-2.09V87.4c0-1.15.94-2.09 2.09-2.09s2.09.97 2.09 2.09zm0-23.28c0 1.11-.97 2.09-2.09 2.09-1.12 0-2.09-.97-2.09-2.09V64.12c0-1.19.9-2.09 2.09-2.09s2.09.94 2.09 2.09zm0-23.15c0 1.15-.94 2.09-2.09 2.09s-2.09-.94-2.09-2.09V40.97c0-1.15.94-2.09 2.09-2.09s2.09.97 2.09 2.09zm0-23.28c0 1.11-.97 2.09-2.09 2.09-1.12 0-2.09-.97-2.09-2.09V17.69c0-1.19.9-2.09 2.09-2.09s2.09.94 2.09 2.09z" fill="#3b1c4a"/></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Ebene_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><defs><style>.cls-1{fill:#f8f8f8;}</style></defs><path class="cls-1" d="m50.67,56.95c-.72.1-1.22.3-1.66.5l2.38,16.91c.41.08.95.13,1.6.04,3.52-.5,4.61-3.64,3.81-9.39-.83-5.87-2.53-8.56-6.12-8.06Z"/><path class="cls-1" d="m116.04,35.05c.71-.17,1.16-.76,1.06-1.48L112.54,1.13c-.1-.72-.77-1.22-1.49-1.12l-36.25,5.09,1.39,9.89c.25,1.75-1.07,3.49-2.82,3.74-1.75.25-3.49-1.07-3.74-2.82l-1.39-9.89L1.13,15.46c-.72.1-1.22.77-1.12,1.49l4.56,32.44c.1.72.7,1.17,1.42,1.13,11.25-.92,21.43,7.1,23.03,18.46s-5.99,21.81-17.07,23.96c-.71.17-1.16.76-1.06,1.48l4.56,32.44c.1.72.77,1.22,1.49,1.12l67.12-9.43-1.41-10.02c-.25-1.81,1.01-3.48,2.82-3.74s3.49,1.07,3.74,2.82l1.41,10.02,36.25-5.09c.72-.1,1.22-.77,1.12-1.49l-4.56-32.44c-.1-.72-.7-1.17-1.42-1.13-11.25.92-21.42-7.04-23.02-18.4-1.6-11.36,5.98-21.87,17.06-24.03Zm-59.84,44.75c-1.76.25-3.29.26-4.04.17l1.59,11.29-9.92,1.39-5.3-37.73c2.5-1.62,5.96-3.03,11.38-3.8,8.68-1.22,15.27,2.58,16.66,12.44,1.25,8.88-3.12,15.21-10.36,16.23Zm30.24,8.14c.25,1.75-1.07,3.49-2.82,3.74s-3.49-1.07-3.74-2.82l-2.38-16.92c-.26-1.87.95-3.48,2.82-3.74s3.48,1.01,3.74,2.82l2.38,16.92Zm-5.11-36.37c.25,1.81-1.01,3.48-2.82,3.74s-3.48-1.01-3.74-2.82l-2.38-16.92c-.25-1.81,1.01-3.48,2.82-3.74,1.75-.25,3.49,1.07,3.74,2.82l2.38,16.92Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 116 116"><path fill="#f8f8f8" d="M45.16 48.35c-.74 0-1.28.13-1.75.27v17.43c.4.13.94.27 1.61.27 3.63 0 5.18-3.03 5.18-8.95s-1.35-9.02-5.05-9.02Z"/><path fill="#f8f8f8" d="M114.36 35.5c.74-.07 1.28-.61 1.28-1.35V.71c0-.74-.61-1.35-1.35-1.35H76.93v10.2c0 1.8-1.58 3.38-3.38 3.38s-3.38-1.58-3.38-3.38V-.63H.98C.24-.63-.36-.03-.36.71v33.44c0 .74.54 1.28 1.28 1.35 11.51.67 20.66 10.23 20.66 21.94S12.42 78.63.92 79.23c-.74.07-1.28.61-1.28 1.35v33.44c0 .74.61 1.35 1.35 1.35h69.19v-10.33c0-1.86 1.52-3.38 3.38-3.38s3.38 1.58 3.38 3.38v10.33h37.36c.74 0 1.35-.61 1.35-1.35V80.58c0-.74-.54-1.28-1.28-1.35-11.51-.67-20.66-10.16-20.66-21.87s9.15-21.26 20.66-21.87ZM47.51 72.24c-1.82 0-3.36-.2-4.1-.4v11.64H33.18V44.59c2.76-1.28 6.46-2.22 12.04-2.22 8.95 0 15.07 4.78 15.07 14.94 0 9.15-5.32 14.94-12.78 14.94Zm29.41 12.53c0 1.8-1.58 3.38-3.38 3.38s-3.38-1.58-3.38-3.38V67.33c0-1.93 1.45-3.38 3.38-3.38s3.38 1.52 3.38 3.38v17.44Zm0-37.49c0 1.86-1.52 3.38-3.38 3.38s-3.38-1.52-3.38-3.38V29.84c0-1.86 1.52-3.38 3.38-3.38s3.38 1.58 3.38 3.38v17.44Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Ebene_1"
viewBox="0 0 128 128"
version="1.1"
sodipodi:docname="pretix-icon-white-on-purple.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="4.125"
inkscape:cx="101.69697"
inkscape:cy="80.727273"
inkscape:window-width="2556"
inkscape:window-height="1275"
inkscape:window-x="0"
inkscape:window-y="144"
inkscape:window-maximized="1"
inkscape:current-layer="Ebene_1" /><defs
id="defs1"><style
id="style1">.cls-1{fill:#f8f8f8;}</style><style
id="style1-9">.cls-1{fill:#492267;}</style></defs><rect
style="fill:#492267;stroke-width:1.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:13.3;paint-order:fill markers stroke;fill-opacity:1"
id="rect2"
width="128"
height="128"
x="0"
y="0" /><path
class="cls-1"
d="M 53.800397,58.604437 C 53.249481,58.680953 52.8669,58.833985 52.530229,58.987018 L 54.351313,71.925899 C 54.665029,71.987112 55.078217,72.02537 55.575572,71.956506 58.26894,71.573925 59.102966,69.171318 58.490837,64.771639 57.855753,60.280141 56.554978,58.221856 53.808048,58.604437 Z"
id="path1"
style="stroke-width:0.765162" /><g
id="g2"
transform="matrix(0.76558824,0,0,0.76558824,15.00618,15.00618)"
style="fill:#f8f8f8;fill-opacity:1"><path
class="cls-1"
d="M 50.67,56.95 C 49.95,57.05 49.45,57.25 49.01,57.45 L 51.39,74.36 C 51.8,74.44 52.34,74.49 52.99,74.4 56.51,73.9 57.6,70.76 56.8,65.01 55.97,59.14 54.27,56.45 50.68,56.95 Z"
id="path1-3"
style="fill:#f8f8f8;fill-opacity:1" /><path
class="cls-1"
d="M 116.04,35.05 C 116.75,34.88 117.2,34.29 117.1,33.57 L 112.54,1.13 C 112.44,0.41 111.77,-0.09 111.05,0.01 L 73.55,5.28 74.28,10.5 C 74.44,11.62 73.66,12.65 72.54,12.81 71.42,12.97 70.39,12.19 70.23,11.07 L 69.5,5.85 1.13,15.46 C 0.41,15.56 -0.09,16.23 0.01,16.95 L 4.57,49.39 C 4.67,50.11 5.27,50.56 5.99,50.52 17.24,49.6 27.42,57.62 29.02,68.98 30.62,80.34 23.03,90.79 11.95,92.94 11.24,93.11 10.79,93.7 10.89,94.42 L 15.45,126.86 C 15.55,127.58 16.22,128.08 16.94,127.98 L 85.31,118.37 84.58,113.15 C 84.42,112 85.17,111 86.32,110.84 87.47,110.68 88.47,111.46 88.63,112.58 L 89.36,117.8 126.86,112.53 C 127.58,112.43 128.08,111.76 127.98,111.04 L 123.42,78.6 C 123.32,77.88 122.72,77.43 122,77.47 110.75,78.39 100.58,70.43 98.98,59.07 97.38,47.71 104.96,37.2 116.04,35.04 Z M 56.2,79.8 C 54.44,80.05 52.91,80.06 52.16,79.97 L 53.75,91.26 43.83,92.65 38.53,54.92 C 41.03,53.3 44.49,51.89 49.91,51.12 58.59,49.9 65.18,53.7 66.57,63.56 67.82,72.44 63.45,78.77 56.21,79.79 Z M 86.93,100.51 C 87.09,101.63 86.31,102.66 85.19,102.82 84.07,102.98 83.04,102.2 82.88,101.08 L 81.41,90.64 C 81.25,89.52 82.03,88.49 83.15,88.33 84.27,88.17 85.31,88.99 85.46,90.07 Z M 83.76,77.93 C 83.91,79.01 83.1,80.09 82.02,80.24 80.94,80.39 79.86,79.58 79.71,78.5 L 78.24,68.06 C 78.08,66.91 78.83,65.91 79.98,65.75 81.1,65.59 82.13,66.37 82.29,67.49 Z M 80.6,55.48 C 80.76,56.6 79.98,57.63 78.86,57.79 77.74,57.95 76.71,57.17 76.55,56.05 L 75.08,45.61 C 74.92,44.49 75.7,43.46 76.82,43.3 77.94,43.14 78.98,43.96 79.13,45.04 Z M 77.43,32.9 C 77.58,33.98 76.77,35.06 75.69,35.21 74.61,35.36 73.53,34.55 73.38,33.47 L 71.91,23.03 C 71.75,21.88 72.5,20.88 73.65,20.72 74.8,20.56 75.8,21.34 75.96,22.46 Z"
id="path2-6"
style="fill:#f8f8f8;fill-opacity:1" /></g></svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Ebene_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><defs><style>.cls-1{fill:#492267;}</style></defs><path class="cls-1" d="m50.67,56.95c-.72.1-1.22.3-1.66.5l2.38,16.91c.41.08.95.13,1.6.04,3.52-.5,4.61-3.64,3.81-9.39-.83-5.87-2.53-8.56-6.12-8.06Z"/><path class="cls-1" d="m116.04,35.05c.71-.17,1.16-.76,1.06-1.48L112.54,1.13c-.1-.72-.77-1.22-1.49-1.12l-37.5,5.27.73,5.22c.16,1.12-.62,2.15-1.74,2.31s-2.15-.62-2.31-1.74l-.73-5.22L1.13,15.46c-.72.1-1.22.77-1.12,1.49l4.56,32.44c.1.72.7,1.17,1.42,1.13,11.25-.92,21.43,7.1,23.03,18.46,1.6,11.36-5.99,21.81-17.07,23.96-.71.17-1.16.76-1.06,1.48l4.56,32.44c.1.72.77,1.22,1.49,1.12l68.37-9.61-.73-5.22c-.16-1.15.59-2.15,1.74-2.31s2.15.62,2.31,1.74l.73,5.22,37.5-5.27c.72-.1,1.22-.77,1.12-1.49l-4.56-32.44c-.1-.72-.7-1.17-1.42-1.13-11.25.92-21.42-7.04-23.02-18.4-1.6-11.36,5.98-21.87,17.06-24.03Zm-59.84,44.75c-1.76.25-3.29.26-4.04.17l1.59,11.29-9.92,1.39-5.3-37.73c2.5-1.62,5.96-3.03,11.38-3.8,8.68-1.22,15.27,2.58,16.66,12.44,1.25,8.88-3.12,15.21-10.36,16.23Zm30.73,20.71c.16,1.12-.62,2.15-1.74,2.31-1.12.16-2.15-.62-2.31-1.74l-1.47-10.44c-.16-1.12.62-2.15,1.74-2.31s2.16.66,2.31,1.74l1.47,10.44Zm-3.17-22.58c.15,1.08-.66,2.16-1.74,2.31s-2.16-.66-2.31-1.74l-1.47-10.44c-.16-1.15.59-2.15,1.74-2.31,1.12-.16,2.15.62,2.31,1.74l1.47,10.44Zm-3.16-22.45c.16,1.12-.62,2.15-1.74,2.31-1.12.16-2.15-.62-2.31-1.74l-1.47-10.44c-.16-1.12.62-2.15,1.74-2.31s2.16.66,2.31,1.74l1.47,10.44Zm-3.17-22.58c.15,1.08-.66,2.16-1.74,2.31s-2.16-.66-2.31-1.74l-1.47-10.44c-.16-1.15.59-2.15,1.74-2.31s2.15.62,2.31,1.74l1.47,10.44Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100%" height="100%" version="1.1" viewBox="0 0 109.594 109.594"><g transform="scale(.94461)"><path d="M45.52 48.98c-.74 0-1.28.13-1.75.27v17.43c.4.13.94.27 1.61.27 3.63 0 5.18-3.03 5.18-8.95s-1.35-9.02-5.05-9.02z" fill="#3b1c4a"/><path d="M114.72 36.13c.74-.07 1.28-.61 1.28-1.35V1.35c0-.74-.61-1.35-1.35-1.35H75.99v5.38c0 1.15-.94 2.09-2.09 2.09s-2.09-.94-2.09-2.09V0H1.35C.61 0 0 .61 0 1.35v33.44c0 .74.54 1.28 1.28 1.35 11.51.67 20.66 10.23 20.66 21.94s-9.15 21.2-20.66 21.8c-.74.07-1.28.61-1.28 1.35v33.44c0 .74.61 1.35 1.35 1.35h70.48v-5.38c0-1.19.9-2.09 2.09-2.09s2.09.94 2.09 2.09v5.38h38.66c.74 0 1.35-.61 1.35-1.35V81.23c0-.74-.54-1.28-1.28-1.35-11.51-.67-20.66-10.16-20.66-21.87s9.15-21.26 20.66-21.87zM47.87 72.87c-1.82 0-3.36-.2-4.1-.4v11.64H33.54V45.22C36.3 43.94 40 43 45.58 43c8.95 0 15.07 4.78 15.07 14.94 0 9.15-5.32 14.94-12.78 14.94zm28.12 25.3c0 1.15-.94 2.09-2.09 2.09s-2.09-.94-2.09-2.09V87.4c0-1.15.94-2.09 2.09-2.09s2.09.97 2.09 2.09zm0-23.28c0 1.11-.97 2.09-2.09 2.09-1.12 0-2.09-.97-2.09-2.09V64.12c0-1.19.9-2.09 2.09-2.09s2.09.94 2.09 2.09zm0-23.15c0 1.15-.94 2.09-2.09 2.09s-2.09-.94-2.09-2.09V40.97c0-1.15.94-2.09 2.09-2.09s2.09.97 2.09 2.09zm0-23.28c0 1.11-.97 2.09-2.09 2.09-1.12 0-2.09-.97-2.09-2.09V17.69c0-1.19.9-2.09 2.09-2.09s2.09.94 2.09 2.09z" fill="#3b1c4a"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,2 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 69.21"><path style="fill: #faf8fc;" d="M40.1,37.97c.37,2.66-.13,4.12-1.76,4.34-.3.04-.55.02-.74-.02l-1.1-7.82c.2-.09.44-.18.77-.23,1.66-.23,2.45,1.01,2.83,3.73ZM60.79,30.87c-1.36.19-1.91,1.53-1.47,3.78l3.61-1.06c-.25-2-.96-2.88-2.14-2.72ZM114.57,27.5c.74,5.26,5.45,8.94,10.65,8.51.34-.02.61.19.66.52l2.11,15.01c.05.33-.19.64-.52.69l-48.7,6.84h0l.15-.02-.34-2.42c-.08-.58-.62-.99-1.21-.91-.59.08-.99.61-.91,1.21l.34,2.42.15-.02h0L7.84,69.05c-.33.05-.64-.19-.69-.52l-2.11-15.01c-.05-.33.16-.61.49-.68,5.13-1,8.64-5.83,7.9-11.09-.74-5.26-5.45-8.97-10.66-8.54-.34.02-.61-.19-.66-.52L0,17.66c-.05-.33.19-.64.52-.69L69.49,7.28l.34,2.42c.08.58.62.99,1.21.91s.99-.62.91-1.21l-.34-2.42L120.16.16c.33-.05.64.19.69.52l2.11,15.01c.05.33-.16.61-.49.68-5.13,1-8.63,5.87-7.89,11.12ZM44.63,37.3c-.64-4.56-3.69-6.32-7.71-5.76-2.51.35-4.11,1.01-5.27,1.76l2.45,17.46,4.59-.65-.73-5.23c.35.04,1.05.04,1.87-.08,3.35-.47,5.37-3.4,4.8-7.51ZM53.46,29.28c-.46.03-.91.07-1.34.13-2.96.39-4.94,1.03-6.17,1.88l1.72,12.27,4.59-.65-1.44-10.24c.57-.3,1.39-.41,2.3-.11l.34-3.28ZM60.61,28.24c-4.08.57-5.77,3.68-5.22,7.57.55,3.9,3.19,6.45,7.45,5.85,2.42-.34,3.86-1.01,4.94-1.71l-1.42-2.67c-.67.46-1.84.97-3.38,1.18-1.66.23-2.48-.36-2.98-1.71l7.43-2.12c-.38-4.44-2.71-7.01-6.81-6.4ZM77.12,46.23c-.08-.56-.64-.99-1.21-.91-.58.08-.99.62-.91,1.21l.68,4.83c.08.58.62.99,1.21.91.58-.08.99-.62.91-1.21l-.68-4.83ZM75.65,35.77c-.08-.58-.62-.99-1.21-.91s-.99.61-.91,1.21l.68,4.83c.08.56.64.99,1.21.91.56-.08.99-.64.91-1.21l-.68-4.83ZM74.19,25.38c-.08-.56-.64-.99-1.21-.91s-.99.62-.91,1.21l.68,4.83c.08.58.62.99,1.21.91s.99-.62.91-1.21l-.68-4.83ZM72.73,14.93c-.08-.58-.62-.99-1.21-.91s-.99.61-.91,1.21l.68,4.83c.08.56.64.99,1.21.91s.99-.64.91-1.21l-.68-4.83ZM87.74,24.65l-1.87.26-.53-3.81-4.43,1.79.37,2.66-1.36.19.42,2.99,1.36-.19.87,6.22c.31,2.24,1.89,3.83,4.82,3.42,1.06-.15,1.83-.54,2.14-.76l-.39-2.81c-.35.17-.52.26-.85.3-.69.1-1.08-.22-1.21-1.18l-.82-5.83,1.87-.26h.03s-.42-3-.42-3ZM94.42,23.74l-4.59.65,1.83,12.99,4.59-.65-1.83-12.99ZM93.97,19.92c-.16-1.15-1.35-1.91-2.68-1.72-1.3.18-2.23,1.24-2.07,2.39s1.35,1.94,2.65,1.75c1.33-.19,2.25-1.27,2.09-2.42ZM110.72,34.73l-5.12-6.43,2.93-6.54-4.26.6-1.26,3.5h-.06s-2.03-3.03-2.03-3.03l-4.77.67,4.54,5.77-3.14,7.28,4.62-.65,1.22-3.84h.06s2.17,3.35,2.17,3.35l5.11-.69Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="254.156" height="109.594" version="1.1"><g transform="scale(1.9856)"><path d="M36.29 23.21c-.35 0-.61.06-.83.13v8.29c.19.06.45.13.77.13 1.73 0 2.46-1.44 2.46-4.26s-.64-4.29-2.4-4.29z" fill="#f8f8f8"/><path d="M61.22 23.15c-1.44 0-2.21 1.31-2.08 3.71l3.9-.58c.03-2.11-.58-3.14-1.82-3.14z" fill="#f8f8f8"/><path d="M127.39 17.1c.35-.03.61-.29.61-.64V.64c0-.35-.29-.64-.64-.64H75.94v2.48c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12V0H.64C.29 0 0 .29 0 .64v15.82c0 .35.26.61.61.64 5.47.32 9.82 4.86 9.82 10.43 0 5.57-4.35 10.08-9.82 10.37-.35.03-.61.29-.61.64v15.82c0 .35.29.64.64.64h73.22-.16v-2.48c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12V55h-.16 51.58c.35 0 .64-.29.64-.64V38.54c0-.35-.26-.61-.61-.64-5.47-.32-9.82-4.83-9.82-10.4s4.35-10.11 9.82-10.4zM37.41 34.57c-.86 0-1.6-.1-1.95-.19v5.54H30.6v-18.5c1.31-.61 3.07-1.06 5.73-1.06 4.26 0 7.17 2.27 7.17 7.1 0 4.35-2.53 7.1-6.08 7.1zm15.58-10.78c-.9-.45-1.76-.45-2.4-.22v10.85h-4.86V21.43c1.41-.7 3.55-1.09 6.69-1.06.45 0 .93.03 1.41.06L53 23.79Zm14.56 4.26-8.03 1.12c.32 1.47 1.09 2.21 2.85 2.21 1.63 0 2.91-.35 3.68-.74l1.09 2.98c-1.22.58-2.82 1.06-5.38 1.06-4.51 0-6.88-3.04-6.88-7.17s2.21-7.1 6.53-7.1c4.35-.03 6.4 2.98 6.14 7.65zm8.38 18.56c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12v-5.12c0-.62.5-1.12 1.12-1.12.62 0 1.12.52 1.12 1.12zm0-11.07c0 .6-.52 1.12-1.12 1.12-.6 0-1.12-.52-1.12-1.12v-5.12c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12zm0-11.01c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12v-5.12c0-.62.5-1.12 1.12-1.12.62 0 1.12.52 1.12 1.12zm0-11.07c0 .6-.52 1.12-1.12 1.12-.6 0-1.12-.52-1.12-1.12V8.34c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12zM90.11 23.8h-2.02v6.18c0 1.02.35 1.41 1.09 1.41.35 0 .54-.06.93-.19v2.98c-.35.19-1.22.48-2.34.48-3.1 0-4.51-1.89-4.51-4.26v-6.59h-1.44v-3.17h1.44v-2.82l4.86-1.22v4.03h1.98v3.17zm7.07 10.62h-4.86V20.66h4.86zm-2.43-15.58c-1.38 0-2.5-.99-2.5-2.21s1.12-2.18 2.5-2.18 2.53.96 2.53 2.18c0 1.22-1.12 2.21-2.53 2.21zm12.35 15.58-1.76-3.81h-.06l-1.82 3.81h-4.9l4.32-7.1-3.87-6.66h5.06l1.66 3.46h.06l1.82-3.46h4.51l-4 6.37 4.38 7.42-5.41-.03z" fill="#f8f8f8"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Ebene_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 70"><defs><style>.cls-1{fill:#492267;}</style></defs><path class="cls-1" d="m37.27,34.63c-.33.05-.57.14-.77.23l1.1,7.82c.19.03.44.06.74.02,1.63-.23,2.14-1.69,1.76-4.34-.38-2.72-1.17-3.96-2.83-3.73Z"/><path class="cls-1" d="m60.79,31.26c-1.36.19-1.91,1.53-1.47,3.78l3.61-1.06c-.25-2-.96-2.88-2.14-2.72Z"/><path class="cls-1" d="m122.47,16.77c.33-.08.54-.35.49-.68l-2.11-15.01c-.05-.33-.36-.57-.69-.52l-48.67,6.84.34,2.42c.07.52-.29,1-.8,1.07s-1-.29-1.07-.8l-.34-2.42L.53,17.37c-.33.05-.57.36-.52.69l2.11,15.01c.05.33.32.54.66.52,5.21-.42,9.92,3.29,10.66,8.54.74,5.26-2.77,10.09-7.9,11.09-.33.08-.54.35-.49.68l2.11,15.01c.05.33.36.57.69.52l69.12-9.71h-.03s-.34-2.41-.34-2.41c-.08-.53.27-.99.8-1.07s1,.29,1.07.8l.34,2.42h-.03s48.7-6.84,48.7-6.84c.33-.05.57-.36.52-.69l-2.11-15.01c-.05-.33-.32-.54-.66-.52-5.21.42-9.92-3.26-10.65-8.51-.74-5.26,2.77-10.12,7.89-11.12Zm-82.63,28.43c-.82.11-1.52.12-1.87.08l.73,5.23-4.59.65-2.45-17.46c1.16-.75,2.76-1.4,5.27-1.76,4.02-.56,7.07,1.19,7.71,5.76.58,4.11-1.44,7.04-4.8,7.51Zm13.28-12.25c-.91-.3-1.72-.19-2.3.11l1.44,10.24-4.59.65-1.72-12.27c1.24-.85,3.21-1.5,6.17-1.88.42-.06.88-.09,1.34-.13l-.34,3.28Zm14.31,2.09l-7.43,2.12c.5,1.35,1.32,1.94,2.98,1.71,1.54-.22,2.7-.72,3.38-1.18l1.42,2.67c-1.07.71-2.52,1.37-4.94,1.71-4.26.6-6.9-1.96-7.45-5.85-.55-3.9,1.14-7,5.22-7.57,4.1-.61,6.44,1.96,6.81,6.4Zm10.26,16.43c.07.52-.29,1-.8,1.07s-1-.29-1.07-.8l-.68-4.83c-.07-.52.29-1,.8-1.07s1,.31,1.07.8l.68,4.83Zm-1.47-10.45c.07.5-.31,1-.8,1.07s-1-.31-1.07-.8l-.68-4.83c-.08-.53.27-.99.8-1.07s1,.29,1.07.8l.68,4.83Zm-1.46-10.39c.07.52-.29,1-.8,1.07s-1-.29-1.07-.8l-.68-4.83c-.07-.52.29-1,.8-1.07s1,.31,1.07.8l.68,4.83Zm-1.47-10.45c.07.5-.31,1-.8,1.07s-1-.31-1.07-.8l-.68-4.83c-.08-.53.27-.99.8-1.07s1,.29,1.07.8l.68,4.83Zm14.88,7.86h-.03s-1.87.27-1.87.27l.82,5.83c.14.97.52,1.28,1.21,1.18.33-.05.51-.13.85-.3l.39,2.81c-.31.23-1.08.61-2.14.76-2.93.41-4.51-1.18-4.82-3.42l-.87-6.22-1.36.19-.42-2.99,1.36-.19-.37-2.66,4.43-1.79.53,3.81,1.87-.26.42,2.99Zm8.09,9.09l-4.59.65-1.83-12.99,4.59-.65,1.83,12.99Zm-4.36-14.39c-1.3.18-2.49-.61-2.65-1.75-.16-1.15.77-2.2,2.07-2.39s2.51.57,2.68,1.72-.76,2.23-2.09,2.42Zm13.73,13.07l-2.17-3.36h-.06s-1.22,3.85-1.22,3.85l-4.62.65,3.14-7.28-4.54-5.77,4.77-.67,2.03,3.04h.06s1.26-3.51,1.26-3.51l4.26-.6-2.93,6.54,5.12,6.43-5.11.69Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="254.156" height="109.594" version="1.1"><g transform="matrix(1.9856 0 0 1.9856 0 .193)"><path d="M36.29 23.21c-.35 0-.61.06-.83.13v8.29c.19.06.45.13.77.13 1.73 0 2.46-1.44 2.46-4.26s-.64-4.29-2.4-4.29z" fill="#3b1c4a"/><path d="M61.22 23.15c-1.44 0-2.21 1.31-2.08 3.71l3.9-.58c.03-2.11-.58-3.14-1.82-3.14z" fill="#3b1c4a"/><path d="M127.39 17.1c.35-.03.61-.29.61-.64V.64c0-.35-.29-.64-.64-.64H75.81v2.48c0 .55-.45.99-.99.99s-.99-.45-.99-.99V0H.64C.29 0 0 .29 0 .64v15.82c0 .35.26.61.61.64 5.47.32 9.82 4.86 9.82 10.43 0 5.57-4.35 10.08-9.82 10.37-.35.03-.61.29-.61.64v15.82c0 .35.29.64.64.64h73.22-.03v-2.48c0-.57.43-.99.99-.99s.99.45.99.99V55h-.03 51.58c.35 0 .64-.29.64-.64V38.54c0-.35-.26-.61-.61-.64-5.47-.32-9.82-4.83-9.82-10.4s4.35-10.11 9.82-10.4zM37.41 34.57c-.86 0-1.6-.1-1.95-.19v5.54H30.6v-18.5c1.31-.61 3.07-1.06 5.73-1.06 4.26 0 7.17 2.27 7.17 7.1 0 4.35-2.53 7.1-6.08 7.1zm15.58-10.78c-.9-.45-1.76-.45-2.4-.22v10.85h-4.86V21.43c1.41-.7 3.55-1.09 6.69-1.06.45 0 .93.03 1.41.06L53 23.79Zm14.56 4.26-8.03 1.12c.32 1.47 1.09 2.21 2.85 2.21 1.63 0 2.91-.35 3.68-.74l1.09 2.98c-1.22.58-2.82 1.06-5.38 1.06-4.51 0-6.88-3.04-6.88-7.17s2.21-7.1 6.53-7.1c4.35-.03 6.4 2.98 6.14 7.65zm8.26 18.56c0 .55-.45.99-.99.99s-.99-.45-.99-.99v-5.12c0-.55.45-.99.99-.99s.99.46.99.99zm0-11.07c0 .53-.46.99-.99.99s-.99-.46-.99-.99v-5.12c0-.57.43-.99.99-.99s.99.45.99.99zm0-11.01c0 .55-.45.99-.99.99s-.99-.45-.99-.99v-5.12c0-.55.45-.99.99-.99s.99.46.99.99zm0-11.07c0 .53-.46.99-.99.99s-.99-.46-.99-.99V8.34c0-.57.43-.99.99-.99s.99.45.99.99zm14.3 10.34h-2.02v6.18c0 1.02.35 1.41 1.09 1.41.35 0 .54-.06.93-.19v2.98c-.35.19-1.22.48-2.34.48-3.1 0-4.51-1.89-4.51-4.26v-6.59h-1.44v-3.17h1.44v-2.82l4.86-1.22v4.03h1.98v3.17zm7.07 10.62h-4.86V20.66h4.86zm-2.43-15.58c-1.38 0-2.5-.99-2.5-2.21s1.12-2.18 2.5-2.18 2.53.96 2.53 2.18c0 1.22-1.12 2.21-2.53 2.21zm12.35 15.58-1.76-3.81h-.06l-1.82 3.81h-4.9l4.32-7.1-3.87-6.66h5.06l1.66 3.46h.06l1.82-3.46h4.51l-4 6.37 4.38 7.42-5.41-.03z" fill="#3b1c4a"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 135.467 135.467"><g transform="matrix(7.9501 0 0 7.9501 -115.332 -24.995)"><rect width="17.04" height="17.04" x="14.507" y="3.144" fill="#492267" color="#000" overflow="visible" rx="1.664" ry="1.664" style="marker:none"/><g fill="#fff"><path d="M17.702 6.339v2.13h-1.065v-2.13c0-.588.477-1.065 1.065-1.065h2.13v1.065h-2.13m10.65-1.065c.588 0 1.065.477 1.065 1.065v2.13h-1.065v-2.13h-2.13V5.274h2.13m-10.65 9.585v2.13h2.13v1.065h-2.13a1.065 1.065 0 0 1-1.065-1.065v-2.13h1.065m10.65 2.13v-2.13h1.065v2.13c0 .588-.477 1.065-1.065 1.065h-2.13v-1.065z"/><path d="M22.606 7.253c-1.563 0-2.6.256-3.367.617v10.867h2.856V15.49c.21.06.631.12 1.142.12 2.09 0 3.577-1.623 3.577-4.178 0-2.84-1.698-4.179-4.208-4.179zm-.015 1.668c1.037 0 1.398.828 1.398 2.526 0 1.653-.42 2.494-1.443 2.494a1.17 1.17 0 0 1-.451-.075v-4.87c.135-.045.286-.075.496-.075z" color="#000" overflow="visible" style="marker:none" transform="matrix(.53249 0 0 .53249 10.765 5.453)"/></g></g><path fill="none" d="M-115.332-24.995H75.47v190.802h-190.802z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 135.467 135.467"><g transform="matrix(7.9501 0 0 7.9501 -115.332 -24.995)"><rect width="17.04" height="17.04" x="14.507" y="3.144" fill="#3b1c4a" color="#000" overflow="visible" rx="1.664" ry="1.664" style="marker:none"/><g fill="#fff"><path d="M17.702 6.339v2.13h-1.065v-2.13c0-.588.477-1.065 1.065-1.065h2.13v1.065h-2.13m10.65-1.065c.588 0 1.065.477 1.065 1.065v2.13h-1.065v-2.13h-2.13V5.274h2.13m-10.65 9.585v2.13h2.13v1.065h-2.13a1.065 1.065 0 0 1-1.065-1.065v-2.13h1.065m10.65 2.13v-2.13h1.065v2.13c0 .588-.477 1.065-1.065 1.065h-2.13v-1.065z"/><path d="M22.606 7.253c-1.563 0-2.6.256-3.367.617v10.867h2.856V15.49c.21.06.631.12 1.142.12 2.09 0 3.577-1.623 3.577-4.178 0-2.84-1.698-4.179-4.208-4.179zm-.015 1.668c1.037 0 1.398.828 1.398 2.526 0 1.653-.42 2.494-1.443 2.494a1.17 1.17 0 0 1-.451-.075v-4.87c.135-.045.286-.075.496-.075z" color="#000" overflow="visible" style="marker:none" transform="matrix(.53249 0 0 .53249 10.765 5.453)"/></g></g><path fill="none" d="M-115.332-24.995H75.47v190.802h-190.802z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -36,21 +36,10 @@ nav.navbar {
margin: 0;
border: 0;
}
.navbar-brand {
position: relative;
padding-bottom: 10px;
padding-top: 10px;
padding-left: 10px;
}
.navbar-brand span {
padding: 4px 8px 6px; // Optical alignment next to logo
display: inline-block;
}
.navbar-brand img {
width: auto;
height: 100%;
display: inline-block;
vertical-align: top;
width: auto;
display: inline;
}
#side-menu img.fa-img {