From 302d36a7d162c7601f07b17579ce1654310ee10c Mon Sep 17 00:00:00 2001 From: amirkey_ Date: Tue, 31 May 2022 20:09:27 +0430 Subject: [PATCH] image_uploader --- .gitignore | 15 + Dockerfile | 17 + Procfile | 1 + README.md | 0 api/__init__.py | 0 api/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 137 bytes api/__pycache__/admin.cpython-310.pyc | Bin 0 -> 178 bytes api/__pycache__/apps.cpython-310.pyc | Bin 0 -> 410 bytes api/__pycache__/models.cpython-310.pyc | Bin 0 -> 175 bytes api/__pycache__/serializers.cpython-310.pyc | Bin 0 -> 1159 bytes api/__pycache__/urls.cpython-310.pyc | Bin 0 -> 1480 bytes api/__pycache__/views.cpython-310.pyc | Bin 0 -> 6996 bytes api/admin.py | 3 + api/apps.py | 6 + api/migrations/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 148 bytes api/models.py | 3 + api/serializers.py | 20 + api/tests.py | 3 + api/urls.py | 25 + api/views.py | 242 +++++ config/nginx/Dockerfile | 7 + config/nginx/docker-compose.yml | 25 + config/nginx/nginx.conf | 30 + imageuploader/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 147 bytes .../__pycache__/settings.cpython-310.pyc | Bin 0 -> 3793 bytes .../__pycache__/urls.cpython-310.pyc | Bin 0 -> 2195 bytes imageuploader/asgi.py | 16 + imageuploader/settings.py | 195 ++++ imageuploader/urls.py | 65 ++ imageuploader/wsgi.py | 16 + manage.py | 22 + openapi-schema.yml | 929 ++++++++++++++++++ requirements.txt | 41 + uploader/__init__.py | 0 uploader/admin.py | 32 + uploader/apps.py | 7 + uploader/forms.py | 44 + uploader/models.py | 57 ++ uploader/signals.py | 15 + uploader/static/bootstrap.min.css | 7 + uploader/static/image/facebook.png | Bin 0 -> 472 bytes uploader/static/image/github.png | Bin 0 -> 3552 bytes uploader/static/image/google.png | Bin 0 -> 938 bytes uploader/static/image/logo.png | Bin 0 -> 6680 bytes uploader/static/image/twitter.png | Bin 0 -> 729 bytes uploader/static/style.css | 40 + uploader/templates/index.html | 156 +++ uploader/templates/login.html | 72 ++ uploader/templates/logout.html | 32 + uploader/templates/profile.html | 80 ++ uploader/templates/signup.html | 63 ++ uploader/templates/uploader.html | 203 ++++ uploader/templates/user-profile.html | 153 +++ uploader/tests.py | 3 + uploader/urls.py | 15 + uploader/views.py | 139 +++ 58 files changed, 2799 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Procfile create mode 100644 README.md create mode 100644 api/__init__.py create mode 100644 api/__pycache__/__init__.cpython-310.pyc create mode 100644 api/__pycache__/admin.cpython-310.pyc create mode 100644 api/__pycache__/apps.cpython-310.pyc create mode 100644 api/__pycache__/models.cpython-310.pyc create mode 100644 api/__pycache__/serializers.cpython-310.pyc create mode 100644 api/__pycache__/urls.cpython-310.pyc create mode 100644 api/__pycache__/views.cpython-310.pyc create mode 100644 api/admin.py create mode 100644 api/apps.py create mode 100644 api/migrations/__init__.py create mode 100644 api/migrations/__pycache__/__init__.cpython-310.pyc create mode 100644 api/models.py create mode 100644 api/serializers.py create mode 100644 api/tests.py create mode 100644 api/urls.py create mode 100644 api/views.py create mode 100644 config/nginx/Dockerfile create mode 100644 config/nginx/docker-compose.yml create mode 100644 config/nginx/nginx.conf create mode 100644 imageuploader/__init__.py create mode 100644 imageuploader/__pycache__/__init__.cpython-310.pyc create mode 100644 imageuploader/__pycache__/settings.cpython-310.pyc create mode 100644 imageuploader/__pycache__/urls.cpython-310.pyc create mode 100644 imageuploader/asgi.py create mode 100644 imageuploader/settings.py create mode 100644 imageuploader/urls.py create mode 100644 imageuploader/wsgi.py create mode 100644 manage.py create mode 100644 openapi-schema.yml create mode 100644 requirements.txt create mode 100644 uploader/__init__.py create mode 100644 uploader/admin.py create mode 100644 uploader/apps.py create mode 100644 uploader/forms.py create mode 100644 uploader/models.py create mode 100644 uploader/signals.py create mode 100644 uploader/static/bootstrap.min.css create mode 100644 uploader/static/image/facebook.png create mode 100644 uploader/static/image/github.png create mode 100644 uploader/static/image/google.png create mode 100644 uploader/static/image/logo.png create mode 100644 uploader/static/image/twitter.png create mode 100644 uploader/static/style.css create mode 100644 uploader/templates/index.html create mode 100644 uploader/templates/login.html create mode 100644 uploader/templates/logout.html create mode 100644 uploader/templates/profile.html create mode 100644 uploader/templates/signup.html create mode 100644 uploader/templates/uploader.html create mode 100644 uploader/templates/user-profile.html create mode 100644 uploader/tests.py create mode 100644 uploader/urls.py create mode 100644 uploader/views.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7153e80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +#Virtual env +env/ +uploader/__pycache__/ + +#Database +db.sqlite3 + +#Migrations +uploader/migrations/ + +#Credentials +.env + +#Static files +media/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..954d95f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.10.4 +LABEL MAINTAINER="Amir Keyhani | https://amir.key_" + +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +RUN mkdir /imageuploader +WORKDIR /imageuploader +COPY . /imageuploader + +ADD requirements.txt /imageuploader +RUN pip install --upgrade pip +RUN pip install -r requirements.txt + +RUN python manage.py collectstatic --no-input + +CMD ["gunicorn", "--chdir", "imageuploader", "--bind", ":8000", "imageuploader.wsgi:application"] \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..255c363 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: waitress-serve --port=$PORT imageuploader.wsgi:application \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/__pycache__/__init__.cpython-310.pyc b/api/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6017c6721b84c0e0b22458a1bdf526ec9f4d0294 GIT binary patch literal 137 zcmd1j<>g`kf{SH+Ng(<$h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2D9#VRHxD={xU zKRz=zF+Ekcv>+!xF(tJ~H?g1~Cb1whCO$qhFS8^*Uaz3?7Kcr4eoARhsvXFbVkRKL G!Tg`kf{SH+NlrleF^Gc(44TX@fuanW zjJH@5Q*tx&{4|-O_)@YG^V0M6lJoOQiZYXmKnAR2C}IXuVB(jii&YFnO?+l sX+chYVoGX}Zel?}OkzQ14A?Bag34PQHo5sJr8%i~j6mJRAd>_b01H7WQ2+n{ literal 0 HcmV?d00001 diff --git a/api/__pycache__/apps.cpython-310.pyc b/api/__pycache__/apps.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..123972421cbc8389dda9dacdf9adc930b7b4bc60 GIT binary patch literal 410 zcmYjNy-ve05I)B#3jJA7S0qLC3m z%AzuDcCE`rx3PCx8T4E_y-Wu_5u%or62cFKAYx}iJQm`mlV;yJK~>1kY=k7aD0ccd z^uC}8SJ=Vt`R&E3-zjt@OEv49u@Y4?lg_PZ9l2{W_u6pMg!{Bd1PR0}VY}Kg<$kpP ecHlNq7#`UFYx-zJHJ@De|Gf&AX~V!VO!*(JBw@_} literal 0 HcmV?d00001 diff --git a/api/__pycache__/models.cpython-310.pyc b/api/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d535644ae82b52b688c7e8853248a71469573df6 GIT binary patch literal 175 zcmd1j<>g`kf{SH+Nj5(44TX@fuanW zjJMcw^HWlDiv2X1ZgHk$CFZ5)>!l+!x nF(tJ~H?g1~Cb1wh24aq0LFFwD8z8$hC)JJ-sJ$3ulmG(&m-{G{ literal 0 HcmV?d00001 diff --git a/api/__pycache__/serializers.cpython-310.pyc b/api/__pycache__/serializers.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d95dbe5f5c9c9adeff620a5909c4f16813bb182 GIT binary patch literal 1159 zcmb7D&2AGh5VqI*mo#bGr38sL$f4nm5UNBaPK}T%4p@<_1v}LiZ#K*(LgZSWfVb!? z`HDDj&W#f@PSQp!Kf#hmp3gf!-{;w?+if#kZzf;fe&dXNC1-bq=$zrMB^u2%x2)un zb2d?RFnNTg##;ti4_lIRqXbc3{X>yi!H-!VTM zaCcA}C~{jY4b%hS($_Ov<=TKtUQ}girgN9Pf@)G&^Nu2Rmq6zX_v$ek!z9;C23U{l z0P6)effQO`t|H-UUtSJ#{}9UN@k;zk3juK3mWJbNaDr8o>@b K;hD(de*6=K^WX~r literal 0 HcmV?d00001 diff --git a/api/__pycache__/urls.cpython-310.pyc b/api/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae0ef4e1e94b42e39215ae668ad44d69860d50f8 GIT binary patch literal 1480 zcmZ{k%Wl&^6ozMVZxSbNTH2KRohDM-9g8ZekeVezNKh75q{?Itslkpd+o8hmz=kJ) zC9mWyt4cfpD`v)L#!d~6Z23F?$*=jx$My}QP5ANd^4t684MKhiC>}c;Uhp%TP(m1C z)FmFZC?%}Is&3^i0m^Dn{a*V)Se-S#RyjAJF1dxg0S(D*bH^aKu_{r{D%n35kNKY~rk zkCC4sKSh291F7!|UJR@)HhM!w<14YRBbwF%JHEK$+bMvKlin(DeVaje;5t!!lo)F) z{;;$?NcMD@L2Ntj(ZpHC$HAwQqojXLN=#jthhWE0Y{@DGyH&tM%fIY0DH&=zzV!J; zp*3H-R0^&PT=bVwzsY%eZ?xOZos74suWarV$NMqD zYL-$vmO^Srl`#nY4~`2eV-b^~qH@M{CFv{H8P^NBRXL;TR2dbQGOh`^V>zR0%#>H7 z?X<%_+RKH1xC-4UtnkTB>z^ICjI8b%&h|?_+G*2{&PCnosq$2ga?Yo6Tys8?vzhZ$ zPL8MI|ycW;LOCP9R^?0*2MGK%7qj0X^6)B(j_fwR!ypZ6@5p| I!hP%aUl?rM`Tzg` literal 0 HcmV?d00001 diff --git a/api/__pycache__/views.cpython-310.pyc b/api/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f640d4b190d5d2055aa2a6829234dcd471facf4 GIT binary patch literal 6996 zcmb_hJ8<0A6~$*i*yWO3krYMhyZTzISPbnbKSz-%leDbJA!U)WGl<48v;e7H0o?Ti zC|NsXk;pTyJej0QkwQw7*-4WkU5Zp`Qlv_SNta2XDh0bV&OH~vVs}N5R2*<{_nmj& z@4owccx(<27bSYuH-B~im**tup8&m2hQJ)Xo-a$1C0Vi~xw0h>!}>6{%R3|Ps6NVN%_+Nw^g~=OIAiX( zKJHHF6O4<_VRurWl%*SzHDr}Om#mVlK2`N2gomvW!Xu2Q2#;E2!ez$Ogb!I`gvS^k zB|L6T5T0OsjPPM=lJF$sqL$3ggp+Pg`dQpJ9B4@LB5|;d6}75>$h)yShpWjQ8Qb0;}ObgpxtdbO_Q1g`T3^n+8ch5zb%?;b;o`|+LNfs zSlndA7Io99x2f@=sBv#q)GevPRCjEz)!gvx4z0!WO@Gs?D#7SY@A{_yfF`TgOy9PG z>4A!6amO~T58qc%X-Gn63tl| zOR?0?Wj$}nv_sjT6pQtK-Sd}f7$APKRDcoB)4Nk4;!6$rnetrPR(*9#wPZ{AQrXV< znXODC`;><3s7tG~(u`|vJgMdc`Um;u{f1rhy+Ab`M--?^lu)0sOy8vWGoJ0N1$kkA zx@miUkXvgC*Yx$mW~2}=D0wGAUE8iw1nHXW2phVkj9 z>4Y4Cp@K;>Q5$K&s5z$R*`6qaIo7g;Tlc(PMuix>@*Z*ub>l>a>D|$YXi`qj$s-Ea zrm9wqQB&Hukywa%VUzXrs}5@Gs_rTQU)quzvL$~hZT^k!NP%iY_Op!~ z6uJ`PJYg-wq}Hk|rfC#`wN?wE8c`8wb90NBzZ)}XC*TAfO`M}2aUSFX2vjIu0~rOm2=XnEWG*hTf-Vtb63i+H zP^w~fz}?m7$WcC*$m8IBS@J#2Qpxx7i3%5N->f?|g$9TplwlO?d^1#NYjD4Yvc+2b zNLnEUQ;qtBqC5WlOr$~i=kjB?B6*_HddMp4Jsa+CK*giYC9wXxQ zVz5BljDpE-HpTn#4Qdue2n`XU8|;&Xht^a`w9 zQ$}(E_36fSg}8efm)12djSMYMW>#P`DD|U-c!HbaP%Ja?AI@aCWS(ivYp+^A|#39^qb+(L^Tb?&o%N0=f!k8PogH<`TLmt1CV4Fxy1GYWn;5>D`R6X z=0-FDPO7lG%Stt@&oJx)78QRJCW{J9YY{CHaT1vfVr+oP zt^|~BS~rMWEd=q7A3ULdf(fpHBunV-=+96;N2I%>uaM8hP4s@9NSufFwqcGMi4B|R zJ+LOElrK>KV?(cZjsdBNK`T?`A-;f;P#*xWqdK z?QDa&3Idd_uPBYh`U+$5K@MP_VC-uk$r8Hy`VH#mh;;Q81^Kk|b#D?AA5uposW<}m zjMN|}U3 z{JNRsk637!N&41skW8{pegDuE6ewNL*iWKKUL}(xnyp~6SIH!QMu#~f?Ww+rQxAhV zYOB&aPw&f_q~EC0GD$16tkg{M7mOWdl9v{>PbPUlUH^pc>`FlCJAQ+>$RyDm2hSvR zOpq3t{s!h8k?xLutxU4F4d23KvmpE>*Fb3?S|XGD9ra-*=@WKluaCE$OyZ*dZi6F} z`~%D|lMD=gfK1|0=f7eA&LlwT`g+Mj4*ET`r@mfb_BkS5ef>|Fq!rrqfiuZNOgo?| zWRicQKFlQ1Zbr*FP$t14>R%Xv%^zr~dLbx>7sWH)gQoCno4zL$;sg_duA7ZDK^MM{ zo8sXNUl~|;%E|RSHny5Yce4Zj#;8B+LAm$fA}rq T&6Eq}q4H??7`+3fiDUl-6FDG! literal 0 HcmV?d00001 diff --git a/api/admin.py b/api/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/api/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/api/apps.py b/api/apps.py new file mode 100644 index 0000000..66656fd --- /dev/null +++ b/api/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'api' diff --git a/api/migrations/__init__.py b/api/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/migrations/__pycache__/__init__.cpython-310.pyc b/api/migrations/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..086210368169cfeafd0e51b9b65c206304b13912 GIT binary patch literal 148 zcmd1j<>g`kf{SH+Ng(<$h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6w<#VRHxD={xU zKRz=zF+Ekcv>+!xF(tJ~H?g1~Cb1whCO0#^D6u3nKd(3@K0Y%qvm`!Vub}c4hfQvN RN@-529mv39CLqDW001ghBAfsK literal 0 HcmV?d00001 diff --git a/api/models.py b/api/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/api/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/api/serializers.py b/api/serializers.py new file mode 100644 index 0000000..f8d1d17 --- /dev/null +++ b/api/serializers.py @@ -0,0 +1,20 @@ +from rest_framework import serializers +from uploader.models import Uploader, Comment, Profile + + +class UploaderSerializer(serializers.ModelSerializer): + class Meta: + model = Uploader + fields = '__all__' + + +class CommentSerializer(serializers.ModelSerializer): + class Meta: + model = Comment + fields = '__all__' + + +class ProfileSerializer(serializers.ModelSerializer): + class Meta: + model = Profile + fields = '__all__' diff --git a/api/tests.py b/api/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/api/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/api/urls.py b/api/urls.py new file mode 100644 index 0000000..35a81d7 --- /dev/null +++ b/api/urls.py @@ -0,0 +1,25 @@ +from django.urls import path +from .views import * + +urlpatterns = [ + path('uploader-list/', UploaderList.as_view(), name="uploader-list"), + path('uploader-detail//', UploaderDetail.as_view(), name="uploader-detail"), + path('uploader-create/', UploaderCreate.as_view(), name="uploader-create"), + path('uploader-update//', UploaderUpdate.as_view(), name="uploader-update"), + path('uploader-patch//', UploaderUpdate.as_view(), name="uploader-patch"), + path('uploader-delete//', UploaderDelete.as_view(), name="uploader-delete"), + + path('comment-list/', CommentList.as_view(), name="comment-list"), + path('comment-detail//', CommentDetail.as_view(), name="comment-detail"), + path('comment-create/', CommentCreate.as_view(), name="comment-create"), + path('comment-update//', CommentUpdate.as_view(), name="comment-update"), + path('comment-patch//', CommentUpdate.as_view(), name="comment-patch"), + path('comment-delete//', CommentDelete.as_view(), name="comment-delete"), + + path('profile-list/', ProfileList.as_view(), name="profile-list"), + path('profile-detail//', ProfileDetail.as_view(), name="profile-detail"), + path('profile-create/', ProfileCreate.as_view(), name="profile-create"), + path('profile-update//', ProfileUpdate.as_view(), name="profile-update"), + path('profile-patch//', ProfileUpdate.as_view(), name="profile-patch"), + path('profile-delete//', ProfileDelete.as_view(), name="profile-delete"), +] \ No newline at end of file diff --git a/api/views.py b/api/views.py new file mode 100644 index 0000000..e4ad19d --- /dev/null +++ b/api/views.py @@ -0,0 +1,242 @@ +from django.shortcuts import render +from rest_framework.views import APIView +from rest_framework.decorators import api_view +from uploader.models import Uploader, Comment, Profile +from .serializers import UploaderSerializer, CommentSerializer, ProfileSerializer +from rest_framework.response import Response +from rest_framework import status +from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly +from rest_framework.authentication import TokenAuthentication + +# Create your views here. + +class UploaderList(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticatedOrReadOnly] + + def get(self, request, format=None): + uploaders = Uploader.objects.all() + serializer = UploaderSerializer(uploaders, many=True) + return Response(serializer.data) + +class UploaderCreate(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def post(self, request, format=None): + serializer = UploaderSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class UploaderDetail(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticatedOrReadOnly] + + def get_object(self, pk): + try: + return Uploader.objects.get(pk=pk) + except Uploader.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def get(self, request, pk, format=None): + uploader = self.get_object(pk) + serializer = UploaderSerializer(uploader) + return Response(serializer.data) + +class UploaderUpdate(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def get_object(self, pk): + try: + return Uploader.objects.get(pk=pk) + except Uploader.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def put(self, request, pk, format=None): + uploader = self.get_object(pk) + serializer = UploaderSerializer(uploader, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def patch(self, request, pk, format=None): + uploader = self.get_object(pk) + serializer = UploaderSerializer( + uploader, data=request.data, partial=True) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class UploaderDelete(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def get_object(self, pk): + try: + return Uploader.objects.get(pk=pk) + except Uploader.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def delete(self, request, pk, format=None): + uploader = self.get_object(pk) + uploader.delete() + return Response('Uploader deleted', status=status.HTTP_204_NO_CONTENT) + +class CommentList(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticatedOrReadOnly] + + def get(self, request, format=None): + comments = Comment.objects.all() + serializer = CommentSerializer(comments, many=True) + return Response(serializer.data) + +class CommentCreate(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def post(self, request, format=None): + serializer = CommentSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class CommentDetail(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticatedOrReadOnly] + + def get_object(self, pk): + try: + return Comment.objects.get(pk=pk) + except Comment.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def get(self, request, pk, format=None): + comment = self.get_object(pk) + serializer = CommentSerializer(comment) + return Response(serializer.data) + +class CommentUpdate(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def get_object(self, pk): + try: + return Comment.objects.get(pk=pk) + except Comment.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def put(self, request, pk, format=None): + comment = self.get_object(pk) + serializer = CommentSerializer(comment, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def patch(self, request, pk, format=None): + comment = self.get_object(pk) + serializer = CommentSerializer( + comment, data=request.data, partial=True) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class CommentDelete(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def get_object(self, pk): + try: + return Comment.objects.get(pk=pk) + except Comment.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def delete(self, request, pk, format=None): + comment = self.get_object(pk) + comment.delete() + return Response('Comment deleted', status=status.HTTP_204_NO_CONTENT) + +class ProfileList(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticatedOrReadOnly] + + def get(self, request, format=None): + profiles = Profile.objects.all() + serializer = ProfileSerializer(profiles, many=True) + return Response(serializer.data) + +class ProfileCreate(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def post(self, request, format=None): + serializer = ProfileSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class ProfileDetail(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticatedOrReadOnly] + + def get_object(self, pk): + try: + return Profile.objects.get(pk=pk) + except Profile.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def get(self, request, pk, format=None): + profile = self.get_object(pk) + serializer = ProfileSerializer(profile) + return Response(serializer.data) + +class ProfileUpdate(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def get_object(self, pk): + try: + return Profile.objects.get(pk=pk) + except Profile.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def put(self, request, pk, format=None): + profile = self.get_object(pk) + serializer = ProfileSerializer(profile, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def patch(self, request, pk, format=None): + profile = self.get_object(pk) + serializer = ProfileSerializer( + profile, data=request.data, partial=True) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class ProfileDelete(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] + + def get_object(self, pk): + try: + return Profile.objects.get(pk=pk) + except Profile.DoesNotExist: + raise Response(status=status.HTTP_404_NOT_FOUND) + + def delete(self, request, pk, format=None): + profile = self.get_object(pk) + profile.delete() + return Response('profile deleted', status=status.HTTP_204_NO_CONTENT) diff --git a/config/nginx/Dockerfile b/config/nginx/Dockerfile new file mode 100644 index 0000000..e535f00 --- /dev/null +++ b/config/nginx/Dockerfile @@ -0,0 +1,7 @@ +FROM nginx:1.21.6 +LABEL MAINTAINER="Amir Keyhani | https://amir.key_" + +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/config/nginx/docker-compose.yml b/config/nginx/docker-compose.yml new file mode 100644 index 0000000..917a288 --- /dev/null +++ b/config/nginx/docker-compose.yml @@ -0,0 +1,25 @@ +version: "3.9" + +services: + nginx: + container_name: nginx + build: + context: . + dockerfile: Dockerfile + ports: + - "80:80" + volumes: + - imageuploader_static_volume:/imageuploader/static + - imageuploader_media_volume:/imageuploader/media + networks: + - nginx_network + + +volumes: + imageuploader_static_volume: + external: true + imageuploader_media_volume: + external: true +networks: + nginx_network: + external: true \ No newline at end of file diff --git a/config/nginx/nginx.conf b/config/nginx/nginx.conf new file mode 100644 index 0000000..0af5b40 --- /dev/null +++ b/config/nginx/nginx.conf @@ -0,0 +1,30 @@ +upstream imageuploader { + server imageuploader:8000; +} + +server { + listen 80; + server_name imageuploader.amirk.cloud www.imageuploader.amirk.cloud; + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + root /usr/share/nginx/html; + index index.html index.htm; + + location / { + proxy_pass http://imageuploader; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Real-IP $remote_addr; + } + + location /static/ { + alias /imageuploader/static/; + } + + location /media/ { + alias /imageuploader/media/; + } +} \ No newline at end of file diff --git a/imageuploader/__init__.py b/imageuploader/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/imageuploader/__pycache__/__init__.cpython-310.pyc b/imageuploader/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04e2f31cf228f01625f65b270db67211a2a73836 GIT binary patch literal 147 zcmd1j<>g`kg1`CV2_X70h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wv#VRHxD={xU zKRz=zF+Ekcv>+!xF(tJ~H?g1~1}p>i~$EXlHDU2Hiv9Y?k(MPO9fZpYK6fk{x}h$1-zXxTfS!9dt02?-Yl z3tAPX51r{J^r0_)Nb=TC=&#^4PyT^EWZI->K~jP!P3%b8#o4pxoIUqlxid4l1pNH- z-~TweznDn;$QJRR6fC}hLGN;j1Wup?<}hz@Hjj9Y!AUELl7uJ1-?{ImzE2#dj#DU& z1(d;4D2r1#-Q`iPo4}bLICKNPS@=%l9GbywHH~Lrp8bI{IehcI(B;r9o<_-$nCy6)oUtbQ{JZj3tshUjA+cWZe6n zM|bdN=`2&+%jQ2;_VLV+}t+kMTM# z;0?UlaKyT$W7~A{)YmrT6<{k9h9MfI(non6+F(w|Xx13roT6p%-Ao@jdfMj65DJOkxLqFIb&GG8W?a z{#l>UV0mJb5=tQkS2t|ffE1v?-AN7~qGqsI(cs=#eG!zVVtbS>CD-Yg-C$nto5KyM zZ;o)2c2LtN6s2{`(wXizM}VjshC6WlU~!C~u3_rd82$KKvc`Y)deD{Pn=!W5X zv`1JqQD`Q|T0|KceJ8#WJ<^55g%X3XKu7XA+L=zfg&V=vC=j-Zu|-aGkBEkD^a!{e zLqV1pd~m*Z9XTb&z%%_bQ5gX-@~4ww9wmktJ5CwmVq9x6tKyU;Fg8Y3xJGr?wp~Xo zMW2t5Qm-SHV0vYe(-`URCsbz6j4L6*8WP_$B45TBCv6?)dYt)SnEx@Z=hqlvna0Vn zZk#}?6JJ+Y8Z`PWaB<_mx`r=`TZQ;Wuj0A(WayxKKv_7hNl9F#Lx!z0Y)q^9OKn6P zcoq$cqZ55%_bo^b@d#8T4j%VXu^hE+b+k=YG#@pIzxWzdkO7uM_zFU>J}Kuam59mF zpc`y_0;Na3g{JEVnuf=P^e1>vX_M`BG{WyKT6TQPAPN?tid&8Lg_-jh;2$d$!Go;_(U;n)6!X`z8X@v zUhws&N;)td(;nD0;&lDq1^=Hvm48@~&5@250>1fF0ri1RJkz);VTw3g1B#MuwS-de zSb)k5GQ}ZKL{m1wrXHk=(YF|k?tRD%Xmqx2S{Lqz*i+XcqRh}Qhq?U$UNVVb+-NT4 z)_L|HxR{LTgPrl!FuGHsUag(eUTz+vLw@3lprGY;O{ZAk(bAr(HnrDUrO`T+T4lMc zHCqj}5l%(#7nFmG#b>R&|1^NM9=|BWz78^mp>M)93qCs{9zY}H2ll`Xb|#ou_FObH z=;G1ceOc3B``4LNb{k!0DJ0QKS*}R!nyNJ=NMVVUh*qjeih{C$ku{}?WORQ_B(>E& zxvo}AF+y1}|MnuA2or_PFs*6ua?`Xh-G}#)WgdAvm=p3Y4Ktd?o(^me^mMIvBuw?; zDsz04c_}F}tI{y1$fcI7YWwn=aH=f7Z109MQmxiF1P|{u6jcdlt93;M6d<6ql`wZu zEthLDL_rRxTaAXQwOh4Pqh1NKs(jF_Nvf=bbBD@qmC@Hmnupo4q)O~qC0t=ff%%GZ z*l3ltS5mDCn+<3lGc~Ec+h$%UHOevwtRBc3YCxf9+MsZC`w#UYRNMZl9;O&hMWMh< z4~1jbbix~;D|ky|ih*&%1t&QJg~^utZUG}!XzZ7r!(AKQb-HQ44;|GtO~Qdz;is8;rU;L{|dhdb9|cT zQk?KJzzcvAV&gx;f&k>~cQz$(Y%rKl@{E28R&34YB%cAPJdB@H{}ZwTm*M^o&7c@{ literal 0 HcmV?d00001 diff --git a/imageuploader/__pycache__/urls.cpython-310.pyc b/imageuploader/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e63604341524a157526780a3bf0fb333b8612d2c GIT binary patch literal 2195 zcma)8O>f&q5G83!)VHlTaU91_%{b2O}DBh(|qF?5Mn!j;H$%&6j2)YuHGk>ywlSHfCUcj^jP!^V;1 zTVXS5IW1+Yh3%;0bQG?KtI?XXR@%EC?2Yh3wC=3y8tIVr*+tyME!@TuU&5<+?Mw%> zfxGy^nU2@bs`w&Vn_V93_|n;mvq?<6L5$gz+16VF@MTiLn{Rc6uK?aE@m0XvCB6pu zdWmlUMkT%p_=^&MNj7I!@mG+|tuq7PhP79~drw(+N^4(QCv|6=ShH*F9oZ&zK-b~A zf$y9d-)hb_{`!R`ul}w#H#9AXya{pBB%~fD4845*6g{BvIGCi&69J7IjiV_+uTvH# zo)Cn^{51*#E)b)sAY4Ack)Y@#Aag!Mk0?VCWdsHBn6gN@KuJhEP7o(#zk%SG3X$-A z+s4%ALp<~12~8NC5nl{_8rdYazZve?f+m5_ZArFad2TlzzVRaP#rGSJ(%6^L70W88 zdqXtB7+P0#O=(1SQS3$J z`<}$Te&a#taXvVP#PE{W|BHf(DPb~@p%Q8l&J*yZqW{cjB!B2}S3240e-hDQ?1w21 z;t7bL)|09Eu$c>e4wWznLV@j(T(Z+g<5J4~Lat&vhEniFkR^9liSpUe9*1;dgMf>b zdeWf$_WJ$CU-E75>v_e)Q4sfy+?0yvR>_8$8Ye>!9EwDGuxLVJFA1{lp)B~9i+UgZeCQY_d)ciK;;Oh1 zSP+yhI?wx+9FLMDyS*sg`FuW{P&x^TD%pgFfgccVLp%|;v+k6HA-zY6f|V4Ap#tFr zVb;9=;s8Ajd=hg4R#R40znWJ>AVT7-;vzTqgfJO=-o%9aEJ$RzJ8R0nOUEuJ>;!x` z7HqKae34rafpmEUVpfy%7>3S;k0Q9ftXIObs#4s}wXD5(>(#DgbSJfsSK474@67 zN`@Lq2QZmNBo;2CRQ%LOx#hZGb6uxXz7Rc)$wgMJrE}P|x$0}fP zE`NM_tk}b%oLN=Qc0TNa>I}}tCwi(r%Q&k^@~4wU3Y^vD%ANC1GWm&x(An5M_4uS{ zJb7&~W=;8wc?f;lu^tpfIn8U|MHHtY`2qeGX#5G>Os%!Lrnlg%8S)M%{2GR-8|B&18@l=4s8#jqKdp7e TSSgqr=7w(mUF~k_=D+^|?ToXi literal 0 HcmV?d00001 diff --git a/imageuploader/asgi.py b/imageuploader/asgi.py new file mode 100644 index 0000000..52c7868 --- /dev/null +++ b/imageuploader/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for image_uploader project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'imageuploader.settings') + +application = get_asgi_application() diff --git a/imageuploader/settings.py b/imageuploader/settings.py new file mode 100644 index 0000000..5b5f505 --- /dev/null +++ b/imageuploader/settings.py @@ -0,0 +1,195 @@ +""" +Django settings for image_uploader project. + +Generated by 'django-admin startproject' using Django 3.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.1/ref/settings/ +""" + +from pathlib import Path +import os + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '%1=gz)n5#))jpo+ac*wh6&mtrn6u*wn#zv%54fjzepn+*u(r*!' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + +ALLOWED_HOSTS = ['imageuploader-app.herokuapp.com', 'localhost'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'uploader.apps.UploaderConfig', + 'api.apps.ApiConfig', + + 'django.contrib.sites', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + 'allauth.socialaccount.providers.google', + 'allauth.socialaccount.providers.facebook', + 'allauth.socialaccount.providers.github', + 'crispy_forms', + + 'rest_framework', + 'rest_framework.authtoken', + # 'corsheaders', + 'dj_rest_auth', + 'dj_rest_auth.registration', + 'drf_yasg', +] + +MIDDLEWARE = [ + # 'django.middleware.cache.UpdateCacheMiddleware', + 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + # 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + # 'django.middleware.cache.FetchFromCacheMiddleware', +] + +ROOT_URLCONF = 'imageuploader.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'imageuploader.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + # 'ENGINE': 'django.db.backends.postgresql_psycopg2', + # 'NAME': 'postgres', + # 'USER': 'postgres', + # 'PASSWORD': 'postgres', + # 'HOST': 'imageuploader_postgresql', + # 'PORT': 5432, + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.1/howto/static-files/ + +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +STATIC_URL = '/static/' +# STATICFILES_DIRS = [ +# os.path.join(BASE_DIR, 'staticfiles'), +# ] + +# Media Files +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +SITE_ID = 1 + +AUTHENTICATION_BACKENDS = [ + 'django.contrib.auth.backends.ModelBackend', + 'allauth.account.auth_backends.AuthenticationBackend', +] + +LOGIN_REDIRECT_URL = '/' +LOGIN_URL = '/login/' +LOGOUT_REDIRECT_URL = '/login/' + +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +SESSION_COOKIE_SECURE = True +CSRF_COOKIE_SECURE = True +# SECURE_SSL_REDIRECT = True + +CRISPY_TEMPLATE_PACK = 'bootstrap4' + +# CORS_ORIGIN_WHITELIST = [ +# 'http://127.0.0.1:3000', +# 'http://127.0.0.1:8000' +# ] + +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 10, + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.TokenAuthentication', + ] +} + +# CACHE_MIDDLEWARE_ALIAS = 'default' +# CACHE_MIDDLEWARE_SECONDS = 604800 +# CACHE_MIDDLEWARE_KEY_PREFIX = '' diff --git a/imageuploader/urls.py b/imageuploader/urls.py new file mode 100644 index 0000000..7bf025e --- /dev/null +++ b/imageuploader/urls.py @@ -0,0 +1,65 @@ +"""image_uploader URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path,include +from django.conf import settings +from django.conf.urls.static import static + +from uploader.views import * +from rest_framework.routers import DefaultRouter +from rest_framework.schemas import get_schema_view +from rest_framework import permissions + +from drf_yasg.views import get_schema_view +from drf_yasg import openapi + +schema_view = get_schema_view( + openapi.Info( + title="ImageUploader API", + default_version="v1", + description="A sample API for ImageUploader WebApp", + terms_of_service="https://www.google.com/policies/terms/", + contact=openapi.Contact(email="hello@example.com"), + license=openapi.License(name="BSD License"), + ), + public=True, + permission_classes=(permissions.AllowAny,) +) + +# router = DefaultRouter() +# router.register(r'uploader', UploaderViewSet, 'uploader') +# router.register(r'comment', CommentViewSet, 'comment') +# router.register(r'profile', ProfileViewSet, 'profile') + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('uploader.urls')), + path('accounts/', include('allauth.urls')), + + # path('api/', include(router.urls)), + path('api/v1/', include('api.urls')), + path('api-auth/', include('rest_framework.urls')), + path('dj-rest-auth/', include('dj_rest_auth.urls')), + path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')), + # path('openapi', get_schema_view(title='imageuploader API', + # description='A sample API for ImageUploader WebApp', + # version='1.0.0'), name='openapi-schema'), + path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), + path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), +] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/imageuploader/wsgi.py b/imageuploader/wsgi.py new file mode 100644 index 0000000..9a3ee52 --- /dev/null +++ b/imageuploader/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for image_uploader project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'imageuploader.settings') + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..e80604c --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'imageuploader.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/openapi-schema.yml b/openapi-schema.yml new file mode 100644 index 0000000..1c949d7 --- /dev/null +++ b/openapi-schema.yml @@ -0,0 +1,929 @@ +openapi: 3.0.2 +info: + title: '' + version: '' +paths: + /api/v1/imageuploader/: + get: + operationId: listImageUploaders + description: '' + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ImageUploader' + description: '' + tags: + - api + post: + operationId: createImageUploader + description: '' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ImageUploader' + multipart/form-data: + schema: + $ref: '#/components/schemas/ImageUploader' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + description: '' + tags: + - api + /api/v1/imageuploader/{id}/: + get: + operationId: retrieveImageUploader + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this image uploader. + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + description: '' + tags: + - api + put: + operationId: updateImageUploader + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this image uploader. + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ImageUploader' + multipart/form-data: + schema: + $ref: '#/components/schemas/ImageUploader' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + description: '' + tags: + - api + patch: + operationId: partialUpdateImageUploader + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this image uploader. + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ImageUploader' + multipart/form-data: + schema: + $ref: '#/components/schemas/ImageUploader' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploader' + description: '' + tags: + - api + delete: + operationId: destroyImageUploader + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this image uploader. + schema: + type: string + responses: + '204': + description: '' + tags: + - api + /api/v1/comments/: + get: + operationId: listComments + description: '' + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Profile' + description: '' + tags: + - api + post: + operationId: createComment + description: '' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Profile' + multipart/form-data: + schema: + $ref: '#/components/schemas/Profile' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + description: '' + tags: + - api + /api/v1/comments/{id}/: + get: + operationId: retrieveComment + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this comment. + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + description: '' + tags: + - api + put: + operationId: updateComment + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this comment. + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Profile' + multipart/form-data: + schema: + $ref: '#/components/schemas/Profile' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + description: '' + tags: + - api + patch: + operationId: partialUpdateComment + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this comment. + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Profile' + multipart/form-data: + schema: + $ref: '#/components/schemas/Profile' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + description: '' + tags: + - api + delete: + operationId: destroyComment + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this comment. + schema: + type: string + responses: + '204': + description: '' + tags: + - api + /api/v1/prof/: + get: + operationId: listProfiles + description: '' + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Comment' + description: '' + tags: + - api + post: + operationId: createProfile + description: '' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Comment' + multipart/form-data: + schema: + $ref: '#/components/schemas/Comment' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + description: '' + tags: + - api + /api/v1/prof/{id}/: + get: + operationId: retrieveProfile + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this profile. + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + description: '' + tags: + - api + put: + operationId: updateProfile + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this profile. + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Comment' + multipart/form-data: + schema: + $ref: '#/components/schemas/Comment' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + description: '' + tags: + - api + patch: + operationId: partialUpdateProfile + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this profile. + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Comment' + multipart/form-data: + schema: + $ref: '#/components/schemas/Comment' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + description: '' + tags: + - api + delete: + operationId: destroyProfile + description: '' + parameters: + - name: id + in: path + required: true + description: A unique integer value identifying this profile. + schema: + type: string + responses: + '204': + description: '' + tags: + - api + /api/v1/dj-rest-auth/logout/: + get: + operationId: listLogouts + description: 'Calls Django logout method and delete the Token object + + assigned to the current User object. + + + Accepts/Returns nothing.' + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: {} + description: '' + tags: + - api + post: + operationId: createLogout + description: 'Calls Django logout method and delete the Token object + + assigned to the current User object. + + + Accepts/Returns nothing.' + parameters: [] + requestBody: + content: + application/json: + schema: {} + application/x-www-form-urlencoded: + schema: {} + multipart/form-data: + schema: {} + responses: + '201': + content: + application/json: + schema: {} + description: '' + tags: + - api + /api/v1/dj-rest-auth/user/: + get: + operationId: retrieveUserDetails + description: 'Reads and updates UserModel fields + + Accepts GET, PUT, PATCH methods. + + + Default accepted fields: username, first_name, last_name + + Default display fields: pk, username, email, first_name, last_name + + Read-only fields: pk, email + + + Returns UserModel fields.' + parameters: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/UserDetails' + description: '' + tags: + - api + put: + operationId: updateUserDetails + description: 'Reads and updates UserModel fields + + Accepts GET, PUT, PATCH methods. + + + Default accepted fields: username, first_name, last_name + + Default display fields: pk, username, email, first_name, last_name + + Read-only fields: pk, email + + + Returns UserModel fields.' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDetails' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/UserDetails' + multipart/form-data: + schema: + $ref: '#/components/schemas/UserDetails' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/UserDetails' + description: '' + tags: + - api + patch: + operationId: partialUpdateUserDetails + description: 'Reads and updates UserModel fields + + Accepts GET, PUT, PATCH methods. + + + Default accepted fields: username, first_name, last_name + + Default display fields: pk, username, email, first_name, last_name + + Read-only fields: pk, email + + + Returns UserModel fields.' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDetails' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/UserDetails' + multipart/form-data: + schema: + $ref: '#/components/schemas/UserDetails' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/UserDetails' + description: '' + tags: + - api + /api/v1/dj-rest-auth/password/reset/: + post: + operationId: createPasswordReset + description: 'Calls Django Auth PasswordResetForm save method. + + + Accepts the following POST parameters: email + + Returns the success/fail message.' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordReset' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PasswordReset' + multipart/form-data: + schema: + $ref: '#/components/schemas/PasswordReset' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordReset' + description: '' + tags: + - api + /api/v1/dj-rest-auth/password/reset/confirm/: + post: + operationId: createPasswordResetConfirm + description: "Password reset e-mail link is confirmed, therefore\nthis resets\ + \ the user's password.\n\nAccepts the following POST parameters: token, uid,\n\ + \ new_password1, new_password2\nReturns the success/fail message." + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + multipart/form-data: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordResetConfirm' + description: '' + tags: + - api + /api/v1/dj-rest-auth/login/: + post: + operationId: createLogin + description: 'Check the credentials and return the REST Token + + if the credentials are valid and authenticated. + + Calls Django Auth login method to register User ID + + in Django session framework + + + Accept the following POST parameters: username, password + + Return the REST Framework Token Object''s key.' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Login' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Login' + multipart/form-data: + schema: + $ref: '#/components/schemas/Login' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/Login' + description: '' + tags: + - api + /api/v1/dj-rest-auth/password/change/: + post: + operationId: createPasswordChange + description: 'Calls Django Auth SetPasswordForm save method. + + + Accepts the following POST parameters: new_password1, new_password2 + + Returns the success/fail message.' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordChange' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PasswordChange' + multipart/form-data: + schema: + $ref: '#/components/schemas/PasswordChange' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordChange' + description: '' + tags: + - api + /api/v1/dj-rest-auth/registration/: + post: + operationId: createRegister + description: '' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Register' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Register' + multipart/form-data: + schema: + $ref: '#/components/schemas/Register' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/Register' + description: '' + tags: + - api + /api/v1/dj-rest-auth/registration/verify-email/: + post: + operationId: createVerifyEmail + description: '' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyEmail' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/VerifyEmail' + multipart/form-data: + schema: + $ref: '#/components/schemas/VerifyEmail' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyEmail' + description: '' + tags: + - api + /api/v1/dj-rest-auth/registration/resend-email/: + post: + operationId: createEmailAddress + description: '' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResendEmailVerification' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ResendEmailVerification' + multipart/form-data: + schema: + $ref: '#/components/schemas/ResendEmailVerification' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/ResendEmailVerification' + description: '' + tags: + - api +components: + schemas: + ImageUploader: + type: object + properties: + id: + type: integer + readOnly: true + title: + type: string + maxLength: 100 + image: + type: string + format: binary + user: + type: string + maxLength: 100 + user_prof: + type: string + maxLength: 100 + date: + type: string + format: date + readOnly: true + likes: + type: integer + required: + - title + - image + - user + - user_prof + Profile: + type: object + properties: + user: + type: integer + prof_img: + type: string + format: binary + bio: + type: string + required: + - user + Comment: + type: object + properties: + id: + type: integer + readOnly: true + name: + type: string + maxLength: 80 + email: + type: string + format: email + maxLength: 254 + body: + type: string + created_at: + type: string + format: date-time + readOnly: true + active: + type: boolean + post: + type: integer + required: + - name + - email + - body + - post + UserDetails: + type: object + properties: + pk: + type: integer + readOnly: true + username: + type: string + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+\z + maxLength: 150 + email: + type: string + format: email + readOnly: true + first_name: + type: string + maxLength: 150 + last_name: + type: string + maxLength: 150 + required: + - username + PasswordReset: + type: object + properties: + email: + type: string + format: email + required: + - email + PasswordResetConfirm: + type: object + properties: + new_password1: + type: string + maxLength: 128 + new_password2: + type: string + maxLength: 128 + uid: + type: string + token: + type: string + required: + - new_password1 + - new_password2 + - uid + - token + Login: + type: object + properties: + username: + type: string + email: + type: string + format: email + password: + type: string + required: + - password + PasswordChange: + type: object + properties: + new_password1: + type: string + maxLength: 128 + new_password2: + type: string + maxLength: 128 + required: + - new_password1 + - new_password2 + Register: + type: object + properties: + username: + type: string + maxLength: 150 + minLength: 1 + email: + type: string + format: email + password1: + type: string + writeOnly: true + password2: + type: string + writeOnly: true + required: + - username + - password1 + - password2 + VerifyEmail: + type: object + properties: + key: + type: string + required: + - key + ResendEmailVerification: + type: object + properties: + email: + type: string + format: email diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7511180 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,41 @@ +asgiref==3.5.2 +autopep8==1.6.0 +certifi==2022.5.18.1 +cffi==1.15.0 +charset-normalizer==2.0.12 +coreapi==2.3.3 +coreschema==0.0.4 +cryptography==37.0.2 +defusedxml==0.7.1 +dj-database-url==0.5.0 +dj-rest-auth==2.2.4 +Django==4.0.4 +django-allauth==0.50.0 +django-cors-headers==3.12.0 +django-crispy-forms==1.14.0 +djangorestframework==3.13.1 +drf-yasg==1.20.0 +idna==3.3 +inflection==0.5.1 +itypes==1.2.0 +Jinja2==3.1.2 +MarkupSafe==2.1.1 +oauthlib==3.2.0 +packaging==21.3 +Pillow==9.1.1 +pycodestyle==2.8.0 +pycparser==2.21 +PyJWT==2.4.0 +pyparsing==3.0.9 +python3-openid==3.2.0 +pytz==2022.1 +requests==2.27.1 +requests-oauthlib==1.3.1 +ruamel.yaml==0.17.21 +ruamel.yaml.clib==0.2.6 +sqlparse==0.4.2 +toml==0.10.2 +tzdata==2022.1 +uritemplate==4.1.1 +urllib3==1.26.9 +whitenoise==6.1.0 diff --git a/uploader/__init__.py b/uploader/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/uploader/admin.py b/uploader/admin.py new file mode 100644 index 0000000..ef34793 --- /dev/null +++ b/uploader/admin.py @@ -0,0 +1,32 @@ +from django.contrib import admin +from .models import Uploader, Profile, Comment + +# Register your models here. +admin.site.site_header = 'Image Uploader administration' +admin.site.index_title = 'Img_uploader-app administration' +admin.site.site_title = 'Django site admin' + + +@admin.register(Uploader) +class UploaderAdmin(admin.ModelAdmin): + list_display = ['id', 'name', 'image', 'user', 'profile', 'created_at'] + + +@admin.register(Profile) +class ProfileAdmin(admin.ModelAdmin): + list_display = ['id', 'user', 'image'] + # list_display_links = ['user'] + list_editable = ('user',) + list_filter = ['user'] + search_fields = ['user', 'image'] + + +@admin.register(Comment) +class CommentAdmin(admin.ModelAdmin): + list_display = ['user', 'text', 'image', 'commented_at', 'active'] + list_filter = ['active', 'commented_at'] + search_fields = ['user', 'email', 'text'] + actions = ['approve_comments'] + + def approve_comments(self, request, queryset): + queryset.update(active=True) diff --git a/uploader/apps.py b/uploader/apps.py new file mode 100644 index 0000000..4a1f915 --- /dev/null +++ b/uploader/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + +class UploaderConfig(AppConfig): + name = 'uploader' + + def ready(self): + import uploader.signals diff --git a/uploader/forms.py b/uploader/forms.py new file mode 100644 index 0000000..f1bdc5b --- /dev/null +++ b/uploader/forms.py @@ -0,0 +1,44 @@ +from django import forms +from django.contrib.auth.models import User +from django.contrib.auth.forms import UserCreationForm +from .models import Uploader, Profile, Comment + +# Create your forms here. + + +class UploaderForm(forms.ModelForm): + class Meta: + model = Uploader + fields = '__all__' + exclude = ['like', 'created_at'] + + +class SignupForm(UserCreationForm): + email = forms.EmailField(max_length=150, help_text='Email') + first_name = forms.CharField(max_length=100, help_text='First Name') + last_name = forms.CharField(max_length=100, help_text='Last Name') + + class Meta: + model = User + fields = ['username', 'first_name', 'last_name', + 'email', 'password1', 'password2'] + + +class UpdateUserForm(forms.ModelForm): + email = forms.EmailField(max_length=150) + + class Meta: + model = User + fields = ['username', 'email', 'first_name', 'last_name'] + + +class ProfileUpdateForm(forms.ModelForm): + class Meta: + model = Profile + fields = ['image', 'bio'] + + +class CommentForm(forms.ModelForm): + class Meta: + model = Comment + fields = ['user', 'email', 'text'] diff --git a/uploader/models.py b/uploader/models.py new file mode 100644 index 0000000..67acad4 --- /dev/null +++ b/uploader/models.py @@ -0,0 +1,57 @@ +from django.db import models +from django.contrib.auth.models import User +from django.urls import reverse + +# Create your models here. + + +def validate_file_extension(value): + import os + from django.core.exceptions import ValidationError + ext = os.path.splitext(value.name)[1] + valid_extensions = ['.jpg', '.png'] + if not ext.lower() in valid_extensions: + raise ValidationError('Unsupported file extension.') + + +class Profile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + image = models.ImageField(default='default.jpg', validators=[ + validate_file_extension], upload_to='profile_pics', null=True, blank=True) + bio = models.TextField(max_length=500, null=True, blank=True) + + def __str__(self) -> str: + return self.user.username + + +class Uploader(models.Model): + name = models.CharField(max_length=100, null=False, blank=False) + image = models.ImageField( + validators=[validate_file_extension], upload_to='images', null=False, blank=False) + user = models.CharField(max_length=100, null=False, blank=False) + profile = models.CharField(max_length=100, null=False, blank=False) + created_at = models.DateTimeField(auto_now_add=True, blank=False) + like = models.IntegerField(default=0, blank=True) + + def __str__(self) -> str: + return f'{self.name} {self.user}' + + def get_absolute_url(self): + return reverse("image_detail", kwargs={"pk": str(self.pk)}) + # args = [str(self.id)] + + +class Comment(models.Model): + image = models.ForeignKey( + Uploader, on_delete=models.CASCADE, related_name='comments') + user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) + email = models.EmailField() + text = models.TextField() + commented_at = models.DateTimeField(auto_now_add=True, blank=False) + active = models.BooleanField(default=False) + + class Meta: + ordering = ['commented_at'] + + def __str__(self) -> str: + return f'Comment {self.text} by {self.user} with email ID: {self.email}' diff --git a/uploader/signals.py b/uploader/signals.py new file mode 100644 index 0000000..894e1db --- /dev/null +++ b/uploader/signals.py @@ -0,0 +1,15 @@ +from django.db.models.signals import post_save +from django.contrib.auth.models import User +from django.dispatch import receiver +from .models import Profile + + +@receiver(post_save, sender=User) +def create_profile(sender, instance, created, **kwargs): + if created: + Profile.objects.create(user=instance) + + +@receiver(post_save, sender=User) +def save_profile(sender, instance, **kwargs): + instance.profile.save() \ No newline at end of file diff --git a/uploader/static/bootstrap.min.css b/uploader/static/bootstrap.min.css new file mode 100644 index 0000000..32ee9d7 --- /dev/null +++ b/uploader/static/bootstrap.min.css @@ -0,0 +1,7 @@ +@charset "UTF-8";/*! + * Bootstrap v5.0.0-beta1 (https://getbootstrap.com/) + * Copyright 2011-2020 The Bootstrap Authors + * Copyright 2011-2020 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0))}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-font-sans-serif);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus{outline:dotted 1px;outline:-webkit-focus-ring-color auto 5px}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{width:100%;padding-right:var(--bs-gutter-x,.75rem);padding-left:var(--bs-gutter-x,.75rem);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y) * -1);margin-right:calc(var(--bs-gutter-x)/ -2);margin-left:calc(var(--bs-gutter-x)/ -2)}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x)/ 2);padding-left:calc(var(--bs-gutter-x)/ 2);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.3333333333%}.col-2{flex:0 0 auto;width:16.6666666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.3333333333%}.col-5{flex:0 0 auto;width:41.6666666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.3333333333%}.col-8{flex:0 0 auto;width:66.6666666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.3333333333%}.col-11{flex:0 0 auto;width:91.6666666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.3333333333%}.col-sm-2{flex:0 0 auto;width:16.6666666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.3333333333%}.col-sm-5{flex:0 0 auto;width:41.6666666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.3333333333%}.col-sm-8{flex:0 0 auto;width:66.6666666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.3333333333%}.col-sm-11{flex:0 0 auto;width:91.6666666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.3333333333%}.col-md-2{flex:0 0 auto;width:16.6666666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.3333333333%}.col-md-5{flex:0 0 auto;width:41.6666666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.3333333333%}.col-md-8{flex:0 0 auto;width:66.6666666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.3333333333%}.col-md-11{flex:0 0 auto;width:91.6666666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.3333333333%}.col-lg-2{flex:0 0 auto;width:16.6666666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.3333333333%}.col-lg-5{flex:0 0 auto;width:41.6666666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.3333333333%}.col-lg-8{flex:0 0 auto;width:66.6666666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.3333333333%}.col-lg-11{flex:0 0 auto;width:91.6666666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.3333333333%}.col-xl-2{flex:0 0 auto;width:16.6666666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.3333333333%}.col-xl-5{flex:0 0 auto;width:41.6666666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.3333333333%}.col-xl-8{flex:0 0 auto;width:66.6666666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.3333333333%}.col-xl-11{flex:0 0 auto;width:91.6666666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.3333333333%}.col-xxl-2{flex:0 0 auto;width:16.6666666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.3333333333%}.col-xxl-5{flex:0 0 auto;width:41.6666666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.3333333333%}.col-xxl-8{flex:0 0 auto;width:66.6666666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.3333333333%}.col-xxl-11{flex:0 0 auto;width:91.6666666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.3333333333%}.offset-xxl-2{margin-left:16.6666666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.3333333333%}.offset-xxl-5{margin-left:41.6666666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.3333333333%}.offset-xxl-8{margin-left:66.6666666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.3333333333%}.offset-xxl-11{margin-left:91.6666666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-bg:transparent;--bs-table-striped-color:#212529;--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:#212529;--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:#212529;--bs-table-hover-bg:rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:#212529;vertical-align:top;border-color:#dee2e6}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);background-image:linear-gradient(var(--bs-table-accent-bg),var(--bs-table-accent-bg));border-bottom-width:1px}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:last-child)>:last-child>*{border-bottom-color:currentColor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-striped>tbody>tr:nth-of-type(odd){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg:#cfe2ff;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:#000;border-color:#bacbe6}.table-secondary{--bs-table-bg:#e2e3e5;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:#000;border-color:#cbccce}.table-success{--bs-table-bg:#d1e7dd;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:#000;border-color:#bcd0c7}.table-info{--bs-table-bg:#cff4fc;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:#000;border-color:#badce3}.table-warning{--bs-table-bg:#fff3cd;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:#000;border-color:#e6dbb9}.table-danger{--bs-table-bg:#f8d7da;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:#000;border-color:#dfc2c4}.table-light{--bs-table-bg:#f8f9fa;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:#000;border-color:#dfe0e1}.table-dark{--bs-table-bg:#212529;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:#fff;border-color:#373b3e}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{max-width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em;border-radius:.25rem}.form-control-color::-webkit-color-swatch{height:1.5em;border-radius:.25rem}.form-select{display:block;width:100%;padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;vertical-align:middle;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{color:#6c757d;background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;transition:background-color .15s ease-in-out,background-position .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-check-input{transition:none}}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);padding:1rem .75rem}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control::-webkit-input-placeholder{color:transparent}.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:1.75rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#198754;padding-right:calc(.75em + 2.3125rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 1.75rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#198754}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#198754}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 1.75rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#dc3545}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#dc3545}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#212529;text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-primary{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-primary:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#0b5ed7;border-color:#0a58ca;box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-check:active+.btn-primary,.btn-check:checked+.btn-primary,.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0a58ca;border-color:#0a53be}.btn-check:active+.btn-primary:focus,.btn-check:checked+.btn-primary:focus,.btn-primary.active:focus,.btn-primary:active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#5c636a;border-color:#565e64;box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-check:active+.btn-secondary,.btn-check:checked+.btn-secondary,.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#565e64;border-color:#51585e}.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary:focus,.btn-secondary.active:focus,.btn-secondary:active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-success{color:#fff;background-color:#198754;border-color:#198754}.btn-success:hover{color:#fff;background-color:#157347;border-color:#146c43}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#157347;border-color:#146c43;box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-check:active+.btn-success,.btn-check:checked+.btn-success,.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#146c43;border-color:#13653f}.btn-check:active+.btn-success:focus,.btn-check:checked+.btn-success:focus,.btn-success.active:focus,.btn-success:active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#198754;border-color:#198754}.btn-info{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-info:hover{color:#000;background-color:#31d2f2;border-color:#25cff2}.btn-check:focus+.btn-info,.btn-info:focus{color:#000;background-color:#31d2f2;border-color:#25cff2;box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-check:active+.btn-info,.btn-check:checked+.btn-info,.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{color:#000;background-color:#3dd5f3;border-color:#25cff2}.btn-check:active+.btn-info:focus,.btn-check:checked+.btn-info:focus,.btn-info.active:focus,.btn-info:active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-info.disabled,.btn-info:disabled{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-warning{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#000;background-color:#ffca2c;border-color:#ffc720}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#000;background-color:#ffca2c;border-color:#ffc720;box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-check:active+.btn-warning,.btn-check:checked+.btn-warning,.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{color:#000;background-color:#ffcd39;border-color:#ffc720}.btn-check:active+.btn-warning:focus,.btn-check:checked+.btn-warning:focus,.btn-warning.active:focus,.btn-warning:active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#bb2d3b;border-color:#b02a37;box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-check:active+.btn-danger,.btn-check:checked+.btn-danger,.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#b02a37;border-color:#a52834}.btn-check:active+.btn-danger:focus,.btn-check:checked+.btn-danger:focus,.btn-danger.active:focus,.btn-danger:active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:focus+.btn-light,.btn-light:focus{color:#000;background-color:#f9fafb;border-color:#f9fafb;box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-check:active+.btn-light,.btn-check:checked+.btn-light,.btn-light.active,.btn-light:active,.show>.btn-light.dropdown-toggle{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:active+.btn-light:focus,.btn-check:checked+.btn-light:focus,.btn-light.active:focus,.btn-light:active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-light.disabled,.btn-light:disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#212529;border-color:#212529}.btn-dark:hover{color:#fff;background-color:#1c1f23;border-color:#1a1e21}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#1c1f23;border-color:#1a1e21;box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-check:active+.btn-dark,.btn-check:checked+.btn-dark,.btn-dark.active,.btn-dark:active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1a1e21;border-color:#191c1f}.btn-check:active+.btn-dark:focus,.btn-check:checked+.btn-dark:focus,.btn-dark.active:focus,.btn-dark:active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#212529;border-color:#212529}.btn-outline-primary{color:#0d6efd;border-color:#0d6efd}.btn-outline-primary:hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-check:active+.btn-outline-primary,.btn-check:checked+.btn-outline-primary,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show,.btn-outline-primary:active{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:active+.btn-outline-primary:focus,.btn-check:checked+.btn-outline-primary:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus,.btn-outline-primary:active:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#0d6efd;background-color:transparent}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-check:active+.btn-outline-secondary,.btn-check:checked+.btn-outline-secondary,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show,.btn-outline-secondary:active{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:active+.btn-outline-secondary:focus,.btn-check:checked+.btn-outline-secondary:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus,.btn-outline-secondary:active:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-success{color:#198754;border-color:#198754}.btn-outline-success:hover{color:#fff;background-color:#198754;border-color:#198754}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-check:active+.btn-outline-success,.btn-check:checked+.btn-outline-success,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show,.btn-outline-success:active{color:#fff;background-color:#198754;border-color:#198754}.btn-check:active+.btn-outline-success:focus,.btn-check:checked+.btn-outline-success:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus,.btn-outline-success:active:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#198754;background-color:transparent}.btn-outline-info{color:#0dcaf0;border-color:#0dcaf0}.btn-outline-info:hover{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-check:active+.btn-outline-info,.btn-check:checked+.btn-outline-info,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show,.btn-outline-info:active{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:active+.btn-outline-info:focus,.btn-check:checked+.btn-outline-info:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus,.btn-outline-info:active:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#0dcaf0;background-color:transparent}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-check:active+.btn-outline-warning,.btn-check:checked+.btn-outline-warning,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show,.btn-outline-warning:active{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:active+.btn-outline-warning:focus,.btn-check:checked+.btn-outline-warning:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus,.btn-outline-warning:active:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-check:active+.btn-outline-danger,.btn-check:checked+.btn-outline-danger,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show,.btn-outline-danger:active{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:active+.btn-outline-danger:focus,.btn-check:checked+.btn-outline-danger:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus,.btn-outline-danger:active:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:active+.btn-outline-light,.btn-check:checked+.btn-outline-light,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show,.btn-outline-light:active{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:active+.btn-outline-light:focus,.btn-check:checked+.btn-outline-light:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus,.btn-outline-light:active:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-dark{color:#212529;border-color:#212529}.btn-outline-dark:hover{color:#fff;background-color:#212529;border-color:#212529}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-check:active+.btn-outline-dark,.btn-check:checked+.btn-outline-dark,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show,.btn-outline-dark:active{color:#fff;background-color:#212529;border-color:#212529}.btn-check:active+.btn-outline-dark:focus,.btn-check:checked+.btn-outline-dark:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus,.btn-outline-dark:active:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#212529;background-color:transparent}.btn-link{font-weight:400;color:#0d6efd;text-decoration:underline}.btn-link:hover{color:#0a58ca}.btn-link.disabled,.btn-link:disabled{color:#6c757d}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropend,.dropstart,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu[style]{right:auto!important}.dropdown-menu-start{--bs-position:start;right:auto;left:0}.dropdown-menu-end{--bs-position:end;right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start;right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end;right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start;right:auto;left:0}.dropdown-menu-md-end{--bs-position:end;right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start;right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end;right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start;right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end;right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start;right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end;right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#1e2125;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#0d6efd}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#343a40;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:focus,.dropdown-menu-dark .dropdown-item:hover{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#0d6efd}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#0d6efd}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{align-items:center;width:100%}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-collapse{display:flex!important}.navbar-expand-sm .navbar-toggler{display:none}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-collapse{display:flex!important}.navbar-expand-md .navbar-toggler{display:none}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-collapse{display:flex!important}.navbar-expand-lg .navbar-toggler{display:none}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-collapse{display:flex!important}.navbar-expand-xl .navbar-toggler{display:none}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-collapse{display:flex!important}.navbar-expand-xxl .navbar-toggler{display:none}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-collapse{display:flex!important}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.55)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.55);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.55)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.55)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.55);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.55)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.5rem 1rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.5rem;margin-bottom:-.5rem;margin-left:-.5rem;border-bottom:0}.card-header-pills{margin-right:-.5rem;margin-left:-.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-group>.card{margin-bottom:.75rem}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#212529;background-color:transparent;border:1px solid rgba(0,0,0,.125);border-radius:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button.collapsed{border-bottom-width:0}.accordion-button:not(.collapsed){color:#0c63e4;background-color:#e7f1ff}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(180deg)}.accordion-button::after{flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.accordion-header{margin-bottom:0}.accordion-item:first-of-type .accordion-button{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-width:1px;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-item:last-of-type .accordion-collapse{border-bottom-width:1px;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-collapse{border:solid rgba(0,0,0,.125);border-width:0 1px}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-button{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item:first-of-type .accordion-button{border-top-width:0;border-top-left-radius:0;border-top-right-radius:0}.accordion-flush .accordion-item:last-of-type .accordion-button.collapsed{border-bottom-width:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.breadcrumb{display:flex;flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#0d6efd;text-decoration:none;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#0a58ca;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#0a58ca;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{color:#084298;background-color:#cfe2ff;border-color:#b6d4fe}.alert-primary .alert-link{color:#06357a}.alert-secondary{color:#41464b;background-color:#e2e3e5;border-color:#d3d6d8}.alert-secondary .alert-link{color:#34383c}.alert-success{color:#0f5132;background-color:#d1e7dd;border-color:#badbcc}.alert-success .alert-link{color:#0c4128}.alert-info{color:#055160;background-color:#cff4fc;border-color:#b6effb}.alert-info .alert-link{color:#04414d}.alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5}.alert-warning .alert-link{color:#523e02}.alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7}.alert-danger .alert-link{color:#6a1a21}.alert-light{color:#636464;background-color:#fefefe;border-color:#fdfdfe}.alert-light .alert-link{color:#4f5050}.alert-dark{color:#141619;background-color:#d3d3d4;border-color:#bcbebf}.alert-dark .alert-link{color:#101214}@-webkit-keyframes progress-bar-stripes{0%{background-position-x:1rem}}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#0d6efd;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;text-decoration:none;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#084298;background-color:#cfe2ff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#084298;background-color:#bacbe6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#084298;border-color:#084298}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#055160;background-color:#cff4fc}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#055160;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#055160;border-color:#055160}.list-group-item-warning{color:#664d03;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#664d03;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#664d03;border-color:#664d03}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#636464;background-color:#fefefe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#636464;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#636464;border-color:#636464}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(0,0,0,.15);border-radius:.25rem}.toast:not(.showing):not(.show){opacity:0}.toast.hide{display:none}.toast-container{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:flex;align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-header .btn-close{margin-right:-.375rem;margin-left:.75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;flex-shrink:0;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[data-popper-placement^=right],.bs-tooltip-end{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[data-popper-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[data-popper-placement^=left],.bs-tooltip-start{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[data-popper-placement^=top],.bs-popover-top{margin-bottom:.5rem!important}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[data-popper-placement^=right],.bs-popover-end{margin-left:.5rem!important}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[data-popper-placement^=bottom],.bs-popover-bottom{margin-top:.5rem!important}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f0f0f0}.bs-popover-auto[data-popper-placement^=left],.bs-popover-start{margin-right:.5rem!important}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#f0f0f0;border-bottom:1px solid #d8d8d8;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators li{background-color:#000}.carousel-dark .carousel-caption{color:#000}@-webkit-keyframes spinner-border{to{transform:rotate(360deg)}}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#0d6efd}.link-primary:focus,.link-primary:hover{color:#0a58ca}.link-secondary{color:#6c757d}.link-secondary:focus,.link-secondary:hover{color:#565e64}.link-success{color:#198754}.link-success:focus,.link-success:hover{color:#146c43}.link-info{color:#0dcaf0}.link-info:focus,.link-info:hover{color:#3dd5f3}.link-warning{color:#ffc107}.link-warning:focus,.link-warning:hover{color:#ffcd39}.link-danger{color:#dc3545}.link-danger:focus,.link-danger:hover{color:#b02a37}.link-light{color:#f8f9fa}.link-light:focus,.link-light:hover{color:#f9fafb}.link-dark{color:#212529}.link-dark:focus,.link-dark:hover{color:#1a1e21}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--aspect-ratio:100%}.ratio-4x3{--aspect-ratio:calc(3 / 4 * 100%)}.ratio-16x9{--aspect-ratio:calc(9 / 16 * 100%)}.ratio-21x9{--aspect-ratio:calc(9 / 21 * 100%)}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.visually-hidden,.visually-hidden-focusable:not(:focus){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:1px solid #dee2e6!important}.border-0{border:0!important}.border-top{border-top:1px solid #dee2e6!important}.border-top-0{border-top:0!important}.border-end{border-right:1px solid #dee2e6!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:1px solid #dee2e6!important}.border-start-0{border-left:0!important}.border-primary{border-color:#0d6efd!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#198754!important}.border-info{border-color:#0dcaf0!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#212529!important}.border-white{border-color:#fff!important}.border-0{border-width:0!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-primary{color:#0d6efd!important}.text-secondary{color:#6c757d!important}.text-success{color:#198754!important}.text-info{color:#0dcaf0!important}.text-warning{color:#ffc107!important}.text-danger{color:#dc3545!important}.text-light{color:#f8f9fa!important}.text-dark{color:#212529!important}.text-white{color:#fff!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-reset{color:inherit!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.bg-primary{background-color:#0d6efd!important}.bg-secondary{background-color:#6c757d!important}.bg-success{background-color:#198754!important}.bg-info{background-color:#0dcaf0!important}.bg-warning{background-color:#ffc107!important}.bg-danger{background-color:#dc3545!important}.bg-light{background-color:#f8f9fa!important}.bg-dark{background-color:#212529!important}.bg-body{background-color:#fff!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.bg-gradient{background-image:var(--bs-gradient)!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:.25rem!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:.2rem!important}.rounded-2{border-radius:.25rem!important}.rounded-3{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-end{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-start{border-bottom-left-radius:.25rem!important;border-top-left-radius:.25rem!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}.fs-sm-1{font-size:2.5rem!important}.fs-sm-2{font-size:2rem!important}.fs-sm-3{font-size:1.75rem!important}.fs-sm-4{font-size:1.5rem!important}.fs-md-1{font-size:2.5rem!important}.fs-md-2{font-size:2rem!important}.fs-md-3{font-size:1.75rem!important}.fs-md-4{font-size:1.5rem!important}.fs-lg-1{font-size:2.5rem!important}.fs-lg-2{font-size:2rem!important}.fs-lg-3{font-size:1.75rem!important}.fs-lg-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/uploader/static/image/facebook.png b/uploader/static/image/facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..83a05f243a422ce2a05d1f7388272fd19c68939a GIT binary patch literal 472 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf2?- zjUdc;OxLp)$dD{?jVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw{mw>;fq^m9)5S5w zqciymU+ht}6QB0|v}bnKVP6)TC5S5A`h>9C-h}tf#qhtI2Z+8K06-`Jb5Q6uc^LLtV&XCl4QmNIHqqpe#v%z^e z8Lq>rVHneJJ)A7hgPGr5jMe{nrC0=`KO{TclrdDt>El}8d3-*Z2XiATU?RZ@jiN z^NV4vl~w4vCB-m2v_X-<8E9XjzaTJBL2y#OlV<}ah4UMSx||>#W?1lMTvTKWKG23j zi>uwrY{3Tz6zCcKDs90B;8YaBuWAyEC>E4aU8+hjqIfBS;7@f4MihVY6C6~TU=b86 zyhN|ayHG1@WFE+8ZYt^~(g0tcVD}RUMiix8|Kc+UMieCjxN!wTH982$h2deuf92jumOmj+8J+0&O#qz-5;* z+iMYmbIvb22K|25zw8{aR5yVe9f0A_soUT5PuV-i5-1h(VwuO9-=4mqsm`mA4uqFS zQ|*}j--+LfEhl^R5hwN2{!mf3v<>DZ6|Eey|L2K=ZQJZP%@^}^Ic$HxDtt@2Fnld- zw>WFd+u;au9R*ODu`{<=>+8af5^R2Rc0I1#-{O7_pgwo3oI?27aAYJ4Ti)_A|L_U+xxtJzV?EoNGZaLPy4SH1pLRntR(`kX-yA}= zP2_rD+75a_$Q2<#hD2$5Om9cqi+MHI->bpb=@4}L{mmwFrGbAM&6me1C2sIC>%2>z zhR5b+8HmCRWUlqV?A-pA*#y|HX2Bvu>@)61af1PO-86w+rZi~AZP5aAgdTPb@-AqGsN58(lbcHn&TYm*yJHa(I zk+E6j`~`+tK$%${h!=z`ncoBvN3%_789>BNZbrVp!KA%StvdQO;+#r`u^(cx1XV%^ z9FB-rY!6va^PPRdP_ZZ}8@$N$`id;KkNSj|s6ioi7};)}@extG@FTtPH^XZ%IiHcXVoMOj)4=Q(=w?IXElC zRxghVw3;-U8nmG?-YSBeYH|vM=%H5=>-j-C2f`$Vk7u==dgKymuwUffVnKJOJ37<*CtxK5#Jc`G-iub_6Gk5q>oINx zDRjtIiCq{2y%TSN+Z?O+(U()a0&7lhsq7v(cFg{(nb!kYpJ?xsA4iw3v=&O!XdrD( zlIWxTeP(a9Wc(m2Qi;#UM(d60EK>Y3O@eQ%>FwxCd?`RObmBw-Tl>)4ReJ?8XLpx1 zbT@~mQz;o=xRsaWLdfq;^yc=jz#hp0e0-36@9JQTW!OVI3rBl$p9YrU0{yx5wtnA% zZ3cI1J~G+TE5UdNGO4xv+6?Iqt5Cmq#u*oUJG0sVnORgNH~hr_7q^*%+8OKcE9DN+ z4$(c=mdJvBwlcVU@YTWz>dV>$8`9{e^a3P9dr})>Gp*13hK*ru{r_f2*0m5v@KY^~ z5!R+yh86P`Sl!9Ah9p?28b*vCY=scd@H1nYh#`8Fer8-6tx_~Yt-{%NVAWAmv@NBG z{j_3=^l~BEAAV>C9Qnf`QlavugwqRb@g<6BuyHB-n1&W04;I96=@PkPNk=!S6tDuB zD7V1ohZPIku$B5KKg8zv73vlqUifpVIcU>Fy0I;F?gzPT_PKVsySL8@g6(TpZ2>L$5Lu8n4 z1wNwC8N^$mUStZH{^I@|y$c`10r6UW!>Av%(i1z|byqpz&s!M!GmO2!9LjrHLTIWr zX=-hi&P3kz(M=M%q&RCxk#dNvQG?j`=LF8K8G4VeO+_yIeyS`9jz!iNo{CN2eli&% zE+%l^2*X^ZS_c>9l6v}oi zfTqJXwH+8Jl6sNU6pYQ9ZH??E><$I4*2O5yb>RZNoJ5&@`BDM?%G&fU z!0@Yx?$r3O@_=&z1qY1cJVj>oI_h-M$=nxh2jF-KT>lCL^S88?pA1LjyH$VG6b+Z>Am;#4y=M8&Fh;Ky?5q7VEES0z-Qolm4Alhon8gft^Z8p0AN9X{LeQ9jv?aob(+!8)gkmwjPe2 zn$7_B?mYJ0axV#S@0(uOuw?}sB7=}Az~6t!+z@Y7)^7M#plUds+(kNMYX+{JlEBWhf(x zTRrl>G;2dtDomvrw&l)b(XEY82~7~P427*s_8)AjI~*j-P+k~9H>jZOibqL?c?6;K z6bV*^aY{puVdmwtT+qul)?Q8fUW#E})eBuq)>b2?kzttsJ`uX-H!N>fyjEC(Arx?U zfI*R1@TX|umpH>B2xf>Ly`&%dd}VWM+dqt!Q`sdf%&;i4o}nIZ$Nf;4?uW z8<1a=Er?-p)_~XDBaL>1`;2Yr!QX;4;e2i)jjoXH!}=c zdMp8xVHC;6FZ=ybJEA0>f|~*qq_E zBO5tl=MmMnCI2Ddw?du{#2>Y_du%~1bKJP_TUHFr~LfGKm5Z# ah~Ym42;a&Om!EwA0000-zqQY8G_>&ni6!Qt-hsx%wA>_;fewrY zQjL!yDpdzkhdK}x#RSCLk_Zh2$1Q?j!3eQnYhy&CgeZ2Ptubj36^&XGt2Ju8F`9es z-K&E(_CC&u5&Ypy{=L@s@5R~YY+)Qdtu8OLR#&T13ldaiPXAy|6nG%e2ih95@t-St z+wc1^#LFC9@=3mxz&>Cr5J+5m@MK16xdnd2VNa;*^xd}xJYE`FE-KByRIhN4fH6gk z$mUPG+fF8$CJDZze21v~;s<|=vaITfuF}tTdIk*bn6*tr52l8`ql_w9iADfG&oDE_ z{RVv%5cihP=7sBO%_C76w4!qbN>fV|*Pl?)~j)%3ZPV_xkkxcbFWUS(&3Bi2F^~HuJi^J zN<6-{>lsyC@oB4`aDWgr0y!SZHzy1kUmqKMUf_F@H40DCY+>Ge!7Bqspx0xmDB8|K zpSC+5&ttDb5pH`PQy0U5;j;FIt1D{=hsQsrVKs|J2hIwzG<^cuZUV|tz)ghLMJj0> zEvydB?`|R-_Ww79)hvGfu*nk+G2_^iMwZd9&@u+!8>yr-n)~03>M-l! zmt>6;rx!NsQsW;2&!SGUA|vbDSe{9xTyul)Rqn8#fYy{Nm$7&P4^90~<5D4}Dv)1|#>)$O2b@y)3!tAfA)w}mu`#&Gn+6b>9Xk~fv z89ZL1a_3x86fG*s#jyGvB6t@N01;Y%;a6Nr-(fAUCqn)T-?BD+$Fow{0F>5I*a?ZZ z6M?Kpw=c=DSjbKB`mj^nhI$+?#C?%(hxbY611jL+Lg%|4Oo(u$&G6NN2{8|^0k(hl z{?g8Tc_BQvc6f+OTjl??5;2Pc%CHj3_#-{kM78vwBN@_PrZoUR{&+qnPW<7B7}uv& zVWB`?PCtxRX^kF}4Vj_v_3Sgmkt9AX2gyGDcnQk#a#`T=fCg`4 z8Hve4NSL3yNOamlkwz@2%m};>s<0+;Hd>L&G_O}K$;=QhCz=41fmmXb5UXZEp*E!( zWGNR`N{j^H*-P}$%n2WHq=>)u$%w}S*G@#W{mRLc^X#V--G;ANwl zh@hPug?X4TY7&$r;0SF;=)t5XkYDHw0G|q!Gj(0oK*ECg@G>nU`J0;!W={Mh<;Nah zEdiFp!&r(>4281jYR7VdYy? z*UzV<3geh;BPgxKnJB~@1Y5O(FiXsg_)7FA^!T&zoEKGjnuH|!5}4Bjte91DRQ0O? zkkeM^WD;naKzCAu!IxuFqUa3b?dftvs$_UWmR0i`#2lEU;}Ai^{gSeuV~TX$IhZM4 zIq?(G=bv7E3XeYv6kMER@0iuP$S{J~W0CUophXE#fmH`eNT^g|xNjGICin!=EZ*Gqs1HtBWA!ZOv-q&{1|Rb?ts zP$e+iru!_g>M_Wzn~otfTv%04v%@PP{`SYeIJX1kT6ky|iuACfK~)vY7^#+YKEpJ5bhKvD}&-iR7;KT;Z5QirDTg#VP;s3u8 zRAW2-Mp2EWl7@gxvMBk=mS9P6NfM6Eofe1u%(KXeQ>fNkZ8&Ncz}$UOXN_Dkh8;h0 z2_Ul^k}Q%7B3YIXujHgUVgn5^Z3o_Yh`?Ly`RFzxu^TAu;oPcoc10iCH~o zkpOX@oEyyBsxmqxha4l5P*2YG_9s-AORfPXk&LsYm6)+t4r z{(rD-8ZhYH$?dMej4^fMZ~gj%Yl8xA7Ervc9$J2U9KVSOi&IQu*3HQq^3POa(bP8E z&rGr`#yOjtlm%%HkM9IMwQUvH(aEf+uK{4r9Om1F%)MCkBz*$PqCY;f?&VBT|Jd)p z`wC`^sj2-K!aW^4`!f8eE3|uSj@Z?aF7!cQR`6sF6@tZaWVRg~#dEnvo@!y{l+B50 zWX=BNhp#4xGVQRUl9d5CQd5GOMNp!0$Ozd~scNs>vF>aRYoF%fA{+rsh4_i^J6m_d z|9MUcZ&8irOWf{at3`*{-ShY`;OmK+klZB*G zh+RU?JLX-*s@cgU4f!w}evjs# z`O(I2y?B0837<1pLO3v6iOx17Ewu3`6R*vg}T z@SGN*9{Ljz|MBy!8-YGcT4f^_46B1{&MjGB4wev2k-dw&RpD!w1v`K}oWs?HfBbU~ z8tjE7sE6^1|K!6<*TUCwT-Hpw)xt%6TexLzQTCuK;hFkzg}Tvc>%HIztS(C|Ia*TpUgP5!=H!}IH6lwtLWn@>!k4hN@chjAhVY{yJmHn_)q;BH zjV$>TJo`Y>vmASCD-z@mm6T7{JSPX-F7K73AGO5FX|(ubbEkw)&wSkweN0?~`q&tW z_|eW&^+ZICJQ0o9T;u;g*v<8!$ij@tHr~?n8r-5uW^2s4w*!ff^4F zjPoU)-vo8#Q(jz~&s~bs+AxF*5OQTL1^%RAU(A zd;FTU$-P+22dk&P`Ev&vjD_&1+b})CN383@zQljJ{p@Ox@D@StZ=~T`KvW2t(8+yD zt~AP(w~zz8e(IY>;>STu--geZFkQm;14+KpAA34{R7528NU2G z@xc!#yLZk*gOMOA{&M(4zo>5hei$pB_l#P{e z2`U2}BWnz>{PaxsP9F{t;SS=%x&ZmXwV=UX=nSveMf|t6PsE~4EB%m!oLkO}K+>70 zozCX@TRPzSnOldGxfAJ*$&Prhhb1XLC9DrieZ(%}qfZ?=H4idz1yu(e<)(Qn(I)ZV zJXxITz?9*Lei-)fr;2{~tnRg;Li|U6eW@MNZ!O5`Jri2w9O8H@vSw&kxFI_V3tYvU z-KjQSNHHUNzYWpH!^axe52HeSETu-Q!_8RYA=m1`+M2<45Mllfw!gP<^Y<C5W^~ zqOU-Maq)Q|)xPa+RpJAD1i1#|MwdwYw62SlJ>HVmA>|>7vHJ$5gehmX-ZaGg{Yys$ zS(4|;uRi<;SjxhfA~gtrtaI;XBebRF-m`{}4e zHUhVxK4Olc1q}{D4_MMK)**bv{DbA?McjTC?R{0AZBV5}c47-;t90Z=CYYzW9@KzH zeFqxshv>}3#924cq6bsL{QSx&-jUV}JTn-9eLWXfTXk`1}A< zCb-9ZNX#thKnpA0R4saS943IabD?DWe}MX!wylqn(v$Dk0Y3tF<;L$QNU`>Q==VM! z=-0{}w!2!jaHynf8_4F)sORNNJ-!9gK@T{|(SrsDVjj7RL{pV8L-+|0(=#m}%af*TbJwmL zfbF6`S=yODF>A^1HH4oGzIB_Ox$5`~o9JA}SHe*G_iT6arVZC@SqH1oU?LPjqFeS$ z;(3y^E;)w}bL*BOw(itb`7Nl2e&gIt4wZb%-l>#>mGZU5YuP;K4Au@uYR@YJ4JJmR zdHm|oYlai^)UFM#hu@fFw&+8HiIFD0m!u7^@zuJFyd83q2N7pY{j<BSfO_d>Y=v7D5F>#On}NL zU1`|JO`59SHL54_>0f^7K&T4BgpmAoT?V)Y4JJZ-f7JsSfm^lnu5XWg*RJyiU1vY)eqkw*1|`?*2&nemOme4t(*q(j$luri-`{fP&3 z7A|oFfu~fv5Pq-0goqisaH?qcr!fX^C4R#Bdcfx7M|eH(Abg?_#^_HxjvDbaMg1=3tj&H$xb-H(@z!UGG8G*YuA|piYI#os}7H&tPB{hS2_7&H?lfff3 z5r^m5LmJRB)PShDub{zxh}}->;j=kSzeeNyUi?E`(9trU?qe~Z83ezDb;U*o2 zx8j^WH6h+?oV%~F|Kp(*KHraH28{S6;4O4%T^*E7uFzu*on=XGU()Frg87(AtSK{nX=fc)t@Iu}N&AGDe`=XJF#%Bn)UEuziC90V*P&9+A7BWz zsN%-y^y)eN3zfN=hK6t@8_<30$0 zrNbX&I`;b~;pBPjc3)Y@CW(&MX}h(R}u@lR@1AyPV z7A_Wl9;(fiUAf^0EKE#6R2Z#gOkh>~&wU{>L+K zTWdFhl!QeG=pYY1A~8b4024r_Q=Mj}(`fM0mnv=_JF$j((V^j5P-*)SCE#Z1mR4^a z*TtpZMgvR)m+72_254*C|5D<|l<%NSY9}Li@a~EM?fqK57T~gizzopY`kS9O3@|2K zwR0Lsg`Wf8rF-Uf$oe5^Yc`qpkKn3({BlL`!?!_0M69NR!=_L{>^%AH`!}d&_s^RK ziPNt`eOyTA8)eU!_&L7){QE%PmRn89_bX6KIy$^hd;yOA)0RpTkZk95eVm)SxX`>t zePoEr{vPV*G0q++`Dw49{)4o7mBYmzaOoYe9I(A=mvnGP?gtbY&$Xx=Y;OH+V+KaW z6nh<)Mv{ER)4%%VXT(JtvKjfbe_xV1I%+?^d0B!&B*=60SL;E-8GS6~f7WP$gE6IX z4xf)C`HGYO@t@K5uY=IGQsg0a_@uC79zRKHo4zlTq_g|gY_4Kg4wu3I78+1&bF!vqJQ z2lX(X+E=6@UI=$Xtk6m;kSyV&)jfO9E~?%ydDnvV0-?18iw$5ap>+btPGT>7tuOr3 zf7j*opA@7?V-qGveXNb%=xAksU8JQuH)crCcg3?V8)W^HiFC+v{X+k5u zMFz3Sq(JPJb8zb>%9Oj+-^kQUrIq>kw{lq?V3TUgs!`1|ixVM;g>#E*y!P?qJ* zaLOg8vh6As_h({f0w|Gy^Tak{q^kb2WTunm^RY$&GzJ6qD};#VT*^1G86w**zDD>{ z>g1Bltj=k*|HJt+RsTirNfDhY_su6X>;!GrAe`#W{}Rh>r4sux_uq1VUQP*gP|as^6}O58y!5N0+gH>66UTCOEC zl2=X3kaOzl7tRE@|1sF0-yHwqf4WcuM@I5J&ivb*PI#E-!++dQE2ta_Nm!+#SYQAx z0XV@WFE!$H@fKM_nq1DU2EZLgns}DsCYoZlqxp}HNl>MsgHm&`f_c@wX8={9=mp85 zEd4x)yk(quU-=)}zwvDZZjVj}ppI zQS8;ZgVY>5|Im#puziRe3#k>-w};wgQl_$EdI+p?rFX3!hmD73#dJNX)PQo@fD}L zx7VN3_WAH=R)MMPhWa`6PA-HqP49+`A(%-`QcGEnYbyb;A}2ey9H@*@DK96ca<;}U zLu6;Ob7_PLq}R85Hf!NjfP?8ay-E2W2T=ZWCEp`9gr555P6r2b?*?N2K|Sbf6Imwh zxg+MaBnmn`|58l3Qz4*YhTuDjOgUG4hD;;ys@>I|EV6f|!oOfJn=6hUMBpKQn?n-ZG&{0HeiFxPJk04ue(ndJTnQ_QN zS2A#ztiq2(rXhBjn^|FI#8)IH_?K^27M`CvUt;lTcvL-Pa{CNkw&Qux5!pF#LM34z zaT2K#>rrMUWgC|+E^IK0`3Srpf^*)|H-ev%R8@#^1gayW$d8`HM@U|!sTq@e%4O-aH`?XR zvCFF79|_fa!m2{ZZozDEBslP8pyl@BqtkQkV~7_@j6;nmb)fhXaoQ2pmosMIb*9^@ z1tF;n`b?Z?^*jO@To-cMD(9lSkJ%;-OT|^dN|T$rFOd6=-zDMC7QXnd2a`UVni;+$ zBl-IQyQu)ul~2N>m3F&;xy3+>3j}2gQzIj`AXXJw*uV!7s@lsevhhbM2B}Gq0)a`X zI|FBWbz*YK8(2hR@a>I(?9Z(KMA(}uH71G#}hC`JbU>$Pwcho i#KSt(J*qkP?*9YUV3It-Fa;g}00005P)xK~zYIwU*6GR8bhlf6tj~yzb zL92qI+7=YFi53wpiV6aC1|kvK)S{qWpin^{6cvRVp(1Cjbnbmxj1x9Z&S3eh?m6#y zf6sY&&%Ni$HjAmSsB|D&XkydgnF?0#u+J0EdW^PyF8kk&(lUTNia)sVl(WnnB zeOnJKP?RfPFdQilf71x|4HOPpUYE4BY$+S$izArLu}iz0ZGAJJK`LK3EbDTeeN0I1 zR}v=6Juo|fj+CNDQGTlDue(1@kaezJm6$18w?y)-Y#?6EhE`z@N4esF2ETPw=Pg-R z=mM74H4v@A+WjM&c@_X<9#k#qPle=NlrP?ma)n;y3vB>N(CWHyKyYn3n;wPPQ&ej5 zg=kv)EY{9h7ckwR?vx?Q6+aoqtGilD3I26h0zhg;SB>ri@jQ7e1RENuAS52EJVyW) zYlQbSlH7ojQtJB?SXMRzkag)l!4bUnfwn?r9020J^mWY8|1dB-o;wb+la8}32Q7{Y zUj74rCbrN1VF19LFRe0%jM^7Um$~R{=6Ov6?_K@{>l`?m0sOr5Eo{OxmH%BF`c zj$z&}z~K1Y=2oOy7mh%wp~8Non?Q4Ywy%`>GKXtL{ + + + + + + Home | Image Uploader + + + + + + + + + + + + + + + +
+

