Free and open source ticket system written in python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

init

Dustin Kroeger a8a7b9b5

+7492
+158
.gitignore
··· 1 + # Byte-compiled / optimized / DLL files 2 + __pycache__/ 3 + *.py[cod] 4 + *$py.class 5 + 6 + # C extensions 7 + *.so 8 + 9 + # Distribution / packaging 10 + .Python 11 + build/ 12 + develop-eggs/ 13 + dist/ 14 + downloads/ 15 + eggs/ 16 + .eggs/ 17 + lib/ 18 + lib64/ 19 + parts/ 20 + sdist/ 21 + var/ 22 + wheels/ 23 + share/python-wheels/ 24 + *.egg-info/ 25 + .installed.cfg 26 + *.egg 27 + MANIFEST 28 + 29 + # PyInstaller 30 + # Usually these files are written by a python script from a template 31 + # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 + *.manifest 33 + *.spec 34 + 35 + # Installer logs 36 + pip-log.txt 37 + pip-delete-this-directory.txt 38 + 39 + # Unit test / coverage reports 40 + htmlcov/ 41 + .tox/ 42 + .nox/ 43 + .coverage 44 + .coverage.* 45 + .cache 46 + nosetests.xml 47 + coverage.xml 48 + *.cover 49 + *.py,cover 50 + .hypothesis/ 51 + .pytest_cache/ 52 + cover/ 53 + 54 + # Translations 55 + *.mo 56 + *.pot 57 + 58 + # Django stuff: 59 + *.log 60 + local_settings.py 61 + db.sqlite3 62 + db.sqlite3-journal 63 + 64 + # Flask stuff: 65 + instance/ 66 + .webassets-cache 67 + 68 + # Scrapy stuff: 69 + .scrapy 70 + 71 + # Sphinx documentation 72 + docs/_build/ 73 + 74 + # PyBuilder 75 + .pybuilder/ 76 + target/ 77 + 78 + # Jupyter Notebook 79 + .ipynb_checkpoints 80 + 81 + # IPython 82 + profile_default/ 83 + ipython_config.py 84 + 85 + # pyenv 86 + # For a library or package, you might want to ignore these files since the code is 87 + # intended to run in multiple environments; otherwise, check them in: 88 + # .python-version 89 + 90 + # pipenv 91 + # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 + # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 + # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 + # install all needed dependencies. 95 + #Pipfile.lock 96 + 97 + # poetry 98 + # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 + # This is especially recommended for binary packages to ensure reproducibility, and is more 100 + # commonly ignored for libraries. 101 + # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 + #poetry.lock 103 + 104 + # pdm 105 + # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 + #pdm.lock 107 + # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 + # in version control. 109 + # https://pdm.fming.dev/#use-with-ide 110 + .pdm.toml 111 + 112 + # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 + __pypackages__/ 114 + 115 + # Celery stuff 116 + celerybeat-schedule 117 + celerybeat.pid 118 + 119 + # SageMath parsed files 120 + *.sage.py 121 + 122 + # Environments 123 + .env 124 + .venv 125 + env/ 126 + venv/ 127 + ENV/ 128 + env.bak/ 129 + venv.bak/ 130 + 131 + # Spyder project settings 132 + .spyderproject 133 + .spyproject 134 + 135 + # Rope project settings 136 + .ropeproject 137 + 138 + # mkdocs documentation 139 + /site 140 + 141 + # mypy 142 + .mypy_cache/ 143 + .dmypy.json 144 + dmypy.json 145 + 146 + # Pyre type checker 147 + .pyre/ 148 + 149 + # pytype static type analyzer 150 + .pytype/ 151 + 152 + # Cython debug symbols 153 + cython_debug/ 154 + node_modules 155 + 156 + 157 + static/admin 158 + static/colorfield
+1
.python-version
··· 1 + 3.12
core/__init__.py

This is a binary file and will not be displayed.

