summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.pre-commit-config.yaml37
-rw-r--r--core/__init__.py0
-rw-r--r--core/apps.py6
-rw-r--r--core/config.py3
-rw-r--r--core/context.py5
-rw-r--r--core/forms.py11
-rw-r--r--core/views.py21
-rwxr-xr-xmanage.py22
-rw-r--r--requirements.txt6
-rw-r--r--static/css/style.css227
-rwxr-xr-xstatic/fonts/font_awesome/all.min.css6
-rwxr-xr-xstatic/fonts/font_awesome/fa-brands-400.ttfbin0 -> 186112 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-brands-400.woff2bin0 -> 107460 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-regular-400.ttfbin0 -> 62048 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-regular-400.woff2bin0 -> 25096 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-solid-900.ttfbin0 -> 397728 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-solid-900.woff2bin0 -> 150472 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-v4compatibility.ttfbin0 -> 10136 bytes
-rwxr-xr-xstatic/fonts/font_awesome/fa-v4compatibility.woff2bin0 -> 4584 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Black.woff2bin0 -> 63264 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-BlackItalic.woff2bin0 -> 66764 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Bold.woff2bin0 -> 67288 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-BoldItalic.woff2bin0 -> 69856 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-ExtraBold.woff2bin0 -> 66792 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-ExtraBoldItalic.woff2bin0 -> 70056 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-ExtraLight.woff2bin0 -> 63952 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-ExtraLightItalic.woff2bin0 -> 66368 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Italic.woff2bin0 -> 66968 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Light.woff2bin0 -> 64292 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-LightItalic.woff2bin0 -> 66908 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Medium.woff2bin0 -> 63328 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-MediumItalic.woff2bin0 -> 65264 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Regular.woff2bin0 -> 64764 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-SemiBold.woff2bin0 -> 67308 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-SemiBoldItalic.woff2bin0 -> 69716 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-Thin.woff2bin0 -> 59852 bytes
-rwxr-xr-xstatic/fonts/raleway/Raleway-ThinItalic.woff2bin0 -> 63072 bytes
-rw-r--r--static/fonts/raleway/raleway.css20
-rw-r--r--statuses/__init__.py0
-rw-r--r--statuses/admin.py8
-rw-r--r--statuses/apps.py6
-rw-r--r--statuses/migrations/0001_initial.py56
-rw-r--r--statuses/migrations/__init__.py0
-rw-r--r--statuses/models/__init__.py1
-rw-r--r--statuses/models/status.py35
-rw-r--r--statuses/views/__init__.py0
-rw-r--r--statuses/views/home.py35
-rw-r--r--takahe/__init__.py0
-rw-r--r--takahe/asgi.py16
-rw-r--r--takahe/settings.py115
-rw-r--r--takahe/urls.py22
-rw-r--r--takahe/wsgi.py16
-rw-r--r--templates/404.html6
-rw-r--r--templates/auth/login.html11
-rw-r--r--templates/base.html34
-rw-r--r--templates/identity/create.html12
-rw-r--r--templates/identity/select.html17
-rw-r--r--templates/identity/view.html13
-rw-r--r--templates/index.html9
-rw-r--r--templates/statuses/_status.html10
-rw-r--r--templates/statuses/home.html15
-rw-r--r--users/__init__.py0
-rw-r--r--users/admin.py18
-rw-r--r--users/apps.py6
-rw-r--r--users/decorators.py39
-rw-r--r--users/migrations/0001_initial.py134
-rw-r--r--users/migrations/__init__.py0
-rw-r--r--users/models/__init__.py3
-rw-r--r--users/models/identity.py79
-rw-r--r--users/models/user.py58
-rw-r--r--users/models/user_event.py22
-rw-r--r--users/shortcuts.py18
-rw-r--r--users/views/__init__.py1
-rw-r--r--users/views/auth.py15
-rw-r--r--users/views/identity.py132
76 files changed, 1328 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b7d269c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.psql
+*.sqlite3
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..9fa3f15
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,37 @@
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v3.3.0
+ hooks:
+ - id: check-case-conflict
+ - id: check-merge-conflict
+ - id: check-yaml
+ - id: end-of-file-fixer
+ - id: file-contents-sorter
+ args: ["--ignore-case"]
+ files: "^.gitignore$"
+ - id: mixed-line-ending
+ args: ["--fix=lf"]
+ - id: trailing-whitespace
+ - id: pretty-format-json
+
+ - repo: https://github.com/psf/black
+ rev: 22.10.0
+ hooks:
+ - id: black
+ args: ["--target-version=py37"]
+
+ - repo: https://github.com/pycqa/isort
+ rev: 5.10.1
+ hooks:
+ - id: isort
+ args: ["--profile=black"]
+
+ - repo: https://gitlab.com/pycqa/flake8
+ rev: 5.0.4
+ hooks:
+ - id: flake8
+
+ - repo: https://github.com/pre-commit/mirrors-mypy
+ rev: v0.982
+ hooks:
+ - id: mypy
diff --git a/core/__init__.py b/core/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/__init__.py
diff --git a/core/apps.py b/core/apps.py
new file mode 100644
index 0000000..c0ce093
--- /dev/null
+++ b/core/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class CoreConfig(AppConfig):
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "core"
diff --git a/core/config.py b/core/config.py
new file mode 100644
index 0000000..0f09404
--- /dev/null
+++ b/core/config.py
@@ -0,0 +1,3 @@
+class Config:
+
+ pass
diff --git a/core/context.py b/core/context.py
new file mode 100644
index 0000000..38a268c
--- /dev/null
+++ b/core/context.py
@@ -0,0 +1,5 @@
+from django.conf import settings
+
+
+def config_context(request):
+ return {"config": {"site_name": settings.SITE_NAME}}
diff --git a/core/forms.py b/core/forms.py
new file mode 100644
index 0000000..8a4801d
--- /dev/null
+++ b/core/forms.py
@@ -0,0 +1,11 @@
+from crispy_forms.helper import FormHelper as BaseFormHelper
+from crispy_forms.layout import Submit
+
+
+class FormHelper(BaseFormHelper):
+
+ submit_text = "Submit"
+
+ def __init__(self, form=None, submit_text=None):
+ super().__init__(form)
+ self.add_input(Submit("submit", submit_text or "Submit"))
diff --git a/core/views.py b/core/views.py
new file mode 100644
index 0000000..dbaebf9
--- /dev/null
+++ b/core/views.py
@@ -0,0 +1,21 @@
+from django.views.generic import TemplateView
+
+from statuses.views.home import Home
+from users.models import Identity
+
+
+def homepage(request):
+ if request.user.is_authenticated:
+ return Home.as_view()(request)
+ else:
+ return LoggedOutHomepage.as_view()(request)
+
+
+class LoggedOutHomepage(TemplateView):
+
+ template_name = "index.html"
+
+ def get_context_data(self):
+ return {
+ "identities": Identity.objects.filter(local=True),
+ }
diff --git a/manage.py b/manage.py
new file mode 100755
index 0000000..21eb71e
--- /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", "takahe.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/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..2d44983
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+django~=4.1
+pyld~=2.0.3
+pillow~=9.3.0
+urlman~=2.0.1
+django-crispy-forms~=1.14
+cryptography~=38.0
diff --git a/static/css/style.css b/static/css/style.css
new file mode 100644
index 0000000..6876156
--- /dev/null
+++ b/static/css/style.css
@@ -0,0 +1,227 @@
+/* Reset CSS */
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+body,
+h1,
+h2,
+h3,
+h4,
+p,
+figure,
+blockquote,
+dl,
+dd,
+menu {
+ margin: 0;
+}
+
+ul[role='list'],
+ol[role='list'] {
+ list-style: none;
+}
+
+html:focus-within {
+ scroll-behavior: smooth;
+}
+
+body {
+ min-height: 100vh;
+ text-rendering: optimizeSpeed;
+ line-height: 1.5;
+ font-family: sans-serif;
+}
+
+a:not([class]) {
+ text-decoration-skip-ink: auto;
+}
+
+img,
+picture {
+ max-width: 100%;
+ display: block;
+}
+
+input,
+button,
+textarea,
+select {
+ font: inherit;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ html:focus-within {
+ scroll-behavior: auto;
+ }
+
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
+
+/* Base template styling */
+
+:root {
+ --color-input-border: #000;
+ --color-input-border-active: #444b5d;
+ --color-button-main: #444b5d;
+ --color-button-main-hover: #515d7c;
+ --color-bg1: #191b22;
+ --color-bg2: #282c37;
+ --color-bg3: #444b5d;
+ --color-text-duller: #5f6983;
+ --color-text-dull: #99a;
+ --color-text-error: rgb(155, 111, 111);
+ --color-text-main: #DDDDDD;
+}
+
+body {
+ background-color: var(--color-bg1);
+ color: white;
+}
+
+header {
+ width: 750px;
+ margin: 0 auto;
+ display: flex;
+ padding: 0 0 20px 0;
+}
+
+header h1 {
+ background: var(--color-fg2);
+ padding: 10px 7px 7px 7px;
+ font-size: 130%;
+ height: 2.2em;
+ color: var(--color-fg1);
+}
+
+header a {
+ color: inherit;
+ text-decoration: none;
+}
+
+header menu {
+ flex-grow: 1;
+ display: flex;
+ list-style-type: none;
+ justify-content: flex-end;
+}
+
+header menu li {
+ padding: 20px 10px 7px 10px;
+ color: #eee;
+}
+
+main {
+ width: 750px;
+ margin: 20px auto;
+}
+
+/* "Modal" boxes */
+
+.modal {
+ background: var(--color-bg2);
+ max-width: 500px;
+ margin: 0 auto;
+ box-shadow: 0 0 30px rgba(0, 0, 0, 0.3);
+ border-radius: 5px;
+}
+
+.modal h1 {
+ color: var(--color-fg1);
+ background: var(--color-bg3);
+ font-family: "Raleway";
+ position: relative;
+ padding: 5px 8px 4px 10px;
+ font-size: 100%;
+ letter-spacing: 0.05em;
+ text-transform: uppercase;
+ border-radius: 5px 5px 0 0;
+}
+
+.modal .option {
+ display: block;
+ padding: 20px 30px;
+ color: var(--color-text-main);
+ text-decoration: none;
+ border-left: 3px solid transparent;
+}
+
+.modal a.option:hover {
+ border-left: 3px solid var(--color-text-dull);
+}
+
+.modal .option.empty {
+ text-align: center;
+ color: var(--color-text-dull);
+}
+
+.modal form {
+ padding: 10px 10px 1px 10px;
+}
+
+/* Forms */
+
+form .control-group {
+ margin: 0 0 15px 0;
+}
+
+form .asteriskField {
+ display: none;
+}
+
+form label {
+ text-transform: uppercase;
+ font-size: 110%;
+ color: var(--color-text-dull);
+ letter-spacing: 0.05em;
+}
+
+form label.requiredField::after {
+ content: " (required)";
+ font-size: 80%;
+ color: var(--color-text-duller);
+}
+
+form .help-block {
+ color: var(--color-text-error);
+ padding: 4px 0 0 0;
+}
+
+form input {
+ width: 100%;
+ padding: 4px 6px;
+ background: var(--color-bg1);
+ border: 1px solid var(--color-input-border);
+ border-radius: 3px;
+ color: var(--color-text-main);
+}
+
+form input:focus {
+ outline: none;
+ border: 1px solid var(--color-input-border-active);
+}
+
+form input[type=submit] {
+ width: 100%;
+ padding: 4px 6px;
+ margin: 0 0 10px;
+ background: var(--color-button-main);
+ border: 0;
+ border-radius: 3px;
+ color: var(--color-text-main);
+ cursor: pointer;
+}
+
+form input[type=submit]:hover {
+ background: var(--color-button-main-hover);
+}
diff --git a/static/fonts/font_awesome/all.min.css b/static/fonts/font_awesome/all.min.css
new file mode 100755
index 0000000..2cae607
--- /dev/null
+++ b/static/fonts/font_awesome/all.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
+ * Copyright 2022 Fonticons, Inc.
+ */
+.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-classic,.fa-regular,.fa-sharp,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,none));transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)}.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{