Image Uploader

+ +
+
+ {% if messages %} + {% for message in messages %} +
{{message}}
+ {% endfor %} + {% endif %} + +
+
+
+ {% for image in images %} +
+
+ + ... + +
+ +
+ + {{image.user}} + +
+
+ {% csrf_token %} + +
+ + +
+ {% endfor %} +
+
+ {% if page_obj.has_previous %} + previous + {% endif %} + + {{page_obj.number}} + + {% if page_obj.has_next %} + next + {% endif %} +
+
+ + + \ No newline at end of file diff --git a/uploader/templates/login.html b/uploader/templates/login.html new file mode 100644 index 0000000..8a93ab4 --- /dev/null +++ b/uploader/templates/login.html @@ -0,0 +1,72 @@ +{% load static %} +{% load socialaccount %} +{% providers_media_js %} + + + + + + + Login | Image Uploader + + + + + + + + + + +
+

Image Uploader

+ +
+
+

Login Form


+
+ {% csrf_token %} + {% for fm in form %} + {{fm.errors}} + {{fm.label}} {{fm}}

+ {% endfor %} + +

+ Need an account Signup
+ {% comment %} Reset + password {% endcomment %} +
+ +
+ + google   + Login with Google +

+ + {% comment %} facebook   Login with Facebook + {% endcomment %} + + github   Login with Github +
+ + + \ No newline at end of file diff --git a/uploader/templates/logout.html b/uploader/templates/logout.html new file mode 100644 index 0000000..88e68bb --- /dev/null +++ b/uploader/templates/logout.html @@ -0,0 +1,32 @@ +{% load static %} + + + + + + + Home | Image Uploader + + + + + + + + + + +
+ You are successfully Logout +
+ + + \ No newline at end of file diff --git a/uploader/templates/profile.html b/uploader/templates/profile.html new file mode 100644 index 0000000..42f7f04 --- /dev/null +++ b/uploader/templates/profile.html @@ -0,0 +1,80 @@ +{% load static %} + + + + + + + profile | Image Uploader + + + + + + + + + + + +
+