+11
core/admin.py
··· 1 + from django.contrib import admin 2 + from django.contrib.auth.admin import UserAdmin 3 + from .models import PawUser 4 + 5 + 6 + @admin.register(PawUser) 7 + class CustomUserAdmin(UserAdmin): 8 + fieldsets = UserAdmin.fieldsets + ( 9 + ('Extended Data', { 10 + 'fields': ('profile_picture', 'language', 'telegram_username')}), 11 + )
+6
core/apps.py
··· 1 + from django.apps import AppConfig 2 + 3 + 4 + class CoreConfig(AppConfig): 5 + default_auto_field = "django.db.models.BigAutoField" 6 + name = "core"
+19
core/forms.py
··· 1 + from django import forms 2 + from django.conf import settings 3 + from .models import PawUser 4 + 5 + 6 + class UserChangeForm(forms.Form): 7 + email = forms.EmailField(required=True, widget=forms.EmailInput( 8 + attrs={'class': 'input input-bordered w-full'})) 9 + profile_picture = forms.ImageField(required=False, widget=forms.FileInput( 10 + attrs={'class': 'file-input file-input-bordered w-full'})) 11 + language = forms.ChoiceField(choices=settings.LANGUAGES, widget=forms.Select( 12 + attrs={'class': 'select select-bordered w-full'})) 13 + telegram_username = forms.CharField(required=False, widget=forms.TextInput(attrs={ 14 + 'class': 'grow', 'placeholder': 'Telegram Username'})) 15 + 16 + class Meta: 17 + model = PawUser 18 + fields = ('email', 'profile_picture', 19 + 'language', 'telegram_username')
+141
core/migrations/0001_initial.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-07 23:13 2 + 3 + import django.contrib.auth.models 4 + import django.contrib.auth.validators 5 + import django.utils.timezone 6 + from django.db import migrations, models 7 + 8 + 9 + class Migration(migrations.Migration): 10 + 11 + initial = True 12 + 13 + dependencies = [ 14 + ("auth", "0012_alter_user_first_name_max_length"), 15 + ] 16 + 17 + operations = [ 18 + migrations.CreateModel( 19 + name="PawUser", 20 + fields=[ 21 + ( 22 + "id", 23 + models.BigAutoField( 24 + auto_created=True, 25 + primary_key=True, 26 + serialize=False, 27 + verbose_name="ID", 28 + ), 29 + ), 30 + ("password", models.CharField(max_length=128, verbose_name="password")), 31 + ( 32 + "last_login", 33 + models.DateTimeField( 34 + blank=True, null=True, verbose_name="last login" 35 + ), 36 + ), 37 + ( 38 + "is_superuser", 39 + models.BooleanField( 40 + default=False, 41 + help_text="Designates that this user has all permissions without explicitly assigning them.", 42 + verbose_name="superuser status", 43 + ), 44 + ), 45 + ( 46 + "username", 47 + models.CharField( 48 + error_messages={ 49 + "unique": "A user with that username already exists." 50 + }, 51 + help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", 52 + max_length=150, 53 + unique=True, 54 + validators=[ 55 + django.contrib.auth.validators.UnicodeUsernameValidator() 56 + ], 57 + verbose_name="username", 58 + ), 59 + ), 60 + ( 61 + "first_name", 62 + models.CharField( 63 + blank=True, max_length=150, verbose_name="first name" 64 + ), 65 + ), 66 + ( 67 + "last_name", 68 + models.CharField( 69 + blank=True, max_length=150, verbose_name="last name" 70 + ), 71 + ), 72 + ( 73 + "email", 74 + models.EmailField( 75 + blank=True, max_length=254, verbose_name="email address" 76 + ), 77 + ), 78 + ( 79 + "is_staff", 80 + models.BooleanField( 81 + default=False, 82 + help_text="Designates whether the user can log into this admin site.", 83 + verbose_name="staff status", 84 + ), 85 + ), 86 + ( 87 + "is_active", 88 + models.BooleanField( 89 + default=True, 90 + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", 91 + verbose_name="active", 92 + ), 93 + ), 94 + ( 95 + "date_joined", 96 + models.DateTimeField( 97 + default=django.utils.timezone.now, verbose_name="date joined" 98 + ), 99 + ), 100 + ( 101 + "profile_picture", 102 + models.ImageField(blank=True, null=True, upload_to="profile_pics/"), 103 + ), 104 + ("language", models.CharField(default="en", max_length=2)), 105 + ( 106 + "telegram_username", 107 + models.CharField(blank=True, max_length=50, null=True), 108 + ), 109 + ( 110 + "groups", 111 + models.ManyToManyField( 112 + blank=True, 113 + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", 114 + related_name="user_set", 115 + related_query_name="user", 116 + to="auth.group", 117 + verbose_name="groups", 118 + ), 119 + ), 120 + ( 121 + "user_permissions", 122 + models.ManyToManyField( 123 + blank=True, 124 + help_text="Specific permissions for this user.", 125 + related_name="user_set", 126 + related_query_name="user", 127 + to="auth.permission", 128 + verbose_name="user permissions", 129 + ), 130 + ), 131 + ], 132 + options={ 133 + "verbose_name": "user", 134 + "verbose_name_plural": "users", 135 + "abstract": False, 136 + }, 137 + managers=[ 138 + ("objects", django.contrib.auth.models.UserManager()), 139 + ], 140 + ), 141 + ]
core/migrations/__init__.py

This is a binary file and will not be displayed.

+12
core/models.py
··· 1 + from django.db import models 2 + from django.contrib.auth.models import AbstractUser 3 + 4 + 5 + class PawUser(AbstractUser): 6 + profile_picture = models.ImageField( 7 + upload_to='profile_pics/', null=True, blank=True) 8 + language = models.CharField(max_length=2, default='en') 9 + telegram_username = models.CharField(max_length=50, null=True, blank=True) 10 + 11 + def __str__(self): 12 + return self.username
+3
core/tests.py
··· 1 + from django.test import TestCase 2 + 3 + # Create your tests here.
+9
core/urls.py
··· 1 + from django.urls import path 2 + 3 + from .views import home_view, logout_view, settings_view 4 + 5 + urlpatterns = [ 6 + path("", home_view, name="home"), 7 + path("settings", settings_view, name="settings"), 8 + path("logout", logout_view, name="logout"), 9 + ]
+8
core/utils/initial_data.py
··· 1 + from django.contrib.auth.management import create_permissions 2 + from django.contrib.auth.models import Group, Permission 3 + 4 + 5 + def populate_groups(apps, schema_editor): 6 + user_roles = ["Client", "Supporter"] 7 + for name in user_roles: 8 + Group.objects.create(name=name)
+51
core/views.py
··· 1 + from django.shortcuts import render, redirect 2 + from django.contrib.auth import logout 3 + from .forms import UserChangeForm 4 + from django.utils import translation 5 + from django.conf import settings 6 + from django.contrib.auth.decorators import login_required 7 + 8 + 9 + @login_required 10 + def home_view(request): 11 + 12 + user_language = request.user.language 13 + translation.activate(user_language) 14 + res = redirect("all_tickets") 15 + res.set_cookie(settings.LANGUAGE_COOKIE_NAME, user_language) 16 + return res 17 + 18 + 19 + def logout_view(request): 20 + logout(request) 21 + return redirect("login") 22 + 23 + 24 + @login_required 25 + def settings_view(request): 26 + changed_user_language = False 27 + 28 + if request.method == "POST": 29 + form = UserChangeForm(request.POST, request.FILES) 30 + if form.is_valid(): 31 + if form.cleaned_data["language"] != request.user.language: 32 + translation.activate(form.cleaned_data["language"]) 33 + changed_user_language = True 34 + 35 + request.user.email = form.cleaned_data["email"] 36 + request.user.language = form.cleaned_data["language"] 37 + request.user.telegram_username = form.cleaned_data["telegram_username"] 38 + if form.cleaned_data["profile_picture"]: 39 + request.user.profile_picture = form.cleaned_data["profile_picture"] 40 + request.user.save() 41 + else: 42 + form = UserChangeForm(initial={ 43 + "email": request.user.email, 44 + "language": request.user.language, 45 + "telegram_username": request.user.telegram_username 46 + }) 47 + 48 + res = render(request, "core/settings.html", {"form": form}) 49 + if changed_user_language: 50 + res.set_cookie(settings.LANGUAGE_COOKIE_NAME, request.user.language) 51 + return res
+22
manage.py
··· 1 + #!/usr/bin/env python 2 + """Django's command-line utility for administrative tasks.""" 3 + import os 4 + import sys 5 + 6 + 7 + def main(): 8 + """Run administrative tasks.""" 9 + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "paw.settings") 10 + try: 11 + from django.core.management import execute_from_command_line 12 + except ImportError as exc: 13 + raise ImportError( 14 + "Couldn't import Django. Are you sure it's installed and " 15 + "available on your PYTHONPATH environment variable? Did you " 16 + "forget to activate a virtual environment?" 17 + ) from exc 18 + execute_from_command_line(sys.argv) 19 + 20 + 21 + if __name__ == "__main__": 22 + main()
+5
paw/__init__.py
··· 1 + from django import get_version 2 + 3 + VERSION = (0, 1, 0, "beta", 1) 4 + 5 + __version__ = get_version(VERSION)
+16
paw/asgi.py
··· 1 + """ 2 + ASGI config for paw project. 3 + 4 + It exposes the ASGI callable as a module-level variable named ``application``. 5 + 6 + For more information on this file, see 7 + https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 8 + """ 9 + 10 + import os 11 + 12 + from django.core.asgi import get_asgi_application 13 + 14 + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "paw.settings") 15 + 16 + application = get_asgi_application()
+35
paw/locale/en/LC_MESSAGES/django.po
··· 1 + # SOME DESCRIPTIVE TITLE. 2 + # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 + # This file is distributed under the same license as the PACKAGE package. 4 + # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 5 + # 6 + #, fuzzy 7 + msgid "" 8 + msgstr "" 9 + "Project-Id-Version: PACKAGE VERSION\n" 10 + "Report-Msgid-Bugs-To: \n" 11 + "POT-Creation-Date: 2024-03-07 15:10+0100\n" 12 + "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 + "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 14 + "Language-Team: LANGUAGE <LL@li.org>\n" 15 + "Language: \n" 16 + "MIME-Version: 1.0\n" 17 + "Content-Type: text/plain; charset=UTF-8\n" 18 + "Content-Transfer-Encoding: 8bit\n" 19 + "Plural-Forms: nplurals=2; plural=(n != 1);\n" 20 + 21 + #: paw/settings.py:114 22 + msgid "English" 23 + msgstr "English" 24 + 25 + #: paw/settings.py:115 26 + msgid "French" 27 + msgstr "French" 28 + 29 + #: paw/settings.py:116 30 + msgid "German" 31 + msgstr "German" 32 + 33 + #: paw/templates/core/settings.html:6 34 + msgid "SettingsHeading" 35 + msgstr "Settings"
+171
paw/locale/fr/LC_MESSAGES/django.po
··· 1 + # SOME DESCRIPTIVE TITLE. 2 + # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 + # This file is distributed under the same license as the PACKAGE package. 4 + # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 5 + # 6 + #, fuzzy 7 + msgid "" 8 + msgstr "" 9 + "Project-Id-Version: PACKAGE VERSION\n" 10 + "Report-Msgid-Bugs-To: \n" 11 + "POT-Creation-Date: 2024-03-08 00:49+0000\n" 12 + "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 + "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 14 + "Language-Team: LANGUAGE <LL@li.org>\n" 15 + "Language: \n" 16 + "MIME-Version: 1.0\n" 17 + "Content-Type: text/plain; charset=UTF-8\n" 18 + "Content-Transfer-Encoding: 8bit\n" 19 + "Plural-Forms: nplurals=2; plural=(n > 1);\n" 20 + 21 + #: paw/settings.py:117 22 + msgid "English" 23 + msgstr "Anglais" 24 + 25 + #: paw/settings.py:118 26 + msgid "French" 27 + msgstr "Français" 28 + 29 + #: paw/settings.py:119 30 + msgid "German" 31 + msgstr "Allemand" 32 + 33 + #: paw/templates/core/settings.html:6 paw/templates/dashboard_base.html:49 34 + msgid "Settings" 35 + msgstr "Paramètres" 36 + 37 + #: paw/templates/core/settings.html:11 38 + msgid "Mail Address" 39 + msgstr "Adresse e-mail" 40 + 41 + #: paw/templates/core/settings.html:18 42 + msgid "Language" 43 + msgstr "Langue" 44 + 45 + #: paw/templates/core/settings.html:25 46 + msgid "Profile Picture" 47 + msgstr "Image du profil" 48 + 49 + #: paw/templates/core/settings.html:30 50 + msgid "Contact" 51 + msgstr "" 52 + 53 + #: paw/templates/core/settings.html:36 54 + msgid "Save" 55 + msgstr "Enregistrer" 56 + 57 + #: paw/templates/dashboard_base.html:14 58 + #: paw/templates/ticketing/create_ticket.html:31 59 + msgid "Create Ticket" 60 + msgstr "Nouveau ticket" 61 + 62 + #: paw/templates/dashboard_base.html:18 63 + msgid "Tickets" 64 + msgstr "" 65 + 66 + #: paw/templates/dashboard_base.html:22 67 + msgid "History" 68 + msgstr "Historique" 69 + 70 + #: paw/templates/dashboard_base.html:53 71 + msgid "Logout" 72 + msgstr "Se déconnecter" 73 + 74 + #: paw/templates/partials/assigned_to.html:11 75 + #: paw/templates/ticketing/ticket_detail.html:104 76 + #: paw/templates/ticketing/ticket_detail.html:134 77 + msgid "Unassigned" 78 + msgstr "Non attribué" 79 + 80 + #: paw/templates/partials/ticket_status_badge.html:4 ticketing/models.py:30 81 + msgid "Open" 82 + msgstr "Ouvert" 83 + 84 + #: paw/templates/partials/ticket_status_badge.html:6 ticketing/models.py:31 85 + msgid "In Progress" 86 + msgstr "En cours" 87 + 88 + #: paw/templates/partials/ticket_status_badge.html:8 ticketing/models.py:32 89 + msgid "Closed" 90 + msgstr "Fermé" 91 + 92 + #: paw/templates/ticketing/create_ticket.html:5 93 + msgid "Create a new ticket" 94 + msgstr "Créer un ticket" 95 + 96 + #: paw/templates/ticketing/create_ticket.html:12 97 + #: paw/templates/ticketing/tickets.html:17 98 + msgid "Title" 99 + msgstr "Titre" 100 + 101 + #: paw/templates/ticketing/create_ticket.html:19 102 + msgid "Description" 103 + msgstr "Description" 104 + 105 + #: paw/templates/ticketing/create_ticket.html:26 106 + #: paw/templates/ticketing/ticket_detail.html:98 107 + #: paw/templates/ticketing/tickets.html:19 108 + msgid "Category" 109 + msgstr "Catégorie" 110 + 111 + #: paw/templates/ticketing/ticket_detail.html:56 112 + msgid "Add Comment" 113 + msgstr "Ajouter un commentaire" 114 + 115 + #: paw/templates/ticketing/ticket_detail.html:58 116 + msgid "Comment and close" 117 + msgstr "Commentaire et fermer" 118 + 119 + #: paw/templates/ticketing/ticket_detail.html:68 120 + msgid "Re-Open Ticket" 121 + msgstr "Réouverture du ticket" 122 + 123 + #: paw/templates/ticketing/ticket_detail.html:110 124 + #, fuzzy 125 + #| msgid "Assign to me" 126 + msgid "Assign to new category" 127 + msgstr "Me l'attribuer" 128 + 129 + #: paw/templates/ticketing/ticket_detail.html:125 130 + msgid "Assign to me" 131 + msgstr "Me l'attribuer" 132 + 133 + #: paw/templates/ticketing/tickets.html:5 134 + #, fuzzy 135 + #| msgid "Re-Open Ticket" 136 + msgid "Open Tickets" 137 + msgstr "Réouverture du ticket" 138 + 139 + #: paw/templates/ticketing/tickets.html:7 140 + msgid "for" 141 + msgstr "pour" 142 + 143 + #: paw/templates/ticketing/tickets.html:18 144 + #, fuzzy 145 + #| msgid "Assign to me" 146 + msgid "Assigned to" 147 + msgstr "Me l'attribuer" 148 + 149 + #: paw/templates/ticketing/tickets.html:20 150 + msgid "Status" 151 + msgstr "Statut" 152 + 153 + #: paw/templates/ticketing/tickets.html:27 154 + msgid "No tickets found" 155 + msgstr "Aucun ticket trouvé" 156 + 157 + #: paw/templates/ticketing/tickets.html:41 158 + msgid "View" 159 + msgstr "Ouvrir" 160 + 161 + #: ticketing/models.py:35 162 + msgid "Low" 163 + msgstr "" 164 + 165 + #: ticketing/models.py:36 166 + msgid "Medium" 167 + msgstr "" 168 + 169 + #: ticketing/models.py:37 170 + msgid "High" 171 + msgstr ""
+147
paw/settings.py
··· 1 + """ 2 + Django settings for paw project. 3 + 4 + Generated by 'django-admin startproject' using Django 5.0.3. 5 + 6 + For more information on this file, see 7 + https://docs.djangoproject.com/en/5.0/topics/settings/ 8 + 9 + For the full list of settings and their values, see 10 + https://docs.djangoproject.com/en/5.0/ref/settings/ 11 + """ 12 + 13 + from pathlib import Path 14 + from os import path 15 + from django.utils.translation import gettext_lazy as _ 16 + 17 + # Build paths inside the project like this: BASE_DIR / 'subdir'. 18 + BASE_DIR = Path(__file__).resolve().parent.parent 19 + 20 + 21 + # Quick-start development settings - unsuitable for production 22 + # See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ 23 + 24 + # SECURITY WARNING: keep the secret key used in production secret! 25 + SECRET_KEY = "django-insecure-d738_hvwfer!9$!h#wk%ynp-z8d0tlk*-et7d)kl9lygm(*0bx" 26 + 27 + # SECURITY WARNING: don't run with debug turned on in production! 28 + DEBUG = True 29 + 30 + ALLOWED_HOSTS = [] 31 + 32 + 33 + # Application definition 34 + 35 + INSTALLED_APPS = [ 36 + "core.apps.CoreConfig", 37 + "ticketing.apps.TicketingConfig", 38 + "django.contrib.admin", 39 + "django.contrib.auth", 40 + "django.contrib.contenttypes", 41 + "django.contrib.sessions", 42 + "django.contrib.messages", 43 + "django.contrib.staticfiles", 44 + "colorfield", 45 + ] 46 + 47 + AUTH_USER_MODEL = "core.PawUser" 48 + 49 + MIDDLEWARE = [ 50 + "django.middleware.security.SecurityMiddleware", 51 + "django.contrib.sessions.middleware.SessionMiddleware", 52 + "django.middleware.locale.LocaleMiddleware", 53 + "django.middleware.common.CommonMiddleware", 54 + "django.middleware.csrf.CsrfViewMiddleware", 55 + "django.contrib.auth.middleware.AuthenticationMiddleware", 56 + "django.contrib.messages.middleware.MessageMiddleware", 57 + "django.middleware.clickjacking.XFrameOptionsMiddleware", 58 + ] 59 + 60 + ROOT_URLCONF = "paw.urls" 61 + 62 + TEMPLATES = [ 63 + { 64 + "BACKEND": "django.template.backends.django.DjangoTemplates", 65 + "DIRS": [BASE_DIR / 'paw' / 'templates'], 66 + "APP_DIRS": True, 67 + "OPTIONS": { 68 + "context_processors": [ 69 + "django.template.context_processors.debug", 70 + "django.template.context_processors.request", 71 + "django.contrib.auth.context_processors.auth", 72 + "django.contrib.messages.context_processors.messages", 73 + 'paw.templatetags.context_processors.app_version', 74 + ], 75 + }, 76 + }, 77 + ] 78 + 79 + WSGI_APPLICATION = "paw.wsgi.application" 80 + 81 + 82 + # Database 83 + # https://docs.djangoproject.com/en/5.0/ref/settings/#databases 84 + 85 + DATABASES = { 86 + "default": { 87 + "ENGINE": "django.db.backends.sqlite3", 88 + "NAME": BASE_DIR / "db.sqlite3", 89 + } 90 + } 91 + 92 + 93 + # Password validation 94 + # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators 95 + 96 + AUTH_PASSWORD_VALIDATORS = [ 97 + { 98 + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 99 + }, 100 + { 101 + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 102 + }, 103 + { 104 + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 105 + }, 106 + { 107 + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 108 + }, 109 + ] 110 + 111 + 112 + # Internationalization 113 + # https://docs.djangoproject.com/en/5.0/topics/i18n/ 114 + 115 + LANGUAGE_CODE = "en" 116 + LANGUAGES = [ 117 + ("en", _("English")), 118 + ("fr", _("French")), 119 + ("de", _("German")), 120 + ] 121 + LOCALE_PATHS = [ 122 + path.join(BASE_DIR, 'paw', 'locale'), 123 + ] 124 + 125 + TIME_ZONE = "UTC" 126 + 127 + USE_I18N = True 128 + 129 + USE_TZ = True 130 + 131 + 132 + # Static files (CSS, JavaScript, Images) 133 + # https://docs.djangoproject.com/en/5.0/howto/static-files/ 134 + 135 + STATIC_URL = "/static/" 136 + # STATIC_ROOT = path.join(BASE_DIR, 'static') 137 + STATICFILES_DIRS = ( 138 + path.join(BASE_DIR, 'static/'), 139 + ) 140 + 141 + 142 + # Default primary key field type 143 + # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field 144 + 145 + DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 146 + 147 + LOGIN_REDIRECT_URL = "/tickets"
+17
paw/templates/base.html
··· 1 + <!DOCTYPE html> 2 + {% load static %} 3 + <html lang="en"> 4 + <head> 5 + <meta charset="UTF-8"> 6 + <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 + <link href="{% static 'css/paw.css' %}?v={{ website_version }}" rel="stylesheet"> 9 + <title>paw</title> 10 + </head> 11 + <body> 12 + 13 + {% block content %} 14 + {% endblock %} 15 + 16 + </body> 17 + </html>
+5
paw/templates/core/home.html
··· 1 + {% extends 'base.html' %} 2 + 3 + {% block content %} 4 + <h1>Helllloooooo!</h1> 5 + {% endblock content %}
+40
paw/templates/core/settings.html
··· 1 + <!-- templates/core/settings.html --> 2 + {% extends 'dashboard_base.html' %} 3 + {% block dashboard_content %} 4 + {% load i18n %} 5 + <div class="w-full max-w-4xl mx-auto p-8"> 6 + <h1 class="text-2xl font-bold mb-4">{% trans 'Settings' %}</h1> 7 + <form method="post"> 8 + {% csrf_token %} 9 + <label class="form-control w-full mb-2"> 10 + <div class="label"> 11 + <span for="{{ form.email.id_for_label }}" class="label-text font-semibold text-base-content">{% trans 'Mail Address' %}</span> 12 + </div> 13 + {{ form.email }} 14 + </label> 15 + 16 + <label class="form-control w-full mb-2"> 17 + <div class="label"> 18 + <span for="{{ form.language.id_for_label }}" class="label-text font-semibold text-base-content">{% trans 'Language' %}</span> 19 + </div> 20 + {{ form.language }} 21 + </label> 22 + 23 + <label class="form-control w-full mb-2"> 24 + <div class="label"> 25 + <span for="{{ form.profile_picture.id_for_label }}" class="label-text font-semibold text-base-content">{% trans 'Profile Picture' %}</span> 26 + </div> 27 + {{ form.profile_picture }} 28 + </label> 29 + 30 + <h2 class="text-xl font-semibold mt-8 mb-2">{% trans 'Contact' %}</h2> 31 + <label class="input input-bordered flex items-center gap-2"> 32 + <svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 opacity-70" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 10l-4 4l6 6l4 -16l-18 7l4 2l2 6l3 -4" /></svg> 33 + {{ form.telegram_username }} 34 + </label> 35 + <div class="flex justify-end items-center mt-4"> 36 + <button type="submit" class="btn btn-success">{% trans 'Save' %}</button> 37 + </div> 38 + </form> 39 + </div> 40 + {% endblock %}
+62
paw/templates/dashboard_base.html
··· 1 + {% extends 'base.html' %} 2 + {% block content %} 3 + {% load i18n %} 4 + <div class="flex h-full min-h-screen"> 5 + <div class="flex-none w-20 lg:w-72 fixed h-full bg-neutral text-neutral-content p-4 overflow-y-auto"> 6 + <div class="flex flex-col h-full"> 7 + <div class="text-accent flex flex-row justify-center items-center mt-4 mb-10"> 8 + <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current h-12 w-12"viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 10c-1.32 0 -1.983 .421 -2.931 1.924l-.244 .398l-.395 .688a50.89 50.89 0 0 0 -.141 .254c-.24 .434 -.571 .753 -1.139 1.142l-.55 .365c-.94 .627 -1.432 1.118 -1.707 1.955c-.124 .338 -.196 .853 -.193 1.28c0 1.687 1.198 2.994 2.8 2.994l.242 -.006c.119 -.006 .234 -.017 .354 -.034l.248 -.043l.132 -.028l.291 -.073l.162 -.045l.57 -.17l.763 -.243l.455 -.136c.53 -.15 .94 -.222 1.283 -.222c.344 0 .753 .073 1.283 .222l.455 .136l.764 .242l.569 .171l.312 .084c.097 .024 .187 .045 .273 .062l.248 .043c.12 .017 .235 .028 .354 .034l.242 .006c1.602 0 2.8 -1.307 2.8 -3c0 -.427 -.073 -.939 -.207 -1.306c-.236 -.724 -.677 -1.223 -1.48 -1.83l-.257 -.19l-.528 -.38c-.642 -.47 -1.003 -.826 -1.253 -1.278l-.27 -.485l-.252 -.432c-1.011 -1.696 -1.618 -2.099 -3.053 -2.099z" stroke-width="0" fill="currentColor" /><path d="M19.78 7h-.03c-1.219 .02 -2.35 1.066 -2.908 2.504c-.69 1.775 -.348 3.72 1.075 4.333c.256 .109 .527 .163 .801 .163c1.231 0 2.38 -1.053 2.943 -2.504c.686 -1.774 .34 -3.72 -1.076 -4.332a2.05 2.05 0 0 0 -.804 -.164z" stroke-width="0" fill="currentColor" /><path d="M9.025 3c-.112 0 -.185 .002 -.27 .015l-.093 .016c-1.532 .206 -2.397 1.989 -2.108 3.855c.272 1.725 1.462 3.114 2.92 3.114l.187 -.005a1.26 1.26 0 0 0 .084 -.01l.092 -.016c1.533 -.206 2.397 -1.989 2.108 -3.855c-.27 -1.727 -1.46 -3.114 -2.92 -3.114z" stroke-width="0" fill="currentColor" /><path d="M14.972 3c-1.459 0 -2.647 1.388 -2.916 3.113c-.29 1.867 .574 3.65 2.174 3.867c.103 .013 .2 .02 .296 .02c1.39 0 2.543 -1.265 2.877 -2.883l.041 -.23c.29 -1.867 -.574 -3.65 -2.174 -3.867a2.154 2.154 0 0 0 -.298 -.02z" stroke-width="0" fill="currentColor" /><path d="M4.217 7c-.274 0 -.544 .054 -.797 .161c-1.426 .615 -1.767 2.562 -1.078 4.335c.563 1.451 1.71 2.504 2.941 2.504c.274 0 .544 -.054 .797 -.161c1.426 -.615 1.767 -2.562 1.078 -4.335c-.563 -1.451 -1.71 -2.504 -2.941 -2.504z" stroke-width="0" fill="currentColor" /></svg> 9 + <span class="hidden lg:block text-4xl font-mono font-bold">paw</span> 10 + <span class="hidden lg:block badge badge-sm self-end">{{ app_version }}</span> 11 + </div> 12 + <a href="{% url 'create_ticket' %}" class="btn btn-ghost btn-square lg:w-full lg:p-4 lg:btn-lg lg:justify-start"> 13 + <svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" /><path d="M13.5 6.5l4 4" /></svg> 14 + <span class="hidden lg:block">{% trans 'Create Ticket' %}</span> 15 + </a> 16 + <a href="{% url 'all_tickets' %}" class="btn btn-ghost btn-square lg:w-full lg:p-4 lg:btn-lg lg:justify-start"> 17 + <svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 5l0 2" /><path d="M15 11l0 2" /><path d="M15 17l0 2" /><path d="M5 5h14a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-3a2 2 0 0 0 0 -4v-3a2 2 0 0 1 2 -2" /></svg> 18 + <span class="hidden lg:block">{% trans 'Tickets' %}</span> 19 + </a> 20 + <a href="{% url 'tickets_history' %}" class="btn btn-ghost btn-square lg:w-full lg:p-4 lg:btn-lg lg:justify-start"> 21 + <svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 4m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z" /><path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10" /><path d="M10 12l4 0" /></svg> 22 + <span class="hidden lg:block">{% trans 'History' %}</span> 23 + </a> 24 + 25 + <div class="flex-grow"></div> 26 + <div class="flex items-center py-2 lg:p-2 justify-center lg:justify-start"> 27 + <div class="avatar placeholder"> 28 + <div class="bg-base-300 text-base-content rounded-full w-10"> 29 + <span class="text-xl">{{ request.user.username|slice:":2" }}</span> 30 + </div> 31 + </div> 32 + <div class="hidden ml-2 text-neutral-content lg:flex flex-col p-1"> 33 + {{ request.user.username }} 34 + <span class="text-xs"> 35 + {% for group in request.user.groups.all %} 36 + {{ group.name }}{%if not forloop.last%},{%endif%} 37 + {% endfor %} 38 + </span> 39 + </div> 40 + </div> 41 + {% if user.is_superuser %} 42 + <a href="/admin" class="btn btn-ghost btn-square lg:w-full lg:px-3 lg:btn-sm lg:justify-start"> 43 + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 10a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M6 4v4" /><path d="M6 12v8" /><path d="M10 16a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M12 4v10" /><path d="M12 18v2" /><path d="M16 7a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M18 4v1" /><path d="M18 9v11" /></svg> 44 + <span class="hidden lg:block">Admin</span> 45 + </a> 46 + {% endif %} 47 + <a href="{% url 'settings' %}" class="btn btn-ghost btn-square lg:w-full lg:px-3 lg:btn-sm lg:justify-start"> 48 + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" /><path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" /></svg> 49 + <span class="hidden lg:block">{% trans 'Settings' %}</span> 50 + </a> 51 + <a href="{% url 'logout' %}" class="btn btn-error btn-square lg:w-full lg:px-3 lg:btn-sm lg:justify-start"> 52 + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M14 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2" /><path d="M9 12h12l-3 -3" /><path d="M18 15l3 -3" /></svg> 53 + <span class="hidden lg:block">{% trans 'Logout' %}</span> 54 + </a> 55 + </div> 56 + </div> 57 + <div class="flex-grow ml-20 lg:ml-72 overflow-y-auto"> 58 + {% block dashboard_content %} 59 + {% endblock %} 60 + </div> 61 + </div> 62 + {% endblock %}
+13
paw/templates/partials/assigned_to.html
··· 1 + {% block assigned_to %} 2 + {% load i18n %} 3 + {% if assigned_to %} 4 + <div class="avatar placeholder"> 5 + <div class="bg-base-300 text-base-content rounded-full w-6 mr-1"> 6 + <span class="text-xl">{{ assigned_to.username|slice:":2" }}</span> 7 + </div> 8 + </div> 9 + {{ assigned_to.username }} 10 + {% else %} 11 + <span class="italic">{% trans 'Unassigned' %}</span> 12 + {% endif %} 13 + {% endblock %}
+9
paw/templates/partials/ticket_priority_badge.html
··· 1 + {% block ticket_priority_badge %} 2 + {% if ticket.priority == 3 %} 3 + <span class="badge badge-success join-item">Low</span> 4 + {% elif ticket.priority == 2 %} 5 + <span class="badge badge-warning join-item">Medium</span> 6 + {% else %} 7 + <span class="badge badge-error join-item">High</span> 8 + {% endif %} 9 + {% endblock %}
+10
paw/templates/partials/ticket_status_badge.html
··· 1 + {% block ticket_status_badge %} 2 + {% load i18n %} 3 + {% if ticket.status == 'open' %} 4 + <span class="badge badge-success join-item">{% trans 'Open' %}</span> 5 + {% elif ticket.status == 'in_progress' %} 6 + <span class="badge badge-warning join-item">{% trans 'In Progress' %}</span> 7 + {% else %} 8 + <span class="badge badge-error join-item">{% trans 'Closed' %}</span> 9 + {% endif %} 10 + {% endblock %}
+10
paw/templates/placeholder.html
··· 1 + <textarea class="textarea textarea-bordered h-32 h-15 w-full"></textarea> 2 + <input type="text" class="input input-bordered w-full" /> 3 + <select class="select select-bordered w-full"> 4 + <option>---</option> 5 + </select> 6 + <select class="select select-sm select-bordered"> 7 + <option>None</option> 8 + </select> 9 + <input type="file" class="file-input file-input-bordered w-full max-w-xs" /> 10 + <input type="text" class="grow" placeholder="Username" />
+30
paw/templates/registration/login.html
··· 1 + <!-- templates/registration/login.html --> 2 + {% extends 'base.html' %} 3 + {% block content %} 4 + <div class="flex flex-col w-full max-w-xl mx-auto h-full min-h-screen justify-center"> 5 + <div class=""> 6 + <h1 class="text-3xl font-bold p-2">Log In</h1> 7 + <div class="bg-base-300 rounded p-8"> 8 + <form method="post"> 9 + {% csrf_token %} 10 + <div> 11 + <label class="label"> 12 + <span class="text-base label-text" for="{{ form.username.id_for_label }}">Username</span> 13 + </label> 14 + <input type="text" name="username" placeholder="Username" class="w-full input input-bordered input-primary" /> 15 + </div> 16 + <div> 17 + <label class="label"> 18 + <span class="text-base label-text" for="{{ form.password.id_for_label }}">Password</span> 19 + </label> 20 + <input type="password" name="password" placeholder="Enter Password" 21 + class="w-full input input-bordered input-primary" /> 22 + </div> 23 + <div class="flex justify-end mt-4"> 24 + <button type="submit" class="btn btn-accent">Log In</button> 25 + </div> 26 + </form> 27 + </div> 28 + </div> 29 + </div> 30 + {% endblock %}
+35
paw/templates/ticketing/create_ticket.html
··· 1 + {% extends 'dashboard_base.html' %} 2 + {% block dashboard_content %} 3 + {% load i18n %} 4 + <div class="w-full max-w-4xl mx-auto p-8"> 5 + <h1 class="text-2xl font-bold mb-4">{% trans 'Create a new ticket' %}</h1> 6 + <form action="" method="post"> 7 + {% csrf_token %} 8 + {{ form.non_field_errors }} 9 + <label class="form-control mb-2"> 10 + {{ form.title.errors }} 11 + <div class="label"> 12 + <span for="{{ form.title.id_for_label }}" class="label-text font-semibold text-base-content">{% trans 'Title' %}</span> 13 + </div> 14 + {{ form.title }} 15 + </label> 16 + <label class="form-control mb-2"> 17 + {{ form.description.errors }} 18 + <div class="label"> 19 + <span for="{{ form.description.id_for_label }}" class="label-text font-semibold text-base-content">{% trans 'Description' %}</span> 20 + </div> 21 + {{ form.description }} 22 + </label> 23 + <label class="form-control mb-2"> 24 + {{ form.category.errors }} 25 + <div class="label"> 26 + <span for="{{ form.category.id_for_label }}" class="label-text font-semibold text-base-content">{% trans 'Category' %}</span> 27 + </div> 28 + {{ form.category }} 29 + </label> 30 + <div class="flex justify-end items-center mt-4"> 31 + <button type="submit" class="btn btn-success">{% trans 'Create Ticket' %}</button> 32 + </div> 33 + </form> 34 + </div> 35 + {% endblock %}
+55
paw/templates/ticketing/dashboard.html
··· 1 + {% extends 'dashboard_base.html' %} 2 + {% block dashboard_content %} 3 + <div class="w-full p-8"> 4 + <div class="stats bg-base-200 mb-10"> 5 + <div class="stat"> 6 + <div class="stat-figure text-success"> 7 + <svg xmlns="http://www.w3.org/2000/svg" class="inline-block w-10 h-10 stroke-current" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M14 3v4a1 1 0 0 0 1 1h4" /><path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" /><path d="M12 11l0 6" /><path d="M9 14l6 0" /></svg> 8 + </div> 9 + <div class="stat-title">Open Tickets</div> 10 + <div class="stat-value">{{ open_tickets.count }}</div> 11 + </div> 12 + 13 + <div class="stat"> 14 + <div class="stat-figure text-warning"> 15 + <svg xmlns="http://www.w3.org/2000/svg" class="inline-block w-10 h-10 stroke-current" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M14 3v4a1 1 0 0 0 1 1h4" /><path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" /><path d="M12 17v.01" /><path d="M12 14a1.5 1.5 0 1 0 -1.14 -2.474" /></svg> 16 + </div> 17 + <div class="stat-title">Progressing Tickets</div> 18 + <div class="stat-value">{{ in_progress_tickets.count }}</div> 19 + </div> 20 + 21 + <div class="stat"> 22 + <div class="stat-figure text-error"> 23 + <svg xmlns="http://www.w3.org/2000/svg" class="inline-block w-10 h-10 stroke-current" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M14 3v4a1 1 0 0 0 1 1h4" /><path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2zm-7 -7h.01m3.99 0h.01" /><path d="M10 17a3.5 3.5 0 0 0 4 0" /></svg> 24 + </div> 25 + <div class="stat-title">Completed Tickets</div> 26 + <div class="stat-value">{{ closed_tickets.count }}</div> 27 + </div> 28 + </div> 29 + 30 + <table class="table w-full"> 31 + <thead> 32 + <tr> 33 + <th></th> 34 + <th>Title</th> 35 + <th>Category</th> 36 + <th>Status</th> 37 + <th></th> 38 + </tr> 39 + </thead> 40 + <tbody> 41 + {% for ticket in tickets %} 42 + <tr> 43 + <td>#{{ ticket.id }}</td> 44 + <td>{{ ticket.title }}</td> 45 + <td><div class="badge badge-neutral">{{ ticket.category }}</div></td> 46 + <td> 47 + {% include 'partials/ticket_status_badge.html' with ticket=ticket %} 48 + </td> 49 + <td><a href="{% url 'ticket_detail' ticket.id %}" class="btn btn-xs btn-accent">View</a></td> 50 + </tr> 51 + {% endfor %} 52 + </tbody> 53 + </table> 54 + </div> 55 + {% endblock %}
+162
paw/templates/ticketing/ticket_detail.html
··· 1 + {% extends 'dashboard_base.html' %} 2 + {% block dashboard_content %} 3 + {% load i18n %} 4 + <div class="flex flex-col lg:flex-row w-full h-full"> 5 + <div class="flex-grow p-8"> 6 + <h1 class="text-2xl font-bold mb-4">{{ ticket.title }}</h1> 7 + <div class="card bg-base-300 rounded-box p-4 mb-6 whitespace-pre-line">{{ ticket.description }}</div> 8 + <h1 class="text-xl font-bold mb-4">Activity</h1> 9 + <div class="mb-4"> 10 + {% for comment in comments %} 11 + {% if not comment.is_only_for_staff or comment.is_only_for_staff and request.user.is_staff %} 12 + {% if comment.user == request.user %} 13 + <div class="chat chat-start"> 14 + {% else %} 15 + <div class="chat chat-end"> 16 + {% endif %} 17 + <div class="chat-header"> 18 + {{ comment.user.username }} 19 + <time class="text-xs opacity-50">{{ comment.created_at|date:"d.m.y" }}</time> 20 + </div> 21 + <div class="chat-bubble whitespace-pre-line">{{ comment.text }}</div> 22 + </div> 23 + {% endif %} 24 + {% endfor %} 25 + </div> 26 + <div class="mb-10"> 27 + {% if ticket.status != 'closed' %} 28 + {% if request.user.is_staff %} 29 + <form action="" method="post"> 30 + {% csrf_token %} 31 + <div class="flex justify-end items-center mt-4 mb-2"> 32 + <div class="form-control w-full max-w-xs"> 33 + {{ template_form.template_select }} 34 + </div> 35 + <button type="submit" name="apply_template" class="btn btn-sm btn-success ml-2">Apply Template</button> 36 + </div> 37 + </form> 38 + {% endif %} 39 + <form action="" method="post"> 40 + {% csrf_token %} 41 + {{ form.non_field_errors }} 42 + 43 + <label class="form-control"> 44 + {{ form.text.errors }} 45 + {{ form.text }} 46 + </label> 47 + <div class="flex justify-end items-center mt-4"> 48 + {% if request.user.is_staff %} 49 + <div class="form-control w-52 mr-4"> 50 + <label for="{{ form.hidden_from_client.id_for_label }}" class="cursor-pointer label"> 51 + <span class="label-text">Hidden from client</span> 52 + {{ form.hidden_from_client }} 53 + </label> 54 + </div> 55 + {% endif %} 56 + <button type="submit" name="submit" class="btn btn-success">{% trans 'Add Comment' %}</button> 57 + {% if request.user.is_staff %} 58 + <button type="submit" name="close" class="btn btn-error ml-4">{% trans 'Comment and close' %}</button> 59 + {% endif %} 60 + </div> 61 + </form> 62 + {% else %} 63 + <div class="divider">{% trans 'Ticket has been closed' %}</div> 64 + {% if request.user.is_staff and ticket.status == 'closed' %} 65 + <div class="flex justify-end items-center mt-4"> 66 + <form method="post"> 67 + {% csrf_token %} 68 + <button class="btn btn-warning ml-2" name="reopen_ticket">{% trans 'Re-Open Ticket' %}</button> 69 + </form> 70 + {% endif %} 71 + </div> 72 + {% endif %} 73 + </div> 74 + </div> 75 + 76 + <div class="order-first lg:order-none w-full lg:max-w-md border-l-2 border-base-300 bg-base-200 p-8"> 77 + <h1 class="text-xl font-bold">Ticket #{{ ticket.id }}</h1> 78 + <div class="text-neutral text-xs mb-4">{% trans 'Created by' %} {{ ticket.user.username }}</div> 79 + <div class="mb-4"> 80 + <div class="join"> 81 + <span class="badge badge-neutral join-item">Status</span> 82 + {% include 'partials/ticket_status_badge.html' with ticket=ticket %} 83 + </div> 84 + <div class="join"> 85 + <span class="badge badge-neutral join-item">Priority</span> 86 + {% include 'partials/ticket_priority_badge.html' with ticket=ticket %} 87 + </div> 88 + </div> 89 + <div class="my-4 text-neutral flex items-center text-sm font-semibold"> 90 + <svg xmlns="http://www.w3.org/2000/svg" class="mr-2 w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z" /><path d="M16 3l0 4" /><path d="M8 3l0 4" /><path d="M4 11l16 0" /><path d="M8 15h2v2h-2z" /></svg> 91 + {% trans 'Created on' %} {{ ticket.created_at }} 92 + </div> 93 + <div class="text-neutral flex items-center text-sm font-semibold"> 94 + <svg xmlns="http://www.w3.org/2000/svg" class="mr-2 w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z" /><path d="M16 3l0 4" /><path d="M8 3l0 4" /><path d="M4 11l16 0" /><path d="M8 15h2v2h-2z" /></svg> 95 + {% trans 'Last updated' %} {{ ticket.updated_at }} 96 + </div> 97 + 98 + <h2 class="font-semibold text-xs mt-4 mb-2">{% trans 'Contact' %}</h2> 99 + <div class="text-neutral flex items-center text-sm mb-1"> 100 + <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-10z" /><path d="M3 7l9 6l9 -6" /></svg> 101 + <a href="mailto:{{ ticket.user.email }}" class="ml-2 underline">{{ ticket.user.email }}</a> 102 + </div> 103 + {% if ticket.user.telegram_username %} 104 + <div class="text-neutral flex items-center text-sm mb-1"> 105 + <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 10l-4 4l6 6l4 -16l-18 7l4 2l2 6l3 -4" /></svg> 106 + <span class="ml-2">{{ ticket.user.telegram_username }}</span> 107 + </div> 108 + {% endif %} 109 + 110 + <div class="divider"></div> 111 + <h2 class="font-semibold mb-4">{% trans 'Category' %}</h2> 112 + <div class="text-neutral flex items-center text-sm mb-6"> 113 + <svg xmlns="http://www.w3.org/2000/svg" class="mr-2 w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 4h6v6h-6z" /><path d="M14 4h6v6h-6z" /><path d="M4 14h6v6h-6z" /><path d="M17 17m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" /></svg> 114 + {% if ticket.category %} 115 + {{ ticket.category.name }} 116 + {% else %} 117 + <span class="italic">{% trans 'Unassigned' %}</span> 118 + {% endif %} 119 + </div> 120 + {% if request.user.is_staff %} 121 + <form action="" method="post"> 122 + {% csrf_token %} 123 + <h2 class="font-semibold text-xs mb-2">{% trans 'Assign to new category' %}</h2> 124 + <div class="flex justify-end items-center mb-2"> 125 + {{ category_assignment_form.category_select }} 126 + <button type="submit" name="assign_to_category" class="btn btn-sm btn-neutral ml-2">Assign</button> 127 + </div> 128 + </form> 129 + {% endif %} 130 + <div class="divider"></div> 131 + <h2 class="font-semibold mb-4">Assignees</h2> 132 + <div class="text-neutral flex items-center text-sm mb-4"> 133 + <svg xmlns="http://www.w3.org/2000/svg" class="mr-2 w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" /><path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" /></svg> 134 + {% include 'partials/assigned_to.html' with assigned_to=ticket.assigned_to %} 135 + {% if request.user.is_staff and ticket.assigned_to != request.user %} 136 + <form method="post"> 137 + {% csrf_token %} 138 + <button class="btn btn-xs btn-neutral ml-2" name="assign_self">{% trans 'Assign to me' %}</button> 139 + </form> 140 + {% endif %} 141 + </div> 142 + <div class="text-neutral flex items-center text-sm mb-6"> 143 + <svg xmlns="http://www.w3.org/2000/svg" class="mr-2 w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" /><path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M17 10h2a2 2 0 0 1 2 2v1" /><path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M3 13v-1a2 2 0 0 1 2 -2h2" /></svg> 144 + {% if ticket.assigned_team %} 145 + {{ ticket.assigned_team.name }} 146 + {% else %} 147 + <span class="italic">{% trans 'Unassigned' %}</span> 148 + {% endif %} 149 + </div> 150 + {% if request.user.is_staff %} 151 + <form action="" method="post"> 152 + {% csrf_token %} 153 + <h2 class="font-semibold text-xs mb-2">Assign to new team</h2> 154 + <div class="flex justify-end items-center mb-2"> 155 + {{ team_assignment_form.team_select }} 156 + <button type="submit" name="assign_to_team" class="btn btn-sm btn-neutral ml-2">Assign</button> 157 + </div> 158 + </form> 159 + {% endif %} 160 + </div> 161 + </div> 162 + {% endblock dashboard_content %}
+47
paw/templates/ticketing/tickets.html
··· 1 + {% extends 'dashboard_base.html' %} 2 + {% block dashboard_content %} 3 + {% load i18n %} 4 + <div class="w-full p-8"> 5 + <h1 class="flex items-center text-2xl text-base-content font-bold mb-4">{% trans 'Open Tickets' %} 6 + {% if request.user.team_set.all %} 7 + {% trans 'for' %}: 8 + {% for team in request.user.team_set.all %} 9 + <span class="ml-2 badge badge-neutral">{{ team.name }}</span> 10 + {% endfor %} 11 + {% endif %} 12 + </h1> 13 + <table class="table w-full"> 14 + <thead> 15 + <tr> 16 + <th></th> 17 + <th>{% trans 'Title' %}</th> 18 + <th>{% trans 'Assigned to' %}</th> 19 + <th>{% trans 'Category' %}</th> 20 + <th>{% trans 'Status' %}</th> 21 + <th></th> 22 + </tr> 23 + </thead> 24 + <tbody> 25 + {% if tickets.count == 0 %} 26 + <tr> 27 + <td colspan="5" class="text-center p-10">{% trans 'No tickets found' %}</td> 28 + </tr> 29 + {% endif %} 30 + {% for ticket in tickets %} 31 + <tr> 32 + <td><span class="badge badge-neutral">#{{ ticket.id }}</span></td> 33 + <td>{{ ticket.title }}</td> 34 + <td> 35 + {% include 'partials/assigned_to.html' with assigned_to=ticket.assigned_to %} 36 + </td> 37 + <td><div class="badge badge-neutral">{{ ticket.category }}</div></td> 38 + <td class="w-48"> 39 + {% include 'partials/ticket_status_badge.html' with ticket=ticket %} 40 + </td> 41 + <td class="flex justify-end"><a href="{% url 'ticket_detail' ticket.id %}" class="btn btn-xs btn-accent">{% trans 'View' %}</a></td> 42 + </tr> 43 + {% endfor %} 44 + </tbody> 45 + </table> 46 + </div> 47 + {% endblock %}
+25
paw/templates/ticketing/tickets_history.html
··· 1 + {% extends 'dashboard_base.html' %} 2 + {% block dashboard_content %} 3 + <div class="w-full p-8"> 4 + <table class="table w-full"> 5 + <thead> 6 + <tr> 7 + <th></th> 8 + <th>Title</th> 9 + <th>Category</th> 10 + <th></th> 11 + </tr> 12 + </thead> 13 + <tbody> 14 + {% for ticket in tickets %} 15 + <tr> 16 + <td>#{{ ticket.id }}</td> 17 + <td>{{ ticket.title }}</td> 18 + <td><div class="badge badge-neutral">{{ ticket.category }}</div></td> 19 + <td class="flex justify-end"><a href="{% url 'ticket_detail' ticket.id %}" class="btn btn-xs btn-accent">View</a></td> 20 + </tr> 21 + {% endfor %} 22 + </tbody> 23 + </table> 24 + </div> 25 + {% endblock %}
+5
paw/templatetags/context_processors.py
··· 1 + from .. import __version__ 2 + 3 + 4 + def app_version(request): 5 + return {'app_version': __version__}
+28
paw/urls.py
··· 1 + """ 2 + URL configuration for paw project. 3 + 4 + The `urlpatterns` list routes URLs to views. For more information please see: 5 + https://docs.djangoproject.com/en/5.0/topics/http/urls/ 6 + Examples: 7 + Function views 8 + 1. Add an import: from my_app import views 9 + 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 + Class-based views 11 + 1. Add an import: from other_app.views import Home 12 + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 + Including another URLconf 14 + 1. Import the include() function: from django.urls import include, path 15 + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 + """ 17 + from django.conf import settings 18 + from django.contrib import admin 19 + from django.urls import path, include 20 + from django.conf.urls.static import static 21 + 22 + urlpatterns = [ 23 + path('i18n/', include('django.conf.urls.i18n')), 24 + path("admin/", admin.site.urls), 25 + path("accounts/", include("django.contrib.auth.urls")), 26 + path("", include("core.urls")), 27 + path("", include("ticketing.urls")), 28 + ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+16
paw/wsgi.py
··· 1 + """ 2 + WSGI config for paw project. 3 + 4 + It exposes the WSGI callable as a module-level variable named ``application``. 5 + 6 + For more information on this file, see 7 + https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 8 + """ 9 + 10 + import os 11 + 12 + from django.core.wsgi import get_wsgi_application 13 + 14 + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "paw.settings") 15 + 16 + application = get_wsgi_application()
+166
poetry.lock
··· 1 + # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. 2 + 3 + [[package]] 4 + name = "asgiref" 5 + version = "3.7.2" 6 + description = "ASGI specs, helper code, and adapters" 7 + optional = false 8 + python-versions = ">=3.7" 9 + files = [ 10 + {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, 11 + {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, 12 + ] 13 + 14 + [package.extras] 15 + tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] 16 + 17 + [[package]] 18 + name = "django" 19 + version = "5.0.3" 20 + description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." 21 + optional = false 22 + python-versions = ">=3.10" 23 + files = [ 24 + {file = "Django-5.0.3-py3-none-any.whl", hash = "sha256:5c7d748ad113a81b2d44750ccc41edc14e933f56581683db548c9257e078cc83"}, 25 + {file = "Django-5.0.3.tar.gz", hash = "sha256:5fb37580dcf4a262f9258c1f4373819aacca906431f505e4688e37f3a99195df"}, 26 + ] 27 + 28 + [package.dependencies] 29 + asgiref = ">=3.7.0,<4" 30 + sqlparse = ">=0.3.1" 31 + tzdata = {version = "*", markers = "sys_platform == \"win32\""} 32 + 33 + [package.extras] 34 + argon2 = ["argon2-cffi (>=19.1.0)"] 35 + bcrypt = ["bcrypt"] 36 + 37 + [[package]] 38 + name = "django-colorfield" 39 + version = "0.11.0" 40 + description = "color field for django models with a nice color-picker in the admin." 41 + optional = false 42 + python-versions = "*" 43 + files = [ 44 + {file = "django-colorfield-0.11.0.tar.gz", hash = "sha256:05c38c8eb2a94938b810a19b2011846391a4ce71d1c92e88a35974fbcc8fc62e"}, 45 + {file = "django_colorfield-0.11.0-py3-none-any.whl", hash = "sha256:460f40e6123b6ae0fb51a4eb86fc258fcdc0ea28f75102b685e8209b1eae9ec3"}, 46 + ] 47 + 48 + [package.dependencies] 49 + Pillow = ">=9.0.0" 50 + 51 + [[package]] 52 + name = "pillow" 53 + version = "10.2.0" 54 + description = "Python Imaging Library (Fork)" 55 + optional = false 56 + python-versions = ">=3.8" 57 + files = [ 58 + {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"}, 59 + {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"}, 60 + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"}, 61 + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"}, 62 + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"}, 63 + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"}, 64 + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"}, 65 + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"}, 66 + {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"}, 67 + {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"}, 68 + {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"}, 69 + {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"}, 70 + {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"}, 71 + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"}, 72 + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"}, 73 + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"}, 74 + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"}, 75 + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"}, 76 + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"}, 77 + {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"}, 78 + {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"}, 79 + {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"}, 80 + {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"}, 81 + {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"}, 82 + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"}, 83 + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"}, 84 + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"}, 85 + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"}, 86 + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"}, 87 + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"}, 88 + {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"}, 89 + {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"}, 90 + {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"}, 91 + {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"}, 92 + {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"}, 93 + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"}, 94 + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"}, 95 + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"}, 96 + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"}, 97 + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"}, 98 + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"}, 99 + {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"}, 100 + {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"}, 101 + {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"}, 102 + {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"}, 103 + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"}, 104 + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"}, 105 + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"}, 106 + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"}, 107 + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"}, 108 + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"}, 109 + {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"}, 110 + {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"}, 111 + {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"}, 112 + {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"}, 113 + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"}, 114 + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"}, 115 + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"}, 116 + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"}, 117 + {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"}, 118 + {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"}, 119 + {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"}, 120 + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"}, 121 + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"}, 122 + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"}, 123 + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"}, 124 + {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"}, 125 + {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"}, 126 + ] 127 + 128 + [package.extras] 129 + docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] 130 + fpx = ["olefile"] 131 + mic = ["olefile"] 132 + tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] 133 + typing = ["typing-extensions"] 134 + xmp = ["defusedxml"] 135 + 136 + [[package]] 137 + name = "sqlparse" 138 + version = "0.4.4" 139 + description = "A non-validating SQL parser." 140 + optional = false 141 + python-versions = ">=3.5" 142 + files = [ 143 + {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"}, 144 + {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"}, 145 + ] 146 + 147 + [package.extras] 148 + dev = ["build", "flake8"] 149 + doc = ["sphinx"] 150 + test = ["pytest", "pytest-cov"] 151 + 152 + [[package]] 153 + name = "tzdata" 154 + version = "2024.1" 155 + description = "Provider of IANA time zone data" 156 + optional = false 157 + python-versions = ">=2" 158 + files = [ 159 + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, 160 + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, 161 + ] 162 + 163 + [metadata] 164 + lock-version = "2.0" 165 + python-versions = "^3.12" 166 + content-hash = "b6020615bc7ed46644a57c2e13c1789753c19e0518c44b4b92ebc918d03f802c"
+17
pyproject.toml
··· 1 + [tool.poetry] 2 + name = "paw" 3 + version = "0.1.0" 4 + description = "" 5 + authors = ["Alex Ottr <alex@otter.foo>"] 6 + license = "MIT" 7 + readme = "README.md" 8 + 9 + [tool.poetry.dependencies] 10 + python = "^3.12" 11 + Django = "^5.0.3" 12 + django-colorfield = "^0.11.0" 13 + 14 + 15 + [build-system] 16 + requires = ["poetry-core"] 17 + build-backend = "poetry.core.masonry.api"
+3846
static/css/paw.css
··· 1 + /* 2 + ! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com 3 + */ 4 + 5 + /* 6 + 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) 7 + 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) 8 + */ 9 + 10 + *, 11 + ::before, 12 + ::after { 13 + box-sizing: border-box; 14 + /* 1 */ 15 + border-width: 0; 16 + /* 2 */ 17 + border-style: solid; 18 + /* 2 */ 19 + border-color: #e5e7eb; 20 + /* 2 */ 21 + } 22 + 23 + ::before, 24 + ::after { 25 + --tw-content: ''; 26 + } 27 + 28 + /* 29 + 1. Use a consistent sensible line-height in all browsers. 30 + 2. Prevent adjustments of font size after orientation changes in iOS. 31 + 3. Use a more readable tab size. 32 + 4. Use the user's configured `sans` font-family by default. 33 + 5. Use the user's configured `sans` font-feature-settings by default. 34 + 6. Use the user's configured `sans` font-variation-settings by default. 35 + 7. Disable tap highlights on iOS 36 + */ 37 + 38 + html, 39 + :host { 40 + line-height: 1.5; 41 + /* 1 */ 42 + -webkit-text-size-adjust: 100%; 43 + /* 2 */ 44 + -moz-tab-size: 4; 45 + /* 3 */ 46 + -o-tab-size: 4; 47 + tab-size: 4; 48 + /* 3 */ 49 + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 50 + /* 4 */ 51 + font-feature-settings: normal; 52 + /* 5 */ 53 + font-variation-settings: normal; 54 + /* 6 */ 55 + -webkit-tap-highlight-color: transparent; 56 + /* 7 */ 57 + } 58 + 59 + /* 60 + 1. Remove the margin in all browsers. 61 + 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. 62 + */ 63 + 64 + body { 65 + margin: 0; 66 + /* 1 */ 67 + line-height: inherit; 68 + /* 2 */ 69 + } 70 + 71 + /* 72 + 1. Add the correct height in Firefox. 73 + 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) 74 + 3. Ensure horizontal rules are visible by default. 75 + */ 76 + 77 + hr { 78 + height: 0; 79 + /* 1 */ 80 + color: inherit; 81 + /* 2 */ 82 + border-top-width: 1px; 83 + /* 3 */ 84 + } 85 + 86 + /* 87 + Add the correct text decoration in Chrome, Edge, and Safari. 88 + */ 89 + 90 + abbr:where([title]) { 91 + -webkit-text-decoration: underline dotted; 92 + text-decoration: underline dotted; 93 + } 94 + 95 + /* 96 + Remove the default font size and weight for headings. 97 + */ 98 + 99 + h1, 100 + h2, 101 + h3, 102 + h4, 103 + h5, 104 + h6 { 105 + font-size: inherit; 106 + font-weight: inherit; 107 + } 108 + 109 + /* 110 + Reset links to optimize for opt-in styling instead of opt-out. 111 + */ 112 + 113 + a { 114 + color: inherit; 115 + text-decoration: inherit; 116 + } 117 + 118 + /* 119 + Add the correct font weight in Edge and Safari. 120 + */ 121 + 122 + b, 123 + strong { 124 + font-weight: bolder; 125 + } 126 + 127 + /* 128 + 1. Use the user's configured `mono` font-family by default. 129 + 2. Use the user's configured `mono` font-feature-settings by default. 130 + 3. Use the user's configured `mono` font-variation-settings by default. 131 + 4. Correct the odd `em` font sizing in all browsers. 132 + */ 133 + 134 + code, 135 + kbd, 136 + samp, 137 + pre { 138 + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 139 + /* 1 */ 140 + font-feature-settings: normal; 141 + /* 2 */ 142 + font-variation-settings: normal; 143 + /* 3 */ 144 + font-size: 1em; 145 + /* 4 */ 146 + } 147 + 148 + /* 149 + Add the correct font size in all browsers. 150 + */ 151 + 152 + small { 153 + font-size: 80%; 154 + } 155 + 156 + /* 157 + Prevent `sub` and `sup` elements from affecting the line height in all browsers. 158 + */ 159 + 160 + sub, 161 + sup { 162 + font-size: 75%; 163 + line-height: 0; 164 + position: relative; 165 + vertical-align: baseline; 166 + } 167 + 168 + sub { 169 + bottom: -0.25em; 170 + } 171 + 172 + sup { 173 + top: -0.5em; 174 + } 175 + 176 + /* 177 + 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) 178 + 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) 179 + 3. Remove gaps between table borders by default. 180 + */ 181 + 182 + table { 183 + text-indent: 0; 184 + /* 1 */ 185 + border-color: inherit; 186 + /* 2 */ 187 + border-collapse: collapse; 188 + /* 3 */ 189 + } 190 + 191 + /* 192 + 1. Change the font styles in all browsers. 193 + 2. Remove the margin in Firefox and Safari. 194 + 3. Remove default padding in all browsers. 195 + */ 196 + 197 + button, 198 + input, 199 + optgroup, 200 + select, 201 + textarea { 202 + font-family: inherit; 203 + /* 1 */ 204 + font-feature-settings: inherit; 205 + /* 1 */ 206 + font-variation-settings: inherit; 207 + /* 1 */ 208 + font-size: 100%; 209 + /* 1 */ 210 + font-weight: inherit; 211 + /* 1 */ 212 + line-height: inherit; 213 + /* 1 */ 214 + color: inherit; 215 + /* 1 */ 216 + margin: 0; 217 + /* 2 */ 218 + padding: 0; 219 + /* 3 */ 220 + } 221 + 222 + /* 223 + Remove the inheritance of text transform in Edge and Firefox. 224 + */ 225 + 226 + button, 227 + select { 228 + text-transform: none; 229 + } 230 + 231 + /* 232 + 1. Correct the inability to style clickable types in iOS and Safari. 233 + 2. Remove default button styles. 234 + */ 235 + 236 + button, 237 + [type='button'], 238 + [type='reset'], 239 + [type='submit'] { 240 + -webkit-appearance: button; 241 + /* 1 */ 242 + background-color: transparent; 243 + /* 2 */ 244 + background-image: none; 245 + /* 2 */ 246 + } 247 + 248 + /* 249 + Use the modern Firefox focus style for all focusable elements. 250 + */ 251 + 252 + :-moz-focusring { 253 + outline: auto; 254 + } 255 + 256 + /* 257 + Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) 258 + */ 259 + 260 + :-moz-ui-invalid { 261 + box-shadow: none; 262 + } 263 + 264 + /* 265 + Add the correct vertical alignment in Chrome and Firefox. 266 + */ 267 + 268 + progress { 269 + vertical-align: baseline; 270 + } 271 + 272 + /* 273 + Correct the cursor style of increment and decrement buttons in Safari. 274 + */ 275 + 276 + ::-webkit-inner-spin-button, 277 + ::-webkit-outer-spin-button { 278 + height: auto; 279 + } 280 + 281 + /* 282 + 1. Correct the odd appearance in Chrome and Safari. 283 + 2. Correct the outline style in Safari. 284 + */ 285 + 286 + [type='search'] { 287 + -webkit-appearance: textfield; 288 + /* 1 */ 289 + outline-offset: -2px; 290 + /* 2 */ 291 + } 292 + 293 + /* 294 + Remove the inner padding in Chrome and Safari on macOS. 295 + */ 296 + 297 + ::-webkit-search-decoration { 298 + -webkit-appearance: none; 299 + } 300 + 301 + /* 302 + 1. Correct the inability to style clickable types in iOS and Safari. 303 + 2. Change font properties to `inherit` in Safari. 304 + */ 305 + 306 + ::-webkit-file-upload-button { 307 + -webkit-appearance: button; 308 + /* 1 */ 309 + font: inherit; 310 + /* 2 */ 311 + } 312 + 313 + /* 314 + Add the correct display in Chrome and Safari. 315 + */ 316 + 317 + summary { 318 + display: list-item; 319 + } 320 + 321 + /* 322 + Removes the default spacing and border for appropriate elements. 323 + */ 324 + 325 + blockquote, 326 + dl, 327 + dd, 328 + h1, 329 + h2, 330 + h3, 331 + h4, 332 + h5, 333 + h6, 334 + hr, 335 + figure, 336 + p, 337 + pre { 338 + margin: 0; 339 + } 340 + 341 + fieldset { 342 + margin: 0; 343 + padding: 0; 344 + } 345 + 346 + legend { 347 + padding: 0; 348 + } 349 + 350 + ol, 351 + ul, 352 + menu { 353 + list-style: none; 354 + margin: 0; 355 + padding: 0; 356 + } 357 + 358 + /* 359 + Reset default styling for dialogs. 360 + */ 361 + 362 + dialog { 363 + padding: 0; 364 + } 365 + 366 + /* 367 + Prevent resizing textareas horizontally by default. 368 + */ 369 + 370 + textarea { 371 + resize: vertical; 372 + } 373 + 374 + /* 375 + 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) 376 + 2. Set the default placeholder color to the user's configured gray 400 color. 377 + */ 378 + 379 + input::-moz-placeholder, textarea::-moz-placeholder { 380 + opacity: 1; 381 + /* 1 */ 382 + color: #9ca3af; 383 + /* 2 */ 384 + } 385 + 386 + input::placeholder, 387 + textarea::placeholder { 388 + opacity: 1; 389 + /* 1 */ 390 + color: #9ca3af; 391 + /* 2 */ 392 + } 393 + 394 + /* 395 + Set the default cursor for buttons. 396 + */ 397 + 398 + button, 399 + [role="button"] { 400 + cursor: pointer; 401 + } 402 + 403 + /* 404 + Make sure disabled buttons don't get the pointer cursor. 405 + */ 406 + 407 + :disabled { 408 + cursor: default; 409 + } 410 + 411 + /* 412 + 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) 413 + 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) 414 + This can trigger a poorly considered lint error in some tools but is included by design. 415 + */ 416 + 417 + img, 418 + svg, 419 + video, 420 + canvas, 421 + audio, 422 + iframe, 423 + embed, 424 + object { 425 + display: block; 426 + /* 1 */ 427 + vertical-align: middle; 428 + /* 2 */ 429 + } 430 + 431 + /* 432 + Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) 433 + */ 434 + 435 + img, 436 + video { 437 + max-width: 100%; 438 + height: auto; 439 + } 440 + 441 + /* Make elements with the HTML hidden attribute stay hidden by default */ 442 + 443 + [hidden] { 444 + display: none; 445 + } 446 + 447 + :root, 448 + [data-theme] { 449 + background-color: var(--fallback-b1,oklch(var(--b1)/1)); 450 + color: var(--fallback-bc,oklch(var(--bc)/1)); 451 + } 452 + 453 + @supports not (color: oklch(0 0 0)) { 454 + :root { 455 + color-scheme: light; 456 + --fallback-p: #491eff; 457 + --fallback-pc: #d4dbff; 458 + --fallback-s: #ff41c7; 459 + --fallback-sc: #fff9fc; 460 + --fallback-a: #00cfbd; 461 + --fallback-ac: #00100d; 462 + --fallback-n: #2b3440; 463 + --fallback-nc: #d7dde4; 464 + --fallback-b1: #ffffff; 465 + --fallback-b2: #e5e6e6; 466 + --fallback-b3: #e5e6e6; 467 + --fallback-bc: #1f2937; 468 + --fallback-in: #00b3f0; 469 + --fallback-inc: #000000; 470 + --fallback-su: #00ca92; 471 + --fallback-suc: #000000; 472 + --fallback-wa: #ffc22d; 473 + --fallback-wac: #000000; 474 + --fallback-er: #ff6f70; 475 + --fallback-erc: #000000; 476 + } 477 + 478 + @media (prefers-color-scheme: dark) { 479 + :root { 480 + color-scheme: dark; 481 + --fallback-p: #7582ff; 482 + --fallback-pc: #050617; 483 + --fallback-s: #ff71cf; 484 + --fallback-sc: #190211; 485 + --fallback-a: #00c7b5; 486 + --fallback-ac: #000e0c; 487 + --fallback-n: #2a323c; 488 + --fallback-nc: #a6adbb; 489 + --fallback-b1: #1d232a; 490 + --fallback-b2: #191e24; 491 + --fallback-b3: #15191e; 492 + --fallback-bc: #a6adbb; 493 + --fallback-in: #00b3f0; 494 + --fallback-inc: #000000; 495 + --fallback-su: #00ca92; 496 + --fallback-suc: #000000; 497 + --fallback-wa: #ffc22d; 498 + --fallback-wac: #000000; 499 + --fallback-er: #ff6f70; 500 + --fallback-erc: #000000; 501 + } 502 + } 503 + } 504 + 505 + html { 506 + -webkit-tap-highlight-color: transparent; 507 + } 508 + 509 + :root { 510 + color-scheme: light; 511 + --pc: 0.118872 0.015449 254.027774; 512 + --sc: 0.139303 0.011822 248.687186; 513 + --ac: 0.154929 0.01245 217.469017; 514 + --inc: 0.138414 0.012499 332.664922; 515 + --suc: 0.153654 0.01498 131.063061; 516 + --wac: 0.170972 0.017847 84.093335; 517 + --erc: 0.12122 0.024119 15.341883; 518 + --animation-btn: 0.25s; 519 + --animation-input: .2s; 520 + --btn-focus-scale: 0.95; 521 + --border-btn: 1px; 522 + --tab-border: 1px; 523 + --p: 0.594359 0.077246 254.027774; 524 + --s: 0.696516 0.059108 248.687186; 525 + --a: 0.774643 0.062249 217.469017; 526 + --n: 0.45229 0.035214 264.1312; 527 + --nc: 0.899258 0.016374 262.749256; 528 + --b1: 0.951276 0.007445 260.731539; 529 + --b2: 0.932996 0.010389 261.788485; 530 + --b3: 0.899258 0.016374 262.749256; 531 + --bc: 0.324374 0.022945 264.182036; 532 + --in: 0.692072 0.062496 332.664922; 533 + --su: 0.76827 0.074899 131.063061; 534 + --wa: 0.854862 0.089234 84.093335; 535 + --er: 0.6061 0.120594 15.341883; 536 + --rounded-box: 0.4rem; 537 + --rounded-btn: 0.2rem; 538 + --rounded-badge: 0.4rem; 539 + --tab-radius: 0.2rem; 540 + } 541 + 542 + *, ::before, ::after { 543 + --tw-border-spacing-x: 0; 544 + --tw-border-spacing-y: 0; 545 + --tw-translate-x: 0; 546 + --tw-translate-y: 0; 547 + --tw-rotate: 0; 548 + --tw-skew-x: 0; 549 + --tw-skew-y: 0; 550 + --tw-scale-x: 1; 551 + --tw-scale-y: 1; 552 + --tw-pan-x: ; 553 + --tw-pan-y: ; 554 + --tw-pinch-zoom: ; 555 + --tw-scroll-snap-strictness: proximity; 556 + --tw-gradient-from-position: ; 557 + --tw-gradient-via-position: ; 558 + --tw-gradient-to-position: ; 559 + --tw-ordinal: ; 560 + --tw-slashed-zero: ; 561 + --tw-numeric-figure: ; 562 + --tw-numeric-spacing: ; 563 + --tw-numeric-fraction: ; 564 + --tw-ring-inset: ; 565 + --tw-ring-offset-width: 0px; 566 + --tw-ring-offset-color: #fff; 567 + --tw-ring-color: rgb(59 130 246 / 0.5); 568 + --tw-ring-offset-shadow: 0 0 #0000; 569 + --tw-ring-shadow: 0 0 #0000; 570 + --tw-shadow: 0 0 #0000; 571 + --tw-shadow-colored: 0 0 #0000; 572 + --tw-blur: ; 573 + --tw-brightness: ; 574 + --tw-contrast: ; 575 + --tw-grayscale: ; 576 + --tw-hue-rotate: ; 577 + --tw-invert: ; 578 + --tw-saturate: ; 579 + --tw-sepia: ; 580 + --tw-drop-shadow: ; 581 + --tw-backdrop-blur: ; 582 + --tw-backdrop-brightness: ; 583 + --tw-backdrop-contrast: ; 584 + --tw-backdrop-grayscale: ; 585 + --tw-backdrop-hue-rotate: ; 586 + --tw-backdrop-invert: ; 587 + --tw-backdrop-opacity: ; 588 + --tw-backdrop-saturate: ; 589 + --tw-backdrop-sepia: ; 590 + } 591 + 592 + ::backdrop { 593 + --tw-border-spacing-x: 0; 594 + --tw-border-spacing-y: 0; 595 + --tw-translate-x: 0; 596 + --tw-translate-y: 0; 597 + --tw-rotate: 0; 598 + --tw-skew-x: 0; 599 + --tw-skew-y: 0; 600 + --tw-scale-x: 1; 601 + --tw-scale-y: 1; 602 + --tw-pan-x: ; 603 + --tw-pan-y: ; 604 + --tw-pinch-zoom: ; 605 + --tw-scroll-snap-strictness: proximity; 606 + --tw-gradient-from-position: ; 607 + --tw-gradient-via-position: ; 608 + --tw-gradient-to-position: ; 609 + --tw-ordinal: ; 610 + --tw-slashed-zero: ; 611 + --tw-numeric-figure: ; 612 + --tw-numeric-spacing: ; 613 + --tw-numeric-fraction: ; 614 + --tw-ring-inset: ; 615 + --tw-ring-offset-width: 0px; 616 + --tw-ring-offset-color: #fff; 617 + --tw-ring-color: rgb(59 130 246 / 0.5); 618 + --tw-ring-offset-shadow: 0 0 #0000; 619 + --tw-ring-shadow: 0 0 #0000; 620 + --tw-shadow: 0 0 #0000; 621 + --tw-shadow-colored: 0 0 #0000; 622 + --tw-blur: ; 623 + --tw-brightness: ; 624 + --tw-contrast: ; 625 + --tw-grayscale: ; 626 + --tw-hue-rotate: ; 627 + --tw-invert: ; 628 + --tw-saturate: ; 629 + --tw-sepia: ; 630 + --tw-drop-shadow: ; 631 + --tw-backdrop-blur: ; 632 + --tw-backdrop-brightness: ; 633 + --tw-backdrop-contrast: ; 634 + --tw-backdrop-grayscale: ; 635 + --tw-backdrop-hue-rotate: ; 636 + --tw-backdrop-invert: ; 637 + --tw-backdrop-opacity: ; 638 + --tw-backdrop-saturate: ; 639 + --tw-backdrop-sepia: ; 640 + } 641 + 642 + .container { 643 + width: 100%; 644 + } 645 + 646 + @media (min-width: 640px) { 647 + .container { 648 + max-width: 640px; 649 + } 650 + } 651 + 652 + @media (min-width: 768px) { 653 + .container { 654 + max-width: 768px; 655 + } 656 + } 657 + 658 + @media (min-width: 1024px) { 659 + .container { 660 + max-width: 1024px; 661 + } 662 + } 663 + 664 + @media (min-width: 1280px) { 665 + .container { 666 + max-width: 1280px; 667 + } 668 + } 669 + 670 + @media (min-width: 1536px) { 671 + .container { 672 + max-width: 1536px; 673 + } 674 + } 675 + 676 + .alert { 677 + display: grid; 678 + width: 100%; 679 + grid-auto-flow: row; 680 + align-content: flex-start; 681 + align-items: center; 682 + justify-items: center; 683 + gap: 1rem; 684 + text-align: center; 685 + border-radius: var(--rounded-box, 1rem); 686 + border-width: 1px; 687 + --tw-border-opacity: 1; 688 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 689 + padding: 1rem; 690 + --tw-text-opacity: 1; 691 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 692 + --alert-bg: var(--fallback-b2,oklch(var(--b2)/1)); 693 + --alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1)); 694 + background-color: var(--alert-bg); 695 + } 696 + 697 + @media (min-width: 640px) { 698 + .alert { 699 + grid-auto-flow: column; 700 + grid-template-columns: auto minmax(auto,1fr); 701 + justify-items: start; 702 + text-align: start; 703 + } 704 + } 705 + 706 + .avatar { 707 + position: relative; 708 + display: inline-flex; 709 + } 710 + 711 + .avatar > div { 712 + display: block; 713 + aspect-ratio: 1 / 1; 714 + overflow: hidden; 715 + } 716 + 717 + .avatar img { 718 + height: 100%; 719 + width: 100%; 720 + -o-object-fit: cover; 721 + object-fit: cover; 722 + } 723 + 724 + .avatar.placeholder > div { 725 + display: flex; 726 + align-items: center; 727 + justify-content: center; 728 + } 729 + 730 + .badge { 731 + display: inline-flex; 732 + align-items: center; 733 + justify-content: center; 734 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; 735 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 736 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; 737 + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 738 + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 739 + transition-duration: 200ms; 740 + height: 1.25rem; 741 + font-size: 0.875rem; 742 + line-height: 1.25rem; 743 + width: -moz-fit-content; 744 + width: fit-content; 745 + padding-left: 0.563rem; 746 + padding-right: 0.563rem; 747 + border-radius: var(--rounded-badge, 1.9rem); 748 + border-width: 1px; 749 + --tw-border-opacity: 1; 750 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 751 + --tw-bg-opacity: 1; 752 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 753 + --tw-text-opacity: 1; 754 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 755 + } 756 + 757 + @media (hover:hover) { 758 + .label a:hover { 759 + --tw-text-opacity: 1; 760 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 761 + } 762 + 763 + .menu li > *:not(ul, .menu-title, details, .btn):active, 764 + .menu li > *:not(ul, .menu-title, details, .btn).active, 765 + .menu li > details > summary:active { 766 + --tw-bg-opacity: 1; 767 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 768 + --tw-text-opacity: 1; 769 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 770 + } 771 + 772 + .table tr.hover:hover, 773 + .table tr.hover:nth-child(even):hover { 774 + --tw-bg-opacity: 1; 775 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 776 + } 777 + } 778 + 779 + .btn { 780 + display: inline-flex; 781 + height: 3rem; 782 + min-height: 3rem; 783 + flex-shrink: 0; 784 + cursor: pointer; 785 + -webkit-user-select: none; 786 + -moz-user-select: none; 787 + user-select: none; 788 + flex-wrap: wrap; 789 + align-items: center; 790 + justify-content: center; 791 + border-radius: var(--rounded-btn, 0.5rem); 792 + border-color: transparent; 793 + border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity)); 794 + padding-left: 1rem; 795 + padding-right: 1rem; 796 + text-align: center; 797 + font-size: 0.875rem; 798 + line-height: 1em; 799 + gap: 0.5rem; 800 + font-weight: 600; 801 + text-decoration-line: none; 802 + transition-duration: 200ms; 803 + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 804 + border-width: var(--border-btn, 1px); 805 + animation: button-pop var(--animation-btn, 0.25s) ease-out; 806 + transition-property: color, background-color, border-color, opacity, box-shadow, transform; 807 + --tw-text-opacity: 1; 808 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 809 + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); 810 + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); 811 + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); 812 + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); 813 + background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity)); 814 + --tw-bg-opacity: 1; 815 + --tw-border-opacity: 1; 816 + } 817 + 818 + .btn-disabled, 819 + .btn[disabled], 820 + .btn:disabled { 821 + pointer-events: none; 822 + } 823 + 824 + .btn-square { 825 + height: 3rem; 826 + width: 3rem; 827 + padding: 0px; 828 + } 829 + 830 + :where(.btn:is(input[type="checkbox"])), 831 + :where(.btn:is(input[type="radio"])) { 832 + width: auto; 833 + -webkit-appearance: none; 834 + -moz-appearance: none; 835 + appearance: none; 836 + } 837 + 838 + .btn:is(input[type="checkbox"]):after, 839 + .btn:is(input[type="radio"]):after { 840 + --tw-content: attr(aria-label); 841 + content: var(--tw-content); 842 + } 843 + 844 + .card { 845 + position: relative; 846 + display: flex; 847 + flex-direction: column; 848 + border-radius: var(--rounded-box, 1rem); 849 + } 850 + 851 + .card:focus { 852 + outline: 2px solid transparent; 853 + outline-offset: 2px; 854 + } 855 + 856 + .card figure { 857 + display: flex; 858 + align-items: center; 859 + justify-content: center; 860 + } 861 + 862 + .card.image-full { 863 + display: grid; 864 + } 865 + 866 + .card.image-full:before { 867 + position: relative; 868 + content: ""; 869 + z-index: 10; 870 + border-radius: var(--rounded-box, 1rem); 871 + --tw-bg-opacity: 1; 872 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 873 + opacity: 0.75; 874 + } 875 + 876 + .card.image-full:before, 877 + .card.image-full > * { 878 + grid-column-start: 1; 879 + grid-row-start: 1; 880 + } 881 + 882 + .card.image-full > figure img { 883 + height: 100%; 884 + -o-object-fit: cover; 885 + object-fit: cover; 886 + } 887 + 888 + .card.image-full > .card-body { 889 + position: relative; 890 + z-index: 20; 891 + --tw-text-opacity: 1; 892 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 893 + } 894 + 895 + .chat { 896 + display: grid; 897 + grid-template-columns: repeat(2, minmax(0, 1fr)); 898 + -moz-column-gap: 0.75rem; 899 + column-gap: 0.75rem; 900 + padding-top: 0.25rem; 901 + padding-bottom: 0.25rem; 902 + } 903 + 904 + .chat-header { 905 + grid-row-start: 1; 906 + font-size: 0.875rem; 907 + line-height: 1.25rem; 908 + } 909 + 910 + .chat-footer { 911 + grid-row-start: 3; 912 + font-size: 0.875rem; 913 + line-height: 1.25rem; 914 + } 915 + 916 + .chat-bubble { 917 + position: relative; 918 + display: block; 919 + width: -moz-fit-content; 920 + width: fit-content; 921 + padding-left: 1rem; 922 + padding-right: 1rem; 923 + padding-top: 0.5rem; 924 + padding-bottom: 0.5rem; 925 + max-width: 90%; 926 + border-radius: var(--rounded-box, 1rem); 927 + min-height: 2.75rem; 928 + min-width: 2.75rem; 929 + --tw-bg-opacity: 1; 930 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 931 + --tw-text-opacity: 1; 932 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 933 + } 934 + 935 + .chat-bubble:before { 936 + position: absolute; 937 + bottom: 0px; 938 + height: 0.75rem; 939 + width: 0.75rem; 940 + background-color: inherit; 941 + content: ""; 942 + -webkit-mask-size: contain; 943 + mask-size: contain; 944 + -webkit-mask-repeat: no-repeat; 945 + mask-repeat: no-repeat; 946 + -webkit-mask-position: center; 947 + mask-position: center; 948 + } 949 + 950 + .chat-start { 951 + place-items: start; 952 + grid-template-columns: auto 1fr; 953 + } 954 + 955 + .chat-start .chat-header { 956 + grid-column-start: 2; 957 + } 958 + 959 + .chat-start .chat-footer { 960 + grid-column-start: 2; 961 + } 962 + 963 + .chat-start .chat-image { 964 + grid-column-start: 1; 965 + } 966 + 967 + .chat-start .chat-bubble { 968 + grid-column-start: 2; 969 + border-end-start-radius: 0px; 970 + } 971 + 972 + .chat-start .chat-bubble:before { 973 + -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e"); 974 + mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e"); 975 + inset-inline-start: -0.749rem; 976 + } 977 + 978 + [dir="rtl"] .chat-start .chat-bubble:before { 979 + -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e"); 980 + mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e"); 981 + } 982 + 983 + .chat-end { 984 + place-items: end; 985 + grid-template-columns: 1fr auto; 986 + } 987 + 988 + .chat-end .chat-header { 989 + grid-column-start: 1; 990 + } 991 + 992 + .chat-end .chat-footer { 993 + grid-column-start: 1; 994 + } 995 + 996 + .chat-end .chat-image { 997 + grid-column-start: 2; 998 + } 999 + 1000 + .chat-end .chat-bubble { 1001 + grid-column-start: 1; 1002 + border-end-end-radius: 0px; 1003 + } 1004 + 1005 + .chat-end .chat-bubble:before { 1006 + -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e"); 1007 + mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e"); 1008 + inset-inline-start: 99.9%; 1009 + } 1010 + 1011 + [dir="rtl"] .chat-end .chat-bubble:before { 1012 + -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e"); 1013 + mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e"); 1014 + } 1015 + 1016 + .checkbox { 1017 + flex-shrink: 0; 1018 + --chkbg: var(--fallback-bc,oklch(var(--bc)/1)); 1019 + --chkfg: var(--fallback-b1,oklch(var(--b1)/1)); 1020 + height: 1.5rem; 1021 + width: 1.5rem; 1022 + cursor: pointer; 1023 + -webkit-appearance: none; 1024 + -moz-appearance: none; 1025 + appearance: none; 1026 + border-radius: var(--rounded-btn, 0.5rem); 1027 + border-width: 1px; 1028 + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); 1029 + --tw-border-opacity: 0.2; 1030 + } 1031 + 1032 + .divider { 1033 + display: flex; 1034 + flex-direction: row; 1035 + align-items: center; 1036 + align-self: stretch; 1037 + margin-top: 1rem; 1038 + margin-bottom: 1rem; 1039 + height: 1rem; 1040 + white-space: nowrap; 1041 + } 1042 + 1043 + .divider:before, 1044 + .divider:after { 1045 + height: 0.125rem; 1046 + width: 100%; 1047 + flex-grow: 1; 1048 + --tw-content: ''; 1049 + content: var(--tw-content); 1050 + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); 1051 + } 1052 + 1053 + .drawer { 1054 + position: relative; 1055 + display: grid; 1056 + grid-auto-columns: max-content auto; 1057 + width: 100%; 1058 + } 1059 + 1060 + .drawer-content { 1061 + grid-column-start: 2; 1062 + grid-row-start: 1; 1063 + min-width: 0px; 1064 + } 1065 + 1066 + .drawer-side { 1067 + pointer-events: none; 1068 + position: fixed; 1069 + inset-inline-start: 0px; 1070 + top: 0px; 1071 + grid-column-start: 1; 1072 + grid-row-start: 1; 1073 + display: grid; 1074 + width: 100%; 1075 + grid-template-columns: repeat(1, minmax(0, 1fr)); 1076 + grid-template-rows: repeat(1, minmax(0, 1fr)); 1077 + align-items: flex-start; 1078 + justify-items: start; 1079 + overflow-x: hidden; 1080 + overflow-y: hidden; 1081 + overscroll-behavior: contain; 1082 + height: 100vh; 1083 + height: 100dvh; 1084 + } 1085 + 1086 + .drawer-side > .drawer-overlay { 1087 + position: sticky; 1088 + top: 0px; 1089 + place-self: stretch; 1090 + cursor: pointer; 1091 + background-color: transparent; 1092 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; 1093 + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1094 + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 1095 + transition-duration: 200ms; 1096 + } 1097 + 1098 + .drawer-side > * { 1099 + grid-column-start: 1; 1100 + grid-row-start: 1; 1101 + } 1102 + 1103 + .drawer-side > *:not(.drawer-overlay) { 1104 + transition-property: transform; 1105 + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1106 + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 1107 + transition-duration: 300ms; 1108 + will-change: transform; 1109 + transform: translateX(-100%); 1110 + } 1111 + 1112 + [dir="rtl"] .drawer-side > *:not(.drawer-overlay) { 1113 + transform: translateX(100%); 1114 + } 1115 + 1116 + .drawer-toggle { 1117 + position: fixed; 1118 + height: 0px; 1119 + width: 0px; 1120 + -webkit-appearance: none; 1121 + -moz-appearance: none; 1122 + appearance: none; 1123 + opacity: 0; 1124 + } 1125 + 1126 + .drawer-toggle:checked ~ .drawer-side { 1127 + pointer-events: auto; 1128 + visibility: visible; 1129 + overflow-y: auto; 1130 + } 1131 + 1132 + .drawer-toggle:checked ~ .drawer-side > *:not(.drawer-overlay) { 1133 + transform: translateX(0%); 1134 + } 1135 + 1136 + .drawer-end .drawer-toggle ~ .drawer-content { 1137 + grid-column-start: 1; 1138 + } 1139 + 1140 + .drawer-end .drawer-toggle ~ .drawer-side { 1141 + grid-column-start: 2; 1142 + justify-items: end; 1143 + } 1144 + 1145 + .drawer-end .drawer-toggle ~ .drawer-side > *:not(.drawer-overlay) { 1146 + transform: translateX(100%); 1147 + } 1148 + 1149 + [dir="rtl"] .drawer-end .drawer-toggle ~ .drawer-side > *:not(.drawer-overlay) { 1150 + transform: translateX(-100%); 1151 + } 1152 + 1153 + .drawer-end .drawer-toggle:checked ~ .drawer-side > *:not(.drawer-overlay) { 1154 + transform: translateX(0%); 1155 + } 1156 + 1157 + @media (hover: hover) { 1158 + .btm-nav > *.disabled:hover, 1159 + .btm-nav > *[disabled]:hover { 1160 + pointer-events: none; 1161 + --tw-border-opacity: 0; 1162 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 1163 + --tw-bg-opacity: 0.1; 1164 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 1165 + --tw-text-opacity: 0.2; 1166 + } 1167 + 1168 + .btn:hover { 1169 + --tw-border-opacity: 1; 1170 + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))); 1171 + --tw-bg-opacity: 1; 1172 + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); 1173 + } 1174 + 1175 + @supports (color: color-mix(in oklab, black, black)) { 1176 + .btn:hover { 1177 + background-color: color-mix( 1178 + in oklab, 1179 + oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%, 1180 + black 1181 + ); 1182 + border-color: color-mix( 1183 + in oklab, 1184 + oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%, 1185 + black 1186 + ); 1187 + } 1188 + } 1189 + 1190 + @supports not (color: oklch(0 0 0)) { 1191 + .btn:hover { 1192 + background-color: var(--btn-color, var(--fallback-b2)); 1193 + border-color: var(--btn-color, var(--fallback-b2)); 1194 + } 1195 + } 1196 + 1197 + .btn.glass:hover { 1198 + --glass-opacity: 25%; 1199 + --glass-border-opacity: 15%; 1200 + } 1201 + 1202 + .btn-ghost:hover { 1203 + border-color: transparent; 1204 + } 1205 + 1206 + @supports (color: oklch(0 0 0)) { 1207 + .btn-ghost:hover { 1208 + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 1209 + } 1210 + } 1211 + 1212 + .btn-outline.btn-primary:hover { 1213 + --tw-text-opacity: 1; 1214 + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); 1215 + } 1216 + 1217 + @supports (color: color-mix(in oklab, black, black)) { 1218 + .btn-outline.btn-primary:hover { 1219 + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); 1220 + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); 1221 + } 1222 + } 1223 + 1224 + .btn-outline.btn-accent:hover { 1225 + --tw-text-opacity: 1; 1226 + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); 1227 + } 1228 + 1229 + @supports (color: color-mix(in oklab, black, black)) { 1230 + .btn-outline.btn-accent:hover { 1231 + background-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); 1232 + border-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); 1233 + } 1234 + } 1235 + 1236 + .btn-outline.btn-success:hover { 1237 + --tw-text-opacity: 1; 1238 + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); 1239 + } 1240 + 1241 + @supports (color: color-mix(in oklab, black, black)) { 1242 + .btn-outline.btn-success:hover { 1243 + background-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); 1244 + border-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); 1245 + } 1246 + } 1247 + 1248 + .btn-outline.btn-warning:hover { 1249 + --tw-text-opacity: 1; 1250 + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); 1251 + } 1252 + 1253 + @supports (color: color-mix(in oklab, black, black)) { 1254 + .btn-outline.btn-warning:hover { 1255 + background-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); 1256 + border-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); 1257 + } 1258 + } 1259 + 1260 + .btn-outline.btn-error:hover { 1261 + --tw-text-opacity: 1; 1262 + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); 1263 + } 1264 + 1265 + @supports (color: color-mix(in oklab, black, black)) { 1266 + .btn-outline.btn-error:hover { 1267 + background-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); 1268 + border-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); 1269 + } 1270 + } 1271 + 1272 + .btn-disabled:hover, 1273 + .btn[disabled]:hover, 1274 + .btn:disabled:hover { 1275 + --tw-border-opacity: 0; 1276 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 1277 + --tw-bg-opacity: 0.2; 1278 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 1279 + --tw-text-opacity: 0.2; 1280 + } 1281 + 1282 + @supports (color: color-mix(in oklab, black, black)) { 1283 + .btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover { 1284 + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); 1285 + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); 1286 + } 1287 + } 1288 + 1289 + :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover { 1290 + cursor: pointer; 1291 + outline: 2px solid transparent; 1292 + outline-offset: 2px; 1293 + } 1294 + 1295 + @supports (color: oklch(0 0 0)) { 1296 + :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover { 1297 + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); 1298 + } 1299 + } 1300 + } 1301 + 1302 + .file-input { 1303 + height: 3rem; 1304 + flex-shrink: 1; 1305 + padding-inline-end: 1rem; 1306 + font-size: 1rem; 1307 + line-height: 2; 1308 + line-height: 1.5rem; 1309 + overflow: hidden; 1310 + border-radius: var(--rounded-btn, 0.5rem); 1311 + border-width: 1px; 1312 + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); 1313 + --tw-border-opacity: 0; 1314 + --tw-bg-opacity: 1; 1315 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1316 + } 1317 + 1318 + .file-input::file-selector-button { 1319 + margin-inline-end: 1rem; 1320 + display: inline-flex; 1321 + height: 100%; 1322 + flex-shrink: 0; 1323 + cursor: pointer; 1324 + -webkit-user-select: none; 1325 + -moz-user-select: none; 1326 + user-select: none; 1327 + flex-wrap: wrap; 1328 + align-items: center; 1329 + justify-content: center; 1330 + padding-left: 1rem; 1331 + padding-right: 1rem; 1332 + text-align: center; 1333 + font-size: 0.875rem; 1334 + line-height: 1.25rem; 1335 + line-height: 1em; 1336 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; 1337 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 1338 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; 1339 + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1340 + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 1341 + transition-duration: 200ms; 1342 + border-style: solid; 1343 + --tw-border-opacity: 1; 1344 + border-color: var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity))); 1345 + --tw-bg-opacity: 1; 1346 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 1347 + font-weight: 600; 1348 + text-transform: uppercase; 1349 + --tw-text-opacity: 1; 1350 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 1351 + text-decoration-line: none; 1352 + border-width: var(--border-btn, 1px); 1353 + animation: button-pop var(--animation-btn, 0.25s) ease-out; 1354 + } 1355 + 1356 + .footer { 1357 + display: grid; 1358 + width: 100%; 1359 + grid-auto-flow: row; 1360 + place-items: start; 1361 + -moz-column-gap: 1rem; 1362 + column-gap: 1rem; 1363 + row-gap: 2.5rem; 1364 + font-size: 0.875rem; 1365 + line-height: 1.25rem; 1366 + } 1367 + 1368 + .footer > * { 1369 + display: grid; 1370 + place-items: start; 1371 + gap: 0.5rem; 1372 + } 1373 + 1374 + @media (min-width: 48rem) { 1375 + .footer { 1376 + grid-auto-flow: column; 1377 + } 1378 + 1379 + .footer-center { 1380 + grid-auto-flow: row dense; 1381 + } 1382 + } 1383 + 1384 + .form-control { 1385 + display: flex; 1386 + flex-direction: column; 1387 + } 1388 + 1389 + .label { 1390 + display: flex; 1391 + -webkit-user-select: none; 1392 + -moz-user-select: none; 1393 + user-select: none; 1394 + align-items: center; 1395 + justify-content: space-between; 1396 + padding-left: 0.25rem; 1397 + padding-right: 0.25rem; 1398 + padding-top: 0.5rem; 1399 + padding-bottom: 0.5rem; 1400 + } 1401 + 1402 + .input { 1403 + flex-shrink: 1; 1404 + -webkit-appearance: none; 1405 + -moz-appearance: none; 1406 + appearance: none; 1407 + height: 3rem; 1408 + padding-left: 1rem; 1409 + padding-right: 1rem; 1410 + font-size: 1rem; 1411 + line-height: 2; 1412 + line-height: 1.5rem; 1413 + border-radius: var(--rounded-btn, 0.5rem); 1414 + border-width: 1px; 1415 + border-color: transparent; 1416 + --tw-bg-opacity: 1; 1417 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1418 + } 1419 + 1420 + .input[type="number"]::-webkit-inner-spin-button, 1421 + .input-md[type="number"]::-webkit-inner-spin-button { 1422 + margin-top: -1rem; 1423 + margin-bottom: -1rem; 1424 + margin-inline-end: -1rem; 1425 + } 1426 + 1427 + .join { 1428 + display: inline-flex; 1429 + align-items: stretch; 1430 + border-radius: var(--rounded-btn, 0.5rem); 1431 + } 1432 + 1433 + .join :where(.join-item) { 1434 + border-start-end-radius: 0; 1435 + border-end-end-radius: 0; 1436 + border-end-start-radius: 0; 1437 + border-start-start-radius: 0; 1438 + } 1439 + 1440 + .join .join-item:not(:first-child):not(:last-child), 1441 + .join *:not(:first-child):not(:last-child) .join-item { 1442 + border-start-end-radius: 0; 1443 + border-end-end-radius: 0; 1444 + border-end-start-radius: 0; 1445 + border-start-start-radius: 0; 1446 + } 1447 + 1448 + .join .join-item:first-child:not(:last-child), 1449 + .join *:first-child:not(:last-child) .join-item { 1450 + border-start-end-radius: 0; 1451 + border-end-end-radius: 0; 1452 + } 1453 + 1454 + .join .dropdown .join-item:first-child:not(:last-child), 1455 + .join *:first-child:not(:last-child) .dropdown .join-item { 1456 + border-start-end-radius: inherit; 1457 + border-end-end-radius: inherit; 1458 + } 1459 + 1460 + .join :where(.join-item:first-child:not(:last-child)), 1461 + .join :where(*:first-child:not(:last-child) .join-item) { 1462 + border-end-start-radius: inherit; 1463 + border-start-start-radius: inherit; 1464 + } 1465 + 1466 + .join .join-item:last-child:not(:first-child), 1467 + .join *:last-child:not(:first-child) .join-item { 1468 + border-end-start-radius: 0; 1469 + border-start-start-radius: 0; 1470 + } 1471 + 1472 + .join :where(.join-item:last-child:not(:first-child)), 1473 + .join :where(*:last-child:not(:first-child) .join-item) { 1474 + border-start-end-radius: inherit; 1475 + border-end-end-radius: inherit; 1476 + } 1477 + 1478 + @supports not selector(:has(*)) { 1479 + :where(.join *) { 1480 + border-radius: inherit; 1481 + } 1482 + } 1483 + 1484 + @supports selector(:has(*)) { 1485 + :where(.join *:has(.join-item)) { 1486 + border-radius: inherit; 1487 + } 1488 + } 1489 + 1490 + .link { 1491 + cursor: pointer; 1492 + text-decoration-line: underline; 1493 + } 1494 + 1495 + .mask { 1496 + -webkit-mask-size: contain; 1497 + mask-size: contain; 1498 + -webkit-mask-repeat: no-repeat; 1499 + mask-repeat: no-repeat; 1500 + -webkit-mask-position: center; 1501 + mask-position: center; 1502 + } 1503 + 1504 + .menu { 1505 + display: flex; 1506 + flex-direction: column; 1507 + flex-wrap: wrap; 1508 + font-size: 0.875rem; 1509 + line-height: 1.25rem; 1510 + padding: 0.5rem; 1511 + } 1512 + 1513 + .menu :where(li ul) { 1514 + position: relative; 1515 + white-space: nowrap; 1516 + margin-inline-start: 1rem; 1517 + padding-inline-start: 0.5rem; 1518 + } 1519 + 1520 + .menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)), .menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) { 1521 + display: grid; 1522 + grid-auto-flow: column; 1523 + align-content: flex-start; 1524 + align-items: center; 1525 + gap: 0.5rem; 1526 + grid-auto-columns: minmax(auto, max-content) auto max-content; 1527 + -webkit-user-select: none; 1528 + -moz-user-select: none; 1529 + user-select: none; 1530 + } 1531 + 1532 + .menu li.disabled { 1533 + cursor: not-allowed; 1534 + -webkit-user-select: none; 1535 + -moz-user-select: none; 1536 + user-select: none; 1537 + color: var(--fallback-bc,oklch(var(--bc)/0.3)); 1538 + } 1539 + 1540 + .menu :where(li > .menu-dropdown:not(.menu-dropdown-show)) { 1541 + display: none; 1542 + } 1543 + 1544 + :where(.menu li) { 1545 + position: relative; 1546 + display: flex; 1547 + flex-shrink: 0; 1548 + flex-direction: column; 1549 + flex-wrap: wrap; 1550 + align-items: stretch; 1551 + } 1552 + 1553 + :where(.menu li) .badge { 1554 + justify-self: end; 1555 + } 1556 + 1557 + .select { 1558 + display: inline-flex; 1559 + cursor: pointer; 1560 + -webkit-user-select: none; 1561 + -moz-user-select: none; 1562 + user-select: none; 1563 + -webkit-appearance: none; 1564 + -moz-appearance: none; 1565 + appearance: none; 1566 + height: 3rem; 1567 + min-height: 3rem; 1568 + padding-left: 1rem; 1569 + padding-right: 2.5rem; 1570 + font-size: 0.875rem; 1571 + line-height: 1.25rem; 1572 + line-height: 2; 1573 + border-radius: var(--rounded-btn, 0.5rem); 1574 + border-width: 1px; 1575 + border-color: transparent; 1576 + --tw-bg-opacity: 1; 1577 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1578 + background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), 1579 + linear-gradient(135deg, currentColor 50%, transparent 50%); 1580 + background-position: calc(100% - 20px) calc(1px + 50%), 1581 + calc(100% - 16.1px) calc(1px + 50%); 1582 + background-size: 4px 4px, 1583 + 4px 4px; 1584 + background-repeat: no-repeat; 1585 + } 1586 + 1587 + .select[multiple] { 1588 + height: auto; 1589 + } 1590 + 1591 + .stats { 1592 + display: inline-grid; 1593 + border-radius: var(--rounded-box, 1rem); 1594 + --tw-bg-opacity: 1; 1595 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1596 + --tw-text-opacity: 1; 1597 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 1598 + } 1599 + 1600 + :where(.stats) { 1601 + grid-auto-flow: column; 1602 + overflow-x: auto; 1603 + } 1604 + 1605 + .stat { 1606 + display: inline-grid; 1607 + width: 100%; 1608 + grid-template-columns: repeat(1, 1fr); 1609 + -moz-column-gap: 1rem; 1610 + column-gap: 1rem; 1611 + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); 1612 + --tw-border-opacity: 0.1; 1613 + padding-left: 1.5rem; 1614 + padding-right: 1.5rem; 1615 + padding-top: 1rem; 1616 + padding-bottom: 1rem; 1617 + } 1618 + 1619 + .stat-figure { 1620 + grid-column-start: 2; 1621 + grid-row: span 3 / span 3; 1622 + grid-row-start: 1; 1623 + place-self: center; 1624 + justify-self: end; 1625 + } 1626 + 1627 + .stat-title { 1628 + grid-column-start: 1; 1629 + white-space: nowrap; 1630 + color: var(--fallback-bc,oklch(var(--bc)/0.6)); 1631 + } 1632 + 1633 + .stat-value { 1634 + grid-column-start: 1; 1635 + white-space: nowrap; 1636 + font-size: 2.25rem; 1637 + line-height: 2.5rem; 1638 + font-weight: 800; 1639 + } 1640 + 1641 + .stat-desc { 1642 + grid-column-start: 1; 1643 + white-space: nowrap; 1644 + font-size: 0.75rem; 1645 + line-height: 1rem; 1646 + color: var(--fallback-bc,oklch(var(--bc)/0.6)); 1647 + } 1648 + 1649 + .table { 1650 + position: relative; 1651 + width: 100%; 1652 + border-radius: var(--rounded-box, 1rem); 1653 + text-align: left; 1654 + font-size: 0.875rem; 1655 + line-height: 1.25rem; 1656 + } 1657 + 1658 + .table :where(.table-pin-rows thead tr) { 1659 + position: sticky; 1660 + top: 0px; 1661 + z-index: 1; 1662 + --tw-bg-opacity: 1; 1663 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1664 + } 1665 + 1666 + .table :where(.table-pin-rows tfoot tr) { 1667 + position: sticky; 1668 + bottom: 0px; 1669 + z-index: 1; 1670 + --tw-bg-opacity: 1; 1671 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1672 + } 1673 + 1674 + .table :where(.table-pin-cols tr th) { 1675 + position: sticky; 1676 + left: 0px; 1677 + right: 0px; 1678 + --tw-bg-opacity: 1; 1679 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1680 + } 1681 + 1682 + .textarea { 1683 + min-height: 3rem; 1684 + flex-shrink: 1; 1685 + padding-left: 1rem; 1686 + padding-right: 1rem; 1687 + padding-top: 0.5rem; 1688 + padding-bottom: 0.5rem; 1689 + font-size: 0.875rem; 1690 + line-height: 1.25rem; 1691 + line-height: 2; 1692 + border-radius: var(--rounded-btn, 0.5rem); 1693 + border-width: 1px; 1694 + border-color: transparent; 1695 + --tw-bg-opacity: 1; 1696 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 1697 + } 1698 + 1699 + .toggle { 1700 + flex-shrink: 0; 1701 + --tglbg: var(--fallback-b1,oklch(var(--b1)/1)); 1702 + --handleoffset: 1.5rem; 1703 + --handleoffsetcalculator: calc(var(--handleoffset) * -1); 1704 + --togglehandleborder: 0 0; 1705 + height: 1.5rem; 1706 + width: 3rem; 1707 + cursor: pointer; 1708 + -webkit-appearance: none; 1709 + -moz-appearance: none; 1710 + appearance: none; 1711 + border-radius: var(--rounded-badge, 1.9rem); 1712 + border-width: 1px; 1713 + border-color: currentColor; 1714 + background-color: currentColor; 1715 + color: var(--fallback-bc,oklch(var(--bc)/0.5)); 1716 + transition: background, 1717 + box-shadow var(--animation-input, 0.2s) ease-out; 1718 + box-shadow: var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset, 1719 + 0 0 0 2px var(--tglbg) inset, 1720 + var(--togglehandleborder); 1721 + } 1722 + 1723 + .alert-error { 1724 + border-color: var(--fallback-er,oklch(var(--er)/0.2)); 1725 + --tw-text-opacity: 1; 1726 + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); 1727 + --alert-bg: var(--fallback-er,oklch(var(--er)/1)); 1728 + --alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1)); 1729 + } 1730 + 1731 + .avatar-group :where(.avatar) { 1732 + overflow: hidden; 1733 + border-radius: 9999px; 1734 + border-width: 4px; 1735 + --tw-border-opacity: 1; 1736 + border-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-border-opacity))); 1737 + } 1738 + 1739 + .badge-neutral { 1740 + --tw-border-opacity: 1; 1741 + border-color: var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity))); 1742 + --tw-bg-opacity: 1; 1743 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 1744 + --tw-text-opacity: 1; 1745 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 1746 + } 1747 + 1748 + .badge-primary { 1749 + --tw-border-opacity: 1; 1750 + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); 1751 + --tw-bg-opacity: 1; 1752 + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); 1753 + --tw-text-opacity: 1; 1754 + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); 1755 + } 1756 + 1757 + .badge-accent { 1758 + --tw-border-opacity: 1; 1759 + border-color: var(--fallback-a,oklch(var(--a)/var(--tw-border-opacity))); 1760 + --tw-bg-opacity: 1; 1761 + background-color: var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity))); 1762 + --tw-text-opacity: 1; 1763 + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); 1764 + } 1765 + 1766 + .badge-success { 1767 + border-color: transparent; 1768 + --tw-bg-opacity: 1; 1769 + background-color: var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity))); 1770 + --tw-text-opacity: 1; 1771 + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); 1772 + } 1773 + 1774 + .badge-warning { 1775 + border-color: transparent; 1776 + --tw-bg-opacity: 1; 1777 + background-color: var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity))); 1778 + --tw-text-opacity: 1; 1779 + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); 1780 + } 1781 + 1782 + .badge-error { 1783 + border-color: transparent; 1784 + --tw-bg-opacity: 1; 1785 + background-color: var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity))); 1786 + --tw-text-opacity: 1; 1787 + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); 1788 + } 1789 + 1790 + .badge-ghost { 1791 + --tw-border-opacity: 1; 1792 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 1793 + --tw-bg-opacity: 1; 1794 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 1795 + --tw-text-opacity: 1; 1796 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 1797 + } 1798 + 1799 + .badge-outline.badge-neutral { 1800 + --tw-text-opacity: 1; 1801 + color: var(--fallback-n,oklch(var(--n)/var(--tw-text-opacity))); 1802 + } 1803 + 1804 + .badge-outline.badge-primary { 1805 + --tw-text-opacity: 1; 1806 + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity))); 1807 + } 1808 + 1809 + .badge-outline.badge-accent { 1810 + --tw-text-opacity: 1; 1811 + color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity))); 1812 + } 1813 + 1814 + .badge-outline.badge-success { 1815 + --tw-text-opacity: 1; 1816 + color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity))); 1817 + } 1818 + 1819 + .badge-outline.badge-warning { 1820 + --tw-text-opacity: 1; 1821 + color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity))); 1822 + } 1823 + 1824 + .badge-outline.badge-error { 1825 + --tw-text-opacity: 1; 1826 + color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))); 1827 + } 1828 + 1829 + .btm-nav > *.disabled, 1830 + .btm-nav > *[disabled] { 1831 + pointer-events: none; 1832 + --tw-border-opacity: 0; 1833 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 1834 + --tw-bg-opacity: 0.1; 1835 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 1836 + --tw-text-opacity: 0.2; 1837 + } 1838 + 1839 + .btm-nav > * .label { 1840 + font-size: 1rem; 1841 + line-height: 1.5rem; 1842 + } 1843 + 1844 + .btn:active:hover, 1845 + .btn:active:focus { 1846 + animation: button-pop 0s ease-out; 1847 + transform: scale(var(--btn-focus-scale, 0.97)); 1848 + } 1849 + 1850 + @supports not (color: oklch(0 0 0)) { 1851 + .btn { 1852 + background-color: var(--btn-color, var(--fallback-b2)); 1853 + border-color: var(--btn-color, var(--fallback-b2)); 1854 + } 1855 + 1856 + .btn-primary { 1857 + --btn-color: var(--fallback-p); 1858 + } 1859 + 1860 + .btn-accent { 1861 + --btn-color: var(--fallback-a); 1862 + } 1863 + 1864 + .btn-neutral { 1865 + --btn-color: var(--fallback-n); 1866 + } 1867 + 1868 + .btn-success { 1869 + --btn-color: var(--fallback-su); 1870 + } 1871 + 1872 + .btn-warning { 1873 + --btn-color: var(--fallback-wa); 1874 + } 1875 + 1876 + .btn-error { 1877 + --btn-color: var(--fallback-er); 1878 + } 1879 + } 1880 + 1881 + @supports (color: color-mix(in oklab, black, black)) { 1882 + .btn-outline.btn-primary.btn-active { 1883 + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); 1884 + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); 1885 + } 1886 + 1887 + .btn-outline.btn-accent.btn-active { 1888 + background-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); 1889 + border-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); 1890 + } 1891 + 1892 + .btn-outline.btn-success.btn-active { 1893 + background-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); 1894 + border-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); 1895 + } 1896 + 1897 + .btn-outline.btn-warning.btn-active { 1898 + background-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); 1899 + border-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); 1900 + } 1901 + 1902 + .btn-outline.btn-error.btn-active { 1903 + background-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); 1904 + border-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); 1905 + } 1906 + } 1907 + 1908 + .btn:focus-visible { 1909 + outline-style: solid; 1910 + outline-width: 2px; 1911 + outline-offset: 2px; 1912 + } 1913 + 1914 + .btn-primary { 1915 + --tw-text-opacity: 1; 1916 + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); 1917 + outline-color: var(--fallback-p,oklch(var(--p)/1)); 1918 + } 1919 + 1920 + @supports (color: oklch(0 0 0)) { 1921 + .btn-primary { 1922 + --btn-color: var(--p); 1923 + } 1924 + 1925 + .btn-accent { 1926 + --btn-color: var(--a); 1927 + } 1928 + 1929 + .btn-neutral { 1930 + --btn-color: var(--n); 1931 + } 1932 + 1933 + .btn-success { 1934 + --btn-color: var(--su); 1935 + } 1936 + 1937 + .btn-warning { 1938 + --btn-color: var(--wa); 1939 + } 1940 + 1941 + .btn-error { 1942 + --btn-color: var(--er); 1943 + } 1944 + } 1945 + 1946 + .btn-accent { 1947 + --tw-text-opacity: 1; 1948 + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); 1949 + outline-color: var(--fallback-a,oklch(var(--a)/1)); 1950 + } 1951 + 1952 + .btn-neutral { 1953 + --tw-text-opacity: 1; 1954 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 1955 + outline-color: var(--fallback-n,oklch(var(--n)/1)); 1956 + } 1957 + 1958 + .btn-success { 1959 + --tw-text-opacity: 1; 1960 + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); 1961 + outline-color: var(--fallback-su,oklch(var(--su)/1)); 1962 + } 1963 + 1964 + .btn-warning { 1965 + --tw-text-opacity: 1; 1966 + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); 1967 + outline-color: var(--fallback-wa,oklch(var(--wa)/1)); 1968 + } 1969 + 1970 + .btn-error { 1971 + --tw-text-opacity: 1; 1972 + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); 1973 + outline-color: var(--fallback-er,oklch(var(--er)/1)); 1974 + } 1975 + 1976 + .btn.glass { 1977 + --tw-shadow: 0 0 #0000; 1978 + --tw-shadow-colored: 0 0 #0000; 1979 + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); 1980 + outline-color: currentColor; 1981 + } 1982 + 1983 + .btn.glass.btn-active { 1984 + --glass-opacity: 25%; 1985 + --glass-border-opacity: 15%; 1986 + } 1987 + 1988 + .btn-ghost { 1989 + border-width: 1px; 1990 + border-color: transparent; 1991 + background-color: transparent; 1992 + color: currentColor; 1993 + --tw-shadow: 0 0 #0000; 1994 + --tw-shadow-colored: 0 0 #0000; 1995 + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); 1996 + outline-color: currentColor; 1997 + } 1998 + 1999 + .btn-ghost.btn-active { 2000 + border-color: transparent; 2001 + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2002 + } 2003 + 2004 + .btn-outline.btn-primary { 2005 + --tw-text-opacity: 1; 2006 + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity))); 2007 + } 2008 + 2009 + .btn-outline.btn-primary.btn-active { 2010 + --tw-text-opacity: 1; 2011 + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); 2012 + } 2013 + 2014 + .btn-outline.btn-accent { 2015 + --tw-text-opacity: 1; 2016 + color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity))); 2017 + } 2018 + 2019 + .btn-outline.btn-accent.btn-active { 2020 + --tw-text-opacity: 1; 2021 + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); 2022 + } 2023 + 2024 + .btn-outline.btn-success { 2025 + --tw-text-opacity: 1; 2026 + color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity))); 2027 + } 2028 + 2029 + .btn-outline.btn-success.btn-active { 2030 + --tw-text-opacity: 1; 2031 + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); 2032 + } 2033 + 2034 + .btn-outline.btn-warning { 2035 + --tw-text-opacity: 1; 2036 + color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity))); 2037 + } 2038 + 2039 + .btn-outline.btn-warning.btn-active { 2040 + --tw-text-opacity: 1; 2041 + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); 2042 + } 2043 + 2044 + .btn-outline.btn-error { 2045 + --tw-text-opacity: 1; 2046 + color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))); 2047 + } 2048 + 2049 + .btn-outline.btn-error.btn-active { 2050 + --tw-text-opacity: 1; 2051 + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); 2052 + } 2053 + 2054 + .btn.btn-disabled, 2055 + .btn[disabled], 2056 + .btn:disabled { 2057 + --tw-border-opacity: 0; 2058 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 2059 + --tw-bg-opacity: 0.2; 2060 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2061 + --tw-text-opacity: 0.2; 2062 + } 2063 + 2064 + .btn:is(input[type="checkbox"]:checked), 2065 + .btn:is(input[type="radio"]:checked) { 2066 + --tw-border-opacity: 1; 2067 + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); 2068 + --tw-bg-opacity: 1; 2069 + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); 2070 + --tw-text-opacity: 1; 2071 + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); 2072 + } 2073 + 2074 + .btn:is(input[type="checkbox"]:checked):focus-visible, .btn:is(input[type="radio"]:checked):focus-visible { 2075 + outline-color: var(--fallback-p,oklch(var(--p)/1)); 2076 + } 2077 + 2078 + @keyframes button-pop { 2079 + 0% { 2080 + transform: scale(var(--btn-focus-scale, 0.98)); 2081 + } 2082 + 2083 + 40% { 2084 + transform: scale(1.02); 2085 + } 2086 + 2087 + 100% { 2088 + transform: scale(1); 2089 + } 2090 + } 2091 + 2092 + .card :where(figure:first-child) { 2093 + overflow: hidden; 2094 + border-start-start-radius: inherit; 2095 + border-start-end-radius: inherit; 2096 + border-end-start-radius: unset; 2097 + border-end-end-radius: unset; 2098 + } 2099 + 2100 + .card :where(figure:last-child) { 2101 + overflow: hidden; 2102 + border-start-start-radius: unset; 2103 + border-start-end-radius: unset; 2104 + border-end-start-radius: inherit; 2105 + border-end-end-radius: inherit; 2106 + } 2107 + 2108 + .card:focus-visible { 2109 + outline: 2px solid currentColor; 2110 + outline-offset: 2px; 2111 + } 2112 + 2113 + .card.bordered { 2114 + border-width: 1px; 2115 + --tw-border-opacity: 1; 2116 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 2117 + } 2118 + 2119 + .card.compact .card-body { 2120 + padding: 1rem; 2121 + font-size: 0.875rem; 2122 + line-height: 1.25rem; 2123 + } 2124 + 2125 + .card.image-full :where(figure) { 2126 + overflow: hidden; 2127 + border-radius: inherit; 2128 + } 2129 + 2130 + .checkbox:focus { 2131 + box-shadow: none; 2132 + } 2133 + 2134 + .checkbox:focus-visible { 2135 + outline-style: solid; 2136 + outline-width: 2px; 2137 + outline-offset: 2px; 2138 + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); 2139 + } 2140 + 2141 + .checkbox:checked, 2142 + .checkbox[checked="true"], 2143 + .checkbox[aria-checked="true"] { 2144 + background-repeat: no-repeat; 2145 + animation: checkmark var(--animation-input, 0.2s) ease-out; 2146 + background-color: var(--chkbg); 2147 + background-image: linear-gradient(-45deg, transparent 65%, var(--chkbg) 65.99%), 2148 + linear-gradient(45deg, transparent 75%, var(--chkbg) 75.99%), 2149 + linear-gradient(-45deg, var(--chkbg) 40%, transparent 40.99%), 2150 + linear-gradient( 2151 + 45deg, 2152 + var(--chkbg) 30%, 2153 + var(--chkfg) 30.99%, 2154 + var(--chkfg) 40%, 2155 + transparent 40.99% 2156 + ), 2157 + linear-gradient(-45deg, var(--chkfg) 50%, var(--chkbg) 50.99%); 2158 + } 2159 + 2160 + .checkbox:indeterminate { 2161 + --tw-bg-opacity: 1; 2162 + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); 2163 + background-repeat: no-repeat; 2164 + animation: checkmark var(--animation-input, 0.2s) ease-out; 2165 + background-image: linear-gradient(90deg, transparent 80%, var(--chkbg) 80%), 2166 + linear-gradient(-90deg, transparent 80%, var(--chkbg) 80%), 2167 + linear-gradient(0deg, var(--chkbg) 43%, var(--chkfg) 43%, var(--chkfg) 57%, var(--chkbg) 57%); 2168 + } 2169 + 2170 + .checkbox:disabled { 2171 + cursor: not-allowed; 2172 + border-color: transparent; 2173 + --tw-bg-opacity: 1; 2174 + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); 2175 + opacity: 0.2; 2176 + } 2177 + 2178 + @keyframes checkmark { 2179 + 0% { 2180 + background-position-y: 5px; 2181 + } 2182 + 2183 + 50% { 2184 + background-position-y: -2px; 2185 + } 2186 + 2187 + 100% { 2188 + background-position-y: 0; 2189 + } 2190 + } 2191 + 2192 + .divider:not(:empty) { 2193 + gap: 1rem; 2194 + } 2195 + 2196 + .drawer-toggle:checked ~ .drawer-side > .drawer-overlay { 2197 + background-color: #0006; 2198 + } 2199 + 2200 + .drawer-toggle:focus-visible ~ .drawer-content label.drawer-button { 2201 + outline-style: solid; 2202 + outline-width: 2px; 2203 + outline-offset: 2px; 2204 + } 2205 + 2206 + .file-input-bordered { 2207 + --tw-border-opacity: 0.2; 2208 + } 2209 + 2210 + .file-input:focus { 2211 + outline-style: solid; 2212 + outline-width: 2px; 2213 + outline-offset: 2px; 2214 + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2215 + } 2216 + 2217 + .file-input-disabled, 2218 + .file-input[disabled] { 2219 + cursor: not-allowed; 2220 + --tw-border-opacity: 1; 2221 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 2222 + --tw-bg-opacity: 1; 2223 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 2224 + --tw-text-opacity: 0.2; 2225 + } 2226 + 2227 + .file-input-disabled::-moz-placeholder, .file-input[disabled]::-moz-placeholder { 2228 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2229 + --tw-placeholder-opacity: 0.2; 2230 + } 2231 + 2232 + .file-input-disabled::placeholder, 2233 + .file-input[disabled]::placeholder { 2234 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2235 + --tw-placeholder-opacity: 0.2; 2236 + } 2237 + 2238 + .file-input-disabled::file-selector-button, .file-input[disabled]::file-selector-button { 2239 + --tw-border-opacity: 0; 2240 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 2241 + --tw-bg-opacity: 0.2; 2242 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2243 + --tw-text-opacity: 0.2; 2244 + } 2245 + 2246 + .label-text { 2247 + font-size: 0.875rem; 2248 + line-height: 1.25rem; 2249 + --tw-text-opacity: 1; 2250 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2251 + } 2252 + 2253 + .label-text-alt { 2254 + font-size: 0.75rem; 2255 + line-height: 1rem; 2256 + --tw-text-opacity: 1; 2257 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2258 + } 2259 + 2260 + .input input { 2261 + --tw-bg-opacity: 1; 2262 + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); 2263 + background-color: transparent; 2264 + } 2265 + 2266 + .input input:focus { 2267 + outline: 2px solid transparent; 2268 + outline-offset: 2px; 2269 + } 2270 + 2271 + .input[list]::-webkit-calendar-picker-indicator { 2272 + line-height: 1em; 2273 + } 2274 + 2275 + .input-bordered { 2276 + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2277 + } 2278 + 2279 + .input:focus, 2280 + .input:focus-within { 2281 + box-shadow: none; 2282 + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2283 + outline-style: solid; 2284 + outline-width: 2px; 2285 + outline-offset: 2px; 2286 + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2287 + } 2288 + 2289 + .input-primary { 2290 + --tw-border-opacity: 1; 2291 + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); 2292 + } 2293 + 2294 + .input-primary:focus, 2295 + .input-primary:focus-within { 2296 + --tw-border-opacity: 1; 2297 + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); 2298 + outline-color: var(--fallback-p,oklch(var(--p)/1)); 2299 + } 2300 + 2301 + .input-disabled, 2302 + .input:disabled, 2303 + .input[disabled] { 2304 + cursor: not-allowed; 2305 + --tw-border-opacity: 1; 2306 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 2307 + --tw-bg-opacity: 1; 2308 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 2309 + color: var(--fallback-bc,oklch(var(--bc)/0.4)); 2310 + } 2311 + 2312 + .input-disabled::-moz-placeholder, .input:disabled::-moz-placeholder, .input[disabled]::-moz-placeholder { 2313 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2314 + --tw-placeholder-opacity: 0.2; 2315 + } 2316 + 2317 + .input-disabled::placeholder, 2318 + .input:disabled::placeholder, 2319 + .input[disabled]::placeholder { 2320 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2321 + --tw-placeholder-opacity: 0.2; 2322 + } 2323 + 2324 + .input::-webkit-date-and-time-value { 2325 + text-align: inherit; 2326 + } 2327 + 2328 + .join > :where(*:not(:first-child)) { 2329 + margin-top: 0px; 2330 + margin-bottom: 0px; 2331 + margin-inline-start: -1px; 2332 + } 2333 + 2334 + .join-item:focus { 2335 + isolation: isolate; 2336 + } 2337 + 2338 + .link:focus { 2339 + outline: 2px solid transparent; 2340 + outline-offset: 2px; 2341 + } 2342 + 2343 + .link:focus-visible { 2344 + outline: 2px solid currentColor; 2345 + outline-offset: 2px; 2346 + } 2347 + 2348 + .mask-squircle { 2349 + -webkit-mask-image: url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M100 0C20 0 0 20 0 100s20 100 100 100 100-20 100-100S180 0 100 0Z'/%3e%3c/svg%3e"); 2350 + mask-image: url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M100 0C20 0 0 20 0 100s20 100 100 100 100-20 100-100S180 0 100 0Z'/%3e%3c/svg%3e"); 2351 + } 2352 + 2353 + :where(.menu li:empty) { 2354 + --tw-bg-opacity: 1; 2355 + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); 2356 + opacity: 0.1; 2357 + margin: 0.5rem 1rem; 2358 + height: 1px; 2359 + } 2360 + 2361 + .menu :where(li ul):before { 2362 + position: absolute; 2363 + bottom: 0.75rem; 2364 + inset-inline-start: 0px; 2365 + top: 0.75rem; 2366 + width: 1px; 2367 + --tw-bg-opacity: 1; 2368 + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); 2369 + opacity: 0.1; 2370 + content: ""; 2371 + } 2372 + 2373 + .menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)), 2374 + .menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) { 2375 + border-radius: var(--rounded-btn, 0.5rem); 2376 + padding-left: 1rem; 2377 + padding-right: 1rem; 2378 + padding-top: 0.5rem; 2379 + padding-bottom: 0.5rem; 2380 + text-align: start; 2381 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; 2382 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 2383 + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; 2384 + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 2385 + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 2386 + transition-duration: 200ms; 2387 + text-wrap: balance; 2388 + } 2389 + 2390 + :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):is(summary):not(.active, .btn):focus-visible, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):is(summary):not(.active, .btn):focus-visible { 2391 + cursor: pointer; 2392 + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); 2393 + --tw-text-opacity: 1; 2394 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2395 + outline: 2px solid transparent; 2396 + outline-offset: 2px; 2397 + } 2398 + 2399 + .menu li > *:not(ul, .menu-title, details, .btn):active, 2400 + .menu li > *:not(ul, .menu-title, details, .btn).active, 2401 + .menu li > details > summary:active { 2402 + --tw-bg-opacity: 1; 2403 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 2404 + --tw-text-opacity: 1; 2405 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 2406 + } 2407 + 2408 + .menu :where(li > details > summary)::-webkit-details-marker { 2409 + display: none; 2410 + } 2411 + 2412 + .menu :where(li > details > summary):after, 2413 + .menu :where(li > .menu-dropdown-toggle):after { 2414 + justify-self: end; 2415 + display: block; 2416 + margin-top: -0.5rem; 2417 + height: 0.5rem; 2418 + width: 0.5rem; 2419 + transform: rotate(45deg); 2420 + transition-property: transform, margin-top; 2421 + transition-duration: 0.3s; 2422 + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 2423 + content: ""; 2424 + transform-origin: 75% 75%; 2425 + box-shadow: 2px 2px; 2426 + pointer-events: none; 2427 + } 2428 + 2429 + .menu :where(li > details[open] > summary):after, 2430 + .menu :where(li > .menu-dropdown-toggle.menu-dropdown-show):after { 2431 + transform: rotate(225deg); 2432 + margin-top: 0; 2433 + } 2434 + 2435 + .mockup-browser .mockup-browser-toolbar .input { 2436 + position: relative; 2437 + margin-left: auto; 2438 + margin-right: auto; 2439 + display: block; 2440 + height: 1.75rem; 2441 + width: 24rem; 2442 + overflow: hidden; 2443 + text-overflow: ellipsis; 2444 + white-space: nowrap; 2445 + --tw-bg-opacity: 1; 2446 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 2447 + padding-left: 2rem; 2448 + direction: ltr; 2449 + } 2450 + 2451 + .mockup-browser .mockup-browser-toolbar .input:before { 2452 + content: ""; 2453 + position: absolute; 2454 + left: 0.5rem; 2455 + top: 50%; 2456 + aspect-ratio: 1 / 1; 2457 + height: 0.75rem; 2458 + --tw-translate-y: -50%; 2459 + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); 2460 + border-radius: 9999px; 2461 + border-width: 2px; 2462 + border-color: currentColor; 2463 + opacity: 0.6; 2464 + } 2465 + 2466 + .mockup-browser .mockup-browser-toolbar .input:after { 2467 + content: ""; 2468 + position: absolute; 2469 + left: 1.25rem; 2470 + top: 50%; 2471 + height: 0.5rem; 2472 + --tw-translate-y: 25%; 2473 + --tw-rotate: -45deg; 2474 + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); 2475 + border-radius: 9999px; 2476 + border-width: 1px; 2477 + border-color: currentColor; 2478 + opacity: 0.6; 2479 + } 2480 + 2481 + @keyframes modal-pop { 2482 + 0% { 2483 + opacity: 0; 2484 + } 2485 + } 2486 + 2487 + @keyframes progress-loading { 2488 + 50% { 2489 + background-position-x: -115%; 2490 + } 2491 + } 2492 + 2493 + @keyframes radiomark { 2494 + 0% { 2495 + box-shadow: 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset, 2496 + 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset; 2497 + } 2498 + 2499 + 50% { 2500 + box-shadow: 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset, 2501 + 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset; 2502 + } 2503 + 2504 + 100% { 2505 + box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset, 2506 + 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset; 2507 + } 2508 + } 2509 + 2510 + @keyframes rating-pop { 2511 + 0% { 2512 + transform: translateY(-0.125em); 2513 + } 2514 + 2515 + 40% { 2516 + transform: translateY(-0.125em); 2517 + } 2518 + 2519 + 100% { 2520 + transform: translateY(0); 2521 + } 2522 + } 2523 + 2524 + .select-bordered { 2525 + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2526 + } 2527 + 2528 + .select:focus { 2529 + box-shadow: none; 2530 + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2531 + outline-style: solid; 2532 + outline-width: 2px; 2533 + outline-offset: 2px; 2534 + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2535 + } 2536 + 2537 + .select-primary { 2538 + --tw-border-opacity: 1; 2539 + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); 2540 + } 2541 + 2542 + .select-primary:focus { 2543 + --tw-border-opacity: 1; 2544 + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); 2545 + outline-color: var(--fallback-p,oklch(var(--p)/1)); 2546 + } 2547 + 2548 + .select-warning { 2549 + --tw-border-opacity: 1; 2550 + border-color: var(--fallback-wa,oklch(var(--wa)/var(--tw-border-opacity))); 2551 + } 2552 + 2553 + .select-warning:focus { 2554 + --tw-border-opacity: 1; 2555 + border-color: var(--fallback-wa,oklch(var(--wa)/var(--tw-border-opacity))); 2556 + outline-color: var(--fallback-wa,oklch(var(--wa)/1)); 2557 + } 2558 + 2559 + .select-error { 2560 + --tw-border-opacity: 1; 2561 + border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity))); 2562 + } 2563 + 2564 + .select-error:focus { 2565 + --tw-border-opacity: 1; 2566 + border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity))); 2567 + outline-color: var(--fallback-er,oklch(var(--er)/1)); 2568 + } 2569 + 2570 + .select-disabled, 2571 + .select:disabled, 2572 + .select[disabled] { 2573 + cursor: not-allowed; 2574 + --tw-border-opacity: 1; 2575 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 2576 + --tw-bg-opacity: 1; 2577 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 2578 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2579 + --tw-text-opacity: 0.2; 2580 + } 2581 + 2582 + .select-disabled::-moz-placeholder, .select:disabled::-moz-placeholder, .select[disabled]::-moz-placeholder { 2583 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2584 + --tw-placeholder-opacity: 0.2; 2585 + } 2586 + 2587 + .select-disabled::placeholder, 2588 + .select:disabled::placeholder, 2589 + .select[disabled]::placeholder { 2590 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2591 + --tw-placeholder-opacity: 0.2; 2592 + } 2593 + 2594 + .select-multiple, 2595 + .select[multiple], 2596 + .select[size].select:not([size="1"]) { 2597 + background-image: none; 2598 + padding-right: 1rem; 2599 + } 2600 + 2601 + [dir="rtl"] .select { 2602 + background-position: calc(0% + 12px) calc(1px + 50%), 2603 + calc(0% + 16px) calc(1px + 50%); 2604 + } 2605 + 2606 + @keyframes skeleton { 2607 + from { 2608 + background-position: 150%; 2609 + } 2610 + 2611 + to { 2612 + background-position: -50%; 2613 + } 2614 + } 2615 + 2616 + :where(.stats) > :not([hidden]) ~ :not([hidden]) { 2617 + --tw-divide-x-reverse: 0; 2618 + border-right-width: calc(1px * var(--tw-divide-x-reverse)); 2619 + border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse))); 2620 + --tw-divide-y-reverse: 0; 2621 + border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse))); 2622 + border-bottom-width: calc(0px * var(--tw-divide-y-reverse)); 2623 + } 2624 + 2625 + :is([dir="rtl"] .stats > :not([hidden]) ~ :not([hidden])) { 2626 + --tw-divide-x-reverse: 1; 2627 + } 2628 + 2629 + :is([dir="rtl"] .table) { 2630 + text-align: right; 2631 + } 2632 + 2633 + .table :where(th, td) { 2634 + padding-left: 1rem; 2635 + padding-right: 1rem; 2636 + padding-top: 0.75rem; 2637 + padding-bottom: 0.75rem; 2638 + vertical-align: middle; 2639 + } 2640 + 2641 + .table tr.active, 2642 + .table tr.active:nth-child(even), 2643 + .table-zebra tbody tr:nth-child(even) { 2644 + --tw-bg-opacity: 1; 2645 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 2646 + } 2647 + 2648 + .table :where(thead, tbody) :where(tr:not(:last-child)), 2649 + .table :where(thead, tbody) :where(tr:first-child:last-child) { 2650 + border-bottom-width: 1px; 2651 + --tw-border-opacity: 1; 2652 + border-bottom-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 2653 + } 2654 + 2655 + .table :where(thead, tfoot) { 2656 + white-space: nowrap; 2657 + font-size: 0.75rem; 2658 + line-height: 1rem; 2659 + font-weight: 700; 2660 + color: var(--fallback-bc,oklch(var(--bc)/0.6)); 2661 + } 2662 + 2663 + .textarea-bordered { 2664 + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2665 + } 2666 + 2667 + .textarea:focus { 2668 + box-shadow: none; 2669 + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2670 + outline-style: solid; 2671 + outline-width: 2px; 2672 + outline-offset: 2px; 2673 + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2674 + } 2675 + 2676 + .textarea-disabled, 2677 + .textarea:disabled, 2678 + .textarea[disabled] { 2679 + cursor: not-allowed; 2680 + --tw-border-opacity: 1; 2681 + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); 2682 + --tw-bg-opacity: 1; 2683 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 2684 + --tw-text-opacity: 0.2; 2685 + } 2686 + 2687 + .textarea-disabled::-moz-placeholder, .textarea:disabled::-moz-placeholder, .textarea[disabled]::-moz-placeholder { 2688 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2689 + --tw-placeholder-opacity: 0.2; 2690 + } 2691 + 2692 + .textarea-disabled::placeholder, 2693 + .textarea:disabled::placeholder, 2694 + .textarea[disabled]::placeholder { 2695 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); 2696 + --tw-placeholder-opacity: 0.2; 2697 + } 2698 + 2699 + @keyframes toast-pop { 2700 + 0% { 2701 + transform: scale(0.9); 2702 + opacity: 0; 2703 + } 2704 + 2705 + 100% { 2706 + transform: scale(1); 2707 + opacity: 1; 2708 + } 2709 + } 2710 + 2711 + [dir="rtl"] .toggle { 2712 + --handleoffsetcalculator: calc(var(--handleoffset) * 1); 2713 + } 2714 + 2715 + .toggle:focus-visible { 2716 + outline-style: solid; 2717 + outline-width: 2px; 2718 + outline-offset: 2px; 2719 + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); 2720 + } 2721 + 2722 + .toggle:hover { 2723 + background-color: currentColor; 2724 + } 2725 + 2726 + .toggle:checked, 2727 + .toggle[checked="true"], 2728 + .toggle[aria-checked="true"] { 2729 + background-image: none; 2730 + --handleoffsetcalculator: var(--handleoffset); 2731 + --tw-text-opacity: 1; 2732 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2733 + } 2734 + 2735 + [dir="rtl"] .toggle:checked, [dir="rtl"] .toggle[checked="true"], [dir="rtl"] .toggle[aria-checked="true"] { 2736 + --handleoffsetcalculator: calc(var(--handleoffset) * -1); 2737 + } 2738 + 2739 + .toggle:indeterminate { 2740 + --tw-text-opacity: 1; 2741 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 2742 + box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset, 2743 + calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset, 2744 + 0 0 0 2px var(--tglbg) inset; 2745 + } 2746 + 2747 + [dir="rtl"] .toggle:indeterminate { 2748 + box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset, 2749 + calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset, 2750 + 0 0 0 2px var(--tglbg) inset; 2751 + } 2752 + 2753 + .toggle-accent:focus-visible { 2754 + outline-color: var(--fallback-a,oklch(var(--a)/1)); 2755 + } 2756 + 2757 + .toggle-accent:checked, 2758 + .toggle-accent[checked="true"], 2759 + .toggle-accent[aria-checked="true"] { 2760 + border-color: var(--fallback-a,oklch(var(--a)/var(--tw-border-opacity))); 2761 + --tw-border-opacity: 0.1; 2762 + --tw-bg-opacity: 1; 2763 + background-color: var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity))); 2764 + --tw-text-opacity: 1; 2765 + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); 2766 + } 2767 + 2768 + .toggle-error:focus-visible { 2769 + outline-color: var(--fallback-er,oklch(var(--er)/1)); 2770 + } 2771 + 2772 + .toggle-error:checked, 2773 + .toggle-error[checked="true"], 2774 + .toggle-error[aria-checked="true"] { 2775 + border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity))); 2776 + --tw-border-opacity: 0.1; 2777 + --tw-bg-opacity: 1; 2778 + background-color: var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity))); 2779 + --tw-text-opacity: 1; 2780 + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); 2781 + } 2782 + 2783 + .toggle:disabled { 2784 + cursor: not-allowed; 2785 + --tw-border-opacity: 1; 2786 + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); 2787 + background-color: transparent; 2788 + opacity: 0.3; 2789 + --togglehandleborder: 0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset, 2790 + var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset; 2791 + } 2792 + 2793 + .badge-sm { 2794 + height: 1rem; 2795 + font-size: 0.75rem; 2796 + line-height: 1rem; 2797 + padding-left: 0.438rem; 2798 + padding-right: 0.438rem; 2799 + } 2800 + 2801 + .btn-xs { 2802 + height: 1.5rem; 2803 + min-height: 1.5rem; 2804 + padding-left: 0.5rem; 2805 + padding-right: 0.5rem; 2806 + font-size: 0.75rem; 2807 + } 2808 + 2809 + .btn-sm { 2810 + height: 2rem; 2811 + min-height: 2rem; 2812 + padding-left: 0.75rem; 2813 + padding-right: 0.75rem; 2814 + font-size: 0.875rem; 2815 + } 2816 + 2817 + .btn-lg { 2818 + height: 4rem; 2819 + min-height: 4rem; 2820 + padding-left: 1.5rem; 2821 + padding-right: 1.5rem; 2822 + font-size: 1.125rem; 2823 + } 2824 + 2825 + .btn-block { 2826 + width: 100%; 2827 + } 2828 + 2829 + .btn-square:where(.btn-xs) { 2830 + height: 1.5rem; 2831 + width: 1.5rem; 2832 + padding: 0px; 2833 + } 2834 + 2835 + .btn-square:where(.btn-sm) { 2836 + height: 2rem; 2837 + width: 2rem; 2838 + padding: 0px; 2839 + } 2840 + 2841 + .btn-square:where(.btn-md) { 2842 + height: 3rem; 2843 + width: 3rem; 2844 + padding: 0px; 2845 + } 2846 + 2847 + .btn-square:where(.btn-lg) { 2848 + height: 4rem; 2849 + width: 4rem; 2850 + padding: 0px; 2851 + } 2852 + 2853 + .btn-circle:where(.btn-xs) { 2854 + height: 1.5rem; 2855 + width: 1.5rem; 2856 + border-radius: 9999px; 2857 + padding: 0px; 2858 + } 2859 + 2860 + .btn-circle:where(.btn-sm) { 2861 + height: 2rem; 2862 + width: 2rem; 2863 + border-radius: 9999px; 2864 + padding: 0px; 2865 + } 2866 + 2867 + .btn-circle:where(.btn-lg) { 2868 + height: 4rem; 2869 + width: 4rem; 2870 + border-radius: 9999px; 2871 + padding: 0px; 2872 + } 2873 + 2874 + .drawer-open > .drawer-toggle { 2875 + display: none; 2876 + } 2877 + 2878 + .drawer-open > .drawer-toggle ~ .drawer-side { 2879 + pointer-events: auto; 2880 + visibility: visible; 2881 + position: sticky; 2882 + display: block; 2883 + width: auto; 2884 + overscroll-behavior: auto; 2885 + } 2886 + 2887 + .drawer-open > .drawer-toggle ~ .drawer-side > *:not(.drawer-overlay) { 2888 + transform: translateX(0%); 2889 + } 2890 + 2891 + [dir="rtl"] .drawer-open > .drawer-toggle ~ .drawer-side > *:not(.drawer-overlay) { 2892 + transform: translateX(0%); 2893 + } 2894 + 2895 + .drawer-open > .drawer-toggle:checked ~ .drawer-side { 2896 + pointer-events: auto; 2897 + visibility: visible; 2898 + } 2899 + 2900 + .drawer-open > .drawer-side { 2901 + overflow-y: auto; 2902 + } 2903 + 2904 + html:has(.drawer-toggle:checked) { 2905 + overflow-y: hidden; 2906 + scrollbar-gutter: stable; 2907 + } 2908 + 2909 + .join.join-vertical { 2910 + flex-direction: column; 2911 + } 2912 + 2913 + .join.join-vertical .join-item:first-child:not(:last-child), 2914 + .join.join-vertical *:first-child:not(:last-child) .join-item { 2915 + border-end-start-radius: 0; 2916 + border-end-end-radius: 0; 2917 + border-start-start-radius: inherit; 2918 + border-start-end-radius: inherit; 2919 + } 2920 + 2921 + .join.join-vertical .join-item:last-child:not(:first-child), 2922 + .join.join-vertical *:last-child:not(:first-child) .join-item { 2923 + border-start-start-radius: 0; 2924 + border-start-end-radius: 0; 2925 + border-end-start-radius: inherit; 2926 + border-end-end-radius: inherit; 2927 + } 2928 + 2929 + .join.join-horizontal { 2930 + flex-direction: row; 2931 + } 2932 + 2933 + .join.join-horizontal .join-item:first-child:not(:last-child), 2934 + .join.join-horizontal *:first-child:not(:last-child) .join-item { 2935 + border-end-end-radius: 0; 2936 + border-start-end-radius: 0; 2937 + border-end-start-radius: inherit; 2938 + border-start-start-radius: inherit; 2939 + } 2940 + 2941 + .join.join-horizontal .join-item:last-child:not(:first-child), 2942 + .join.join-horizontal *:last-child:not(:first-child) .join-item { 2943 + border-end-start-radius: 0; 2944 + border-start-start-radius: 0; 2945 + border-end-end-radius: inherit; 2946 + border-start-end-radius: inherit; 2947 + } 2948 + 2949 + .select-sm { 2950 + height: 2rem; 2951 + min-height: 2rem; 2952 + padding-left: 0.75rem; 2953 + padding-right: 2rem; 2954 + font-size: 0.875rem; 2955 + line-height: 2rem; 2956 + } 2957 + 2958 + [dir="rtl"] .select-sm { 2959 + padding-left: 2rem; 2960 + padding-right: 0.75rem; 2961 + } 2962 + 2963 + .avatar.online:before { 2964 + content: ""; 2965 + position: absolute; 2966 + z-index: 10; 2967 + display: block; 2968 + border-radius: 9999px; 2969 + --tw-bg-opacity: 1; 2970 + background-color: var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity))); 2971 + outline-style: solid; 2972 + outline-width: 2px; 2973 + outline-color: var(--fallback-b1,oklch(var(--b1)/1)); 2974 + width: 15%; 2975 + height: 15%; 2976 + top: 7%; 2977 + right: 7%; 2978 + } 2979 + 2980 + .avatar.offline:before { 2981 + content: ""; 2982 + position: absolute; 2983 + z-index: 10; 2984 + display: block; 2985 + border-radius: 9999px; 2986 + --tw-bg-opacity: 1; 2987 + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); 2988 + outline-style: solid; 2989 + outline-width: 2px; 2990 + outline-color: var(--fallback-b1,oklch(var(--b1)/1)); 2991 + width: 15%; 2992 + height: 15%; 2993 + top: 7%; 2994 + right: 7%; 2995 + } 2996 + 2997 + .drawer-open > .drawer-toggle ~ .drawer-side > .drawer-overlay { 2998 + cursor: default; 2999 + background-color: transparent; 3000 + } 3001 + 3002 + .join.join-vertical > :where(*:not(:first-child)) { 3003 + margin-left: 0px; 3004 + margin-right: 0px; 3005 + margin-top: -1px; 3006 + } 3007 + 3008 + .join.join-horizontal > :where(*:not(:first-child)) { 3009 + margin-top: 0px; 3010 + margin-bottom: 0px; 3011 + margin-inline-start: -1px; 3012 + } 3013 + 3014 + .static { 3015 + position: static; 3016 + } 3017 + 3018 + .fixed { 3019 + position: fixed; 3020 + } 3021 + 3022 + .order-first { 3023 + order: -9999; 3024 + } 3025 + 3026 + .m-10 { 3027 + margin: 2.5rem; 3028 + } 3029 + 3030 + .mx-auto { 3031 + margin-left: auto; 3032 + margin-right: auto; 3033 + } 3034 + 3035 + .my-4 { 3036 + margin-top: 1rem; 3037 + margin-bottom: 1rem; 3038 + } 3039 + 3040 + .mb-10 { 3041 + margin-bottom: 2.5rem; 3042 + } 3043 + 3044 + .mb-6 { 3045 + margin-bottom: 1.5rem; 3046 + } 3047 + 3048 + .mb-4 { 3049 + margin-bottom: 1rem; 3050 + } 3051 + 3052 + .mr-10 { 3053 + margin-right: 2.5rem; 3054 + } 3055 + 3056 + .mr-2 { 3057 + margin-right: 0.5rem; 3058 + } 3059 + 3060 + .mt-4 { 3061 + margin-top: 1rem; 3062 + } 3063 + 3064 + .mr-4 { 3065 + margin-right: 1rem; 3066 + } 3067 + 3068 + .ml-4 { 3069 + margin-left: 1rem; 3070 + } 3071 + 3072 + .ml-2 { 3073 + margin-left: 0.5rem; 3074 + } 3075 + 3076 + .mb-2 { 3077 + margin-bottom: 0.5rem; 3078 + } 3079 + 3080 + .mb-1 { 3081 + margin-bottom: 0.25rem; 3082 + } 3083 + 3084 + .-ml-2 { 3085 + margin-left: -0.5rem; 3086 + } 3087 + 3088 + .ml-64 { 3089 + margin-left: 16rem; 3090 + } 3091 + 3092 + .ml-72 { 3093 + margin-left: 18rem; 3094 + } 3095 + 3096 + .mr-1 { 3097 + margin-right: 0.25rem; 3098 + } 3099 + 3100 + .ml-36 { 3101 + margin-left: 9rem; 3102 + } 3103 + 3104 + .ml-20 { 3105 + margin-left: 5rem; 3106 + } 3107 + 3108 + .mt-8 { 3109 + margin-top: 2rem; 3110 + } 3111 + 3112 + .block { 3113 + display: block; 3114 + } 3115 + 3116 + .inline-block { 3117 + display: inline-block; 3118 + } 3119 + 3120 + .flex { 3121 + display: flex; 3122 + } 3123 + 3124 + .table { 3125 + display: table; 3126 + } 3127 + 3128 + .grid { 3129 + display: grid; 3130 + } 3131 + 3132 + .hidden { 3133 + display: none; 3134 + } 3135 + 3136 + .h-20 { 3137 + height: 5rem; 3138 + } 3139 + 3140 + .h-10 { 3141 + height: 2.5rem; 3142 + } 3143 + 3144 + .h-6 { 3145 + height: 1.5rem; 3146 + } 3147 + 3148 + .h-full { 3149 + height: 100%; 3150 + } 3151 + 3152 + .h-screen { 3153 + height: 100vh; 3154 + } 3155 + 3156 + .h-24 { 3157 + height: 6rem; 3158 + } 3159 + 3160 + .h-32 { 3161 + height: 8rem; 3162 + } 3163 + 3164 + .h-8 { 3165 + height: 2rem; 3166 + } 3167 + 3168 + .h-12 { 3169 + height: 3rem; 3170 + } 3171 + 3172 + .h-16 { 3173 + height: 4rem; 3174 + } 3175 + 3176 + .h-7 { 3177 + height: 1.75rem; 3178 + } 3179 + 3180 + .h-4 { 3181 + height: 1rem; 3182 + } 3183 + 3184 + .h-5 { 3185 + height: 1.25rem; 3186 + } 3187 + 3188 + .min-h-full { 3189 + min-height: 100%; 3190 + } 3191 + 3192 + .min-h-screen { 3193 + min-height: 100vh; 3194 + } 3195 + 3196 + .w-full { 3197 + width: 100%; 3198 + } 3199 + 3200 + .w-10 { 3201 + width: 2.5rem; 3202 + } 3203 + 3204 + .w-6 { 3205 + width: 1.5rem; 3206 + } 3207 + 3208 + .w-80 { 3209 + width: 20rem; 3210 + } 3211 + 3212 + .w-56 { 3213 + width: 14rem; 3214 + } 3215 + 3216 + .w-64 { 3217 + width: 16rem; 3218 + } 3219 + 3220 + .w-72 { 3221 + width: 18rem; 3222 + } 3223 + 3224 + .w-52 { 3225 + width: 13rem; 3226 + } 3227 + 3228 + .w-8 { 3229 + width: 2rem; 3230 + } 3231 + 3232 + .w-12 { 3233 + width: 3rem; 3234 + } 3235 + 3236 + .w-32 { 3237 + width: 8rem; 3238 + } 3239 + 3240 + .w-24 { 3241 + width: 6rem; 3242 + } 3243 + 3244 + .w-48 { 3245 + width: 12rem; 3246 + } 3247 + 3248 + .w-96 { 3249 + width: 24rem; 3250 + } 3251 + 3252 + .w-16 { 3253 + width: 4rem; 3254 + } 3255 + 3256 + .w-4 { 3257 + width: 1rem; 3258 + } 3259 + 3260 + .w-36 { 3261 + width: 9rem; 3262 + } 3263 + 3264 + .w-20 { 3265 + width: 5rem; 3266 + } 3267 + 3268 + .w-7 { 3269 + width: 1.75rem; 3270 + } 3271 + 3272 + .w-5 { 3273 + width: 1.25rem; 3274 + } 3275 + 3276 + .max-w-3xl { 3277 + max-width: 48rem; 3278 + } 3279 + 3280 + .max-w-4xl { 3281 + max-width: 56rem; 3282 + } 3283 + 3284 + .max-w-xl { 3285 + max-width: 36rem; 3286 + } 3287 + 3288 + .max-w-lg { 3289 + max-width: 32rem; 3290 + } 3291 + 3292 + .max-w-md { 3293 + max-width: 28rem; 3294 + } 3295 + 3296 + .max-w-2xl { 3297 + max-width: 42rem; 3298 + } 3299 + 3300 + .max-w-xs { 3301 + max-width: 20rem; 3302 + } 3303 + 3304 + .max-w-80 { 3305 + max-width: 20rem; 3306 + } 3307 + 3308 + .max-w-sm { 3309 + max-width: 24rem; 3310 + } 3311 + 3312 + .flex-none { 3313 + flex: none; 3314 + } 3315 + 3316 + .flex-grow { 3317 + flex-grow: 1; 3318 + } 3319 + 3320 + .grow { 3321 + flex-grow: 1; 3322 + } 3323 + 3324 + .cursor-pointer { 3325 + cursor: pointer; 3326 + } 3327 + 3328 + .flex-row { 3329 + flex-direction: row; 3330 + } 3331 + 3332 + .flex-col { 3333 + flex-direction: column; 3334 + } 3335 + 3336 + .place-items-center { 3337 + place-items: center; 3338 + } 3339 + 3340 + .items-start { 3341 + align-items: flex-start; 3342 + } 3343 + 3344 + .items-end { 3345 + align-items: flex-end; 3346 + } 3347 + 3348 + .items-center { 3349 + align-items: center; 3350 + } 3351 + 3352 + .justify-start { 3353 + justify-content: flex-start; 3354 + } 3355 + 3356 + .justify-end { 3357 + justify-content: flex-end; 3358 + } 3359 + 3360 + .justify-center { 3361 + justify-content: center; 3362 + } 3363 + 3364 + .gap-3 { 3365 + gap: 0.75rem; 3366 + } 3367 + 3368 + .gap-2 { 3369 + gap: 0.5rem; 3370 + } 3371 + 3372 + .self-end { 3373 + align-self: flex-end; 3374 + } 3375 + 3376 + .overflow-hidden { 3377 + overflow: hidden; 3378 + } 3379 + 3380 + .overflow-y-auto { 3381 + overflow-y: auto; 3382 + } 3383 + 3384 + .whitespace-pre-line { 3385 + white-space: pre-line; 3386 + } 3387 + 3388 + .rounded-box { 3389 + border-radius: var(--rounded-box, 1rem); 3390 + } 3391 + 3392 + .rounded { 3393 + border-radius: 0.25rem; 3394 + } 3395 + 3396 + .rounded-full { 3397 + border-radius: 9999px; 3398 + } 3399 + 3400 + .border { 3401 + border-width: 1px; 3402 + } 3403 + 3404 + .border-l-2 { 3405 + border-left-width: 2px; 3406 + } 3407 + 3408 + .border-base-300 { 3409 + --tw-border-opacity: 1; 3410 + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))); 3411 + } 3412 + 3413 + .border-neutral { 3414 + --tw-border-opacity: 1; 3415 + border-color: var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity))); 3416 + } 3417 + 3418 + .bg-base-300 { 3419 + --tw-bg-opacity: 1; 3420 + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); 3421 + } 3422 + 3423 + .bg-base-200 { 3424 + --tw-bg-opacity: 1; 3425 + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); 3426 + } 3427 + 3428 + .bg-black { 3429 + --tw-bg-opacity: 1; 3430 + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); 3431 + } 3432 + 3433 + .bg-neutral { 3434 + --tw-bg-opacity: 1; 3435 + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); 3436 + } 3437 + 3438 + .bg-blue-500 { 3439 + --tw-bg-opacity: 1; 3440 + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); 3441 + } 3442 + 3443 + .bg-base-100 { 3444 + --tw-bg-opacity: 1; 3445 + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); 3446 + } 3447 + 3448 + .stroke-current { 3449 + stroke: currentColor; 3450 + } 3451 + 3452 + .p-10 { 3453 + padding: 2.5rem; 3454 + } 3455 + 3456 + .p-4 { 3457 + padding: 1rem; 3458 + } 3459 + 3460 + .p-6 { 3461 + padding: 1.5rem; 3462 + } 3463 + 3464 + .p-8 { 3465 + padding: 2rem; 3466 + } 3467 + 3468 + .p-2 { 3469 + padding: 0.5rem; 3470 + } 3471 + 3472 + .p-1 { 3473 + padding: 0.25rem; 3474 + } 3475 + 3476 + .px-4 { 3477 + padding-left: 1rem; 3478 + padding-right: 1rem; 3479 + } 3480 + 3481 + .py-2 { 3482 + padding-top: 0.5rem; 3483 + padding-bottom: 0.5rem; 3484 + } 3485 + 3486 + .text-left { 3487 + text-align: left; 3488 + } 3489 + 3490 + .text-center { 3491 + text-align: center; 3492 + } 3493 + 3494 + .align-middle { 3495 + vertical-align: middle; 3496 + } 3497 + 3498 + .font-mono { 3499 + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 3500 + } 3501 + 3502 + .text-sm { 3503 + font-size: 0.875rem; 3504 + line-height: 1.25rem; 3505 + } 3506 + 3507 + .text-2xl { 3508 + font-size: 1.5rem; 3509 + line-height: 2rem; 3510 + } 3511 + 3512 + .text-xl { 3513 + font-size: 1.25rem; 3514 + line-height: 1.75rem; 3515 + } 3516 + 3517 + .text-xs { 3518 + font-size: 0.75rem; 3519 + line-height: 1rem; 3520 + } 3521 + 3522 + .text-base { 3523 + font-size: 1rem; 3524 + line-height: 1.5rem; 3525 + } 3526 + 3527 + .text-3xl { 3528 + font-size: 1.875rem; 3529 + line-height: 2.25rem; 3530 + } 3531 + 3532 + .text-4xl { 3533 + font-size: 2.25rem; 3534 + line-height: 2.5rem; 3535 + } 3536 + 3537 + .font-bold { 3538 + font-weight: 700; 3539 + } 3540 + 3541 + .font-semibold { 3542 + font-weight: 600; 3543 + } 3544 + 3545 + .capitalize { 3546 + text-transform: capitalize; 3547 + } 3548 + 3549 + .italic { 3550 + font-style: italic; 3551 + } 3552 + 3553 + .text-base-100 { 3554 + --tw-text-opacity: 1; 3555 + color: var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity))); 3556 + } 3557 + 3558 + .text-base-300 { 3559 + --tw-text-opacity: 1; 3560 + color: var(--fallback-b3,oklch(var(--b3)/var(--tw-text-opacity))); 3561 + } 3562 + 3563 + .text-neutral { 3564 + --tw-text-opacity: 1; 3565 + color: var(--fallback-n,oklch(var(--n)/var(--tw-text-opacity))); 3566 + } 3567 + 3568 + .text-base-content { 3569 + --tw-text-opacity: 1; 3570 + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); 3571 + } 3572 + 3573 + .text-blue-500 { 3574 + --tw-text-opacity: 1; 3575 + color: rgb(59 130 246 / var(--tw-text-opacity)); 3576 + } 3577 + 3578 + .text-neutral-content { 3579 + --tw-text-opacity: 1; 3580 + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); 3581 + } 3582 + 3583 + .text-white { 3584 + --tw-text-opacity: 1; 3585 + color: rgb(255 255 255 / var(--tw-text-opacity)); 3586 + } 3587 + 3588 + .text-secondary { 3589 + --tw-text-opacity: 1; 3590 + color: var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity))); 3591 + } 3592 + 3593 + .text-accent { 3594 + --tw-text-opacity: 1; 3595 + color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity))); 3596 + } 3597 + 3598 + .text-success { 3599 + --tw-text-opacity: 1; 3600 + color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity))); 3601 + } 3602 + 3603 + .text-error { 3604 + --tw-text-opacity: 1; 3605 + color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))); 3606 + } 3607 + 3608 + .text-warning { 3609 + --tw-text-opacity: 1; 3610 + color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity))); 3611 + } 3612 + 3613 + .underline { 3614 + text-decoration-line: underline; 3615 + } 3616 + 3617 + .opacity-50 { 3618 + opacity: 0.5; 3619 + } 3620 + 3621 + .opacity-70 { 3622 + opacity: 0.7; 3623 + } 3624 + 3625 + .shadow { 3626 + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); 3627 + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); 3628 + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); 3629 + } 3630 + 3631 + .ring { 3632 + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); 3633 + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color); 3634 + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); 3635 + } 3636 + 3637 + .ring-primary { 3638 + --tw-ring-opacity: 1; 3639 + --tw-ring-color: var(--fallback-p,oklch(var(--p)/var(--tw-ring-opacity))); 3640 + } 3641 + 3642 + .ring-warning { 3643 + --tw-ring-opacity: 1; 3644 + --tw-ring-color: var(--fallback-wa,oklch(var(--wa)/var(--tw-ring-opacity))); 3645 + } 3646 + 3647 + .ring-neutral { 3648 + --tw-ring-opacity: 1; 3649 + --tw-ring-color: var(--fallback-n,oklch(var(--n)/var(--tw-ring-opacity))); 3650 + } 3651 + 3652 + .ring-offset-2 { 3653 + --tw-ring-offset-width: 2px; 3654 + } 3655 + 3656 + .ring-offset-base-100 { 3657 + --tw-ring-offset-color: var(--fallback-b1,oklch(var(--b1)/1)); 3658 + } 3659 + 3660 + .ring-offset-neutral { 3661 + --tw-ring-offset-color: var(--fallback-n,oklch(var(--n)/1)); 3662 + } 3663 + 3664 + @media (min-width: 1024px) { 3665 + .lg\:btn-sm { 3666 + height: 2rem; 3667 + min-height: 2rem; 3668 + padding-left: 0.75rem; 3669 + padding-right: 0.75rem; 3670 + font-size: 0.875rem; 3671 + } 3672 + 3673 + .lg\:btn-lg { 3674 + height: 4rem; 3675 + min-height: 4rem; 3676 + padding-left: 1.5rem; 3677 + padding-right: 1.5rem; 3678 + font-size: 1.125rem; 3679 + } 3680 + 3681 + .lg\:btn-block { 3682 + width: 100%; 3683 + } 3684 + 3685 + .btn-square:where(.lg\:btn-sm) { 3686 + height: 2rem; 3687 + width: 2rem; 3688 + padding: 0px; 3689 + } 3690 + 3691 + .btn-square:where(.lg\:btn-lg) { 3692 + height: 4rem; 3693 + width: 4rem; 3694 + padding: 0px; 3695 + } 3696 + 3697 + .btn-circle:where(.lg\:btn-sm) { 3698 + height: 2rem; 3699 + width: 2rem; 3700 + border-radius: 9999px; 3701 + padding: 0px; 3702 + } 3703 + 3704 + .btn-circle:where(.lg\:btn-lg) { 3705 + height: 4rem; 3706 + width: 4rem; 3707 + border-radius: 9999px; 3708 + padding: 0px; 3709 + } 3710 + 3711 + .lg\:drawer-open > .drawer-toggle { 3712 + display: none; 3713 + } 3714 + 3715 + .lg\:drawer-open > .drawer-toggle ~ .drawer-side { 3716 + pointer-events: auto; 3717 + visibility: visible; 3718 + position: sticky; 3719 + display: block; 3720 + width: auto; 3721 + overscroll-behavior: auto; 3722 + } 3723 + 3724 + .lg\:drawer-open > .drawer-toggle ~ .drawer-side > *:not(.drawer-overlay) { 3725 + transform: translateX(0%); 3726 + } 3727 + 3728 + [dir="rtl"] .lg\:drawer-open > .drawer-toggle ~ .drawer-side > *:not(.drawer-overlay) { 3729 + transform: translateX(0%); 3730 + } 3731 + 3732 + .lg\:drawer-open > .drawer-toggle:checked ~ .drawer-side { 3733 + pointer-events: auto; 3734 + visibility: visible; 3735 + } 3736 + 3737 + .lg\:drawer-open > .drawer-side { 3738 + overflow-y: auto; 3739 + } 3740 + 3741 + html:has(.lg\:drawer-open.lg\:drawer-open) { 3742 + overflow-y: auto; 3743 + scrollbar-gutter: auto; 3744 + } 3745 + 3746 + .lg\:drawer-open > .drawer-toggle ~ .drawer-side > .drawer-overlay { 3747 + cursor: default; 3748 + background-color: transparent; 3749 + } 3750 + } 3751 + 3752 + .hover\:bg-blue-700:hover { 3753 + --tw-bg-opacity: 1; 3754 + background-color: rgb(29 78 216 / var(--tw-bg-opacity)); 3755 + } 3756 + 3757 + @media (min-width: 640px) { 3758 + .sm\:max-w-md { 3759 + max-width: 28rem; 3760 + } 3761 + 3762 + .sm\:flex-row { 3763 + flex-direction: row; 3764 + } 3765 + } 3766 + 3767 + @media (min-width: 768px) { 3768 + .md\:max-w-md { 3769 + max-width: 28rem; 3770 + } 3771 + 3772 + .md\:flex-row { 3773 + flex-direction: row; 3774 + } 3775 + } 3776 + 3777 + @media (min-width: 1024px) { 3778 + .lg\:order-none { 3779 + order: 0; 3780 + } 3781 + 3782 + .lg\:ml-72 { 3783 + margin-left: 18rem; 3784 + } 3785 + 3786 + .lg\:block { 3787 + display: block; 3788 + } 3789 + 3790 + .lg\:flex { 3791 + display: flex; 3792 + } 3793 + 3794 + .lg\:hidden { 3795 + display: none; 3796 + } 3797 + 3798 + .lg\:h-7 { 3799 + height: 1.75rem; 3800 + } 3801 + 3802 + .lg\:w-72 { 3803 + width: 18rem; 3804 + } 3805 + 3806 + .lg\:w-full { 3807 + width: 100%; 3808 + } 3809 + 3810 + .lg\:w-7 { 3811 + width: 1.75rem; 3812 + } 3813 + 3814 + .lg\:max-w-md { 3815 + max-width: 28rem; 3816 + } 3817 + 3818 + .lg\:flex-row { 3819 + flex-direction: row; 3820 + } 3821 + 3822 + .lg\:justify-start { 3823 + justify-content: flex-start; 3824 + } 3825 + 3826 + .lg\:p-4 { 3827 + padding: 1rem; 3828 + } 3829 + 3830 + .lg\:p-2 { 3831 + padding: 0.5rem; 3832 + } 3833 + 3834 + .lg\:p-1 { 3835 + padding: 0.25rem; 3836 + } 3837 + 3838 + .lg\:p-3 { 3839 + padding: 0.75rem; 3840 + } 3841 + 3842 + .lg\:px-3 { 3843 + padding-left: 0.75rem; 3844 + padding-right: 0.75rem; 3845 + } 3846 + }
+3
theme/input.css
··· 1 + @tailwind base; 2 + @tailwind components; 3 + @tailwind utilities;
+1425
theme/package-lock.json
··· 1 + { 2 + "name": "theme", 3 + "version": "1.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "theme", 9 + "version": "1.0.0", 10 + "license": "MIT", 11 + "devDependencies": { 12 + "daisyui": "^4.7.2", 13 + "tailwindcss": "^3.4.1" 14 + } 15 + }, 16 + "node_modules/@alloc/quick-lru": { 17 + "version": "5.2.0", 18 + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", 19 + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", 20 + "dev": true, 21 + "engines": { 22 + "node": ">=10" 23 + }, 24 + "funding": { 25 + "url": "https://github.com/sponsors/sindresorhus" 26 + } 27 + }, 28 + "node_modules/@isaacs/cliui": { 29 + "version": "8.0.2", 30 + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 31 + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 32 + "dev": true, 33 + "dependencies": { 34 + "string-width": "^5.1.2", 35 + "string-width-cjs": "npm:string-width@^4.2.0", 36 + "strip-ansi": "^7.0.1", 37 + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 38 + "wrap-ansi": "^8.1.0", 39 + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 40 + }, 41 + "engines": { 42 + "node": ">=12" 43 + } 44 + }, 45 + "node_modules/@jridgewell/gen-mapping": { 46 + "version": "0.3.5", 47 + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 48 + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 49 + "dev": true, 50 + "dependencies": { 51 + "@jridgewell/set-array": "^1.2.1", 52 + "@jridgewell/sourcemap-codec": "^1.4.10", 53 + "@jridgewell/trace-mapping": "^0.3.24" 54 + }, 55 + "engines": { 56 + "node": ">=6.0.0" 57 + } 58 + }, 59 + "node_modules/@jridgewell/resolve-uri": { 60 + "version": "3.1.2", 61 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 62 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 63 + "dev": true, 64 + "engines": { 65 + "node": ">=6.0.0" 66 + } 67 + }, 68 + "node_modules/@jridgewell/set-array": { 69 + "version": "1.2.1", 70 + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 71 + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 72 + "dev": true, 73 + "engines": { 74 + "node": ">=6.0.0" 75 + } 76 + }, 77 + "node_modules/@jridgewell/sourcemap-codec": { 78 + "version": "1.4.15", 79 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 80 + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 81 + "dev": true 82 + }, 83 + "node_modules/@jridgewell/trace-mapping": { 84 + "version": "0.3.25", 85 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 86 + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 87 + "dev": true, 88 + "dependencies": { 89 + "@jridgewell/resolve-uri": "^3.1.0", 90 + "@jridgewell/sourcemap-codec": "^1.4.14" 91 + } 92 + }, 93 + "node_modules/@nodelib/fs.scandir": { 94 + "version": "2.1.5", 95 + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 96 + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 97 + "dev": true, 98 + "dependencies": { 99 + "@nodelib/fs.stat": "2.0.5", 100 + "run-parallel": "^1.1.9" 101 + }, 102 + "engines": { 103 + "node": ">= 8" 104 + } 105 + }, 106 + "node_modules/@nodelib/fs.stat": { 107 + "version": "2.0.5", 108 + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 109 + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 110 + "dev": true, 111 + "engines": { 112 + "node": ">= 8" 113 + } 114 + }, 115 + "node_modules/@nodelib/fs.walk": { 116 + "version": "1.2.8", 117 + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 118 + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 119 + "dev": true, 120 + "dependencies": { 121 + "@nodelib/fs.scandir": "2.1.5", 122 + "fastq": "^1.6.0" 123 + }, 124 + "engines": { 125 + "node": ">= 8" 126 + } 127 + }, 128 + "node_modules/@pkgjs/parseargs": { 129 + "version": "0.11.0", 130 + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 131 + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 132 + "dev": true, 133 + "optional": true, 134 + "engines": { 135 + "node": ">=14" 136 + } 137 + }, 138 + "node_modules/ansi-regex": { 139 + "version": "6.0.1", 140 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 141 + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 142 + "dev": true, 143 + "engines": { 144 + "node": ">=12" 145 + }, 146 + "funding": { 147 + "url": "https://github.com/chalk/ansi-regex?sponsor=1" 148 + } 149 + }, 150 + "node_modules/ansi-styles": { 151 + "version": "6.2.1", 152 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 153 + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 154 + "dev": true, 155 + "engines": { 156 + "node": ">=12" 157 + }, 158 + "funding": { 159 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 160 + } 161 + }, 162 + "node_modules/any-promise": { 163 + "version": "1.3.0", 164 + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 165 + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", 166 + "dev": true 167 + }, 168 + "node_modules/anymatch": { 169 + "version": "3.1.3", 170 + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 171 + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 172 + "dev": true, 173 + "dependencies": { 174 + "normalize-path": "^3.0.0", 175 + "picomatch": "^2.0.4" 176 + }, 177 + "engines": { 178 + "node": ">= 8" 179 + } 180 + }, 181 + "node_modules/arg": { 182 + "version": "5.0.2", 183 + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", 184 + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", 185 + "dev": true 186 + }, 187 + "node_modules/balanced-match": { 188 + "version": "1.0.2", 189 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 190 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 191 + "dev": true 192 + }, 193 + "node_modules/binary-extensions": { 194 + "version": "2.2.0", 195 + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 196 + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 197 + "dev": true, 198 + "engines": { 199 + "node": ">=8" 200 + } 201 + }, 202 + "node_modules/brace-expansion": { 203 + "version": "2.0.1", 204 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 205 + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 206 + "dev": true, 207 + "dependencies": { 208 + "balanced-match": "^1.0.0" 209 + } 210 + }, 211 + "node_modules/braces": { 212 + "version": "3.0.2", 213 + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 214 + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 215 + "dev": true, 216 + "dependencies": { 217 + "fill-range": "^7.0.1" 218 + }, 219 + "engines": { 220 + "node": ">=8" 221 + } 222 + }, 223 + "node_modules/camelcase-css": { 224 + "version": "2.0.1", 225 + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", 226 + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", 227 + "dev": true, 228 + "engines": { 229 + "node": ">= 6" 230 + } 231 + }, 232 + "node_modules/chokidar": { 233 + "version": "3.6.0", 234 + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 235 + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 236 + "dev": true, 237 + "dependencies": { 238 + "anymatch": "~3.1.2", 239 + "braces": "~3.0.2", 240 + "glob-parent": "~5.1.2", 241 + "is-binary-path": "~2.1.0", 242 + "is-glob": "~4.0.1", 243 + "normalize-path": "~3.0.0", 244 + "readdirp": "~3.6.0" 245 + }, 246 + "engines": { 247 + "node": ">= 8.10.0" 248 + }, 249 + "funding": { 250 + "url": "https://paulmillr.com/funding/" 251 + }, 252 + "optionalDependencies": { 253 + "fsevents": "~2.3.2" 254 + } 255 + }, 256 + "node_modules/chokidar/node_modules/glob-parent": { 257 + "version": "5.1.2", 258 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 259 + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 260 + "dev": true, 261 + "dependencies": { 262 + "is-glob": "^4.0.1" 263 + }, 264 + "engines": { 265 + "node": ">= 6" 266 + } 267 + }, 268 + "node_modules/color-convert": { 269 + "version": "2.0.1", 270 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 271 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 272 + "dev": true, 273 + "dependencies": { 274 + "color-name": "~1.1.4" 275 + }, 276 + "engines": { 277 + "node": ">=7.0.0" 278 + } 279 + }, 280 + "node_modules/color-name": { 281 + "version": "1.1.4", 282 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 283 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 284 + "dev": true 285 + }, 286 + "node_modules/commander": { 287 + "version": "4.1.1", 288 + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 289 + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 290 + "dev": true, 291 + "engines": { 292 + "node": ">= 6" 293 + } 294 + }, 295 + "node_modules/cross-spawn": { 296 + "version": "7.0.3", 297 + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 298 + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 299 + "dev": true, 300 + "dependencies": { 301 + "path-key": "^3.1.0", 302 + "shebang-command": "^2.0.0", 303 + "which": "^2.0.1" 304 + }, 305 + "engines": { 306 + "node": ">= 8" 307 + } 308 + }, 309 + "node_modules/css-selector-tokenizer": { 310 + "version": "0.8.0", 311 + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", 312 + "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", 313 + "dev": true, 314 + "dependencies": { 315 + "cssesc": "^3.0.0", 316 + "fastparse": "^1.1.2" 317 + } 318 + }, 319 + "node_modules/cssesc": { 320 + "version": "3.0.0", 321 + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 322 + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 323 + "dev": true, 324 + "bin": { 325 + "cssesc": "bin/cssesc" 326 + }, 327 + "engines": { 328 + "node": ">=4" 329 + } 330 + }, 331 + "node_modules/culori": { 332 + "version": "3.3.0", 333 + "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz", 334 + "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==", 335 + "dev": true, 336 + "engines": { 337 + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 338 + } 339 + }, 340 + "node_modules/daisyui": { 341 + "version": "4.7.2", 342 + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.7.2.tgz", 343 + "integrity": "sha512-9UCss12Zmyk/22u+JbkVrHHxOzFOyY17HuqP5LeswI4hclbj6qbjJTovdj2zRy8cCH6/n6Wh0lTLjriGnyGh0g==", 344 + "dev": true, 345 + "dependencies": { 346 + "css-selector-tokenizer": "^0.8", 347 + "culori": "^3", 348 + "picocolors": "^1", 349 + "postcss-js": "^4" 350 + }, 351 + "engines": { 352 + "node": ">=16.9.0" 353 + }, 354 + "funding": { 355 + "type": "opencollective", 356 + "url": "https://opencollective.com/daisyui" 357 + } 358 + }, 359 + "node_modules/didyoumean": { 360 + "version": "1.2.2", 361 + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", 362 + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", 363 + "dev": true 364 + }, 365 + "node_modules/dlv": { 366 + "version": "1.1.3", 367 + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 368 + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", 369 + "dev": true 370 + }, 371 + "node_modules/eastasianwidth": { 372 + "version": "0.2.0", 373 + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 374 + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 375 + "dev": true 376 + }, 377 + "node_modules/emoji-regex": { 378 + "version": "9.2.2", 379 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 380 + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 381 + "dev": true 382 + }, 383 + "node_modules/fast-glob": { 384 + "version": "3.3.2", 385 + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", 386 + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", 387 + "dev": true, 388 + "dependencies": { 389 + "@nodelib/fs.stat": "^2.0.2", 390 + "@nodelib/fs.walk": "^1.2.3", 391 + "glob-parent": "^5.1.2", 392 + "merge2": "^1.3.0", 393 + "micromatch": "^4.0.4" 394 + }, 395 + "engines": { 396 + "node": ">=8.6.0" 397 + } 398 + }, 399 + "node_modules/fast-glob/node_modules/glob-parent": { 400 + "version": "5.1.2", 401 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 402 + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 403 + "dev": true, 404 + "dependencies": { 405 + "is-glob": "^4.0.1" 406 + }, 407 + "engines": { 408 + "node": ">= 6" 409 + } 410 + }, 411 + "node_modules/fastparse": { 412 + "version": "1.1.2", 413 + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", 414 + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", 415 + "dev": true 416 + }, 417 + "node_modules/fastq": { 418 + "version": "1.17.1", 419 + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", 420 + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", 421 + "dev": true, 422 + "dependencies": { 423 + "reusify": "^1.0.4" 424 + } 425 + }, 426 + "node_modules/fill-range": { 427 + "version": "7.0.1", 428 + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 429 + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 430 + "dev": true, 431 + "dependencies": { 432 + "to-regex-range": "^5.0.1" 433 + }, 434 + "engines": { 435 + "node": ">=8" 436 + } 437 + }, 438 + "node_modules/foreground-child": { 439 + "version": "3.1.1", 440 + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 441 + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 442 + "dev": true, 443 + "dependencies": { 444 + "cross-spawn": "^7.0.0", 445 + "signal-exit": "^4.0.1" 446 + }, 447 + "engines": { 448 + "node": ">=14" 449 + }, 450 + "funding": { 451 + "url": "https://github.com/sponsors/isaacs" 452 + } 453 + }, 454 + "node_modules/fsevents": { 455 + "version": "2.3.3", 456 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 457 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 458 + "dev": true, 459 + "hasInstallScript": true, 460 + "optional": true, 461 + "os": [ 462 + "darwin" 463 + ], 464 + "engines": { 465 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 466 + } 467 + }, 468 + "node_modules/function-bind": { 469 + "version": "1.1.2", 470 + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 471 + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 472 + "dev": true, 473 + "funding": { 474 + "url": "https://github.com/sponsors/ljharb" 475 + } 476 + }, 477 + "node_modules/glob": { 478 + "version": "10.3.10", 479 + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", 480 + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", 481 + "dev": true, 482 + "dependencies": { 483 + "foreground-child": "^3.1.0", 484 + "jackspeak": "^2.3.5", 485 + "minimatch": "^9.0.1", 486 + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", 487 + "path-scurry": "^1.10.1" 488 + }, 489 + "bin": { 490 + "glob": "dist/esm/bin.mjs" 491 + }, 492 + "engines": { 493 + "node": ">=16 || 14 >=14.17" 494 + }, 495 + "funding": { 496 + "url": "https://github.com/sponsors/isaacs" 497 + } 498 + }, 499 + "node_modules/glob-parent": { 500 + "version": "6.0.2", 501 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 502 + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 503 + "dev": true, 504 + "dependencies": { 505 + "is-glob": "^4.0.3" 506 + }, 507 + "engines": { 508 + "node": ">=10.13.0" 509 + } 510 + }, 511 + "node_modules/hasown": { 512 + "version": "2.0.1", 513 + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", 514 + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", 515 + "dev": true, 516 + "dependencies": { 517 + "function-bind": "^1.1.2" 518 + }, 519 + "engines": { 520 + "node": ">= 0.4" 521 + } 522 + }, 523 + "node_modules/is-binary-path": { 524 + "version": "2.1.0", 525 + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 526 + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 527 + "dev": true, 528 + "dependencies": { 529 + "binary-extensions": "^2.0.0" 530 + }, 531 + "engines": { 532 + "node": ">=8" 533 + } 534 + }, 535 + "node_modules/is-core-module": { 536 + "version": "2.13.1", 537 + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", 538 + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", 539 + "dev": true, 540 + "dependencies": { 541 + "hasown": "^2.0.0" 542 + }, 543 + "funding": { 544 + "url": "https://github.com/sponsors/ljharb" 545 + } 546 + }, 547 + "node_modules/is-extglob": { 548 + "version": "2.1.1", 549 + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 550 + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 551 + "dev": true, 552 + "engines": { 553 + "node": ">=0.10.0" 554 + } 555 + }, 556 + "node_modules/is-fullwidth-code-point": { 557 + "version": "3.0.0", 558 + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 559 + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 560 + "dev": true, 561 + "engines": { 562 + "node": ">=8" 563 + } 564 + }, 565 + "node_modules/is-glob": { 566 + "version": "4.0.3", 567 + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 568 + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 569 + "dev": true, 570 + "dependencies": { 571 + "is-extglob": "^2.1.1" 572 + }, 573 + "engines": { 574 + "node": ">=0.10.0" 575 + } 576 + }, 577 + "node_modules/is-number": { 578 + "version": "7.0.0", 579 + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 580 + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 581 + "dev": true, 582 + "engines": { 583 + "node": ">=0.12.0" 584 + } 585 + }, 586 + "node_modules/isexe": { 587 + "version": "2.0.0", 588 + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 589 + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 590 + "dev": true 591 + }, 592 + "node_modules/jackspeak": { 593 + "version": "2.3.6", 594 + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", 595 + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", 596 + "dev": true, 597 + "dependencies": { 598 + "@isaacs/cliui": "^8.0.2" 599 + }, 600 + "engines": { 601 + "node": ">=14" 602 + }, 603 + "funding": { 604 + "url": "https://github.com/sponsors/isaacs" 605 + }, 606 + "optionalDependencies": { 607 + "@pkgjs/parseargs": "^0.11.0" 608 + } 609 + }, 610 + "node_modules/jiti": { 611 + "version": "1.21.0", 612 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", 613 + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", 614 + "dev": true, 615 + "bin": { 616 + "jiti": "bin/jiti.js" 617 + } 618 + }, 619 + "node_modules/lilconfig": { 620 + "version": "2.1.0", 621 + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", 622 + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", 623 + "dev": true, 624 + "engines": { 625 + "node": ">=10" 626 + } 627 + }, 628 + "node_modules/lines-and-columns": { 629 + "version": "1.2.4", 630 + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 631 + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", 632 + "dev": true 633 + }, 634 + "node_modules/lru-cache": { 635 + "version": "10.2.0", 636 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", 637 + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", 638 + "dev": true, 639 + "engines": { 640 + "node": "14 || >=16.14" 641 + } 642 + }, 643 + "node_modules/merge2": { 644 + "version": "1.4.1", 645 + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 646 + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 647 + "dev": true, 648 + "engines": { 649 + "node": ">= 8" 650 + } 651 + }, 652 + "node_modules/micromatch": { 653 + "version": "4.0.5", 654 + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 655 + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 656 + "dev": true, 657 + "dependencies": { 658 + "braces": "^3.0.2", 659 + "picomatch": "^2.3.1" 660 + }, 661 + "engines": { 662 + "node": ">=8.6" 663 + } 664 + }, 665 + "node_modules/minimatch": { 666 + "version": "9.0.3", 667 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", 668 + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", 669 + "dev": true, 670 + "dependencies": { 671 + "brace-expansion": "^2.0.1" 672 + }, 673 + "engines": { 674 + "node": ">=16 || 14 >=14.17" 675 + }, 676 + "funding": { 677 + "url": "https://github.com/sponsors/isaacs" 678 + } 679 + }, 680 + "node_modules/minipass": { 681 + "version": "7.0.4", 682 + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", 683 + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", 684 + "dev": true, 685 + "engines": { 686 + "node": ">=16 || 14 >=14.17" 687 + } 688 + }, 689 + "node_modules/mz": { 690 + "version": "2.7.0", 691 + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", 692 + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", 693 + "dev": true, 694 + "dependencies": { 695 + "any-promise": "^1.0.0", 696 + "object-assign": "^4.0.1", 697 + "thenify-all": "^1.0.0" 698 + } 699 + }, 700 + "node_modules/nanoid": { 701 + "version": "3.3.7", 702 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 703 + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 704 + "dev": true, 705 + "funding": [ 706 + { 707 + "type": "github", 708 + "url": "https://github.com/sponsors/ai" 709 + } 710 + ], 711 + "bin": { 712 + "nanoid": "bin/nanoid.cjs" 713 + }, 714 + "engines": { 715 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 716 + } 717 + }, 718 + "node_modules/normalize-path": { 719 + "version": "3.0.0", 720 + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 721 + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 722 + "dev": true, 723 + "engines": { 724 + "node": ">=0.10.0" 725 + } 726 + }, 727 + "node_modules/object-assign": { 728 + "version": "4.1.1", 729 + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 730 + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 731 + "dev": true, 732 + "engines": { 733 + "node": ">=0.10.0" 734 + } 735 + }, 736 + "node_modules/object-hash": { 737 + "version": "3.0.0", 738 + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", 739 + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", 740 + "dev": true, 741 + "engines": { 742 + "node": ">= 6" 743 + } 744 + }, 745 + "node_modules/path-key": { 746 + "version": "3.1.1", 747 + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 748 + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 749 + "dev": true, 750 + "engines": { 751 + "node": ">=8" 752 + } 753 + }, 754 + "node_modules/path-parse": { 755 + "version": "1.0.7", 756 + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 757 + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 758 + "dev": true 759 + }, 760 + "node_modules/path-scurry": { 761 + "version": "1.10.1", 762 + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", 763 + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", 764 + "dev": true, 765 + "dependencies": { 766 + "lru-cache": "^9.1.1 || ^10.0.0", 767 + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 768 + }, 769 + "engines": { 770 + "node": ">=16 || 14 >=14.17" 771 + }, 772 + "funding": { 773 + "url": "https://github.com/sponsors/isaacs" 774 + } 775 + }, 776 + "node_modules/picocolors": { 777 + "version": "1.0.0", 778 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 779 + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 780 + "dev": true 781 + }, 782 + "node_modules/picomatch": { 783 + "version": "2.3.1", 784 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 785 + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 786 + "dev": true, 787 + "engines": { 788 + "node": ">=8.6" 789 + }, 790 + "funding": { 791 + "url": "https://github.com/sponsors/jonschlinkert" 792 + } 793 + }, 794 + "node_modules/pify": { 795 + "version": "2.3.0", 796 + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 797 + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", 798 + "dev": true, 799 + "engines": { 800 + "node": ">=0.10.0" 801 + } 802 + }, 803 + "node_modules/pirates": { 804 + "version": "4.0.6", 805 + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", 806 + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", 807 + "dev": true, 808 + "engines": { 809 + "node": ">= 6" 810 + } 811 + }, 812 + "node_modules/postcss": { 813 + "version": "8.4.35", 814 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", 815 + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", 816 + "dev": true, 817 + "funding": [ 818 + { 819 + "type": "opencollective", 820 + "url": "https://opencollective.com/postcss/" 821 + }, 822 + { 823 + "type": "tidelift", 824 + "url": "https://tidelift.com/funding/github/npm/postcss" 825 + }, 826 + { 827 + "type": "github", 828 + "url": "https://github.com/sponsors/ai" 829 + } 830 + ], 831 + "dependencies": { 832 + "nanoid": "^3.3.7", 833 + "picocolors": "^1.0.0", 834 + "source-map-js": "^1.0.2" 835 + }, 836 + "engines": { 837 + "node": "^10 || ^12 || >=14" 838 + } 839 + }, 840 + "node_modules/postcss-import": { 841 + "version": "15.1.0", 842 + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", 843 + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", 844 + "dev": true, 845 + "dependencies": { 846 + "postcss-value-parser": "^4.0.0", 847 + "read-cache": "^1.0.0", 848 + "resolve": "^1.1.7" 849 + }, 850 + "engines": { 851 + "node": ">=14.0.0" 852 + }, 853 + "peerDependencies": { 854 + "postcss": "^8.0.0" 855 + } 856 + }, 857 + "node_modules/postcss-js": { 858 + "version": "4.0.1", 859 + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", 860 + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", 861 + "dev": true, 862 + "dependencies": { 863 + "camelcase-css": "^2.0.1" 864 + }, 865 + "engines": { 866 + "node": "^12 || ^14 || >= 16" 867 + }, 868 + "funding": { 869 + "type": "opencollective", 870 + "url": "https://opencollective.com/postcss/" 871 + }, 872 + "peerDependencies": { 873 + "postcss": "^8.4.21" 874 + } 875 + }, 876 + "node_modules/postcss-load-config": { 877 + "version": "4.0.2", 878 + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", 879 + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", 880 + "dev": true, 881 + "funding": [ 882 + { 883 + "type": "opencollective", 884 + "url": "https://opencollective.com/postcss/" 885 + }, 886 + { 887 + "type": "github", 888 + "url": "https://github.com/sponsors/ai" 889 + } 890 + ], 891 + "dependencies": { 892 + "lilconfig": "^3.0.0", 893 + "yaml": "^2.3.4" 894 + }, 895 + "engines": { 896 + "node": ">= 14" 897 + }, 898 + "peerDependencies": { 899 + "postcss": ">=8.0.9", 900 + "ts-node": ">=9.0.0" 901 + }, 902 + "peerDependenciesMeta": { 903 + "postcss": { 904 + "optional": true 905 + }, 906 + "ts-node": { 907 + "optional": true 908 + } 909 + } 910 + }, 911 + "node_modules/postcss-load-config/node_modules/lilconfig": { 912 + "version": "3.1.1", 913 + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", 914 + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", 915 + "dev": true, 916 + "engines": { 917 + "node": ">=14" 918 + }, 919 + "funding": { 920 + "url": "https://github.com/sponsors/antonk52" 921 + } 922 + }, 923 + "node_modules/postcss-nested": { 924 + "version": "6.0.1", 925 + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", 926 + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", 927 + "dev": true, 928 + "dependencies": { 929 + "postcss-selector-parser": "^6.0.11" 930 + }, 931 + "engines": { 932 + "node": ">=12.0" 933 + }, 934 + "funding": { 935 + "type": "opencollective", 936 + "url": "https://opencollective.com/postcss/" 937 + }, 938 + "peerDependencies": { 939 + "postcss": "^8.2.14" 940 + } 941 + }, 942 + "node_modules/postcss-selector-parser": { 943 + "version": "6.0.15", 944 + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", 945 + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", 946 + "dev": true, 947 + "dependencies": { 948 + "cssesc": "^3.0.0", 949 + "util-deprecate": "^1.0.2" 950 + }, 951 + "engines": { 952 + "node": ">=4" 953 + } 954 + }, 955 + "node_modules/postcss-value-parser": { 956 + "version": "4.2.0", 957 + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 958 + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 959 + "dev": true 960 + }, 961 + "node_modules/queue-microtask": { 962 + "version": "1.2.3", 963 + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 964 + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 965 + "dev": true, 966 + "funding": [ 967 + { 968 + "type": "github", 969 + "url": "https://github.com/sponsors/feross" 970 + }, 971 + { 972 + "type": "patreon", 973 + "url": "https://www.patreon.com/feross" 974 + }, 975 + { 976 + "type": "consulting", 977 + "url": "https://feross.org/support" 978 + } 979 + ] 980 + }, 981 + "node_modules/read-cache": { 982 + "version": "1.0.0", 983 + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", 984 + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", 985 + "dev": true, 986 + "dependencies": { 987 + "pify": "^2.3.0" 988 + } 989 + }, 990 + "node_modules/readdirp": { 991 + "version": "3.6.0", 992 + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 993 + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 994 + "dev": true, 995 + "dependencies": { 996 + "picomatch": "^2.2.1" 997 + }, 998 + "engines": { 999 + "node": ">=8.10.0" 1000 + } 1001 + }, 1002 + "node_modules/resolve": { 1003 + "version": "1.22.8", 1004 + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", 1005 + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", 1006 + "dev": true, 1007 + "dependencies": { 1008 + "is-core-module": "^2.13.0", 1009 + "path-parse": "^1.0.7", 1010 + "supports-preserve-symlinks-flag": "^1.0.0" 1011 + }, 1012 + "bin": { 1013 + "resolve": "bin/resolve" 1014 + }, 1015 + "funding": { 1016 + "url": "https://github.com/sponsors/ljharb" 1017 + } 1018 + }, 1019 + "node_modules/reusify": { 1020 + "version": "1.0.4", 1021 + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1022 + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1023 + "dev": true, 1024 + "engines": { 1025 + "iojs": ">=1.0.0", 1026 + "node": ">=0.10.0" 1027 + } 1028 + }, 1029 + "node_modules/run-parallel": { 1030 + "version": "1.2.0", 1031 + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1032 + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1033 + "dev": true, 1034 + "funding": [ 1035 + { 1036 + "type": "github", 1037 + "url": "https://github.com/sponsors/feross" 1038 + }, 1039 + { 1040 + "type": "patreon", 1041 + "url": "https://www.patreon.com/feross" 1042 + }, 1043 + { 1044 + "type": "consulting", 1045 + "url": "https://feross.org/support" 1046 + } 1047 + ], 1048 + "dependencies": { 1049 + "queue-microtask": "^1.2.2" 1050 + } 1051 + }, 1052 + "node_modules/shebang-command": { 1053 + "version": "2.0.0", 1054 + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1055 + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1056 + "dev": true, 1057 + "dependencies": { 1058 + "shebang-regex": "^3.0.0" 1059 + }, 1060 + "engines": { 1061 + "node": ">=8" 1062 + } 1063 + }, 1064 + "node_modules/shebang-regex": { 1065 + "version": "3.0.0", 1066 + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1067 + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1068 + "dev": true, 1069 + "engines": { 1070 + "node": ">=8" 1071 + } 1072 + }, 1073 + "node_modules/signal-exit": { 1074 + "version": "4.1.0", 1075 + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 1076 + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 1077 + "dev": true, 1078 + "engines": { 1079 + "node": ">=14" 1080 + }, 1081 + "funding": { 1082 + "url": "https://github.com/sponsors/isaacs" 1083 + } 1084 + }, 1085 + "node_modules/source-map-js": { 1086 + "version": "1.0.2", 1087 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1088 + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1089 + "dev": true, 1090 + "engines": { 1091 + "node": ">=0.10.0" 1092 + } 1093 + }, 1094 + "node_modules/string-width": { 1095 + "version": "5.1.2", 1096 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 1097 + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 1098 + "dev": true, 1099 + "dependencies": { 1100 + "eastasianwidth": "^0.2.0", 1101 + "emoji-regex": "^9.2.2", 1102 + "strip-ansi": "^7.0.1" 1103 + }, 1104 + "engines": { 1105 + "node": ">=12" 1106 + }, 1107 + "funding": { 1108 + "url": "https://github.com/sponsors/sindresorhus" 1109 + } 1110 + }, 1111 + "node_modules/string-width-cjs": { 1112 + "name": "string-width", 1113 + "version": "4.2.3", 1114 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1115 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1116 + "dev": true, 1117 + "dependencies": { 1118 + "emoji-regex": "^8.0.0", 1119 + "is-fullwidth-code-point": "^3.0.0", 1120 + "strip-ansi": "^6.0.1" 1121 + }, 1122 + "engines": { 1123 + "node": ">=8" 1124 + } 1125 + }, 1126 + "node_modules/string-width-cjs/node_modules/ansi-regex": { 1127 + "version": "5.0.1", 1128 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1129 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1130 + "dev": true, 1131 + "engines": { 1132 + "node": ">=8" 1133 + } 1134 + }, 1135 + "node_modules/string-width-cjs/node_modules/emoji-regex": { 1136 + "version": "8.0.0", 1137 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1138 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1139 + "dev": true 1140 + }, 1141 + "node_modules/string-width-cjs/node_modules/strip-ansi": { 1142 + "version": "6.0.1", 1143 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1144 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1145 + "dev": true, 1146 + "dependencies": { 1147 + "ansi-regex": "^5.0.1" 1148 + }, 1149 + "engines": { 1150 + "node": ">=8" 1151 + } 1152 + }, 1153 + "node_modules/strip-ansi": { 1154 + "version": "7.1.0", 1155 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 1156 + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 1157 + "dev": true, 1158 + "dependencies": { 1159 + "ansi-regex": "^6.0.1" 1160 + }, 1161 + "engines": { 1162 + "node": ">=12" 1163 + }, 1164 + "funding": { 1165 + "url": "https://github.com/chalk/strip-ansi?sponsor=1" 1166 + } 1167 + }, 1168 + "node_modules/strip-ansi-cjs": { 1169 + "name": "strip-ansi", 1170 + "version": "6.0.1", 1171 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1172 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1173 + "dev": true, 1174 + "dependencies": { 1175 + "ansi-regex": "^5.0.1" 1176 + }, 1177 + "engines": { 1178 + "node": ">=8" 1179 + } 1180 + }, 1181 + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 1182 + "version": "5.0.1", 1183 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1184 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1185 + "dev": true, 1186 + "engines": { 1187 + "node": ">=8" 1188 + } 1189 + }, 1190 + "node_modules/sucrase": { 1191 + "version": "3.35.0", 1192 + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", 1193 + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", 1194 + "dev": true, 1195 + "dependencies": { 1196 + "@jridgewell/gen-mapping": "^0.3.2", 1197 + "commander": "^4.0.0", 1198 + "glob": "^10.3.10", 1199 + "lines-and-columns": "^1.1.6", 1200 + "mz": "^2.7.0", 1201 + "pirates": "^4.0.1", 1202 + "ts-interface-checker": "^0.1.9" 1203 + }, 1204 + "bin": { 1205 + "sucrase": "bin/sucrase", 1206 + "sucrase-node": "bin/sucrase-node" 1207 + }, 1208 + "engines": { 1209 + "node": ">=16 || 14 >=14.17" 1210 + } 1211 + }, 1212 + "node_modules/supports-preserve-symlinks-flag": { 1213 + "version": "1.0.0", 1214 + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1215 + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1216 + "dev": true, 1217 + "engines": { 1218 + "node": ">= 0.4" 1219 + }, 1220 + "funding": { 1221 + "url": "https://github.com/sponsors/ljharb" 1222 + } 1223 + }, 1224 + "node_modules/tailwindcss": { 1225 + "version": "3.4.1", 1226 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", 1227 + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", 1228 + "dev": true, 1229 + "dependencies": { 1230 + "@alloc/quick-lru": "^5.2.0", 1231 + "arg": "^5.0.2", 1232 + "chokidar": "^3.5.3", 1233 + "didyoumean": "^1.2.2", 1234 + "dlv": "^1.1.3", 1235 + "fast-glob": "^3.3.0", 1236 + "glob-parent": "^6.0.2", 1237 + "is-glob": "^4.0.3", 1238 + "jiti": "^1.19.1", 1239 + "lilconfig": "^2.1.0", 1240 + "micromatch": "^4.0.5", 1241 + "normalize-path": "^3.0.0", 1242 + "object-hash": "^3.0.0", 1243 + "picocolors": "^1.0.0", 1244 + "postcss": "^8.4.23", 1245 + "postcss-import": "^15.1.0", 1246 + "postcss-js": "^4.0.1", 1247 + "postcss-load-config": "^4.0.1", 1248 + "postcss-nested": "^6.0.1", 1249 + "postcss-selector-parser": "^6.0.11", 1250 + "resolve": "^1.22.2", 1251 + "sucrase": "^3.32.0" 1252 + }, 1253 + "bin": { 1254 + "tailwind": "lib/cli.js", 1255 + "tailwindcss": "lib/cli.js" 1256 + }, 1257 + "engines": { 1258 + "node": ">=14.0.0" 1259 + } 1260 + }, 1261 + "node_modules/thenify": { 1262 + "version": "3.3.1", 1263 + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", 1264 + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", 1265 + "dev": true, 1266 + "dependencies": { 1267 + "any-promise": "^1.0.0" 1268 + } 1269 + }, 1270 + "node_modules/thenify-all": { 1271 + "version": "1.6.0", 1272 + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 1273 + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", 1274 + "dev": true, 1275 + "dependencies": { 1276 + "thenify": ">= 3.1.0 < 4" 1277 + }, 1278 + "engines": { 1279 + "node": ">=0.8" 1280 + } 1281 + }, 1282 + "node_modules/to-regex-range": { 1283 + "version": "5.0.1", 1284 + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1285 + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1286 + "dev": true, 1287 + "dependencies": { 1288 + "is-number": "^7.0.0" 1289 + }, 1290 + "engines": { 1291 + "node": ">=8.0" 1292 + } 1293 + }, 1294 + "node_modules/ts-interface-checker": { 1295 + "version": "0.1.13", 1296 + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", 1297 + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", 1298 + "dev": true 1299 + }, 1300 + "node_modules/util-deprecate": { 1301 + "version": "1.0.2", 1302 + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1303 + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1304 + "dev": true 1305 + }, 1306 + "node_modules/which": { 1307 + "version": "2.0.2", 1308 + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1309 + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1310 + "dev": true, 1311 + "dependencies": { 1312 + "isexe": "^2.0.0" 1313 + }, 1314 + "bin": { 1315 + "node-which": "bin/node-which" 1316 + }, 1317 + "engines": { 1318 + "node": ">= 8" 1319 + } 1320 + }, 1321 + "node_modules/wrap-ansi": { 1322 + "version": "8.1.0", 1323 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 1324 + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 1325 + "dev": true, 1326 + "dependencies": { 1327 + "ansi-styles": "^6.1.0", 1328 + "string-width": "^5.0.1", 1329 + "strip-ansi": "^7.0.1" 1330 + }, 1331 + "engines": { 1332 + "node": ">=12" 1333 + }, 1334 + "funding": { 1335 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1336 + } 1337 + }, 1338 + "node_modules/wrap-ansi-cjs": { 1339 + "name": "wrap-ansi", 1340 + "version": "7.0.0", 1341 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1342 + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1343 + "dev": true, 1344 + "dependencies": { 1345 + "ansi-styles": "^4.0.0", 1346 + "string-width": "^4.1.0", 1347 + "strip-ansi": "^6.0.0" 1348 + }, 1349 + "engines": { 1350 + "node": ">=10" 1351 + }, 1352 + "funding": { 1353 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1354 + } 1355 + }, 1356 + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 1357 + "version": "5.0.1", 1358 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1359 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1360 + "dev": true, 1361 + "engines": { 1362 + "node": ">=8" 1363 + } 1364 + }, 1365 + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 1366 + "version": "4.3.0", 1367 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1368 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1369 + "dev": true, 1370 + "dependencies": { 1371 + "color-convert": "^2.0.1" 1372 + }, 1373 + "engines": { 1374 + "node": ">=8" 1375 + }, 1376 + "funding": { 1377 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1378 + } 1379 + }, 1380 + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 1381 + "version": "8.0.0", 1382 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1383 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1384 + "dev": true 1385 + }, 1386 + "node_modules/wrap-ansi-cjs/node_modules/string-width": { 1387 + "version": "4.2.3", 1388 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1389 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1390 + "dev": true, 1391 + "dependencies": { 1392 + "emoji-regex": "^8.0.0", 1393 + "is-fullwidth-code-point": "^3.0.0", 1394 + "strip-ansi": "^6.0.1" 1395 + }, 1396 + "engines": { 1397 + "node": ">=8" 1398 + } 1399 + }, 1400 + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 1401 + "version": "6.0.1", 1402 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1403 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1404 + "dev": true, 1405 + "dependencies": { 1406 + "ansi-regex": "^5.0.1" 1407 + }, 1408 + "engines": { 1409 + "node": ">=8" 1410 + } 1411 + }, 1412 + "node_modules/yaml": { 1413 + "version": "2.4.1", 1414 + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", 1415 + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", 1416 + "dev": true, 1417 + "bin": { 1418 + "yaml": "bin.mjs" 1419 + }, 1420 + "engines": { 1421 + "node": ">= 14" 1422 + } 1423 + } 1424 + } 1425 + }
+10
theme/package.json
··· 1 + { 2 + "name": "theme", 3 + "version": "1.0.0", 4 + "author": "Alex Ottr <alex@otter.foo>", 5 + "license": "MIT", 6 + "devDependencies": { 7 + "daisyui": "^4.7.2", 8 + "tailwindcss": "^3.4.1" 9 + } 10 + }
+12
theme/tailwind.config.js
··· 1 + /** @type {import('tailwindcss').Config} */ 2 + module.exports = { 3 + content: ["../paw/templates/**/*.{html,js}"], 4 + theme: { 5 + extend: {}, 6 + }, 7 + plugins: [require("daisyui")], 8 + daisyui: { 9 + themes: ["nord"], 10 + }, 11 + } 12 +
ticketing/__init__.py

This is a binary file and will not be displayed.

+9
ticketing/admin.py
··· 1 + from django.contrib import admin 2 + from .models import Category, Ticket, Comment, Template, Team 3 + 4 + # Register your models here. 5 + admin.site.register(Category) 6 + admin.site.register(Ticket) 7 + admin.site.register(Comment) 8 + admin.site.register(Template) 9 + admin.site.register(Team)
+6
ticketing/apps.py
··· 1 + from django.apps import AppConfig 2 + 3 + 4 + class TicketingConfig(AppConfig): 5 + default_auto_field = "django.db.models.BigAutoField" 6 + name = "ticketing"
+40
ticketing/forms.py
··· 1 + from django import forms 2 + from .models import Ticket, Template, Team, Category 3 + 4 + 5 + class CommentForm(forms.Form): 6 + text = forms.CharField(widget=forms.Textarea( 7 + attrs={'class': 'textarea textarea-bordered h-32', 'placeholder': 'Enter your comment here...'})) 8 + hidden_from_client = forms.BooleanField(widget=forms.CheckboxInput( 9 + attrs={'class': 'toggle toggle-error'}), required=False) 10 + 11 + 12 + class TicketForm(forms.ModelForm): 13 + class Meta: 14 + model = Ticket 15 + fields = ['title', 'description', 'category'] 16 + widgets = { 17 + 'title': forms.TextInput(attrs={'class': 'input input-bordered w-full'}), 18 + 'description': forms.Textarea(attrs={'class': 'textarea textarea-bordered h-32 w-full'}), 19 + 'category': forms.Select(attrs={'class': 'select select-bordered w-full'}), 20 + } 21 + 22 + 23 + class TemplateForm(forms.Form): 24 + 25 + template_select = forms.ModelChoiceField(queryset=Template.objects.all(), widget=forms.Select( 26 + attrs={'class': 'select select-bordered select-sm w-full'})) 27 + 28 + # def __init__(self, queryset, *args, **kwargs): 29 + # self.fields["template"].queryset = queryset 30 + # super(TemplateForm, self).__init__(*args, **kwargs) 31 + 32 + 33 + class TeamAssignmentForm(forms.Form): 34 + team_select = forms.ModelChoiceField(queryset=Team.objects.all(), empty_label='No Team', required=False, widget=forms.Select( 35 + attrs={'class': 'select select-bordered select-sm w-full'})) 36 + 37 + 38 + class CategoryAssignmentForm(forms.Form): 39 + category_select = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label='No Category', required=False, widget=forms.Select( 40 + attrs={'class': 'select select-bordered select-sm w-full'}))
+78
ticketing/migrations/0001_initial.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-06 21:31 2 + 3 + import django.db.models.deletion 4 + from django.db import migrations, models 5 + 6 + 7 + class Migration(migrations.Migration): 8 + 9 + initial = True 10 + 11 + dependencies = [] 12 + 13 + operations = [ 14 + migrations.CreateModel( 15 + name="Category", 16 + fields=[ 17 + ( 18 + "id", 19 + models.BigAutoField( 20 + auto_created=True, 21 + primary_key=True, 22 + serialize=False, 23 + verbose_name="ID", 24 + ), 25 + ), 26 + ("name", models.CharField(max_length=200)), 27 + ], 28 + ), 29 + migrations.CreateModel( 30 + name="Ticket", 31 + fields=[ 32 + ( 33 + "id", 34 + models.BigAutoField( 35 + auto_created=True, 36 + primary_key=True, 37 + serialize=False, 38 + verbose_name="ID", 39 + ), 40 + ), 41 + ("title", models.CharField(max_length=200)), 42 + ("description", models.TextField()), 43 + ( 44 + "status", 45 + models.CharField( 46 + choices=[ 47 + ("open", "Open"), 48 + ("in_progress", "In Progress"), 49 + ("closed", "Closed"), 50 + ], 51 + default="open", 52 + max_length=20, 53 + ), 54 + ), 55 + ( 56 + "priority", 57 + models.CharField( 58 + choices=[ 59 + ("low", "Low"), 60 + ("medium", "Medium"), 61 + ("high", "High"), 62 + ], 63 + default="medium", 64 + max_length=20, 65 + ), 66 + ), 67 + ("created_at", models.DateTimeField(auto_now_add=True)), 68 + ("updated_at", models.DateTimeField(auto_now=True)), 69 + ( 70 + "category", 71 + models.ForeignKey( 72 + on_delete=django.db.models.deletion.CASCADE, 73 + to="ticketing.category", 74 + ), 75 + ), 76 + ], 77 + ), 78 + ]
+24
ticketing/migrations/0002_alter_ticket_category.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-06 21:32 2 + 3 + import django.db.models.deletion 4 + from django.db import migrations, models 5 + 6 + 7 + class Migration(migrations.Migration): 8 + 9 + dependencies = [ 10 + ("ticketing", "0001_initial"), 11 + ] 12 + 13 + operations = [ 14 + migrations.AlterField( 15 + model_name="ticket", 16 + name="category", 17 + field=models.ForeignKey( 18 + blank=True, 19 + null=True, 20 + on_delete=django.db.models.deletion.CASCADE, 21 + to="ticketing.category", 22 + ), 23 + ), 24 + ]
+47
ticketing/migrations/0003_comment.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-06 21:42 2 + 3 + import django.db.models.deletion 4 + from django.conf import settings 5 + from django.db import migrations, models 6 + 7 + 8 + class Migration(migrations.Migration): 9 + 10 + dependencies = [ 11 + ("ticketing", "0002_alter_ticket_category"), 12 + migrations.swappable_dependency(settings.AUTH_USER_MODEL), 13 + ] 14 + 15 + operations = [ 16 + migrations.CreateModel( 17 + name="Comment", 18 + fields=[ 19 + ( 20 + "id", 21 + models.BigAutoField( 22 + auto_created=True, 23 + primary_key=True, 24 + serialize=False, 25 + verbose_name="ID", 26 + ), 27 + ), 28 + ("text", models.TextField()), 29 + ("is_only_for_staff", models.BooleanField(default=False)), 30 + ("created_at", models.DateTimeField(auto_now_add=True)), 31 + ( 32 + "ticket", 33 + models.ForeignKey( 34 + on_delete=django.db.models.deletion.CASCADE, 35 + to="ticketing.ticket", 36 + ), 37 + ), 38 + ( 39 + "user", 40 + models.ForeignKey( 41 + on_delete=django.db.models.deletion.CASCADE, 42 + to=settings.AUTH_USER_MODEL, 43 + ), 44 + ), 45 + ], 46 + ), 47 + ]
+26
ticketing/migrations/0004_ticket_user.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-07 03:28 2 + 3 + import django.db.models.deletion 4 + from django.conf import settings 5 + from django.db import migrations, models 6 + 7 + 8 + class Migration(migrations.Migration): 9 + 10 + dependencies = [ 11 + ("ticketing", "0003_comment"), 12 + migrations.swappable_dependency(settings.AUTH_USER_MODEL), 13 + ] 14 + 15 + operations = [ 16 + migrations.AddField( 17 + model_name="ticket", 18 + name="user", 19 + field=models.ForeignKey( 20 + default=1, 21 + on_delete=django.db.models.deletion.CASCADE, 22 + to=settings.AUTH_USER_MODEL, 23 + ), 24 + preserve_default=False, 25 + ), 26 + ]
+39
ticketing/migrations/0005_template.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-07 03:39 2 + 3 + import django.db.models.deletion 4 + from django.db import migrations, models 5 + 6 + 7 + class Migration(migrations.Migration): 8 + 9 + dependencies = [ 10 + ("ticketing", "0004_ticket_user"), 11 + ] 12 + 13 + operations = [ 14 + migrations.CreateModel( 15 + name="Template", 16 + fields=[ 17 + ( 18 + "id", 19 + models.BigAutoField( 20 + auto_created=True, 21 + primary_key=True, 22 + serialize=False, 23 + verbose_name="ID", 24 + ), 25 + ), 26 + ("name", models.CharField(max_length=200)), 27 + ("content", models.TextField()), 28 + ( 29 + "category", 30 + models.ForeignKey( 31 + blank=True, 32 + null=True, 33 + on_delete=django.db.models.deletion.CASCADE, 34 + to="ticketing.category", 35 + ), 36 + ), 37 + ], 38 + ), 39 + ]
+30
ticketing/migrations/0006_alter_ticket_priority_and_more.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-07 16:43 2 + 3 + from django.conf import settings 4 + from django.db import migrations, models 5 + 6 + 7 + class Migration(migrations.Migration): 8 + 9 + dependencies = [ 10 + ("ticketing", "0005_template"), 11 + migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 + ] 13 + 14 + operations = [ 15 + migrations.AlterField( 16 + model_name="ticket", 17 + name="priority", 18 + field=models.PositiveSmallIntegerField( 19 + choices=[(3, "Low"), (2, "Medium"), (1, "High")], 20 + db_index=True, 21 + default=2, 22 + ), 23 + ), 24 + migrations.AddIndex( 25 + model_name="ticket", 26 + index=models.Index( 27 + fields=["priority", "title"], name="ticketing_t_priorit_b4d7ff_idx" 28 + ), 29 + ), 30 + ]
+39
ticketing/migrations/0007_ticket_assigned_group_ticket_assigned_to.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-07 17:04 2 + 3 + import django.db.models.deletion 4 + from django.conf import settings 5 + from django.db import migrations, models 6 + 7 + 8 + class Migration(migrations.Migration): 9 + 10 + dependencies = [ 11 + ("auth", "0012_alter_user_first_name_max_length"), 12 + ("ticketing", "0006_alter_ticket_priority_and_more"), 13 + migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 + ] 15 + 16 + operations = [ 17 + migrations.AddField( 18 + model_name="ticket", 19 + name="assigned_group", 20 + field=models.ForeignKey( 21 + blank=True, 22 + null=True, 23 + on_delete=django.db.models.deletion.CASCADE, 24 + related_name="assigned_to_group", 25 + to="auth.group", 26 + ), 27 + ), 28 + migrations.AddField( 29 + model_name="ticket", 30 + name="assigned_to", 31 + field=models.ForeignKey( 32 + blank=True, 33 + null=True, 34 + on_delete=django.db.models.deletion.CASCADE, 35 + related_name="assigned_to_user", 36 + to=settings.AUTH_USER_MODEL, 37 + ), 38 + ), 39 + ]
+58
ticketing/migrations/0008_remove_ticket_assigned_group_team_category_team_and_more.py
··· 1 + # Generated by Django 5.0.3 on 2024-03-07 18:32 2 + 3 + import django.db.models.deletion 4 + from django.conf import settings 5 + from django.db import migrations, models 6 + 7 + 8 + class Migration(migrations.Migration): 9 + 10 + dependencies = [ 11 + ("ticketing", "0007_ticket_assigned_group_ticket_assigned_to"), 12 + migrations.swappable_dependency(settings.AUTH_USER_MODEL), 13 + ] 14 + 15 + operations = [ 16 + migrations.RemoveField( 17 + model_name="ticket", 18 + name="assigned_group", 19 + ), 20 + migrations.CreateModel( 21 + name="Team", 22 + fields=[ 23 + ( 24 + "id", 25 + models.BigAutoField( 26 + auto_created=True, 27 + primary_key=True, 28 + serialize=False, 29 + verbose_name="ID", 30 + ), 31 + ), 32 + ("name", models.CharField(max_length=200)), 33 + ("description", models.TextField(blank=True)), 34 + ("members", models.ManyToManyField(to=settings.AUTH_USER_MODEL)), 35 + ], 36 + ), 37 + migrations.AddField( 38 + model_name="category", 39 + name="team", 40 + field=models.ForeignKey( 41 + blank=True, 42 + null=True, 43 + on_delete=django.db.models.deletion.CASCADE, 44 + to="ticketing.team", 45 + ), 46 + ), 47 + migrations.AddField( 48 + model_name="ticket", 49 + name="assigned_team", 50 + field=models.ForeignKey( 51 + blank=True, 52 + null=True, 53 + on_delete=django.db.models.deletion.CASCADE, 54 + related_name="assigned_to_team", 55 + to="ticketing.team", 56 + ), 57 + ), 58 + ]
ticketing/migrations/__init__.py

This is a binary file and will not be displayed.

+112
ticketing/models.py
··· 1 + from django.db import models 2 + from core.models import PawUser 3 + from django.utils import timezone 4 + from django.utils.translation import gettext_lazy as _ 5 + from django.db.models.signals import post_save 6 + from django.dispatch import receiver 7 + 8 + 9 + class Team(models.Model): 10 + name = models.CharField(max_length=200) 11 + description = models.TextField(blank=True) 12 + members = models.ManyToManyField(PawUser) 13 + 14 + def __str__(self): 15 + return self.name 16 + 17 + 18 + class Category(models.Model): 19 + name = models.CharField(max_length=200) 20 + team = models.ForeignKey( 21 + Team, on_delete=models.CASCADE, null=True, blank=True, help_text="If a team is selected, new tickets will automatically assigned to this team.") 22 + 23 + def __str__(self): 24 + return self.name 25 + 26 + 27 + class Ticket(models.Model): 28 + 29 + class Status(models.TextChoices): 30 + OPEN = 'open', _('Open') 31 + IN_PROGRESS = 'in_progress', _('In Progress') 32 + CLOSED = 'closed', _('Closed') 33 + 34 + class Priority(models.IntegerChoices): 35 + LOW = 3, _("Low") 36 + MEDIUM = 2, _("Medium") 37 + HIGH = 1, _("High") 38 + 39 + title = models.CharField(max_length=200) 40 + user = models.ForeignKey(PawUser, on_delete=models.CASCADE) 41 + description = models.TextField() 42 + category = models.ForeignKey( 43 + Category, on_delete=models.CASCADE, null=True, blank=True) 44 + status = models.CharField( 45 + max_length=20, choices=Status.choices, default=Status.OPEN) 46 + priority = models.PositiveSmallIntegerField( 47 + choices=Priority.choices, db_index=True, default=Priority.MEDIUM) 48 + created_at = models.DateTimeField(auto_now_add=True) 49 + updated_at = models.DateTimeField(auto_now=True) 50 + assigned_to = models.ForeignKey( 51 + PawUser, on_delete=models.CASCADE, related_name='assigned_to_user', null=True, blank=True) 52 + assigned_team = models.ForeignKey( 53 + Team, on_delete=models.CASCADE, related_name='assigned_to_team', null=True, blank=True) 54 + 55 + class Meta: 56 + indexes = [ 57 + models.Index(fields=["priority", "title"]), 58 + ] 59 + 60 + def close_ticket(self): 61 + self.status = self.Status.CLOSED 62 + self.save() 63 + 64 + def assign_to_team(self, team): 65 + if self.assigned_team != team and team is not None: 66 + self.assigned_to = None 67 + 68 + self.assigned_team = team 69 + self.save() 70 + 71 + def get_priority(self): 72 + return self.Priority(self.priority).label 73 + 74 + def __str__(self): 75 + return self.title 76 + 77 + 78 + @receiver(post_save, sender=Ticket, dispatch_uid="team_auto_assignment") 79 + def update_team_assignment(sender, instance, created, **kwargs): 80 + if not created or not instance.category or not instance.category.team: 81 + return 82 + 83 + instance.assigned_team = instance.category.team 84 + instance.save() 85 + 86 + 87 + class Comment(models.Model): 88 + ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) 89 + user = models.ForeignKey(PawUser, on_delete=models.CASCADE) 90 + text = models.TextField() 91 + is_only_for_staff = models.BooleanField(default=False) 92 + created_at = models.DateTimeField(auto_now_add=True) 93 + 94 + def save(self, *args, **kwargs): 95 + self.ticket.status = Ticket.Status.IN_PROGRESS 96 + self.ticket.updated_at = timezone.now() 97 + self.ticket.save() 98 + 99 + super().save(*args, **kwargs) 100 + 101 + def __str__(self): 102 + return f'Comment by {self.user.username} on {self.ticket.title}' 103 + 104 + 105 + class Template(models.Model): 106 + name = models.CharField(max_length=200) 107 + content = models.TextField() 108 + category = models.ForeignKey( 109 + Category, on_delete=models.CASCADE, null=True, blank=True) 110 + 111 + def __str__(self): 112 + return self.name
+3
ticketing/tests.py
··· 1 + from django.test import TestCase 2 + 3 + # Create your tests here.
+11
ticketing/urls.py
··· 1 + from django.urls import path 2 + 3 + from .views import show_ticket, show_tickets, create_ticket, dashboard, show_tickets_history 4 + 5 + urlpatterns = [ 6 + path("tickets/<int:ticket_id>", show_ticket, name="ticket_detail"), 7 + path("tickets/new", create_ticket, name="create_ticket"), 8 + path("tickets", show_tickets, name="all_tickets"), 9 + path("tickets/history", show_tickets_history, name="tickets_history"), 10 + path("dashboard", dashboard, name="dashboard"), 11 + ]
+107
ticketing/views.py
··· 1 + from django.shortcuts import render, redirect 2 + from django.contrib.auth.decorators import login_required 3 + from django.shortcuts import get_object_or_404 4 + from .models import Ticket, Template 5 + from django.db.models import Q 6 + from .forms import CommentForm, TicketForm, TemplateForm, TeamAssignmentForm, CategoryAssignmentForm 7 + 8 + 9 + @login_required 10 + def show_tickets(request): 11 + if request.user.is_staff: 12 + # show only tickets that are not closed and are not assigned or assigned to the current user's team 13 + tickets = Ticket.objects.filter( 14 + ~Q(status=Ticket.Status.CLOSED) & (~Q(assigned_team=None) 15 + | ~Q(assigned_team__in=request.user.team_set.all())) 16 + ).order_by("priority", "-created_at") 17 + else: 18 + tickets = Ticket.objects.filter( 19 + user=request.user).order_by("-created_at") 20 + return render(request, "ticketing/tickets.html", {"tickets": tickets}) 21 + 22 + 23 + @login_required 24 + def show_tickets_history(request): 25 + if request.user.is_staff: 26 + tickets = Ticket.objects.filter( 27 + status=Ticket.Status.CLOSED).order_by("priority", "-created_at") 28 + print(tickets) 29 + else: 30 + tickets = Ticket.objects.filter( 31 + user=request.user).order_by("-created_at") 32 + return render(request, "ticketing/tickets_history.html", {"tickets": tickets}) 33 + 34 + 35 + @login_required 36 + def show_ticket(request, ticket_id): 37 + ticket = get_object_or_404(Ticket, pk=ticket_id) 38 + # comment_templates = Template.objects.filter(category=ticket.category) 39 + 40 + if request.user != ticket.user and not request.user.is_staff: 41 + return redirect("all_tickets") 42 + 43 + form, template_form, team_assignment_form, category_assignment_form = CommentForm( 44 + ), TemplateForm(), TeamAssignmentForm(), CategoryAssignmentForm() 45 + 46 + if request.method == "POST": 47 + if 'apply_template' in request.POST and request.user.is_staff: 48 + template_form = TemplateForm(request.POST) 49 + if template_form.is_valid(): 50 + template = template_form.cleaned_data["template_select"] 51 + form = CommentForm(initial={"text": template.content}) 52 + elif 'assign_to_team' in request.POST and request.user.is_staff: 53 + team_assignment_form = TeamAssignmentForm(request.POST) 54 + if team_assignment_form.is_valid(): 55 + ticket.assign_to_team( 56 + team_assignment_form.cleaned_data["team_select"]) 57 + elif 'assign_to_category' in request.POST and request.user.is_staff: 58 + category_assignment_form = CategoryAssignmentForm(request.POST) 59 + if category_assignment_form.is_valid(): 60 + ticket.category = category_assignment_form.cleaned_data["category_select"] 61 + ticket.save() 62 + elif 'assign_self' in request.POST and request.user.is_staff: 63 + ticket.assigned_to = request.user 64 + ticket.save() 65 + elif 'reopen_ticket' in request.POST and request.user.is_staff: 66 + ticket.status = Ticket.Status.IN_PROGRESS 67 + ticket.save() 68 + else: 69 + form = CommentForm(request.POST) 70 + if form.is_valid(): 71 + ticket.comment_set.create( 72 + user=request.user, ticket=ticket, 73 + text=form.cleaned_data["text"], is_only_for_staff=form.cleaned_data["hidden_from_client"] 74 + ) 75 + if 'close' in request.POST and request.user.is_staff: 76 + ticket.close_ticket() 77 + 78 + comments = ticket.comment_set.all() 79 + context = { 80 + "ticket": ticket, "comments": comments, "form": form, "template_form": template_form, 81 + "team_assignment_form": team_assignment_form, "category_assignment_form": category_assignment_form 82 + } 83 + return render(request, "ticketing/ticket_detail.html", context) 84 + 85 + 86 + @login_required 87 + def create_ticket(request): 88 + if request.method == "POST": 89 + form = TicketForm(request.POST) 90 + if form.is_valid(): 91 + ticket = form.save(commit=False) 92 + ticket.user = request.user 93 + ticket.save() 94 + return redirect("ticket_detail", ticket_id=ticket.id) 95 + else: 96 + form = TicketForm() 97 + return render(request, "ticketing/create_ticket.html", {"form": form}) 98 + 99 + 100 + @login_required 101 + def dashboard(request): 102 + 103 + tickets = Ticket.objects.all().order_by("-created_at") 104 + open_tickets = tickets.filter(status=Ticket.Status.OPEN) 105 + in_progress_tickets = tickets.filter(status=Ticket.Status.IN_PROGRESS) 106 + closed_tickets = tickets.filter(status=Ticket.Status.CLOSED) 107 + return render(request, "ticketing/dashboard.html", {"tickets": tickets, "open_tickets": open_tickets, "in_progress_tickets": in_progress_tickets, "closed_tickets": closed_tickets})