Image Uploader

+ +
+ + + + {% if messages%} + {% for message in messages %} +
+ {{message}} +
+ {%endfor%} + {%endif%} + + + + + \ No newline at end of file diff --git a/uploader/templates/signup.html b/uploader/templates/signup.html new file mode 100644 index 0000000..d356459 --- /dev/null +++ b/uploader/templates/signup.html @@ -0,0 +1,63 @@ +{% load static %} + + + + + + + Signup | Image Uploader + + + + + + + + + +
+

Image Uploader

+ +
+ + + + + + + \ No newline at end of file diff --git a/uploader/templates/uploader.html b/uploader/templates/uploader.html new file mode 100644 index 0000000..9c0207d --- /dev/null +++ b/uploader/templates/uploader.html @@ -0,0 +1,203 @@ +{% load static %} + + + + + + + Home | Image Uploader + + + + + + + + + + + + + + + +
+

Image Uploader

+ +
+
+ {% if messages %} + {% for message in messages %} +
{{message}}
+ {% endfor %} + {% endif %} +
+

Submit a Photo

+
+
+ {% csrf_token %} +
+ +
+ +
+ + {% if user.is_authenticated %} + + {% else %} + Submit Photo + {% endif %} +
+
+
+
+
+ {% for image in images %} +
+
+ + ... + +
+ +
+ + {{image.user}} + +
+
+ {% csrf_token %} + +
+ + +
+ {% endfor %} +
+
+
+ +

{{ comments.count }} comments

+ {% for comment in comments %} +
+

+ {{ comment.user }} + + {{ comment.commented_at }} + +

+ {{ comment.email | linebreaks }} + {{ comment.text | linebreaks }} +
+ {% endfor %} +
+
+
+ {% if new_comment %} + + {% else %} +

Leave a comment

+
+ {{ comment_form.as_p }} + {% csrf_token %} + +
+ {% endif %} +
+
+ {% if page_obj.has_previous %} + previous + {% endif %} + + {{page_obj.number}} + + {% if page_obj.has_next %} + next + {% endif %} +
+
+ + + \ No newline at end of file diff --git a/uploader/templates/user-profile.html b/uploader/templates/user-profile.html new file mode 100644 index 0000000..7db6f3f --- /dev/null +++ b/uploader/templates/user-profile.html @@ -0,0 +1,153 @@ +{% load static %} + + + + + + + profile | Image Uploader + + + + + + + + + + + +
+

Image Uploader

+ +
+ + + + + +
+ +

Profile

+

+
+
+ +
+ +
+

@{{user.username}}


+
{{user.email}}
+ +
{{user.first_name}} {{user.last_name}}
+ +
+
+ +
+ + +
+ +
+
+ +
+ {% for images in image %} +
+ + ... + +
+ + + + + + + + + + {%endfor%} +
+ + +
+ +
+
+ + + + \ No newline at end of file diff --git a/uploader/tests.py b/uploader/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/uploader/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/uploader/urls.py b/uploader/urls.py new file mode 100644 index 0000000..f192d68 --- /dev/null +++ b/uploader/urls.py @@ -0,0 +1,15 @@ +from django.urls import path +from .views import * +from django.contrib.auth import views as authviews + +urlpatterns = [ + path('', index, name='home'), + path('uploader/', image_uploader, name='imageuploader'), + path('signup/', signup, name='signup'), + path('login/', login, name='login'), + path('logout/', authviews.LogoutView.as_view(template_name='logout.html'), name='logout'), + path('profile/', profile_update, name='profile-update'), + path('profile//', user_profile, name='user-profile'), + path('like//', image_like, name='image-like'), + path('/', image_detail, name='image-comment'), +] diff --git a/uploader/views.py b/uploader/views.py new file mode 100644 index 0000000..270bcd8 --- /dev/null +++ b/uploader/views.py @@ -0,0 +1,139 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from .forms import CommentForm, SignupForm, UpdateUserForm, ProfileUpdateForm +from .models import Uploader +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.auth import authenticate +from django.contrib.auth import login as auth_login +from django.contrib.auth.models import User +from django.contrib.auth.forms import AuthenticationForm +from django.core.paginator import Paginator + +# Create your views here. + + +def index(request): + images = Uploader.objects.all().order_by('-created_at')[:9] + paginator = Paginator(images, 10) + page_number = request.GET.get('page') + page_obj = paginator.get_page(page_number) + + return render(request, 'index.html', {'images': images, 'page_obj': page_obj}) + + +@login_required(login_url='login') +def image_uploader(request): + if request.method == 'POST' and 'upload' in request.POST: + name = 'name' in request.POST and request.POST['name'] + image = 'image' in request.FILES and request.FILES['image'] + profile = 'profile' in request.POST and request.POST['profile'] + + uploader = Uploader(user=request.user, name=name, + image=image, profile=profile) + uploader.save() + messages.success(request, 'Your Image Uploaded Successfully!!') + + images = Uploader.objects.all().order_by('-created_at')[:9] + paginator = Paginator(images, 10) + page_number = request.GET.get('page') + page_obj = paginator.get_page(page_number) + + return render(request, 'uploader.html', + {'images': images, 'page_obj': page_obj}) + + +login_required(login_url='login') +def image_like(request, pk): + uploader = Uploader.objects.get(pk=pk) + uploader.like += 1 + uploader.save() + return redirect('/') + + +@login_required(login_url='login') +def image_detail(request, pk): + image = get_object_or_404(Uploader, pk=pk) + comments = image.comments.filter(active=True) + new_comment = None + if request.method == 'POST': + comment_form = CommentForm(data=request.POST) + if comment_form.is_valid(): + new_comment = comment_form.save(commit=False) + new_comment.image = image + new_comment.save() + else: + comment_form = CommentForm() + + return render(request, 'uploader.html', + {'image': image, 'comments': comments, + 'new_comment': new_comment, 'comment_form': comment_form}) + + +def signup(request): + if request.method == 'POST': + fm = SignupForm(request.POST) + if fm.is_valid(): + user = fm.save() + user.refresh_from_db() + user.profile.first_name = fm.cleaned_data.get('first_name') + user.profile.last_name = fm.cleaned_data.get('last_name') + user.profile.email = fm.cleaned_data.get('email') + user.save() + username = fm.cleaned_data.get('username') + password = fm.cleaned_data.get('password1') + user = authenticate(request, username=username, password=password) + if user is not None: + auth_login(request, user) + messages.success(request, 'Sign up Done, You are logged in!!') + return redirect('/') + else: + fm = SignupForm() + + return render(request, 'signup.html', {'fm': fm}) + + +def login(request): + if request.method == 'POST': + form = AuthenticationForm(request.POST) + username = request.POST['username'] + password = request.POST['password'] + user = authenticate(request, username=username, password=password) + if user is not None: + auth_login(request, user) + messages.success(request, f'Welcome back {request.user} !') + return redirect('/') + else: + messages.info(request, 'Account does not exist, plz sign up!!') + else: + form = AuthenticationForm() + + return render(request, 'login.html', {'form': form}) + + +@login_required(login_url='login') +def profile_update(request): + if request.method == 'POST': + uu_form = UpdateUserForm(instance=request.user, + data=request.POST) + pu_form = ProfileUpdateForm(request.POST, + request.FILES, + instance=request.user.profile) + if uu_form.is_valid() and pu_form.is_valid(): + uu_form.save() + pu_form.save() + messages.success(request, 'Your Profile has been updated!') + else: + uu_form = UpdateUserForm(instance=request.user) + pu_form = ProfileUpdateForm(instance=request.user.profile) + + return render(request, 'profile.html', + {'uu_form': uu_form, 'pu_form': pu_form}) + + +@login_required(login_url='login') +def user_profile(request, user): + usr = User.objects.get(username=user) + prof_img = Uploader.objects.filter(user=user) + + return render(request, 'user-profile.html', + {'user': usr, 'prof_img': prof_img})