commit 76f98b74ddea6dcf6f71d0329eedc2c9fff99aa2 Author: Eliot Berriot Date: Fri Jun 23 23:00:42 2017 +0200 Initial commit that merge both the front end and the API in the same repository diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..7a1408eda --- /dev/null +++ b/.dockerignore @@ -0,0 +1,69 @@ +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Basics +*.py[cod] +__pycache__ + +# Logs +*.log +api/pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml +htmlcov + +# Translations +*.mo +*.pot + +# Pycharm +.idea + +# Vim + +*~ +*.swp +*.swo + +# npm +front/node_modules/ + +# Compass +.sass-cache + +# virtual environments +.env + +# User-uploaded media +api/funkwhale_api/media/ + +# Hitch directory +api/tests/.hitch + +# MailHog binary +mailhog + +*.sqlite3 +api/music +api/media diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..f1b072246 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,rst,ini}] +indent_style = space +indent_size = 4 + +[*.py] +line_length=120 +known_first_party=funkwhale_api +multi_line_output=3 +default_section=THIRDPARTY + +[*.{html,js,vue,css,scss,json,yml}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.env.dev b/.env.dev new file mode 100644 index 000000000..75954b6bc --- /dev/null +++ b/.env.dev @@ -0,0 +1,3 @@ +BACKEND_URL=http://localhost:6001 +YOUTUBE_API_KEY= +API_AUTHENTICATION_REQUIRED=False diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..176a458f9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..3ca72845e --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Basics +*.py[cod] +__pycache__ + +# Logs +*.log +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml +htmlcov + +# Translations +*.mo +*.pot + +# Pycharm +.idea + +# Vim + +*~ +*.swp +*.swo + +# npm +front/node_modules/ + +# Compass +.sass-cache + +# virtual environments +.env + +# User-uploaded media +api/funkwhale_api/media/ + +# Hitch directory +tests/.hitch + +# MailHog binary +mailhog + +*.sqlite3 + +# Api +api/music +api/media +api/staticfiles +api/static + + +# Front +front/node_modules/ +front/dist/ +front/npm-debug.log* +front/yarn-debug.log* +front/yarn-error.log* +front/test/unit/coverage +front/test/e2e/reports +front/selenium-debug.log diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..a63410119 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,22 @@ +image: docker:latest + +# When using dind, it's wise to use the overlayfs driver for +# improved performance. +# variables: +# DOCKER_DRIVER: overlay +# +# services: +# - docker:dind +# +# +# # build: +# # stage: build +# # script: +# # - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" +# # - docker build -t funkwhale/front . +# # - docker push +# # +# # tags: +# # - dind +# # only: +# # - master diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt new file mode 100644 index 000000000..63e6c9864 --- /dev/null +++ b/CONTRIBUTORS.txt @@ -0,0 +1 @@ +Eliot Berriot diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..e30bee823 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Eliot Berriot +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +* Neither the name of funkwhale_api nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.rst b/README.rst new file mode 100644 index 000000000..1cec0a6b7 --- /dev/null +++ b/README.rst @@ -0,0 +1,50 @@ +Funkwhale +============= + +A self-hosted tribute to Grooveshark.com. + +LICENSE: BSD + +Setting up a development environment (docker) +---------------------------------------------- + +First of all, pull the repository. + +Then, pull and build all the containers:: + + docker-compose -f dev.yml build + docker-compose -f dev.yml pull + + +API setup +^^^^^^^^^^ + +You'll have apply database migrations:: + + docker-compose -f dev.yml run celeryworker python manage.py migrate + +And to create an admin user:: + + docker-compose -f dev.yml run celeryworker python manage.py createsuperuser + + +Launch all services +^^^^^^^^^^^^^^^^^^^ + +Then you can run everything with:: + + docker-compose up + +The API server will be accessible at http://localhost:6001, and the front-end at http://localhost:8080. + +Running API tests +------------------ + +Everything is managed using docker and docker-compose, just run:: + + ./api/runtests + +This bash script invoke `python manage.py test` in a docker container under the hood, so you can use +traditional django test arguments and options, such as:: + + ./api/runtests funkwhale_api.music # run a specific app test diff --git a/api/.coveragerc b/api/.coveragerc new file mode 100644 index 000000000..4e3cf2bad --- /dev/null +++ b/api/.coveragerc @@ -0,0 +1,5 @@ +[run] +include = funkwhale_api/* +omit = *migrations*, *tests* +plugins = + django_coverage_plugin diff --git a/api/.pylintrc b/api/.pylintrc new file mode 100644 index 000000000..2117a3951 --- /dev/null +++ b/api/.pylintrc @@ -0,0 +1,11 @@ +[MASTER] +load-plugins=pylint_common, pylint_django, pylint_celery + +[FORMAT] +max-line-length=120 + +[MESSAGES CONTROL] +disable=missing-docstring,invalid-name + +[DESIGN] +max-parents=13 \ No newline at end of file diff --git a/api/Dockerfile b/api/Dockerfile new file mode 100644 index 000000000..bb1942c22 --- /dev/null +++ b/api/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.5 + +ENV PYTHONUNBUFFERED 1 + +# Requirements have to be pulled and installed here, otherwise caching won't work + +COPY ./requirements.apt /requirements.apt +RUN apt-get update -qq && grep "^[^#;]" requirements.apt | xargs apt-get install -y + + +COPY ./requirements /requirements +RUN pip install -r /requirements/production.txt + +COPY . /app + +# Since youtube-dl code is updated fairly often, we split it here +RUN pip install --upgrade youtube-dl + +WORKDIR /app + +ENTRYPOINT ["./compose/django/entrypoint.sh"] diff --git a/api/compose/django/entrypoint.sh b/api/compose/django/entrypoint.sh new file mode 100755 index 000000000..a4060f658 --- /dev/null +++ b/api/compose/django/entrypoint.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e +# This entrypoint is used to play nicely with the current cookiecutter configuration. +# Since docker-compose relies heavily on environment variables itself for configuration, we'd have to define multiple +# environment variables just to support cookiecutter out of the box. That makes no sense, so this little entrypoint +# does all this for us. +export REDIS_URL=redis://redis:6379/0 + +# the official postgres image uses 'postgres' as default user if not set explictly. +if [ -z "$POSTGRES_ENV_POSTGRES_USER" ]; then + export POSTGRES_ENV_POSTGRES_USER=postgres +fi + +export DATABASE_URL=postgres://$POSTGRES_ENV_POSTGRES_USER:$POSTGRES_ENV_POSTGRES_PASSWORD@postgres:5432/$POSTGRES_ENV_POSTGRES_USER + +export CELERY_BROKER_URL=$REDIS_URL + +exec "$@" \ No newline at end of file diff --git a/api/compose/django/gunicorn.sh b/api/compose/django/gunicorn.sh new file mode 100755 index 000000000..014f173e3 --- /dev/null +++ b/api/compose/django/gunicorn.sh @@ -0,0 +1,3 @@ +#!/bin/sh +python /app/manage.py collectstatic --noinput +/usr/local/bin/gunicorn config.wsgi -w 4 -b 0.0.0.0:5000 --chdir=/app \ No newline at end of file diff --git a/api/compose/nginx/Dockerfile b/api/compose/nginx/Dockerfile new file mode 100644 index 000000000..196395763 --- /dev/null +++ b/api/compose/nginx/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx:latest +ADD nginx.conf /etc/nginx/nginx.conf \ No newline at end of file diff --git a/api/compose/nginx/nginx.conf b/api/compose/nginx/nginx.conf new file mode 100644 index 000000000..331d8d45f --- /dev/null +++ b/api/compose/nginx/nginx.conf @@ -0,0 +1,53 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + upstream app { + server django:12081; + } + + server { + listen 80; + charset utf-8; + + root /staticfiles; + location / { + # checks for static file, if not found proxy to app + try_files $uri @proxy_to_app; + } + + location @proxy_to_app { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_redirect off; + + proxy_pass http://app; + } + + } +} diff --git a/api/config/__init__.py b/api/config/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/config/api_urls.py b/api/config/api_urls.py new file mode 100644 index 000000000..4ed81d284 --- /dev/null +++ b/api/config/api_urls.py @@ -0,0 +1,26 @@ +from rest_framework import routers +from django.conf.urls import include, url +from funkwhale_api.music import views +from funkwhale_api.playlists import views as playlists_views + +router = routers.SimpleRouter() +router.register(r'tags', views.TagViewSet, 'tags') +router.register(r'tracks', views.TrackViewSet, 'tracks') +router.register(r'artists', views.ArtistViewSet, 'artists') +router.register(r'albums', views.AlbumViewSet, 'albums') +router.register(r'import-batches', views.ImportBatchViewSet, 'import-batches') +router.register(r'submit', views.SubmitViewSet, 'submit') +router.register(r'playlists', playlists_views.PlaylistViewSet, 'playlists') +router.register(r'playlist-tracks', playlists_views.PlaylistTrackViewSet, 'playlist-tracks') +urlpatterns = router.urls + +urlpatterns += [ + url(r'^providers/', include('funkwhale_api.providers.urls', namespace='providers')), + url(r'^favorites/', include('funkwhale_api.favorites.urls', namespace='favorites')), + url(r'^search$', views.Search.as_view(), name='search'), + url(r'^radios/', include('funkwhale_api.radios.urls', namespace='radios')), + url(r'^history/', include('funkwhale_api.history.urls', namespace='history')), + url(r'^users/', include('funkwhale_api.users.api_urls', namespace='users')), + url(r'^token/', 'rest_framework_jwt.views.obtain_jwt_token'), + url(r'^token/refresh/', 'rest_framework_jwt.views.refresh_jwt_token'), +] diff --git a/api/config/settings/__init__.py b/api/config/settings/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/api/config/settings/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/api/config/settings/common.py b/api/config/settings/common.py new file mode 100644 index 000000000..5c55dfdc1 --- /dev/null +++ b/api/config/settings/common.py @@ -0,0 +1,307 @@ +# -*- coding: utf-8 -*- +""" +Django settings for funkwhale_api project. + +For more information on this file, see +https://docs.djangoproject.com/en/dev/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/dev/ref/settings/ +""" +from __future__ import absolute_import, unicode_literals + +import os +import environ + +ROOT_DIR = environ.Path(__file__) - 3 # (/a/b/myfile.py - 3 = /) +APPS_DIR = ROOT_DIR.path('funkwhale_api') + +env = environ.Env() + +try: + env.read_env(ROOT_DIR.file('.env')) +except FileNotFoundError: + pass +# APP CONFIGURATION +# ------------------------------------------------------------------------------ +DJANGO_APPS = ( + # Default Django apps: + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + # Useful template tags: + # 'django.contrib.humanize', + + # Admin + 'django.contrib.admin', +) +THIRD_PARTY_APPS = ( + # 'crispy_forms', # Form layouts + 'allauth', # registration + 'allauth.account', # registration + 'allauth.socialaccount', # registration + 'corsheaders', + 'rest_framework', + 'rest_framework.authtoken', + 'djcelery', + 'taggit', + 'cachalot', + 'rest_auth', + 'rest_auth.registration', + 'mptt', +) + +# Apps specific for this project go here. +LOCAL_APPS = ( + 'funkwhale_api.users', # custom users app + # Your stuff: custom apps go here + 'funkwhale_api.music', + 'funkwhale_api.favorites', + 'funkwhale_api.radios', + 'funkwhale_api.history', + 'funkwhale_api.playlists', + 'funkwhale_api.providers.audiofile', +) + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps +INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS + +# MIDDLEWARE CONFIGURATION +# ------------------------------------------------------------------------------ +MIDDLEWARE_CLASSES = ( + # Make sure djangosecure.middleware.SecurityMiddleware is listed first + 'django.contrib.sessions.middleware.SessionMiddleware', + 'funkwhale_api.users.middleware.AnonymousSessionMiddleware', + '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', +) + +# MIGRATIONS CONFIGURATION +# ------------------------------------------------------------------------------ +MIGRATION_MODULES = { + 'sites': 'funkwhale_api.contrib.sites.migrations' +} + +# DEBUG +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug +DEBUG = env.bool("DJANGO_DEBUG", False) + +# FIXTURE CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS +FIXTURE_DIRS = ( + str(APPS_DIR.path('fixtures')), +) + +# EMAIL CONFIGURATION +# ------------------------------------------------------------------------------ +EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend') + +# MANAGER CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins +ADMINS = ( + ("""Eliot Berriot""", 'contact@eliotberriot.om'), +) + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers +MANAGERS = ADMINS + +# DATABASE CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases +DATABASES = { + # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ + 'default': env.db("DATABASE_URL", default="postgresql://postgres@postgres/postgres"), +} +DATABASES['default']['ATOMIC_REQUESTS'] = True +# +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.sqlite3', +# 'NAME': 'db.sqlite3', +# } +# } +# GENERAL CONFIGURATION +# ------------------------------------------------------------------------------ +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# In a Windows environment this must be set to your system time zone. +TIME_ZONE = 'UTC' + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code +LANGUAGE_CODE = 'en-us' + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id +SITE_ID = 1 + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n +USE_I18N = True + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n +USE_L10N = True + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz +USE_TZ = True + +# TEMPLATE CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#templates +TEMPLATES = [ + { + # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs + 'DIRS': [ + str(APPS_DIR.path('templates')), + ], + 'OPTIONS': { + # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug + 'debug': DEBUG, + # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders + # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types + 'loaders': [ + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + ], + # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + # Your stuff: custom template context processors go here + ], + }, + }, +] + +# See: http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs +CRISPY_TEMPLATE_PACK = 'bootstrap3' + +# STATIC FILE CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root +STATIC_ROOT = str(ROOT_DIR('staticfiles')) + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url +STATIC_URL = env("STATIC_URL", default='/static/') + +# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS +STATICFILES_DIRS = ( + str(APPS_DIR.path('static')), +) + +# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +) + +# MEDIA CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root +MEDIA_ROOT = str(APPS_DIR('media')) + +USE_SAMPLE_TRACK = env.bool("USE_SAMPLE_TRACK", False) + + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url +MEDIA_URL = '/media/' + +# URL Configuration +# ------------------------------------------------------------------------------ +ROOT_URLCONF = 'config.urls' + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application +WSGI_APPLICATION = 'config.wsgi.application' + +# AUTHENTICATION CONFIGURATION +# ------------------------------------------------------------------------------ +AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.ModelBackend', + 'allauth.account.auth_backends.AuthenticationBackend', +) + +# Some really nice defaults +ACCOUNT_AUTHENTICATION_METHOD = 'username' +ACCOUNT_EMAIL_REQUIRED = True +ACCOUNT_EMAIL_VERIFICATION = 'mandatory' + +# Custom user app defaults +# Select the correct user model +AUTH_USER_MODEL = 'users.User' +LOGIN_REDIRECT_URL = 'users:redirect' +LOGIN_URL = 'account_login' + +# SLUGLIFIER +AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify' + +########## CELERY +INSTALLED_APPS += ('funkwhale_api.taskapp.celery.CeleryConfig',) +# if you are not using the django database broker (e.g. rabbitmq, redis, memcached), you can remove the next line. +INSTALLED_APPS += ('kombu.transport.django',) +BROKER_URL = env("CELERY_BROKER_URL", default='django://') +########## END CELERY + + +# Location of root django.contrib.admin URL, use {% url 'admin:index' %} +ADMIN_URL = r'^admin/' +SESSION_SAVE_EVERY_REQUEST = True +# Your common stuff: Below this line define 3rd party library settings +CELERY_DEFAULT_RATE_LIMIT = 1 +CELERYD_TASK_TIME_LIMIT = 300 +import datetime +JWT_AUTH = { + 'JWT_ALLOW_REFRESH': True, + 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), + 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=30), + 'JWT_AUTH_HEADER_PREFIX': 'JWT', +} + +ACCOUNT_ADAPTER = 'funkwhale_api.users.adapters.FunkwhaleAccountAdapter' +CORS_ORIGIN_ALLOW_ALL = True +# CORS_ORIGIN_WHITELIST = ( +# 'localhost', +# 'funkwhale.localhost', +# ) +CORS_ALLOW_CREDENTIALS = True +API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True) +REGISTRATION_MODE = env('REGISTRATION_MODE', default='disabled') +REST_FRAMEWORK = { + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ), + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 25, + + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.BasicAuthentication', + ), + 'DEFAULT_FILTER_BACKENDS': ( + 'rest_framework.filters.OrderingFilter', + ) +} + +FUNKWHALE_PROVIDERS = { + 'youtube': { + 'api_key': env('YOUTUBE_API_KEY', default='REPLACE_ME') + } +} +ATOMIC_REQUESTS = False diff --git a/api/config/settings/local.py b/api/config/settings/local.py new file mode 100644 index 000000000..762ffe7aa --- /dev/null +++ b/api/config/settings/local.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +''' +Local settings + +- Run in Debug mode +- Use console backend for emails +- Add Django Debug Toolbar +- Add django-extensions as app +''' + +from .common import * # noqa + +# DEBUG +# ------------------------------------------------------------------------------ +DEBUG = env.bool('DJANGO_DEBUG', default=True) +TEMPLATES[0]['OPTIONS']['debug'] = DEBUG + +# SECRET CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key +# Note: This key only used for development and testing. +SECRET_KEY = env("DJANGO_SECRET_KEY", default='mc$&b=5j#6^bv7tld1gyjp2&+^-qrdy=0sw@r5sua*1zp4fmxc') + +# Mail settings +# ------------------------------------------------------------------------------ +EMAIL_HOST = 'localhost' +EMAIL_PORT = 1025 +EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', + default='django.core.mail.backends.console.EmailBackend') + +# CACHING +# ------------------------------------------------------------------------------ +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + 'LOCATION': '' + } +} + +# django-debug-toolbar +# ------------------------------------------------------------------------------ +MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',) + +# INTERNAL_IPS = ('127.0.0.1', '10.0.2.2',) + +DEBUG_TOOLBAR_CONFIG = { + 'DISABLE_PANELS': [ + 'debug_toolbar.panels.redirects.RedirectsPanel', + ], + 'SHOW_TEMPLATE_CONTEXT': True, + 'SHOW_TOOLBAR_CALLBACK': lambda request: True, +} + +# django-extensions +# ------------------------------------------------------------------------------ +# INSTALLED_APPS += ('django_extensions', ) +INSTALLED_APPS += ('debug_toolbar', ) + +# TESTING +# ------------------------------------------------------------------------------ +TEST_RUNNER = 'django.test.runner.DiscoverRunner' + +########## CELERY +# In development, all tasks will be executed locally by blocking until the task returns +CELERY_ALWAYS_EAGER = False +########## END CELERY + +# Your local stuff: Below this line define 3rd party library settings + +LOGGING = { + 'version': 1, + 'handlers': { + 'console':{ + 'level':'DEBUG', + 'class':'logging.StreamHandler', + }, + }, + 'loggers': { + 'django.request': { + 'handlers':['console'], + 'propagate': True, + 'level':'DEBUG', + } + }, +} diff --git a/api/config/settings/production.py b/api/config/settings/production.py new file mode 100644 index 000000000..937328d1f --- /dev/null +++ b/api/config/settings/production.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +''' +Production Configurations + +- Use djangosecure +- Use Amazon's S3 for storing static files and uploaded media +- Use mailgun to send emails +- Use Redis on Heroku + + +''' +from __future__ import absolute_import, unicode_literals + +from django.utils import six + + +from .common import * # noqa + +# SECRET CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key +# Raises ImproperlyConfigured exception if DJANGO_SECRET_KEY not in os.environ +SECRET_KEY = env("DJANGO_SECRET_KEY") + +# This ensures that Django will be able to detect a secure connection +# properly on Heroku. +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + +# django-secure +# ------------------------------------------------------------------------------ +# INSTALLED_APPS += ("djangosecure", ) +# +# SECURITY_MIDDLEWARE = ( +# 'djangosecure.middleware.SecurityMiddleware', +# ) +# +# +# # Make sure djangosecure.middleware.SecurityMiddleware is listed first +# MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES +# +# # set this to 60 seconds and then to 518400 when you can prove it works +# SECURE_HSTS_SECONDS = 60 +# SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( +# "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True) +# SECURE_FRAME_DENY = env.bool("DJANGO_SECURE_FRAME_DENY", default=True) +# SECURE_CONTENT_TYPE_NOSNIFF = env.bool( +# "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True) +# SECURE_BROWSER_XSS_FILTER = True +# SESSION_COOKIE_SECURE = False +# SESSION_COOKIE_HTTPONLY = True +# SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) + +# SITE CONFIGURATION +# ------------------------------------------------------------------------------ +# Hosts/domain names that are valid for this site +# See https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts +ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['funkwhale.io']) +# END SITE CONFIGURATION + +INSTALLED_APPS += ("gunicorn", ) + +# STORAGE CONFIGURATION +# ------------------------------------------------------------------------------ +# Uploaded Media Files +# ------------------------ +DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' + +# URL that handles the media served from MEDIA_ROOT, used for managing +# stored files. +MEDIA_URL = '/media/' + +# Static Assets +# ------------------------ +STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' + + +# EMAIL +# ------------------------------------------------------------------------------ +DEFAULT_FROM_EMAIL = env('DJANGO_DEFAULT_FROM_EMAIL', + default='funkwhale_api ') + +EMAIL_SUBJECT_PREFIX = env("DJANGO_EMAIL_SUBJECT_PREFIX", default='[funkwhale_api] ') +SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=DEFAULT_FROM_EMAIL) + + +# TEMPLATE CONFIGURATION +# ------------------------------------------------------------------------------ +# See: +# https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loaders.cached.Loader +TEMPLATES[0]['OPTIONS']['loaders'] = [ + ('django.template.loaders.cached.Loader', [ + 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ]), +] + +# DATABASE CONFIGURATION +# ------------------------------------------------------------------------------ +# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ +DATABASES['default'] = env.db("DATABASE_URL") + +# CACHING +# ------------------------------------------------------------------------------ +# Heroku URL does not pass the DB number, so we parse it in +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "{0}/{1}".format(env.cache_url('REDIS_URL', default="redis://127.0.0.1:6379"), 0), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + "IGNORE_EXCEPTIONS": True, # mimics memcache behavior. + # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior + } + } +} + + +# LOGGING CONFIGURATION +# ------------------------------------------------------------------------------ +# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error when DEBUG=False. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(module)s ' + '%(process)d %(thread)d %(message)s' + }, + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + }, + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'verbose', + }, + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True + }, + 'django.security.DisallowedHost': { + 'level': 'ERROR', + 'handlers': ['console', 'mail_admins'], + 'propagate': True + } + } +} + +# Custom Admin URL, use {% url 'admin:index' %} +ADMIN_URL = env('DJANGO_ADMIN_URL') + +# Your production stuff: Below this line define 3rd party library settings diff --git a/api/config/settings/test.py b/api/config/settings/test.py new file mode 100644 index 000000000..1323ff35a --- /dev/null +++ b/api/config/settings/test.py @@ -0,0 +1,34 @@ +from .common import * # noqa +SECRET_KEY = env("DJANGO_SECRET_KEY", default='test') +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } +} + +# Mail settings +# ------------------------------------------------------------------------------ +EMAIL_HOST = 'localhost' +EMAIL_PORT = 1025 +EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', + default='django.core.mail.backends.console.EmailBackend') + +# CACHING +# ------------------------------------------------------------------------------ +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + 'LOCATION': '' + } +} +# TESTING +# ------------------------------------------------------------------------------ +TEST_RUNNER = 'django.test.runner.DiscoverRunner' + +########## CELERY +# In development, all tasks will be executed locally by blocking until the task returns +CELERY_ALWAYS_EAGER = True +########## END CELERY + +# Your local stuff: Below this line define 3rd party library settings diff --git a/api/config/urls.py b/api/config/urls.py new file mode 100644 index 000000000..8764640d1 --- /dev/null +++ b/api/config/urls.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf import settings +from django.conf.urls import include, url +from django.conf.urls.static import static +from django.contrib import admin +from django.views.generic import TemplateView +from django.views import defaults as default_views + +urlpatterns = [ + # Django Admin, use {% url 'admin:index' %} + url(settings.ADMIN_URL, include(admin.site.urls)), + + url(r'^api/', include("config.api_urls", namespace="api")), + url(r'^api/auth/', include('rest_auth.urls')), + url(r'^api/auth/registration/', include('funkwhale_api.users.rest_auth_urls')), + url(r'^accounts/', include('allauth.urls')), + + # Your stuff: custom urls includes go here + + +] + +if settings.DEBUG: + # This allows the error pages to be debugged during development, just visit + # these url in browser to see how these error pages look like. + urlpatterns += [ + url(r'^400/$', default_views.bad_request), + url(r'^403/$', default_views.permission_denied), + url(r'^404/$', default_views.page_not_found), + url(r'^500/$', default_views.server_error), + ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/api/config/wsgi.py b/api/config/wsgi.py new file mode 100644 index 000000000..a53b580d7 --- /dev/null +++ b/api/config/wsgi.py @@ -0,0 +1,41 @@ +""" +WSGI config for funkwhale_api project. + +This module contains the WSGI application used by Django's development server +and any production WSGI deployments. It should expose a module-level variable +named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover +this application via the ``WSGI_APPLICATION`` setting. + +Usually you will have the standard Django WSGI application here, but it also +might make sense to replace the whole Django WSGI application with a custom one +that later delegates to the Django one. For example, you could introduce WSGI +middleware here, or combine a Django application with an application of another +framework. + +""" +import os + + +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise + + +# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks +# if running multiple sites in the same mod_wsgi process. To fix this, use +# mod_wsgi daemon mode with each site in its own daemon process, or use +# os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production" +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production") + +# This application object is used by any WSGI server configured to use this +# file. This includes Django's development server, if the WSGI_APPLICATION +# setting points here. +application = get_wsgi_application() + +# Use Whitenoise to serve static files +# See: https://whitenoise.readthedocs.org/ +application = DjangoWhiteNoise(application) + + +# Apply WSGI middleware here. +# from helloworld.wsgi import HelloWorldApplication +# application = HelloWorldApplication(application) diff --git a/api/demo/demo-user.py b/api/demo/demo-user.py new file mode 100644 index 000000000..64f48f9aa --- /dev/null +++ b/api/demo/demo-user.py @@ -0,0 +1,6 @@ +from funkwhale_api.users.models import User + + +u = User.objects.create(email='demo@demo.com', username='demo', is_staff=True) +u.set_password('demo') +u.save() diff --git a/api/demo/load-demo-data.sh b/api/demo/load-demo-data.sh new file mode 100755 index 000000000..c09c5075e --- /dev/null +++ b/api/demo/load-demo-data.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +echo "Loading demo data..." + +python manage.py migrate --noinput + +echo "Creating demo user..." + +cat demo/demo-user.py | python manage.py shell --plain + +echo "Importing demo tracks..." + +python manage.py import_files "/music/**/*.ogg" --recursive --noinput diff --git a/api/docker-compose.yml b/api/docker-compose.yml new file mode 100644 index 000000000..4f79eb301 --- /dev/null +++ b/api/docker-compose.yml @@ -0,0 +1,42 @@ +version: '2' +services: + postgres: + image: postgres:9.5 + + api: + build: . + links: + - postgres + - redis + command: ./compose/django/gunicorn.sh + env_file: .env + volumes: + - ./media:/app/funkwhale_api/media + - ./staticfiles:/app/staticfiles + - ./music:/music + ports: + - "127.0.0.1:6001:5000" + + redis: + image: redis:3.0 + + celeryworker: + build: . + env_file: .env + links: + - postgres + - redis + command: celery -A funkwhale_api.taskapp worker -l INFO + volumes: + - ./media:/app/funkwhale_api/media + - ./music:/music + environment: + - C_FORCE_ROOT=True + + celerybeat: + build: . + env_file: .env + links: + - postgres + - redis + command: celery -A funkwhale_api.taskapp beat -l INFO diff --git a/api/docker/Dockerfile.base b/api/docker/Dockerfile.base new file mode 100644 index 000000000..2617c9587 --- /dev/null +++ b/api/docker/Dockerfile.base @@ -0,0 +1,10 @@ +FROM python:3.5 + +ENV PYTHONUNBUFFERED 1 + +# Requirements have to be pulled and installed here, otherwise caching won't work +COPY ./requirements.apt /requirements.apt +COPY ./install_os_dependencies.sh /install_os_dependencies.sh +RUN bash install_os_dependencies.sh install +COPY ./requirements /requirements +RUN pip install -r /requirements/base.txt diff --git a/api/docker/Dockerfile.local b/api/docker/Dockerfile.local new file mode 100644 index 000000000..b70410459 --- /dev/null +++ b/api/docker/Dockerfile.local @@ -0,0 +1,12 @@ +FROM python:3.5 + +ENV PYTHONUNBUFFERED 1 + +# Requirements have to be pulled and installed here, otherwise caching won't work +COPY ./requirements.apt /requirements.apt +COPY ./install_os_dependencies.sh /install_os_dependencies.sh +RUN bash install_os_dependencies.sh install +COPY ./requirements /requirements +RUN pip install -r /requirements/local.txt + +WORKDIR /app diff --git a/api/docker/Dockerfile.test b/api/docker/Dockerfile.test new file mode 100644 index 000000000..f2e2ef893 --- /dev/null +++ b/api/docker/Dockerfile.test @@ -0,0 +1,13 @@ +FROM funkwhale/apibase + +ENV PYTHONUNBUFFERED 1 + +# Requirements have to be pulled and installed here, otherwise caching won't work +COPY ./requirements.apt /requirements.apt +COPY ./install_os_dependencies.sh /install_os_dependencies.sh +RUN bash install_os_dependencies.sh install +COPY ./requirements /requirements +RUN pip install -r /requirements/local.txt +RUN pip install -r /requirements/test.txt + +WORKDIR /app diff --git a/api/funkwhale_api/__init__.py b/api/funkwhale_api/__init__.py new file mode 100644 index 000000000..6b304975e --- /dev/null +++ b/api/funkwhale_api/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +__version__ = '0.1.0' +__version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace('-', '.', 1).split('.')]) diff --git a/api/funkwhale_api/common/__init__.py b/api/funkwhale_api/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/common/permissions.py b/api/funkwhale_api/common/permissions.py new file mode 100644 index 000000000..3f13b2005 --- /dev/null +++ b/api/funkwhale_api/common/permissions.py @@ -0,0 +1,11 @@ +from django.conf import settings + +from rest_framework.permissions import BasePermission + + +class ConditionalAuthentication(BasePermission): + + def has_permission(self, request, view): + if settings.API_AUTHENTICATION_REQUIRED: + return request.user and request.user.is_authenticated() + return True diff --git a/api/funkwhale_api/common/utils.py b/api/funkwhale_api/common/utils.py new file mode 100644 index 000000000..838c15c00 --- /dev/null +++ b/api/funkwhale_api/common/utils.py @@ -0,0 +1,19 @@ +import os +import shutil + + +def rename_file(instance, field_name, new_name, allow_missing_file=False): + field = getattr(instance, field_name) + current_name, extension = os.path.splitext(field.name) + + new_name_with_extension = '{}{}'.format(new_name, extension) + try: + shutil.move(field.path, new_name_with_extension) + except FileNotFoundError: + if not allow_missing_file: + raise + print('Skipped missing file', field.path) + initial_path = os.path.dirname(field.name) + field.name = os.path.join(initial_path, new_name_with_extension) + instance.save() + return new_name_with_extension diff --git a/api/funkwhale_api/contrib/__init__.py b/api/funkwhale_api/contrib/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/api/funkwhale_api/contrib/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/api/funkwhale_api/contrib/sites/__init__.py b/api/funkwhale_api/contrib/sites/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/api/funkwhale_api/contrib/sites/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/api/funkwhale_api/contrib/sites/migrations/0001_initial.py b/api/funkwhale_api/contrib/sites/migrations/0001_initial.py new file mode 100644 index 000000000..555d02c42 --- /dev/null +++ b/api/funkwhale_api/contrib/sites/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.contrib.sites.models + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Site', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)), + ('domain', models.CharField(verbose_name='domain name', max_length=100, validators=[django.contrib.sites.models._simple_domain_name_validator])), + ('name', models.CharField(verbose_name='display name', max_length=50)), + ], + options={ + 'verbose_name_plural': 'sites', + 'verbose_name': 'site', + 'db_table': 'django_site', + 'ordering': ('domain',), + }, + managers=[ + (b'objects', django.contrib.sites.models.SiteManager()), + ], + ), + ] diff --git a/api/funkwhale_api/contrib/sites/migrations/0002_set_site_domain_and_name.py b/api/funkwhale_api/contrib/sites/migrations/0002_set_site_domain_and_name.py new file mode 100644 index 000000000..e92c8c338 --- /dev/null +++ b/api/funkwhale_api/contrib/sites/migrations/0002_set_site_domain_and_name.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations + + +def update_site_forward(apps, schema_editor): + """Set site domain and name.""" + Site = apps.get_model("sites", "Site") + Site.objects.update_or_create( + id=settings.SITE_ID, + defaults={ + "domain": "funkwhale.io", + "name": "funkwhale_api" + } + ) + + +def update_site_backward(apps, schema_editor): + """Revert site domain and name to default.""" + Site = apps.get_model("sites", "Site") + Site.objects.update_or_create( + id=settings.SITE_ID, + defaults={ + "domain": "example.com", + "name": "example.com" + } + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('sites', '0001_initial'), + ] + + operations = [ + migrations.RunPython(update_site_forward, update_site_backward), + ] diff --git a/api/funkwhale_api/contrib/sites/migrations/__init__.py b/api/funkwhale_api/contrib/sites/migrations/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/api/funkwhale_api/contrib/sites/migrations/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/api/funkwhale_api/downloader/__init__.py b/api/funkwhale_api/downloader/__init__.py new file mode 100644 index 000000000..29ec89954 --- /dev/null +++ b/api/funkwhale_api/downloader/__init__.py @@ -0,0 +1,2 @@ + +from .downloader import download diff --git a/api/funkwhale_api/downloader/downloader.py b/api/funkwhale_api/downloader/downloader.py new file mode 100644 index 000000000..b35ed6f7d --- /dev/null +++ b/api/funkwhale_api/downloader/downloader.py @@ -0,0 +1,27 @@ +import os +import requests +import json +from urllib.parse import quote_plus +import youtube_dl +from django.conf import settings +import glob + + +def download( + url, + target_directory=settings.MEDIA_ROOT, + name="%(id)s.%(ext)s", + bitrate=192): + target_path = os.path.join(target_directory, name) + ydl_opts = { + 'quiet': True, + 'outtmpl': target_path, + 'postprocessors': [{ + 'key': 'FFmpegExtractAudio', + 'preferredcodec': 'vorbis', + }], + } + _downloader = youtube_dl.YoutubeDL(ydl_opts) + info = _downloader.extract_info(url) + info['audio_file_path'] = target_path % {'id': info['id'], 'ext': 'ogg'} + return info diff --git a/api/funkwhale_api/downloader/tests/__init__.py b/api/funkwhale_api/downloader/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/downloader/tests/test_downloader.py b/api/funkwhale_api/downloader/tests/test_downloader.py new file mode 100644 index 000000000..7cfaa63c8 --- /dev/null +++ b/api/funkwhale_api/downloader/tests/test_downloader.py @@ -0,0 +1,14 @@ +import os +from test_plus.test import TestCase +from .. import downloader +from funkwhale_api.utils.tests import TMPDirTestCaseMixin + + +class TestDownloader(TMPDirTestCaseMixin, TestCase): + + def test_can_download_audio_from_youtube_url_to_vorbis(self): + data = downloader.download('https://www.youtube.com/watch?v=tPEE9ZwTmy0', target_directory=self.download_dir) + self.assertEqual( + data['audio_file_path'], + os.path.join(self.download_dir, 'tPEE9ZwTmy0.ogg')) + self.assertTrue(os.path.exists(data['audio_file_path'])) diff --git a/api/funkwhale_api/favorites/__init__.py b/api/funkwhale_api/favorites/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/favorites/migrations/0001_initial.py b/api/funkwhale_api/favorites/migrations/0001_initial.py new file mode 100644 index 000000000..0a6f0e5fc --- /dev/null +++ b/api/funkwhale_api/favorites/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0003_auto_20151222_2233'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='TrackFavorite', + fields=[ + ('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('track', models.ForeignKey(related_name='track_favorites', to='music.Track')), + ('user', models.ForeignKey(related_name='track_favorites', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ('-creation_date',), + }, + ), + migrations.AlterUniqueTogether( + name='trackfavorite', + unique_together=set([('track', 'user')]), + ), + ] diff --git a/api/funkwhale_api/favorites/migrations/__init__.py b/api/funkwhale_api/favorites/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/favorites/models.py b/api/funkwhale_api/favorites/models.py new file mode 100644 index 000000000..f9c6426e6 --- /dev/null +++ b/api/funkwhale_api/favorites/models.py @@ -0,0 +1,18 @@ +from django.db import models +from django.utils import timezone + +from funkwhale_api.music.models import Track + +class TrackFavorite(models.Model): + creation_date = models.DateTimeField(default=timezone.now) + user = models.ForeignKey('users.User', related_name='track_favorites') + track = models.ForeignKey(Track, related_name='track_favorites') + + class Meta: + unique_together = ('track', 'user') + ordering = ('-creation_date',) + + @classmethod + def add(cls, track, user): + favorite, created = cls.objects.get_or_create(user=user, track=track) + return favorite diff --git a/api/funkwhale_api/favorites/serializers.py b/api/funkwhale_api/favorites/serializers.py new file mode 100644 index 000000000..57af4570e --- /dev/null +++ b/api/funkwhale_api/favorites/serializers.py @@ -0,0 +1,12 @@ +from rest_framework import serializers + +from funkwhale_api.music.serializers import TrackSerializerNested + +from . import models + + +class UserTrackFavoriteSerializer(serializers.ModelSerializer): + # track = TrackSerializerNested(read_only=True) + class Meta: + model = models.TrackFavorite + fields = ('id', 'track', 'creation_date') diff --git a/api/funkwhale_api/favorites/tests/__init__.py b/api/funkwhale_api/favorites/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/favorites/tests/test_favorites.py b/api/funkwhale_api/favorites/tests/test_favorites.py new file mode 100644 index 000000000..a68659ba4 --- /dev/null +++ b/api/funkwhale_api/favorites/tests/test_favorites.py @@ -0,0 +1,113 @@ +import json +from test_plus.test import TestCase +from django.core.urlresolvers import reverse + +from funkwhale_api.music.models import Track, Artist +from funkwhale_api.favorites.models import TrackFavorite +from funkwhale_api.users.models import User + +class TestFavorites(TestCase): + + def setUp(self): + super().setUp() + self.artist = Artist.objects.create(name='test') + self.track = Track.objects.create(title='test', artist=self.artist) + self.user = User.objects.create_user(username='test', email='test@test.com', password='test') + + def test_user_can_add_favorite(self): + TrackFavorite.add(self.track, self.user) + + favorite = TrackFavorite.objects.latest('id') + self.assertEqual(favorite.track, self.track) + self.assertEqual(favorite.user, self.user) + + def test_user_can_get_his_favorites(self): + favorite = TrackFavorite.add(self.track, self.user) + + url = reverse('api:favorites:tracks-list') + self.client.login(username=self.user.username, password='test') + + response = self.client.get(url) + + expected = [ + { + 'track': self.track.pk, + 'id': favorite.id, + 'creation_date': favorite.creation_date.isoformat().replace('+00:00', 'Z'), + } + ] + parsed_json = json.loads(response.content.decode('utf-8')) + + self.assertEqual(expected, parsed_json['results']) + + def test_user_can_add_favorite_via_api(self): + url = reverse('api:favorites:tracks-list') + self.client.login(username=self.user.username, password='test') + response = self.client.post(url, {'track': self.track.pk}) + + favorite = TrackFavorite.objects.latest('id') + expected = { + 'track': self.track.pk, + 'id': favorite.id, + 'creation_date': favorite.creation_date.isoformat().replace('+00:00', 'Z'), + } + parsed_json = json.loads(response.content.decode('utf-8')) + + self.assertEqual(expected, parsed_json) + self.assertEqual(favorite.track, self.track) + self.assertEqual(favorite.user, self.user) + + def test_user_can_remove_favorite_via_api(self): + favorite = TrackFavorite.add(self.track, self.user) + + url = reverse('api:favorites:tracks-detail', kwargs={'pk': favorite.pk}) + self.client.login(username=self.user.username, password='test') + response = self.client.delete(url, {'track': self.track.pk}) + self.assertEqual(response.status_code, 204) + self.assertEqual(TrackFavorite.objects.count(), 0) + + def test_user_can_remove_favorite_via_api_using_track_id(self): + favorite = TrackFavorite.add(self.track, self.user) + + url = reverse('api:favorites:tracks-remove') + self.client.login(username=self.user.username, password='test') + response = self.client.delete( + url, json.dumps({'track': self.track.pk}), + content_type='application/json' + ) + + self.assertEqual(response.status_code, 204) + self.assertEqual(TrackFavorite.objects.count(), 0) + + from funkwhale_api.users.models import User + + def test_can_restrict_api_views_to_authenticated_users(self): + urls = [ + ('api:favorites:tracks-list', 'get'), + ] + + for route_name, method in urls: + url = self.reverse(route_name) + with self.settings(API_AUTHENTICATION_REQUIRED=True): + response = getattr(self.client, method)(url) + self.assertEqual(response.status_code, 401) + + self.client.login(username=self.user.username, password='test') + + for route_name, method in urls: + url = self.reverse(route_name) + with self.settings(API_AUTHENTICATION_REQUIRED=False): + response = getattr(self.client, method)(url) + self.assertEqual(response.status_code, 200) + + def test_can_filter_tracks_by_favorites(self): + favorite = TrackFavorite.add(self.track, self.user) + + url = reverse('api:tracks-list') + self.client.login(username=self.user.username, password='test') + + response = self.client.get(url, data={'favorites': True}) + + parsed_json = json.loads(response.content.decode('utf-8')) + self.assertEqual(parsed_json['count'], 1) + self.assertEqual(parsed_json['results'][0]['id'], self.track.id) diff --git a/api/funkwhale_api/favorites/urls.py b/api/funkwhale_api/favorites/urls.py new file mode 100644 index 000000000..6a9b12a81 --- /dev/null +++ b/api/funkwhale_api/favorites/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import include, url +from . import views + +from rest_framework import routers +router = routers.SimpleRouter() +router.register(r'tracks', views.TrackFavoriteViewSet, 'tracks') + +urlpatterns = router.urls diff --git a/api/funkwhale_api/favorites/views.py b/api/funkwhale_api/favorites/views.py new file mode 100644 index 000000000..98c0cfc08 --- /dev/null +++ b/api/funkwhale_api/favorites/views.py @@ -0,0 +1,54 @@ +from rest_framework import generics, mixins, viewsets +from rest_framework import status +from rest_framework.response import Response +from rest_framework import pagination +from rest_framework.decorators import list_route + +from funkwhale_api.music.models import Track +from funkwhale_api.common.permissions import ConditionalAuthentication + +from . import models +from . import serializers + + +class CustomLimitPagination(pagination.PageNumberPagination): + page_size = 100 + page_size_query_param = 'page_size' + max_page_size = 100 + + +class TrackFavoriteViewSet(mixins.CreateModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin, + viewsets.GenericViewSet): + + serializer_class = serializers.UserTrackFavoriteSerializer + queryset = (models.TrackFavorite.objects.all()) + permission_classes = [ConditionalAuthentication] + pagination_class = CustomLimitPagination + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + instance = self.perform_create(serializer) + serializer = self.get_serializer(instance=instance) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + def get_queryset(self): + return self.queryset.filter(user=self.request.user) + + def perform_create(self, serializer): + track = Track.objects.get(pk=serializer.data['track']) + favorite = models.TrackFavorite.add(track=track, user=self.request.user) + return favorite + + @list_route(methods=['delete']) + def remove(self, request, *args, **kwargs): + try: + pk = int(request.data['track']) + favorite = request.user.track_favorites.get(track__pk=pk) + except (AttributeError, ValueError, models.TrackFavorite.DoesNotExist): + return Response({}, status=400) + favorite.delete() + return Response([], status=status.HTTP_204_NO_CONTENT) diff --git a/api/funkwhale_api/history/__init__.py b/api/funkwhale_api/history/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/history/admin.py b/api/funkwhale_api/history/admin.py new file mode 100644 index 000000000..f8f587a01 --- /dev/null +++ b/api/funkwhale_api/history/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +from . import models + +@admin.register(models.Listening) +class ListeningAdmin(admin.ModelAdmin): + list_display = ['track', 'end_date', 'user', 'session_key'] + search_fields = ['track__name', 'user__username'] diff --git a/api/funkwhale_api/history/migrations/0001_initial.py b/api/funkwhale_api/history/migrations/0001_initial.py new file mode 100644 index 000000000..5ddfc26f3 --- /dev/null +++ b/api/funkwhale_api/history/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0008_auto_20160529_1456'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Listening', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)), + ('end_date', models.DateTimeField(null=True, blank=True, default=django.utils.timezone.now)), + ('session_key', models.CharField(null=True, blank=True, max_length=100)), + ('track', models.ForeignKey(related_name='listenings', to='music.Track')), + ('user', models.ForeignKey(blank=True, null=True, related_name='listenings', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ('-end_date',), + }, + ), + ] diff --git a/api/funkwhale_api/history/migrations/__init__.py b/api/funkwhale_api/history/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/history/models.py b/api/funkwhale_api/history/models.py new file mode 100644 index 000000000..0810ecf81 --- /dev/null +++ b/api/funkwhale_api/history/models.py @@ -0,0 +1,21 @@ +from django.utils import timezone +from django.db import models +from django.core.exceptions import ValidationError + +from funkwhale_api.music.models import Track + + +class Listening(models.Model): + end_date = models.DateTimeField(default=timezone.now, null=True, blank=True) + track = models.ForeignKey(Track, related_name="listenings") + user = models.ForeignKey('users.User', related_name="listenings", null=True, blank=True) + session_key = models.CharField(max_length=100, null=True, blank=True) + + class Meta: + ordering = ('-end_date',) + + def save(self, **kwargs): + if not self.user and not self.session_key: + raise ValidationError('Cannot have both session_key and user empty for listening') + + super().save(**kwargs) diff --git a/api/funkwhale_api/history/serializers.py b/api/funkwhale_api/history/serializers.py new file mode 100644 index 000000000..64bdf41c6 --- /dev/null +++ b/api/funkwhale_api/history/serializers.py @@ -0,0 +1,20 @@ +from rest_framework import serializers + +from funkwhale_api.music.serializers import TrackSerializerNested +from . import models + + +class ListeningSerializer(serializers.ModelSerializer): + + class Meta: + model = models.Listening + fields = ('id', 'user', 'session_key', 'track', 'end_date') + + + def create(self, validated_data): + if self.context.get('user'): + validated_data['user'] = self.context.get('user') + else: + validated_data['session_key'] = self.context['session_key'] + + return super().create(validated_data) diff --git a/api/funkwhale_api/history/tests/__init__.py b/api/funkwhale_api/history/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/history/tests/test_history.py b/api/funkwhale_api/history/tests/test_history.py new file mode 100644 index 000000000..448c5b15e --- /dev/null +++ b/api/funkwhale_api/history/tests/test_history.py @@ -0,0 +1,49 @@ +import random +import json +from test_plus.test import TestCase +from django.core.urlresolvers import reverse +from django.core.exceptions import ValidationError +from django.utils import timezone + +from model_mommy import mommy + +from funkwhale_api.users.models import User +from funkwhale_api.history import models + +class TestHistory(TestCase): + + def setUp(self): + super().setUp() + self.user = User.objects.create_user(username='test', email='test@test.com', password='test') + + def test_can_create_listening(self): + track = mommy.make('music.Track') + now = timezone.now() + l = models.Listening.objects.create(user=self.user, track=track) + + def test_anonymous_user_can_create_listening_via_api(self): + track = mommy.make('music.Track') + url = self.reverse('api:history:listenings-list') + response = self.client.post(url, { + 'track': track.pk, + }) + + listening = models.Listening.objects.latest('id') + + self.assertEqual(listening.track, track) + self.assertIsNotNone(listening.session_key) + + def test_logged_in_user_can_create_listening_via_api(self): + track = mommy.make('music.Track') + + self.client.login(username=self.user.username, password='test') + + url = self.reverse('api:history:listenings-list') + response = self.client.post(url, { + 'track': track.pk, + }) + + listening = models.Listening.objects.latest('id') + + self.assertEqual(listening.track, track) + self.assertEqual(listening.user, self.user) diff --git a/api/funkwhale_api/history/urls.py b/api/funkwhale_api/history/urls.py new file mode 100644 index 000000000..6bd72a8a2 --- /dev/null +++ b/api/funkwhale_api/history/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import include, url +from . import views + +from rest_framework import routers +router = routers.SimpleRouter() +router.register(r'listenings', views.ListeningViewSet, 'listenings') + +urlpatterns = router.urls diff --git a/api/funkwhale_api/history/views.py b/api/funkwhale_api/history/views.py new file mode 100644 index 000000000..d65a70f87 --- /dev/null +++ b/api/funkwhale_api/history/views.py @@ -0,0 +1,36 @@ +from rest_framework import generics, mixins, viewsets +from rest_framework import status +from rest_framework.response import Response +from rest_framework.decorators import detail_route + +from funkwhale_api.music.serializers import TrackSerializerNested +from funkwhale_api.common.permissions import ConditionalAuthentication + +from . import models +from . import serializers + +class ListeningViewSet(mixins.CreateModelMixin, + mixins.RetrieveModelMixin, + viewsets.GenericViewSet): + + serializer_class = serializers.ListeningSerializer + queryset = models.Listening.objects.all() + permission_classes = [ConditionalAuthentication] + + def create(self, request, *args, **kwargs): + return super().create(request, *args, **kwargs) + + def get_queryset(self): + queryset = super().get_queryset() + if self.request.user.is_authenticated(): + return queryset.filter(user=self.request.user) + else: + return queryset.filter(session_key=self.request.session.session_key) + + def get_serializer_context(self): + context = super().get_serializer_context() + if self.request.user.is_authenticated(): + context['user'] = self.request.user + else: + context['session_key'] = self.request.session.session_key + return context diff --git a/api/funkwhale_api/music/__init__.py b/api/funkwhale_api/music/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/music/admin.py b/api/funkwhale_api/music/admin.py new file mode 100644 index 000000000..a6a7f94f3 --- /dev/null +++ b/api/funkwhale_api/music/admin.py @@ -0,0 +1,47 @@ +from django.contrib import admin + +from . import models + +@admin.register(models.Artist) +class ArtistAdmin(admin.ModelAdmin): + list_display = ['name', 'mbid', 'creation_date'] + search_fields = ['name', 'mbid'] + +@admin.register(models.Album) +class AlbumAdmin(admin.ModelAdmin): + list_display = ['title', 'artist', 'mbid', 'release_date', 'creation_date'] + search_fields = ['title', 'artist__name', 'mbid'] + list_select_related = True + +@admin.register(models.Track) +class TrackAdmin(admin.ModelAdmin): + list_display = ['title', 'artist', 'album', 'mbid'] + search_fields = ['title', 'artist__name', 'album__title', 'mbid'] + list_select_related = True + +@admin.register(models.ImportBatch) +class ImportBatchAdmin(admin.ModelAdmin): + list_display = ['creation_date', 'status'] + +@admin.register(models.ImportJob) +class ImportJobAdmin(admin.ModelAdmin): + list_display = ['source', 'batch', 'status', 'mbid'] + list_select_related = True + search_fields = ['source', 'batch__pk', 'mbid'] + list_filter = ['status'] + + +@admin.register(models.Work) +class WorkAdmin(admin.ModelAdmin): + list_display = ['title', 'mbid', 'language', 'nature'] + list_select_related = True + search_fields = ['title'] + list_filter = ['language', 'nature'] + + +@admin.register(models.Lyrics) +class LyricsAdmin(admin.ModelAdmin): + list_display = ['url', 'id', 'url'] + list_select_related = True + search_fields = ['url', 'work__title'] + list_filter = ['work__language'] diff --git a/api/funkwhale_api/music/importers.py b/api/funkwhale_api/music/importers.py new file mode 100644 index 000000000..7e26fe968 --- /dev/null +++ b/api/funkwhale_api/music/importers.py @@ -0,0 +1,42 @@ + + +def load(model, *args, **kwargs): + importer = registry[model.__name__](model=model) + return importer.load(*args, **kwargs) + +class Importer(object): + def __init__(self, model): + self.model = model + + def load(self, cleaned_data, raw_data, import_hooks): + mbid = cleaned_data.pop('mbid') + m = self.model.objects.update_or_create(mbid=mbid, defaults=cleaned_data)[0] + for hook in import_hooks: + hook(m, cleaned_data, raw_data) + return m + +class Mapping(object): + """Cast musicbrainz data to funkwhale data and vice-versa""" + def __init__(self, musicbrainz_mapping): + self.musicbrainz_mapping = musicbrainz_mapping + + self._from_musicbrainz = {} + self._to_musicbrainz = {} + for field_name, conf in self.musicbrainz_mapping.items(): + self._from_musicbrainz[conf['musicbrainz_field_name']] = { + 'field_name': field_name, + 'converter': conf.get('converter', lambda v: v) + } + self._to_musicbrainz[field_name] = { + 'field_name': conf['musicbrainz_field_name'], + 'converter': conf.get('converter', lambda v: v) + } + def from_musicbrainz(self, key, value): + return self._from_musicbrainz[key]['field_name'], self._from_musicbrainz[key]['converter'](value) + +registry = { + 'Artist': Importer, + 'Track': Importer, + 'Album': Importer, + 'Work': Importer, +} diff --git a/api/funkwhale_api/music/lyrics.py b/api/funkwhale_api/music/lyrics.py new file mode 100644 index 000000000..1ad69ce25 --- /dev/null +++ b/api/funkwhale_api/music/lyrics.py @@ -0,0 +1,31 @@ +import urllib.request +import html.parser +from bs4 import BeautifulSoup + + +def _get_html(url): + with urllib.request.urlopen(url) as response: + html = response.read() + return html.decode('utf-8') + + +def extract_content(html): + soup = BeautifulSoup(html, "html.parser") + return soup.find_all("div", class_='lyricbox')[0].contents + + +def clean_content(contents): + final_content = "" + for e in contents: + if e == '\n': + continue + if e.name == 'script': + continue + if e.name == 'br': + final_content += "\n" + continue + try: + final_content += e.text + except AttributeError: + final_content += str(e) + return final_content diff --git a/api/funkwhale_api/music/metadata.py b/api/funkwhale_api/music/metadata.py new file mode 100644 index 000000000..3fe61e652 --- /dev/null +++ b/api/funkwhale_api/music/metadata.py @@ -0,0 +1,34 @@ +import mutagen + +NODEFAULT = object() + +class Metadata(object): + ALIASES = { + 'release': 'musicbrainz_albumid', + 'artist': 'musicbrainz_artistid', + 'recording': 'musicbrainz_trackid', + } + + def __init__(self, path): + self._file = mutagen.File(path) + + def get(self, key, default=NODEFAULT, single=True): + try: + v = self._file[key] + except KeyError: + if default == NODEFAULT: + raise + return default + + # Some tags are returned as lists of string + if single: + return v[0] + return v + + def __getattr__(self, key): + try: + alias = self.ALIASES[key] + except KeyError: + raise ValueError('Invalid alias {}'.format(key)) + + return self.get(alias, single=True) diff --git a/api/funkwhale_api/music/migrations/0001_initial.py b/api/funkwhale_api/music/migrations/0001_initial.py new file mode 100644 index 000000000..e78647948 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0001_initial.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Album', + fields=[ + ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), + ('mbid', models.UUIDField(editable=False, blank=True, null=True)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('title', models.CharField(max_length=255)), + ('release_date', models.DateField()), + ('type', models.CharField(default='album', choices=[('album', 'Album')], max_length=30)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Artist', + fields=[ + ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), + ('mbid', models.UUIDField(editable=False, blank=True, null=True)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('name', models.CharField(max_length=255)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ImportBatch', + fields=[ + ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('submitted_by', models.ForeignKey(related_name='imports', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='ImportJob', + fields=[ + ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), + ('source', models.URLField()), + ('mbid', models.UUIDField(editable=False)), + ('status', models.CharField(default='pending', choices=[('pending', 'Pending'), ('finished', 'finished')], max_length=30)), + ('batch', models.ForeignKey(related_name='jobs', to='music.ImportBatch')), + ], + ), + migrations.CreateModel( + name='Track', + fields=[ + ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), + ('mbid', models.UUIDField(editable=False, blank=True, null=True)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('title', models.CharField(max_length=255)), + ('album', models.ForeignKey(related_name='tracks', blank=True, null=True, to='music.Album')), + ('artist', models.ForeignKey(related_name='tracks', to='music.Artist')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TrackFile', + fields=[ + ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), + ('audio_file', models.FileField(upload_to='tracks')), + ('source', models.URLField(blank=True, null=True)), + ('duration', models.IntegerField(blank=True, null=True)), + ('track', models.ForeignKey(related_name='files', to='music.Track')), + ], + ), + migrations.AddField( + model_name='album', + name='artist', + field=models.ForeignKey(related_name='albums', to='music.Artist'), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0002_auto_20151215_1645.py b/api/funkwhale_api/music/migrations/0002_auto_20151215_1645.py new file mode 100644 index 000000000..1b54a5cfc --- /dev/null +++ b/api/funkwhale_api/music/migrations/0002_auto_20151215_1645.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='album', + options={'ordering': ['-creation_date']}, + ), + migrations.AlterModelOptions( + name='artist', + options={'ordering': ['-creation_date']}, + ), + migrations.AlterModelOptions( + name='importbatch', + options={'ordering': ['-creation_date']}, + ), + migrations.AlterModelOptions( + name='track', + options={'ordering': ['-creation_date']}, + ), + migrations.AddField( + model_name='album', + name='cover', + field=models.ImageField(upload_to='albums/covers/%Y/%m/%d', null=True, blank=True), + ), + migrations.AlterField( + model_name='trackfile', + name='audio_file', + field=models.FileField(upload_to='tracks/%Y/%m/%d'), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0003_auto_20151222_2233.py b/api/funkwhale_api/music/migrations/0003_auto_20151222_2233.py new file mode 100644 index 000000000..060957dc1 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0003_auto_20151222_2233.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0002_auto_20151215_1645'), + ] + + operations = [ + migrations.AlterField( + model_name='album', + name='release_date', + field=models.DateField(null=True), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0004_track_tags.py b/api/funkwhale_api/music/migrations/0004_track_tags.py new file mode 100644 index 000000000..f95b08b0e --- /dev/null +++ b/api/funkwhale_api/music/migrations/0004_track_tags.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import taggit.managers + + +class Migration(migrations.Migration): + + dependencies = [ + ('taggit', '0002_auto_20150616_2121'), + ('music', '0003_auto_20151222_2233'), + ] + + operations = [ + migrations.AddField( + model_name='track', + name='tags', + field=taggit.managers.TaggableManager(verbose_name='Tags', help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag'), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0005_deduplicate.py b/api/funkwhale_api/music/migrations/0005_deduplicate.py new file mode 100644 index 000000000..82dca0caa --- /dev/null +++ b/api/funkwhale_api/music/migrations/0005_deduplicate.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +def get_duplicates(model): + return [i['mbid'] for i in model.objects.values('mbid').annotate(idcount=models.Count('mbid')).order_by('-idcount') if i['idcount'] > 1] + +def deduplicate(apps, schema_editor): + Artist = apps.get_model("music", "Artist") + Album = apps.get_model("music", "Album") + Track = apps.get_model("music", "Track") + + for mbid in get_duplicates(Artist): + ref = Artist.objects.filter(mbid=mbid).order_by('pk').first() + duplicates = Artist.objects.filter(mbid=mbid).exclude(pk=ref.pk) + Album.objects.filter(artist__in=duplicates).update(artist=ref) + Track.objects.filter(artist__in=duplicates).update(artist=ref) + duplicates.delete() + + for mbid in get_duplicates(Album): + ref = Album.objects.filter(mbid=mbid).order_by('pk').first() + duplicates = Album.objects.filter(mbid=mbid).exclude(pk=ref.pk) + Track.objects.filter(album__in=duplicates).update(album=ref) + duplicates.delete() + +def rewind(*args, **kwargs): + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0004_track_tags'), + ] + + operations = [ + migrations.RunPython(deduplicate, rewind), + ] diff --git a/api/funkwhale_api/music/migrations/0006_unique_mbid.py b/api/funkwhale_api/music/migrations/0006_unique_mbid.py new file mode 100644 index 000000000..e13e3a743 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0006_unique_mbid.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0005_deduplicate'), + ] + + operations = [ + migrations.AlterField( + model_name='album', + name='mbid', + field=models.UUIDField(null=True, editable=False, unique=True, blank=True, db_index=True), + ), + migrations.AlterField( + model_name='artist', + name='mbid', + field=models.UUIDField(null=True, editable=False, unique=True, blank=True, db_index=True), + ), + migrations.AlterField( + model_name='track', + name='mbid', + field=models.UUIDField(null=True, editable=False, unique=True, blank=True, db_index=True), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0007_track_position.py b/api/funkwhale_api/music/migrations/0007_track_position.py new file mode 100644 index 000000000..089e0128f --- /dev/null +++ b/api/funkwhale_api/music/migrations/0007_track_position.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0006_unique_mbid'), + ] + + operations = [ + migrations.AddField( + model_name='track', + name='position', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0008_auto_20160529_1456.py b/api/funkwhale_api/music/migrations/0008_auto_20160529_1456.py new file mode 100644 index 000000000..e7fa5c8f4 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0008_auto_20160529_1456.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0007_track_position'), + ] + + operations = [ + migrations.AlterField( + model_name='album', + name='mbid', + field=models.UUIDField(null=True, db_index=True, unique=True, blank=True), + ), + migrations.AlterField( + model_name='artist', + name='mbid', + field=models.UUIDField(null=True, db_index=True, unique=True, blank=True), + ), + migrations.AlterField( + model_name='track', + name='mbid', + field=models.UUIDField(null=True, db_index=True, unique=True, blank=True), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py b/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py new file mode 100644 index 000000000..2046a7127 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone +import versatileimagefield.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0008_auto_20160529_1456'), + ] + + operations = [ + migrations.CreateModel( + name='Lyrics', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)), + ('url', models.URLField()), + ('content', models.TextField(null=True, blank=True)), + ], + ), + migrations.CreateModel( + name='Work', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)), + ('mbid', models.UUIDField(unique=True, null=True, db_index=True, blank=True)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('language', models.CharField(max_length=20)), + ('nature', models.CharField(max_length=50)), + ('title', models.CharField(max_length=255)), + ], + options={ + 'ordering': ['-creation_date'], + 'abstract': False, + }, + ), + migrations.AddField( + model_name='lyrics', + name='work', + field=models.ForeignKey(related_name='lyrics', to='music.Work', blank=True, null=True), + ), + migrations.AddField( + model_name='track', + name='work', + field=models.ForeignKey(related_name='tracks', to='music.Work', blank=True, null=True), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py b/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py new file mode 100644 index 000000000..03ac05793 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import versatileimagefield.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0009_auto_20160920_1614'), + ] + + operations = [ + migrations.AlterField( + model_name='lyrics', + name='url', + field=models.URLField(unique=True), + ), + ] diff --git a/api/funkwhale_api/music/migrations/0011_rename_files.py b/api/funkwhale_api/music/migrations/0011_rename_files.py new file mode 100644 index 000000000..1c59535f5 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0011_rename_files.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import os + +from django.db import migrations, models +from funkwhale_api.common.utils import rename_file + + +def rename_files(apps, schema_editor): + """ + This migration script is utterly broken and made me redownload all my audio files. + So next time -> Write some actual tests before running a migration script + on thousand of tracks... + """ + return + # TrackFile = apps.get_model("music", "TrackFile") + # qs = TrackFile.objects.select_related( + # 'track__album__artist', 'track__artist') + # total = len(qs) + # + # + # for i, tf in enumerate(qs): + # try: + # new_name = '{} - {} - {}'.format( + # tf.track.artist.name, + # tf.track.album.title, + # tf.track.title, + # ) + # except AttributeError: + # new_name = '{} - {}'.format( + # tf.track.artist.name, + # tf.track.title, + # ) + # rename_file( + # instance=tf, + # field_name='audio_file', + # allow_missing_file=True, + # new_name=new_name) + # print('Renamed file {}/{} (new name: {})'.format( + # i + 1, total, tf.audio_file.name + # )) + + +def rewind(apps, schema_editor): + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0010_auto_20160920_1742'), + ] + + operations = [ + migrations.AlterField( + model_name='trackfile', + name='audio_file', + field=models.FileField(upload_to='tracks/%Y/%m/%d', max_length=255), + ), + migrations.RunPython(rename_files, rewind), + ] diff --git a/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py b/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py new file mode 100644 index 000000000..8d7e25246 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import versatileimagefield.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0011_rename_files'), + ] + + operations = [ + migrations.AlterField( + model_name='album', + name='cover', + field=versatileimagefield.fields.VersatileImageField(null=True, blank=True, upload_to='albums/covers/%Y/%m/%d'), + ), + ] diff --git a/api/funkwhale_api/music/migrations/__init__.py b/api/funkwhale_api/music/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py new file mode 100644 index 000000000..8d4e84a23 --- /dev/null +++ b/api/funkwhale_api/music/models.py @@ -0,0 +1,408 @@ +import os +import io +import arrow +import datetime +import tempfile +import shutil +import markdown + +from django.conf import settings +from django.db import models +from django.contrib.staticfiles.templatetags.staticfiles import static +from django.core.files.base import ContentFile +from django.core.files import File +from django.core.urlresolvers import reverse +from django.utils import timezone +from taggit.managers import TaggableManager +from versatileimagefield.fields import VersatileImageField + +from funkwhale_api.taskapp import celery +from funkwhale_api import downloader +from funkwhale_api import musicbrainz +from . import importers +from . import lyrics as lyrics_utils + + +class APIModelMixin(models.Model): + mbid = models.UUIDField(unique=True, db_index=True, null=True, blank=True) + api_includes = [] + creation_date = models.DateTimeField(default=timezone.now) + import_hooks = [] + class Meta: + abstract = True + ordering = ['-creation_date'] + + @classmethod + def get_or_create_from_api(cls, mbid): + try: + return cls.objects.get(mbid=mbid), False + except cls.DoesNotExist: + return cls.create_from_api(id=mbid), True + + def get_api_data(self): + return self.__class__.api.get(id=self.mbid, includes=self.api_includes)[self.musicbrainz_model] + + @classmethod + def create_from_api(cls, **kwargs): + if kwargs.get('id'): + raw_data = cls.api.get(id=kwargs['id'], includes=cls.api_includes)[cls.musicbrainz_model] + else: + raw_data = cls.api.search(**kwargs)['{0}-list'.format(cls.musicbrainz_model)][0] + cleaned_data = cls.clean_musicbrainz_data(raw_data) + return importers.load(cls, cleaned_data, raw_data, cls.import_hooks) + + @classmethod + def clean_musicbrainz_data(cls, data): + cleaned_data = {} + mapping = importers.Mapping(cls.musicbrainz_mapping) + for key, value in data.items(): + try: + cleaned_key, cleaned_value = mapping.from_musicbrainz(key, value) + cleaned_data[cleaned_key] = cleaned_value + except KeyError as e: + pass + return cleaned_data + +class Artist(APIModelMixin): + name = models.CharField(max_length=255) + + musicbrainz_model = 'artist' + musicbrainz_mapping = { + 'mbid': { + 'musicbrainz_field_name': 'id' + }, + 'name': { + 'musicbrainz_field_name': 'name' + } + } + api = musicbrainz.api.artists + + def __str__(self): + return self.name + + @property + def tags(self): + t = [] + for album in self.albums.all(): + for tag in album.tags: + t.append(tag) + return set(t) + +def import_artist(v): + a = Artist.get_or_create_from_api(mbid=v[0]['artist']['id'])[0] + return a + +def parse_date(v): + if len(v) == 4: + return datetime.date(int(v), 1, 1) + d = arrow.get(v).date() + return d + + +def import_tracks(instance, cleaned_data, raw_data): + for track_data in raw_data['medium-list'][0]['track-list']: + track_cleaned_data = Track.clean_musicbrainz_data(track_data['recording']) + track_cleaned_data['album'] = instance + track_cleaned_data['position'] = int(track_data['position']) + track = importers.load(Track, track_cleaned_data, track_data, Track.import_hooks) + +class Album(APIModelMixin): + title = models.CharField(max_length=255) + artist = models.ForeignKey(Artist, related_name='albums') + release_date = models.DateField(null=True) + cover = VersatileImageField(upload_to='albums/covers/%Y/%m/%d', null=True, blank=True) + TYPE_CHOICES = ( + ('album', 'Album'), + ) + type = models.CharField(choices=TYPE_CHOICES, max_length=30, default='album') + + api_includes = ['artist-credits', 'recordings', 'media'] + api = musicbrainz.api.releases + musicbrainz_model = 'release' + musicbrainz_mapping = { + 'mbid': { + 'musicbrainz_field_name': 'id', + }, + 'position': { + 'musicbrainz_field_name': 'release-list', + 'converter': lambda v: int(v[0]['medium-list'][0]['position']), + }, + 'title': { + 'musicbrainz_field_name': 'title', + }, + 'release_date': { + 'musicbrainz_field_name': 'date', + 'converter': parse_date, + + }, + 'type': { + 'musicbrainz_field_name': 'type', + 'converter': lambda v: v.lower(), + }, + 'artist': { + 'musicbrainz_field_name': 'artist-credit', + 'converter': import_artist, + } + } + + def get_image(self): + image_data = musicbrainz.api.images.get_front(str(self.mbid)) + f = ContentFile(image_data) + self.cover.save('{0}.jpg'.format(self.mbid), f) + return self.cover.file + + def __str__(self): + return self.title + + @property + def tags(self): + t = [] + for track in self.tracks.all(): + for tag in track.tags.all(): + t.append(tag) + return set(t) + +def import_tags(instance, cleaned_data, raw_data): + MINIMUM_COUNT = 2 + tags_to_add = [] + for tag_data in raw_data.get('tag-list', []): + try: + if int(tag_data['count']) < MINIMUM_COUNT: + continue + except ValueError: + continue + tags_to_add.append(tag_data['name']) + instance.tags.add(*tags_to_add) + +def import_album(v): + a = Album.get_or_create_from_api(mbid=v[0]['id'])[0] + return a + + +def link_recordings(instance, cleaned_data, raw_data): + tracks = [ + r['target'] + for r in raw_data['recording-relation-list'] + ] + Track.objects.filter(mbid__in=tracks).update(work=instance) + + +def import_lyrics(instance, cleaned_data, raw_data): + try: + url = [ + url_data + for url_data in raw_data['url-relation-list'] + if url_data['type'] == 'lyrics' + ][0]['target'] + except (IndexError, KeyError): + return + l, _ = Lyrics.objects.get_or_create(work=instance, url=url) + + return l + + +class Work(APIModelMixin): + language = models.CharField(max_length=20) + nature = models.CharField(max_length=50) + title = models.CharField(max_length=255) + + api = musicbrainz.api.works + api_includes = ['url-rels', 'recording-rels'] + musicbrainz_model = 'work' + musicbrainz_mapping = { + 'mbid': { + 'musicbrainz_field_name': 'id' + }, + 'title': { + 'musicbrainz_field_name': 'title' + }, + 'language': { + 'musicbrainz_field_name': 'language', + }, + 'nature': { + 'musicbrainz_field_name': 'type', + 'converter': lambda v: v.lower(), + }, + } + import_hooks = [ + import_lyrics, + link_recordings + ] + + def fetch_lyrics(self): + l = self.lyrics.first() + if l: + return l + data = self.api.get(self.mbid, includes=['url-rels'])['work'] + l = import_lyrics(self, {}, data) + + return l + + +class Lyrics(models.Model): + work = models.ForeignKey(Work, related_name='lyrics', null=True, blank=True) + url = models.URLField(unique=True) + content = models.TextField(null=True, blank=True) + + @celery.app.task(name='Lyrics.fetch_content', filter=celery.task_method) + def fetch_content(self): + html = lyrics_utils._get_html(self.url) + content = lyrics_utils.extract_content(html) + cleaned_content = lyrics_utils.clean_content(content) + self.content = cleaned_content + self.save() + + @property + def content_rendered(self): + return markdown.markdown( + self.content, + safe_mode=True, + enable_attributes=False, + extensions=['markdown.extensions.nl2br']) + + +class Track(APIModelMixin): + title = models.CharField(max_length=255) + artist = models.ForeignKey(Artist, related_name='tracks') + position = models.PositiveIntegerField(null=True, blank=True) + album = models.ForeignKey(Album, related_name='tracks', null=True, blank=True) + work = models.ForeignKey(Work, related_name='tracks', null=True, blank=True) + + musicbrainz_model = 'recording' + api = musicbrainz.api.recordings + api_includes = ['artist-credits', 'releases', 'media', 'tags', 'work-rels'] + musicbrainz_mapping = { + 'mbid': { + 'musicbrainz_field_name': 'id' + }, + 'title': { + 'musicbrainz_field_name': 'title' + }, + 'artist': { + 'musicbrainz_field_name': 'artist-credit', + 'converter': lambda v: Artist.get_or_create_from_api(mbid=v[0]['artist']['id'])[0], + }, + 'album': { + 'musicbrainz_field_name': 'release-list', + 'converter': import_album, + }, + } + import_hooks = [ + import_tags + ] + tags = TaggableManager() + + def __str__(self): + return self.title + + def save(self, **kwargs): + try: + self.artist + except Artist.DoesNotExist: + self.artist = self.album.artist + super().save(**kwargs) + + def get_work(self): + if self.work: + return self.work + data = self.api.get(self.mbid, includes=['work-rels']) + try: + work_data = data['recording']['work-relation-list'][0]['work'] + except (IndexError, KeyError): + return + work, _ = Work.get_or_create_from_api(mbid=work_data['id']) + return work + + def get_lyrics_url(self): + return reverse('api:tracks-lyrics', kwargs={'pk': self.pk}) + + @property + def full_name(self): + try: + return '{} - {} - {}'.format( + self.artist.name, + self.album.title, + self.title, + ) + except AttributeError: + return '{} - {}'.format( + self.artist.name, + self.title, + ) + + +class TrackFile(models.Model): + track = models.ForeignKey(Track, related_name='files') + audio_file = models.FileField(upload_to='tracks/%Y/%m/%d', max_length=255) + source = models.URLField(null=True, blank=True) + duration = models.IntegerField(null=True, blank=True) + + def download_file(self): + # import the track file, since there is not any + # we create a tmp dir for the download + tmp_dir = tempfile.mkdtemp() + data = downloader.download( + self.source, + target_directory=tmp_dir) + self.duration = data.get('duration', None) + self.audio_file.save( + os.path.basename(data['audio_file_path']), + File(open(data['audio_file_path'], 'rb')) + ) + shutil.rmtree(tmp_dir) + return self.audio_file + + @property + def path(self): + if settings.USE_SAMPLE_TRACK: + return static('music/sample1.ogg') + return self.audio_file.url + +class ImportBatch(models.Model): + creation_date = models.DateTimeField(default=timezone.now) + submitted_by = models.ForeignKey('users.User', related_name='imports') + + class Meta: + ordering = ['-creation_date'] + + def __str__(self): + return str(self.pk) + + @property + def status(self): + pending = any([job.status == 'pending' for job in self.jobs.all()]) + if pending: + return 'pending' + return 'finished' + +class ImportJob(models.Model): + batch = models.ForeignKey(ImportBatch, related_name='jobs') + source = models.URLField() + mbid = models.UUIDField(editable=False) + STATUS_CHOICES = ( + ('pending', 'Pending'), + ('finished', 'finished'), + ) + status = models.CharField(choices=STATUS_CHOICES, default='pending', max_length=30) + + @celery.app.task(name='ImportJob.run', filter=celery.task_method) + def run(self, replace=False): + try: + track, created = Track.get_or_create_from_api(mbid=self.mbid) + track_file = None + if replace: + track_file = track.files.first() + elif track.files.count() > 0: + return + + track_file = track_file or TrackFile(track=track, source=self.source) + track_file.download_file() + track_file.save() + self.status = 'finished' + self.save() + return track.pk + + except Exception as exc: + if not settings.DEBUG: + raise ImportJob.run.retry(args=[self], exc=exc, countdown=30, max_retries=3) + raise diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py new file mode 100644 index 000000000..e7d7399ad --- /dev/null +++ b/api/funkwhale_api/music/serializers.py @@ -0,0 +1,96 @@ +from rest_framework import serializers +from taggit.models import Tag + +from . import models + + +class TagSerializer(serializers.ModelSerializer): + class Meta: + model = Tag + fields = ('id', 'name', 'slug') + +class SimpleArtistSerializer(serializers.ModelSerializer): + class Meta: + model = models.Artist + fields = ('id', 'mbid', 'name') + +class ArtistSerializer(serializers.ModelSerializer): + tags = TagSerializer(many=True, read_only=True) + class Meta: + model = models.Artist + fields = ('id', 'mbid', 'name', 'tags') + +class ImportJobSerializer(serializers.ModelSerializer): + class Meta: + model = models.ImportJob + fields = ('id', 'mbid', 'source', 'status') + +class ImportBatchSerializer(serializers.ModelSerializer): + jobs = ImportJobSerializer(many=True, read_only=True) + class Meta: + model = models.ImportBatch + fields = ('id', 'jobs', 'status', 'creation_date') + +class TrackFileSerializer(serializers.ModelSerializer): + class Meta: + model = models.TrackFile + fields = ('id', 'path', 'duration', 'source') + + +class SimpleAlbumSerializer(serializers.ModelSerializer): + + class Meta: + model = models.Album + fields = ('id', 'mbid', 'title', 'release_date', 'cover') + +class AlbumSerializer(serializers.ModelSerializer): + tags = TagSerializer(many=True, read_only=True) + class Meta: + model = models.Album + fields = ('id', 'mbid', 'title', 'cover', 'release_date', 'tags') + + +class LyricsMixin(serializers.ModelSerializer): + lyrics = serializers.SerializerMethodField() + + def get_lyrics(self, obj): + return obj.get_lyrics_url() + + +class TrackSerializer(LyricsMixin): + files = TrackFileSerializer(many=True, read_only=True) + tags = TagSerializer(many=True, read_only=True) + class Meta: + model = models.Track + fields = ('id', 'mbid', 'title', 'artist', 'files', 'tags', 'lyrics') + +class TrackSerializerNested(LyricsMixin): + artist = ArtistSerializer() + files = TrackFileSerializer(many=True, read_only=True) + album = SimpleAlbumSerializer(read_only=True) + tags = TagSerializer(many=True, read_only=True) + class Meta: + model = models.Track + fields = ('id', 'mbid', 'title', 'artist', 'files', 'album', 'tags', 'lyrics') + +class AlbumSerializerNested(serializers.ModelSerializer): + tracks = TrackSerializer(many=True, read_only=True) + artist = SimpleArtistSerializer() + tags = TagSerializer(many=True, read_only=True) + + class Meta: + model = models.Album + fields = ('id', 'mbid', 'title', 'cover', 'artist', 'release_date', 'tracks', 'tags') + +class ArtistSerializerNested(serializers.ModelSerializer): + albums = AlbumSerializerNested(many=True, read_only=True) + tags = TagSerializer(many=True, read_only=True) + class Meta: + model = models.Artist + fields = ('id', 'mbid', 'name', 'albums', 'tags') + + +class LyricsSerializer(serializers.ModelSerializer): + class Meta: + model = models.Lyrics + fields = ('id', 'work', 'content', 'content_rendered') diff --git a/api/funkwhale_api/music/tests/__init__.py b/api/funkwhale_api/music/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/music/tests/cover.py b/api/funkwhale_api/music/tests/cover.py new file mode 100644 index 000000000..401bc1052 --- /dev/null +++ b/api/funkwhale_api/music/tests/cover.py @@ -0,0 +1 @@ +binary_data = b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x01\x00H\x00H\x00\x00\xff\xed\x08\xaePhotoshop 3.0\x008BIM\x03\xe9\x00\x00\x00\x00\x00x\x00\x03\x00\x00\x00H\x00H\x00\x00\x00\x00\x02\xd8\x02(\xff\xe1\xff\xe2\x02\xf9\x02F\x03G\x05(\x03\xfc\x00\x02\x00\x00\x00H\x00H\x00\x00\x00\x00\x02\xd8\x02(\x00\x01\x00\x00\x00d\x00\x00\x00\x01\x00\x03\x03\x03\x00\x00\x00\x01\'\x0f\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x08\x00\x19\x01\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00H\x00\x00\x00\x01\x00\x01\x00H\x00\x00\x00\x01\x00\x018BIM\x03\xf3\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x008BIM\x04\n\x00\x00\x00\x00\x00\x01\x00\x008BIM\'\x10\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\x00\x00\x00\x028BIM\x03\xf5\x00\x00\x00\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00-\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\x00\x00\x02\x00\x018BIM\x04\x02\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x008BIM\x04\t\x00\x00\x00\x00\x06\x9b\x00\x00\x00\x01\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x01\x80\x00\x00\xc0\x00\x00\x00\x06\x7f\x00\x18\x00\x01\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x01\x00H\x00H\x00\x00\xff\xfe\x00\'File written by Adobe Photoshop\xa8 4.0\x00\xff\xee\x00\x0eAdobe\x00d\x80\x00\x00\x00\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\t\x08\x0c\t\t\x0c\x11\x0b\n\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\r\x0b\x0b\r\x0e\r\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x00\x80\x00\x80\x03\x01"\x00\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x08\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\t\n\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x10\x00\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\x00\x02\x11\x03\x04!\x121\x05AQa\x13"q\x812\x06\x14\x91\xa1\xb1B#$\x15R\xc1b34r\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\x83&D\x93TdE\xc2\xa3t6\x17\xd2U\xe2e\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\'\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\x055\x01\x00\x02\x11\x03!1\x12\x04AQaq"\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$b\xe1r\x82\x92CS\x15cs4\xf1%\x06\x16\xa2\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17dEU6te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\'7GWgw\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf5T\x92I%)$\x92IJI$\x92R\x92I$\x94\xa4\x92I%)$\x92IJI$\x92R\x92I$\x94\xff\x00\xff\xd0\xf5T\x92I%)$\x92IJI%\xe7\xff\x00Z\x7f\xc6\xbf\xfc\xde\xeb\xb9]\x1f\xf6_\xda~\xcd\xe9\xfe\x9b\xed\x1e\x9e\xefR\xba\xef\xfeo\xec\xf6\xed\xdb\xea\xec\xfeq%>\x80\x92\xf2\xaf\xfc}?\xf3I\xff\x00\xb3_\xfb\xe8\x97\xfe>\x9f\xf9\xa4\xff\x00\xd9\xaf\xfd\xf4IO\xaa\xa4\xbc\xab\xff\x00\x1fO\xfc\xd2\x7f\xec\xd7\xfe\xfa%\xff\x00\x8f\xa7\xfei?\xf6k\xff\x00}\x12S\xea\xa9.+\xeaW\xf8\xc8\xff\x00\x9d}V\xde\x9d\xfb;\xec~\x96;\xb2=O[\xd5\x9d\xaf\xaa\xad\x9b=\n\x7f\xd3}-\xeb\xb5IJI$\x92R\x92I$\x94\xff\x00\xff\xd1\xf5T\x92I%)$\x97\x9f\xff\x00\x8d\x7f\xad=w\xea\xf7\xec\xbf\xd8\xf9_f\xfbO\xda=o\xd1\xd7f\xefO\xec\xfe\x9f\xf3\xf5\xdb\xb7o\xabg\xd0IO\xa0/\x9f\xff\x00\xc6\x97\xfe.\xfa\x9f\xfdc\xff\x00m\xf1\xd2\xff\x00\xc7K\xeb\xdf\xfeY\xff\x00\xe0\x18\xff\x00\xfb\xce\xb9\xfe\xa9\xd53\xfa\xbe}\xbdG\xa8\xdb\xeb\xe5\xdf\xb7\xd4\xb3kY;\x1a\xda\x99\xec\xa9\xac\xaf\xf9\xb63\xf3\x12SU$\x92IJI$\x92S\xdf\xff\x00\x89O\xfcUe\x7f\xe1\x0b?\xf3\xf6*\xf6\xb5\xf3/D\xeb\xfd[\xa0\xe5?3\xa4\xdf\xf6l\x8b+59\xfb\x18\xf9a-\xb1\xcd\xdb{-g\xd3\xa9\x8bk\xff\x00\x1d/\xaf\x7f\xf9g\xff\x00\x80c\xff\x00\xef:J~\x80Iq\xff\x00\xe2\xbf\xaf\xf5n\xbd\xd023:\xb5\xff\x00i\xc8\xaf-\xf55\xfb\x18\xc8`\xae\x8b\x1a\xdd\xb42\xa6};^\xbb\x04\x94\xa4\x92I%?\xff\xd2\xf5T\x92I%)yW\xf8\xf4\xff\x00\xbcO\xfd\n\xff\x00\xddE\xea\xab\xca\xbf\xc7\xa7\xfd\xe2\x7f\xe8W\xfe\xea$\xa7\xca\x92I$\x94\xa4\x92I%)$\x92IJI$\x92S\xed_\xe2S\xff\x00\x12\xb9_\xf8~\xcf\xfc\xf3\x8a\xbd\x01y\xff\x00\xf8\x94\xff\x00\xc4\xaeW\xfe\x1f\xb3\xff\x00<\xe2\xaf@IJI$\x92S\xff\xd3\xf5T\x92I%)yW\xf8\xf4\xff\x00\xbcO\xfd\n\xff\x00\xddE\xea\xab\xca\xbf\xc7\xa7\xfd\xe2\x7f\xe8W\xfe\xea$\xa7\xca\x92I$\x94\xa4\x92I%)$\x92IJI$\x92S\xed_\xe2S\xff\x00\x12\xb9_\xf8~\xcf\xfc\xf3\x8a\xbd\x01y\xff\x00\xf8\x94\xff\x00\xc4\xaeW\xfe\x1f\xb3\xff\x00<\xe2\xaf@IJI$\x92S\xff\xd4\xf5T\x92I%)q_\xe3#\xeaWU\xfa\xd7\xfb;\xf6u\xb8\xf5}\x8f\xd6\xf5>\xd0\xe7\xb6}_Cf\xcfJ\xab\xbf\xd0\xbfr\xedRIO\x8a\x7f\xe3)\xf5\xab\xfe\xe5`\x7f\xdb\x97\x7f\xef*\xe4:\xff\x00D\xca\xe8=Z\xfe\x93\x98\xfa\xec\xc8\xc6\xd9\xbd\xd5\x12Xw\xb1\x97\xb7k\xacmO\xfa\x16\xfe\xe2\xfai|\xff\x00\xfe4\xbf\xf1w\xd4\xff\x00\xeb\x1f\xfbo\x8e\x92\x9eU$\x92IJI$\x92S\xb1\xf5_\xea\xbfP\xfa\xd1\xd4,\xc0\xc0\xb2\x9a\xad\xaa\x93{\x9dys[\xb5\xae\xae\xa2\x01\xaa\xbb\x9d\xbfu\xcd\xfc\xd5\xd3\xff\x00\xe3)\xf5\xab\xfe\xe5`\x7f\xdb\x97\x7f\xef*_\xe2S\xff\x00\x15Y_\xf8B\xcf\xfc\xfd\x8a\xbd\xad%<\xbf\xf8\xbc\xfa\xaf\xd4>\xab\xf4[\xb03\xec\xa6\xdbm\xc9u\xedu\x05\xcen\xd7WM@\x13mt\xbb~\xea]\xf9\xab\xa8I$\x94\xa4\x92I%?\xff\xd5\xf5T\x92I%)$\x92IJ\\\x7f_\xff\x00\x15\xfd\x03\xafuk\xfa\xb6fF]y\x19;7\xb6\xa7\xd6\x1861\x947kl\xa2\xd7\xfd\n\xbf}v\t$\xa7\xcf\xff\x00\xf1\x94\xfa\xab\xff\x00r\xb3\xff\x00\xed\xca\x7f\xf7\x95/\xfce>\xaa\xff\x00\xdc\xac\xff\x00\xfbr\x9f\xfd\xe5^\x80\x92J|\xff\x00\xff\x00\x19O\xaa\xbf\xf7+?\xfe\xdc\xa7\xff\x00yR\xff\x00\xc6S\xea\xaf\xfd\xca\xcf\xff\x00\xb7)\xff\x00\xdeU\xe8\t$\xa7\x97\xfa\xaf\xfe/:/\xd5~\xa1f~\x05\xd96\xdbm&\x876\xf7V\xe6\xeds\xab\xb4\x90*\xa6\x97o\xddK\x7f9u\t$\x92\x94\x92I$\xa5$\x92I)\xff\xd6\xf5T\x92I%)$\x92IJI$\x92R\x92I$\x94\xa4\x92I%)$\x92IJI$\x92R\x92I$\x94\xff\x00\xff\xd9\x008BIM\x04\x06\x00\x00\x00\x00\x00\x07\x00\x03\x00\x00\x00\x01\x01\x00\xff\xfe\x00\'File written by Adobe Photoshop\xa8 4.0\x00\xff\xee\x00\x0eAdobe\x00d\x00\x00\x00\x00\x01\xff\xdb\x00\x84\x00\n\x07\x07\x07\x08\x07\n\x08\x08\n\x0f\n\x08\n\x0f\x12\r\n\n\r\x12\x14\x10\x10\x12\x10\x10\x14\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0b\x0c\x0c\x15\x13\x15"\x18\x18"\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x00\t\x00\t\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x02\xff\xc4\x01\xa2\x00\x00\x00\x07\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x04\x05\x03\x02\x06\x01\x00\x07\x08\t\n\x0b\x01\x00\x02\x02\x03\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x10\x00\x02\x01\x03\x03\x02\x04\x02\x06\x07\x03\x04\x02\x06\x02s\x01\x02\x03\x11\x04\x00\x05!\x121AQ\x06\x13a"q\x81\x142\x91\xa1\x07\x15\xb1B#\xc1R\xd1\xe13\x16b\xf0$r\x82\xf1%C4S\x92\xa2\xb2cs\xc25D\'\x93\xa3\xb36\x17Tdt\xc3\xd2\xe2\x08&\x83\t\n\x18\x19\x84\x94EF\xa4\xb4V\xd3U(\x1a\xf2\xe3\xf3\xc4\xd4\xe4\xf4eu\x85\x95\xa5\xb5\xc5\xd5\xe5\xf5fv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\xf78HXhx\x88\x98\xa8\xb8\xc8\xd8\xe8\xf8)9IYiy\x89\x99\xa9\xb9\xc9\xd9\xe9\xf9*:JZjz\x8a\x9a\xaa\xba\xca\xda\xea\xfa\x11\x00\x02\x02\x01\x02\x03\x05\x05\x04\x05\x06\x04\x08\x03\x03m\x01\x00\x02\x11\x03\x04!\x121A\x05Q\x13a"\x06q\x81\x912\xa1\xb1\xf0\x14\xc1\xd1\xe1#B\x15Rbr\xf13$4C\x82\x16\x92S%\xa2c\xb2\xc2\x07s\xd25\xe2D\x83\x17T\x93\x08\t\n\x18\x19&6E\x1a\'dtU7\xf2\xa3\xb3\xc3()\xd3\xe3\xf3\x84\x94\xa4\xb4\xc4\xd4\xe4\xf4eu\x85\x95\xa5\xb5\xc5\xd5\xe5\xf5FVfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\xf78HXhx\x88\x98\xa8\xb8\xc8\xd8\xe8\xf89IYiy\x89\x99\xa9\xb9\xc9\xd9\xe9\xf9*:JZjz\x8a\x9a\xaa\xba\xca\xda\xea\xfa\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\x91\xea\xfa\xbf\xe6D_\x99\x16\x96\x16\x16\x8c\xdeWf\x84;\x88U\xa1hY\x7f\xd3\'\x9e\xf3\xedCq\x0bz\xfe\x94^\xbc?\xdc\xdb\xff\x00\xa3\xcd\xeb\x7f\xa4\xaa\xf4 + + + + + + + + + + + + + + + + + + + + + + +System Of A Down:Chop Suey! Lyrics - LyricWikia - Wikia + + +
+We're rolling "Suicide".

Wake up (wake up)
Grab a brush and put on a little makeup
Hide the scars to fade away the shakeup (hide the scars to fade away the)
Why'd you leave the keys upon the table?
Here you go, create another fable

You wanted to
Grab a brush and put a little makeup
You wanted to
Hide the scars to fade away the shakeup
You wanted to
Why'd you leave the keys upon the table?
You wanted to

I don't think you trust
In my self-righteous suicide
I cry when angels deserve to die

Wake up (wake up)
Grab a brush and put on a little makeup
Hide the scars to fade away the (hide the scars to fade away the)
Why'd you leave the keys upon the table?
Here you go, create another fable

You wanted to
Grab a brush and put a little makeup
You wanted to
Hide the scars to fade away the shakeup
You wanted to
Why'd you leave the keys upon the table?
You wanted to

I don't think you trust
In my self-righteous suicide
I cry when angels deserve to die
In my self-righteous suicide
I cry when angels deserve to die

Father (father)
Father (father)
Father (father)
Father (father)
Father, into your hands I commit my spirit
Father, into your hands

Why have you forsaken me?
In your eyes forsaken me
In your thoughts forsaken me
In your heart forsaken me, oh

Trust in my self-righteous suicide
I cry when angels deserve to die
In my self-righteous suicide
I cry when angels deserve to die +
+ + +""" diff --git a/api/funkwhale_api/music/tests/test.ogg b/api/funkwhale_api/music/tests/test.ogg new file mode 100644 index 000000000..bf480acde Binary files /dev/null and b/api/funkwhale_api/music/tests/test.ogg differ diff --git a/api/funkwhale_api/music/tests/test_api.py b/api/funkwhale_api/music/tests/test_api.py new file mode 100644 index 000000000..ff3deedf3 --- /dev/null +++ b/api/funkwhale_api/music/tests/test_api.py @@ -0,0 +1,216 @@ +import json +import unittest +from test_plus.test import TestCase +from django.core.urlresolvers import reverse + +from funkwhale_api.music import models +from funkwhale_api.utils.tests import TMPDirTestCaseMixin +from funkwhale_api.musicbrainz import api +from funkwhale_api.music import serializers +from funkwhale_api.users.models import User + +from . import data as api_data + +class TestAPI(TMPDirTestCaseMixin, TestCase): + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['adhesive_wombat']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.get', return_value=api_data.albums['get']['marsupial']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.get', return_value=api_data.tracks['get']['8bitadventures']) + @unittest.mock.patch('funkwhale_api.music.models.TrackFile.download_file', return_value=None) + def test_can_submit_youtube_url_for_track_import(self, *mocks): + mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed' + video_id = 'tPEE9ZwTmy0' + url = reverse('api:submit-single') + user = User.objects.create_superuser(username='test', email='test@test.com', password='test') + self.client.login(username=user.username, password='test') + response = self.client.post(url, {'import_url': 'https://www.youtube.com/watch?v={0}'.format(video_id), 'mbid': mbid}) + track = models.Track.objects.get(mbid=mbid) + self.assertEqual(track.artist.name, 'Adhesive Wombat') + self.assertEqual(track.album.title, 'Marsupial Madness') + # self.assertIn(video_id, track.files.first().audio_file.name) + + def test_import_creates_an_import_with_correct_data(self): + user = User.objects.create_superuser(username='test', email='test@test.com', password='test') + mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed' + video_id = 'tPEE9ZwTmy0' + url = reverse('api:submit-single') + self.client.login(username=user.username, password='test') + with self.settings(CELERY_ALWAYS_EAGER=False): + response = self.client.post(url, {'import_url': 'https://www.youtube.com/watch?v={0}'.format(video_id), 'mbid': mbid}) + + batch = models.ImportBatch.objects.latest('id') + self.assertEqual(batch.jobs.count(), 1) + self.assertEqual(batch.submitted_by, user) + self.assertEqual(batch.status, 'pending') + job = batch.jobs.first() + self.assertEqual(str(job.mbid), mbid) + self.assertEqual(job.status, 'pending') + self.assertEqual(job.source, 'https://www.youtube.com/watch?v={0}'.format(video_id)) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['soad']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.images.get_front', return_value=b'') + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.get', return_value=api_data.albums['get_with_includes']['hypnotize']) + def test_can_import_whole_album(self, *mocks): + user = User.objects.create_superuser(username='test', email='test@test.com', password='test') + payload = { + 'releaseId': '47ae093f-1607-49a3-be11-a15d335ccc94', + 'tracks': [ + { + 'mbid': '1968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=1111111111', + }, + { + 'mbid': '2968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=2222222222', + }, + { + 'mbid': '3968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=3333333333', + }, + ] + } + url = reverse('api:submit-album') + self.client.login(username=user.username, password='test') + with self.settings(CELERY_ALWAYS_EAGER=False): + response = self.client.post(url, json.dumps(payload), content_type="application/json") + + batch = models.ImportBatch.objects.latest('id') + self.assertEqual(batch.jobs.count(), 3) + self.assertEqual(batch.submitted_by, user) + self.assertEqual(batch.status, 'pending') + + album = models.Album.objects.latest('id') + self.assertEqual(str(album.mbid), '47ae093f-1607-49a3-be11-a15d335ccc94') + medium_data = api_data.albums['get_with_includes']['hypnotize']['release']['medium-list'][0] + self.assertEqual(int(medium_data['track-count']), album.tracks.all().count()) + + for track in medium_data['track-list']: + instance = models.Track.objects.get(mbid=track['recording']['id']) + self.assertEqual(instance.title, track['recording']['title']) + self.assertEqual(instance.position, int(track['position'])) + self.assertEqual(instance.title, track['recording']['title']) + + for row in payload['tracks']: + job = models.ImportJob.objects.get(mbid=row['mbid']) + self.assertEqual(str(job.mbid), row['mbid']) + self.assertEqual(job.status, 'pending') + self.assertEqual(job.source, row['source']) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['soad']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.images.get_front', return_value=b'') + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.get', return_value=api_data.albums['get_with_includes']['hypnotize']) + def test_can_import_whole_artist(self, *mocks): + user = User.objects.create_superuser(username='test', email='test@test.com', password='test') + payload = { + 'artistId': 'mbid', + 'albums': [ + { + 'releaseId': '47ae093f-1607-49a3-be11-a15d335ccc94', + 'tracks': [ + { + 'mbid': '1968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=1111111111', + }, + { + 'mbid': '2968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=2222222222', + }, + { + 'mbid': '3968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=3333333333', + }, + ] + } + ] + } + url = reverse('api:submit-artist') + self.client.login(username=user.username, password='test') + with self.settings(CELERY_ALWAYS_EAGER=False): + response = self.client.post(url, json.dumps(payload), content_type="application/json") + + batch = models.ImportBatch.objects.latest('id') + self.assertEqual(batch.jobs.count(), 3) + self.assertEqual(batch.submitted_by, user) + self.assertEqual(batch.status, 'pending') + + album = models.Album.objects.latest('id') + self.assertEqual(str(album.mbid), '47ae093f-1607-49a3-be11-a15d335ccc94') + medium_data = api_data.albums['get_with_includes']['hypnotize']['release']['medium-list'][0] + self.assertEqual(int(medium_data['track-count']), album.tracks.all().count()) + + for track in medium_data['track-list']: + instance = models.Track.objects.get(mbid=track['recording']['id']) + self.assertEqual(instance.title, track['recording']['title']) + self.assertEqual(instance.position, int(track['position'])) + self.assertEqual(instance.title, track['recording']['title']) + + for row in payload['albums'][0]['tracks']: + job = models.ImportJob.objects.get(mbid=row['mbid']) + self.assertEqual(str(job.mbid), row['mbid']) + self.assertEqual(job.status, 'pending') + self.assertEqual(job.source, row['source']) + + def test_user_can_query_api_for_his_own_batches(self): + user1 = User.objects.create_superuser(username='test1', email='test1@test.com', password='test') + user2 = User.objects.create_superuser(username='test2', email='test2@test.com', password='test') + mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed' + source = 'https://www.youtube.com/watch?v=tPEE9ZwTmy0' + + batch = models.ImportBatch.objects.create(submitted_by=user1) + job = models.ImportJob.objects.create(batch=batch, mbid=mbid, source=source) + + url = reverse('api:import-batches-list') + + self.client.login(username=user2.username, password='test') + response2 = self.client.get(url) + self.assertJSONEqual(response2.content.decode('utf-8'), '{"count":0,"next":null,"previous":null,"results":[]}') + self.client.logout() + + self.client.login(username=user1.username, password='test') + response1 = self.client.get(url) + self.assertIn(mbid, response1.content.decode('utf-8')) + + def test_can_search_artist(self): + artist1 = models.Artist.objects.create(name='Test1') + artist2 = models.Artist.objects.create(name='Test2') + query = 'test1' + expected = '[{0}]'.format(json.dumps(serializers.ArtistSerializerNested(artist1).data)) + url = self.reverse('api:artists-search') + response = self.client.get(url + '?query={0}'.format(query)) + + self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8'))) + + def test_can_search_tracks(self): + artist1 = models.Artist.objects.create(name='Test1') + artist2 = models.Artist.objects.create(name='Test2') + track1 = models.Track.objects.create(artist=artist1, title="test_track1") + track2 = models.Track.objects.create(artist=artist2, title="test_track2") + query = 'test track 1' + expected = '[{0}]'.format(json.dumps(serializers.TrackSerializerNested(track1).data)) + url = self.reverse('api:tracks-search') + response = self.client.get(url + '?query={0}'.format(query)) + + self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8'))) + + def test_can_restrict_api_views_to_authenticated_users(self): + urls = [ + ('api:tags-list', 'get'), + ('api:tracks-list', 'get'), + ('api:artists-list', 'get'), + ('api:albums-list', 'get'), + ] + + for route_name, method in urls: + url = self.reverse(route_name) + with self.settings(API_AUTHENTICATION_REQUIRED=True): + response = getattr(self.client, method)(url) + self.assertEqual(response.status_code, 401) + + user = User.objects.create_superuser(username='test', email='test@test.com', password='test') + self.client.login(username=user.username, password='test') + + for route_name, method in urls: + url = self.reverse(route_name) + with self.settings(API_AUTHENTICATION_REQUIRED=False): + response = getattr(self.client, method)(url) + self.assertEqual(response.status_code, 200) diff --git a/api/funkwhale_api/music/tests/test_lyrics.py b/api/funkwhale_api/music/tests/test_lyrics.py new file mode 100644 index 000000000..f74ecb2ef --- /dev/null +++ b/api/funkwhale_api/music/tests/test_lyrics.py @@ -0,0 +1,75 @@ +import json +import unittest +from test_plus.test import TestCase +from django.core.urlresolvers import reverse +from model_mommy import mommy + +from funkwhale_api.music import models +from funkwhale_api.musicbrainz import api +from funkwhale_api.music import serializers +from funkwhale_api.users.models import User + +from .mocking import lyricswiki +from . import data as api_data +from funkwhale_api.music import lyrics as lyrics_utils + +class TestLyrics(TestCase): + + @unittest.mock.patch('funkwhale_api.music.lyrics._get_html', + return_value=lyricswiki.content) + def test_works_import_lyrics_if_any(self, *mocks): + lyrics = mommy.make( + models.Lyrics, + url='http://lyrics.wikia.com/System_Of_A_Down:Chop_Suey!') + + lyrics.fetch_content() + self.assertIn( + 'Grab a brush and put on a little makeup', + lyrics.content, + ) + + def test_clean_content(self): + c = """
Hello
Is it me you're looking for?
""" + d = lyrics_utils.extract_content(c) + d = lyrics_utils.clean_content(d) + + expected = """Hello +Is it me you're looking for? +""" + self.assertEqual(d, expected) + + def test_markdown_rendering(self): + content = """Hello +Is it me you're looking for?""" + + l = mommy.make(models.Lyrics, content=content) + + expected = "

Hello
Is it me you're looking for?

" + self.assertHTMLEqual(expected, l.content_rendered) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.works.get', + return_value=api_data.works['get']['chop_suey']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.get', + return_value=api_data.tracks['get']['chop_suey']) + @unittest.mock.patch('funkwhale_api.music.lyrics._get_html', + return_value=lyricswiki.content) + def test_works_import_lyrics_if_any(self, *mocks): + track = mommy.make( + models.Track, + work=None, + mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448') + + url = reverse('api:tracks-lyrics', kwargs={'pk': track.pk}) + user = User.objects.create_user( + username='test', email='test@test.com', password='test') + self.client.login(username=user.username, password='test') + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + + track.refresh_from_db() + lyrics = models.Lyrics.objects.latest('id') + work = models.Work.objects.latest('id') + + self.assertEqual(track.work, work) + self.assertEqual(lyrics.work, work) diff --git a/api/funkwhale_api/music/tests/test_metadata.py b/api/funkwhale_api/music/tests/test_metadata.py new file mode 100644 index 000000000..7832baedb --- /dev/null +++ b/api/funkwhale_api/music/tests/test_metadata.py @@ -0,0 +1,27 @@ +import unittest +import os +from test_plus.test import TestCase +from funkwhale_api.music import metadata + +DATA_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class TestMetadata(TestCase): + + def test_can_get_metadata_from_file(self, *mocks): + path = os.path.join(DATA_DIR, 'test.ogg') + data = metadata.Metadata(path) + + self.assertEqual( + data.get('musicbrainz_albumid'), + 'a766da8b-8336-47aa-a3ee-371cc41ccc75') + self.assertEqual( + data.get('musicbrainz_trackid'), + 'bd21ac48-46d8-4e78-925f-d9cc2a294656') + self.assertEqual( + data.get('musicbrainz_artistid'), + '013c8e5b-d72a-4cd3-8dee-6c64d6125823') + + self.assertEqual(data.release, data.get('musicbrainz_albumid')) + self.assertEqual(data.artist, data.get('musicbrainz_artistid')) + self.assertEqual(data.recording, data.get('musicbrainz_trackid')) diff --git a/api/funkwhale_api/music/tests/test_music.py b/api/funkwhale_api/music/tests/test_music.py new file mode 100644 index 000000000..cc01bc9ed --- /dev/null +++ b/api/funkwhale_api/music/tests/test_music.py @@ -0,0 +1,115 @@ +from test_plus.test import TestCase +import unittest.mock +from funkwhale_api.music import models +import datetime +from model_mommy import mommy +from . import data as api_data +from .cover import binary_data + +def prettyprint(d): + import json + print(json.dumps(d, sort_keys=True, indent=4)) + +class TestMusic(TestCase): + + @unittest.mock.patch('musicbrainzngs.search_artists', return_value=api_data.artists['search']['adhesive_wombat']) + def test_can_create_artist_from_api(self, *mocks): + artist = models.Artist.create_from_api(query="Adhesive wombat") + data = models.Artist.api.search(query='Adhesive wombat')['artist-list'][0] + + self.assertEqual(int(data['ext:score']), 100) + self.assertEqual(data['id'], '62c3befb-6366-4585-b256-809472333801') + self.assertEqual(artist.mbid, data['id']) + self.assertEqual(artist.name, 'Adhesive Wombat') + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.search', return_value=api_data.albums['search']['hypnotize']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['soad']) + def test_can_create_album_from_api(self, *mocks): + album = models.Album.create_from_api(query="Hypnotize", artist='system of a down', type='album') + data = models.Album.api.search(query='Hypnotize', artist='system of a down', type='album')['release-list'][0] + + self.assertEqual(album.mbid, data['id']) + self.assertEqual(album.title, 'Hypnotize') + with self.assertRaises(ValueError): + self.assertFalse(album.cover.path is None) + self.assertEqual(album.release_date, datetime.date(2005, 1, 1)) + self.assertEqual(album.artist.name, 'System of a Down') + self.assertEqual(album.artist.mbid, data['artist-credit'][0]['artist']['id']) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['adhesive_wombat']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.get', return_value=api_data.albums['get']['marsupial']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.search', return_value=api_data.tracks['search']['8bitadventures']) + def test_can_create_track_from_api(self, *mocks): + track = models.Track.create_from_api(query="8-bit adventure") + data = models.Track.api.search(query='8-bit adventure')['recording-list'][0] + self.assertEqual(int(data['ext:score']), 100) + self.assertEqual(data['id'], '9968a9d6-8d92-4051-8f76-674e157b6eed') + self.assertEqual(track.mbid, data['id']) + self.assertTrue(track.artist.pk is not None) + self.assertEqual(str(track.artist.mbid), '62c3befb-6366-4585-b256-809472333801') + self.assertEqual(track.artist.name, 'Adhesive Wombat') + self.assertEqual(str(track.album.mbid), 'a50d2a81-2a50-484d-9cb4-b9f6833f583e') + self.assertEqual(track.album.title, 'Marsupial Madness') + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['adhesive_wombat']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.get', return_value=api_data.albums['get']['marsupial']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.get', return_value=api_data.tracks['get']['8bitadventures']) + def test_can_create_track_from_api_with_corresponding_tags(self, *mocks): + track = models.Track.create_from_api(id='9968a9d6-8d92-4051-8f76-674e157b6eed') + expected_tags = ['techno', 'good-music'] + track_tags = [tag.slug for tag in track.tags.all()] + for tag in expected_tags: + self.assertIn(tag, track_tags) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.artists.get', return_value=api_data.artists['get']['adhesive_wombat']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.releases.get', return_value=api_data.albums['get']['marsupial']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.search', return_value=api_data.tracks['search']['8bitadventures']) + def test_can_get_or_create_track_from_api(self, *mocks): + track = models.Track.create_from_api(query="8-bit adventure") + data = models.Track.api.search(query='8-bit adventure')['recording-list'][0] + self.assertEqual(int(data['ext:score']), 100) + self.assertEqual(data['id'], '9968a9d6-8d92-4051-8f76-674e157b6eed') + self.assertEqual(track.mbid, data['id']) + self.assertTrue(track.artist.pk is not None) + self.assertEqual(str(track.artist.mbid), '62c3befb-6366-4585-b256-809472333801') + self.assertEqual(track.artist.name, 'Adhesive Wombat') + + track2, created = models.Track.get_or_create_from_api(mbid=data['id']) + self.assertFalse(created) + self.assertEqual(track, track2) + + def test_album_tags_deduced_from_tracks_tags(self): + tag = mommy.make('taggit.Tag') + album = mommy.make('music.Album') + tracks = mommy.make('music.Track', album=album, _quantity=5) + + for track in tracks: + track.tags.add(tag) + + album = models.Album.objects.prefetch_related('tracks__tags').get(pk=album.pk) + + with self.assertNumQueries(0): + self.assertIn(tag, album.tags) + + def test_artist_tags_deduced_from_album_tags(self): + tag = mommy.make('taggit.Tag') + artist = mommy.make('music.Artist') + album = mommy.make('music.Album', artist=artist) + tracks = mommy.make('music.Track', album=album, _quantity=5) + + for track in tracks: + track.tags.add(tag) + + artist = models.Artist.objects.prefetch_related('albums__tracks__tags').get(pk=artist.pk) + + with self.assertNumQueries(0): + self.assertIn(tag, artist.tags) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.images.get_front', return_value=binary_data) + def test_can_download_image_file_for_album(self, *mocks): + # client._api.get_image_front('55ea4f82-b42b-423e-a0e5-290ccdf443ed') + album = mommy.make('music.Album', mbid='55ea4f82-b42b-423e-a0e5-290ccdf443ed') + album.get_image() + album.save() + + self.assertEqual(album.cover.file.read(), binary_data) diff --git a/api/funkwhale_api/music/tests/test_works.py b/api/funkwhale_api/music/tests/test_works.py new file mode 100644 index 000000000..84cb51cde --- /dev/null +++ b/api/funkwhale_api/music/tests/test_works.py @@ -0,0 +1,66 @@ +import json +import unittest +from test_plus.test import TestCase +from django.core.urlresolvers import reverse +from model_mommy import mommy + +from funkwhale_api.music import models +from funkwhale_api.musicbrainz import api +from funkwhale_api.music import serializers +from funkwhale_api.users.models import User + +from . import data as api_data + +class TestWorks(TestCase): + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.works.get', + return_value=api_data.works['get']['chop_suey']) + def test_can_import_work(self, *mocks): + recording = mommy.make( + models.Track, mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448') + mbid = 'e2ecabc4-1b9d-30b2-8f30-3596ec423dc5' + work = models.Work.create_from_api(id=mbid) + + self.assertEqual(work.title, 'Chop Suey!') + self.assertEqual(work.nature, 'song') + self.assertEqual(work.language, 'eng') + self.assertEqual(work.mbid, mbid) + + # a imported work should also be linked to corresponding recordings + + recording.refresh_from_db() + self.assertEqual(recording.work, work) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.works.get', + return_value=api_data.works['get']['chop_suey']) + @unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.get', + return_value=api_data.tracks['get']['chop_suey']) + def test_can_get_work_from_recording(self, *mocks): + recording = mommy.make( + models.Track, + work=None, + mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448') + mbid = 'e2ecabc4-1b9d-30b2-8f30-3596ec423dc5' + + self.assertEqual(recording.work, None) + + work = recording.get_work() + + self.assertEqual(work.title, 'Chop Suey!') + self.assertEqual(work.nature, 'song') + self.assertEqual(work.language, 'eng') + self.assertEqual(work.mbid, mbid) + + recording.refresh_from_db() + self.assertEqual(recording.work, work) + + @unittest.mock.patch('funkwhale_api.musicbrainz.api.works.get', + return_value=api_data.works['get']['chop_suey']) + def test_works_import_lyrics_if_any(self, *mocks): + mbid = 'e2ecabc4-1b9d-30b2-8f30-3596ec423dc5' + work = models.Work.create_from_api(id=mbid) + + lyrics = models.Lyrics.objects.latest('id') + self.assertEqual(lyrics.work, work) + self.assertEqual( + lyrics.url, 'http://lyrics.wikia.com/System_Of_A_Down:Chop_Suey!') diff --git a/api/funkwhale_api/music/utils.py b/api/funkwhale_api/music/utils.py new file mode 100644 index 000000000..32b1aeb47 --- /dev/null +++ b/api/funkwhale_api/music/utils.py @@ -0,0 +1,37 @@ +import re + +from django.db.models import Q + +def normalize_query(query_string, + findterms=re.compile(r'"([^"]+)"|(\S+)').findall, + normspace=re.compile(r'\s{2,}').sub): + ''' Splits the query string in invidual keywords, getting rid of unecessary spaces + and grouping quoted words together. + Example: + + >>> normalize_query(' some random words "with quotes " and spaces') + ['some', 'random', 'words', 'with quotes', 'and', 'spaces'] + + ''' + return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)] + +def get_query(query_string, search_fields): + ''' Returns a query, that is a combination of Q objects. That combination + aims to search keywords within a model by testing the given search fields. + + ''' + query = None # Query to search for every search term + terms = normalize_query(query_string) + for term in terms: + or_query = None # Query to search for a given term in each field + for field_name in search_fields: + q = Q(**{"%s__icontains" % field_name: term}) + if or_query is None: + or_query = q + else: + or_query = or_query | q + if query is None: + query = or_query + else: + query = query & or_query + return query diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py new file mode 100644 index 000000000..4887ad139 --- /dev/null +++ b/api/funkwhale_api/music/views.py @@ -0,0 +1,254 @@ +import os +import json +from django.core.urlresolvers import reverse +from django.db import models, transaction +from django.db.models.functions import Length +from rest_framework import viewsets, views +from rest_framework.decorators import detail_route, list_route +from rest_framework.response import Response +from rest_framework import permissions +from musicbrainzngs import ResponseError +from django.contrib.auth.decorators import login_required +from django.utils.decorators import method_decorator + +from funkwhale_api.musicbrainz import api +from funkwhale_api.common.permissions import ConditionalAuthentication +from taggit.models import Tag + +from . import models +from . import serializers +from . import importers +from . import utils + +class SearchMixin(object): + search_fields = [] + + @list_route(methods=['get']) + def search(self, request, *args, **kwargs): + query = utils.get_query(request.GET['query'], self.search_fields) + queryset = self.get_queryset().filter(query) + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data) + +class TagViewSetMixin(object): + + def get_queryset(self): + queryset = super().get_queryset() + tag = self.request.query_params.get('tag') + if tag: + queryset = queryset.filter(tags__pk=tag) + return queryset + +class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet): + queryset = ( + models.Artist.objects.all() + .order_by('name') + .prefetch_related( + 'albums__tracks__files', + 'albums__tracks__tags')) + serializer_class = serializers.ArtistSerializerNested + permission_classes = [ConditionalAuthentication] + search_fields = ['name'] + ordering_fields = ('creation_date',) + +class AlbumViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet): + queryset = ( + models.Album.objects.all() + .order_by('-creation_date') + .select_related() + .prefetch_related('tracks__tags', + 'tracks__files')) + serializer_class = serializers.AlbumSerializerNested + permission_classes = [ConditionalAuthentication] + search_fields = ['title'] + ordering_fields = ('creation_date',) + +class ImportBatchViewSet(viewsets.ReadOnlyModelViewSet): + queryset = models.ImportBatch.objects.all().order_by('-creation_date') + serializer_class = serializers.ImportBatchSerializer + + def get_queryset(self): + return super().get_queryset().filter(submitted_by=self.request.user) + +class TrackViewSet(TagViewSetMixin, SearchMixin, viewsets.ReadOnlyModelViewSet): + """ + A simple ViewSet for viewing and editing accounts. + """ + queryset = (models.Track.objects.all() + .select_related() + .select_related('album__artist') + .prefetch_related( + 'tags', + 'files', + 'artist__albums__tracks__tags')) + serializer_class = serializers.TrackSerializerNested + permission_classes = [ConditionalAuthentication] + search_fields = ['title', 'artist__name'] + ordering_fields = ('creation_date',) + + def get_queryset(self): + queryset = super().get_queryset() + filter_favorites = self.request.GET.get('favorites', None) + user = self.request.user + if user.is_authenticated() and filter_favorites == 'true': + queryset = queryset.filter(track_favorites__user=user) + + return queryset + + @detail_route(methods=['get']) + @transaction.non_atomic_requests + def lyrics(self, request, *args, **kwargs): + try: + track = models.Track.objects.get(pk=kwargs['pk']) + except models.Track.DoesNotExist: + return Response(status=404) + + work = track.work + if not work: + work = track.get_work() + + if not work: + return Response({'error': 'unavailable work '}, status=404) + + lyrics = work.fetch_lyrics() + try: + if not lyrics.content: + lyrics.fetch_content() + except AttributeError: + return Response({'error': 'unavailable lyrics'}, status=404) + serializer = serializers.LyricsSerializer(lyrics) + return Response(serializer.data) + + +class TagViewSet(viewsets.ReadOnlyModelViewSet): + queryset = Tag.objects.all() + serializer_class = serializers.TagSerializer + permission_classes = [ConditionalAuthentication] + + +class Search(views.APIView): + max_results = 3 + def get(self, request, *args, **kwargs): + query = request.GET['query'] + results = { + 'tags': serializers.TagSerializer(self.get_tags(query), many=True).data, + 'artists': serializers.ArtistSerializerNested(self.get_artists(query), many=True).data, + 'tracks': serializers.TrackSerializerNested(self.get_tracks(query), many=True).data, + 'albums': serializers.AlbumSerializerNested(self.get_albums(query), many=True).data, + } + return Response(results, status=200) + + def get_tracks(self, query): + search_fields = ['mbid', 'title', 'album__title', 'artist__name'] + query_obj = utils.get_query(query, search_fields) + return ( + models.Track.objects.all() + .filter(query_obj) + .select_related('album__artist') + .prefetch_related( + 'tags', + 'artist__albums__tracks__tags', + 'files') + )[:self.max_results] + + + def get_albums(self, query): + search_fields = ['mbid', 'title', 'artist__name'] + query_obj = utils.get_query(query, search_fields) + return ( + models.Album.objects.all() + .filter(query_obj) + .select_related() + .prefetch_related( + 'tracks__tags', + 'tracks__files', + ) + )[:self.max_results] + + + def get_artists(self, query): + search_fields = ['mbid', 'name'] + query_obj = utils.get_query(query, search_fields) + return ( + models.Artist.objects.all() + .filter(query_obj) + .select_related() + .prefetch_related( + 'albums__tracks__tags', + 'albums__tracks__files', + ) + + )[:self.max_results] + + + def get_tags(self, query): + search_fields = ['slug', 'name'] + query_obj = utils.get_query(query, search_fields) + + # We want the shortest tag first + qs = Tag.objects.all().annotate(slug_length=Length('slug')).order_by('slug_length') + + return qs.filter(query_obj)[:self.max_results] + + +class SubmitViewSet(viewsets.ViewSet): + queryset = models.ImportBatch.objects.none() + permission_classes = (permissions.DjangoModelPermissions, ) + + @list_route(methods=['post']) + @transaction.non_atomic_requests + def single(self, request, *args, **kwargs): + try: + models.Track.objects.get(mbid=request.POST['mbid']) + return Response({}) + except models.Track.DoesNotExist: + pass + batch = models.ImportBatch.objects.create(submitted_by=request.user) + job = models.ImportJob.objects.create(mbid=request.POST['mbid'], batch=batch, source=request.POST['import_url']) + job.run.delay() + serializer = serializers.ImportBatchSerializer(batch) + return Response(serializer.data) + + @list_route(methods=['post']) + @transaction.non_atomic_requests + def album(self, request, *args, **kwargs): + data = json.loads(request.body.decode('utf-8')) + import_data, batch = self._import_album(data, request, batch=None) + return Response(import_data) + + def _import_album(self, data, request, batch=None): + # we import the whole album here to prevent race conditions that occurs + # when using get_or_create_from_api in tasks + album_data = api.releases.get(id=data['releaseId'], includes=models.Album.api_includes)['release'] + cleaned_data = models.Album.clean_musicbrainz_data(album_data) + album = importers.load(models.Album, cleaned_data, album_data, import_hooks=[models.import_tracks]) + try: + album.get_image() + except ResponseError: + pass + if not batch: + batch = models.ImportBatch.objects.create(submitted_by=request.user) + for row in data['tracks']: + try: + models.TrackFile.objects.get(track__mbid=row['mbid']) + except models.TrackFile.DoesNotExist: + job = models.ImportJob.objects.create(mbid=row['mbid'], batch=batch, source=row['source']) + job.run.delay() + serializer = serializers.ImportBatchSerializer(batch) + return serializer.data, batch + + @list_route(methods=['post']) + @transaction.non_atomic_requests + def artist(self, request, *args, **kwargs): + data = json.loads(request.body.decode('utf-8')) + artist_data = api.artists.get(id=data['artistId'])['artist'] + cleaned_data = models.Artist.clean_musicbrainz_data(artist_data) + artist = importers.load(models.Artist, cleaned_data, artist_data, import_hooks=[]) + + import_data = [] + batch = None + for row in data['albums']: + row_data, batch = self._import_album(row, request, batch=batch) + import_data.append(row_data) + + return Response(import_data[0]) diff --git a/api/funkwhale_api/musicbrainz/__init__.py b/api/funkwhale_api/musicbrainz/__init__.py new file mode 100644 index 000000000..00aa85d5c --- /dev/null +++ b/api/funkwhale_api/musicbrainz/__init__.py @@ -0,0 +1 @@ +from .client import api diff --git a/api/funkwhale_api/musicbrainz/client.py b/api/funkwhale_api/musicbrainz/client.py new file mode 100644 index 000000000..e281555b2 --- /dev/null +++ b/api/funkwhale_api/musicbrainz/client.py @@ -0,0 +1,46 @@ +import musicbrainzngs + +from django.conf import settings +from funkwhale_api import __version__ +_api = musicbrainzngs +_api.set_useragent('funkwhale', str(__version__), 'contact@eliotberriot.com') + + +def clean_artist_search(query, **kwargs): + cleaned_kwargs = {} + if kwargs.get('name'): + cleaned_kwargs['artist'] = kwargs.get('name') + return _api.search_artists(query, **cleaned_kwargs) + + +class API(object): + _api = _api + + class artists(object): + search = clean_artist_search + get = _api.get_artist_by_id + + class images(object): + get_front = _api.get_image_front + + class recordings(object): + search = _api.search_recordings + get = _api.get_recording_by_id + + class works(object): + search = _api.search_works + get = _api.get_work_by_id + + class releases(object): + search = _api.search_releases + get = _api.get_release_by_id + browse = _api.browse_releases + # get_image_front = _api.get_image_front + + class release_groups(object): + search = _api.search_release_groups + get = _api.get_release_group_by_id + browse = _api.browse_release_groups + # get_image_front = _api.get_image_front + +api = API() diff --git a/api/funkwhale_api/musicbrainz/tests/__init__.py b/api/funkwhale_api/musicbrainz/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/musicbrainz/tests/data.py b/api/funkwhale_api/musicbrainz/tests/data.py new file mode 100644 index 000000000..1d7b9a3de --- /dev/null +++ b/api/funkwhale_api/musicbrainz/tests/data.py @@ -0,0 +1,478 @@ +artists = {'search': {}, 'get': {}} +artists['search']['lost fingers'] = { + 'artist-count': 696, + 'artist-list': [ + { + 'country': 'CA', + 'sort-name': 'Lost Fingers, The', + 'id': 'ac16bbc0-aded-4477-a3c3-1d81693d58c9', + 'type': 'Group', + 'life-span': { + 'ended': 'false', + 'begin': '2008' + }, + 'area': { + 'sort-name': 'Canada', + 'id': '71bbafaa-e825-3e15-8ca9-017dcad1748b', + 'name': 'Canada' + }, + 'ext:score': '100', + 'name': 'The Lost Fingers' + }, + ] +} +artists['get']['lost fingers'] = { + "artist": { + "life-span": { + "begin": "2008" + }, + "type": "Group", + "id": "ac16bbc0-aded-4477-a3c3-1d81693d58c9", + "release-group-count": 8, + "name": "The Lost Fingers", + "release-group-list": [ + { + "title": "Gypsy Kameleon", + "first-release-date": "2010", + "type": "Album", + "id": "03d3f1d4-e2b0-40d3-8314-05f1896e93a0", + "primary-type": "Album" + }, + { + "title": "Gitan Kameleon", + "first-release-date": "2011-11-11", + "type": "Album", + "id": "243c0cd2-2492-4f5d-bf37-c7c76bed05b7", + "primary-type": "Album" + }, + { + "title": "Pump Up the Jam \u2013 Do Not Cover, Pt. 3", + "first-release-date": "2014-03-17", + "type": "Single", + "id": "4429befd-ff45-48eb-a8f4-cdf7bf007f3f", + "primary-type": "Single" + }, + { + "title": "La Marquise", + "first-release-date": "2012-03-27", + "type": "Album", + "id": "4dab4b96-0a6b-4507-a31e-2189e3e7bad1", + "primary-type": "Album" + }, + { + "title": "Christmas Caravan", + "first-release-date": "2016-11-11", + "type": "Album", + "id": "ca0a506d-6ba9-47c3-a712-de5ce9ae6b1f", + "primary-type": "Album" + }, + { + "title": "Rendez-vous rose", + "first-release-date": "2009-06-16", + "type": "Album", + "id": "d002f1a8-5890-4188-be58-1caadbbd767f", + "primary-type": "Album" + }, + { + "title": "Wonders of the World", + "first-release-date": "2014-05-06", + "type": "Album", + "id": "eeb644c2-5000-42fb-b959-e5e9cc2901c5", + "primary-type": "Album" + }, + { + "title": "Lost in the 80s", + "first-release-date": "2008-05-06", + "type": "Album", + "id": "f04ed607-11b7-3843-957e-503ecdd485d1", + "primary-type": "Album" + } + ], + "area": { + "iso-3166-1-code-list": [ + "CA" + ], + "name": "Canada", + "id": "71bbafaa-e825-3e15-8ca9-017dcad1748b", + "sort-name": "Canada" + }, + "sort-name": "Lost Fingers, The", + "country": "CA" + } +} + + +release_groups = {'browse': {}} +release_groups['browse']["lost fingers"] = { + "release-group-list": [ + { + "first-release-date": "2010", + "type": "Album", + "primary-type": "Album", + "title": "Gypsy Kameleon", + "id": "03d3f1d4-e2b0-40d3-8314-05f1896e93a0" + }, + { + "first-release-date": "2011-11-11", + "type": "Album", + "primary-type": "Album", + "title": "Gitan Kameleon", + "id": "243c0cd2-2492-4f5d-bf37-c7c76bed05b7" + }, + { + "first-release-date": "2014-03-17", + "type": "Single", + "primary-type": "Single", + "title": "Pump Up the Jam \u2013 Do Not Cover, Pt. 3", + "id": "4429befd-ff45-48eb-a8f4-cdf7bf007f3f" + }, + { + "first-release-date": "2012-03-27", + "type": "Album", + "primary-type": "Album", + "title": "La Marquise", + "id": "4dab4b96-0a6b-4507-a31e-2189e3e7bad1" + }, + { + "first-release-date": "2016-11-11", + "type": "Album", + "primary-type": "Album", + "title": "Christmas Caravan", + "id": "ca0a506d-6ba9-47c3-a712-de5ce9ae6b1f" + }, + { + "first-release-date": "2009-06-16", + "type": "Album", + "primary-type": "Album", + "title": "Rendez-vous rose", + "id": "d002f1a8-5890-4188-be58-1caadbbd767f" + }, + { + "first-release-date": "2014-05-06", + "type": "Album", + "primary-type": "Album", + "title": "Wonders of the World", + "id": "eeb644c2-5000-42fb-b959-e5e9cc2901c5" + }, + { + "first-release-date": "2008-05-06", + "type": "Album", + "primary-type": "Album", + "title": "Lost in the 80s", + "id": "f04ed607-11b7-3843-957e-503ecdd485d1" + } + ], + "release-group-count": 8 +} + +recordings = {'search': {}, 'get': {}} +recordings['search']['brontide matador'] = { + "recording-count": 1044, + "recording-list": [ + { + "ext:score": "100", + "length": "366280", + "release-list": [ + { + "date": "2011-05-30", + "medium-track-count": 8, + "release-event-list": [ + { + "area": { + "name": "United Kingdom", + "sort-name": "United Kingdom", + "id": "8a754a16-0027-3a29-b6d7-2b40ea0481ed", + "iso-3166-1-code-list": ["GB"] + }, + "date": "2011-05-30" + } + ], + "country": "GB", + "title": "Sans Souci", + "status": "Official", + "id": "fde538c8-ffef-47c6-9b5a-bd28f4070e5c", + "release-group": { + "type": "Album", + "id": "113ab958-cfb8-4782-99af-639d4d9eae8d", + "primary-type": "Album" + }, + "medium-list": [ + { + "format": "CD", + "track-list": [ + { + "track_or_recording_length": "366280", + "id": "fe506782-a5cb-3d89-9b3e-86287be05768", + "length": "366280", + "title": "Matador", "number": "1" + } + ], + "position": "1", + "track-count": 8 + } + ] + }, + ] + } + ] +} + +releases = {'search': {}, 'get': {}, 'browse': {}} +releases['search']['brontide matador'] = { + "release-count": 116, "release-list": [ + { + "ext:score": "100", + "date": "2009-04-02", + "release-event-list": [ + { + "area": { + "name": "[Worldwide]", + "sort-name": "[Worldwide]", + "id": "525d4e18-3d00-31b9-a58b-a146a916de8f", + "iso-3166-1-code-list": ["XW"] + }, + "date": "2009-04-02" + } + ], + "label-info-list": [ + { + "label": { + "name": "Holy Roar", + "id": "6e940f35-961d-4ac3-bc2a-569fc211c2e3" + } + } + ], + "medium-track-count": 3, + "packaging": "None", + "artist-credit": [ + { + "artist": { + "name": "Brontide", + "sort-name": "Brontide", + "id": "2179fbd2-3c88-4b94-a778-eb3daf1e81a1" + } + } + ], + "artist-credit-phrase": "Brontide", + "country": "XW", + "title": "Brontide EP", + "status": "Official", + "barcode": "", + "id": "59fbd4d1-6121-40e3-9b76-079694fe9702", + "release-group": { + "type": "EP", + "secondary-type-list": ["Demo"], + "id": "b9207129-2d03-4a68-8a53-3c46fe7d2810", + "primary-type": "EP" + }, + "medium-list": [ + { + "disc-list": [], + "format": "Digital Media", + "disc-count": 0, + "track-count": 3, + "track-list": [] + } + ], + "medium-count": 1, + "text-representation": { + "script": "Latn", + "language": "eng" + } + }, + ] +} + +releases['browse']['Lost in the 80s'] = { + "release-count": 3, + "release-list": [ + { + "quality": "normal", + "status": "Official", + "text-representation": { + "script": "Latn", + "language": "eng" + }, + "title": "Lost in the 80s", + "date": "2008-05-06", + "release-event-count": 1, + "id": "34e27fa0-aad4-4cc5-83a3-0f97089154dc", + "barcode": "622406580223", + "medium-count": 1, + "release-event-list": [ + { + "area": { + "iso-3166-1-code-list": [ + "CA" + ], + "id": "71bbafaa-e825-3e15-8ca9-017dcad1748b", + "name": "Canada", + "sort-name": "Canada" + }, + "date": "2008-05-06" + } + ], + "country": "CA", + "cover-art-archive": { + "back": "false", + "artwork": "false", + "front": "false", + "count": "0" + }, + "medium-list": [ + { + "position": "1", + "track-count": 12, + "format": "CD", + "track-list": [ + { + "id": "1662bdf8-31d6-3f6e-846b-fe88c087b109", + "length": "228000", + "recording": { + "id": "2e0dbf37-65af-4408-8def-7b0b3cb8426b", + "length": "228000", + "title": "Pump Up the Jam" + }, + "track_or_recording_length": "228000", + "position": "1", + "number": "1" + }, + { + "id": "01a8cf99-2170-3d3f-96ef-5e4ef7a015a4", + "length": "231000", + "recording": { + "id": "57017e2e-625d-4e7b-a445-47cdb0224dd2", + "length": "231000", + "title": "You Give Love a Bad Name" + }, + "track_or_recording_length": "231000", + "position": "2", + "number": "2" + }, + { + "id": "375a7ce7-5a41-3fbf-9809-96d491401034", + "length": "189000", + "recording": { + "id": "a948672b-b42d-44a5-89b0-7e9ab6a7e11d", + "length": "189000", + "title": "You Shook Me All Night Long" + }, + "track_or_recording_length": "189000", + "position": "3", + "number": "3" + }, + { + "id": "ed7d823e-76da-31be-82a8-770288e27d32", + "length": "253000", + "recording": { + "id": "6e097e31-f37b-4fae-8ad0-ada57f3091a7", + "length": "253000", + "title": "Incognito" + }, + "track_or_recording_length": "253000", + "position": "4", + "number": "4" + }, + { + "id": "76ac8c77-6a99-34d9-ae4d-be8f056d50e0", + "length": "221000", + "recording": { + "id": "faa922e6-e834-44ee-8125-79e640a690e3", + "length": "221000", + "title": "Touch Me" + }, + "track_or_recording_length": "221000", + "position": "5", + "number": "5" + }, + { + "id": "d0a87409-2be6-3ab7-8526-4313e7134be1", + "length": "228000", + "recording": { + "id": "02da8148-60d8-4c79-ab31-8d90d233d711", + "length": "228000", + "title": "Part-Time Lover" + }, + "track_or_recording_length": "228000", + "position": "6", + "number": "6" + }, + { + "id": "02c5384b-5ca9-38e9-8b7c-c08dce608deb", + "length": "248000", + "recording": { + "id": "40085704-d6ab-44f6-a4d8-b27c9ca25b31", + "length": "248000", + "title": "Fresh" + }, + "track_or_recording_length": "248000", + "position": "7", + "number": "7" + }, + { + "id": "ab389542-53d5-346a-b168-1d915ecf0ef6", + "length": "257000", + "recording": { + "id": "77edd338-eeaf-4157-9e2a-5cc3bcee8abd", + "length": "257000", + "title": "Billie Jean" + }, + "track_or_recording_length": "257000", + "position": "8", + "number": "8" + }, + { + "id": "6d9e722b-7408-350e-bb7c-2de1e329ae84", + "length": "293000", + "recording": { + "id": "040aaffa-7206-40ff-9930-469413fe2420", + "length": "293000", + "title": "Careless Whisper" + }, + "track_or_recording_length": "293000", + "position": "9", + "number": "9" + }, + { + "id": "63b4e67c-7536-3cd0-8c47-0310c1e40866", + "length": "211000", + "recording": { + "id": "054942f0-4c0f-4e92-a606-d590976b1cff", + "length": "211000", + "title": "Tainted Love" + }, + "track_or_recording_length": "211000", + "position": "10", + "number": "10" + }, + { + "id": "a07f4ca3-dbf0-3337-a247-afcd0509334a", + "length": "245000", + "recording": { + "id": "8023b5ad-649a-4c67-b7a2-e12358606f6e", + "length": "245000", + "title": "Straight Up" + }, + "track_or_recording_length": "245000", + "position": "11", + "number": "11" + }, + { + "id": "73d47f16-b18d-36ff-b0bb-1fa1fd32ebf7", + "length": "322000", + "recording": { + "id": "95a8c8a1-fcb6-4cbb-a853-be86d816b357", + "length": "322000", + "title": "Black Velvet" + }, + "track_or_recording_length": "322000", + "position": "12", + "number": "12" + } + ] + } + ], + "asin": "B0017M8YTO" + }, + ] +} diff --git a/api/funkwhale_api/musicbrainz/tests/test_api.py b/api/funkwhale_api/musicbrainz/tests/test_api.py new file mode 100644 index 000000000..1734c943c --- /dev/null +++ b/api/funkwhale_api/musicbrainz/tests/test_api.py @@ -0,0 +1,87 @@ +import json +import unittest +from test_plus.test import TestCase +from django.core.urlresolvers import reverse + +from funkwhale_api.musicbrainz import api +from . import data as api_data + + +class TestAPI(TestCase): + @unittest.mock.patch( + 'funkwhale_api.musicbrainz.api.recordings.search', + return_value=api_data.recordings['search']['brontide matador']) + def test_can_search_recording_in_musicbrainz_api(self, *mocks): + query = 'brontide matador' + url = reverse('api:providers:musicbrainz:search-recordings') + expected = api_data.recordings['search']['brontide matador'] + response = self.client.get(url, data={'query': query}) + + self.assertEqual(expected, json.loads(response.content.decode('utf-8'))) + + @unittest.mock.patch( + 'funkwhale_api.musicbrainz.api.releases.search', + return_value=api_data.releases['search']['brontide matador']) + def test_can_search_release_in_musicbrainz_api(self, *mocks): + query = 'brontide matador' + url = reverse('api:providers:musicbrainz:search-releases') + expected = api_data.releases['search']['brontide matador'] + response = self.client.get(url, data={'query': query}) + + self.assertEqual(expected, json.loads(response.content.decode('utf-8'))) + + @unittest.mock.patch( + 'funkwhale_api.musicbrainz.api.artists.search', + return_value=api_data.artists['search']['lost fingers']) + def test_can_search_artists_in_musicbrainz_api(self, *mocks): + query = 'lost fingers' + url = reverse('api:providers:musicbrainz:search-artists') + expected = api_data.artists['search']['lost fingers'] + response = self.client.get(url, data={'query': query}) + + self.assertEqual(expected, json.loads(response.content.decode('utf-8'))) + + @unittest.mock.patch( + 'funkwhale_api.musicbrainz.api.artists.get', + return_value=api_data.artists['get']['lost fingers']) + def test_can_get_artist_in_musicbrainz_api(self, *mocks): + uuid = 'ac16bbc0-aded-4477-a3c3-1d81693d58c9' + url = reverse('api:providers:musicbrainz:artist-detail', kwargs={ + 'uuid': uuid, + }) + response = self.client.get(url) + expected = api_data.artists['get']['lost fingers'] + + self.assertEqual(expected, json.loads(response.content.decode('utf-8'))) + + @unittest.mock.patch( + 'funkwhale_api.musicbrainz.api.release_groups.browse', + return_value=api_data.release_groups['browse']['lost fingers']) + def test_can_broswe_release_group_using_musicbrainz_api(self, *mocks): + uuid = 'ac16bbc0-aded-4477-a3c3-1d81693d58c9' + url = reverse( + 'api:providers:musicbrainz:release-group-browse', + kwargs={ + 'artist_uuid': uuid, + } + ) + response = self.client.get(url) + expected = api_data.release_groups['browse']['lost fingers'] + + self.assertEqual(expected, json.loads(response.content.decode('utf-8'))) + + @unittest.mock.patch( + 'funkwhale_api.musicbrainz.api.releases.browse', + return_value=api_data.releases['browse']['Lost in the 80s']) + def test_can_broswe_releases_using_musicbrainz_api(self, *mocks): + uuid = 'f04ed607-11b7-3843-957e-503ecdd485d1' + url = reverse( + 'api:providers:musicbrainz:release-browse', + kwargs={ + 'release_group_uuid': uuid, + } + ) + response = self.client.get(url) + expected = api_data.releases['browse']['Lost in the 80s'] + + self.assertEqual(expected, json.loads(response.content.decode('utf-8'))) diff --git a/api/funkwhale_api/musicbrainz/urls.py b/api/funkwhale_api/musicbrainz/urls.py new file mode 100644 index 000000000..7befe49ab --- /dev/null +++ b/api/funkwhale_api/musicbrainz/urls.py @@ -0,0 +1,24 @@ +from django.conf.urls import include, url +from rest_framework import routers + +from . import views + +router = routers.SimpleRouter() +router.register(r'search', views.SearchViewSet, 'search') +urlpatterns = [ + url('releases/(?P[0-9a-z-]+)/$', + views.ReleaseDetail.as_view(), + name='release-detail'), + url('artists/(?P[0-9a-z-]+)/$', + views.ArtistDetail.as_view(), + name='artist-detail'), + url('release-groups/browse/(?P[0-9a-z-]+)/$', + views.ReleaseGroupBrowse.as_view(), + name='release-group-browse'), + url('releases/browse/(?P[0-9a-z-]+)/$', + views.ReleaseBrowse.as_view(), + name='release-browse'), + # url('release-groups/(?P[0-9a-z-]+)/$', + # views.ReleaseGroupDetail.as_view(), + # name='release-group-detail'), +] + router.urls diff --git a/api/funkwhale_api/musicbrainz/views.py b/api/funkwhale_api/musicbrainz/views.py new file mode 100644 index 000000000..fac8089b9 --- /dev/null +++ b/api/funkwhale_api/musicbrainz/views.py @@ -0,0 +1,70 @@ +from rest_framework import viewsets +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework.decorators import list_route + +from funkwhale_api.common.permissions import ConditionalAuthentication + + +from .client import api + + +class ReleaseDetail(APIView): + permission_classes = [ConditionalAuthentication] + + def get(self, request, *args, **kwargs): + result = api.releases.get( + id=kwargs['uuid'], includes=['artists', 'recordings']) + return Response(result) + + +class ArtistDetail(APIView): + permission_classes = [ConditionalAuthentication] + + def get(self, request, *args, **kwargs): + result = api.artists.get( + id=kwargs['uuid'], + includes=['release-groups']) + # import json; print(json.dumps(result, indent=4)) + return Response(result) + + +class ReleaseGroupBrowse(APIView): + permission_classes = [ConditionalAuthentication] + + def get(self, request, *args, **kwargs): + result = api.release_groups.browse( + artist=kwargs['artist_uuid']) + return Response(result) + + +class ReleaseBrowse(APIView): + permission_classes = [ConditionalAuthentication] + + def get(self, request, *args, **kwargs): + result = api.releases.browse( + release_group=kwargs['release_group_uuid'], + includes=['recordings']) + return Response(result) + + +class SearchViewSet(viewsets.ViewSet): + permission_classes = [ConditionalAuthentication] + + @list_route(methods=['get']) + def recordings(self, request, *args, **kwargs): + query = request.GET['query'] + results = api.recordings.search(query, artist=query) + return Response(results) + + @list_route(methods=['get']) + def releases(self, request, *args, **kwargs): + query = request.GET['query'] + results = api.releases.search(query, artist=query) + return Response(results) + + @list_route(methods=['get']) + def artists(self, request, *args, **kwargs): + query = request.GET['query'] + results = api.artists.search(query) + return Response(results) diff --git a/api/funkwhale_api/playlists/__init__.py b/api/funkwhale_api/playlists/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/playlists/admin.py b/api/funkwhale_api/playlists/admin.py new file mode 100644 index 000000000..b337154c9 --- /dev/null +++ b/api/funkwhale_api/playlists/admin.py @@ -0,0 +1,17 @@ +from django.contrib import admin + +from . import models + + +@admin.register(models.Playlist) +class PlaylistAdmin(admin.ModelAdmin): + list_display = ['name', 'user', 'is_public', 'creation_date'] + search_fields = ['name', ] + list_select_related = True + + +@admin.register(models.PlaylistTrack) +class PlaylistTrackAdmin(admin.ModelAdmin): + list_display = ['playlist', 'track', 'position', ] + search_fields = ['track__name', 'playlist__name'] + list_select_related = True diff --git a/api/funkwhale_api/playlists/migrations/0001_initial.py b/api/funkwhale_api/playlists/migrations/0001_initial.py new file mode 100644 index 000000000..f42ca154e --- /dev/null +++ b/api/funkwhale_api/playlists/migrations/0001_initial.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings +import django.utils.timezone +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('music', '0012_auto_20161122_1905'), + ] + + operations = [ + migrations.CreateModel( + name='Playlist', + fields=[ + ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), + ('name', models.CharField(max_length=50)), + ('is_public', models.BooleanField(default=False)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='playlists')), + ], + ), + migrations.CreateModel( + name='PlaylistTrack', + fields=[ + ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('position', models.PositiveIntegerField(db_index=True, editable=False)), + ('playlist', models.ForeignKey(to='playlists.Playlist', related_name='playlist_tracks')), + ('previous', mptt.fields.TreeOneToOneField(null=True, to='playlists.PlaylistTrack', related_name='next', blank=True)), + ('track', models.ForeignKey(to='music.Track', related_name='playlist_tracks')), + ], + options={ + 'ordering': ('-playlist', 'position'), + }, + ), + ] diff --git a/api/funkwhale_api/playlists/migrations/__init__.py b/api/funkwhale_api/playlists/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/playlists/models.py b/api/funkwhale_api/playlists/models.py new file mode 100644 index 000000000..35a30a704 --- /dev/null +++ b/api/funkwhale_api/playlists/models.py @@ -0,0 +1,33 @@ +from django.db import models +from django.utils import timezone + +from mptt.models import MPTTModel, TreeOneToOneField + + +class Playlist(models.Model): + name = models.CharField(max_length=50) + is_public = models.BooleanField(default=False) + user = models.ForeignKey('users.User', related_name="playlists") + creation_date = models.DateTimeField(default=timezone.now) + + def __str__(self): + return self.name + + def add_track(self, track, previous=None): + plt = PlaylistTrack(previous=previous, track=track, playlist=self) + plt.save() + + return plt + + +class PlaylistTrack(MPTTModel): + track = models.ForeignKey('music.Track', related_name='playlist_tracks') + previous = TreeOneToOneField('self', blank=True, null=True, related_name='next') + playlist = models.ForeignKey(Playlist, related_name='playlist_tracks') + + class MPTTMeta: + level_attr = 'position' + parent_attr = 'previous' + + class Meta: + ordering = ('-playlist', 'position') diff --git a/api/funkwhale_api/playlists/serializers.py b/api/funkwhale_api/playlists/serializers.py new file mode 100644 index 000000000..7f889d53e --- /dev/null +++ b/api/funkwhale_api/playlists/serializers.py @@ -0,0 +1,30 @@ +from rest_framework import serializers +from taggit.models import Tag + +from funkwhale_api.music.serializers import TrackSerializerNested + +from . import models + + +class PlaylistTrackSerializer(serializers.ModelSerializer): + track = TrackSerializerNested() + + class Meta: + model = models.PlaylistTrack + fields = ('id', 'track', 'playlist', 'position') + + +class PlaylistTrackCreateSerializer(serializers.ModelSerializer): + + class Meta: + model = models.PlaylistTrack + fields = ('id', 'track', 'playlist', 'position') + + +class PlaylistSerializer(serializers.ModelSerializer): + playlist_tracks = PlaylistTrackSerializer(many=True, read_only=True) + + class Meta: + model = models.Playlist + fields = ('id', 'name', 'is_public', 'creation_date', 'playlist_tracks') + read_only_fields = ['id', 'playlist_tracks', 'creation_date'] diff --git a/api/funkwhale_api/playlists/tests/__init__.py b/api/funkwhale_api/playlists/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/playlists/tests/test_playlists.py b/api/funkwhale_api/playlists/tests/test_playlists.py new file mode 100644 index 000000000..056ca06e6 --- /dev/null +++ b/api/funkwhale_api/playlists/tests/test_playlists.py @@ -0,0 +1,65 @@ +import json +from test_plus.test import TestCase +from django.core.urlresolvers import reverse +from django.core.exceptions import ValidationError +from django.utils import timezone + +from model_mommy import mommy + +from funkwhale_api.users.models import User +from funkwhale_api.playlists import models +from funkwhale_api.playlists.serializers import PlaylistSerializer + + +class TestPlayLists(TestCase): + + def setUp(self): + super().setUp() + self.user = User.objects.create_user(username='test', email='test@test.com', password='test') + + def test_can_create_playlist(self): + tracks = list(mommy.make('music.Track', _quantity=5)) + playlist = models.Playlist.objects.create(user=self.user, name="test") + + previous = None + for i in range(len(tracks)): + previous = playlist.add_track(tracks[i], previous=previous) + + playlist_tracks = list(playlist.playlist_tracks.all()) + + previous = None + for idx, track in enumerate(tracks): + plt = playlist_tracks[idx] + self.assertEqual(plt.position, idx) + self.assertEqual(plt.track, track) + if previous: + self.assertEqual(playlist_tracks[idx + 1], previous) + self.assertEqual(plt.playlist, playlist) + + def test_can_create_playlist_via_api(self): + self.client.login(username=self.user.username, password='test') + url = reverse('api:playlists-list') + data = { + 'name': 'test', + } + + response = self.client.post(url, data) + + playlist = self.user.playlists.latest('id') + self.assertEqual(playlist.name, 'test') + + def test_can_add_playlist_track_via_api(self): + tracks = list(mommy.make('music.Track', _quantity=5)) + playlist = models.Playlist.objects.create(user=self.user, name="test") + + self.client.login(username=self.user.username, password='test') + + url = reverse('api:playlist-tracks-list') + data = { + 'playlist': playlist.pk, + 'track': tracks[0].pk + } + + response = self.client.post(url, data) + plts = self.user.playlists.latest('id').playlist_tracks.all() + self.assertEqual(plts.first().track, tracks[0]) diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py new file mode 100644 index 000000000..1a88d231e --- /dev/null +++ b/api/funkwhale_api/playlists/views.py @@ -0,0 +1,58 @@ +from rest_framework import generics, mixins, viewsets +from rest_framework import status +from rest_framework.response import Response + +from funkwhale_api.music.models import Track +from funkwhale_api.common.permissions import ConditionalAuthentication + +from . import models +from . import serializers + + +class PlaylistViewSet( + mixins.RetrieveModelMixin, + mixins.CreateModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin, + viewsets.GenericViewSet): + + serializer_class = serializers.PlaylistSerializer + queryset = (models.Playlist.objects.all()) + permission_classes = [ConditionalAuthentication] + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + instance = self.perform_create(serializer) + serializer = self.get_serializer(instance=instance) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + def get_queryset(self): + return self.queryset.filter(user=self.request.user) + + def perform_create(self, serializer): + return serializer.save(user=self.request.user) + + +class PlaylistTrackViewSet( + mixins.CreateModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin, + viewsets.GenericViewSet): + + serializer_class = serializers.PlaylistTrackSerializer + queryset = (models.PlaylistTrack.objects.all()) + permission_classes = [ConditionalAuthentication] + + def create(self, request, *args, **kwargs): + serializer = serializers.PlaylistTrackCreateSerializer( + data=request.data) + serializer.is_valid(raise_exception=True) + instance = self.perform_create(serializer) + serializer = self.get_serializer(instance=instance) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + def get_queryset(self): + return self.queryset.filter(playlist__user=self.request.user) diff --git a/api/funkwhale_api/providers/__init__.py b/api/funkwhale_api/providers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/audiofile/__init__.py b/api/funkwhale_api/providers/audiofile/__init__.py new file mode 100644 index 000000000..18e2c469a --- /dev/null +++ b/api/funkwhale_api/providers/audiofile/__init__.py @@ -0,0 +1,4 @@ +""" +This module is responsible from importing existing audiofiles from the +filesystem into funkwhale. +""" diff --git a/api/funkwhale_api/providers/audiofile/importer.py b/api/funkwhale_api/providers/audiofile/importer.py new file mode 100644 index 000000000..d95c120e1 --- /dev/null +++ b/api/funkwhale_api/providers/audiofile/importer.py @@ -0,0 +1,60 @@ +import os +import datetime +from django.core.files import File + +from funkwhale_api.taskapp import celery +from funkwhale_api.music import models, metadata + + +@celery.app.task(name='audiofile.from_path') +def from_path(path): + data = metadata.Metadata(path) + + artist = models.Artist.objects.get_or_create( + name__iexact=data.get('artist'), + defaults={'name': data.get('artist')}, + )[0] + + release_date = None + try: + year, month, day = data.get('date', None).split('-') + release_date = datetime.date( + int(year), int(month), int(day) + ) + except (ValueError, TypeError): + pass + + album = models.Album.objects.get_or_create( + title__iexact=data.get('album'), + artist=artist, + defaults={ + 'title': data.get('album'), + 'release_date': release_date, + }, + )[0] + + position = None + try: + position = int(data.get('tracknumber', None)) + except ValueError: + pass + track = models.Track.objects.get_or_create( + title__iexact=data.get('title'), + album=album, + defaults={ + 'title': data.get('title'), + 'position': position, + }, + )[0] + + if track.files.count() > 0: + raise ValueError('File already exists for track {}'.format(track.pk)) + + track_file = models.TrackFile(track=track) + track_file.audio_file.save( + os.path.basename(path), + File(open(path, 'rb')) + ) + track_file.save() + + return track_file diff --git a/api/funkwhale_api/providers/audiofile/management/__init__.py b/api/funkwhale_api/providers/audiofile/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/audiofile/management/commands/__init__.py b/api/funkwhale_api/providers/audiofile/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/audiofile/management/commands/import_files.py b/api/funkwhale_api/providers/audiofile/management/commands/import_files.py new file mode 100644 index 000000000..8a99156cb --- /dev/null +++ b/api/funkwhale_api/providers/audiofile/management/commands/import_files.py @@ -0,0 +1,61 @@ +import glob +from django.core.management.base import BaseCommand, CommandError +from funkwhale_api.providers.audiofile import importer + + +class Command(BaseCommand): + help = 'Import audio files mathinc given glob pattern' + + def add_arguments(self, parser): + parser.add_argument('path', type=str) + parser.add_argument( + '--recursive', + action='store_true', + dest='recursive', + default=False, + help='Will match the pattern recursively (including subdirectories)', + ) + parser.add_argument( + '--async', + action='store_true', + dest='async', + default=False, + help='Will launch celery tasks for each file to import instead of doing it synchronously and block the CLI', + ) + parser.add_argument( + '--noinput', '--no-input', action='store_false', dest='interactive', + help="Do NOT prompt the user for input of any kind.", + ) + + def handle(self, *args, **options): + # self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id)) + matching = glob.glob(options['path'], recursive=options['recursive']) + self.stdout.write('This will import {} files matching this pattern: {}'.format( + len(matching), options['path'])) + + if not matching: + raise CommandError('No file matching pattern, aborting') + + if options['interactive']: + message = ( + 'Are you sure you want to do this?\n\n' + "Type 'yes' to continue, or 'no' to cancel: " + ) + if input(''.join(message)) != 'yes': + raise CommandError("Import cancelled.") + + message = 'Importing {}...' + if options['async']: + message = 'Launching import for {}...' + + for path in matching: + self.stdout.write(message.format(path)) + try: + importer.from_path(path) + except Exception as e: + self.stdout.write('Error: {}'.format(e)) + + message = 'Successfully imported {} tracks' + if options['async']: + message = 'Successfully launched import for {} tracks' + self.stdout.write(message.format(len(matching))) diff --git a/api/funkwhale_api/providers/audiofile/tests/__init__.py b/api/funkwhale_api/providers/audiofile/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/audiofile/tests/dummy_file.ogg b/api/funkwhale_api/providers/audiofile/tests/dummy_file.ogg new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/audiofile/tests/test_disk_import.py b/api/funkwhale_api/providers/audiofile/tests/test_disk_import.py new file mode 100644 index 000000000..26532a8c9 --- /dev/null +++ b/api/funkwhale_api/providers/audiofile/tests/test_disk_import.py @@ -0,0 +1,34 @@ +import os +import datetime +import unittest +from test_plus.test import TestCase + +from funkwhale_api.providers.audiofile import importer + +DATA_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class TestAudioFile(TestCase): + def test_can_import_single_audio_file(self, *mocks): + metadata = { + 'artist': ['Test artist'], + 'album': ['Test album'], + 'title': ['Test track'], + 'tracknumber': ['4'], + 'date': ['2012-08-15'] + } + + with unittest.mock.patch('mutagen.File', return_value=metadata): + track_file = importer.from_path( + os.path.join(DATA_DIR, 'dummy_file.ogg')) + + self.assertEqual( + track_file.track.title, metadata['title'][0]) + self.assertEqual( + track_file.track.position, 4) + self.assertEqual( + track_file.track.album.title, metadata['album'][0]) + self.assertEqual( + track_file.track.album.release_date, datetime.date(2012, 8, 15)) + self.assertEqual( + track_file.track.artist.name, metadata['artist'][0]) diff --git a/api/funkwhale_api/providers/urls.py b/api/funkwhale_api/providers/urls.py new file mode 100644 index 000000000..a6d417e5b --- /dev/null +++ b/api/funkwhale_api/providers/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import include, url +from funkwhale_api.music import views + + +urlpatterns = [ + url(r'^youtube/', include('funkwhale_api.providers.youtube.urls', namespace='youtube')), + url(r'^musicbrainz/', include('funkwhale_api.musicbrainz.urls', namespace='musicbrainz')), +] diff --git a/api/funkwhale_api/providers/youtube/__init__.py b/api/funkwhale_api/providers/youtube/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/youtube/client.py b/api/funkwhale_api/providers/youtube/client.py new file mode 100644 index 000000000..7c0ea326c --- /dev/null +++ b/api/funkwhale_api/providers/youtube/client.py @@ -0,0 +1,58 @@ +import threading + +from apiclient.discovery import build +from apiclient.errors import HttpError +from oauth2client.tools import argparser + +from django.conf import settings + +# Set DEVELOPER_KEY to the API key value from the APIs & auth > Registered apps +# tab of +# https://cloud.google.com/console +# Please ensure that you have enabled the YouTube Data API for your project. +DEVELOPER_KEY = settings.FUNKWHALE_PROVIDERS['youtube']['api_key'] +YOUTUBE_API_SERVICE_NAME = "youtube" +YOUTUBE_API_VERSION = "v3" +VIDEO_BASE_URL = 'https://www.youtube.com/watch?v={0}' + + +def _do_search(query): + youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, + developerKey=DEVELOPER_KEY) + + return youtube.search().list( + q=query, + part="id,snippet", + maxResults=25 + ).execute() + + +class Client(object): + + def search(self, query): + search_response = _do_search(query) + videos = [] + for search_result in search_response.get("items", []): + if search_result["id"]["kind"] == "youtube#video": + search_result['full_url'] = VIDEO_BASE_URL.format(search_result["id"]['videoId']) + videos.append(search_result) + return videos + + def search_multiple(self, queries): + results = {} + + def search(key, query): + results[key] = self.search(query) + + threads = [ + threading.Thread(target=search, args=(key, query,)) + for key, query in queries.items() + ] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + + return results + +client = Client() diff --git a/api/funkwhale_api/providers/youtube/tests/__init__.py b/api/funkwhale_api/providers/youtube/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/providers/youtube/tests/data.py b/api/funkwhale_api/providers/youtube/tests/data.py new file mode 100644 index 000000000..a8372d4c9 --- /dev/null +++ b/api/funkwhale_api/providers/youtube/tests/data.py @@ -0,0 +1,162 @@ + + +search = {} + + +search['8 bit adventure'] = { + "pageInfo": { + "totalResults": 1000000, + "resultsPerPage": 25 + }, + "nextPageToken": "CBkQAA", + "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/1L34zetsKWv-raAFiz0MuT0SsfQ\"", + "items": [ + { + "id": { + "videoId": "0HxZn6CzOIo", + "kind": "youtube#video" + }, + "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/GxK-wHBWUYfrJsd1dijBPTufrVE\"", + "snippet": { + "liveBroadcastContent": "none", + "description": "Make sure to apply adhesive evenly before use. GET IT HERE: http://adhesivewombat.bandcamp.com/album/marsupial-madness Facebook: ...", + "channelId": "UCps63j3krzAG4OyXeEyuhFw", + "title": "AdhesiveWombat - 8 Bit Adventure", + "channelTitle": "AdhesiveWombat", + "publishedAt": "2012-08-22T18:41:03.000Z", + "thumbnails": { + "medium": { + "url": "https://i.ytimg.com/vi/0HxZn6CzOIo/mqdefault.jpg", + "height": 180, + "width": 320 + }, + "high": { + "url": "https://i.ytimg.com/vi/0HxZn6CzOIo/hqdefault.jpg", + "height": 360, + "width": 480 + }, + "default": { + "url": "https://i.ytimg.com/vi/0HxZn6CzOIo/default.jpg", + "height": 90, + "width": 120 + } + } + }, + "kind": "youtube#searchResult" + }, + { + "id": { + "videoId": "n4A_F5SXmgo", + "kind": "youtube#video" + }, + "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/aRVESw24jlgiErDgJKxNrazKRDc\"", + "snippet": { + "liveBroadcastContent": "none", + "description": "Free Download: http://bit.ly/1fZ1pMJ I don't post 8 bit'ish music much but damn I must admit this is goood! Enjoy \u2665 \u25bbSpikedGrin: ...", + "channelId": "UCMOgdURr7d8pOVlc-alkfRg", + "title": "\u3010Electro\u3011AdhesiveWombat - 8 Bit Adventure (SpikedGrin Remix) [Free Download]", + "channelTitle": "xKito Music", + "publishedAt": "2013-10-27T13:16:48.000Z", + "thumbnails": { + "medium": { + "url": "https://i.ytimg.com/vi/n4A_F5SXmgo/mqdefault.jpg", + "height": 180, + "width": 320 + }, + "high": { + "url": "https://i.ytimg.com/vi/n4A_F5SXmgo/hqdefault.jpg", + "height": 360, + "width": 480 + }, + "default": { + "url": "https://i.ytimg.com/vi/n4A_F5SXmgo/default.jpg", + "height": 90, + "width": 120 + } + } + }, + "kind": "youtube#searchResult" + }, + ], + "regionCode": "FR", + "kind": "youtube#searchListResponse" +} + +search['system of a down toxicity'] = { + "items": [ + { + "id": { + "kind": "youtube#video", + "videoId": "BorYwGi2SJc" + }, + "kind": "youtube#searchResult", + "snippet": { + "title": "System of a Down: Toxicity", + "channelTitle": "Vedres Csaba", + "channelId": "UCBXeuQORNwPv4m68fgGMtPQ", + "thumbnails": { + "default": { + "height": 90, + "width": 120, + "url": "https://i.ytimg.com/vi/BorYwGi2SJc/default.jpg" + }, + "high": { + "height": 360, + "width": 480, + "url": "https://i.ytimg.com/vi/BorYwGi2SJc/hqdefault.jpg" + }, + "medium": { + "height": 180, + "width": 320, + "url": "https://i.ytimg.com/vi/BorYwGi2SJc/mqdefault.jpg" + } + }, + "publishedAt": "2007-12-17T12:39:54.000Z", + "description": "http://www.vedrescsaba.uw.hu The System of a Down song Toxicity arranged for a classical piano quintet, played by Vedres Csaba and the Kairosz quartet.", + "liveBroadcastContent": "none" + }, + "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/UwR8H6P6kbijNZmBNkYd2jAzDnI\"" + }, + { + "id": { + "kind": "youtube#video", + "videoId": "ENBv2i88g6Y" + }, + "kind": "youtube#searchResult", + "snippet": { + "title": "System Of A Down - Question!", + "channelTitle": "systemofadownVEVO", + "channelId": "UCvtZDkeFxMkRTNqfqXtxxkw", + "thumbnails": { + "default": { + "height": 90, + "width": 120, + "url": "https://i.ytimg.com/vi/ENBv2i88g6Y/default.jpg" + }, + "high": { + "height": 360, + "width": 480, + "url": "https://i.ytimg.com/vi/ENBv2i88g6Y/hqdefault.jpg" + }, + "medium": { + "height": 180, + "width": 320, + "url": "https://i.ytimg.com/vi/ENBv2i88g6Y/mqdefault.jpg" + } + }, + "publishedAt": "2009-10-03T04:49:03.000Z", + "description": "System of a Down's official music video for 'Question!'. Click to listen to System of a Down on Spotify: http://smarturl.it/SystemSpotify?IQid=SystemQu As featured ...", + "liveBroadcastContent": "none" + }, + "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/dB-M0N9mB4xE-k4yAF_4d8aU0I4\"" + }, + ], + "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/yhLQgSpeObNnybd5JqSzlGiJ8Ew\"", + "nextPageToken": "CBkQAA", + "pageInfo": { + "resultsPerPage": 25, + "totalResults": 26825 + }, + "kind": "youtube#searchListResponse", + "regionCode": "FR" +} diff --git a/api/funkwhale_api/providers/youtube/tests/test_youtube.py b/api/funkwhale_api/providers/youtube/tests/test_youtube.py new file mode 100644 index 000000000..56b87a354 --- /dev/null +++ b/api/funkwhale_api/providers/youtube/tests/test_youtube.py @@ -0,0 +1,74 @@ +import json +from collections import OrderedDict +import unittest +from test_plus.test import TestCase +from django.core.urlresolvers import reverse +from funkwhale_api.providers.youtube.client import client + +from . import data as api_data + +class TestAPI(TestCase): + + @unittest.mock.patch( + 'funkwhale_api.providers.youtube.client._do_search', + return_value=api_data.search['8 bit adventure']) + def test_can_get_search_results_from_youtube(self, *mocks): + query = '8 bit adventure' + + results = client.search(query) + self.assertEqual(results[0]['id']['videoId'], '0HxZn6CzOIo') + self.assertEqual(results[0]['snippet']['title'], 'AdhesiveWombat - 8 Bit Adventure') + self.assertEqual(results[0]['full_url'], 'https://www.youtube.com/watch?v=0HxZn6CzOIo') + + @unittest.mock.patch( + 'funkwhale_api.providers.youtube.client._do_search', + return_value=api_data.search['8 bit adventure']) + def test_can_get_search_results_from_funkwhale(self, *mocks): + query = '8 bit adventure' + expected = json.dumps(client.search(query)) + url = self.reverse('api:providers:youtube:search') + response = self.client.get(url + '?query={0}'.format(query)) + + self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8'))) + + @unittest.mock.patch( + 'funkwhale_api.providers.youtube.client._do_search', + side_effect=[ + api_data.search['8 bit adventure'], + api_data.search['system of a down toxicity'], + ] + ) + def test_can_send_multiple_queries_at_once(self, *mocks): + queries = OrderedDict() + queries['1'] = { + 'q': '8 bit adventure', + } + queries['2'] = { + 'q': 'system of a down toxicity', + } + + results = client.search_multiple(queries) + + self.assertEqual(results['1'][0]['id']['videoId'], '0HxZn6CzOIo') + self.assertEqual(results['1'][0]['snippet']['title'], 'AdhesiveWombat - 8 Bit Adventure') + self.assertEqual(results['1'][0]['full_url'], 'https://www.youtube.com/watch?v=0HxZn6CzOIo') + self.assertEqual(results['2'][0]['id']['videoId'], 'BorYwGi2SJc') + self.assertEqual(results['2'][0]['snippet']['title'], 'System of a Down: Toxicity') + self.assertEqual(results['2'][0]['full_url'], 'https://www.youtube.com/watch?v=BorYwGi2SJc') + + @unittest.mock.patch( + 'funkwhale_api.providers.youtube.client._do_search', + return_value=api_data.search['8 bit adventure'], + ) + def test_can_send_multiple_queries_at_once_from_funwkhale(self, *mocks): + queries = OrderedDict() + queries['1'] = { + 'q': '8 bit adventure', + } + + expected = json.dumps(client.search_multiple(queries)) + url = self.reverse('api:providers:youtube:searchs') + response = self.client.post( + url, json.dumps(queries), content_type='application/json') + + self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8'))) diff --git a/api/funkwhale_api/providers/youtube/urls.py b/api/funkwhale_api/providers/youtube/urls.py new file mode 100644 index 000000000..243d2b852 --- /dev/null +++ b/api/funkwhale_api/providers/youtube/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import include, url +from .views import APISearch, APISearchs + + +urlpatterns = [ + url(r'^search/$', APISearch.as_view(), name='search'), + url(r'^searchs/$', APISearchs.as_view(), name='searchs'), +] diff --git a/api/funkwhale_api/providers/youtube/views.py b/api/funkwhale_api/providers/youtube/views.py new file mode 100644 index 000000000..7ad2c2c3d --- /dev/null +++ b/api/funkwhale_api/providers/youtube/views.py @@ -0,0 +1,21 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +from funkwhale_api.common.permissions import ConditionalAuthentication + +from .client import client + + +class APISearch(APIView): + permission_classes = [ConditionalAuthentication] + + def get(self, request, *args, **kwargs): + results = client.search(request.GET['query']) + return Response(results) + + +class APISearchs(APIView): + permission_classes = [ConditionalAuthentication] + + def post(self, request, *args, **kwargs): + results = client.search_multiple(request.data) + return Response(results) diff --git a/api/funkwhale_api/radios/__init__.py b/api/funkwhale_api/radios/__init__.py new file mode 100644 index 000000000..1258181b5 --- /dev/null +++ b/api/funkwhale_api/radios/__init__.py @@ -0,0 +1 @@ +from .registries import registry diff --git a/api/funkwhale_api/radios/migrations/0001_initial.py b/api/funkwhale_api/radios/migrations/0001_initial.py new file mode 100644 index 000000000..9ec25805d --- /dev/null +++ b/api/funkwhale_api/radios/migrations/0001_initial.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('music', '0004_track_tags'), + ] + + operations = [ + migrations.CreateModel( + name='RadioSession', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)), + ('radio_type', models.CharField(max_length=50)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('user', models.ForeignKey(related_name='radio_sessions', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ], + ), + migrations.CreateModel( + name='RadioSessionTrack', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)), + ('position', models.IntegerField(default=1)), + ('session', models.ForeignKey(to='radios.RadioSession', related_name='session_tracks')), + ('track', models.ForeignKey(to='music.Track', related_name='radio_session_tracks')), + ], + options={ + 'ordering': ('session', 'position'), + }, + ), + migrations.AlterUniqueTogether( + name='radiosessiontrack', + unique_together=set([('session', 'position')]), + ), + ] diff --git a/api/funkwhale_api/radios/migrations/0002_radiosession_session_key.py b/api/funkwhale_api/radios/migrations/0002_radiosession_session_key.py new file mode 100644 index 000000000..a903ae3ea --- /dev/null +++ b/api/funkwhale_api/radios/migrations/0002_radiosession_session_key.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('radios', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='radiosession', + name='session_key', + field=models.CharField(null=True, blank=True, max_length=100), + ), + ] diff --git a/api/funkwhale_api/radios/migrations/0003_auto_20160521_1708.py b/api/funkwhale_api/radios/migrations/0003_auto_20160521_1708.py new file mode 100644 index 000000000..4629d68fe --- /dev/null +++ b/api/funkwhale_api/radios/migrations/0003_auto_20160521_1708.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('radios', '0002_radiosession_session_key'), + ] + + operations = [ + migrations.AddField( + model_name='radiosession', + name='related_object_content_type', + field=models.ForeignKey(null=True, to='contenttypes.ContentType', blank=True), + ), + migrations.AddField( + model_name='radiosession', + name='related_object_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/api/funkwhale_api/radios/migrations/__init__.py b/api/funkwhale_api/radios/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/radios/models.py b/api/funkwhale_api/radios/models.py new file mode 100644 index 000000000..a3a353132 --- /dev/null +++ b/api/funkwhale_api/radios/models.py @@ -0,0 +1,52 @@ +from django.db import models +from django.utils import timezone +from django.core.exceptions import ValidationError +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType + +from funkwhale_api.music.models import Track + +class RadioSession(models.Model): + user = models.ForeignKey('users.User', related_name='radio_sessions', null=True, blank=True) + session_key = models.CharField(max_length=100, null=True, blank=True) + radio_type = models.CharField(max_length=50) + creation_date = models.DateTimeField(default=timezone.now) + related_object_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True) + related_object_id = models.PositiveIntegerField(blank=True, null=True) + related_object = GenericForeignKey('related_object_content_type', 'related_object_id') + + def save(self, **kwargs): + if not self.user and not self.session_key: + raise ValidationError('Cannot have both session_key and user empty for radio session') + self.radio.clean(self) + super().save(**kwargs) + + @property + def next_position(self): + next_position = 1 + + last_session_track = self.session_tracks.all().order_by('-position').first() + if last_session_track: + next_position = last_session_track.position + 1 + + return next_position + + def add(self, track): + new_session_track = RadioSessionTrack.objects.create(track=track, session=self, position=self.next_position) + + return new_session_track + + @property + def radio(self): + from .registries import registry + from . import radios + return registry[self.radio_type](session=self) + +class RadioSessionTrack(models.Model): + session = models.ForeignKey(RadioSession, related_name='session_tracks') + position = models.IntegerField(default=1) + track = models.ForeignKey(Track, related_name='radio_session_tracks') + + class Meta: + ordering = ('session', 'position') + unique_together = ('session', 'position') diff --git a/api/funkwhale_api/radios/radios.py b/api/funkwhale_api/radios/radios.py new file mode 100644 index 000000000..0f2632fe9 --- /dev/null +++ b/api/funkwhale_api/radios/radios.py @@ -0,0 +1,125 @@ +import random +from django.core.exceptions import ValidationError +from taggit.models import Tag +from funkwhale_api.users.models import User +from funkwhale_api.music.models import Track, Artist +from . import models +from .registries import registry + +class SimpleRadio(object): + + def clean(self, instance): + return + + def pick(self, choices, previous_choices=[]): + return random.sample(set(choices).difference(previous_choices), 1)[0] + + def pick_many(self, choices, quantity): + return random.sample(set(choices), quantity) + + def weighted_pick(self, choices, previous_choices=[]): + total = sum(weight for c, weight in choices) + r = random.uniform(0, total) + upto = 0 + for choice, weight in choices: + if upto + weight >= r: + return choice + upto += weight + + +class SessionRadio(SimpleRadio): + def __init__(self, session=None): + self.session = session + + def start_session(self, user, **kwargs): + self.session = models.RadioSession.objects.create(user=user, radio_type=self.radio_type, **kwargs) + return self.session + + def get_queryset(self): + raise NotImplementedError + + def get_queryset_kwargs(self): + return {} + + def get_choices(self, **kwargs): + kwargs.update(self.get_queryset_kwargs()) + queryset = self.get_queryset(**kwargs) + if self.session: + queryset = self.filter_from_session(queryset) + return queryset + + def filter_from_session(self, queryset): + already_played = self.session.session_tracks.all().values_list('track', flat=True) + queryset = queryset.exclude(pk__in=already_played) + return queryset + + def pick(self, **kwargs): + return self.pick_many(quantity=1, **kwargs)[0] + + def pick_many(self, quantity, **kwargs): + choices = self.get_choices(**kwargs) + picked_choices = super().pick_many(choices=choices, quantity=quantity) + if self.session: + for choice in picked_choices: + self.session.add(choice) + return picked_choices + +@registry.register(name='random') +class RandomRadio(SessionRadio): + def get_queryset(self, **kwargs): + return Track.objects.all() + +@registry.register(name='favorites') +class FavoritesRadio(SessionRadio): + + def get_queryset_kwargs(self): + kwargs = super().get_queryset_kwargs() + if self.session: + kwargs['user'] = self.session.user + return kwargs + + def get_queryset(self, **kwargs): + track_ids = kwargs['user'].track_favorites.all().values_list('track', flat=True) + return Track.objects.filter(pk__in=track_ids) + + +class RelatedObjectRadio(SessionRadio): + """Abstract radio related to an object (tag, artist, user...)""" + + def clean(self, instance): + super().clean(instance) + if not instance.related_object: + raise ValidationError('Cannot start RelatedObjectRadio without related object') + if not isinstance(instance.related_object, self.model): + raise ValidationError('Trying to start radio with bad related object') + + def get_related_object(self, pk): + return self.model.objects.get(pk=pk) + + +@registry.register(name='tag') +class TagRadio(RelatedObjectRadio): + model = Tag + + def get_queryset(self, **kwargs): + return Track.objects.filter(tags__in=[self.session.related_object]) + +@registry.register(name='artist') +class ArtistRadio(RelatedObjectRadio): + model = Artist + + def get_queryset(self, **kwargs): + return self.session.related_object.tracks.all() + + +@registry.register(name='less-listened') +class LessListenedRadio(RelatedObjectRadio): + model = User + + def clean(self, instance): + instance.related_object = instance.user + super().clean(instance) + + def get_queryset(self, **kwargs): + listened = self.session.user.listenings.all().values_list('track', flat=True) + return Track.objects.exclude(pk__in=listened).order_by('?') diff --git a/api/funkwhale_api/radios/registries.py b/api/funkwhale_api/radios/registries.py new file mode 100644 index 000000000..eec223539 --- /dev/null +++ b/api/funkwhale_api/radios/registries.py @@ -0,0 +1,8 @@ +import persisting_theory + +class RadioRegistry(persisting_theory.Registry): + def prepare_name(self, data, name=None): + setattr(data, 'radio_type', name) + return name + +registry = RadioRegistry() diff --git a/api/funkwhale_api/radios/serializers.py b/api/funkwhale_api/radios/serializers.py new file mode 100644 index 000000000..c389e06db --- /dev/null +++ b/api/funkwhale_api/radios/serializers.py @@ -0,0 +1,35 @@ +from rest_framework import serializers + +from funkwhale_api.music.serializers import TrackSerializerNested +from . import models + + +class RadioSessionTrackSerializerCreate(serializers.ModelSerializer): + class Meta: + model = models.RadioSessionTrack + fields = ('session',) + + +class RadioSessionTrackSerializer(serializers.ModelSerializer): + track = TrackSerializerNested() + + class Meta: + model = models.RadioSessionTrack + fields = ('id', 'session', 'position', 'track') + + +class RadioSessionSerializer(serializers.ModelSerializer): + class Meta: + model = models.RadioSession + fields = ('id', 'radio_type', 'related_object_id', 'user', 'creation_date', 'session_key') + + def create(self, validated_data): + if self.context.get('user'): + validated_data['user'] = self.context.get('user') + else: + validated_data['session_key'] = self.context['session_key'] + if validated_data.get('related_object_id'): + from . import radios + radio = radios.registry[validated_data['radio_type']]() + validated_data['related_object'] = radio.get_related_object(validated_data['related_object_id']) + return super().create(validated_data) diff --git a/api/funkwhale_api/radios/tests/__init__.py b/api/funkwhale_api/radios/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/radios/tests/test_radios.py b/api/funkwhale_api/radios/tests/test_radios.py new file mode 100644 index 000000000..eb839a426 --- /dev/null +++ b/api/funkwhale_api/radios/tests/test_radios.py @@ -0,0 +1,194 @@ +import random +import json +from test_plus.test import TestCase +from django.core.urlresolvers import reverse +from django.core.exceptions import ValidationError + +from model_mommy import mommy + +from funkwhale_api.radios import radios +from funkwhale_api.radios import models +from funkwhale_api.favorites.models import TrackFavorite +from funkwhale_api.users.models import User +from funkwhale_api.music.models import Artist + +class TestRadios(TestCase): + + def setUp(self): + super().setUp() + self.user = User.objects.create_user(username='test', email='test@test.com', password='test') + + def test_can_pick_track_from_choices(self): + choices = [1, 2, 3, 4, 5] + + radio = radios.SimpleRadio() + + first_pick = radio.pick(choices=choices) + + self.assertIn(first_pick, choices) + + previous_choices = [first_pick] + for remaining_choice in choices: + pick = radio.pick(choices=choices, previous_choices=previous_choices) + self.assertIn(pick, set(choices).difference(previous_choices)) + + def test_can_pick_by_weight(self): + choices_with_weight = [ + # choice, weight + (1, 1), + (2, 2), + (3, 3), + (4, 4), + (5, 5), + ] + + picks = {choice: 0 for choice, weight in choices_with_weight} + + for i in range(1000): + radio = radios.SimpleRadio() + pick = radio.weighted_pick(choices=choices_with_weight) + picks[pick] = picks[pick] + 1 + + self.assertTrue(picks[5] > picks[4]) + self.assertTrue(picks[4] > picks[3]) + self.assertTrue(picks[3] > picks[2]) + self.assertTrue(picks[2] > picks[1]) + + def test_can_get_choices_for_favorites_radio(self): + tracks = mommy.make('music.Track', _quantity=100) + + for i in range(20): + TrackFavorite.add(track=random.choice(tracks), user=self.user) + + radio = radios.FavoritesRadio() + choices = radio.get_choices(user=self.user) + + self.assertEqual(choices.count(), self.user.track_favorites.all().count()) + + for favorite in self.user.track_favorites.all(): + self.assertIn(favorite.track, choices) + + for i in range(20): + pick = radio.pick(user=self.user) + self.assertIn(pick, choices) + + def test_can_use_radio_session_to_filter_choices(self): + tracks = mommy.make('music.Track', _quantity=30) + + radio = radios.RandomRadio() + session = radio.start_session(self.user) + + for i in range(30): + radio.pick() + + # ensure 30 differents tracks have been suggested + tracks_id = [session_track.track.pk for session_track in session.session_tracks.all()] + self.assertEqual(len(set(tracks_id)), 30) + + def test_can_restore_radio_from_previous_session(self): + tracks = mommy.make('music.Track', _quantity=30) + + radio = radios.RandomRadio() + session = radio.start_session(self.user) + + restarted_radio = radios.RandomRadio(session) + self.assertEqual(radio.session, restarted_radio.session) + + def test_can_get_start_radio_from_api(self): + url = reverse('api:radios:sessions-list') + response = self.client.post(url, {'radio_type': 'random'}) + session = models.RadioSession.objects.latest('id') + self.assertEqual(session.radio_type, 'random') + self.assertEqual(session.user, None) + + self.client.login(username=self.user.username, password='test') + response = self.client.post(url, {'radio_type': 'random'}) + session = models.RadioSession.objects.latest('id') + self.assertEqual(session.radio_type, 'random') + self.assertEqual(session.user, self.user) + + def test_can_start_radio_for_anonymous_user(self): + url = reverse('api:radios:sessions-list') + response = self.client.post(url, {'radio_type': 'random'}) + session = models.RadioSession.objects.latest('id') + + self.assertIsNone(session.user) + self.assertIsNotNone(session.session_key) + + def test_can_get_track_for_session_from_api(self): + tracks = mommy.make('music.Track', _quantity=1) + + self.client.login(username=self.user.username, password='test') + url = reverse('api:radios:sessions-list') + response = self.client.post(url, {'radio_type': 'random'}) + session = models.RadioSession.objects.latest('id') + + url = reverse('api:radios:tracks-list') + response = self.client.post(url, {'session': session.pk}) + data = json.loads(response.content.decode('utf-8')) + + self.assertEqual(data['track']['id'], tracks[0].id) + self.assertEqual(data['position'], 1) + + next_track = mommy.make('music.Track') + response = self.client.post(url, {'session': session.pk}) + data = json.loads(response.content.decode('utf-8')) + + self.assertEqual(data['track']['id'], next_track.id) + self.assertEqual(data['position'], 2) + + def test_related_object_radio_validate_related_object(self): + # cannot start without related object + radio = radios.ArtistRadio() + with self.assertRaises(ValidationError): + radio.start_session(self.user) + + # cannot start with bad related object type + radio = radios.ArtistRadio() + with self.assertRaises(ValidationError): + radio.start_session(self.user, related_object=self.user) + + def test_can_start_artist_radio(self): + artist = mommy.make('music.Artist') + wrong_tracks = mommy.make('music.Track', _quantity=30) + good_tracks = mommy.make('music.Track', artist=artist, _quantity=5) + + radio = radios.ArtistRadio() + session = radio.start_session(self.user, related_object=artist) + self.assertEqual(session.radio_type, 'artist') + for i in range(5): + self.assertIn(radio.pick(), good_tracks) + + def test_can_start_tag_radio(self): + tag = mommy.make('taggit.Tag') + wrong_tracks = mommy.make('music.Track', _quantity=30) + good_tracks = mommy.make('music.Track', _quantity=5) + for track in good_tracks: + track.tags.add(tag) + + radio = radios.TagRadio() + session = radio.start_session(self.user, related_object=tag) + self.assertEqual(session.radio_type, 'tag') + for i in range(5): + self.assertIn(radio.pick(), good_tracks) + + def test_can_start_artist_radio_from_api(self): + artist = mommy.make('music.Artist') + url = reverse('api:radios:sessions-list') + + response = self.client.post(url, {'radio_type': 'artist', 'related_object_id': artist.id}) + session = models.RadioSession.objects.latest('id') + self.assertEqual(session.radio_type, 'artist') + self.assertEqual(session.related_object, artist) + + def test_can_start_less_listened_radio(self): + history = mommy.make('history.Listening', _quantity=5, user=self.user) + wrong_tracks = [h.track for h in history] + + good_tracks = mommy.make('music.Track', _quantity=30) + + radio = radios.LessListenedRadio() + session = radio.start_session(self.user) + self.assertEqual(session.related_object, self.user) + for i in range(5): + self.assertIn(radio.pick(), good_tracks) diff --git a/api/funkwhale_api/radios/urls.py b/api/funkwhale_api/radios/urls.py new file mode 100644 index 000000000..57e47f063 --- /dev/null +++ b/api/funkwhale_api/radios/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls import include, url +from . import views + +from rest_framework import routers +router = routers.SimpleRouter() +router.register(r'sessions', views.RadioSessionViewSet, 'sessions') +router.register(r'tracks', views.RadioSessionTrackViewSet, 'tracks') + +urlpatterns = router.urls diff --git a/api/funkwhale_api/radios/views.py b/api/funkwhale_api/radios/views.py new file mode 100644 index 000000000..1ae788fcb --- /dev/null +++ b/api/funkwhale_api/radios/views.py @@ -0,0 +1,64 @@ +from rest_framework import generics, mixins, viewsets +from rest_framework import status +from rest_framework.response import Response +from rest_framework.decorators import detail_route + +from funkwhale_api.music.serializers import TrackSerializerNested +from funkwhale_api.common.permissions import ConditionalAuthentication + +from . import models +from . import serializers + +class RadioSessionViewSet(mixins.CreateModelMixin, + mixins.RetrieveModelMixin, + viewsets.GenericViewSet): + + serializer_class = serializers.RadioSessionSerializer + queryset = models.RadioSession.objects.all() + permission_classes = [ConditionalAuthentication] + + def get_queryset(self): + queryset = super().get_queryset() + if self.request.user.is_authenticated(): + return queryset.filter(user=self.request.user) + else: + return queryset.filter(session_key=self.request.session.session_key) + + def get_serializer_context(self): + context = super().get_serializer_context() + if self.request.user.is_authenticated(): + context['user'] = self.request.user + else: + context['session_key'] = self.request.session.session_key + return context + + +class RadioSessionTrackViewSet(mixins.CreateModelMixin, + viewsets.GenericViewSet): + serializer_class = serializers.RadioSessionTrackSerializer + queryset = models.RadioSessionTrack.objects.all() + permission_classes = [ConditionalAuthentication] + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + session = serializer.validated_data['session'] + try: + if request.user.is_authenticated(): + assert request.user == session.user + else: + assert request.session.session_key == session.session_key + except AssertionError: + return Response(status=status.HTTP_403_FORBIDDEN) + track = session.radio.pick() + session_track = session.session_tracks.all().latest('id') + # self.perform_create(serializer) + # dirty override here, since we use a different serializer for creation and detail + serializer = self.serializer_class(instance=session_track, context=self.get_serializer_context()) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + def get_serializer_class(self, *args, **kwargs): + if self.action == 'create': + return serializers.RadioSessionTrackSerializerCreate + return super().get_serializer_class(*args, **kwargs) diff --git a/api/funkwhale_api/static/css/project.css b/api/funkwhale_api/static/css/project.css new file mode 100644 index 000000000..08505aeef --- /dev/null +++ b/api/funkwhale_api/static/css/project.css @@ -0,0 +1,38 @@ +/* These styles are generated from project.scss. */ + +.alert-debug { + color: black; + background-color: white; + border-color: #d6e9c6; +} + +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +/* This is a fix for the bootstrap4 alpha release */ +@media (max-width: 47.9em) { + .navbar-nav .nav-item { + float: none; + width: 100%; + display: inline-block; + } + + .navbar-nav .nav-item + .nav-item { + margin-left: 0; + } + + .nav.navbar-nav.pull-right { + float: none !important; + } +} + +/* Display django-debug-toolbar. + See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742 + and https://github.com/pydanny/cookiecutter-django/issues/317 +*/ +[hidden][style="display: block;"] { + display: block !important; +} \ No newline at end of file diff --git a/api/funkwhale_api/static/fonts/.gitkeep b/api/funkwhale_api/static/fonts/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/static/images/favicon.ico b/api/funkwhale_api/static/images/favicon.ico new file mode 100644 index 000000000..e1c1dd1a3 Binary files /dev/null and b/api/funkwhale_api/static/images/favicon.ico differ diff --git a/api/funkwhale_api/static/js/project.js b/api/funkwhale_api/static/js/project.js new file mode 100644 index 000000000..d26d23b9b --- /dev/null +++ b/api/funkwhale_api/static/js/project.js @@ -0,0 +1 @@ +/* Project specific Javascript goes here. */ diff --git a/api/funkwhale_api/static/music/sample1.ogg b/api/funkwhale_api/static/music/sample1.ogg new file mode 100644 index 000000000..f2f3b7cda Binary files /dev/null and b/api/funkwhale_api/static/music/sample1.ogg differ diff --git a/api/funkwhale_api/static/sass/project.scss b/api/funkwhale_api/static/sass/project.scss new file mode 100644 index 000000000..37c69e454 --- /dev/null +++ b/api/funkwhale_api/static/sass/project.scss @@ -0,0 +1,51 @@ +// project specific CSS goes here + +// Alert colors + +$white: #fff; +$mint-green: #d6e9c6; +$black: #000; +$pink: #f2dede; +$dark-pink: #eed3d7; +$red: #b94a48; + +// bootstrap alert CSS, translated to the django-standard levels of +// debug, info, success, warning, error + +.alert-debug { + background-color: $white; + border-color: $mint-green; + color: $black; +} + +.alert-error { + background-color: $pink; + border-color: $dark-pink; + color: $red; +} + +// This is a fix for the bootstrap4 alpha release + +@media (max-width: 47.9em) { + .navbar-nav .nav-item { + display: inline-block; + float: none; + width: 100%; + } + + .navbar-nav .nav-item + .nav-item { + margin-left: 0; + } + + .nav.navbar-nav.pull-right { + float: none !important; + } +} + +// Display django-debug-toolbar. +// See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742 +// and https://github.com/pydanny/cookiecutter-django/issues/317 + +[hidden][style="display: block;"] { + display: block !important; +} diff --git a/api/funkwhale_api/taskapp/__init__.py b/api/funkwhale_api/taskapp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/taskapp/celery.py b/api/funkwhale_api/taskapp/celery.py new file mode 100644 index 000000000..795262e50 --- /dev/null +++ b/api/funkwhale_api/taskapp/celery.py @@ -0,0 +1,32 @@ + +from __future__ import absolute_import +import os +from celery import Celery +from django.apps import AppConfig +from django.conf import settings +from celery.contrib.methods import task_method + +if not settings.configured: + # set the default Django settings module for the 'celery' program. + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") # pragma: no cover + + +app = Celery('funkwhale_api') + + +class CeleryConfig(AppConfig): + name = 'funkwhale_api.taskapp' + verbose_name = 'Celery Config' + + def ready(self): + # Using a string here means the worker will not have to + # pickle the object when using Windows. + app.config_from_object('django.conf:settings') + app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True) + + + + +@app.task(bind=True) +def debug_task(self): + print('Request: {0!r}'.format(self.request)) # pragma: no cover diff --git a/api/funkwhale_api/templates/404.html b/api/funkwhale_api/templates/404.html new file mode 100644 index 000000000..b9cb60846 --- /dev/null +++ b/api/funkwhale_api/templates/404.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% block title %}Page Not found{% endblock %} + +{% block content %} +

Page Not found

+ +

This is not the page you were looking for.

+{% endblock content %} diff --git a/api/funkwhale_api/templates/500.html b/api/funkwhale_api/templates/500.html new file mode 100644 index 000000000..21df60665 --- /dev/null +++ b/api/funkwhale_api/templates/500.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% block title %}Server Error{% endblock %} + +{% block content %} +

Ooops!!! 500

+ +

Looks like something went wrong!

+ +

We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.

+{% endblock content %} + + diff --git a/api/funkwhale_api/templates/account/base.html b/api/funkwhale_api/templates/account/base.html new file mode 100644 index 000000000..c64b47a4a --- /dev/null +++ b/api/funkwhale_api/templates/account/base.html @@ -0,0 +1,2 @@ +{% extends "base.html" %} +{% block title %}{% block head_title %}{% endblock head_title %}{% endblock title %} diff --git a/api/funkwhale_api/templates/account/email.html b/api/funkwhale_api/templates/account/email.html new file mode 100644 index 000000000..7c52a4a27 --- /dev/null +++ b/api/funkwhale_api/templates/account/email.html @@ -0,0 +1,80 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load crispy_forms_tags %} + +{% block head_title %}{% trans "Account" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "E-mail Addresses" %}

+ {% if user.emailaddress_set.all %} +

{% trans 'The following e-mail addresses are associated with your account:' %}

+ + + + {% else %} +

{% trans 'Warning:'%} {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}

+ + {% endif %} + + +

{% trans "Add E-mail Address" %}

+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+
+{% endblock %} + + +{% block extra_body %} + +{% endblock %} + diff --git a/api/funkwhale_api/templates/account/email_confirm.html b/api/funkwhale_api/templates/account/email_confirm.html new file mode 100644 index 000000000..4395d46bf --- /dev/null +++ b/api/funkwhale_api/templates/account/email_confirm.html @@ -0,0 +1,37 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} + +{% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %} + + +{% block content %} +
+
+
+

{% trans "Confirm E-mail Address" %}

+ + {% if confirmation %} + + {% user_display confirmation.email_address.user as user_display %} + +

{% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}

+ +
+ {% csrf_token %} + +
+ + {% else %} + + {% url 'account_email' as email_url %} + +

{% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktrans %}

+ + {% endif %} +
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/email_confirmed.html b/api/funkwhale_api/templates/account/email_confirmed.html new file mode 100644 index 000000000..7b2edf08b --- /dev/null +++ b/api/funkwhale_api/templates/account/email_confirmed.html @@ -0,0 +1,21 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} + +{% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %} + + +{% block content %} +
+
+
+

{% trans "Confirm E-mail Address" %}

+ + {% user_display email_address.user as user_display %} + +

{% blocktrans with email_address.email as email %}You have confirmed that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}

+
+
+
+{% endblock %} diff --git a/api/funkwhale_api/templates/account/login.html b/api/funkwhale_api/templates/account/login.html new file mode 100644 index 000000000..4a05dc772 --- /dev/null +++ b/api/funkwhale_api/templates/account/login.html @@ -0,0 +1,48 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} +{% load socialaccount %} +{% load crispy_forms_tags %} + +{% block head_title %}{% trans "Sign In" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Sign In" %}

+ {% get_providers as socialaccount_providers %} + {% if socialaccount_providers %} +

{% blocktrans with site.name as site_name %}Please sign in with one + of your existing third party accounts. Or, sign up + for a {{ site_name }} account and sign in below:{% endblocktrans %}

+ +
+ +
    + {% include "socialaccount/snippets/provider_list.html" with process="login" %} +
+ + + +
+ + {% include "socialaccount/snippets/login_extra.html" %} + + {% endif %} + + +
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/logout.html b/api/funkwhale_api/templates/account/logout.html new file mode 100644 index 000000000..4f1f8f3e6 --- /dev/null +++ b/api/funkwhale_api/templates/account/logout.html @@ -0,0 +1,28 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Sign Out" %}{% endblock %} + +{% block content %} +
+
+
+ +

{% trans "Sign Out" %}

+ +

{% trans 'Are you sure you want to sign out?' %}

+ +
+ {% csrf_token %} + {% if redirect_field_value %} + + {% endif %} + +
+
+
+
+ +{% endblock %} + diff --git a/api/funkwhale_api/templates/account/password_change.html b/api/funkwhale_api/templates/account/password_change.html new file mode 100644 index 000000000..e282b14ad --- /dev/null +++ b/api/funkwhale_api/templates/account/password_change.html @@ -0,0 +1,22 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load crispy_forms_tags %} +{% block head_title %}{% trans "Change Password" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Change Password" %}

+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/password_reset.html b/api/funkwhale_api/templates/account/password_reset.html new file mode 100644 index 000000000..efdfbd05c --- /dev/null +++ b/api/funkwhale_api/templates/account/password_reset.html @@ -0,0 +1,39 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} +{% load crispy_forms_tags %} + +{% block head_title %}{% trans "Password Reset" %}{% endblock %} + +{% block content %} +
+
+
+ +

{% trans "Password Reset" %}

+ {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} + +

{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}

+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+ +

{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}

+
+
+
+{% endblock %} + +{% block javascript %} + {{ block.super }} + +{% endblock javascript %} + diff --git a/api/funkwhale_api/templates/account/password_reset_done.html b/api/funkwhale_api/templates/account/password_reset_done.html new file mode 100644 index 000000000..865ecaa0a --- /dev/null +++ b/api/funkwhale_api/templates/account/password_reset_done.html @@ -0,0 +1,22 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} + +{% block head_title %}{% trans "Password Reset" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Password Reset" %}

+ + {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} + +

{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

+
+
+
+{% endblock %} diff --git a/api/funkwhale_api/templates/account/password_reset_from_key.html b/api/funkwhale_api/templates/account/password_reset_from_key.html new file mode 100644 index 000000000..41b50843f --- /dev/null +++ b/api/funkwhale_api/templates/account/password_reset_from_key.html @@ -0,0 +1,32 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load crispy_forms_tags %} + +{% block head_title %}{% trans "Change Password" %}{% endblock %} + +{% block content %} +
+
+
+

{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}

+ + {% if token_fail %} + {% url 'account_reset_password' as passwd_reset_url %} +

{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %}

+ {% else %} + {% if form %} +
+ {% csrf_token %} + {{ form|crispy }} + +
+ {% else %} +

{% trans 'Your password is now changed.' %}

+ {% endif %} + {% endif %} +
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/password_reset_from_key_done.html b/api/funkwhale_api/templates/account/password_reset_from_key_done.html new file mode 100644 index 000000000..e940eb83d --- /dev/null +++ b/api/funkwhale_api/templates/account/password_reset_from_key_done.html @@ -0,0 +1,16 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% block head_title %}{% trans "Change Password" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Change Password" %}

+

{% trans 'Your password is now changed.' %}

+
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/password_set.html b/api/funkwhale_api/templates/account/password_set.html new file mode 100644 index 000000000..03e2fcd2d --- /dev/null +++ b/api/funkwhale_api/templates/account/password_set.html @@ -0,0 +1,23 @@ + +{% extends "account/base.html" %} + +{% load i18n crispy_forms_tags %} + +{% block head_title %}{% trans "Set Password" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Set Password" %}

+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/signup.html b/api/funkwhale_api/templates/account/signup.html new file mode 100644 index 000000000..5db1cac77 --- /dev/null +++ b/api/funkwhale_api/templates/account/signup.html @@ -0,0 +1,33 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load crispy_forms_tags %} + +{% block title %}{% trans "Signup" %}{% endblock title %} + +{% block content %} + +
+
+
+

{% trans "Sign Up" %}

+ +

{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}

+ + +
+
+
+ + +{% endblock content %} + + + diff --git a/api/funkwhale_api/templates/account/signup_closed.html b/api/funkwhale_api/templates/account/signup_closed.html new file mode 100644 index 000000000..24e93d7bc --- /dev/null +++ b/api/funkwhale_api/templates/account/signup_closed.html @@ -0,0 +1,18 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Sign Up Closed" %}

+ +

{% trans "We are sorry, but the sign up is currently closed." %}

+
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/account/verification_sent.html b/api/funkwhale_api/templates/account/verification_sent.html new file mode 100644 index 000000000..f994b46e0 --- /dev/null +++ b/api/funkwhale_api/templates/account/verification_sent.html @@ -0,0 +1,18 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Verify Your E-mail Address" %}

+ +

{% blocktrans %}We have sent an e-mail to {{ email }} for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

+
+
+
+ +{% endblock %} diff --git a/api/funkwhale_api/templates/account/verified_email_required.html b/api/funkwhale_api/templates/account/verified_email_required.html new file mode 100644 index 000000000..bf4887a4a --- /dev/null +++ b/api/funkwhale_api/templates/account/verified_email_required.html @@ -0,0 +1,28 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} + +{% block content %} +
+
+
+

{% trans "Verify Your E-mail Address" %}

+ + {% url 'account_email' as email_url %} + +

{% blocktrans %}This part of the site requires us to verify that + you are who you claim to be. For this purpose, we require that you + verify ownership of your e-mail address. {% endblocktrans %}

+ +

{% blocktrans %}We have sent an e-mail to you for + verification. Please click on the link inside this e-mail. Please + contact us if you do not receive it within a few minutes.{% endblocktrans %}

+ +

{% blocktrans %}Note: you can still change your e-mail address.{% endblocktrans %}

+
+
+
+{% endblock %} + diff --git a/api/funkwhale_api/templates/base.html b/api/funkwhale_api/templates/base.html new file mode 100644 index 000000000..e8788f44a --- /dev/null +++ b/api/funkwhale_api/templates/base.html @@ -0,0 +1,107 @@ +{% load staticfiles i18n %} + + + + + {% block title %}funkwhale_api{% endblock title %} + + + + + + + + {% block css %} + + + + + + + + {% endblock %} + + {% block angular %} + + {% endblock %} + + + + + +
+ +
+ +
+ + {% if messages %} + {% for message in messages %} +
{{ message }}
+ {% endfor %} + {% endif %} + + {% block content %} +

Use this document as a way to quick start any new project.

+ {% endblock content %} + +
+ + {% block modal %}{% endblock modal %} + + + + {% block javascript %} + + + + + + + + + + + {% endblock javascript %} + + diff --git a/api/funkwhale_api/templates/pages/about.html b/api/funkwhale_api/templates/pages/about.html new file mode 100644 index 000000000..63913c188 --- /dev/null +++ b/api/funkwhale_api/templates/pages/about.html @@ -0,0 +1 @@ +{% extends "base.html" %} \ No newline at end of file diff --git a/api/funkwhale_api/templates/pages/home.html b/api/funkwhale_api/templates/pages/home.html new file mode 100644 index 000000000..63913c188 --- /dev/null +++ b/api/funkwhale_api/templates/pages/home.html @@ -0,0 +1 @@ +{% extends "base.html" %} \ No newline at end of file diff --git a/api/funkwhale_api/templates/users/user_detail.html b/api/funkwhale_api/templates/users/user_detail.html new file mode 100644 index 000000000..f8deb6b72 --- /dev/null +++ b/api/funkwhale_api/templates/users/user_detail.html @@ -0,0 +1,36 @@ +{% extends "base.html" %} +{% load static %} + +{% block title %}User: {{ object.username }}{% endblock %} + +{% block content %} +
+ +
+
+ +

{{ object.username }}

+ {% if object.name %} +

{{ object.name }}

+ {% endif %} +
+
+ +{% if object == request.user %} + +
+ +
+ My Info + E-Mail + +
+ +
+ +{% endif %} + + +
+{% endblock content %} + diff --git a/api/funkwhale_api/templates/users/user_form.html b/api/funkwhale_api/templates/users/user_form.html new file mode 100644 index 000000000..c07b8f2fc --- /dev/null +++ b/api/funkwhale_api/templates/users/user_form.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} +{% load crispy_forms_tags %} + +{% block title %}{{ user.username }}{% endblock %} + +{% block content %} +

{{ user.username }}

+
+ {% csrf_token %} + {{ form|crispy }} +
+
+ +
+
+
+{% endblock %} diff --git a/api/funkwhale_api/templates/users/user_list.html b/api/funkwhale_api/templates/users/user_list.html new file mode 100644 index 000000000..7fbcc52d4 --- /dev/null +++ b/api/funkwhale_api/templates/users/user_list.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load static %}{% load i18n %} +{% block title %}Members{% endblock %} + +{% block content %} + +
+ +

Users

+ +
+ {% for user in user_list %} + +

{{ user.username }}

+
+ {% endfor %} + +
+ +{% endblock content %} diff --git a/api/funkwhale_api/users/__init__.py b/api/funkwhale_api/users/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/api/funkwhale_api/users/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/api/funkwhale_api/users/adapters.py b/api/funkwhale_api/users/adapters.py new file mode 100644 index 000000000..792b4860f --- /dev/null +++ b/api/funkwhale_api/users/adapters.py @@ -0,0 +1,15 @@ +from allauth.account.adapter import DefaultAccountAdapter + +from django.conf import settings + + +class FunkwhaleAccountAdapter(DefaultAccountAdapter): + + def is_open_for_signup(self, request): + + if settings.REGISTRATION_MODE == "disabled": + return False + if settings.REGISTRATION_MODE == "public": + return True + + return False diff --git a/api/funkwhale_api/users/admin.py b/api/funkwhale_api/users/admin.py new file mode 100644 index 000000000..ac3712015 --- /dev/null +++ b/api/funkwhale_api/users/admin.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +from django import forms +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin as AuthUserAdmin +from django.contrib.auth.forms import UserChangeForm, UserCreationForm + +from .models import User + + +class MyUserChangeForm(UserChangeForm): + class Meta(UserChangeForm.Meta): + model = User + + +class MyUserCreationForm(UserCreationForm): + + error_message = UserCreationForm.error_messages.update({ + 'duplicate_username': 'This username has already been taken.' + }) + + class Meta(UserCreationForm.Meta): + model = User + + def clean_username(self): + username = self.cleaned_data["username"] + try: + User.objects.get(username=username) + except User.DoesNotExist: + return username + raise forms.ValidationError(self.error_messages['duplicate_username']) + + +@admin.register(User) +class UserAdmin(AuthUserAdmin): + form = MyUserChangeForm + add_form = MyUserCreationForm diff --git a/api/funkwhale_api/users/api_urls.py b/api/funkwhale_api/users/api_urls.py new file mode 100644 index 000000000..8aba7f1a8 --- /dev/null +++ b/api/funkwhale_api/users/api_urls.py @@ -0,0 +1,7 @@ +from rest_framework import routers +from . import views + +router = routers.SimpleRouter() +router.register(r'users', views.UserViewSet, 'users') + +urlpatterns = router.urls diff --git a/api/funkwhale_api/users/middleware.py b/api/funkwhale_api/users/middleware.py new file mode 100644 index 000000000..0f572c203 --- /dev/null +++ b/api/funkwhale_api/users/middleware.py @@ -0,0 +1,6 @@ + + +class AnonymousSessionMiddleware(object): + def process_request(self, request): + if not request.session.session_key: + request.session.save() diff --git a/api/funkwhale_api/users/migrations/0001_initial.py b/api/funkwhale_api/users/migrations/0001_initial.py new file mode 100644 index 000000000..8327d2890 --- /dev/null +++ b/api/funkwhale_api/users/migrations/0001_initial.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone +import django.contrib.auth.models +import django.core.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0006_require_contenttypes_0002'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(null=True, verbose_name='last login', blank=True)), + ('is_superuser', models.BooleanField(help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status', default=False)), + ('username', models.CharField(max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], verbose_name='username', error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True)), + ('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)), + ('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)), + ('email', models.EmailField(max_length=254, verbose_name='email address', blank=True)), + ('is_staff', models.BooleanField(help_text='Designates whether the user can log into this admin site.', verbose_name='staff status', default=False)), + ('is_active', models.BooleanField(help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active', default=True)), + ('date_joined', models.DateTimeField(verbose_name='date joined', default=django.utils.timezone.now)), + ('groups', models.ManyToManyField(related_name='user_set', blank=True, verbose_name='groups', to='auth.Group', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_query_name='user')), + ('user_permissions', models.ManyToManyField(related_name='user_set', blank=True, verbose_name='user permissions', to='auth.Permission', help_text='Specific permissions for this user.', related_query_name='user')), + ('name', models.CharField(max_length=255, verbose_name='Name of User', blank=True)), + ], + options={ + 'verbose_name': 'user', + 'abstract': False, + 'verbose_name_plural': 'users', + }, + managers=[ + (b'objects', django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/api/funkwhale_api/users/migrations/__init__.py b/api/funkwhale_api/users/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py new file mode 100644 index 000000000..1abbbb51f --- /dev/null +++ b/api/funkwhale_api/users/models.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals, absolute_import + +from django.contrib.auth.models import AbstractUser +from django.core.urlresolvers import reverse +from django.db import models +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext_lazy as _ + + +@python_2_unicode_compatible +class User(AbstractUser): + + # First Name and Last Name do not cover name patterns + # around the globe. + name = models.CharField(_("Name of User"), blank=True, max_length=255) + + # permissions that are used for API access and that worth serializing + relevant_permissions = { + # internal_codename : {external_codename} + 'music.add_importbatch': { + 'external_codename': 'import.launch' + } + } + + def __str__(self): + return self.username + + def get_absolute_url(self): + return reverse('users:detail', kwargs={'username': self.username}) diff --git a/api/funkwhale_api/users/rest_auth_urls.py b/api/funkwhale_api/users/rest_auth_urls.py new file mode 100644 index 000000000..9770e69e4 --- /dev/null +++ b/api/funkwhale_api/users/rest_auth_urls.py @@ -0,0 +1,24 @@ +from django.views.generic import TemplateView +from django.conf.urls import url + +from rest_auth.registration.views import VerifyEmailView +from .views import RegisterView + +urlpatterns = [ + url(r'^$', RegisterView.as_view(), name='rest_register'), + url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'), + + # This url is used by django-allauth and empty TemplateView is + # defined just to allow reverse() call inside app, for example when email + # with verification link is being sent, then it's required to render email + # content. + + # account_confirm_email - You should override this view to handle it in + # your API client somehow and then, send post to /verify-email/ endpoint + # with proper key. + # If you don't want to use API on that step, then just use ConfirmEmailView + # view from: + # djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190 + url(r'^account-confirm-email/(?P\w+)/$', TemplateView.as_view(), + name='account_confirm_email'), +] diff --git a/api/funkwhale_api/users/serializers.py b/api/funkwhale_api/users/serializers.py new file mode 100644 index 000000000..261873bdb --- /dev/null +++ b/api/funkwhale_api/users/serializers.py @@ -0,0 +1,29 @@ +from rest_framework import serializers + +from . import models + + +class UserSerializer(serializers.ModelSerializer): + + permissions = serializers.SerializerMethodField() + + class Meta: + model = models.User + fields = [ + 'id', + 'username', + 'name', + 'email', + 'is_staff', + 'is_superuser', + 'permissions', + 'date_joined', + ] + + def get_permissions(self, o): + perms = {} + for internal_codename, conf in o.relevant_permissions.items(): + perms[conf['external_codename']] = { + 'status': o.has_perm(internal_codename) + } + return perms diff --git a/api/funkwhale_api/users/tests/__init__.py b/api/funkwhale_api/users/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/funkwhale_api/users/tests/factories.py b/api/funkwhale_api/users/tests/factories.py new file mode 100644 index 000000000..351884ff4 --- /dev/null +++ b/api/funkwhale_api/users/tests/factories.py @@ -0,0 +1,30 @@ +import factory + +from django.contrib.auth.models import Permission + + +class UserFactory(factory.django.DjangoModelFactory): + username = factory.Sequence(lambda n: 'user-{0}'.format(n)) + email = factory.Sequence(lambda n: 'user-{0}@example.com'.format(n)) + password = factory.PostGenerationMethodCall('set_password', 'password') + + class Meta: + model = 'users.User' + django_get_or_create = ('username', ) + + @factory.post_generation + def perms(self, create, extracted, **kwargs): + if not create: + # Simple build, do nothing. + return + + if extracted: + perms = [ + Permission.objects.get( + content_type__app_label=p.split('.')[0], + codename=p.split('.')[1], + ) + for p in extracted + ] + # A list of permissions were passed in, use them + self.user_permissions.add(*perms) diff --git a/api/funkwhale_api/users/tests/test_admin.py b/api/funkwhale_api/users/tests/test_admin.py new file mode 100644 index 000000000..10b07b749 --- /dev/null +++ b/api/funkwhale_api/users/tests/test_admin.py @@ -0,0 +1,40 @@ +from test_plus.test import TestCase + +from ..admin import MyUserCreationForm + + +class TestMyUserCreationForm(TestCase): + + def setUp(self): + self.user = self.make_user() + + def test_clean_username_success(self): + # Instantiate the form with a new username + form = MyUserCreationForm({ + 'username': 'alamode', + 'password1': '123456', + 'password2': '123456', + }) + # Run is_valid() to trigger the validation + valid = form.is_valid() + self.assertTrue(valid) + + # Run the actual clean_username method + username = form.clean_username() + self.assertEqual('alamode', username) + + def test_clean_username_false(self): + # Instantiate the form with the same username as self.user + form = MyUserCreationForm({ + 'username': self.user.username, + 'password1': '123456', + 'password2': '123456', + }) + # Run is_valid() to trigger the validation, which is going to fail + # because the username is already taken + valid = form.is_valid() + self.assertFalse(valid) + + # The form.errors dict should contain a single error called 'username' + self.assertTrue(len(form.errors) == 1) + self.assertTrue('username' in form.errors) diff --git a/api/funkwhale_api/users/tests/test_models.py b/api/funkwhale_api/users/tests/test_models.py new file mode 100644 index 000000000..fbc7eb5f9 --- /dev/null +++ b/api/funkwhale_api/users/tests/test_models.py @@ -0,0 +1,13 @@ +from test_plus.test import TestCase + + +class TestUser(TestCase): + + def setUp(self): + self.user = self.make_user() + + def test__str__(self): + self.assertEqual( + self.user.__str__(), + "testuser" # This is the default username for self.make_user() + ) diff --git a/api/funkwhale_api/users/tests/test_views.py b/api/funkwhale_api/users/tests/test_views.py new file mode 100644 index 000000000..5f8233bc6 --- /dev/null +++ b/api/funkwhale_api/users/tests/test_views.py @@ -0,0 +1,65 @@ +import json + +from django.test import RequestFactory + +from test_plus.test import TestCase +from funkwhale_api.users.models import User + +from . factories import UserFactory + + +class UserTestCase(TestCase): + + def setUp(self): + self.user = self.make_user() + self.factory = RequestFactory() + + def test_can_create_user_via_api(self): + url = self.reverse('rest_register') + data = { + 'username': 'test1', + 'email': 'test1@test.com', + 'password1': 'testtest', + 'password2': 'testtest', + } + with self.settings(REGISTRATION_MODE="public"): + response = self.client.post(url, data) + self.assertEqual(response.status_code, 201) + + u = User.objects.get(email='test1@test.com') + self.assertEqual(u.username, 'test1') + + def test_can_disable_registration_view(self): + url = self.reverse('rest_register') + data = { + 'username': 'test1', + 'email': 'test1@test.com', + 'password1': 'testtest', + 'password2': 'testtest', + } + with self.settings(REGISTRATION_MODE="disabled"): + response = self.client.post(url, data) + self.assertEqual(response.status_code, 403) + + def test_can_fetch_data_from_api(self): + url = self.reverse('api:users:users-me') + response = self.client.get(url) + # login required + self.assertEqual(response.status_code, 401) + + user = UserFactory(is_staff=True, perms=['music.add_importbatch']) + self.assertTrue(user.has_perm('music.add_importbatch')) + self.login(user) + + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + payload = json.loads(response.content.decode('utf-8')) + + self.assertEqual(payload['username'], user.username) + self.assertEqual(payload['is_staff'], user.is_staff) + self.assertEqual(payload['is_superuser'], user.is_superuser) + self.assertEqual(payload['email'], user.email) + self.assertEqual(payload['name'], user.name) + self.assertEqual( + payload['permissions']['import.launch']['status'], True) diff --git a/api/funkwhale_api/users/urls.py b/api/funkwhale_api/users/urls.py new file mode 100644 index 000000000..94b18b264 --- /dev/null +++ b/api/funkwhale_api/users/urls.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +from django.conf.urls import url + +from . import views + +urlpatterns = [ + +] diff --git a/api/funkwhale_api/users/views.py b/api/funkwhale_api/users/views.py new file mode 100644 index 000000000..b7c1df28f --- /dev/null +++ b/api/funkwhale_api/users/views.py @@ -0,0 +1,34 @@ +from rest_framework.response import Response +from rest_framework import viewsets +from rest_framework.decorators import list_route + +from rest_auth.registration.views import RegisterView as BaseRegisterView +from allauth.account.adapter import get_adapter + +from . import models +from . import serializers + + +class RegisterView(BaseRegisterView): + + def create(self, request, *args, **kwargs): + if not self.is_open_for_signup(request): + r = { + 'detail': 'Registration has been disabled', + } + return Response(r, status=403) + return super().create(request, *args, **kwargs) + + def is_open_for_signup(self, request): + return get_adapter().is_open_for_signup(request) + + +class UserViewSet(viewsets.GenericViewSet): + queryset = models.User.objects.all() + serializer_class = serializers.UserSerializer + + @list_route(methods=['get']) + def me(self, request, *args, **kwargs): + """Return information about the current user""" + serializer = self.serializer_class(request.user) + return Response(serializer.data) diff --git a/api/funkwhale_api/utils/tests.py b/api/funkwhale_api/utils/tests.py new file mode 100644 index 000000000..2605d3b4c --- /dev/null +++ b/api/funkwhale_api/utils/tests.py @@ -0,0 +1,12 @@ +import tempfile +import shutil + + +class TMPDirTestCaseMixin(object): + def setUp(self): + super().tearDown() + self.download_dir = tempfile.mkdtemp() + + def tearDown(self): + super().tearDown() + shutil.rmtree(self.download_dir) diff --git a/api/install_os_dependencies.sh b/api/install_os_dependencies.sh new file mode 100755 index 000000000..aea9dec45 --- /dev/null +++ b/api/install_os_dependencies.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +OS_REQUIREMENTS_FILENAME="requirements.apt" + +# Handle call with wrong command +function wrong_command() +{ + echo "${0##*/} - unknown command: '${1}'" + usage_message +} + +# Print help / script usage +function usage_message() +{ + echo "usage: ./${0##*/} " + echo "available commands are:" + echo -e "\tlist\t\tPrint a list of all packages defined on ${OS_REQUIREMENTS_FILENAME} file" + echo -e "\thelp\t\tPrint this help" + echo -e "\n\tCommands that require superuser permission:" + echo -e "\tinstall\t\tInstall packages defined on ${OS_REQUIREMENTS_FILENAME} file. Note: This\n\t\t\t does not upgrade the packages already installed for new\n\t\t\t versions, even if new version is available in the repository." + echo -e "\tupgrade\t\tSame that install, but upgrate the already installed packages,\n\t\t\t if new version is available." + +} + +# Read the requirements.apt file, and remove comments and blank lines +function list_packages(){ + grep -v "#" ${OS_REQUIREMENTS_FILENAME} | grep -v "^$"; +} + +function install() +{ + list_packages | xargs apt-get --no-upgrade install -y; +} + +function upgrade() +{ + list_packages | xargs apt-get install -y; +} + + +function install_or_upgrade() +{ + P=${1} + PARAN=${P:-"install"} + + if [[ $EUID -ne 0 ]]; then + echo -e "\nYou must run this with root privilege" 2>&1 + echo -e "Please do:\n" 2>&1 + echo "sudo ./${0##*/} $PARAN" 2>&1 + echo -e "\n" 2>&1 + + exit 1 + else + + apt-get update + + # Install the basic compilation dependencies and other required libraries of this project + if [ "$PARAN" == "install" ]; then + install; + else + upgrade; + fi + + # cleaning downloaded packages from apt-get cache + apt-get clean + + exit 0 + fi + + +} + + +# Handle command argument +case "$1" in + install) install_or_upgrade;; + upgrade) install_or_upgrade "upgrade";; + list) list_packages;; + help) usage_message;; + *) wrong_command $1;; +esac + diff --git a/api/install_python_dependencies.sh b/api/install_python_dependencies.sh new file mode 100755 index 000000000..34929e607 --- /dev/null +++ b/api/install_python_dependencies.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +pip --version >/dev/null 2>&1 || { + echo >&2 -e "\npip is required but it's not installed." + echo >&2 -e "You can install it by running the following command:\n" + echo >&2 "wget https://bootstrap.pypa.io/get-pip.py --output-document=get-pip.py; chmod +x get-pip.py; sudo -H python3 get-pip.py" + echo >&2 -e "\n" + echo >&2 -e "\nFor more information, see pip documentation: https://pip.pypa.io/en/latest/" + exit 1; +} + +virtualenv --version >/dev/null 2>&1 || { + echo >&2 -e "\nvirtualenv is required but it's not installed." + echo >&2 -e "You can install it by running the following command:\n" + echo >&2 "sudo -H pip3 install virtualenv" + echo >&2 -e "\n" + echo >&2 -e "\nFor more information, see virtualenv documentation: https://virtualenv.pypa.io/en/latest/" + exit 1; +} + +if [ -z "$VIRTUAL_ENV" ]; then + echo >&2 -e "\nYou need activate a virtualenv first" + echo >&2 -e 'If you do not have a virtualenv created, run the following command to create and automatically activate a new virtualenv named "venv" on current folder:\n' + echo >&2 -e "virtualenv venv --python=\`which python3\`" + echo >&2 -e "\nTo leave/disable the currently active virtualenv, run the following command:\n" + echo >&2 "deactivate" + echo >&2 -e "\nTo activate the virtualenv again, run the following command:\n" + echo >&2 "source venv/bin/activate" + echo >&2 -e "\nFor more information, see virtualenv documentation: https://virtualenv.pypa.io/en/latest/" + echo >&2 -e "\n" + exit 1; +else + + pip install -r requirements/local.txt + pip install -r requirements/test.txt + pip install -r requirements.txt +fi diff --git a/api/manage.py b/api/manage.py new file mode 100755 index 000000000..7b367ffeb --- /dev/null +++ b/api/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/api/requirements.apt b/api/requirements.apt new file mode 100644 index 000000000..68eaf2881 --- /dev/null +++ b/api/requirements.apt @@ -0,0 +1,46 @@ +##basic build dependencies of various Django apps for Ubuntu 14.04 +#build-essential metapackage install: make, gcc, g++, +build-essential +#required to translate +gettext +#python-dev + +##shared dependencies of: +##Pillow, pylibmc +zlib1g-dev + +##Postgresql and psycopg2 dependencies +libpq-dev +postgresql-client +##Pillow dependencies +#libtiff4-dev +#libjpeg8-dev +#libfreetype6-dev +#liblcms1-dev +#libwebp-dev + + +##django-extensions +#graphviz-dev + +##hitch +#python-setuptools +#python3-dev +#python-virtualenv +#python-pip +#firefox +#automake +#libtool +#libreadline6 +#libreadline6-dev +#libreadline-dev +libsqlite3-dev +#libxml2 +#libxml2-dev +#libssl-dev +#libbz2-dev +#wget +#curl +#llvm + +libav-tools diff --git a/api/requirements.txt b/api/requirements.txt new file mode 100644 index 000000000..d1197135e --- /dev/null +++ b/api/requirements.txt @@ -0,0 +1,3 @@ +# This file is here because many Platforms as a Service look for +# requirements.txt in the root directory of a project. +-r requirements/production.txt diff --git a/api/requirements/base.txt b/api/requirements/base.txt new file mode 100644 index 000000000..626525572 --- /dev/null +++ b/api/requirements/base.txt @@ -0,0 +1,62 @@ +# Bleeding edge Django +django==1.8.7 + +# Configuration +django-environ==0.4.0 +django-secure==1.0.1 +whitenoise==2.0.6 + + +# Forms +django-braces==1.8.1 +# django-crispy-forms==1.5.2 +# django-floppyforms==1.5.2 + +# Models +django-model-utils==2.3.1 + +# Images +Pillow==3.0.0 + +# For user registration, either via email or social +# Well-built with regular release cycles! +django-allauth==0.24.1 + + +# Python-PostgreSQL Database Adapter +psycopg2==2.6.1 + +# Unicode slugification +unicode-slugify==0.1.3 +django-autoslug==1.9.3 + +# Time zones support +pytz==2015.7 + +# Redis support +django-redis==4.3.0 +redis>=2.10.0 + + +celery==3.1.19 + + +# Your custom requirements go here +django-cors-headers +musicbrainzngs +youtube_dl>=2015.12.21 +djangorestframework +djangorestframework-jwt +django-celery +django-mptt +google-api-python-client +arrow +django-taggit +persisting_theory +django-versatileimagefield +django-cachalot +django-rest-auth +beautifulsoup4 +markdown +ipython +mutagen diff --git a/api/requirements/local.txt b/api/requirements/local.txt new file mode 100644 index 000000000..ff8f35c74 --- /dev/null +++ b/api/requirements/local.txt @@ -0,0 +1,15 @@ +# Local development dependencies go here +-r base.txt +coverage==4.0.3 +django_coverage_plugin==1.1 +Sphinx +django-extensions==1.5.9 +Werkzeug==0.11.2 +django-test-plus==1.0.11 +factory_boy==2.6.0 + +# django-debug-toolbar that works with Django 1.5+ +django-debug-toolbar>=1.5,<1.6 + +# improved REPL +ipdb==0.8.1 diff --git a/api/requirements/production.txt b/api/requirements/production.txt new file mode 100644 index 000000000..10d05fd34 --- /dev/null +++ b/api/requirements/production.txt @@ -0,0 +1,13 @@ +# Pro-tip: Try not to put anything here. There should be no dependency in +# production that isn't in development. +-r base.txt + + + +# WSGI Handler +# ------------------------------------------------ + +# there's no python 3 support in stable, have to use the latest release candidate for gevent +gevent==1.1rc1 + +gunicorn==19.4.1 diff --git a/api/requirements/test.txt b/api/requirements/test.txt new file mode 100644 index 000000000..e3540b72d --- /dev/null +++ b/api/requirements/test.txt @@ -0,0 +1,12 @@ +# Test dependencies go here. +-r base.txt + + + +coverage==4.0.3 +django_coverage_plugin==1.1 +flake8==2.5.0 +django-test-plus==1.0.11 +factory_boy==2.6.0 +model_mommy +tox diff --git a/api/runtests b/api/runtests new file mode 100755 index 000000000..bd8db7a84 --- /dev/null +++ b/api/runtests @@ -0,0 +1,5 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +docker-compose -f $DIR/test.yml run test python manage.py test "$@" diff --git a/api/setup.cfg b/api/setup.cfg new file mode 100644 index 000000000..c18b80d95 --- /dev/null +++ b/api/setup.cfg @@ -0,0 +1,7 @@ +[flake8] +max-line-length = 120 +exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules + +[pep8] +max-line-length = 120 +exclude=.tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules diff --git a/api/test.yml b/api/test.yml new file mode 100644 index 000000000..c28a8138c --- /dev/null +++ b/api/test.yml @@ -0,0 +1,9 @@ +test: + dockerfile: docker/Dockerfile.test + build: . + command: python manage.py test + volumes: + - .:/app + environment: + - DJANGO_SETTINGS_MODULE=config.settings.test + - API_AUTHENTICATION_REQUIRED=False diff --git a/dev.yml b/dev.yml new file mode 100644 index 000000000..2144d4b16 --- /dev/null +++ b/dev.yml @@ -0,0 +1,63 @@ +version: '2' + +services: + + front: + build: + dockerfile: docker/Dockerfile.dev + context: ./front + env_file: .env.dev + environment: + - "HOST=0.0.0.0" + ports: + - "8080:8080" + volumes: + - './front:/app' + - /app/node_modules + + postgres: + env_file: .env.dev + image: postgres + + redis: + env_file: .env.dev + image: redis:3.0 + + celeryworker: + env_file: .env.dev + build: + context: ./api + dockerfile: docker/Dockerfile.local + links: + - postgres + - redis + command: python manage.py celery worker + environment: + - C_FORCE_ROOT=true + volumes: + - ./api:/app + + api: + env_file: .env.dev + build: + context: ./api + dockerfile: docker/Dockerfile.local + command: python /app/manage.py runserver 0.0.0.0:12081 + volumes: + - ./api:/app + ports: + - "12081" + links: + - postgres + - redis + - celeryworker + + nginx: + env_file: .env.dev + build: ./api/compose/nginx + links: + - api + volumes: + - ./api/funkwhale_api/media:/staticfiles/media + ports: + - "0.0.0.0:6001:80" diff --git a/front/.babelrc b/front/.babelrc new file mode 100644 index 000000000..13f0e4716 --- /dev/null +++ b/front/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + ["env", { "modules": false }], + "stage-2" + ], + "plugins": ["transform-runtime"], + "comments": false, + "env": { + "test": { + "presets": ["env", "stage-2"], + "plugins": [ "istanbul" ] + } + } +} diff --git a/front/.eslintignore b/front/.eslintignore new file mode 100644 index 000000000..34af3774f --- /dev/null +++ b/front/.eslintignore @@ -0,0 +1,2 @@ +build/*.js +config/*.js diff --git a/front/.eslintrc.js b/front/.eslintrc.js new file mode 100644 index 000000000..67c085d60 --- /dev/null +++ b/front/.eslintrc.js @@ -0,0 +1,27 @@ +// http://eslint.org/docs/user-guide/configuring + +module.exports = { + root: true, + parser: 'babel-eslint', + parserOptions: { + sourceType: 'module' + }, + env: { + browser: true, + }, + // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style + extends: 'standard', + // required to lint *.vue files + plugins: [ + 'html' + ], + // add your custom rules here + 'rules': { + // allow paren-less arrow functions + 'arrow-parens': 0, + // allow async-await + 'generator-star-spacing': 0, + // allow debugger during development + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 + } +} diff --git a/front/.postcssrc.js b/front/.postcssrc.js new file mode 100644 index 000000000..ea9a5ab87 --- /dev/null +++ b/front/.postcssrc.js @@ -0,0 +1,8 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + "plugins": { + // to edit target browsers: use "browserlist" field in package.json + "autoprefixer": {} + } +} diff --git a/front/Dockerfile b/front/Dockerfile new file mode 100644 index 000000000..ad05f72eb --- /dev/null +++ b/front/Dockerfile @@ -0,0 +1,13 @@ +FROM node:6-alpine + +EXPOSE 8080 + +RUN mkdir /app +WORKDIR /app +ADD package.json . + +RUN npm install + +ADD . . + +RUN npm run build diff --git a/front/build/build.js b/front/build/build.js new file mode 100644 index 000000000..6b8add100 --- /dev/null +++ b/front/build/build.js @@ -0,0 +1,35 @@ +require('./check-versions')() + +process.env.NODE_ENV = 'production' + +var ora = require('ora') +var rm = require('rimraf') +var path = require('path') +var chalk = require('chalk') +var webpack = require('webpack') +var config = require('../config') +var webpackConfig = require('./webpack.prod.conf') + +var spinner = ora('building for production...') +spinner.start() + +rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { + if (err) throw err + webpack(webpackConfig, function (err, stats) { + spinner.stop() + if (err) throw err + process.stdout.write(stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false + }) + '\n\n') + + console.log(chalk.cyan(' Build complete.\n')) + console.log(chalk.yellow( + ' Tip: built files are meant to be served over an HTTP server.\n' + + ' Opening index.html over file:// won\'t work.\n' + )) + }) +}) diff --git a/front/build/check-versions.js b/front/build/check-versions.js new file mode 100644 index 000000000..100f3a0fe --- /dev/null +++ b/front/build/check-versions.js @@ -0,0 +1,48 @@ +var chalk = require('chalk') +var semver = require('semver') +var packageConfig = require('../package.json') +var shell = require('shelljs') +function exec (cmd) { + return require('child_process').execSync(cmd).toString().trim() +} + +var versionRequirements = [ + { + name: 'node', + currentVersion: semver.clean(process.version), + versionRequirement: packageConfig.engines.node + }, +] + +if (shell.which('npm')) { + versionRequirements.push({ + name: 'npm', + currentVersion: exec('npm --version'), + versionRequirement: packageConfig.engines.npm + }) +} + +module.exports = function () { + var warnings = [] + for (var i = 0; i < versionRequirements.length; i++) { + var mod = versionRequirements[i] + if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { + warnings.push(mod.name + ': ' + + chalk.red(mod.currentVersion) + ' should be ' + + chalk.green(mod.versionRequirement) + ) + } + } + + if (warnings.length) { + console.log('') + console.log(chalk.yellow('To use this template, you must update following to modules:')) + console.log() + for (var i = 0; i < warnings.length; i++) { + var warning = warnings[i] + console.log(' ' + warning) + } + console.log() + process.exit(1) + } +} diff --git a/front/build/dev-client.js b/front/build/dev-client.js new file mode 100644 index 000000000..18aa1e219 --- /dev/null +++ b/front/build/dev-client.js @@ -0,0 +1,9 @@ +/* eslint-disable */ +require('eventsource-polyfill') +var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') + +hotClient.subscribe(function (event) { + if (event.action === 'reload') { + window.location.reload() + } +}) diff --git a/front/build/dev-server.js b/front/build/dev-server.js new file mode 100644 index 000000000..634a6d41e --- /dev/null +++ b/front/build/dev-server.js @@ -0,0 +1,92 @@ +require('./check-versions')() + +var config = require('../config') +if (!process.env.NODE_ENV) { + process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) +} + +var opn = require('opn') +var path = require('path') +var express = require('express') +var webpack = require('webpack') +var proxyMiddleware = require('http-proxy-middleware') +var webpackConfig = process.env.NODE_ENV === 'testing' + ? require('./webpack.prod.conf') + : require('./webpack.dev.conf') + +// default port where dev server listens for incoming traffic +var port = process.env.PORT || config.dev.port +var host = process.env.HOST || config.dev.host +// automatically open browser, if not set will be false +var autoOpenBrowser = !!config.dev.autoOpenBrowser +// Define HTTP proxies to your custom API backend +// https://github.com/chimurai/http-proxy-middleware +var proxyTable = config.dev.proxyTable + +var app = express() +var compiler = webpack(webpackConfig) + +var devMiddleware = require('webpack-dev-middleware')(compiler, { + publicPath: webpackConfig.output.publicPath, + quiet: true +}) + +var hotMiddleware = require('webpack-hot-middleware')(compiler, { + log: () => {} +}) +// force page reload when html-webpack-plugin template changes +compiler.plugin('compilation', function (compilation) { + compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { + hotMiddleware.publish({ action: 'reload' }) + cb() + }) +}) + +// proxy api requests +Object.keys(proxyTable).forEach(function (context) { + var options = proxyTable[context] + if (typeof options === 'string') { + options = { target: options } + } + app.use(proxyMiddleware(options.filter || context, options)) +}) + +// handle fallback for HTML5 history API +app.use(require('connect-history-api-fallback')()) + +// serve webpack bundle output +app.use(devMiddleware) + +// enable hot-reload and state-preserving +// compilation error display +app.use(hotMiddleware) + +// serve pure static assets +var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) +app.use(staticPath, express.static('./static')) + +var uri = 'http://' + host + ':' + port + +var _resolve +var readyPromise = new Promise(resolve => { + _resolve = resolve +}) + +console.log('> Starting dev server...') +devMiddleware.waitUntilValid(() => { + console.log('> Listening at ' + uri + '\n') + // when env is testing, don't need open it + if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { + opn(uri) + } + _resolve() +}) + +var server = app.listen(port, host) + +module.exports = { + ready: readyPromise, + close: () => { + server.close() + } +} diff --git a/front/build/utils.js b/front/build/utils.js new file mode 100644 index 000000000..b1d54b4d6 --- /dev/null +++ b/front/build/utils.js @@ -0,0 +1,71 @@ +var path = require('path') +var config = require('../config') +var ExtractTextPlugin = require('extract-text-webpack-plugin') + +exports.assetsPath = function (_path) { + var assetsSubDirectory = process.env.NODE_ENV === 'production' + ? config.build.assetsSubDirectory + : config.dev.assetsSubDirectory + return path.posix.join(assetsSubDirectory, _path) +} + +exports.cssLoaders = function (options) { + options = options || {} + + var cssLoader = { + loader: 'css-loader', + options: { + minimize: process.env.NODE_ENV === 'production', + sourceMap: options.sourceMap + } + } + + // generate loader string to be used with extract text plugin + function generateLoaders (loader, loaderOptions) { + var loaders = [cssLoader] + if (loader) { + loaders.push({ + loader: loader + '-loader', + options: Object.assign({}, loaderOptions, { + sourceMap: options.sourceMap + }) + }) + } + + // Extract CSS when that option is specified + // (which is the case during production build) + if (options.extract) { + return ExtractTextPlugin.extract({ + use: loaders, + fallback: 'vue-style-loader' + }) + } else { + return ['vue-style-loader'].concat(loaders) + } + } + + // https://vue-loader.vuejs.org/en/configurations/extract-css.html + return { + css: generateLoaders(), + postcss: generateLoaders(), + less: generateLoaders('less'), + sass: generateLoaders('sass', { indentedSyntax: true }), + scss: generateLoaders('sass'), + stylus: generateLoaders('stylus'), + styl: generateLoaders('stylus') + } +} + +// Generate loaders for standalone style files (outside of .vue) +exports.styleLoaders = function (options) { + var output = [] + var loaders = exports.cssLoaders(options) + for (var extension in loaders) { + var loader = loaders[extension] + output.push({ + test: new RegExp('\\.' + extension + '$'), + use: loader + }) + } + return output +} diff --git a/front/build/vue-loader.conf.js b/front/build/vue-loader.conf.js new file mode 100644 index 000000000..7aee79bae --- /dev/null +++ b/front/build/vue-loader.conf.js @@ -0,0 +1,12 @@ +var utils = require('./utils') +var config = require('../config') +var isProduction = process.env.NODE_ENV === 'production' + +module.exports = { + loaders: utils.cssLoaders({ + sourceMap: isProduction + ? config.build.productionSourceMap + : config.dev.cssSourceMap, + extract: isProduction + }) +} diff --git a/front/build/webpack.base.conf.js b/front/build/webpack.base.conf.js new file mode 100644 index 000000000..f47b326bf --- /dev/null +++ b/front/build/webpack.base.conf.js @@ -0,0 +1,67 @@ +var path = require('path') +var utils = require('./utils') +var config = require('../config') +var vueLoaderConfig = require('./vue-loader.conf') + +function resolve (dir) { + return path.join(__dirname, '..', dir) +} + +module.exports = { + entry: { + app: './src/main.js' + }, + output: { + path: config.build.assetsRoot, + filename: '[name].js', + publicPath: process.env.NODE_ENV === 'production' + ? config.build.assetsPublicPath + : config.dev.assetsPublicPath + }, + resolve: { + extensions: ['.js', '.vue', '.json'], + alias: { + 'vue$': 'vue/dist/vue.esm.js', + '@': resolve('src') + } + }, + module: { + rules: [ + { + test: /\.(js|vue)$/, + loader: 'eslint-loader', + enforce: 'pre', + include: [resolve('src'), resolve('test')], + options: { + formatter: require('eslint-friendly-formatter') + } + }, + { + test: /\.vue$/, + loader: 'vue-loader', + options: vueLoaderConfig + }, + { + test: /\.js$/, + loader: 'babel-loader', + include: [resolve('src'), resolve('test')] + }, + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('img/[name].[hash:7].[ext]') + } + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('fonts/[name].[hash:7].[ext]') + } + } + ] + } +} diff --git a/front/build/webpack.dev.conf.js b/front/build/webpack.dev.conf.js new file mode 100644 index 000000000..5470402d0 --- /dev/null +++ b/front/build/webpack.dev.conf.js @@ -0,0 +1,35 @@ +var utils = require('./utils') +var webpack = require('webpack') +var config = require('../config') +var merge = require('webpack-merge') +var baseWebpackConfig = require('./webpack.base.conf') +var HtmlWebpackPlugin = require('html-webpack-plugin') +var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') + +// add hot-reload related code to entry chunks +Object.keys(baseWebpackConfig.entry).forEach(function (name) { + baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) +}) + +module.exports = merge(baseWebpackConfig, { + module: { + rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) + }, + // cheap-module-eval-source-map is faster for development + devtool: '#cheap-module-eval-source-map', + plugins: [ + new webpack.DefinePlugin({ + 'process.env': config.dev.env + }), + // https://github.com/glenjamin/webpack-hot-middleware#installation--usage + new webpack.HotModuleReplacementPlugin(), + new webpack.NoEmitOnErrorsPlugin(), + // https://github.com/ampedandwired/html-webpack-plugin + new HtmlWebpackPlugin({ + filename: 'index.html', + template: 'index.html', + inject: true + }), + new FriendlyErrorsPlugin() + ] +}) diff --git a/front/build/webpack.prod.conf.js b/front/build/webpack.prod.conf.js new file mode 100644 index 000000000..99713cc42 --- /dev/null +++ b/front/build/webpack.prod.conf.js @@ -0,0 +1,124 @@ +var path = require('path') +var utils = require('./utils') +var webpack = require('webpack') +var config = require('../config') +var merge = require('webpack-merge') +var baseWebpackConfig = require('./webpack.base.conf') +var CopyWebpackPlugin = require('copy-webpack-plugin') +var HtmlWebpackPlugin = require('html-webpack-plugin') +var ExtractTextPlugin = require('extract-text-webpack-plugin') +var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') + +var env = process.env.NODE_ENV === 'testing' + ? require('../config/test.env') + : config.build.env + +var webpackConfig = merge(baseWebpackConfig, { + module: { + rules: utils.styleLoaders({ + sourceMap: config.build.productionSourceMap, + extract: true + }) + }, + devtool: config.build.productionSourceMap ? '#source-map' : false, + output: { + path: config.build.assetsRoot, + filename: utils.assetsPath('js/[name].[chunkhash].js'), + chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') + }, + plugins: [ + // http://vuejs.github.io/vue-loader/en/workflow/production.html + new webpack.DefinePlugin({ + 'process.env': env + }), + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false + }, + sourceMap: true + }), + // extract css into its own file + new ExtractTextPlugin({ + filename: utils.assetsPath('css/[name].[contenthash].css') + }), + // Compress extracted CSS. We are using this plugin so that possible + // duplicated CSS from different components can be deduped. + new OptimizeCSSPlugin({ + cssProcessorOptions: { + safe: true + } + }), + // generate dist index.html with correct asset hash for caching. + // you can customize output by editing /index.html + // see https://github.com/ampedandwired/html-webpack-plugin + new HtmlWebpackPlugin({ + filename: process.env.NODE_ENV === 'testing' + ? 'index.html' + : config.build.index, + template: 'index.html', + inject: true, + minify: { + removeComments: true, + collapseWhitespace: true, + removeAttributeQuotes: true + // more options: + // https://github.com/kangax/html-minifier#options-quick-reference + }, + // necessary to consistently work with multiple chunks via CommonsChunkPlugin + chunksSortMode: 'dependency' + }), + // split vendor js into its own file + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + minChunks: function (module, count) { + // any required modules inside node_modules are extracted to vendor + return ( + module.resource && + /\.js$/.test(module.resource) && + module.resource.indexOf( + path.join(__dirname, '../node_modules') + ) === 0 + ) + } + }), + // extract webpack runtime and module manifest to its own file in order to + // prevent vendor hash from being updated whenever app bundle is updated + new webpack.optimize.CommonsChunkPlugin({ + name: 'manifest', + chunks: ['vendor'] + }), + // copy custom static assets + new CopyWebpackPlugin([ + { + from: path.resolve(__dirname, '../static'), + to: config.build.assetsSubDirectory, + ignore: ['.*'] + } + ]) + ] +}) + +if (config.build.productionGzip) { + var CompressionWebpackPlugin = require('compression-webpack-plugin') + + webpackConfig.plugins.push( + new CompressionWebpackPlugin({ + asset: '[path].gz[query]', + algorithm: 'gzip', + test: new RegExp( + '\\.(' + + config.build.productionGzipExtensions.join('|') + + ')$' + ), + threshold: 10240, + minRatio: 0.8 + }) + ) +} + +if (config.build.bundleAnalyzerReport) { + var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin + webpackConfig.plugins.push(new BundleAnalyzerPlugin()) +} + +module.exports = webpackConfig diff --git a/front/build/webpack.test.conf.js b/front/build/webpack.test.conf.js new file mode 100644 index 000000000..d6c8c8dd3 --- /dev/null +++ b/front/build/webpack.test.conf.js @@ -0,0 +1,31 @@ +// This is the webpack config used for unit tests. + +var utils = require('./utils') +var webpack = require('webpack') +var merge = require('webpack-merge') +var baseConfig = require('./webpack.base.conf') + +var webpackConfig = merge(baseConfig, { + // use inline sourcemap for karma-sourcemap-loader + module: { + rules: utils.styleLoaders() + }, + devtool: '#inline-source-map', + resolveLoader: { + alias: { + // necessary to to make lang="scss" work in test when using vue-loader's ?inject option + // see discussion at https://github.com/vuejs/vue-loader/issues/724 + 'scss-loader': 'sass-loader' + } + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': require('../config/test.env') + }) + ] +}) + +// no need for app entry during tests +delete webpackConfig.entry + +module.exports = webpackConfig diff --git a/front/config/dev.env.js b/front/config/dev.env.js new file mode 100644 index 000000000..efead7c84 --- /dev/null +++ b/front/config/dev.env.js @@ -0,0 +1,6 @@ +var merge = require('webpack-merge') +var prodEnv = require('./prod.env') + +module.exports = merge(prodEnv, { + NODE_ENV: '"development"' +}) diff --git a/front/config/index.js b/front/config/index.js new file mode 100644 index 000000000..a312c7b26 --- /dev/null +++ b/front/config/index.js @@ -0,0 +1,39 @@ +// see http://vuejs-templates.github.io/webpack for documentation. +var path = require('path') + +module.exports = { + build: { + env: require('./prod.env'), + index: path.resolve(__dirname, '../dist/index.html'), + assetsRoot: path.resolve(__dirname, '../dist'), + assetsSubDirectory: 'static', + assetsPublicPath: '/', + productionSourceMap: true, + // Gzip off by default as many popular static hosts such as + // Surge or Netlify already gzip all static assets for you. + // Before setting to `true`, make sure to: + // npm install --save-dev compression-webpack-plugin + productionGzip: false, + productionGzipExtensions: ['js', 'css'], + // Run the build command with an extra argument to + // View the bundle analyzer report after build finishes: + // `npm run build --report` + // Set to `true` or `false` to always turn it on or off + bundleAnalyzerReport: process.env.npm_config_report + }, + dev: { + env: require('./dev.env'), + port: 8080, + host: '127.0.0.1', + autoOpenBrowser: true, + assetsSubDirectory: 'static', + assetsPublicPath: '/', + proxyTable: {}, + // CSS Sourcemaps off by default because relative paths are "buggy" + // with this option, according to the CSS-Loader README + // (https://github.com/webpack/css-loader#sourcemaps) + // In our experience, they generally work as expected, + // just be aware of this issue when enabling this option. + cssSourceMap: false + } +} diff --git a/front/config/prod.env.js b/front/config/prod.env.js new file mode 100644 index 000000000..fe0e80b8f --- /dev/null +++ b/front/config/prod.env.js @@ -0,0 +1,4 @@ +module.exports = { + NODE_ENV: '"production"', + BACKEND_URL: '"' + (process.env.BACKEND_URL || '/') + '"' +} diff --git a/front/config/test.env.js b/front/config/test.env.js new file mode 100644 index 000000000..89f90deb2 --- /dev/null +++ b/front/config/test.env.js @@ -0,0 +1,6 @@ +var merge = require('webpack-merge') +var devEnv = require('./dev.env') + +module.exports = merge(devEnv, { + NODE_ENV: '"testing"' +}) diff --git a/front/docker/Dockerfile.dev b/front/docker/Dockerfile.dev new file mode 100644 index 000000000..1a0c90c9e --- /dev/null +++ b/front/docker/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM node:6-alpine + +EXPOSE 8080 + +RUN mkdir /app +WORKDIR /app +ADD package.json . + +RUN npm install + +VOLUME ["/app/node_modules"] + +CMD ["npm", "run", "dev"] diff --git a/front/index.html b/front/index.html new file mode 100644 index 000000000..55e32a7ee --- /dev/null +++ b/front/index.html @@ -0,0 +1,11 @@ + + + + + Funkwhale + + +
+ + + diff --git a/front/package.json b/front/package.json new file mode 100644 index 000000000..732fdb406 --- /dev/null +++ b/front/package.json @@ -0,0 +1,100 @@ +{ + "name": "front", + "version": "1.0.0", + "description": "Funkwhale front-end", + "author": "Eliot Berriot ", + "private": true, + "scripts": { + "dev": "node build/dev-server.js", + "start": "node build/dev-server.js", + "build": "node build/build.js", + "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", + "e2e": "node test/e2e/runner.js", + "test": "npm run unit && npm run e2e", + "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" + }, + "dependencies": { + "dateformat": "^2.0.0", + "js-logger": "^1.3.0", + "semantic-ui-css": "^2.2.10", + "vue": "^2.3.3", + "vue-resource": "^1.3.4", + "vue-router": "^2.3.1" + }, + "devDependencies": { + "autoprefixer": "^6.7.2", + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-loader": "^6.2.10", + "babel-plugin-istanbul": "^4.1.1", + "babel-plugin-transform-runtime": "^6.22.0", + "babel-preset-env": "^1.3.2", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.22.0", + "chai": "^3.5.0", + "chalk": "^1.1.3", + "chromedriver": "^2.27.2", + "connect-history-api-fallback": "^1.3.0", + "copy-webpack-plugin": "^4.0.1", + "cross-env": "^4.0.0", + "cross-spawn": "^5.0.1", + "css-loader": "^0.28.0", + "eslint": "^3.19.0", + "eslint-config-standard": "^6.2.1", + "eslint-friendly-formatter": "^2.0.7", + "eslint-loader": "^1.7.1", + "eslint-plugin-html": "^2.0.0", + "eslint-plugin-promise": "^3.4.0", + "eslint-plugin-standard": "^2.0.1", + "eventsource-polyfill": "^0.9.6", + "express": "^4.14.1", + "extract-text-webpack-plugin": "^2.0.0", + "file-loader": "^0.11.1", + "friendly-errors-webpack-plugin": "^1.1.3", + "html-webpack-plugin": "^2.28.0", + "http-proxy-middleware": "^0.17.3", + "inject-loader": "^3.0.0", + "karma": "^1.4.1", + "karma-coverage": "^1.1.1", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-phantomjs-shim": "^1.4.0", + "karma-sinon-chai": "^1.3.1", + "karma-sourcemap-loader": "^0.3.7", + "karma-spec-reporter": "0.0.30", + "karma-webpack": "^2.0.2", + "lolex": "^1.5.2", + "mocha": "^3.2.0", + "nightwatch": "^0.9.12", + "node-sass": "^4.5.3", + "opn": "^4.0.2", + "optimize-css-assets-webpack-plugin": "^1.3.0", + "ora": "^1.2.0", + "phantomjs-prebuilt": "^2.1.14", + "rimraf": "^2.6.0", + "sass-loader": "^6.0.5", + "selenium-server": "^3.0.1", + "semver": "^5.3.0", + "shelljs": "^0.7.6", + "sinon": "^2.1.0", + "sinon-chai": "^2.8.0", + "url-loader": "^0.5.8", + "vue-loader": "^12.1.0", + "vue-style-loader": "^3.0.1", + "vue-template-compiler": "^2.3.3", + "webpack": "^2.6.1", + "webpack-bundle-analyzer": "^2.2.1", + "webpack-dev-middleware": "^1.10.0", + "webpack-hot-middleware": "^2.18.0", + "webpack-merge": "^4.1.0" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} diff --git a/front/src/App.vue b/front/src/App.vue new file mode 100644 index 000000000..2704ad151 --- /dev/null +++ b/front/src/App.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/front/src/assets/audio/default-cover.png b/front/src/assets/audio/default-cover.png new file mode 100644 index 000000000..c1dde7e5f Binary files /dev/null and b/front/src/assets/audio/default-cover.png differ diff --git a/front/src/assets/logo/favicon.ico b/front/src/assets/logo/favicon.ico new file mode 100644 index 000000000..089442fab Binary files /dev/null and b/front/src/assets/logo/favicon.ico differ diff --git a/front/src/assets/logo/logo-full.png b/front/src/assets/logo/logo-full.png new file mode 100644 index 000000000..725dcc8ac Binary files /dev/null and b/front/src/assets/logo/logo-full.png differ diff --git a/front/src/assets/logo/logo-with-text.svg b/front/src/assets/logo/logo-with-text.svg new file mode 100644 index 000000000..46ee3b3c6 --- /dev/null +++ b/front/src/assets/logo/logo-with-text.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + diff --git a/front/src/assets/logo/logo.png b/front/src/assets/logo/logo.png new file mode 100644 index 000000000..7cf562171 Binary files /dev/null and b/front/src/assets/logo/logo.png differ diff --git a/front/src/assets/logo/logo.svg b/front/src/assets/logo/logo.svg new file mode 100644 index 000000000..5909fcc98 --- /dev/null +++ b/front/src/assets/logo/logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/front/src/assets/logo/logos.png b/front/src/assets/logo/logos.png new file mode 100644 index 000000000..d73f4c36b Binary files /dev/null and b/front/src/assets/logo/logos.png differ diff --git a/front/src/audio/backend.js b/front/src/audio/backend.js new file mode 100644 index 000000000..5b4c70706 --- /dev/null +++ b/front/src/audio/backend.js @@ -0,0 +1,37 @@ +import config from '@/config' + +var Album = { + clean (album) { + // we manually rebind the album and artist to each child track + album.tracks = album.tracks.map((track) => { + track.artist = album.artist + track.album = album + return track + }) + return album + } +} +var Artist = { + clean (artist) { + // clean data as given by the API + artist.albums = artist.albums.map((album) => { + return Album.clean(album) + }) + return artist + } +} +export default { + absoluteUrl (url) { + if (url.startsWith('http')) { + return url + } + if (url.startsWith('/')) { + return config.BACKEND_URL + url.substr(1) + } else { + return config.BACKEND_URL + url + } + }, + Artist: Artist, + Album: Album + +} diff --git a/front/src/audio/index.js b/front/src/audio/index.js new file mode 100644 index 000000000..22cc85ad3 --- /dev/null +++ b/front/src/audio/index.js @@ -0,0 +1,194 @@ +import logger from '@/logging' + +const pad = (val) => { + val = Math.floor(val) + if (val < 10) { + return '0' + val + } + return val + '' +} + +const Cov = { + on (el, type, func) { + el.addEventListener(type, func) + }, + off (el, type, func) { + el.removeEventListener(type, func) + } +} + +class Audio { + constructor (src, options = {}) { + let preload = true + if (options.preload !== undefined && options.preload === false) { + preload = false + } + this.tmp = { + src: src, + options: options + } + this.onEnded = function (e) { + logger.default.info('track ended') + } + if (options.onEnded) { + this.onEnded = options.onEnded + } + + this.state = { + preload: preload, + startLoad: false, + failed: false, + try: 3, + tried: 0, + playing: false, + paused: false, + playbackRate: 1.0, + progress: 0, + currentTime: 0, + volume: 0.5, + duration: 0, + loaded: '0', + durationTimerFormat: '00:00', + currentTimeFormat: '00:00', + lastTimeFormat: '00:00' + } + if (options.volume !== undefined) { + this.state.volume = options.volume + } + this.hook = { + playState: [], + loadState: [] + } + if (preload) { + this.init(src, options) + } + } + + init (src, options = {}) { + if (!src) throw Error('src must be required') + this.state.startLoad = true + if (this.state.tried === this.state.try) { + this.state.failed = true + return + } + this.$Audio = new window.Audio(src) + Cov.on(this.$Audio, 'error', () => { + this.state.tried++ + this.init(src, options) + }) + if (options.autoplay) { + this.play() + } + if (options.rate) { + this.$Audio.playbackRate = options.rate + } + if (options.loop) { + this.$Audio.loop = true + } + if (options.volume) { + this.setVolume(options.volume) + } + this.loadState() + } + + loadState () { + if (this.$Audio.readyState >= 2) { + Cov.on(this.$Audio, 'progress', this.updateLoadState.bind(this)) + } else { + Cov.on(this.$Audio, 'loadeddata', () => { + this.loadState() + }) + } + } + + updateLoadState (e) { + if (!this.$Audio) return + this.hook.loadState.forEach(func => { + func(this.state) + }) + this.state.duration = Math.round(this.$Audio.duration * 100) / 100 + this.state.loaded = Math.round(10000 * this.$Audio.buffered.end(0) / this.$Audio.duration) / 100 + this.state.durationTimerFormat = this.timeParse(this.state.duration) + } + + updatePlayState (e) { + this.state.currentTime = Math.round(this.$Audio.currentTime * 100) / 100 + this.state.duration = Math.round(this.$Audio.duration * 100) / 100 + this.state.progress = Math.round(10000 * this.state.currentTime / this.state.duration) / 100 + + this.state.durationTimerFormat = this.timeParse(this.state.duration) + this.state.currentTimeFormat = this.timeParse(this.state.currentTime) + this.state.lastTimeFormat = this.timeParse(this.state.duration - this.state.currentTime) + + this.hook.playState.forEach(func => { + func(this.state) + }) + } + + updateHook (type, func) { + if (!(type in this.hook)) throw Error('updateHook: type should be playState or loadState') + this.hook[type].push(func) + } + + play () { + logger.default.info('Playing track') + if (this.state.startLoad) { + if (!this.state.playing && this.$Audio.readyState >= 2) { + this.$Audio.play() + this.state.paused = false + this.state.playing = true + Cov.on(this.$Audio, 'timeupdate', this.updatePlayState.bind(this)) + Cov.on(this.$Audio, 'ended', this.onEnded) + } else { + Cov.on(this.$Audio, 'loadeddata', () => { + this.play() + }) + } + } else { + this.init(this.tmp.src, this.tmp.options) + Cov.on(this.$Audio, 'loadeddata', () => { + this.play() + }) + } + } + + destroyed () { + this.$Audio.pause() + Cov.off(this.$Audio, 'timeupdate', this.updatePlayState) + Cov.off(this.$Audio, 'progress', this.updateLoadState) + Cov.off(this.$Audio, 'ended', this.onEnded) + this.$Audio.remove() + } + + pause () { + logger.default.info('Pausing track') + this.$Audio.pause() + this.state.paused = true + this.state.playing = false + this.$Audio.removeEventListener('timeupdate', this.updatePlayState) + } + + setVolume (number) { + if (number > -0.01 && number <= 1) { + this.state.volume = Math.round(number * 100) / 100 + this.$Audio.volume = this.state.volume + } + } + + setTime (time) { + if (time < 0 && time > this.state.duration) { + return false + } + this.$Audio.currentTime = time + } + + timeParse (sec) { + let min = 0 + min = Math.floor(sec / 60) + sec = sec - min * 60 + return pad(min) + ':' + pad(sec) + } + +} + +export default Audio diff --git a/front/src/audio/queue.js b/front/src/audio/queue.js new file mode 100644 index 000000000..ba0af486f --- /dev/null +++ b/front/src/audio/queue.js @@ -0,0 +1,215 @@ +import logger from '@/logging' +import cache from '@/cache' +import config from '@/config' +import Audio from '@/audio' +import backend from '@/audio/backend' +import radios from '@/radios' +import Vue from 'vue' + +class Queue { + constructor (options = {}) { + logger.default.info('Instanciating queue') + this.previousQueue = cache.get('queue') + this.tracks = [] + this.currentIndex = -1 + this.currentTrack = null + this.ended = true + this.state = { + volume: cache.get('volume', 0.5) + } + this.audio = { + state: { + startLoad: false, + failed: false, + try: 3, + tried: 0, + playing: false, + paused: false, + playbackRate: 1.0, + progress: 0, + currentTime: 0, + duration: 0, + volume: this.state.volume, + loaded: '0', + durationTimerFormat: '00:00', + currentTimeFormat: '00:00', + lastTimeFormat: '00:00' + } + } + } + + cache () { + let cached = { + tracks: this.tracks.map(track => { + // we keep only valuable fields to make the cache lighter and avoid + // cyclic value serialization errors + let artist = { + id: track.artist.id, + mbid: track.artist.mbid, + name: track.artist.name + } + return { + id: track.id, + title: track.title, + mbid: track.mbid, + album: { + id: track.album.id, + title: track.album.title, + mbid: track.album.mbid, + cover: track.album.cover, + artist: artist + }, + artist: artist, + files: track.files + } + }), + currentIndex: this.currentIndex + } + cache.set('queue', cached) + } + + restore () { + let cached = cache.get('queue') + if (!cached) { + return false + } + logger.default.info('Restoring previous queue...') + this.tracks = cached.tracks + this.play(cached.currentIndex) + this.previousQueue = null + return true + } + removePrevious () { + this.previousQueue = undefined + cache.remove('queue') + } + setVolume (newValue) { + this.state.volume = newValue + if (this.audio.setVolume) { + this.audio.setVolume(newValue) + } else { + this.audio.state.volume = newValue + } + cache.set('volume', newValue) + } + append (track, index) { + this.previousQueue = null + index = index || this.tracks.length + if (index > this.tracks.length - 1) { + // we simply push to the end + this.tracks.push(track) + } else { + // we insert the track at given position + this.tracks.splice(index, 0, track) + } + if (this.ended) { + this.play(this.currentIndex + 1) + } + this.cache() + } + + appendMany (tracks, index) { + let self = this + index = index || this.tracks.length - 1 + tracks.forEach((t) => { + self.append(t, index) + index += 1 + }) + } + + populateFromRadio () { + if (!radios.running) { + return + } + var self = this + radios.fetch().then((response) => { + logger.default.info('Adding track to queue from radio') + self.append(response.data.track) + }, (response) => { + logger.default.error('Error while adding track to queue from radio') + }) + } + + clean () { + this.stop() + this.tracks = [] + this.currentIndex = -1 + this.currentTrack = null + } + + cleanTrack (index) { + if (index === this.currentIndex) { + this.stop() + } + if (index < this.currentIndex) { + this.currentIndex -= 1 + } + this.tracks.splice(index, 1) + } + + stop () { + this.audio.pause() + this.audio.destroyed() + } + play (index) { + if (this.audio.destroyed) { + logger.default.debug('Destroying previous audio...') + this.audio.destroyed() + } + this.currentIndex = index + this.currentTrack = this.tracks[index] + this.ended = false + let file = this.currentTrack.files[0] + if (!file) { + return this.next() + } + this.audio = new Audio(backend.absoluteUrl(file.path), { + preload: true, + autoplay: true, + rate: 1, + loop: false, + volume: this.state.volume, + onEnded: this.handleAudioEnded.bind(this) + }) + if (this.currentIndex === this.tracks.length - 1) { + this.populateFromRadio() + } + this.cache() + } + + handleAudioEnded (e) { + this.recordListen(this.currentTrack) + if (this.currentIndex < this.tracks.length - 1) { + logger.default.info('Audio track ended, playing next one') + this.next() + } else { + logger.default.info('We reached the end of the queue') + this.ended = true + } + } + + recordListen (track) { + let url = config.API_URL + 'history/listenings/' + let resource = Vue.resource(url) + resource.save({}, {'track': track.id}).then((response) => {}, (response) => { + logger.default.error('Could not record track in history') + }) + } + + previous () { + if (this.currentIndex > 0) { + this.play(this.currentIndex - 1) + } + } + + next () { + if (this.currentIndex < this.tracks.length - 1) { + this.play(this.currentIndex + 1) + } + } + +} + +let queue = new Queue() + +export default queue diff --git a/front/src/audio/track.js b/front/src/audio/track.js new file mode 100644 index 000000000..9873b74ec --- /dev/null +++ b/front/src/audio/track.js @@ -0,0 +1,7 @@ +import backend from './backend' + +export default { + getCover (track) { + return backend.absoluteUrl(track.album.cover) + } +} diff --git a/front/src/auth/index.js b/front/src/auth/index.js new file mode 100644 index 000000000..b5a3fb5ad --- /dev/null +++ b/front/src/auth/index.js @@ -0,0 +1,89 @@ +import logger from '@/logging' +import config from '@/config' +import cache from '@/cache' +import Vue from 'vue' + +import favoriteTracks from '@/favorites/tracks' + +// URL and endpoint constants +const LOGIN_URL = config.API_URL + 'token/' +const USER_PROFILE_URL = config.API_URL + 'users/users/me/' +// const SIGNUP_URL = API_URL + 'users/' + +export default { + + // User object will let us check authentication status + user: { + authenticated: false, + username: '', + profile: null + }, + + // Send a request to the login URL and save the returned JWT + login (context, creds, redirect, onError) { + return context.$http.post(LOGIN_URL, creds).then(response => { + logger.default.info('Successfully logged in as', creds.username) + cache.set('token', response.data.token) + cache.set('username', creds.username) + + this.user.authenticated = true + this.user.username = creds.username + this.connect() + // Redirect to a specified route + if (redirect) { + context.$router.push(redirect) + } + }, response => { + logger.default.error('Error while logging in', response.data) + if (onError) { + onError(response) + } + }) + }, + + // To log out, we just need to remove the token + logout () { + cache.clear() + this.user.authenticated = false + logger.default.info('Log out, goodbye!') + }, + + checkAuth () { + logger.default.info('Checking authentication...') + var jwt = cache.get('token') + var username = cache.get('username') + if (jwt) { + this.user.authenticated = true + this.user.username = username + logger.default.info('Logged back in as ' + username) + this.connect() + } else { + logger.default.info('Anonymous user') + this.user.authenticated = false + } + }, + + // The object to be passed as a header for authenticated requests + getAuthHeader () { + return 'JWT ' + cache.get('token') + }, + + fetchProfile () { + let resource = Vue.resource(USER_PROFILE_URL) + return resource.get({}).then((response) => { + logger.default.info('Successfully fetched user profile') + return response.data + }, (response) => { + logger.default.info('Error while fetching user profile') + }) + }, + connect () { + // called once user has logged in successfully / reauthenticated + // e.g. after a page refresh + let self = this + this.fetchProfile().then(data => { + Vue.set(self.user, 'profile', data) + }) + favoriteTracks.fetch() + } +} diff --git a/front/src/cache/index.js b/front/src/cache/index.js new file mode 100644 index 000000000..e039ee788 --- /dev/null +++ b/front/src/cache/index.js @@ -0,0 +1,29 @@ +import logger from '@/logging' +export default { + get (key, d) { + let v = localStorage.getItem(key) + if (v === null) { + return d + } else { + try { + return JSON.parse(v).value + } catch (e) { + logger.default.error('Removing unparsable cached value for key ' + key) + this.remove(key) + return d + } + } + }, + set (key, value) { + return localStorage.setItem(key, JSON.stringify({value: value})) + }, + + remove (key) { + return localStorage.removeItem(key) + }, + + clear () { + localStorage.clear() + } + +} diff --git a/front/src/components/Home.vue b/front/src/components/Home.vue new file mode 100644 index 000000000..891e99ae0 --- /dev/null +++ b/front/src/components/Home.vue @@ -0,0 +1,157 @@ + + + + + + diff --git a/front/src/components/Logo.vue b/front/src/components/Logo.vue new file mode 100644 index 000000000..f63bd7ab6 --- /dev/null +++ b/front/src/components/Logo.vue @@ -0,0 +1,33 @@ + + + + + + diff --git a/front/src/components/Sidebar.vue b/front/src/components/Sidebar.vue new file mode 100644 index 000000000..c98dc2f01 --- /dev/null +++ b/front/src/components/Sidebar.vue @@ -0,0 +1,190 @@ + + + + + + diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue new file mode 100644 index 000000000..240fa4980 --- /dev/null +++ b/front/src/components/audio/PlayButton.vue @@ -0,0 +1,67 @@ + + + + + + diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue new file mode 100644 index 000000000..2f41bbbf0 --- /dev/null +++ b/front/src/components/audio/Player.vue @@ -0,0 +1,189 @@ + + + + + + diff --git a/front/src/components/audio/Search.vue b/front/src/components/audio/Search.vue new file mode 100644 index 000000000..5c902e5e5 --- /dev/null +++ b/front/src/components/audio/Search.vue @@ -0,0 +1,116 @@ + + + + + + diff --git a/front/src/components/audio/SearchBar.vue b/front/src/components/audio/SearchBar.vue new file mode 100644 index 000000000..64bf3202f --- /dev/null +++ b/front/src/components/audio/SearchBar.vue @@ -0,0 +1,101 @@ + + + + + + diff --git a/front/src/components/audio/album/Card.vue b/front/src/components/audio/album/Card.vue new file mode 100644 index 000000000..79261ef7e --- /dev/null +++ b/front/src/components/audio/album/Card.vue @@ -0,0 +1,98 @@ + + + + + + diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue new file mode 100644 index 000000000..4cdd2969f --- /dev/null +++ b/front/src/components/audio/artist/Card.vue @@ -0,0 +1,84 @@ + + + + + + diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue new file mode 100644 index 000000000..aa3d324ed --- /dev/null +++ b/front/src/components/audio/track/Table.vue @@ -0,0 +1,68 @@ + + + + + + diff --git a/front/src/components/auth/Login.vue b/front/src/components/auth/Login.vue new file mode 100644 index 000000000..af4936b3d --- /dev/null +++ b/front/src/components/auth/Login.vue @@ -0,0 +1,90 @@ + + + + + + diff --git a/front/src/components/auth/Logout.vue b/front/src/components/auth/Logout.vue new file mode 100644 index 000000000..f4b2979bc --- /dev/null +++ b/front/src/components/auth/Logout.vue @@ -0,0 +1,37 @@ + + + + + + diff --git a/front/src/components/auth/Profile.vue b/front/src/components/auth/Profile.vue new file mode 100644 index 000000000..2aaae9e2d --- /dev/null +++ b/front/src/components/auth/Profile.vue @@ -0,0 +1,62 @@ + + + + + + diff --git a/front/src/components/browse/Album.vue b/front/src/components/browse/Album.vue new file mode 100644 index 000000000..35b1f3a3c --- /dev/null +++ b/front/src/components/browse/Album.vue @@ -0,0 +1,105 @@ + + + + + + diff --git a/front/src/components/browse/Artist.vue b/front/src/components/browse/Artist.vue new file mode 100644 index 000000000..5eab08ddf --- /dev/null +++ b/front/src/components/browse/Artist.vue @@ -0,0 +1,133 @@ + + + + + + diff --git a/front/src/components/browse/Browse.vue b/front/src/components/browse/Browse.vue new file mode 100644 index 000000000..d8f542a5e --- /dev/null +++ b/front/src/components/browse/Browse.vue @@ -0,0 +1,48 @@ + + + + + + diff --git a/front/src/components/browse/Home.vue b/front/src/components/browse/Home.vue new file mode 100644 index 000000000..3ce8616a3 --- /dev/null +++ b/front/src/components/browse/Home.vue @@ -0,0 +1,80 @@ + + + + + + diff --git a/front/src/components/browse/Track.vue b/front/src/components/browse/Track.vue new file mode 100644 index 000000000..336af285b --- /dev/null +++ b/front/src/components/browse/Track.vue @@ -0,0 +1,153 @@ + + + + + + diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue new file mode 100644 index 000000000..f7972a07c --- /dev/null +++ b/front/src/components/favorites/List.vue @@ -0,0 +1,78 @@ + + + + + + diff --git a/front/src/components/favorites/TrackFavoriteIcon.vue b/front/src/components/favorites/TrackFavoriteIcon.vue new file mode 100644 index 000000000..ef490da9b --- /dev/null +++ b/front/src/components/favorites/TrackFavoriteIcon.vue @@ -0,0 +1,50 @@ + + + + + + diff --git a/front/src/components/radios/Button.vue b/front/src/components/radios/Button.vue new file mode 100644 index 000000000..b334dce56 --- /dev/null +++ b/front/src/components/radios/Button.vue @@ -0,0 +1,50 @@ + + + + + + diff --git a/front/src/components/radios/Card.vue b/front/src/components/radios/Card.vue new file mode 100644 index 000000000..1e496324a --- /dev/null +++ b/front/src/components/radios/Card.vue @@ -0,0 +1,37 @@ + + + + + + diff --git a/front/src/config.js b/front/src/config.js new file mode 100644 index 000000000..03e7a1821 --- /dev/null +++ b/front/src/config.js @@ -0,0 +1,11 @@ +class Config { + constructor () { + this.BACKEND_URL = process.env.BACKEND_URL + if (!this.BACKEND_URL.endsWith('/')) { + this.BACKEND_URL += '/' + } + this.API_URL = this.BACKEND_URL + 'api/' + } +} + +export default new Config() diff --git a/front/src/favorites/tracks.js b/front/src/favorites/tracks.js new file mode 100644 index 000000000..ac3cb5eaa --- /dev/null +++ b/front/src/favorites/tracks.js @@ -0,0 +1,53 @@ +import config from '@/config' +import logger from '@/logging' +import Vue from 'vue' + +const REMOVE_URL = config.API_URL + 'favorites/tracks/remove/' +const FAVORITES_URL = config.API_URL + 'favorites/tracks/' + +export default { + objects: {}, + count: 0, + set (id, newValue) { + let self = this + Vue.set(self.objects, id, newValue) + if (newValue) { + Vue.set(self, 'count', self.count + 1) + let resource = Vue.resource(FAVORITES_URL) + resource.save({}, {'track': id}).then((response) => { + logger.default.info('Successfully added track to favorites') + }, (response) => { + logger.default.info('Error while adding track to favorites') + Vue.set(self.objects, id, !newValue) + Vue.set(self, 'count', self.count - 1) + }) + } else { + Vue.set(self, 'count', self.count - 1) + let resource = Vue.resource(REMOVE_URL) + resource.delete({}, {'track': id}).then((response) => { + logger.default.info('Successfully removed track from favorites') + }, (response) => { + logger.default.info('Error while removing track from favorites') + Vue.set(self.objects, id, !newValue) + Vue.set(self, 'count', self.count + 1) + }) + } + }, + fetch (url) { + // will fetch favorites by batches from API to have them locally + var self = this + url = url || FAVORITES_URL + let resource = Vue.resource(url) + resource.get().then((response) => { + logger.default.info('Fetched a batch of ' + response.data.results.length + ' favorites') + Vue.set(self, 'count', response.data.count) + response.data.results.forEach(result => { + Vue.set(self.objects, result.track, true) + }) + if (response.data.next) { + self.fetch(response.data.next) + } + }) + } + +} diff --git a/front/src/logging.js b/front/src/logging.js new file mode 100644 index 000000000..ebb98c005 --- /dev/null +++ b/front/src/logging.js @@ -0,0 +1,8 @@ +import jsLogger from 'js-logger' + +jsLogger.useDefaults() + +export default { + get: jsLogger.get, + default: jsLogger.get('default') +} diff --git a/front/src/main.js b/front/src/main.js new file mode 100644 index 000000000..4ffbdb2f7 --- /dev/null +++ b/front/src/main.js @@ -0,0 +1,47 @@ +// The Vue build version to load with the `import` command +// (runtime-only or standalone) has been set in webpack.base.conf with an alias. +import logger from '@/logging' + +logger.default.info('Loading environment:', process.env.NODE_ENV) +logger.default.debug('Environment variables:', process.env) + +import Vue from 'vue' +import App from './App' +import router from './router' +import VueResource from 'vue-resource' +import auth from './auth' + +window.$ = window.jQuery = require('jquery') + +// this is absolutely dirty but at the moment, semantic UI does not +// play really nice with webpack and I want to get rid of Google Fonts +// require('./semantic/semantic.css') +require('semantic-ui-css/semantic.js') + +Vue.use(VueResource) +Vue.config.productionTip = false + +Vue.http.interceptors.push(function (request, next) { + // modify headers + if (auth.user.authenticated) { + request.headers.set('Authorization', auth.getAuthHeader()) + } + next(function (response) { + // redirect to login form when we get unauthorized response from server + if (response.status === 401) { + logger.default.warn('Received 401 response from API, redirecting to login form') + router.push({name: 'login'}) + } + }) +}) + +auth.checkAuth() +/* eslint-disable no-new */ +new Vue({ + el: '#app', + router, + template: '', + components: { App } +}) + +logger.default.info('Everything loaded!') diff --git a/front/src/radios/index.js b/front/src/radios/index.js new file mode 100644 index 000000000..b46883086 --- /dev/null +++ b/front/src/radios/index.js @@ -0,0 +1,64 @@ +import Vue from 'vue' +import config from '@/config' +import logger from '@/logging' +import queue from '@/audio/queue' + +const CREATE_RADIO_URL = config.API_URL + 'radios/sessions/' +const GET_TRACK_URL = config.API_URL + 'radios/tracks/' + +var radios = { + types: { + random: { + name: 'Random', + description: "Totally random picks, maybe you'll discover new things?" + }, + favorites: { + name: 'Favorites', + description: 'Play your favorites tunes in a never-ending happiness loop.' + }, + 'less-listened': { + name: 'Less listened', + description: "Listen to tracks you usually don't. It's time to restore some balance." + } + }, + start (type, objectId) { + this.current.type = type + this.current.objectId = objectId + this.running = true + let resource = Vue.resource(CREATE_RADIO_URL) + var self = this + var params = { + radio_type: type, + related_object_id: objectId + } + resource.save({}, params).then((response) => { + logger.default.info('Successfully started radio ', type) + self.current.session = response.data.id + queue.populateFromRadio() + }, (response) => { + logger.default.error('Error while starting radio', type) + }) + }, + stop () { + this.current.type = null + this.current.objectId = null + this.running = false + this.session = null + }, + fetch () { + let resource = Vue.resource(GET_TRACK_URL) + var self = this + var params = { + session: self.current.session + } + return resource.save({}, params) + } +} + +Vue.set(radios, 'running', false) +Vue.set(radios, 'current', {}) +Vue.set(radios.current, 'objectId', null) +Vue.set(radios.current, 'type', null) +Vue.set(radios.current, 'session', null) + +export default radios diff --git a/front/src/router/index.js b/front/src/router/index.js new file mode 100644 index 000000000..bb92b5ae1 --- /dev/null +++ b/front/src/router/index.js @@ -0,0 +1,57 @@ +import Vue from 'vue' +import Router from 'vue-router' +import Home from '@/components/Home' +import Login from '@/components/auth/Login' +import Profile from '@/components/auth/Profile' +import Logout from '@/components/auth/Logout' +import Browse from '@/components/browse/Browse' +import BrowseHome from '@/components/browse/Home' +import BrowseArtist from '@/components/browse/Artist' +import BrowseAlbum from '@/components/browse/Album' +import BrowseTrack from '@/components/browse/Track' +import Favorites from '@/components/favorites/List' + +Vue.use(Router) + +export default new Router({ + mode: 'history', + linkActiveClass: 'active', + routes: [ + { + path: '/', + name: 'index', + component: Home + }, + { + path: '/login', + name: 'login', + component: Login + }, + { + path: '/logout', + name: 'logout', + component: Logout + }, + { + path: '/@:username', + name: 'profile', + component: Profile, + props: true + }, + { + path: '/favorites', + component: Favorites + }, + { + path: '/browse', + component: Browse, + children: [ + { path: '', component: BrowseHome }, + { path: 'artist/:id', name: 'browse.artist', component: BrowseArtist, props: true }, + { path: 'album/:id', name: 'browse.album', component: BrowseAlbum, props: true }, + { path: 'track/:id', name: 'browse.track', component: BrowseTrack, props: true } + ] + } + + ] +}) diff --git a/front/src/semantic/semantic.css b/front/src/semantic/semantic.css new file mode 100755 index 000000000..99c5ddaa5 --- /dev/null +++ b/front/src/semantic/semantic.css @@ -0,0 +1,36998 @@ + /* + * # Semantic UI - 2.2.10 + * https://github.com/Semantic-Org/Semantic-UI + * http://www.semantic-ui.com/ + * + * Copyright 2014 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ +/*@import url('https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin');*/ +/*! + * # Semantic UI 2.2.10 - Reset + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Reset +*******************************/ + +/* Border-Box */ + +*, +*:before, +*:after { + box-sizing: inherit; +} + +html { + box-sizing: border-box; +} + +/* iPad Input Shadows */ + +input[type="text"], +input[type="email"], +input[type="search"], +input[type="password"] { + -webkit-appearance: none; + -moz-appearance: none; + /* mobile firefox too! */ +} + +/******************************* + Theme Overrides +*******************************/ + +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ + +/** + * Correct `block` display not defined in IE 8/9. + */ + +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Site + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Page +*******************************/ + +html, +body { + height: 100%; +} + +html { + font-size: 14px; +} + +body { + margin: 0px; + padding: 0px; + overflow-x: hidden; + min-width: 320px; + background: #FFFFFF; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 14px; + line-height: 1.4285em; + color: rgba(0, 0, 0, 0.87); + font-smoothing: antialiased; +} + +/******************************* + Headers +*******************************/ + +h1, +h2, +h3, +h4, +h5 { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + line-height: 1.28571429em; + margin: calc(2rem - 0.14285714em ) 0em 1rem; + font-weight: bold; + padding: 0em; +} + +h1 { + min-height: 1rem; + font-size: 2rem; +} + +h2 { + font-size: 1.71428571rem; +} + +h3 { + font-size: 1.28571429rem; +} + +h4 { + font-size: 1.07142857rem; +} + +h5 { + font-size: 1rem; +} + +h1:first-child, +h2:first-child, +h3:first-child, +h4:first-child, +h5:first-child { + margin-top: 0em; +} + +h1:last-child, +h2:last-child, +h3:last-child, +h4:last-child, +h5:last-child { + margin-bottom: 0em; +} + +/******************************* + Text +*******************************/ + +p { + margin: 0em 0em 1em; + line-height: 1.4285em; +} + +p:first-child { + margin-top: 0em; +} + +p:last-child { + margin-bottom: 0em; +} + +/*------------------- + Links +--------------------*/ + +a { + color: #4183C4; + text-decoration: none; +} + +a:hover { + color: #1e70bf; + text-decoration: none; +} + +/******************************* + Highlighting +*******************************/ + +/* Site */ + +::-webkit-selection { + background-color: #CCE2FF; + color: rgba(0, 0, 0, 0.87); +} + +::-moz-selection { + background-color: #CCE2FF; + color: rgba(0, 0, 0, 0.87); +} + +::selection { + background-color: #CCE2FF; + color: rgba(0, 0, 0, 0.87); +} + +/* Form */ + +textarea::-webkit-selection, +input::-webkit-selection { + background-color: rgba(100, 100, 100, 0.4); + color: rgba(0, 0, 0, 0.87); +} + +textarea::-moz-selection, +input::-moz-selection { + background-color: rgba(100, 100, 100, 0.4); + color: rgba(0, 0, 0, 0.87); +} + +textarea::selection, +input::selection { + background-color: rgba(100, 100, 100, 0.4); + color: rgba(0, 0, 0, 0.87); +} + +/******************************* + Global Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Button + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Button +*******************************/ + +.ui.button { + cursor: pointer; + display: inline-block; + min-height: 1em; + outline: none; + border: none; + vertical-align: baseline; + background: #E0E1E2 none; + color: rgba(0, 0, 0, 0.6); + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + margin: 0em 0.25em 0em 0em; + padding: 0.78571429em 1.5em 0.78571429em; + text-transform: none; + text-shadow: none; + font-weight: bold; + line-height: 1em; + font-style: normal; + text-align: center; + text-decoration: none; + border-radius: 0.28571429rem; + box-shadow: 0px 0px 0px 1px transparent inset, 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease; + transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease; + will-change: ''; + -webkit-tap-highlight-color: transparent; +} + +/******************************* + States +*******************************/ + +/*-------------- + Hover +---------------*/ + +.ui.button:hover { + background-color: #CACBCD; + background-image: none; + box-shadow: 0px 0px 0px 1px transparent inset, 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; + color: rgba(0, 0, 0, 0.8); +} + +.ui.button:hover .icon { + opacity: 0.85; +} + +/*-------------- + Focus +---------------*/ + +.ui.button:focus { + background-color: #CACBCD; + color: rgba(0, 0, 0, 0.8); + background-image: '' !important; + box-shadow: '' !important; +} + +.ui.button:focus .icon { + opacity: 0.85; +} + +/*-------------- + Down +---------------*/ + +.ui.button:active, +.ui.active.button:active { + background-color: #BABBBC; + background-image: ''; + color: rgba(0, 0, 0, 0.9); + box-shadow: 0px 0px 0px 1px transparent inset, none; +} + +/*-------------- + Active +---------------*/ + +.ui.active.button { + background-color: #C0C1C2; + background-image: none; + box-shadow: 0px 0px 0px 1px transparent inset; + color: rgba(0, 0, 0, 0.95); +} + +.ui.active.button:hover { + background-color: #C0C1C2; + background-image: none; + color: rgba(0, 0, 0, 0.95); +} + +.ui.active.button:active { + background-color: #C0C1C2; + background-image: none; +} + +/*-------------- + Loading +---------------*/ + +/* Specificity hack */ + +.ui.loading.loading.loading.loading.loading.loading.button { + position: relative; + cursor: default; + text-shadow: none !important; + color: transparent !important; + opacity: 1; + pointer-events: auto; + -webkit-transition: all 0s linear, opacity 0.1s ease; + transition: all 0s linear, opacity 0.1s ease; +} + +.ui.loading.button:before { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.15); +} + +.ui.loading.button:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + -webkit-animation: button-spin 0.6s linear; + animation: button-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #FFFFFF transparent transparent; + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; +} + +.ui.labeled.icon.loading.button .icon { + background-color: transparent; + box-shadow: none; +} + +@-webkit-keyframes button-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes button-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.ui.basic.loading.button:not(.inverted):before { + border-color: rgba(0, 0, 0, 0.1); +} + +.ui.basic.loading.button:not(.inverted):after { + border-top-color: #767676; +} + +/*------------------- + Disabled +--------------------*/ + +.ui.buttons .disabled.button, +.ui.disabled.button, +.ui.button:disabled, +.ui.disabled.button:hover, +.ui.disabled.active.button { + cursor: default; + opacity: 0.45 !important; + background-image: none !important; + box-shadow: none !important; + pointer-events: none !important; +} + +/* Basic Group With Disabled */ + +.ui.basic.buttons .ui.disabled.button { + border-color: rgba(34, 36, 38, 0.5); +} + +/******************************* + Types +*******************************/ + +/*------------------- + Animated +--------------------*/ + +.ui.animated.button { + position: relative; + overflow: hidden; + padding-right: 0em !important; + vertical-align: middle; + z-index: 1; +} + +.ui.animated.button .content { + will-change: transform, opacity; +} + +.ui.animated.button .visible.content { + position: relative; + margin-right: 1.5em; +} + +.ui.animated.button .hidden.content { + position: absolute; + width: 100%; +} + +/* Horizontal */ + +.ui.animated.button .visible.content, +.ui.animated.button .hidden.content { + -webkit-transition: right 0.3s ease 0s; + transition: right 0.3s ease 0s; +} + +.ui.animated.button .visible.content { + left: auto; + right: 0%; +} + +.ui.animated.button .hidden.content { + top: 50%; + left: auto; + right: -100%; + margin-top: -0.5em; +} + +.ui.animated.button:focus .visible.content, +.ui.animated.button:hover .visible.content { + left: auto; + right: 200%; +} + +.ui.animated.button:focus .hidden.content, +.ui.animated.button:hover .hidden.content { + left: auto; + right: 0%; +} + +/* Vertical */ + +.ui.vertical.animated.button .visible.content, +.ui.vertical.animated.button .hidden.content { + -webkit-transition: top 0.3s ease, -webkit-transform 0.3s ease; + transition: top 0.3s ease, -webkit-transform 0.3s ease; + transition: top 0.3s ease, transform 0.3s ease; + transition: top 0.3s ease, transform 0.3s ease, -webkit-transform 0.3s ease; +} + +.ui.vertical.animated.button .visible.content { + -webkit-transform: translateY(0%); + transform: translateY(0%); + right: auto; +} + +.ui.vertical.animated.button .hidden.content { + top: -50%; + left: 0%; + right: auto; +} + +.ui.vertical.animated.button:focus .visible.content, +.ui.vertical.animated.button:hover .visible.content { + -webkit-transform: translateY(200%); + transform: translateY(200%); + right: auto; +} + +.ui.vertical.animated.button:focus .hidden.content, +.ui.vertical.animated.button:hover .hidden.content { + top: 50%; + right: auto; +} + +/* Fade */ + +.ui.fade.animated.button .visible.content, +.ui.fade.animated.button .hidden.content { + -webkit-transition: opacity 0.3s ease, -webkit-transform 0.3s ease; + transition: opacity 0.3s ease, -webkit-transform 0.3s ease; + transition: opacity 0.3s ease, transform 0.3s ease; + transition: opacity 0.3s ease, transform 0.3s ease, -webkit-transform 0.3s ease; +} + +.ui.fade.animated.button .visible.content { + left: auto; + right: auto; + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); +} + +.ui.fade.animated.button .hidden.content { + opacity: 0; + left: 0%; + right: auto; + -webkit-transform: scale(1.5); + transform: scale(1.5); +} + +.ui.fade.animated.button:focus .visible.content, +.ui.fade.animated.button:hover .visible.content { + left: auto; + right: auto; + opacity: 0; + -webkit-transform: scale(0.75); + transform: scale(0.75); +} + +.ui.fade.animated.button:focus .hidden.content, +.ui.fade.animated.button:hover .hidden.content { + left: 0%; + right: auto; + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); +} + +/*------------------- + Inverted +--------------------*/ + +.ui.inverted.button { + box-shadow: 0px 0px 0px 2px #FFFFFF inset !important; + background: transparent none; + color: #FFFFFF; + text-shadow: none !important; +} + +/* Group */ + +.ui.inverted.buttons .button { + margin: 0px 0px 0px -2px; +} + +.ui.inverted.buttons .button:first-child { + margin-left: 0em; +} + +.ui.inverted.vertical.buttons .button { + margin: 0px 0px -2px 0px; +} + +.ui.inverted.vertical.buttons .button:first-child { + margin-top: 0em; +} + +/* States */ + +/* Hover */ + +.ui.inverted.button:hover { + background: #FFFFFF; + box-shadow: 0px 0px 0px 2px #FFFFFF inset !important; + color: rgba(0, 0, 0, 0.8); +} + +/* Active / Focus */ + +.ui.inverted.button:focus, +.ui.inverted.button.active { + background: #FFFFFF; + box-shadow: 0px 0px 0px 2px #FFFFFF inset !important; + color: rgba(0, 0, 0, 0.8); +} + +/* Active Focus */ + +.ui.inverted.button.active:focus { + background: #DCDDDE; + box-shadow: 0px 0px 0px 2px #DCDDDE inset !important; + color: rgba(0, 0, 0, 0.8); +} + +/*------------------- + Labeled Button +--------------------*/ + +.ui.labeled.button:not(.icon) { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + background: none !important; + padding: 0px !important; + border: none !important; + box-shadow: none !important; +} + +.ui.labeled.button > .button { + margin: 0px; +} + +.ui.labeled.button > .label { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + margin: 0px 0px 0px -1px !important; + padding: ''; + font-size: 1em; + border-color: rgba(34, 36, 38, 0.15); +} + +/* Tag */ + +.ui.labeled.button > .tag.label:before { + width: 1.85em; + height: 1.85em; +} + +/* Right */ + +.ui.labeled.button:not([class*="left labeled"]) > .button { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; +} + +.ui.labeled.button:not([class*="left labeled"]) > .label { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +/* Left Side */ + +.ui[class*="left labeled"].button > .button { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +.ui[class*="left labeled"].button > .label { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; +} + +/*------------------- + Social +--------------------*/ + +/* Facebook */ + +.ui.facebook.button { + background-color: #3B5998; + color: #FFFFFF; + text-shadow: none; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.facebook.button:hover { + background-color: #304d8a; + color: #FFFFFF; + text-shadow: none; +} + +.ui.facebook.button:active { + background-color: #2d4373; + color: #FFFFFF; + text-shadow: none; +} + +/* Twitter */ + +.ui.twitter.button { + background-color: #55ACEE; + color: #FFFFFF; + text-shadow: none; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.twitter.button:hover { + background-color: #35a2f4; + color: #FFFFFF; + text-shadow: none; +} + +.ui.twitter.button:active { + background-color: #2795e9; + color: #FFFFFF; + text-shadow: none; +} + +/* Google Plus */ + +.ui.google.plus.button { + background-color: #DD4B39; + color: #FFFFFF; + text-shadow: none; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.google.plus.button:hover { + background-color: #e0321c; + color: #FFFFFF; + text-shadow: none; +} + +.ui.google.plus.button:active { + background-color: #c23321; + color: #FFFFFF; + text-shadow: none; +} + +/* Linked In */ + +.ui.linkedin.button { + background-color: #1F88BE; + color: #FFFFFF; + text-shadow: none; +} + +.ui.linkedin.button:hover { + background-color: #147baf; + color: #FFFFFF; + text-shadow: none; +} + +.ui.linkedin.button:active { + background-color: #186992; + color: #FFFFFF; + text-shadow: none; +} + +/* YouTube */ + +.ui.youtube.button { + background-color: #CC181E; + color: #FFFFFF; + text-shadow: none; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.youtube.button:hover { + background-color: #bd0d13; + color: #FFFFFF; + text-shadow: none; +} + +.ui.youtube.button:active { + background-color: #9e1317; + color: #FFFFFF; + text-shadow: none; +} + +/* Instagram */ + +.ui.instagram.button { + background-color: #49769C; + color: #FFFFFF; + text-shadow: none; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.instagram.button:hover { + background-color: #3d698e; + color: #FFFFFF; + text-shadow: none; +} + +.ui.instagram.button:active { + background-color: #395c79; + color: #FFFFFF; + text-shadow: none; +} + +/* Pinterest */ + +.ui.pinterest.button { + background-color: #BD081C; + color: #FFFFFF; + text-shadow: none; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.pinterest.button:hover { + background-color: #ac0013; + color: #FFFFFF; + text-shadow: none; +} + +.ui.pinterest.button:active { + background-color: #8c0615; + color: #FFFFFF; + text-shadow: none; +} + +/* VK */ + +.ui.vk.button { + background-color: #4D7198; + color: #FFFFFF; + background-image: none; + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.vk.button:hover { + background-color: #41648a; + color: #FFFFFF; +} + +.ui.vk.button:active { + background-color: #3c5876; + color: #FFFFFF; +} + +/*-------------- + Icon +---------------*/ + +.ui.button > .icon:not(.button) { + height: 0.85714286em; + opacity: 0.8; + margin: 0em 0.42857143em 0em -0.21428571em; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; + vertical-align: ''; + color: ''; +} + +.ui.button:not(.icon) > .icon:not(.button):not(.dropdown) { + margin: 0em 0.42857143em 0em -0.21428571em; +} + +.ui.button:not(.icon) > .right.icon:not(.button):not(.dropdown) { + margin: 0em -0.21428571em 0em 0.42857143em; +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Floated +--------------------*/ + +.ui[class*="left floated"].buttons, +.ui[class*="left floated"].button { + float: left; + margin-left: 0em; + margin-right: 0.25em; +} + +.ui[class*="right floated"].buttons, +.ui[class*="right floated"].button { + float: right; + margin-right: 0em; + margin-left: 0.25em; +} + +/*------------------- + Compact +--------------------*/ + +.ui.compact.buttons .button, +.ui.compact.button { + padding: 0.58928571em 1.125em 0.58928571em; +} + +.ui.compact.icon.buttons .button, +.ui.compact.icon.button { + padding: 0.58928571em 0.58928571em 0.58928571em; +} + +.ui.compact.labeled.icon.buttons .button, +.ui.compact.labeled.icon.button { + padding: 0.58928571em 3.69642857em 0.58928571em; +} + +/*------------------- + Sizes +--------------------*/ + +.ui.mini.buttons .button, +.ui.mini.buttons .or, +.ui.mini.button { + font-size: 0.78571429rem; +} + +.ui.tiny.buttons .button, +.ui.tiny.buttons .or, +.ui.tiny.button { + font-size: 0.85714286rem; +} + +.ui.small.buttons .button, +.ui.small.buttons .or, +.ui.small.button { + font-size: 0.92857143rem; +} + +.ui.buttons .button, +.ui.buttons .or, +.ui.button { + font-size: 1rem; +} + +.ui.large.buttons .button, +.ui.large.buttons .or, +.ui.large.button { + font-size: 1.14285714rem; +} + +.ui.big.buttons .button, +.ui.big.buttons .or, +.ui.big.button { + font-size: 1.28571429rem; +} + +.ui.huge.buttons .button, +.ui.huge.buttons .or, +.ui.huge.button { + font-size: 1.42857143rem; +} + +.ui.massive.buttons .button, +.ui.massive.buttons .or, +.ui.massive.button { + font-size: 1.71428571rem; +} + +/*-------------- + Icon Only +---------------*/ + +.ui.icon.buttons .button, +.ui.icon.button { + padding: 0.78571429em 0.78571429em 0.78571429em; +} + +.ui.icon.buttons .button > .icon, +.ui.icon.button > .icon { + opacity: 0.9; + margin: 0em !important; + vertical-align: top; +} + +/*------------------- + Basic +--------------------*/ + +.ui.basic.buttons .button, +.ui.basic.button { + background: transparent none !important; + color: rgba(0, 0, 0, 0.6) !important; + font-weight: normal; + border-radius: 0.28571429rem; + text-transform: none; + text-shadow: none !important; + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset; +} + +.ui.basic.buttons { + box-shadow: none; + border: 1px solid rgba(34, 36, 38, 0.15); + border-radius: 0.28571429rem; +} + +.ui.basic.buttons .button { + border-radius: 0em; +} + +.ui.basic.buttons .button:hover, +.ui.basic.button:hover { + background: #FFFFFF !important; + color: rgba(0, 0, 0, 0.8) !important; + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.35) inset, 0px 0px 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.basic.buttons .button:focus, +.ui.basic.button:focus { + background: #FFFFFF !important; + color: rgba(0, 0, 0, 0.8) !important; + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.35) inset, 0px 0px 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.basic.buttons .button:active, +.ui.basic.button:active { + background: #F8F8F8 !important; + color: rgba(0, 0, 0, 0.9) !important; + box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.15) inset, 0px 1px 4px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.basic.buttons .active.button, +.ui.basic.active.button { + background: rgba(0, 0, 0, 0.05) !important; + box-shadow: '' !important; + color: rgba(0, 0, 0, 0.95); +} + +.ui.basic.buttons .active.button:hover, +.ui.basic.active.button:hover { + background-color: rgba(0, 0, 0, 0.05); +} + +/* Vertical */ + +.ui.basic.buttons .button:hover { + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.35) inset, 0px 0px 0px 0px rgba(34, 36, 38, 0.15) inset inset; +} + +.ui.basic.buttons .button:active { + box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.15) inset, 0px 1px 4px 0px rgba(34, 36, 38, 0.15) inset inset; +} + +.ui.basic.buttons .active.button { + box-shadow: '' !important; +} + +/* Standard Basic Inverted */ + +.ui.basic.inverted.buttons .button, +.ui.basic.inverted.button { + background-color: transparent !important; + color: #F9FAFB !important; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; +} + +.ui.basic.inverted.buttons .button:hover, +.ui.basic.inverted.button:hover { + color: #FFFFFF !important; + box-shadow: 0px 0px 0px 2px #ffffff inset !important; +} + +.ui.basic.inverted.buttons .button:focus, +.ui.basic.inverted.button:focus { + color: #FFFFFF !important; + box-shadow: 0px 0px 0px 2px #ffffff inset !important; +} + +.ui.basic.inverted.buttons .button:active, +.ui.basic.inverted.button:active { + background-color: rgba(255, 255, 255, 0.08) !important; + color: #FFFFFF !important; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.9) inset !important; +} + +.ui.basic.inverted.buttons .active.button, +.ui.basic.inverted.active.button { + background-color: rgba(255, 255, 255, 0.08); + color: #FFFFFF; + text-shadow: none; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.7) inset; +} + +.ui.basic.inverted.buttons .active.button:hover, +.ui.basic.inverted.active.button:hover { + background-color: rgba(255, 255, 255, 0.15); + box-shadow: 0px 0px 0px 2px #ffffff inset !important; +} + +/* Basic Group */ + +.ui.basic.buttons .button { + border-left: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: none; +} + +.ui.basic.vertical.buttons .button { + border-left: none; +} + +.ui.basic.vertical.buttons .button { + border-left-width: 0px; + border-top: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.basic.vertical.buttons .button:first-child { + border-top-width: 0px; +} + +/*-------------- + Labeled Icon +---------------*/ + +.ui.labeled.icon.buttons .button, +.ui.labeled.icon.button { + position: relative; + padding-left: 4.07142857em !important; + padding-right: 1.5em !important; +} + +/* Left Labeled */ + +.ui.labeled.icon.buttons > .button > .icon, +.ui.labeled.icon.button > .icon { + position: absolute; + height: 100%; + line-height: 1; + border-radius: 0px; + border-top-left-radius: inherit; + border-bottom-left-radius: inherit; + text-align: center; + margin: 0em; + width: 2.57142857em; + background-color: rgba(0, 0, 0, 0.05); + color: ''; + box-shadow: -1px 0px 0px 0px transparent inset; +} + +/* Left Labeled */ + +.ui.labeled.icon.buttons > .button > .icon, +.ui.labeled.icon.button > .icon { + top: 0em; + left: 0em; +} + +/* Right Labeled */ + +.ui[class*="right labeled"].icon.button { + padding-right: 4.07142857em !important; + padding-left: 1.5em !important; +} + +.ui[class*="right labeled"].icon.button > .icon { + left: auto; + right: 0em; + border-radius: 0px; + border-top-right-radius: inherit; + border-bottom-right-radius: inherit; + box-shadow: 1px 0px 0px 0px transparent inset; +} + +.ui.labeled.icon.buttons > .button > .icon:before, +.ui.labeled.icon.button > .icon:before, +.ui.labeled.icon.buttons > .button > .icon:after, +.ui.labeled.icon.button > .icon:after { + display: block; + position: absolute; + width: 100%; + top: 50%; + text-align: center; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} + +.ui.labeled.icon.buttons .button > .icon { + border-radius: 0em; +} + +.ui.labeled.icon.buttons .button:first-child > .icon { + border-top-left-radius: 0.28571429rem; + border-bottom-left-radius: 0.28571429rem; +} + +.ui.labeled.icon.buttons .button:last-child > .icon { + border-top-right-radius: 0.28571429rem; + border-bottom-right-radius: 0.28571429rem; +} + +.ui.vertical.labeled.icon.buttons .button:first-child > .icon { + border-radius: 0em; + border-top-left-radius: 0.28571429rem; +} + +.ui.vertical.labeled.icon.buttons .button:last-child > .icon { + border-radius: 0em; + border-bottom-left-radius: 0.28571429rem; +} + +/* Fluid Labeled */ + +.ui.fluid[class*="left labeled"].icon.button, +.ui.fluid[class*="right labeled"].icon.button { + padding-left: 1.5em !important; + padding-right: 1.5em !important; +} + +/*-------------- + Toggle +---------------*/ + +/* Toggle (Modifies active state to give affordances) */ + +.ui.toggle.buttons .active.button, +.ui.buttons .button.toggle.active, +.ui.button.toggle.active { + background-color: #21BA45 !important; + box-shadow: none !important; + text-shadow: none; + color: #FFFFFF !important; +} + +.ui.button.toggle.active:hover { + background-color: #16ab39 !important; + text-shadow: none; + color: #FFFFFF !important; +} + +/*-------------- + Circular +---------------*/ + +.ui.circular.button { + border-radius: 10em; +} + +.ui.circular.button > .icon { + width: 1em; + vertical-align: baseline; +} + +/*------------------- + Or Buttons +--------------------*/ + +.ui.buttons .or { + position: relative; + width: 0.3em; + height: 2.57142857em; + z-index: 3; +} + +.ui.buttons .or:before { + position: absolute; + text-align: center; + border-radius: 500rem; + content: 'or'; + top: 50%; + left: 50%; + background-color: #FFFFFF; + text-shadow: none; + margin-top: -0.89285714em; + margin-left: -0.89285714em; + width: 1.78571429em; + height: 1.78571429em; + line-height: 1.78571429em; + color: rgba(0, 0, 0, 0.4); + font-style: normal; + font-weight: bold; + box-shadow: 0px 0px 0px 1px transparent inset; +} + +.ui.buttons .or[data-text]:before { + content: attr(data-text); +} + +/* Fluid Or */ + +.ui.fluid.buttons .or { + width: 0em !important; +} + +.ui.fluid.buttons .or:after { + display: none; +} + +/*------------------- + Attached +--------------------*/ + +/* Singular */ + +.ui.attached.button { + position: relative; + display: block; + margin: 0em; + border-radius: 0em; + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.15) !important; +} + +/* Top / Bottom */ + +.ui.attached.top.button { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.attached.bottom.button { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +/* Left / Right */ + +.ui.left.attached.button { + display: inline-block; + border-left: none; + text-align: right; + padding-right: 0.75em; + border-radius: 0.28571429rem 0em 0em 0.28571429rem; +} + +.ui.right.attached.button { + display: inline-block; + text-align: left; + padding-left: 0.75em; + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +/* Plural */ + +.ui.attached.buttons { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + border-radius: 0em; + width: auto !important; + z-index: 2; + margin-left: -1px; + margin-right: -1px; +} + +.ui.attached.buttons .button { + margin: 0em; +} + +.ui.attached.buttons .button:first-child { + border-radius: 0em; +} + +.ui.attached.buttons .button:last-child { + border-radius: 0em; +} + +/* Top / Bottom */ + +.ui[class*="top attached"].buttons { + margin-bottom: -1px; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui[class*="top attached"].buttons .button:first-child { + border-radius: 0.28571429rem 0em 0em 0em; +} + +.ui[class*="top attached"].buttons .button:last-child { + border-radius: 0em 0.28571429rem 0em 0em; +} + +.ui[class*="bottom attached"].buttons { + margin-top: -1px; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui[class*="bottom attached"].buttons .button:first-child { + border-radius: 0em 0em 0em 0.28571429rem; +} + +.ui[class*="bottom attached"].buttons .button:last-child { + border-radius: 0em 0em 0.28571429rem 0em; +} + +/* Left / Right */ + +.ui[class*="left attached"].buttons { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + margin-right: 0em; + margin-left: -1px; + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +.ui[class*="left attached"].buttons .button:first-child { + margin-left: -1px; + border-radius: 0em 0.28571429rem 0em 0em; +} + +.ui[class*="left attached"].buttons .button:last-child { + margin-left: -1px; + border-radius: 0em 0em 0.28571429rem 0em; +} + +.ui[class*="right attached"].buttons { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + margin-left: 0em; + margin-right: -1px; + border-radius: 0.28571429rem 0em 0em 0.28571429rem; +} + +.ui[class*="right attached"].buttons .button:first-child { + margin-left: -1px; + border-radius: 0.28571429rem 0em 0em 0em; +} + +.ui[class*="right attached"].buttons .button:last-child { + margin-left: -1px; + border-radius: 0em 0em 0em 0.28571429rem; +} + +/*------------------- + Fluid +--------------------*/ + +.ui.fluid.buttons, +.ui.fluid.button { + width: 100%; +} + +.ui.fluid.button { + display: block; +} + +.ui.two.buttons { + width: 100%; +} + +.ui.two.buttons > .button { + width: 50%; +} + +.ui.three.buttons { + width: 100%; +} + +.ui.three.buttons > .button { + width: 33.333%; +} + +.ui.four.buttons { + width: 100%; +} + +.ui.four.buttons > .button { + width: 25%; +} + +.ui.five.buttons { + width: 100%; +} + +.ui.five.buttons > .button { + width: 20%; +} + +.ui.six.buttons { + width: 100%; +} + +.ui.six.buttons > .button { + width: 16.666%; +} + +.ui.seven.buttons { + width: 100%; +} + +.ui.seven.buttons > .button { + width: 14.285%; +} + +.ui.eight.buttons { + width: 100%; +} + +.ui.eight.buttons > .button { + width: 12.500%; +} + +.ui.nine.buttons { + width: 100%; +} + +.ui.nine.buttons > .button { + width: 11.11%; +} + +.ui.ten.buttons { + width: 100%; +} + +.ui.ten.buttons > .button { + width: 10%; +} + +.ui.eleven.buttons { + width: 100%; +} + +.ui.eleven.buttons > .button { + width: 9.09%; +} + +.ui.twelve.buttons { + width: 100%; +} + +.ui.twelve.buttons > .button { + width: 8.3333%; +} + +/* Fluid Vertical Buttons */ + +.ui.fluid.vertical.buttons, +.ui.fluid.vertical.buttons > .button { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: auto; +} + +.ui.two.vertical.buttons > .button { + height: 50%; +} + +.ui.three.vertical.buttons > .button { + height: 33.333%; +} + +.ui.four.vertical.buttons > .button { + height: 25%; +} + +.ui.five.vertical.buttons > .button { + height: 20%; +} + +.ui.six.vertical.buttons > .button { + height: 16.666%; +} + +.ui.seven.vertical.buttons > .button { + height: 14.285%; +} + +.ui.eight.vertical.buttons > .button { + height: 12.500%; +} + +.ui.nine.vertical.buttons > .button { + height: 11.11%; +} + +.ui.ten.vertical.buttons > .button { + height: 10%; +} + +.ui.eleven.vertical.buttons > .button { + height: 9.09%; +} + +.ui.twelve.vertical.buttons > .button { + height: 8.3333%; +} + +/*------------------- + Colors +--------------------*/ + +/*--- Black ---*/ + +.ui.black.buttons .button, +.ui.black.button { + background-color: #1B1C1D; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.black.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.black.buttons .button:hover, +.ui.black.button:hover { + background-color: #27292a; + color: #FFFFFF; + text-shadow: none; +} + +.ui.black.buttons .button:focus, +.ui.black.button:focus { + background-color: #2f3032; + color: #FFFFFF; + text-shadow: none; +} + +.ui.black.buttons .button:active, +.ui.black.button:active { + background-color: #343637; + color: #FFFFFF; + text-shadow: none; +} + +.ui.black.buttons .active.button, +.ui.black.buttons .active.button:active, +.ui.black.active.button, +.ui.black.button .active.button:active { + background-color: #0f0f10; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.black.buttons .button, +.ui.basic.black.button { + box-shadow: 0px 0px 0px 1px #1B1C1D inset !important; + color: #1B1C1D !important; +} + +.ui.basic.black.buttons .button:hover, +.ui.basic.black.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #27292a inset !important; + color: #27292a !important; +} + +.ui.basic.black.buttons .button:focus, +.ui.basic.black.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #2f3032 inset !important; + color: #27292a !important; +} + +.ui.basic.black.buttons .active.button, +.ui.basic.black.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #0f0f10 inset !important; + color: #343637 !important; +} + +.ui.basic.black.buttons .button:active, +.ui.basic.black.button:active { + box-shadow: 0px 0px 0px 1px #343637 inset !important; + color: #343637 !important; +} + +.ui.buttons:not(.vertical) > .basic.black.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.black.buttons .button, +.ui.inverted.black.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #D4D4D5 inset !important; + color: #FFFFFF; +} + +.ui.inverted.black.buttons .button:hover, +.ui.inverted.black.button:hover, +.ui.inverted.black.buttons .button:focus, +.ui.inverted.black.button:focus, +.ui.inverted.black.buttons .button.active, +.ui.inverted.black.button.active, +.ui.inverted.black.buttons .button:active, +.ui.inverted.black.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.black.buttons .button:hover, +.ui.inverted.black.button:hover { + background-color: #000000; +} + +.ui.inverted.black.buttons .button:focus, +.ui.inverted.black.button:focus { + background-color: #000000; +} + +.ui.inverted.black.buttons .active.button, +.ui.inverted.black.active.button { + background-color: #000000; +} + +.ui.inverted.black.buttons .button:active, +.ui.inverted.black.button:active { + background-color: #000000; +} + +/* Inverted Basic */ + +.ui.inverted.black.basic.buttons .button, +.ui.inverted.black.buttons .basic.button, +.ui.inverted.black.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.black.basic.buttons .button:hover, +.ui.inverted.black.buttons .basic.button:hover, +.ui.inverted.black.basic.button:hover { + box-shadow: 0px 0px 0px 2px #000000 inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.black.basic.buttons .button:focus, +.ui.inverted.black.basic.buttons .button:focus, +.ui.inverted.black.basic.button:focus { + box-shadow: 0px 0px 0px 2px #000000 inset !important; + color: #545454 !important; +} + +.ui.inverted.black.basic.buttons .active.button, +.ui.inverted.black.buttons .basic.active.button, +.ui.inverted.black.basic.active.button { + box-shadow: 0px 0px 0px 2px #000000 inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.black.basic.buttons .button:active, +.ui.inverted.black.buttons .basic.button:active, +.ui.inverted.black.basic.button:active { + box-shadow: 0px 0px 0px 2px #000000 inset !important; + color: #FFFFFF !important; +} + +/*--- Grey ---*/ + +.ui.grey.buttons .button, +.ui.grey.button { + background-color: #767676; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.grey.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.grey.buttons .button:hover, +.ui.grey.button:hover { + background-color: #838383; + color: #FFFFFF; + text-shadow: none; +} + +.ui.grey.buttons .button:focus, +.ui.grey.button:focus { + background-color: #8a8a8a; + color: #FFFFFF; + text-shadow: none; +} + +.ui.grey.buttons .button:active, +.ui.grey.button:active { + background-color: #909090; + color: #FFFFFF; + text-shadow: none; +} + +.ui.grey.buttons .active.button, +.ui.grey.buttons .active.button:active, +.ui.grey.active.button, +.ui.grey.button .active.button:active { + background-color: #696969; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.grey.buttons .button, +.ui.basic.grey.button { + box-shadow: 0px 0px 0px 1px #767676 inset !important; + color: #767676 !important; +} + +.ui.basic.grey.buttons .button:hover, +.ui.basic.grey.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #838383 inset !important; + color: #838383 !important; +} + +.ui.basic.grey.buttons .button:focus, +.ui.basic.grey.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #8a8a8a inset !important; + color: #838383 !important; +} + +.ui.basic.grey.buttons .active.button, +.ui.basic.grey.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #696969 inset !important; + color: #909090 !important; +} + +.ui.basic.grey.buttons .button:active, +.ui.basic.grey.button:active { + box-shadow: 0px 0px 0px 1px #909090 inset !important; + color: #909090 !important; +} + +.ui.buttons:not(.vertical) > .basic.grey.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.grey.buttons .button, +.ui.inverted.grey.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #D4D4D5 inset !important; + color: #FFFFFF; +} + +.ui.inverted.grey.buttons .button:hover, +.ui.inverted.grey.button:hover, +.ui.inverted.grey.buttons .button:focus, +.ui.inverted.grey.button:focus, +.ui.inverted.grey.buttons .button.active, +.ui.inverted.grey.button.active, +.ui.inverted.grey.buttons .button:active, +.ui.inverted.grey.button:active { + box-shadow: none !important; + color: rgba(0, 0, 0, 0.6); +} + +.ui.inverted.grey.buttons .button:hover, +.ui.inverted.grey.button:hover { + background-color: #cfd0d2; +} + +.ui.inverted.grey.buttons .button:focus, +.ui.inverted.grey.button:focus { + background-color: #c7c9cb; +} + +.ui.inverted.grey.buttons .active.button, +.ui.inverted.grey.active.button { + background-color: #cfd0d2; +} + +.ui.inverted.grey.buttons .button:active, +.ui.inverted.grey.button:active { + background-color: #c2c4c5; +} + +/* Inverted Basic */ + +.ui.inverted.grey.basic.buttons .button, +.ui.inverted.grey.buttons .basic.button, +.ui.inverted.grey.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.grey.basic.buttons .button:hover, +.ui.inverted.grey.buttons .basic.button:hover, +.ui.inverted.grey.basic.button:hover { + box-shadow: 0px 0px 0px 2px #cfd0d2 inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.grey.basic.buttons .button:focus, +.ui.inverted.grey.basic.buttons .button:focus, +.ui.inverted.grey.basic.button:focus { + box-shadow: 0px 0px 0px 2px #c7c9cb inset !important; + color: #DCDDDE !important; +} + +.ui.inverted.grey.basic.buttons .active.button, +.ui.inverted.grey.buttons .basic.active.button, +.ui.inverted.grey.basic.active.button { + box-shadow: 0px 0px 0px 2px #cfd0d2 inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.grey.basic.buttons .button:active, +.ui.inverted.grey.buttons .basic.button:active, +.ui.inverted.grey.basic.button:active { + box-shadow: 0px 0px 0px 2px #c2c4c5 inset !important; + color: #FFFFFF !important; +} + +/*--- Brown ---*/ + +.ui.brown.buttons .button, +.ui.brown.button { + background-color: #A5673F; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.brown.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.brown.buttons .button:hover, +.ui.brown.button:hover { + background-color: #975b33; + color: #FFFFFF; + text-shadow: none; +} + +.ui.brown.buttons .button:focus, +.ui.brown.button:focus { + background-color: #90532b; + color: #FFFFFF; + text-shadow: none; +} + +.ui.brown.buttons .button:active, +.ui.brown.button:active { + background-color: #805031; + color: #FFFFFF; + text-shadow: none; +} + +.ui.brown.buttons .active.button, +.ui.brown.buttons .active.button:active, +.ui.brown.active.button, +.ui.brown.button .active.button:active { + background-color: #995a31; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.brown.buttons .button, +.ui.basic.brown.button { + box-shadow: 0px 0px 0px 1px #A5673F inset !important; + color: #A5673F !important; +} + +.ui.basic.brown.buttons .button:hover, +.ui.basic.brown.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #975b33 inset !important; + color: #975b33 !important; +} + +.ui.basic.brown.buttons .button:focus, +.ui.basic.brown.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #90532b inset !important; + color: #975b33 !important; +} + +.ui.basic.brown.buttons .active.button, +.ui.basic.brown.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #995a31 inset !important; + color: #805031 !important; +} + +.ui.basic.brown.buttons .button:active, +.ui.basic.brown.button:active { + box-shadow: 0px 0px 0px 1px #805031 inset !important; + color: #805031 !important; +} + +.ui.buttons:not(.vertical) > .basic.brown.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.brown.buttons .button, +.ui.inverted.brown.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #D67C1C inset !important; + color: #D67C1C; +} + +.ui.inverted.brown.buttons .button:hover, +.ui.inverted.brown.button:hover, +.ui.inverted.brown.buttons .button:focus, +.ui.inverted.brown.button:focus, +.ui.inverted.brown.buttons .button.active, +.ui.inverted.brown.button.active, +.ui.inverted.brown.buttons .button:active, +.ui.inverted.brown.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.brown.buttons .button:hover, +.ui.inverted.brown.button:hover { + background-color: #c86f11; +} + +.ui.inverted.brown.buttons .button:focus, +.ui.inverted.brown.button:focus { + background-color: #c16808; +} + +.ui.inverted.brown.buttons .active.button, +.ui.inverted.brown.active.button { + background-color: #cc6f0d; +} + +.ui.inverted.brown.buttons .button:active, +.ui.inverted.brown.button:active { + background-color: #a96216; +} + +/* Inverted Basic */ + +.ui.inverted.brown.basic.buttons .button, +.ui.inverted.brown.buttons .basic.button, +.ui.inverted.brown.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.brown.basic.buttons .button:hover, +.ui.inverted.brown.buttons .basic.button:hover, +.ui.inverted.brown.basic.button:hover { + box-shadow: 0px 0px 0px 2px #c86f11 inset !important; + color: #D67C1C !important; +} + +.ui.inverted.brown.basic.buttons .button:focus, +.ui.inverted.brown.basic.buttons .button:focus, +.ui.inverted.brown.basic.button:focus { + box-shadow: 0px 0px 0px 2px #c16808 inset !important; + color: #D67C1C !important; +} + +.ui.inverted.brown.basic.buttons .active.button, +.ui.inverted.brown.buttons .basic.active.button, +.ui.inverted.brown.basic.active.button { + box-shadow: 0px 0px 0px 2px #cc6f0d inset !important; + color: #D67C1C !important; +} + +.ui.inverted.brown.basic.buttons .button:active, +.ui.inverted.brown.buttons .basic.button:active, +.ui.inverted.brown.basic.button:active { + box-shadow: 0px 0px 0px 2px #a96216 inset !important; + color: #D67C1C !important; +} + +/*--- Blue ---*/ + +.ui.blue.buttons .button, +.ui.blue.button { + background-color: #2185D0; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.blue.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.blue.buttons .button:hover, +.ui.blue.button:hover { + background-color: #1678c2; + color: #FFFFFF; + text-shadow: none; +} + +.ui.blue.buttons .button:focus, +.ui.blue.button:focus { + background-color: #0d71bb; + color: #FFFFFF; + text-shadow: none; +} + +.ui.blue.buttons .button:active, +.ui.blue.button:active { + background-color: #1a69a4; + color: #FFFFFF; + text-shadow: none; +} + +.ui.blue.buttons .active.button, +.ui.blue.buttons .active.button:active, +.ui.blue.active.button, +.ui.blue.button .active.button:active { + background-color: #1279c6; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.blue.buttons .button, +.ui.basic.blue.button { + box-shadow: 0px 0px 0px 1px #2185D0 inset !important; + color: #2185D0 !important; +} + +.ui.basic.blue.buttons .button:hover, +.ui.basic.blue.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #1678c2 inset !important; + color: #1678c2 !important; +} + +.ui.basic.blue.buttons .button:focus, +.ui.basic.blue.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #0d71bb inset !important; + color: #1678c2 !important; +} + +.ui.basic.blue.buttons .active.button, +.ui.basic.blue.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #1279c6 inset !important; + color: #1a69a4 !important; +} + +.ui.basic.blue.buttons .button:active, +.ui.basic.blue.button:active { + box-shadow: 0px 0px 0px 1px #1a69a4 inset !important; + color: #1a69a4 !important; +} + +.ui.buttons:not(.vertical) > .basic.blue.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.blue.buttons .button, +.ui.inverted.blue.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #54C8FF inset !important; + color: #54C8FF; +} + +.ui.inverted.blue.buttons .button:hover, +.ui.inverted.blue.button:hover, +.ui.inverted.blue.buttons .button:focus, +.ui.inverted.blue.button:focus, +.ui.inverted.blue.buttons .button.active, +.ui.inverted.blue.button.active, +.ui.inverted.blue.buttons .button:active, +.ui.inverted.blue.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.blue.buttons .button:hover, +.ui.inverted.blue.button:hover { + background-color: #3ac0ff; +} + +.ui.inverted.blue.buttons .button:focus, +.ui.inverted.blue.button:focus { + background-color: #2bbbff; +} + +.ui.inverted.blue.buttons .active.button, +.ui.inverted.blue.active.button { + background-color: #3ac0ff; +} + +.ui.inverted.blue.buttons .button:active, +.ui.inverted.blue.button:active { + background-color: #21b8ff; +} + +/* Inverted Basic */ + +.ui.inverted.blue.basic.buttons .button, +.ui.inverted.blue.buttons .basic.button, +.ui.inverted.blue.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.blue.basic.buttons .button:hover, +.ui.inverted.blue.buttons .basic.button:hover, +.ui.inverted.blue.basic.button:hover { + box-shadow: 0px 0px 0px 2px #3ac0ff inset !important; + color: #54C8FF !important; +} + +.ui.inverted.blue.basic.buttons .button:focus, +.ui.inverted.blue.basic.buttons .button:focus, +.ui.inverted.blue.basic.button:focus { + box-shadow: 0px 0px 0px 2px #2bbbff inset !important; + color: #54C8FF !important; +} + +.ui.inverted.blue.basic.buttons .active.button, +.ui.inverted.blue.buttons .basic.active.button, +.ui.inverted.blue.basic.active.button { + box-shadow: 0px 0px 0px 2px #3ac0ff inset !important; + color: #54C8FF !important; +} + +.ui.inverted.blue.basic.buttons .button:active, +.ui.inverted.blue.buttons .basic.button:active, +.ui.inverted.blue.basic.button:active { + box-shadow: 0px 0px 0px 2px #21b8ff inset !important; + color: #54C8FF !important; +} + +/*--- Green ---*/ + +.ui.green.buttons .button, +.ui.green.button { + background-color: #21BA45; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.green.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.green.buttons .button:hover, +.ui.green.button:hover { + background-color: #16ab39; + color: #FFFFFF; + text-shadow: none; +} + +.ui.green.buttons .button:focus, +.ui.green.button:focus { + background-color: #0ea432; + color: #FFFFFF; + text-shadow: none; +} + +.ui.green.buttons .button:active, +.ui.green.button:active { + background-color: #198f35; + color: #FFFFFF; + text-shadow: none; +} + +.ui.green.buttons .active.button, +.ui.green.buttons .active.button:active, +.ui.green.active.button, +.ui.green.button .active.button:active { + background-color: #13ae38; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.green.buttons .button, +.ui.basic.green.button { + box-shadow: 0px 0px 0px 1px #21BA45 inset !important; + color: #21BA45 !important; +} + +.ui.basic.green.buttons .button:hover, +.ui.basic.green.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #16ab39 inset !important; + color: #16ab39 !important; +} + +.ui.basic.green.buttons .button:focus, +.ui.basic.green.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #0ea432 inset !important; + color: #16ab39 !important; +} + +.ui.basic.green.buttons .active.button, +.ui.basic.green.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #13ae38 inset !important; + color: #198f35 !important; +} + +.ui.basic.green.buttons .button:active, +.ui.basic.green.button:active { + box-shadow: 0px 0px 0px 1px #198f35 inset !important; + color: #198f35 !important; +} + +.ui.buttons:not(.vertical) > .basic.green.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.green.buttons .button, +.ui.inverted.green.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #2ECC40 inset !important; + color: #2ECC40; +} + +.ui.inverted.green.buttons .button:hover, +.ui.inverted.green.button:hover, +.ui.inverted.green.buttons .button:focus, +.ui.inverted.green.button:focus, +.ui.inverted.green.buttons .button.active, +.ui.inverted.green.button.active, +.ui.inverted.green.buttons .button:active, +.ui.inverted.green.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.green.buttons .button:hover, +.ui.inverted.green.button:hover { + background-color: #22be34; +} + +.ui.inverted.green.buttons .button:focus, +.ui.inverted.green.button:focus { + background-color: #19b82b; +} + +.ui.inverted.green.buttons .active.button, +.ui.inverted.green.active.button { + background-color: #1fc231; +} + +.ui.inverted.green.buttons .button:active, +.ui.inverted.green.button:active { + background-color: #25a233; +} + +/* Inverted Basic */ + +.ui.inverted.green.basic.buttons .button, +.ui.inverted.green.buttons .basic.button, +.ui.inverted.green.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.green.basic.buttons .button:hover, +.ui.inverted.green.buttons .basic.button:hover, +.ui.inverted.green.basic.button:hover { + box-shadow: 0px 0px 0px 2px #22be34 inset !important; + color: #2ECC40 !important; +} + +.ui.inverted.green.basic.buttons .button:focus, +.ui.inverted.green.basic.buttons .button:focus, +.ui.inverted.green.basic.button:focus { + box-shadow: 0px 0px 0px 2px #19b82b inset !important; + color: #2ECC40 !important; +} + +.ui.inverted.green.basic.buttons .active.button, +.ui.inverted.green.buttons .basic.active.button, +.ui.inverted.green.basic.active.button { + box-shadow: 0px 0px 0px 2px #1fc231 inset !important; + color: #2ECC40 !important; +} + +.ui.inverted.green.basic.buttons .button:active, +.ui.inverted.green.buttons .basic.button:active, +.ui.inverted.green.basic.button:active { + box-shadow: 0px 0px 0px 2px #25a233 inset !important; + color: #2ECC40 !important; +} + +/*--- Orange ---*/ + +.ui.orange.buttons .button, +.ui.orange.button { + background-color: #F2711C; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.orange.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.orange.buttons .button:hover, +.ui.orange.button:hover { + background-color: #f26202; + color: #FFFFFF; + text-shadow: none; +} + +.ui.orange.buttons .button:focus, +.ui.orange.button:focus { + background-color: #e55b00; + color: #FFFFFF; + text-shadow: none; +} + +.ui.orange.buttons .button:active, +.ui.orange.button:active { + background-color: #cf590c; + color: #FFFFFF; + text-shadow: none; +} + +.ui.orange.buttons .active.button, +.ui.orange.buttons .active.button:active, +.ui.orange.active.button, +.ui.orange.button .active.button:active { + background-color: #f56100; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.orange.buttons .button, +.ui.basic.orange.button { + box-shadow: 0px 0px 0px 1px #F2711C inset !important; + color: #F2711C !important; +} + +.ui.basic.orange.buttons .button:hover, +.ui.basic.orange.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #f26202 inset !important; + color: #f26202 !important; +} + +.ui.basic.orange.buttons .button:focus, +.ui.basic.orange.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #e55b00 inset !important; + color: #f26202 !important; +} + +.ui.basic.orange.buttons .active.button, +.ui.basic.orange.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #f56100 inset !important; + color: #cf590c !important; +} + +.ui.basic.orange.buttons .button:active, +.ui.basic.orange.button:active { + box-shadow: 0px 0px 0px 1px #cf590c inset !important; + color: #cf590c !important; +} + +.ui.buttons:not(.vertical) > .basic.orange.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.orange.buttons .button, +.ui.inverted.orange.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #FF851B inset !important; + color: #FF851B; +} + +.ui.inverted.orange.buttons .button:hover, +.ui.inverted.orange.button:hover, +.ui.inverted.orange.buttons .button:focus, +.ui.inverted.orange.button:focus, +.ui.inverted.orange.buttons .button.active, +.ui.inverted.orange.button.active, +.ui.inverted.orange.buttons .button:active, +.ui.inverted.orange.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.orange.buttons .button:hover, +.ui.inverted.orange.button:hover { + background-color: #ff7701; +} + +.ui.inverted.orange.buttons .button:focus, +.ui.inverted.orange.button:focus { + background-color: #f17000; +} + +.ui.inverted.orange.buttons .active.button, +.ui.inverted.orange.active.button { + background-color: #ff7701; +} + +.ui.inverted.orange.buttons .button:active, +.ui.inverted.orange.button:active { + background-color: #e76b00; +} + +/* Inverted Basic */ + +.ui.inverted.orange.basic.buttons .button, +.ui.inverted.orange.buttons .basic.button, +.ui.inverted.orange.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.orange.basic.buttons .button:hover, +.ui.inverted.orange.buttons .basic.button:hover, +.ui.inverted.orange.basic.button:hover { + box-shadow: 0px 0px 0px 2px #ff7701 inset !important; + color: #FF851B !important; +} + +.ui.inverted.orange.basic.buttons .button:focus, +.ui.inverted.orange.basic.buttons .button:focus, +.ui.inverted.orange.basic.button:focus { + box-shadow: 0px 0px 0px 2px #f17000 inset !important; + color: #FF851B !important; +} + +.ui.inverted.orange.basic.buttons .active.button, +.ui.inverted.orange.buttons .basic.active.button, +.ui.inverted.orange.basic.active.button { + box-shadow: 0px 0px 0px 2px #ff7701 inset !important; + color: #FF851B !important; +} + +.ui.inverted.orange.basic.buttons .button:active, +.ui.inverted.orange.buttons .basic.button:active, +.ui.inverted.orange.basic.button:active { + box-shadow: 0px 0px 0px 2px #e76b00 inset !important; + color: #FF851B !important; +} + +/*--- Pink ---*/ + +.ui.pink.buttons .button, +.ui.pink.button { + background-color: #E03997; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.pink.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.pink.buttons .button:hover, +.ui.pink.button:hover { + background-color: #e61a8d; + color: #FFFFFF; + text-shadow: none; +} + +.ui.pink.buttons .button:focus, +.ui.pink.button:focus { + background-color: #e10f85; + color: #FFFFFF; + text-shadow: none; +} + +.ui.pink.buttons .button:active, +.ui.pink.button:active { + background-color: #c71f7e; + color: #FFFFFF; + text-shadow: none; +} + +.ui.pink.buttons .active.button, +.ui.pink.buttons .active.button:active, +.ui.pink.active.button, +.ui.pink.button .active.button:active { + background-color: #ea158d; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.pink.buttons .button, +.ui.basic.pink.button { + box-shadow: 0px 0px 0px 1px #E03997 inset !important; + color: #E03997 !important; +} + +.ui.basic.pink.buttons .button:hover, +.ui.basic.pink.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #e61a8d inset !important; + color: #e61a8d !important; +} + +.ui.basic.pink.buttons .button:focus, +.ui.basic.pink.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #e10f85 inset !important; + color: #e61a8d !important; +} + +.ui.basic.pink.buttons .active.button, +.ui.basic.pink.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #ea158d inset !important; + color: #c71f7e !important; +} + +.ui.basic.pink.buttons .button:active, +.ui.basic.pink.button:active { + box-shadow: 0px 0px 0px 1px #c71f7e inset !important; + color: #c71f7e !important; +} + +.ui.buttons:not(.vertical) > .basic.pink.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.pink.buttons .button, +.ui.inverted.pink.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #FF8EDF inset !important; + color: #FF8EDF; +} + +.ui.inverted.pink.buttons .button:hover, +.ui.inverted.pink.button:hover, +.ui.inverted.pink.buttons .button:focus, +.ui.inverted.pink.button:focus, +.ui.inverted.pink.buttons .button.active, +.ui.inverted.pink.button.active, +.ui.inverted.pink.buttons .button:active, +.ui.inverted.pink.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.pink.buttons .button:hover, +.ui.inverted.pink.button:hover { + background-color: #ff74d8; +} + +.ui.inverted.pink.buttons .button:focus, +.ui.inverted.pink.button:focus { + background-color: #ff65d3; +} + +.ui.inverted.pink.buttons .active.button, +.ui.inverted.pink.active.button { + background-color: #ff74d8; +} + +.ui.inverted.pink.buttons .button:active, +.ui.inverted.pink.button:active { + background-color: #ff5bd1; +} + +/* Inverted Basic */ + +.ui.inverted.pink.basic.buttons .button, +.ui.inverted.pink.buttons .basic.button, +.ui.inverted.pink.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.pink.basic.buttons .button:hover, +.ui.inverted.pink.buttons .basic.button:hover, +.ui.inverted.pink.basic.button:hover { + box-shadow: 0px 0px 0px 2px #ff74d8 inset !important; + color: #FF8EDF !important; +} + +.ui.inverted.pink.basic.buttons .button:focus, +.ui.inverted.pink.basic.buttons .button:focus, +.ui.inverted.pink.basic.button:focus { + box-shadow: 0px 0px 0px 2px #ff65d3 inset !important; + color: #FF8EDF !important; +} + +.ui.inverted.pink.basic.buttons .active.button, +.ui.inverted.pink.buttons .basic.active.button, +.ui.inverted.pink.basic.active.button { + box-shadow: 0px 0px 0px 2px #ff74d8 inset !important; + color: #FF8EDF !important; +} + +.ui.inverted.pink.basic.buttons .button:active, +.ui.inverted.pink.buttons .basic.button:active, +.ui.inverted.pink.basic.button:active { + box-shadow: 0px 0px 0px 2px #ff5bd1 inset !important; + color: #FF8EDF !important; +} + +/*--- Violet ---*/ + +.ui.violet.buttons .button, +.ui.violet.button { + background-color: #6435C9; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.violet.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.violet.buttons .button:hover, +.ui.violet.button:hover { + background-color: #5829bb; + color: #FFFFFF; + text-shadow: none; +} + +.ui.violet.buttons .button:focus, +.ui.violet.button:focus { + background-color: #4f20b5; + color: #FFFFFF; + text-shadow: none; +} + +.ui.violet.buttons .button:active, +.ui.violet.button:active { + background-color: #502aa1; + color: #FFFFFF; + text-shadow: none; +} + +.ui.violet.buttons .active.button, +.ui.violet.buttons .active.button:active, +.ui.violet.active.button, +.ui.violet.button .active.button:active { + background-color: #5626bf; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.violet.buttons .button, +.ui.basic.violet.button { + box-shadow: 0px 0px 0px 1px #6435C9 inset !important; + color: #6435C9 !important; +} + +.ui.basic.violet.buttons .button:hover, +.ui.basic.violet.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #5829bb inset !important; + color: #5829bb !important; +} + +.ui.basic.violet.buttons .button:focus, +.ui.basic.violet.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #4f20b5 inset !important; + color: #5829bb !important; +} + +.ui.basic.violet.buttons .active.button, +.ui.basic.violet.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #5626bf inset !important; + color: #502aa1 !important; +} + +.ui.basic.violet.buttons .button:active, +.ui.basic.violet.button:active { + box-shadow: 0px 0px 0px 1px #502aa1 inset !important; + color: #502aa1 !important; +} + +.ui.buttons:not(.vertical) > .basic.violet.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.violet.buttons .button, +.ui.inverted.violet.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #A291FB inset !important; + color: #A291FB; +} + +.ui.inverted.violet.buttons .button:hover, +.ui.inverted.violet.button:hover, +.ui.inverted.violet.buttons .button:focus, +.ui.inverted.violet.button:focus, +.ui.inverted.violet.buttons .button.active, +.ui.inverted.violet.button.active, +.ui.inverted.violet.buttons .button:active, +.ui.inverted.violet.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.violet.buttons .button:hover, +.ui.inverted.violet.button:hover { + background-color: #8a73ff; +} + +.ui.inverted.violet.buttons .button:focus, +.ui.inverted.violet.button:focus { + background-color: #7d64ff; +} + +.ui.inverted.violet.buttons .active.button, +.ui.inverted.violet.active.button { + background-color: #8a73ff; +} + +.ui.inverted.violet.buttons .button:active, +.ui.inverted.violet.button:active { + background-color: #7860f9; +} + +/* Inverted Basic */ + +.ui.inverted.violet.basic.buttons .button, +.ui.inverted.violet.buttons .basic.button, +.ui.inverted.violet.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.violet.basic.buttons .button:hover, +.ui.inverted.violet.buttons .basic.button:hover, +.ui.inverted.violet.basic.button:hover { + box-shadow: 0px 0px 0px 2px #8a73ff inset !important; + color: #A291FB !important; +} + +.ui.inverted.violet.basic.buttons .button:focus, +.ui.inverted.violet.basic.buttons .button:focus, +.ui.inverted.violet.basic.button:focus { + box-shadow: 0px 0px 0px 2px #7d64ff inset !important; + color: #A291FB !important; +} + +.ui.inverted.violet.basic.buttons .active.button, +.ui.inverted.violet.buttons .basic.active.button, +.ui.inverted.violet.basic.active.button { + box-shadow: 0px 0px 0px 2px #8a73ff inset !important; + color: #A291FB !important; +} + +.ui.inverted.violet.basic.buttons .button:active, +.ui.inverted.violet.buttons .basic.button:active, +.ui.inverted.violet.basic.button:active { + box-shadow: 0px 0px 0px 2px #7860f9 inset !important; + color: #A291FB !important; +} + +/*--- Purple ---*/ + +.ui.purple.buttons .button, +.ui.purple.button { + background-color: #A333C8; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.purple.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.purple.buttons .button:hover, +.ui.purple.button:hover { + background-color: #9627ba; + color: #FFFFFF; + text-shadow: none; +} + +.ui.purple.buttons .button:focus, +.ui.purple.button:focus { + background-color: #8f1eb4; + color: #FFFFFF; + text-shadow: none; +} + +.ui.purple.buttons .button:active, +.ui.purple.button:active { + background-color: #82299f; + color: #FFFFFF; + text-shadow: none; +} + +.ui.purple.buttons .active.button, +.ui.purple.buttons .active.button:active, +.ui.purple.active.button, +.ui.purple.button .active.button:active { + background-color: #9724be; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.purple.buttons .button, +.ui.basic.purple.button { + box-shadow: 0px 0px 0px 1px #A333C8 inset !important; + color: #A333C8 !important; +} + +.ui.basic.purple.buttons .button:hover, +.ui.basic.purple.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #9627ba inset !important; + color: #9627ba !important; +} + +.ui.basic.purple.buttons .button:focus, +.ui.basic.purple.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #8f1eb4 inset !important; + color: #9627ba !important; +} + +.ui.basic.purple.buttons .active.button, +.ui.basic.purple.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #9724be inset !important; + color: #82299f !important; +} + +.ui.basic.purple.buttons .button:active, +.ui.basic.purple.button:active { + box-shadow: 0px 0px 0px 1px #82299f inset !important; + color: #82299f !important; +} + +.ui.buttons:not(.vertical) > .basic.purple.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.purple.buttons .button, +.ui.inverted.purple.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #DC73FF inset !important; + color: #DC73FF; +} + +.ui.inverted.purple.buttons .button:hover, +.ui.inverted.purple.button:hover, +.ui.inverted.purple.buttons .button:focus, +.ui.inverted.purple.button:focus, +.ui.inverted.purple.buttons .button.active, +.ui.inverted.purple.button.active, +.ui.inverted.purple.buttons .button:active, +.ui.inverted.purple.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.purple.buttons .button:hover, +.ui.inverted.purple.button:hover { + background-color: #d65aff; +} + +.ui.inverted.purple.buttons .button:focus, +.ui.inverted.purple.button:focus { + background-color: #d24aff; +} + +.ui.inverted.purple.buttons .active.button, +.ui.inverted.purple.active.button { + background-color: #d65aff; +} + +.ui.inverted.purple.buttons .button:active, +.ui.inverted.purple.button:active { + background-color: #cf40ff; +} + +/* Inverted Basic */ + +.ui.inverted.purple.basic.buttons .button, +.ui.inverted.purple.buttons .basic.button, +.ui.inverted.purple.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.purple.basic.buttons .button:hover, +.ui.inverted.purple.buttons .basic.button:hover, +.ui.inverted.purple.basic.button:hover { + box-shadow: 0px 0px 0px 2px #d65aff inset !important; + color: #DC73FF !important; +} + +.ui.inverted.purple.basic.buttons .button:focus, +.ui.inverted.purple.basic.buttons .button:focus, +.ui.inverted.purple.basic.button:focus { + box-shadow: 0px 0px 0px 2px #d24aff inset !important; + color: #DC73FF !important; +} + +.ui.inverted.purple.basic.buttons .active.button, +.ui.inverted.purple.buttons .basic.active.button, +.ui.inverted.purple.basic.active.button { + box-shadow: 0px 0px 0px 2px #d65aff inset !important; + color: #DC73FF !important; +} + +.ui.inverted.purple.basic.buttons .button:active, +.ui.inverted.purple.buttons .basic.button:active, +.ui.inverted.purple.basic.button:active { + box-shadow: 0px 0px 0px 2px #cf40ff inset !important; + color: #DC73FF !important; +} + +/*--- Red ---*/ + +.ui.red.buttons .button, +.ui.red.button { + background-color: #DB2828; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.red.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.red.buttons .button:hover, +.ui.red.button:hover { + background-color: #d01919; + color: #FFFFFF; + text-shadow: none; +} + +.ui.red.buttons .button:focus, +.ui.red.button:focus { + background-color: #ca1010; + color: #FFFFFF; + text-shadow: none; +} + +.ui.red.buttons .button:active, +.ui.red.button:active { + background-color: #b21e1e; + color: #FFFFFF; + text-shadow: none; +} + +.ui.red.buttons .active.button, +.ui.red.buttons .active.button:active, +.ui.red.active.button, +.ui.red.button .active.button:active { + background-color: #d41515; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.red.buttons .button, +.ui.basic.red.button { + box-shadow: 0px 0px 0px 1px #DB2828 inset !important; + color: #DB2828 !important; +} + +.ui.basic.red.buttons .button:hover, +.ui.basic.red.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #d01919 inset !important; + color: #d01919 !important; +} + +.ui.basic.red.buttons .button:focus, +.ui.basic.red.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #ca1010 inset !important; + color: #d01919 !important; +} + +.ui.basic.red.buttons .active.button, +.ui.basic.red.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #d41515 inset !important; + color: #b21e1e !important; +} + +.ui.basic.red.buttons .button:active, +.ui.basic.red.button:active { + box-shadow: 0px 0px 0px 1px #b21e1e inset !important; + color: #b21e1e !important; +} + +.ui.buttons:not(.vertical) > .basic.red.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.red.buttons .button, +.ui.inverted.red.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #FF695E inset !important; + color: #FF695E; +} + +.ui.inverted.red.buttons .button:hover, +.ui.inverted.red.button:hover, +.ui.inverted.red.buttons .button:focus, +.ui.inverted.red.button:focus, +.ui.inverted.red.buttons .button.active, +.ui.inverted.red.button.active, +.ui.inverted.red.buttons .button:active, +.ui.inverted.red.button:active { + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.inverted.red.buttons .button:hover, +.ui.inverted.red.button:hover { + background-color: #ff5144; +} + +.ui.inverted.red.buttons .button:focus, +.ui.inverted.red.button:focus { + background-color: #ff4335; +} + +.ui.inverted.red.buttons .active.button, +.ui.inverted.red.active.button { + background-color: #ff5144; +} + +.ui.inverted.red.buttons .button:active, +.ui.inverted.red.button:active { + background-color: #ff392b; +} + +/* Inverted Basic */ + +.ui.inverted.red.basic.buttons .button, +.ui.inverted.red.buttons .basic.button, +.ui.inverted.red.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.red.basic.buttons .button:hover, +.ui.inverted.red.buttons .basic.button:hover, +.ui.inverted.red.basic.button:hover { + box-shadow: 0px 0px 0px 2px #ff5144 inset !important; + color: #FF695E !important; +} + +.ui.inverted.red.basic.buttons .button:focus, +.ui.inverted.red.basic.buttons .button:focus, +.ui.inverted.red.basic.button:focus { + box-shadow: 0px 0px 0px 2px #ff4335 inset !important; + color: #FF695E !important; +} + +.ui.inverted.red.basic.buttons .active.button, +.ui.inverted.red.buttons .basic.active.button, +.ui.inverted.red.basic.active.button { + box-shadow: 0px 0px 0px 2px #ff5144 inset !important; + color: #FF695E !important; +} + +.ui.inverted.red.basic.buttons .button:active, +.ui.inverted.red.buttons .basic.button:active, +.ui.inverted.red.basic.button:active { + box-shadow: 0px 0px 0px 2px #ff392b inset !important; + color: #FF695E !important; +} + +/*--- Teal ---*/ + +.ui.teal.buttons .button, +.ui.teal.button { + background-color: #00B5AD; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.teal.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.teal.buttons .button:hover, +.ui.teal.button:hover { + background-color: #009c95; + color: #FFFFFF; + text-shadow: none; +} + +.ui.teal.buttons .button:focus, +.ui.teal.button:focus { + background-color: #008c86; + color: #FFFFFF; + text-shadow: none; +} + +.ui.teal.buttons .button:active, +.ui.teal.button:active { + background-color: #00827c; + color: #FFFFFF; + text-shadow: none; +} + +.ui.teal.buttons .active.button, +.ui.teal.buttons .active.button:active, +.ui.teal.active.button, +.ui.teal.button .active.button:active { + background-color: #009c95; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.teal.buttons .button, +.ui.basic.teal.button { + box-shadow: 0px 0px 0px 1px #00B5AD inset !important; + color: #00B5AD !important; +} + +.ui.basic.teal.buttons .button:hover, +.ui.basic.teal.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #009c95 inset !important; + color: #009c95 !important; +} + +.ui.basic.teal.buttons .button:focus, +.ui.basic.teal.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #008c86 inset !important; + color: #009c95 !important; +} + +.ui.basic.teal.buttons .active.button, +.ui.basic.teal.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #009c95 inset !important; + color: #00827c !important; +} + +.ui.basic.teal.buttons .button:active, +.ui.basic.teal.button:active { + box-shadow: 0px 0px 0px 1px #00827c inset !important; + color: #00827c !important; +} + +.ui.buttons:not(.vertical) > .basic.teal.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.teal.buttons .button, +.ui.inverted.teal.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #6DFFFF inset !important; + color: #6DFFFF; +} + +.ui.inverted.teal.buttons .button:hover, +.ui.inverted.teal.button:hover, +.ui.inverted.teal.buttons .button:focus, +.ui.inverted.teal.button:focus, +.ui.inverted.teal.buttons .button.active, +.ui.inverted.teal.button.active, +.ui.inverted.teal.buttons .button:active, +.ui.inverted.teal.button:active { + box-shadow: none !important; + color: rgba(0, 0, 0, 0.6); +} + +.ui.inverted.teal.buttons .button:hover, +.ui.inverted.teal.button:hover { + background-color: #54ffff; +} + +.ui.inverted.teal.buttons .button:focus, +.ui.inverted.teal.button:focus { + background-color: #44ffff; +} + +.ui.inverted.teal.buttons .active.button, +.ui.inverted.teal.active.button { + background-color: #54ffff; +} + +.ui.inverted.teal.buttons .button:active, +.ui.inverted.teal.button:active { + background-color: #3affff; +} + +/* Inverted Basic */ + +.ui.inverted.teal.basic.buttons .button, +.ui.inverted.teal.buttons .basic.button, +.ui.inverted.teal.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.teal.basic.buttons .button:hover, +.ui.inverted.teal.buttons .basic.button:hover, +.ui.inverted.teal.basic.button:hover { + box-shadow: 0px 0px 0px 2px #54ffff inset !important; + color: #6DFFFF !important; +} + +.ui.inverted.teal.basic.buttons .button:focus, +.ui.inverted.teal.basic.buttons .button:focus, +.ui.inverted.teal.basic.button:focus { + box-shadow: 0px 0px 0px 2px #44ffff inset !important; + color: #6DFFFF !important; +} + +.ui.inverted.teal.basic.buttons .active.button, +.ui.inverted.teal.buttons .basic.active.button, +.ui.inverted.teal.basic.active.button { + box-shadow: 0px 0px 0px 2px #54ffff inset !important; + color: #6DFFFF !important; +} + +.ui.inverted.teal.basic.buttons .button:active, +.ui.inverted.teal.buttons .basic.button:active, +.ui.inverted.teal.basic.button:active { + box-shadow: 0px 0px 0px 2px #3affff inset !important; + color: #6DFFFF !important; +} + +/*--- Olive ---*/ + +.ui.olive.buttons .button, +.ui.olive.button { + background-color: #B5CC18; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.olive.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.olive.buttons .button:hover, +.ui.olive.button:hover { + background-color: #a7bd0d; + color: #FFFFFF; + text-shadow: none; +} + +.ui.olive.buttons .button:focus, +.ui.olive.button:focus { + background-color: #a0b605; + color: #FFFFFF; + text-shadow: none; +} + +.ui.olive.buttons .button:active, +.ui.olive.button:active { + background-color: #8d9e13; + color: #FFFFFF; + text-shadow: none; +} + +.ui.olive.buttons .active.button, +.ui.olive.buttons .active.button:active, +.ui.olive.active.button, +.ui.olive.button .active.button:active { + background-color: #aac109; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.olive.buttons .button, +.ui.basic.olive.button { + box-shadow: 0px 0px 0px 1px #B5CC18 inset !important; + color: #B5CC18 !important; +} + +.ui.basic.olive.buttons .button:hover, +.ui.basic.olive.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #a7bd0d inset !important; + color: #a7bd0d !important; +} + +.ui.basic.olive.buttons .button:focus, +.ui.basic.olive.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #a0b605 inset !important; + color: #a7bd0d !important; +} + +.ui.basic.olive.buttons .active.button, +.ui.basic.olive.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #aac109 inset !important; + color: #8d9e13 !important; +} + +.ui.basic.olive.buttons .button:active, +.ui.basic.olive.button:active { + box-shadow: 0px 0px 0px 1px #8d9e13 inset !important; + color: #8d9e13 !important; +} + +.ui.buttons:not(.vertical) > .basic.olive.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.olive.buttons .button, +.ui.inverted.olive.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #D9E778 inset !important; + color: #D9E778; +} + +.ui.inverted.olive.buttons .button:hover, +.ui.inverted.olive.button:hover, +.ui.inverted.olive.buttons .button:focus, +.ui.inverted.olive.button:focus, +.ui.inverted.olive.buttons .button.active, +.ui.inverted.olive.button.active, +.ui.inverted.olive.buttons .button:active, +.ui.inverted.olive.button:active { + box-shadow: none !important; + color: rgba(0, 0, 0, 0.6); +} + +.ui.inverted.olive.buttons .button:hover, +.ui.inverted.olive.button:hover { + background-color: #d8ea5c; +} + +.ui.inverted.olive.buttons .button:focus, +.ui.inverted.olive.button:focus { + background-color: #daef47; +} + +.ui.inverted.olive.buttons .active.button, +.ui.inverted.olive.active.button { + background-color: #daed59; +} + +.ui.inverted.olive.buttons .button:active, +.ui.inverted.olive.button:active { + background-color: #cddf4d; +} + +/* Inverted Basic */ + +.ui.inverted.olive.basic.buttons .button, +.ui.inverted.olive.buttons .basic.button, +.ui.inverted.olive.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.olive.basic.buttons .button:hover, +.ui.inverted.olive.buttons .basic.button:hover, +.ui.inverted.olive.basic.button:hover { + box-shadow: 0px 0px 0px 2px #d8ea5c inset !important; + color: #D9E778 !important; +} + +.ui.inverted.olive.basic.buttons .button:focus, +.ui.inverted.olive.basic.buttons .button:focus, +.ui.inverted.olive.basic.button:focus { + box-shadow: 0px 0px 0px 2px #daef47 inset !important; + color: #D9E778 !important; +} + +.ui.inverted.olive.basic.buttons .active.button, +.ui.inverted.olive.buttons .basic.active.button, +.ui.inverted.olive.basic.active.button { + box-shadow: 0px 0px 0px 2px #daed59 inset !important; + color: #D9E778 !important; +} + +.ui.inverted.olive.basic.buttons .button:active, +.ui.inverted.olive.buttons .basic.button:active, +.ui.inverted.olive.basic.button:active { + box-shadow: 0px 0px 0px 2px #cddf4d inset !important; + color: #D9E778 !important; +} + +/*--- Yellow ---*/ + +.ui.yellow.buttons .button, +.ui.yellow.button { + background-color: #FBBD08; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.yellow.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.yellow.buttons .button:hover, +.ui.yellow.button:hover { + background-color: #eaae00; + color: #FFFFFF; + text-shadow: none; +} + +.ui.yellow.buttons .button:focus, +.ui.yellow.button:focus { + background-color: #daa300; + color: #FFFFFF; + text-shadow: none; +} + +.ui.yellow.buttons .button:active, +.ui.yellow.button:active { + background-color: #cd9903; + color: #FFFFFF; + text-shadow: none; +} + +.ui.yellow.buttons .active.button, +.ui.yellow.buttons .active.button:active, +.ui.yellow.active.button, +.ui.yellow.button .active.button:active { + background-color: #eaae00; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.yellow.buttons .button, +.ui.basic.yellow.button { + box-shadow: 0px 0px 0px 1px #FBBD08 inset !important; + color: #FBBD08 !important; +} + +.ui.basic.yellow.buttons .button:hover, +.ui.basic.yellow.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #eaae00 inset !important; + color: #eaae00 !important; +} + +.ui.basic.yellow.buttons .button:focus, +.ui.basic.yellow.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #daa300 inset !important; + color: #eaae00 !important; +} + +.ui.basic.yellow.buttons .active.button, +.ui.basic.yellow.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #eaae00 inset !important; + color: #cd9903 !important; +} + +.ui.basic.yellow.buttons .button:active, +.ui.basic.yellow.button:active { + box-shadow: 0px 0px 0px 1px #cd9903 inset !important; + color: #cd9903 !important; +} + +.ui.buttons:not(.vertical) > .basic.yellow.button:not(:first-child) { + margin-left: -1px; +} + +/* Inverted */ + +.ui.inverted.yellow.buttons .button, +.ui.inverted.yellow.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px #FFE21F inset !important; + color: #FFE21F; +} + +.ui.inverted.yellow.buttons .button:hover, +.ui.inverted.yellow.button:hover, +.ui.inverted.yellow.buttons .button:focus, +.ui.inverted.yellow.button:focus, +.ui.inverted.yellow.buttons .button.active, +.ui.inverted.yellow.button.active, +.ui.inverted.yellow.buttons .button:active, +.ui.inverted.yellow.button:active { + box-shadow: none !important; + color: rgba(0, 0, 0, 0.6); +} + +.ui.inverted.yellow.buttons .button:hover, +.ui.inverted.yellow.button:hover { + background-color: #ffdf05; +} + +.ui.inverted.yellow.buttons .button:focus, +.ui.inverted.yellow.button:focus { + background-color: #f5d500; +} + +.ui.inverted.yellow.buttons .active.button, +.ui.inverted.yellow.active.button { + background-color: #ffdf05; +} + +.ui.inverted.yellow.buttons .button:active, +.ui.inverted.yellow.button:active { + background-color: #ebcd00; +} + +/* Inverted Basic */ + +.ui.inverted.yellow.basic.buttons .button, +.ui.inverted.yellow.buttons .basic.button, +.ui.inverted.yellow.basic.button { + background-color: transparent; + box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.5) inset !important; + color: #FFFFFF !important; +} + +.ui.inverted.yellow.basic.buttons .button:hover, +.ui.inverted.yellow.buttons .basic.button:hover, +.ui.inverted.yellow.basic.button:hover { + box-shadow: 0px 0px 0px 2px #ffdf05 inset !important; + color: #FFE21F !important; +} + +.ui.inverted.yellow.basic.buttons .button:focus, +.ui.inverted.yellow.basic.buttons .button:focus, +.ui.inverted.yellow.basic.button:focus { + box-shadow: 0px 0px 0px 2px #f5d500 inset !important; + color: #FFE21F !important; +} + +.ui.inverted.yellow.basic.buttons .active.button, +.ui.inverted.yellow.buttons .basic.active.button, +.ui.inverted.yellow.basic.active.button { + box-shadow: 0px 0px 0px 2px #ffdf05 inset !important; + color: #FFE21F !important; +} + +.ui.inverted.yellow.basic.buttons .button:active, +.ui.inverted.yellow.buttons .basic.button:active, +.ui.inverted.yellow.basic.button:active { + box-shadow: 0px 0px 0px 2px #ebcd00 inset !important; + color: #FFE21F !important; +} + +/*------------------- + Primary +--------------------*/ + +/*--- Standard ---*/ + +.ui.primary.buttons .button, +.ui.primary.button { + background-color: #2185D0; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.primary.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.primary.buttons .button:hover, +.ui.primary.button:hover { + background-color: #1678c2; + color: #FFFFFF; + text-shadow: none; +} + +.ui.primary.buttons .button:focus, +.ui.primary.button:focus { + background-color: #0d71bb; + color: #FFFFFF; + text-shadow: none; +} + +.ui.primary.buttons .button:active, +.ui.primary.button:active { + background-color: #1a69a4; + color: #FFFFFF; + text-shadow: none; +} + +.ui.primary.buttons .active.button, +.ui.primary.buttons .active.button:active, +.ui.primary.active.button, +.ui.primary.button .active.button:active { + background-color: #1279c6; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.primary.buttons .button, +.ui.basic.primary.button { + box-shadow: 0px 0px 0px 1px #2185D0 inset !important; + color: #2185D0 !important; +} + +.ui.basic.primary.buttons .button:hover, +.ui.basic.primary.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #1678c2 inset !important; + color: #1678c2 !important; +} + +.ui.basic.primary.buttons .button:focus, +.ui.basic.primary.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #0d71bb inset !important; + color: #1678c2 !important; +} + +.ui.basic.primary.buttons .active.button, +.ui.basic.primary.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #1279c6 inset !important; + color: #1a69a4 !important; +} + +.ui.basic.primary.buttons .button:active, +.ui.basic.primary.button:active { + box-shadow: 0px 0px 0px 1px #1a69a4 inset !important; + color: #1a69a4 !important; +} + +.ui.buttons:not(.vertical) > .basic.primary.button:not(:first-child) { + margin-left: -1px; +} + +/*------------------- + Secondary +--------------------*/ + +/* Standard */ + +.ui.secondary.buttons .button, +.ui.secondary.button { + background-color: #1B1C1D; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.secondary.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.secondary.buttons .button:hover, +.ui.secondary.button:hover { + background-color: #27292a; + color: #FFFFFF; + text-shadow: none; +} + +.ui.secondary.buttons .button:focus, +.ui.secondary.button:focus { + background-color: #2e3032; + color: #FFFFFF; + text-shadow: none; +} + +.ui.secondary.buttons .button:active, +.ui.secondary.button:active { + background-color: #343637; + color: #FFFFFF; + text-shadow: none; +} + +.ui.secondary.buttons .active.button, +.ui.secondary.buttons .active.button:active, +.ui.secondary.active.button, +.ui.secondary.button .active.button:active { + background-color: #27292a; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.secondary.buttons .button, +.ui.basic.secondary.button { + box-shadow: 0px 0px 0px 1px #1B1C1D inset !important; + color: #1B1C1D !important; +} + +.ui.basic.secondary.buttons .button:hover, +.ui.basic.secondary.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #27292a inset !important; + color: #27292a !important; +} + +.ui.basic.secondary.buttons .button:focus, +.ui.basic.secondary.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #2e3032 inset !important; + color: #27292a !important; +} + +.ui.basic.secondary.buttons .active.button, +.ui.basic.secondary.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #27292a inset !important; + color: #343637 !important; +} + +.ui.basic.secondary.buttons .button:active, +.ui.basic.secondary.button:active { + box-shadow: 0px 0px 0px 1px #343637 inset !important; + color: #343637 !important; +} + +.ui.buttons:not(.vertical) > .basic.primary.button:not(:first-child) { + margin-left: -1px; +} + +/*--------------- + Positive +----------------*/ + +/* Standard */ + +.ui.positive.buttons .button, +.ui.positive.button { + background-color: #21BA45; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.positive.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.positive.buttons .button:hover, +.ui.positive.button:hover { + background-color: #16ab39; + color: #FFFFFF; + text-shadow: none; +} + +.ui.positive.buttons .button:focus, +.ui.positive.button:focus { + background-color: #0ea432; + color: #FFFFFF; + text-shadow: none; +} + +.ui.positive.buttons .button:active, +.ui.positive.button:active { + background-color: #198f35; + color: #FFFFFF; + text-shadow: none; +} + +.ui.positive.buttons .active.button, +.ui.positive.buttons .active.button:active, +.ui.positive.active.button, +.ui.positive.button .active.button:active { + background-color: #13ae38; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.positive.buttons .button, +.ui.basic.positive.button { + box-shadow: 0px 0px 0px 1px #21BA45 inset !important; + color: #21BA45 !important; +} + +.ui.basic.positive.buttons .button:hover, +.ui.basic.positive.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #16ab39 inset !important; + color: #16ab39 !important; +} + +.ui.basic.positive.buttons .button:focus, +.ui.basic.positive.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #0ea432 inset !important; + color: #16ab39 !important; +} + +.ui.basic.positive.buttons .active.button, +.ui.basic.positive.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #13ae38 inset !important; + color: #198f35 !important; +} + +.ui.basic.positive.buttons .button:active, +.ui.basic.positive.button:active { + box-shadow: 0px 0px 0px 1px #198f35 inset !important; + color: #198f35 !important; +} + +.ui.buttons:not(.vertical) > .basic.primary.button:not(:first-child) { + margin-left: -1px; +} + +/*--------------- + Negative +----------------*/ + +/* Standard */ + +.ui.negative.buttons .button, +.ui.negative.button { + background-color: #DB2828; + color: #FFFFFF; + text-shadow: none; + background-image: none; +} + +.ui.negative.button { + box-shadow: 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.negative.buttons .button:hover, +.ui.negative.button:hover { + background-color: #d01919; + color: #FFFFFF; + text-shadow: none; +} + +.ui.negative.buttons .button:focus, +.ui.negative.button:focus { + background-color: #ca1010; + color: #FFFFFF; + text-shadow: none; +} + +.ui.negative.buttons .button:active, +.ui.negative.button:active { + background-color: #b21e1e; + color: #FFFFFF; + text-shadow: none; +} + +.ui.negative.buttons .active.button, +.ui.negative.buttons .active.button:active, +.ui.negative.active.button, +.ui.negative.button .active.button:active { + background-color: #d41515; + color: #FFFFFF; + text-shadow: none; +} + +/* Basic */ + +.ui.basic.negative.buttons .button, +.ui.basic.negative.button { + box-shadow: 0px 0px 0px 1px #DB2828 inset !important; + color: #DB2828 !important; +} + +.ui.basic.negative.buttons .button:hover, +.ui.basic.negative.button:hover { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #d01919 inset !important; + color: #d01919 !important; +} + +.ui.basic.negative.buttons .button:focus, +.ui.basic.negative.button:focus { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #ca1010 inset !important; + color: #d01919 !important; +} + +.ui.basic.negative.buttons .active.button, +.ui.basic.negative.active.button { + background: transparent !important; + box-shadow: 0px 0px 0px 1px #d41515 inset !important; + color: #b21e1e !important; +} + +.ui.basic.negative.buttons .button:active, +.ui.basic.negative.button:active { + box-shadow: 0px 0px 0px 1px #b21e1e inset !important; + color: #b21e1e !important; +} + +.ui.buttons:not(.vertical) > .basic.primary.button:not(:first-child) { + margin-left: -1px; +} + +/******************************* + Groups +*******************************/ + +.ui.buttons { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + font-size: 0em; + vertical-align: baseline; + margin: 0em 0.25em 0em 0em; +} + +.ui.buttons:not(.basic):not(.inverted) { + box-shadow: none; +} + +/* Clearfix */ + +.ui.buttons:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +/* Standard Group */ + +.ui.buttons .button { + -webkit-box-flex: 1; + -webkit-flex: 1 0 auto; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + margin: 0em; + border-radius: 0em; + margin: 0px 0px 0px 0px; +} + +.ui.buttons > .ui.button:not(.basic):not(.inverted), +.ui.buttons:not(.basic):not(.inverted) > .button { + box-shadow: 0px 0px 0px 1px transparent inset, 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset; +} + +.ui.buttons .button:first-child { + border-left: none; + margin-left: 0em; + border-top-left-radius: 0.28571429rem; + border-bottom-left-radius: 0.28571429rem; +} + +.ui.buttons .button:last-child { + border-top-right-radius: 0.28571429rem; + border-bottom-right-radius: 0.28571429rem; +} + +/* Vertical Style */ + +.ui.vertical.buttons { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +.ui.vertical.buttons .button { + display: block; + float: none; + width: 100%; + margin: 0px 0px 0px 0px; + box-shadow: none; + border-radius: 0em; +} + +.ui.vertical.buttons .button:first-child { + border-top-left-radius: 0.28571429rem; + border-top-right-radius: 0.28571429rem; +} + +.ui.vertical.buttons .button:last-child { + margin-bottom: 0px; + border-bottom-left-radius: 0.28571429rem; + border-bottom-right-radius: 0.28571429rem; +} + +.ui.vertical.buttons .button:only-child { + border-radius: 0.28571429rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Container + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Container +*******************************/ + +/* All Sizes */ + +.ui.container { + display: block; + max-width: 100% !important; +} + +/* Mobile */ + +@media only screen and (max-width: 767px) { + .ui.container { + width: auto !important; + margin-left: 1em !important; + margin-right: 1em !important; + } + + .ui.grid.container { + width: auto !important; + } + + .ui.relaxed.grid.container { + width: auto !important; + } + + .ui.very.relaxed.grid.container { + width: auto !important; + } +} + +/* Tablet */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui.container { + width: 723px; + margin-left: auto !important; + margin-right: auto !important; + } + + .ui.grid.container { + width: calc( 723px + 2rem ) !important; + } + + .ui.relaxed.grid.container { + width: calc( 723px + 3rem ) !important; + } + + .ui.very.relaxed.grid.container { + width: calc( 723px + 5rem ) !important; + } +} + +/* Small Monitor */ + +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .ui.container { + width: 933px; + margin-left: auto !important; + margin-right: auto !important; + } + + .ui.grid.container { + width: calc( 933px + 2rem ) !important; + } + + .ui.relaxed.grid.container { + width: calc( 933px + 3rem ) !important; + } + + .ui.very.relaxed.grid.container { + width: calc( 933px + 5rem ) !important; + } +} + +/* Large Monitor */ + +@media only screen and (min-width: 1200px) { + .ui.container { + width: 1127px; + margin-left: auto !important; + margin-right: auto !important; + } + + .ui.grid.container { + width: calc( 1127px + 2rem ) !important; + } + + .ui.relaxed.grid.container { + width: calc( 1127px + 3rem ) !important; + } + + .ui.very.relaxed.grid.container { + width: calc( 1127px + 5rem ) !important; + } +} + +/******************************* + Types +*******************************/ + +/* Text Container */ + +.ui.text.container { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + max-width: 700px !important; + line-height: 1.5; +} + +.ui.text.container { + font-size: 1.14285714rem; +} + +/* Fluid */ + +.ui.fluid.container { + width: 100%; +} + +/******************************* + Variations +*******************************/ + +.ui[class*="left aligned"].container { + text-align: left; +} + +.ui[class*="center aligned"].container { + text-align: center; +} + +.ui[class*="right aligned"].container { + text-align: right; +} + +.ui.justified.container { + text-align: justify; + -webkit-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Divider + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Divider +*******************************/ + +.ui.divider { + margin: 1rem 0rem; + line-height: 1; + height: 0em; + font-weight: bold; + text-transform: uppercase; + letter-spacing: 0.05em; + color: rgba(0, 0, 0, 0.85); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +/*-------------- + Basic +---------------*/ + +.ui.divider:not(.vertical):not(.horizontal) { + border-top: 1px solid rgba(34, 36, 38, 0.15); + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +/*-------------- + Coupling +---------------*/ + +/* Allow divider between each column row */ + +.ui.grid > .column + .divider, +.ui.grid > .row > .column + .divider { + left: auto; +} + +/*-------------- + Horizontal +---------------*/ + +.ui.horizontal.divider { + display: table; + white-space: nowrap; + height: auto; + margin: ''; + line-height: 1; + text-align: center; +} + +.ui.horizontal.divider:before, +.ui.horizontal.divider:after { + content: ''; + display: table-cell; + position: relative; + top: 50%; + width: 50%; + background-repeat: no-repeat; +} + +.ui.horizontal.divider:before { + background-position: right 1em top 50%; +} + +.ui.horizontal.divider:after { + background-position: left 1em top 50%; +} + +/*-------------- + Vertical +---------------*/ + +.ui.vertical.divider { + position: absolute; + z-index: 2; + top: 50%; + left: 50%; + margin: 0rem; + padding: 0em; + width: auto; + height: 50%; + line-height: 0em; + text-align: center; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); +} + +.ui.vertical.divider:before, +.ui.vertical.divider:after { + position: absolute; + left: 50%; + content: ''; + z-index: 3; + border-left: 1px solid rgba(34, 36, 38, 0.15); + border-right: 1px solid rgba(255, 255, 255, 0.1); + width: 0%; + height: calc(100% - 1rem ); +} + +.ui.vertical.divider:before { + top: -100%; +} + +.ui.vertical.divider:after { + top: auto; + bottom: 0px; +} + +/* Inside grid */ + +@media only screen and (max-width: 767px) { + .ui.stackable.grid .ui.vertical.divider, + .ui.grid .stackable.row .ui.vertical.divider { + display: table; + white-space: nowrap; + height: auto; + margin: ''; + overflow: hidden; + line-height: 1; + text-align: center; + position: static; + top: 0; + left: 0; + -webkit-transform: none; + transform: none; + } + + .ui.stackable.grid .ui.vertical.divider:before, + .ui.grid .stackable.row .ui.vertical.divider:before, + .ui.stackable.grid .ui.vertical.divider:after, + .ui.grid .stackable.row .ui.vertical.divider:after { + position: static; + left: 0; + border-left: none; + border-right: none; + content: ''; + display: table-cell; + position: relative; + top: 50%; + width: 50%; + background-repeat: no-repeat; + } + + .ui.stackable.grid .ui.vertical.divider:before, + .ui.grid .stackable.row .ui.vertical.divider:before { + background-position: right 1em top 50%; + } + + .ui.stackable.grid .ui.vertical.divider:after, + .ui.grid .stackable.row .ui.vertical.divider:after { + background-position: left 1em top 50%; + } +} + +/*-------------- + Icon +---------------*/ + +.ui.divider > .icon { + margin: 0rem; + font-size: 1rem; + height: 1em; + vertical-align: middle; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Hidden +---------------*/ + +.ui.hidden.divider { + border-color: transparent !important; +} + +.ui.hidden.divider:before, +.ui.hidden.divider:after { + display: none; +} + +/*-------------- + Inverted +---------------*/ + +.ui.divider.inverted, +.ui.vertical.inverted.divider, +.ui.horizontal.inverted.divider { + color: #FFFFFF; +} + +.ui.divider.inverted, +.ui.divider.inverted:after, +.ui.divider.inverted:before { + border-top-color: rgba(34, 36, 38, 0.15) !important; + border-left-color: rgba(34, 36, 38, 0.15) !important; + border-bottom-color: rgba(255, 255, 255, 0.15) !important; + border-right-color: rgba(255, 255, 255, 0.15) !important; +} + +/*-------------- + Fitted +---------------*/ + +.ui.fitted.divider { + margin: 0em; +} + +/*-------------- + Clearing +---------------*/ + +.ui.clearing.divider { + clear: both; +} + +/*-------------- + Section +---------------*/ + +.ui.section.divider { + margin-top: 2rem; + margin-bottom: 2rem; +} + +/*-------------- + Sizes +---------------*/ + +.ui.divider { + font-size: 1rem; +} + +/******************************* + Theme Overrides +*******************************/ + +.ui.horizontal.divider:before, +.ui.horizontal.divider:after { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC'); +} + +@media only screen and (max-width: 767px) { + .ui.stackable.grid .ui.vertical.divider:before, + .ui.grid .stackable.row .ui.vertical.divider:before, + .ui.stackable.grid .ui.vertical.divider:after, + .ui.grid .stackable.row .ui.vertical.divider:after { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC'); + } +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Flag + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Flag +*******************************/ + +i.flag:not(.icon) { + display: inline-block; + width: 16px; + height: 11px; + line-height: 11px; + vertical-align: baseline; + margin: 0em 0.5em 0em 0em; + text-decoration: inherit; + speak: none; + font-smoothing: antialiased; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} + +/* Sprite */ + +i.flag:not(.icon):before { + display: inline-block; + content: ''; + background: url("./themes/default/assets/images/flags.png") no-repeat -108px -1976px; + width: 16px; + height: 11px; +} + +/* Flag Sprite Based On http://www.famfamfam.com/lab/icons/flags/ */ + +/******************************* + Theme Overrides +*******************************/ + +i.flag.ad:before, +i.flag.andorra:before { + background-position: 0px 0px; +} + +i.flag.ae:before, +i.flag.united.arab.emirates:before, +i.flag.uae:before { + background-position: 0px -26px; +} + +i.flag.af:before, +i.flag.afghanistan:before { + background-position: 0px -52px; +} + +i.flag.ag:before, +i.flag.antigua:before { + background-position: 0px -78px; +} + +i.flag.ai:before, +i.flag.anguilla:before { + background-position: 0px -104px; +} + +i.flag.al:before, +i.flag.albania:before { + background-position: 0px -130px; +} + +i.flag.am:before, +i.flag.armenia:before { + background-position: 0px -156px; +} + +i.flag.an:before, +i.flag.netherlands.antilles:before { + background-position: 0px -182px; +} + +i.flag.ao:before, +i.flag.angola:before { + background-position: 0px -208px; +} + +i.flag.ar:before, +i.flag.argentina:before { + background-position: 0px -234px; +} + +i.flag.as:before, +i.flag.american.samoa:before { + background-position: 0px -260px; +} + +i.flag.at:before, +i.flag.austria:before { + background-position: 0px -286px; +} + +i.flag.au:before, +i.flag.australia:before { + background-position: 0px -312px; +} + +i.flag.aw:before, +i.flag.aruba:before { + background-position: 0px -338px; +} + +i.flag.ax:before, +i.flag.aland.islands:before { + background-position: 0px -364px; +} + +i.flag.az:before, +i.flag.azerbaijan:before { + background-position: 0px -390px; +} + +i.flag.ba:before, +i.flag.bosnia:before { + background-position: 0px -416px; +} + +i.flag.bb:before, +i.flag.barbados:before { + background-position: 0px -442px; +} + +i.flag.bd:before, +i.flag.bangladesh:before { + background-position: 0px -468px; +} + +i.flag.be:before, +i.flag.belgium:before { + background-position: 0px -494px; +} + +i.flag.bf:before, +i.flag.burkina.faso:before { + background-position: 0px -520px; +} + +i.flag.bg:before, +i.flag.bulgaria:before { + background-position: 0px -546px; +} + +i.flag.bh:before, +i.flag.bahrain:before { + background-position: 0px -572px; +} + +i.flag.bi:before, +i.flag.burundi:before { + background-position: 0px -598px; +} + +i.flag.bj:before, +i.flag.benin:before { + background-position: 0px -624px; +} + +i.flag.bm:before, +i.flag.bermuda:before { + background-position: 0px -650px; +} + +i.flag.bn:before, +i.flag.brunei:before { + background-position: 0px -676px; +} + +i.flag.bo:before, +i.flag.bolivia:before { + background-position: 0px -702px; +} + +i.flag.br:before, +i.flag.brazil:before { + background-position: 0px -728px; +} + +i.flag.bs:before, +i.flag.bahamas:before { + background-position: 0px -754px; +} + +i.flag.bt:before, +i.flag.bhutan:before { + background-position: 0px -780px; +} + +i.flag.bv:before, +i.flag.bouvet.island:before { + background-position: 0px -806px; +} + +i.flag.bw:before, +i.flag.botswana:before { + background-position: 0px -832px; +} + +i.flag.by:before, +i.flag.belarus:before { + background-position: 0px -858px; +} + +i.flag.bz:before, +i.flag.belize:before { + background-position: 0px -884px; +} + +i.flag.ca:before, +i.flag.canada:before { + background-position: 0px -910px; +} + +i.flag.cc:before, +i.flag.cocos.islands:before { + background-position: 0px -962px; +} + +i.flag.cd:before, +i.flag.congo:before { + background-position: 0px -988px; +} + +i.flag.cf:before, +i.flag.central.african.republic:before { + background-position: 0px -1014px; +} + +i.flag.cg:before, +i.flag.congo.brazzaville:before { + background-position: 0px -1040px; +} + +i.flag.ch:before, +i.flag.switzerland:before { + background-position: 0px -1066px; +} + +i.flag.ci:before, +i.flag.cote.divoire:before { + background-position: 0px -1092px; +} + +i.flag.ck:before, +i.flag.cook.islands:before { + background-position: 0px -1118px; +} + +i.flag.cl:before, +i.flag.chile:before { + background-position: 0px -1144px; +} + +i.flag.cm:before, +i.flag.cameroon:before { + background-position: 0px -1170px; +} + +i.flag.cn:before, +i.flag.china:before { + background-position: 0px -1196px; +} + +i.flag.co:before, +i.flag.colombia:before { + background-position: 0px -1222px; +} + +i.flag.cr:before, +i.flag.costa.rica:before { + background-position: 0px -1248px; +} + +i.flag.cs:before, +i.flag.serbia:before { + background-position: 0px -1274px; +} + +i.flag.cu:before, +i.flag.cuba:before { + background-position: 0px -1300px; +} + +i.flag.cv:before, +i.flag.cape.verde:before { + background-position: 0px -1326px; +} + +i.flag.cx:before, +i.flag.christmas.island:before { + background-position: 0px -1352px; +} + +i.flag.cy:before, +i.flag.cyprus:before { + background-position: 0px -1378px; +} + +i.flag.cz:before, +i.flag.czech.republic:before { + background-position: 0px -1404px; +} + +i.flag.de:before, +i.flag.germany:before { + background-position: 0px -1430px; +} + +i.flag.dj:before, +i.flag.djibouti:before { + background-position: 0px -1456px; +} + +i.flag.dk:before, +i.flag.denmark:before { + background-position: 0px -1482px; +} + +i.flag.dm:before, +i.flag.dominica:before { + background-position: 0px -1508px; +} + +i.flag.do:before, +i.flag.dominican.republic:before { + background-position: 0px -1534px; +} + +i.flag.dz:before, +i.flag.algeria:before { + background-position: 0px -1560px; +} + +i.flag.ec:before, +i.flag.ecuador:before { + background-position: 0px -1586px; +} + +i.flag.ee:before, +i.flag.estonia:before { + background-position: 0px -1612px; +} + +i.flag.eg:before, +i.flag.egypt:before { + background-position: 0px -1638px; +} + +i.flag.eh:before, +i.flag.western.sahara:before { + background-position: 0px -1664px; +} + +i.flag.er:before, +i.flag.eritrea:before { + background-position: 0px -1716px; +} + +i.flag.es:before, +i.flag.spain:before { + background-position: 0px -1742px; +} + +i.flag.et:before, +i.flag.ethiopia:before { + background-position: 0px -1768px; +} + +i.flag.eu:before, +i.flag.european.union:before { + background-position: 0px -1794px; +} + +i.flag.fi:before, +i.flag.finland:before { + background-position: 0px -1846px; +} + +i.flag.fj:before, +i.flag.fiji:before { + background-position: 0px -1872px; +} + +i.flag.fk:before, +i.flag.falkland.islands:before { + background-position: 0px -1898px; +} + +i.flag.fm:before, +i.flag.micronesia:before { + background-position: 0px -1924px; +} + +i.flag.fo:before, +i.flag.faroe.islands:before { + background-position: 0px -1950px; +} + +i.flag.fr:before, +i.flag.france:before { + background-position: 0px -1976px; +} + +i.flag.ga:before, +i.flag.gabon:before { + background-position: -36px 0px; +} + +i.flag.gb:before, +i.flag.united.kingdom:before { + background-position: -36px -26px; +} + +i.flag.gd:before, +i.flag.grenada:before { + background-position: -36px -52px; +} + +i.flag.ge:before, +i.flag.georgia:before { + background-position: -36px -78px; +} + +i.flag.gf:before, +i.flag.french.guiana:before { + background-position: -36px -104px; +} + +i.flag.gh:before, +i.flag.ghana:before { + background-position: -36px -130px; +} + +i.flag.gi:before, +i.flag.gibraltar:before { + background-position: -36px -156px; +} + +i.flag.gl:before, +i.flag.greenland:before { + background-position: -36px -182px; +} + +i.flag.gm:before, +i.flag.gambia:before { + background-position: -36px -208px; +} + +i.flag.gn:before, +i.flag.guinea:before { + background-position: -36px -234px; +} + +i.flag.gp:before, +i.flag.guadeloupe:before { + background-position: -36px -260px; +} + +i.flag.gq:before, +i.flag.equatorial.guinea:before { + background-position: -36px -286px; +} + +i.flag.gr:before, +i.flag.greece:before { + background-position: -36px -312px; +} + +i.flag.gs:before, +i.flag.sandwich.islands:before { + background-position: -36px -338px; +} + +i.flag.gt:before, +i.flag.guatemala:before { + background-position: -36px -364px; +} + +i.flag.gu:before, +i.flag.guam:before { + background-position: -36px -390px; +} + +i.flag.gw:before, +i.flag.guinea-bissau:before { + background-position: -36px -416px; +} + +i.flag.gy:before, +i.flag.guyana:before { + background-position: -36px -442px; +} + +i.flag.hk:before, +i.flag.hong.kong:before { + background-position: -36px -468px; +} + +i.flag.hm:before, +i.flag.heard.island:before { + background-position: -36px -494px; +} + +i.flag.hn:before, +i.flag.honduras:before { + background-position: -36px -520px; +} + +i.flag.hr:before, +i.flag.croatia:before { + background-position: -36px -546px; +} + +i.flag.ht:before, +i.flag.haiti:before { + background-position: -36px -572px; +} + +i.flag.hu:before, +i.flag.hungary:before { + background-position: -36px -598px; +} + +i.flag.id:before, +i.flag.indonesia:before { + background-position: -36px -624px; +} + +i.flag.ie:before, +i.flag.ireland:before { + background-position: -36px -650px; +} + +i.flag.il:before, +i.flag.israel:before { + background-position: -36px -676px; +} + +i.flag.in:before, +i.flag.india:before { + background-position: -36px -702px; +} + +i.flag.io:before, +i.flag.indian.ocean.territory:before { + background-position: -36px -728px; +} + +i.flag.iq:before, +i.flag.iraq:before { + background-position: -36px -754px; +} + +i.flag.ir:before, +i.flag.iran:before { + background-position: -36px -780px; +} + +i.flag.is:before, +i.flag.iceland:before { + background-position: -36px -806px; +} + +i.flag.it:before, +i.flag.italy:before { + background-position: -36px -832px; +} + +i.flag.jm:before, +i.flag.jamaica:before { + background-position: -36px -858px; +} + +i.flag.jo:before, +i.flag.jordan:before { + background-position: -36px -884px; +} + +i.flag.jp:before, +i.flag.japan:before { + background-position: -36px -910px; +} + +i.flag.ke:before, +i.flag.kenya:before { + background-position: -36px -936px; +} + +i.flag.kg:before, +i.flag.kyrgyzstan:before { + background-position: -36px -962px; +} + +i.flag.kh:before, +i.flag.cambodia:before { + background-position: -36px -988px; +} + +i.flag.ki:before, +i.flag.kiribati:before { + background-position: -36px -1014px; +} + +i.flag.km:before, +i.flag.comoros:before { + background-position: -36px -1040px; +} + +i.flag.kn:before, +i.flag.saint.kitts.and.nevis:before { + background-position: -36px -1066px; +} + +i.flag.kp:before, +i.flag.north.korea:before { + background-position: -36px -1092px; +} + +i.flag.kr:before, +i.flag.south.korea:before { + background-position: -36px -1118px; +} + +i.flag.kw:before, +i.flag.kuwait:before { + background-position: -36px -1144px; +} + +i.flag.ky:before, +i.flag.cayman.islands:before { + background-position: -36px -1170px; +} + +i.flag.kz:before, +i.flag.kazakhstan:before { + background-position: -36px -1196px; +} + +i.flag.la:before, +i.flag.laos:before { + background-position: -36px -1222px; +} + +i.flag.lb:before, +i.flag.lebanon:before { + background-position: -36px -1248px; +} + +i.flag.lc:before, +i.flag.saint.lucia:before { + background-position: -36px -1274px; +} + +i.flag.li:before, +i.flag.liechtenstein:before { + background-position: -36px -1300px; +} + +i.flag.lk:before, +i.flag.sri.lanka:before { + background-position: -36px -1326px; +} + +i.flag.lr:before, +i.flag.liberia:before { + background-position: -36px -1352px; +} + +i.flag.ls:before, +i.flag.lesotho:before { + background-position: -36px -1378px; +} + +i.flag.lt:before, +i.flag.lithuania:before { + background-position: -36px -1404px; +} + +i.flag.lu:before, +i.flag.luxembourg:before { + background-position: -36px -1430px; +} + +i.flag.lv:before, +i.flag.latvia:before { + background-position: -36px -1456px; +} + +i.flag.ly:before, +i.flag.libya:before { + background-position: -36px -1482px; +} + +i.flag.ma:before, +i.flag.morocco:before { + background-position: -36px -1508px; +} + +i.flag.mc:before, +i.flag.monaco:before { + background-position: -36px -1534px; +} + +i.flag.md:before, +i.flag.moldova:before { + background-position: -36px -1560px; +} + +i.flag.me:before, +i.flag.montenegro:before { + background-position: -36px -1586px; +} + +i.flag.mg:before, +i.flag.madagascar:before { + background-position: -36px -1613px; +} + +i.flag.mh:before, +i.flag.marshall.islands:before { + background-position: -36px -1639px; +} + +i.flag.mk:before, +i.flag.macedonia:before { + background-position: -36px -1665px; +} + +i.flag.ml:before, +i.flag.mali:before { + background-position: -36px -1691px; +} + +i.flag.mm:before, +i.flag.myanmar:before, +i.flag.burma:before { + background-position: -73px -1821px; +} + +i.flag.mn:before, +i.flag.mongolia:before { + background-position: -36px -1743px; +} + +i.flag.mo:before, +i.flag.macau:before { + background-position: -36px -1769px; +} + +i.flag.mp:before, +i.flag.northern.mariana.islands:before { + background-position: -36px -1795px; +} + +i.flag.mq:before, +i.flag.martinique:before { + background-position: -36px -1821px; +} + +i.flag.mr:before, +i.flag.mauritania:before { + background-position: -36px -1847px; +} + +i.flag.ms:before, +i.flag.montserrat:before { + background-position: -36px -1873px; +} + +i.flag.mt:before, +i.flag.malta:before { + background-position: -36px -1899px; +} + +i.flag.mu:before, +i.flag.mauritius:before { + background-position: -36px -1925px; +} + +i.flag.mv:before, +i.flag.maldives:before { + background-position: -36px -1951px; +} + +i.flag.mw:before, +i.flag.malawi:before { + background-position: -36px -1977px; +} + +i.flag.mx:before, +i.flag.mexico:before { + background-position: -72px 0px; +} + +i.flag.my:before, +i.flag.malaysia:before { + background-position: -72px -26px; +} + +i.flag.mz:before, +i.flag.mozambique:before { + background-position: -72px -52px; +} + +i.flag.na:before, +i.flag.namibia:before { + background-position: -72px -78px; +} + +i.flag.nc:before, +i.flag.new.caledonia:before { + background-position: -72px -104px; +} + +i.flag.ne:before, +i.flag.niger:before { + background-position: -72px -130px; +} + +i.flag.nf:before, +i.flag.norfolk.island:before { + background-position: -72px -156px; +} + +i.flag.ng:before, +i.flag.nigeria:before { + background-position: -72px -182px; +} + +i.flag.ni:before, +i.flag.nicaragua:before { + background-position: -72px -208px; +} + +i.flag.nl:before, +i.flag.netherlands:before { + background-position: -72px -234px; +} + +i.flag.no:before, +i.flag.norway:before { + background-position: -72px -260px; +} + +i.flag.np:before, +i.flag.nepal:before { + background-position: -72px -286px; +} + +i.flag.nr:before, +i.flag.nauru:before { + background-position: -72px -312px; +} + +i.flag.nu:before, +i.flag.niue:before { + background-position: -72px -338px; +} + +i.flag.nz:before, +i.flag.new.zealand:before { + background-position: -72px -364px; +} + +i.flag.om:before, +i.flag.oman:before { + background-position: -72px -390px; +} + +i.flag.pa:before, +i.flag.panama:before { + background-position: -72px -416px; +} + +i.flag.pe:before, +i.flag.peru:before { + background-position: -72px -442px; +} + +i.flag.pf:before, +i.flag.french.polynesia:before { + background-position: -72px -468px; +} + +i.flag.pg:before, +i.flag.new.guinea:before { + background-position: -72px -494px; +} + +i.flag.ph:before, +i.flag.philippines:before { + background-position: -72px -520px; +} + +i.flag.pk:before, +i.flag.pakistan:before { + background-position: -72px -546px; +} + +i.flag.pl:before, +i.flag.poland:before { + background-position: -72px -572px; +} + +i.flag.pm:before, +i.flag.saint.pierre:before { + background-position: -72px -598px; +} + +i.flag.pn:before, +i.flag.pitcairn.islands:before { + background-position: -72px -624px; +} + +i.flag.pr:before, +i.flag.puerto.rico:before { + background-position: -72px -650px; +} + +i.flag.ps:before, +i.flag.palestine:before { + background-position: -72px -676px; +} + +i.flag.pt:before, +i.flag.portugal:before { + background-position: -72px -702px; +} + +i.flag.pw:before, +i.flag.palau:before { + background-position: -72px -728px; +} + +i.flag.py:before, +i.flag.paraguay:before { + background-position: -72px -754px; +} + +i.flag.qa:before, +i.flag.qatar:before { + background-position: -72px -780px; +} + +i.flag.re:before, +i.flag.reunion:before { + background-position: -72px -806px; +} + +i.flag.ro:before, +i.flag.romania:before { + background-position: -72px -832px; +} + +i.flag.rs:before, +i.flag.serbia:before { + background-position: -72px -858px; +} + +i.flag.ru:before, +i.flag.russia:before { + background-position: -72px -884px; +} + +i.flag.rw:before, +i.flag.rwanda:before { + background-position: -72px -910px; +} + +i.flag.sa:before, +i.flag.saudi.arabia:before { + background-position: -72px -936px; +} + +i.flag.sb:before, +i.flag.solomon.islands:before { + background-position: -72px -962px; +} + +i.flag.sc:before, +i.flag.seychelles:before { + background-position: -72px -988px; +} + +i.flag.gb.sct:before, +i.flag.scotland:before { + background-position: -72px -1014px; +} + +i.flag.sd:before, +i.flag.sudan:before { + background-position: -72px -1040px; +} + +i.flag.se:before, +i.flag.sweden:before { + background-position: -72px -1066px; +} + +i.flag.sg:before, +i.flag.singapore:before { + background-position: -72px -1092px; +} + +i.flag.sh:before, +i.flag.saint.helena:before { + background-position: -72px -1118px; +} + +i.flag.si:before, +i.flag.slovenia:before { + background-position: -72px -1144px; +} + +i.flag.sj:before, +i.flag.svalbard:before, +i.flag.jan.mayen:before { + background-position: -72px -1170px; +} + +i.flag.sk:before, +i.flag.slovakia:before { + background-position: -72px -1196px; +} + +i.flag.sl:before, +i.flag.sierra.leone:before { + background-position: -72px -1222px; +} + +i.flag.sm:before, +i.flag.san.marino:before { + background-position: -72px -1248px; +} + +i.flag.sn:before, +i.flag.senegal:before { + background-position: -72px -1274px; +} + +i.flag.so:before, +i.flag.somalia:before { + background-position: -72px -1300px; +} + +i.flag.sr:before, +i.flag.suriname:before { + background-position: -72px -1326px; +} + +i.flag.st:before, +i.flag.sao.tome:before { + background-position: -72px -1352px; +} + +i.flag.sv:before, +i.flag.el.salvador:before { + background-position: -72px -1378px; +} + +i.flag.sy:before, +i.flag.syria:before { + background-position: -72px -1404px; +} + +i.flag.sz:before, +i.flag.swaziland:before { + background-position: -72px -1430px; +} + +i.flag.tc:before, +i.flag.caicos.islands:before { + background-position: -72px -1456px; +} + +i.flag.td:before, +i.flag.chad:before { + background-position: -72px -1482px; +} + +i.flag.tf:before, +i.flag.french.territories:before { + background-position: -72px -1508px; +} + +i.flag.tg:before, +i.flag.togo:before { + background-position: -72px -1534px; +} + +i.flag.th:before, +i.flag.thailand:before { + background-position: -72px -1560px; +} + +i.flag.tj:before, +i.flag.tajikistan:before { + background-position: -72px -1586px; +} + +i.flag.tk:before, +i.flag.tokelau:before { + background-position: -72px -1612px; +} + +i.flag.tl:before, +i.flag.timorleste:before { + background-position: -72px -1638px; +} + +i.flag.tm:before, +i.flag.turkmenistan:before { + background-position: -72px -1664px; +} + +i.flag.tn:before, +i.flag.tunisia:before { + background-position: -72px -1690px; +} + +i.flag.to:before, +i.flag.tonga:before { + background-position: -72px -1716px; +} + +i.flag.tr:before, +i.flag.turkey:before { + background-position: -72px -1742px; +} + +i.flag.tt:before, +i.flag.trinidad:before { + background-position: -72px -1768px; +} + +i.flag.tv:before, +i.flag.tuvalu:before { + background-position: -72px -1794px; +} + +i.flag.tw:before, +i.flag.taiwan:before { + background-position: -72px -1820px; +} + +i.flag.tz:before, +i.flag.tanzania:before { + background-position: -72px -1846px; +} + +i.flag.ua:before, +i.flag.ukraine:before { + background-position: -72px -1872px; +} + +i.flag.ug:before, +i.flag.uganda:before { + background-position: -72px -1898px; +} + +i.flag.um:before, +i.flag.us.minor.islands:before { + background-position: -72px -1924px; +} + +i.flag.us:before, +i.flag.america:before, +i.flag.united.states:before { + background-position: -72px -1950px; +} + +i.flag.uy:before, +i.flag.uruguay:before { + background-position: -72px -1976px; +} + +i.flag.uz:before, +i.flag.uzbekistan:before { + background-position: -108px 0px; +} + +i.flag.va:before, +i.flag.vatican.city:before { + background-position: -108px -26px; +} + +i.flag.vc:before, +i.flag.saint.vincent:before { + background-position: -108px -52px; +} + +i.flag.ve:before, +i.flag.venezuela:before { + background-position: -108px -78px; +} + +i.flag.vg:before, +i.flag.british.virgin.islands:before { + background-position: -108px -104px; +} + +i.flag.vi:before, +i.flag.us.virgin.islands:before { + background-position: -108px -130px; +} + +i.flag.vn:before, +i.flag.vietnam:before { + background-position: -108px -156px; +} + +i.flag.vu:before, +i.flag.vanuatu:before { + background-position: -108px -182px; +} + +i.flag.gb.wls:before, +i.flag.wales:before { + background-position: -108px -208px; +} + +i.flag.wf:before, +i.flag.wallis.and.futuna:before { + background-position: -108px -234px; +} + +i.flag.ws:before, +i.flag.samoa:before { + background-position: -108px -260px; +} + +i.flag.ye:before, +i.flag.yemen:before { + background-position: -108px -286px; +} + +i.flag.yt:before, +i.flag.mayotte:before { + background-position: -108px -312px; +} + +i.flag.za:before, +i.flag.south.africa:before { + background-position: -108px -338px; +} + +i.flag.zm:before, +i.flag.zambia:before { + background-position: -108px -364px; +} + +i.flag.zw:before, +i.flag.zimbabwe:before { + background-position: -108px -390px; +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Header + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Header +*******************************/ + +/* Standard */ + +.ui.header { + border: none; + margin: calc(2rem - 0.14285714em ) 0em 1rem; + padding: 0em 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-weight: bold; + line-height: 1.28571429em; + text-transform: none; + color: rgba(0, 0, 0, 0.87); +} + +.ui.header:first-child { + margin-top: -0.14285714em; +} + +.ui.header:last-child { + margin-bottom: 0em; +} + +/*-------------- + Sub Header +---------------*/ + +.ui.header .sub.header { + display: block; + font-weight: normal; + padding: 0em; + margin: 0em; + font-size: 1rem; + line-height: 1.2em; + color: rgba(0, 0, 0, 0.6); +} + +/*-------------- + Icon +---------------*/ + +.ui.header > .icon { + display: table-cell; + opacity: 1; + font-size: 1.5em; + padding-top: 0.14285714em; + vertical-align: middle; +} + +/* With Text Node */ + +.ui.header .icon:only-child { + display: inline-block; + padding: 0em; + margin-right: 0.75rem; +} + +/*------------------- + Image +--------------------*/ + +.ui.header > .image:not(.icon), +.ui.header > img { + display: inline-block; + margin-top: 0.14285714em; + width: 2.5em; + height: auto; + vertical-align: middle; +} + +.ui.header > .image:not(.icon):only-child, +.ui.header > img:only-child { + margin-right: 0.75rem; +} + +/*-------------- + Content +---------------*/ + +.ui.header .content { + display: inline-block; + vertical-align: top; +} + +/* After Image */ + +.ui.header > img + .content, +.ui.header > .image + .content { + padding-left: 0.75rem; + vertical-align: middle; +} + +/* After Icon */ + +.ui.header > .icon + .content { + padding-left: 0.75rem; + display: table-cell; + vertical-align: middle; +} + +/*-------------- + Loose Coupling +---------------*/ + +.ui.header .ui.label { + font-size: ''; + margin-left: 0.5rem; + vertical-align: middle; +} + +/* Positioning */ + +.ui.header + p { + margin-top: 0em; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Page +---------------*/ + +h1.ui.header { + font-size: 2rem; +} + +h2.ui.header { + font-size: 1.71428571rem; +} + +h3.ui.header { + font-size: 1.28571429rem; +} + +h4.ui.header { + font-size: 1.07142857rem; +} + +h5.ui.header { + font-size: 1rem; +} + +/* Sub Header */ + +h1.ui.header .sub.header { + font-size: 1.14285714rem; +} + +h2.ui.header .sub.header { + font-size: 1.14285714rem; +} + +h3.ui.header .sub.header { + font-size: 1rem; +} + +h4.ui.header .sub.header { + font-size: 1rem; +} + +h5.ui.header .sub.header { + font-size: 0.92857143rem; +} + +/*-------------- + Content Heading +---------------*/ + +.ui.huge.header { + min-height: 1em; + font-size: 2em; +} + +.ui.large.header { + font-size: 1.71428571em; +} + +.ui.medium.header { + font-size: 1.28571429em; +} + +.ui.small.header { + font-size: 1.07142857em; +} + +.ui.tiny.header { + font-size: 1em; +} + +/* Sub Header */ + +.ui.huge.header .sub.header { + font-size: 1.14285714rem; +} + +.ui.large.header .sub.header { + font-size: 1.14285714rem; +} + +.ui.header .sub.header { + font-size: 1rem; +} + +.ui.small.header .sub.header { + font-size: 1rem; +} + +.ui.tiny.header .sub.header { + font-size: 0.92857143rem; +} + +/*-------------- + Sub Heading +---------------*/ + +.ui.sub.header { + padding: 0em; + margin-bottom: 0.14285714rem; + font-weight: bold; + font-size: 0.85714286em; + text-transform: uppercase; + color: ''; +} + +.ui.small.sub.header { + font-size: 0.78571429em; +} + +.ui.sub.header { + font-size: 0.85714286em; +} + +.ui.large.sub.header { + font-size: 0.92857143em; +} + +.ui.huge.sub.header { + font-size: 1em; +} + +/*------------------- + Icon +--------------------*/ + +.ui.icon.header { + display: inline-block; + text-align: center; + margin: 2rem 0em 1rem; +} + +.ui.icon.header:after { + content: ''; + display: block; + height: 0px; + clear: both; + visibility: hidden; +} + +.ui.icon.header:first-child { + margin-top: 0em; +} + +.ui.icon.header .icon { + float: none; + display: block; + width: auto; + height: auto; + line-height: 1; + padding: 0em; + font-size: 3em; + margin: 0em auto 0.5rem; + opacity: 1; +} + +.ui.icon.header .content { + display: block; + padding: 0em; +} + +.ui.icon.header .circular.icon { + font-size: 2em; +} + +.ui.icon.header .square.icon { + font-size: 2em; +} + +.ui.block.icon.header .icon { + margin-bottom: 0em; +} + +.ui.icon.header.aligned { + margin-left: auto; + margin-right: auto; + display: block; +} + +/******************************* + States +*******************************/ + +.ui.disabled.header { + opacity: 0.45; +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Inverted +--------------------*/ + +.ui.inverted.header { + color: #FFFFFF; +} + +.ui.inverted.header .sub.header { + color: rgba(255, 255, 255, 0.8); +} + +.ui.inverted.attached.header { + background: #545454 -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + background: #545454 linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + box-shadow: none; + border-color: transparent; +} + +.ui.inverted.block.header { + background: #545454 -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + background: #545454 linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + box-shadow: none; +} + +.ui.inverted.block.header { + border-bottom: none; +} + +/*------------------- + Colors +--------------------*/ + +/*--- Red ---*/ + +.ui.red.header { + color: #DB2828 !important; +} + +a.ui.red.header:hover { + color: #d01919 !important; +} + +.ui.red.dividing.header { + border-bottom: 2px solid #DB2828; +} + +/* Inverted */ + +.ui.inverted.red.header { + color: #FF695E !important; +} + +a.ui.inverted.red.header:hover { + color: #ff5144 !important; +} + +/*--- Orange ---*/ + +.ui.orange.header { + color: #F2711C !important; +} + +a.ui.orange.header:hover { + color: #f26202 !important; +} + +.ui.orange.dividing.header { + border-bottom: 2px solid #F2711C; +} + +/* Inverted */ + +.ui.inverted.orange.header { + color: #FF851B !important; +} + +a.ui.inverted.orange.header:hover { + color: #ff7701 !important; +} + +/*--- Olive ---*/ + +.ui.olive.header { + color: #B5CC18 !important; +} + +a.ui.olive.header:hover { + color: #a7bd0d !important; +} + +.ui.olive.dividing.header { + border-bottom: 2px solid #B5CC18; +} + +/* Inverted */ + +.ui.inverted.olive.header { + color: #D9E778 !important; +} + +a.ui.inverted.olive.header:hover { + color: #d8ea5c !important; +} + +/*--- Yellow ---*/ + +.ui.yellow.header { + color: #FBBD08 !important; +} + +a.ui.yellow.header:hover { + color: #eaae00 !important; +} + +.ui.yellow.dividing.header { + border-bottom: 2px solid #FBBD08; +} + +/* Inverted */ + +.ui.inverted.yellow.header { + color: #FFE21F !important; +} + +a.ui.inverted.yellow.header:hover { + color: #ffdf05 !important; +} + +/*--- Green ---*/ + +.ui.green.header { + color: #21BA45 !important; +} + +a.ui.green.header:hover { + color: #16ab39 !important; +} + +.ui.green.dividing.header { + border-bottom: 2px solid #21BA45; +} + +/* Inverted */ + +.ui.inverted.green.header { + color: #2ECC40 !important; +} + +a.ui.inverted.green.header:hover { + color: #22be34 !important; +} + +/*--- Teal ---*/ + +.ui.teal.header { + color: #00B5AD !important; +} + +a.ui.teal.header:hover { + color: #009c95 !important; +} + +.ui.teal.dividing.header { + border-bottom: 2px solid #00B5AD; +} + +/* Inverted */ + +.ui.inverted.teal.header { + color: #6DFFFF !important; +} + +a.ui.inverted.teal.header:hover { + color: #54ffff !important; +} + +/*--- Blue ---*/ + +.ui.blue.header { + color: #2185D0 !important; +} + +a.ui.blue.header:hover { + color: #1678c2 !important; +} + +.ui.blue.dividing.header { + border-bottom: 2px solid #2185D0; +} + +/* Inverted */ + +.ui.inverted.blue.header { + color: #54C8FF !important; +} + +a.ui.inverted.blue.header:hover { + color: #3ac0ff !important; +} + +/*--- Violet ---*/ + +.ui.violet.header { + color: #6435C9 !important; +} + +a.ui.violet.header:hover { + color: #5829bb !important; +} + +.ui.violet.dividing.header { + border-bottom: 2px solid #6435C9; +} + +/* Inverted */ + +.ui.inverted.violet.header { + color: #A291FB !important; +} + +a.ui.inverted.violet.header:hover { + color: #8a73ff !important; +} + +/*--- Purple ---*/ + +.ui.purple.header { + color: #A333C8 !important; +} + +a.ui.purple.header:hover { + color: #9627ba !important; +} + +.ui.purple.dividing.header { + border-bottom: 2px solid #A333C8; +} + +/* Inverted */ + +.ui.inverted.purple.header { + color: #DC73FF !important; +} + +a.ui.inverted.purple.header:hover { + color: #d65aff !important; +} + +/*--- Pink ---*/ + +.ui.pink.header { + color: #E03997 !important; +} + +a.ui.pink.header:hover { + color: #e61a8d !important; +} + +.ui.pink.dividing.header { + border-bottom: 2px solid #E03997; +} + +/* Inverted */ + +.ui.inverted.pink.header { + color: #FF8EDF !important; +} + +a.ui.inverted.pink.header:hover { + color: #ff74d8 !important; +} + +/*--- Brown ---*/ + +.ui.brown.header { + color: #A5673F !important; +} + +a.ui.brown.header:hover { + color: #975b33 !important; +} + +.ui.brown.dividing.header { + border-bottom: 2px solid #A5673F; +} + +/* Inverted */ + +.ui.inverted.brown.header { + color: #D67C1C !important; +} + +a.ui.inverted.brown.header:hover { + color: #c86f11 !important; +} + +/*--- Grey ---*/ + +.ui.grey.header { + color: #767676 !important; +} + +a.ui.grey.header:hover { + color: #838383 !important; +} + +.ui.grey.dividing.header { + border-bottom: 2px solid #767676; +} + +/* Inverted */ + +.ui.inverted.grey.header { + color: #DCDDDE !important; +} + +a.ui.inverted.grey.header:hover { + color: #cfd0d2 !important; +} + +/*------------------- + Aligned +--------------------*/ + +.ui.left.aligned.header { + text-align: left; +} + +.ui.right.aligned.header { + text-align: right; +} + +.ui.centered.header, +.ui.center.aligned.header { + text-align: center; +} + +.ui.justified.header { + text-align: justify; +} + +.ui.justified.header:after { + display: inline-block; + content: ''; + width: 100%; +} + +/*------------------- + Floated +--------------------*/ + +.ui.floated.header, +.ui[class*="left floated"].header { + float: left; + margin-top: 0em; + margin-right: 0.5em; +} + +.ui[class*="right floated"].header { + float: right; + margin-top: 0em; + margin-left: 0.5em; +} + +/*------------------- + Fitted +--------------------*/ + +.ui.fitted.header { + padding: 0em; +} + +/*------------------- + Dividing +--------------------*/ + +.ui.dividing.header { + padding-bottom: 0.21428571rem; + border-bottom: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.dividing.header .sub.header { + padding-bottom: 0.21428571rem; +} + +.ui.dividing.header .icon { + margin-bottom: 0em; +} + +.ui.inverted.dividing.header { + border-bottom-color: rgba(255, 255, 255, 0.1); +} + +/*------------------- + Block +--------------------*/ + +.ui.block.header { + background: #F3F4F5; + padding: 0.78571429rem 1rem; + box-shadow: none; + border: 1px solid #D4D4D5; + border-radius: 0.28571429rem; +} + +.ui.tiny.block.header { + font-size: 0.85714286rem; +} + +.ui.small.block.header { + font-size: 0.92857143rem; +} + +.ui.block.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { + font-size: 1rem; +} + +.ui.large.block.header { + font-size: 1.14285714rem; +} + +.ui.huge.block.header { + font-size: 1.42857143rem; +} + +/*------------------- + Attached +--------------------*/ + +.ui.attached.header { + background: #FFFFFF; + padding: 0.78571429rem 1rem; + margin-left: -1px; + margin-right: -1px; + box-shadow: none; + border: 1px solid #D4D4D5; +} + +.ui.attached.block.header { + background: #F3F4F5; +} + +.ui.attached:not(.top):not(.bottom).header { + margin-top: 0em; + margin-bottom: 0em; + border-top: none; + border-radius: 0em; +} + +.ui.top.attached.header { + margin-bottom: 0em; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.bottom.attached.header { + margin-top: 0em; + border-top: none; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +/* Attached Sizes */ + +.ui.tiny.attached.header { + font-size: 0.85714286em; +} + +.ui.small.attached.header { + font-size: 0.92857143em; +} + +.ui.attached.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { + font-size: 1em; +} + +.ui.large.attached.header { + font-size: 1.14285714em; +} + +.ui.huge.attached.header { + font-size: 1.42857143em; +} + +/*------------------- + Sizing +--------------------*/ + +.ui.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { + font-size: 1.28571429em; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Icon + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Icon +*******************************/ + +@font-face { + font-family: 'Icons'; + src: url("./themes/default/assets/fonts/icons.eot"); + src: url("./themes/default/assets/fonts/icons.eot?#iefix") format('embedded-opentype'), url("./themes/default/assets/fonts/icons.woff2") format('woff2'), url("./themes/default/assets/fonts/icons.woff") format('woff'), url("./themes/default/assets/fonts/icons.ttf") format('truetype'), url("./themes/default/assets/fonts/icons.svg#icons") format('svg'); + font-style: normal; + font-weight: normal; + font-variant: normal; + text-decoration: inherit; + text-transform: none; +} + +i.icon { + display: inline-block; + opacity: 1; + margin: 0em 0.25rem 0em 0em; + width: 1.18em; + height: 1em; + font-family: 'Icons'; + font-style: normal; + font-weight: normal; + text-decoration: inherit; + text-align: center; + speak: none; + font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} + +i.icon:before { + background: none !important; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Loading +---------------*/ + +i.icon.loading { + height: 1em; + line-height: 1; + -webkit-animation: icon-loading 2s linear infinite; + animation: icon-loading 2s linear infinite; +} + +@-webkit-keyframes icon-loading { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes icon-loading { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/******************************* + States +*******************************/ + +i.icon.hover { + opacity: 1 !important; +} + +i.icon.active { + opacity: 1 !important; +} + +i.emphasized.icon { + opacity: 1 !important; +} + +i.disabled.icon { + opacity: 0.45 !important; +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Fitted +--------------------*/ + +i.fitted.icon { + width: auto; + margin: 0em; +} + +/*------------------- + Link +--------------------*/ + +i.link.icon, +i.link.icons { + cursor: pointer; + opacity: 0.8; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; +} + +i.link.icon:hover, +i.link.icons:hover { + opacity: 1 !important; +} + +/*------------------- + Circular +--------------------*/ + +i.circular.icon { + border-radius: 500em !important; + line-height: 1 !important; + padding: 0.5em 0.5em !important; + box-shadow: 0em 0em 0em 0.1em rgba(0, 0, 0, 0.1) inset; + width: 2em !important; + height: 2em !important; +} + +i.circular.inverted.icon { + border: none; + box-shadow: none; +} + +/*------------------- + Flipped +--------------------*/ + +i.flipped.icon, +i.horizontally.flipped.icon { + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); +} + +i.vertically.flipped.icon { + -webkit-transform: scale(1, -1); + transform: scale(1, -1); +} + +/*------------------- + Rotated +--------------------*/ + +i.rotated.icon, +i.right.rotated.icon, +i.clockwise.rotated.icon { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} + +i.left.rotated.icon, +i.counterclockwise.rotated.icon { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); +} + +/*------------------- + Bordered +--------------------*/ + +i.bordered.icon { + line-height: 1; + vertical-align: baseline; + width: 2em; + height: 2em; + padding: 0.5em 0.41em !important; + box-shadow: 0em 0em 0em 0.1em rgba(0, 0, 0, 0.1) inset; +} + +i.bordered.inverted.icon { + border: none; + box-shadow: none; +} + +/*------------------- + Inverted +--------------------*/ + +/* Inverted Shapes */ + +i.inverted.bordered.icon, +i.inverted.circular.icon { + background-color: #1B1C1D !important; + color: #FFFFFF !important; +} + +i.inverted.icon { + color: #FFFFFF; +} + +/*------------------- + Colors +--------------------*/ + +/* Red */ + +i.red.icon { + color: #DB2828 !important; +} + +i.inverted.red.icon { + color: #FF695E !important; +} + +i.inverted.bordered.red.icon, +i.inverted.circular.red.icon { + background-color: #DB2828 !important; + color: #FFFFFF !important; +} + +/* Orange */ + +i.orange.icon { + color: #F2711C !important; +} + +i.inverted.orange.icon { + color: #FF851B !important; +} + +i.inverted.bordered.orange.icon, +i.inverted.circular.orange.icon { + background-color: #F2711C !important; + color: #FFFFFF !important; +} + +/* Yellow */ + +i.yellow.icon { + color: #FBBD08 !important; +} + +i.inverted.yellow.icon { + color: #FFE21F !important; +} + +i.inverted.bordered.yellow.icon, +i.inverted.circular.yellow.icon { + background-color: #FBBD08 !important; + color: #FFFFFF !important; +} + +/* Olive */ + +i.olive.icon { + color: #B5CC18 !important; +} + +i.inverted.olive.icon { + color: #D9E778 !important; +} + +i.inverted.bordered.olive.icon, +i.inverted.circular.olive.icon { + background-color: #B5CC18 !important; + color: #FFFFFF !important; +} + +/* Green */ + +i.green.icon { + color: #21BA45 !important; +} + +i.inverted.green.icon { + color: #2ECC40 !important; +} + +i.inverted.bordered.green.icon, +i.inverted.circular.green.icon { + background-color: #21BA45 !important; + color: #FFFFFF !important; +} + +/* Teal */ + +i.teal.icon { + color: #00B5AD !important; +} + +i.inverted.teal.icon { + color: #6DFFFF !important; +} + +i.inverted.bordered.teal.icon, +i.inverted.circular.teal.icon { + background-color: #00B5AD !important; + color: #FFFFFF !important; +} + +/* Blue */ + +i.blue.icon { + color: #2185D0 !important; +} + +i.inverted.blue.icon { + color: #54C8FF !important; +} + +i.inverted.bordered.blue.icon, +i.inverted.circular.blue.icon { + background-color: #2185D0 !important; + color: #FFFFFF !important; +} + +/* Violet */ + +i.violet.icon { + color: #6435C9 !important; +} + +i.inverted.violet.icon { + color: #A291FB !important; +} + +i.inverted.bordered.violet.icon, +i.inverted.circular.violet.icon { + background-color: #6435C9 !important; + color: #FFFFFF !important; +} + +/* Purple */ + +i.purple.icon { + color: #A333C8 !important; +} + +i.inverted.purple.icon { + color: #DC73FF !important; +} + +i.inverted.bordered.purple.icon, +i.inverted.circular.purple.icon { + background-color: #A333C8 !important; + color: #FFFFFF !important; +} + +/* Pink */ + +i.pink.icon { + color: #E03997 !important; +} + +i.inverted.pink.icon { + color: #FF8EDF !important; +} + +i.inverted.bordered.pink.icon, +i.inverted.circular.pink.icon { + background-color: #E03997 !important; + color: #FFFFFF !important; +} + +/* Brown */ + +i.brown.icon { + color: #A5673F !important; +} + +i.inverted.brown.icon { + color: #D67C1C !important; +} + +i.inverted.bordered.brown.icon, +i.inverted.circular.brown.icon { + background-color: #A5673F !important; + color: #FFFFFF !important; +} + +/* Grey */ + +i.grey.icon { + color: #767676 !important; +} + +i.inverted.grey.icon { + color: #DCDDDE !important; +} + +i.inverted.bordered.grey.icon, +i.inverted.circular.grey.icon { + background-color: #767676 !important; + color: #FFFFFF !important; +} + +/* Black */ + +i.black.icon { + color: #1B1C1D !important; +} + +i.inverted.black.icon { + color: #545454 !important; +} + +i.inverted.bordered.black.icon, +i.inverted.circular.black.icon { + background-color: #1B1C1D !important; + color: #FFFFFF !important; +} + +/*------------------- + Sizes +--------------------*/ + +i.mini.icon, +i.mini.icons { + line-height: 1; + font-size: 0.4em; +} + +i.tiny.icon, +i.tiny.icons { + line-height: 1; + font-size: 0.5em; +} + +i.small.icon, +i.small.icons { + line-height: 1; + font-size: 0.75em; +} + +i.icon, +i.icons { + font-size: 1em; +} + +i.large.icon, +i.large.icons { + line-height: 1; + vertical-align: middle; + font-size: 1.5em; +} + +i.big.icon, +i.big.icons { + line-height: 1; + vertical-align: middle; + font-size: 2em; +} + +i.huge.icon, +i.huge.icons { + line-height: 1; + vertical-align: middle; + font-size: 4em; +} + +i.massive.icon, +i.massive.icons { + line-height: 1; + vertical-align: middle; + font-size: 8em; +} + +/******************************* + Groups +*******************************/ + +i.icons { + display: inline-block; + position: relative; + line-height: 1; +} + +i.icons .icon { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + margin: 0em; + margin: 0; +} + +i.icons .icon:first-child { + position: static; + width: auto; + height: auto; + vertical-align: top; + -webkit-transform: none; + transform: none; + margin-right: 0.25rem; +} + +/* Corner Icon */ + +i.icons .corner.icon { + top: auto; + left: auto; + right: 0; + bottom: 0; + -webkit-transform: none; + transform: none; + font-size: 0.45em; + text-shadow: -1px -1px 0 #FFFFFF, 1px -1px 0 #FFFFFF, -1px 1px 0 #FFFFFF, 1px 1px 0 #FFFFFF; +} + +i.icons .inverted.corner.icon { + text-shadow: -1px -1px 0 #1B1C1D, 1px -1px 0 #1B1C1D, -1px 1px 0 #1B1C1D, 1px 1px 0 #1B1C1D; +} + +/* + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +/******************************* + +Semantic-UI integration of font-awesome : + +///class names are separated +i.icon.circle => i.icon.circle +i.icon.circle-o => i.icon.circle.outline + +//abbreviation are replaced by full letters: +i.icon.ellipsis-h => i.icon.ellipsis.horizontal +i.icon.ellipsis-v => i.icon.ellipsis.vertical +.alpha => .i.icon.alphabet +.asc => .i.icon.ascending +.desc => .i.icon.descending +.alt =>.alternate + +ASCII order is conserved for easier maintenance. + +Icons that only have one style 'outline', 'square' etc do not require this class +for instance `lemon icon` not `lemon outline icon` since there is only one lemon + +*******************************/ + +/******************************* + Icons +*******************************/ + +/* Web Content */ + +i.icon.search:before { + content: "\f002"; +} + +i.icon.mail.outline:before { + content: "\f003"; +} + +i.icon.signal:before { + content: "\f012"; +} + +i.icon.setting:before { + content: "\f013"; +} + +i.icon.home:before { + content: "\f015"; +} + +i.icon.inbox:before { + content: "\f01c"; +} + +i.icon.browser:before { + content: "\f022"; +} + +i.icon.tag:before { + content: "\f02b"; +} + +i.icon.tags:before { + content: "\f02c"; +} + +i.icon.image:before { + content: "\f03e"; +} + +i.icon.calendar:before { + content: "\f073"; +} + +i.icon.comment:before { + content: "\f075"; +} + +i.icon.shop:before { + content: "\f07a"; +} + +i.icon.comments:before { + content: "\f086"; +} + +i.icon.external:before { + content: "\f08e"; +} + +i.icon.privacy:before { + content: "\f084"; +} + +i.icon.settings:before { + content: "\f085"; +} + +i.icon.comments:before { + content: "\f086"; +} + +i.icon.external:before { + content: "\f08e"; +} + +i.icon.trophy:before { + content: "\f091"; +} + +i.icon.payment:before { + content: "\f09d"; +} + +i.icon.feed:before { + content: "\f09e"; +} + +i.icon.alarm.outline:before { + content: "\f0a2"; +} + +i.icon.tasks:before { + content: "\f0ae"; +} + +i.icon.cloud:before { + content: "\f0c2"; +} + +i.icon.lab:before { + content: "\f0c3"; +} + +i.icon.mail:before { + content: "\f0e0"; +} + +i.icon.dashboard:before { + content: "\f0e4"; +} + +i.icon.comment.outline:before { + content: "\f0e5"; +} + +i.icon.comments.outline:before { + content: "\f0e6"; +} + +i.icon.sitemap:before { + content: "\f0e8"; +} + +i.icon.idea:before { + content: "\f0eb"; +} + +i.icon.alarm:before { + content: "\f0f3"; +} + +i.icon.terminal:before { + content: "\f120"; +} + +i.icon.code:before { + content: "\f121"; +} + +i.icon.protect:before { + content: "\f132"; +} + +i.icon.calendar.outline:before { + content: "\f133"; +} + +i.icon.ticket:before { + content: "\f145"; +} + +i.icon.external.square:before { + content: "\f14c"; +} + +i.icon.bug:before { + content: "\f188"; +} + +i.icon.mail.square:before { + content: "\f199"; +} + +i.icon.history:before { + content: "\f1da"; +} + +i.icon.options:before { + content: "\f1de"; +} + +i.icon.text.telephone:before { + content: "\f1e4"; +} + +i.icon.find:before { + content: "\f1e5"; +} + +i.icon.alarm.mute:before { + content: "\f1f6"; +} + +i.icon.alarm.mute.outline:before { + content: "\f1f7"; +} + +i.icon.copyright:before { + content: "\f1f9"; +} + +i.icon.at:before { + content: "\f1fa"; +} + +i.icon.eyedropper:before { + content: "\f1fb"; +} + +i.icon.paint.brush:before { + content: "\f1fc"; +} + +i.icon.heartbeat:before { + content: "\f21e"; +} + +i.icon.mouse.pointer:before { + content: "\f245"; +} + +i.icon.hourglass.empty:before { + content: "\f250"; +} + +i.icon.hourglass.start:before { + content: "\f251"; +} + +i.icon.hourglass.half:before { + content: "\f252"; +} + +i.icon.hourglass.end:before { + content: "\f253"; +} + +i.icon.hourglass.full:before { + content: "\f254"; +} + +i.icon.hand.pointer:before { + content: "\f25a"; +} + +i.icon.trademark:before { + content: "\f25c"; +} + +i.icon.registered:before { + content: "\f25d"; +} + +i.icon.creative.commons:before { + content: "\f25e"; +} + +i.icon.add.to.calendar:before { + content: "\f271"; +} + +i.icon.remove.from.calendar:before { + content: "\f272"; +} + +i.icon.delete.calendar:before { + content: "\f273"; +} + +i.icon.checked.calendar:before { + content: "\f274"; +} + +i.icon.industry:before { + content: "\f275"; +} + +i.icon.shopping.bag:before { + content: "\f290"; +} + +i.icon.shopping.basket:before { + content: "\f291"; +} + +i.icon.hashtag:before { + content: "\f292"; +} + +i.icon.percent:before { + content: "\f295"; +} + +i.icon.handshake:before { + content: "\f2b5"; +} + +i.icon.open.envelope:before { + content: "\f2b6"; +} + +i.icon.open.envelope.outline:before { + content: "\f2b7"; +} + +i.icon.address.book:before { + content: "\f2b9"; +} + +i.icon.address.book.outline:before { + content: "\f2ba"; +} + +i.icon.address.card:before { + content: "\f2bb"; +} + +i.icon.address.card.outline:before { + content: "\f2bc"; +} + +i.icon.id.badge:before { + content: "\f2c1"; +} + +i.icon.id.card:before { + content: "\f2c2"; +} + +i.icon.id.card.outline:before { + content: "\f2c3"; +} + +i.icon.podcast:before { + content: "\f2ce"; +} + +i.icon.window.maximize:before { + content: "\f2d0"; +} + +i.icon.window.minimize:before { + content: "\f2d1"; +} + +i.icon.window.restore:before { + content: "\f2d2"; +} + +i.icon.window.close:before { + content: "\f2d3"; +} + +i.icon.window.close.outline:before { + content: "\f2d4"; +} + +/* User Actions */ + +i.icon.wait:before { + content: "\f017"; +} + +i.icon.download:before { + content: "\f019"; +} + +i.icon.repeat:before { + content: "\f01e"; +} + +i.icon.refresh:before { + content: "\f021"; +} + +i.icon.lock:before { + content: "\f023"; +} + +i.icon.bookmark:before { + content: "\f02e"; +} + +i.icon.print:before { + content: "\f02f"; +} + +i.icon.write:before { + content: "\f040"; +} + +i.icon.adjust:before { + content: "\f042"; +} + +i.icon.theme:before { + content: "\f043"; +} + +i.icon.edit:before { + content: "\f044"; +} + +i.icon.external.share:before { + content: "\f045"; +} + +i.icon.ban:before { + content: "\f05e"; +} + +i.icon.mail.forward:before { + content: "\f064"; +} + +i.icon.share:before { + content: "\f064"; +} + +i.icon.expand:before { + content: "\f065"; +} + +i.icon.compress:before { + content: "\f066"; +} + +i.icon.unhide:before { + content: "\f06e"; +} + +i.icon.hide:before { + content: "\f070"; +} + +i.icon.random:before { + content: "\f074"; +} + +i.icon.retweet:before { + content: "\f079"; +} + +i.icon.sign.out:before { + content: "\f08b"; +} + +i.icon.pin:before { + content: "\f08d"; +} + +i.icon.sign.in:before { + content: "\f090"; +} + +i.icon.upload:before { + content: "\f093"; +} + +i.icon.call:before { + content: "\f095"; +} + +i.icon.remove.bookmark:before { + content: "\f097"; +} + +i.icon.call.square:before { + content: "\f098"; +} + +i.icon.unlock:before { + content: "\f09c"; +} + +i.icon.configure:before { + content: "\f0ad"; +} + +i.icon.filter:before { + content: "\f0b0"; +} + +i.icon.wizard:before { + content: "\f0d0"; +} + +i.icon.undo:before { + content: "\f0e2"; +} + +i.icon.exchange:before { + content: "\f0ec"; +} + +i.icon.cloud.download:before { + content: "\f0ed"; +} + +i.icon.cloud.upload:before { + content: "\f0ee"; +} + +i.icon.reply:before { + content: "\f112"; +} + +i.icon.reply.all:before { + content: "\f122"; +} + +i.icon.erase:before { + content: "\f12d"; +} + +i.icon.unlock.alternate:before { + content: "\f13e"; +} + +i.icon.write.square:before { + content: "\f14b"; +} + +i.icon.share.square:before { + content: "\f14d"; +} + +i.icon.archive:before { + content: "\f187"; +} + +i.icon.translate:before { + content: "\f1ab"; +} + +i.icon.recycle:before { + content: "\f1b8"; +} + +i.icon.send:before { + content: "\f1d8"; +} + +i.icon.send.outline:before { + content: "\f1d9"; +} + +i.icon.share.alternate:before { + content: "\f1e0"; +} + +i.icon.share.alternate.square:before { + content: "\f1e1"; +} + +i.icon.add.to.cart:before { + content: "\f217"; +} + +i.icon.in.cart:before { + content: "\f218"; +} + +i.icon.add.user:before { + content: "\f234"; +} + +i.icon.remove.user:before { + content: "\f235"; +} + +i.icon.object.group:before { + content: "\f247"; +} + +i.icon.object.ungroup:before { + content: "\f248"; +} + +i.icon.clone:before { + content: "\f24d"; +} + +i.icon.talk:before { + content: "\f27a"; +} + +i.icon.talk.outline:before { + content: "\f27b"; +} + +/* Messages */ + +i.icon.help.circle:before { + content: "\f059"; +} + +i.icon.info.circle:before { + content: "\f05a"; +} + +i.icon.warning.circle:before { + content: "\f06a"; +} + +i.icon.warning.sign:before { + content: "\f071"; +} + +i.icon.announcement:before { + content: "\f0a1"; +} + +i.icon.help:before { + content: "\f128"; +} + +i.icon.info:before { + content: "\f129"; +} + +i.icon.warning:before { + content: "\f12a"; +} + +i.icon.birthday:before { + content: "\f1fd"; +} + +i.icon.help.circle.outline:before { + content: "\f29c"; +} + +/* Users */ + +i.icon.user:before { + content: "\f007"; +} + +i.icon.users:before { + content: "\f0c0"; +} + +i.icon.doctor:before { + content: "\f0f0"; +} + +i.icon.handicap:before { + content: "\f193"; +} + +i.icon.student:before { + content: "\f19d"; +} + +i.icon.child:before { + content: "\f1ae"; +} + +i.icon.spy:before { + content: "\f21b"; +} + +i.icon.user.circle:before { + content: "\f2bd"; +} + +i.icon.user.circle.outline:before { + content: "\f2be"; +} + +i.icon.user.outline:before { + content: "\f2c0"; +} + +/* Gender & Sexuality */ + +i.icon.female:before { + content: "\f182"; +} + +i.icon.male:before { + content: "\f183"; +} + +i.icon.woman:before { + content: "\f221"; +} + +i.icon.man:before { + content: "\f222"; +} + +i.icon.non.binary.transgender:before { + content: "\f223"; +} + +i.icon.intergender:before { + content: "\f224"; +} + +i.icon.transgender:before { + content: "\f225"; +} + +i.icon.lesbian:before { + content: "\f226"; +} + +i.icon.gay:before { + content: "\f227"; +} + +i.icon.heterosexual:before { + content: "\f228"; +} + +i.icon.other.gender:before { + content: "\f229"; +} + +i.icon.other.gender.vertical:before { + content: "\f22a"; +} + +i.icon.other.gender.horizontal:before { + content: "\f22b"; +} + +i.icon.neuter:before { + content: "\f22c"; +} + +i.icon.genderless:before { + content: "\f22d"; +} + +/* Accessibility */ + +i.icon.universal.access:before { + content: "\f29a"; +} + +i.icon.wheelchair:before { + content: "\f29b"; +} + +i.icon.blind:before { + content: "\f29d"; +} + +i.icon.audio.description:before { + content: "\f29e"; +} + +i.icon.volume.control.phone:before { + content: "\f2a0"; +} + +i.icon.braille:before { + content: "\f2a1"; +} + +i.icon.asl:before { + content: "\f2a3"; +} + +i.icon.assistive.listening.systems:before { + content: "\f2a2"; +} + +i.icon.deafness:before { + content: "\f2a4"; +} + +i.icon.sign.language:before { + content: "\f2a7"; +} + +i.icon.low.vision:before { + content: "\f2a8"; +} + +/* View Adjustment */ + +i.icon.block.layout:before { + content: "\f009"; +} + +i.icon.grid.layout:before { + content: "\f00a"; +} + +i.icon.list.layout:before { + content: "\f00b"; +} + +i.icon.zoom:before { + content: "\f00e"; +} + +i.icon.zoom.out:before { + content: "\f010"; +} + +i.icon.resize.vertical:before { + content: "\f07d"; +} + +i.icon.resize.horizontal:before { + content: "\f07e"; +} + +i.icon.maximize:before { + content: "\f0b2"; +} + +i.icon.crop:before { + content: "\f125"; +} + +/* Literal Objects */ + +i.icon.cocktail:before { + content: "\f000"; +} + +i.icon.road:before { + content: "\f018"; +} + +i.icon.flag:before { + content: "\f024"; +} + +i.icon.book:before { + content: "\f02d"; +} + +i.icon.gift:before { + content: "\f06b"; +} + +i.icon.leaf:before { + content: "\f06c"; +} + +i.icon.fire:before { + content: "\f06d"; +} + +i.icon.plane:before { + content: "\f072"; +} + +i.icon.magnet:before { + content: "\f076"; +} + +i.icon.lemon:before { + content: "\f094"; +} + +i.icon.world:before { + content: "\f0ac"; +} + +i.icon.travel:before { + content: "\f0b1"; +} + +i.icon.shipping:before { + content: "\f0d1"; +} + +i.icon.money:before { + content: "\f0d6"; +} + +i.icon.legal:before { + content: "\f0e3"; +} + +i.icon.lightning:before { + content: "\f0e7"; +} + +i.icon.umbrella:before { + content: "\f0e9"; +} + +i.icon.treatment:before { + content: "\f0f1"; +} + +i.icon.suitcase:before { + content: "\f0f2"; +} + +i.icon.bar:before { + content: "\f0fc"; +} + +i.icon.flag.outline:before { + content: "\f11d"; +} + +i.icon.flag.checkered:before { + content: "\f11e"; +} + +i.icon.puzzle:before { + content: "\f12e"; +} + +i.icon.fire.extinguisher:before { + content: "\f134"; +} + +i.icon.rocket:before { + content: "\f135"; +} + +i.icon.anchor:before { + content: "\f13d"; +} + +i.icon.bullseye:before { + content: "\f140"; +} + +i.icon.sun:before { + content: "\f185"; +} + +i.icon.moon:before { + content: "\f186"; +} + +i.icon.fax:before { + content: "\f1ac"; +} + +i.icon.life.ring:before { + content: "\f1cd"; +} + +i.icon.bomb:before { + content: "\f1e2"; +} + +i.icon.soccer:before { + content: "\f1e3"; +} + +i.icon.calculator:before { + content: "\f1ec"; +} + +i.icon.diamond:before { + content: "\f219"; +} + +i.icon.sticky.note:before { + content: "\f249"; +} + +i.icon.sticky.note.outline:before { + content: "\f24a"; +} + +i.icon.law:before { + content: "\f24e"; +} + +i.icon.hand.peace:before { + content: "\f25b"; +} + +i.icon.hand.rock:before { + content: "\f255"; +} + +i.icon.hand.paper:before { + content: "\f256"; +} + +i.icon.hand.scissors:before { + content: "\f257"; +} + +i.icon.hand.lizard:before { + content: "\f258"; +} + +i.icon.hand.spock:before { + content: "\f259"; +} + +i.icon.tv:before { + content: "\f26c"; +} + +i.icon.thermometer.full:before { + content: "\f2c7"; +} + +i.icon.thermometer.three.quarters:before { + content: "\f2c8"; +} + +i.icon.thermometer.half:before { + content: "\f2c9"; +} + +i.icon.thermometer.quarter:before { + content: "\f2ca"; +} + +i.icon.thermometer.empty:before { + content: "\f2cb"; +} + +i.icon.shower:before { + content: "\f2cc"; +} + +i.icon.bathtub:before { + content: "\f2cd"; +} + +i.icon.snowflake:before { + content: "\f2dc"; +} + +/* Shapes */ + +i.icon.crosshairs:before { + content: "\f05b"; +} + +i.icon.asterisk:before { + content: "\f069"; +} + +i.icon.square.outline:before { + content: "\f096"; +} + +i.icon.certificate:before { + content: "\f0a3"; +} + +i.icon.square:before { + content: "\f0c8"; +} + +i.icon.quote.left:before { + content: "\f10d"; +} + +i.icon.quote.right:before { + content: "\f10e"; +} + +i.icon.spinner:before { + content: "\f110"; +} + +i.icon.circle:before { + content: "\f111"; +} + +i.icon.ellipsis.horizontal:before { + content: "\f141"; +} + +i.icon.ellipsis.vertical:before { + content: "\f142"; +} + +i.icon.cube:before { + content: "\f1b2"; +} + +i.icon.cubes:before { + content: "\f1b3"; +} + +i.icon.circle.notched:before { + content: "\f1ce"; +} + +i.icon.circle.thin:before { + content: "\f1db"; +} + +/* Item Selection */ + +i.icon.checkmark:before { + content: "\f00c"; +} + +i.icon.remove:before { + content: "\f00d"; +} + +i.icon.checkmark.box:before { + content: "\f046"; +} + +i.icon.move:before { + content: "\f047"; +} + +i.icon.add.circle:before { + content: "\f055"; +} + +i.icon.minus.circle:before { + content: "\f056"; +} + +i.icon.remove.circle:before { + content: "\f057"; +} + +i.icon.check.circle:before { + content: "\f058"; +} + +i.icon.remove.circle.outline:before { + content: "\f05c"; +} + +i.icon.check.circle.outline:before { + content: "\f05d"; +} + +i.icon.plus:before { + content: "\f067"; +} + +i.icon.minus:before { + content: "\f068"; +} + +i.icon.add.square:before { + content: "\f0fe"; +} + +i.icon.radio:before { + content: "\f10c"; +} + +i.icon.minus.square:before { + content: "\f146"; +} + +i.icon.minus.square.outline:before { + content: "\f147"; +} + +i.icon.check.square:before { + content: "\f14a"; +} + +i.icon.selected.radio:before { + content: "\f192"; +} + +i.icon.plus.square.outline:before { + content: "\f196"; +} + +i.icon.toggle.off:before { + content: "\f204"; +} + +i.icon.toggle.on:before { + content: "\f205"; +} + +/* Media */ + +i.icon.film:before { + content: "\f008"; +} + +i.icon.sound:before { + content: "\f025"; +} + +i.icon.photo:before { + content: "\f030"; +} + +i.icon.bar.chart:before { + content: "\f080"; +} + +i.icon.camera.retro:before { + content: "\f083"; +} + +i.icon.newspaper:before { + content: "\f1ea"; +} + +i.icon.area.chart:before { + content: "\f1fe"; +} + +i.icon.pie.chart:before { + content: "\f200"; +} + +i.icon.line.chart:before { + content: "\f201"; +} + +/* Pointers */ + +i.icon.arrow.circle.outline.down:before { + content: "\f01a"; +} + +i.icon.arrow.circle.outline.up:before { + content: "\f01b"; +} + +i.icon.chevron.left:before { + content: "\f053"; +} + +i.icon.chevron.right:before { + content: "\f054"; +} + +i.icon.arrow.left:before { + content: "\f060"; +} + +i.icon.arrow.right:before { + content: "\f061"; +} + +i.icon.arrow.up:before { + content: "\f062"; +} + +i.icon.arrow.down:before { + content: "\f063"; +} + +i.icon.chevron.up:before { + content: "\f077"; +} + +i.icon.chevron.down:before { + content: "\f078"; +} + +i.icon.pointing.right:before { + content: "\f0a4"; +} + +i.icon.pointing.left:before { + content: "\f0a5"; +} + +i.icon.pointing.up:before { + content: "\f0a6"; +} + +i.icon.pointing.down:before { + content: "\f0a7"; +} + +i.icon.arrow.circle.left:before { + content: "\f0a8"; +} + +i.icon.arrow.circle.right:before { + content: "\f0a9"; +} + +i.icon.arrow.circle.up:before { + content: "\f0aa"; +} + +i.icon.arrow.circle.down:before { + content: "\f0ab"; +} + +i.icon.caret.down:before { + content: "\f0d7"; +} + +i.icon.caret.up:before { + content: "\f0d8"; +} + +i.icon.caret.left:before { + content: "\f0d9"; +} + +i.icon.caret.right:before { + content: "\f0da"; +} + +i.icon.angle.double.left:before { + content: "\f100"; +} + +i.icon.angle.double.right:before { + content: "\f101"; +} + +i.icon.angle.double.up:before { + content: "\f102"; +} + +i.icon.angle.double.down:before { + content: "\f103"; +} + +i.icon.angle.left:before { + content: "\f104"; +} + +i.icon.angle.right:before { + content: "\f105"; +} + +i.icon.angle.up:before { + content: "\f106"; +} + +i.icon.angle.down:before { + content: "\f107"; +} + +i.icon.chevron.circle.left:before { + content: "\f137"; +} + +i.icon.chevron.circle.right:before { + content: "\f138"; +} + +i.icon.chevron.circle.up:before { + content: "\f139"; +} + +i.icon.chevron.circle.down:before { + content: "\f13a"; +} + +i.icon.toggle.down:before { + content: "\f150"; +} + +i.icon.toggle.up:before { + content: "\f151"; +} + +i.icon.toggle.right:before { + content: "\f152"; +} + +i.icon.long.arrow.down:before { + content: "\f175"; +} + +i.icon.long.arrow.up:before { + content: "\f176"; +} + +i.icon.long.arrow.left:before { + content: "\f177"; +} + +i.icon.long.arrow.right:before { + content: "\f178"; +} + +i.icon.arrow.circle.outline.right:before { + content: "\f18e"; +} + +i.icon.arrow.circle.outline.left:before { + content: "\f190"; +} + +i.icon.toggle.left:before { + content: "\f191"; +} + +/* Mobile */ + +i.icon.tablet:before { + content: "\f10a"; +} + +i.icon.mobile:before { + content: "\f10b"; +} + +i.icon.battery.full:before { + content: "\f240"; +} + +i.icon.battery.high:before { + content: "\f241"; +} + +i.icon.battery.medium:before { + content: "\f242"; +} + +i.icon.battery.low:before { + content: "\f243"; +} + +i.icon.battery.empty:before { + content: "\f244"; +} + +/* Computer */ + +i.icon.power:before { + content: "\f011"; +} + +i.icon.trash.outline:before { + content: "\f014"; +} + +i.icon.disk.outline:before { + content: "\f0a0"; +} + +i.icon.desktop:before { + content: "\f108"; +} + +i.icon.laptop:before { + content: "\f109"; +} + +i.icon.game:before { + content: "\f11b"; +} + +i.icon.keyboard:before { + content: "\f11c"; +} + +i.icon.plug:before { + content: "\f1e6"; +} + +/* File System */ + +i.icon.trash:before { + content: "\f1f8"; +} + +i.icon.file.outline:before { + content: "\f016"; +} + +i.icon.folder:before { + content: "\f07b"; +} + +i.icon.folder.open:before { + content: "\f07c"; +} + +i.icon.file.text.outline:before { + content: "\f0f6"; +} + +i.icon.folder.outline:before { + content: "\f114"; +} + +i.icon.folder.open.outline:before { + content: "\f115"; +} + +i.icon.level.up:before { + content: "\f148"; +} + +i.icon.level.down:before { + content: "\f149"; +} + +i.icon.file:before { + content: "\f15b"; +} + +i.icon.file.text:before { + content: "\f15c"; +} + +i.icon.file.pdf.outline:before { + content: "\f1c1"; +} + +i.icon.file.word.outline:before { + content: "\f1c2"; +} + +i.icon.file.excel.outline:before { + content: "\f1c3"; +} + +i.icon.file.powerpoint.outline:before { + content: "\f1c4"; +} + +i.icon.file.image.outline:before { + content: "\f1c5"; +} + +i.icon.file.archive.outline:before { + content: "\f1c6"; +} + +i.icon.file.audio.outline:before { + content: "\f1c7"; +} + +i.icon.file.video.outline:before { + content: "\f1c8"; +} + +i.icon.file.code.outline:before { + content: "\f1c9"; +} + +/* Technologies */ + +i.icon.qrcode:before { + content: "\f029"; +} + +i.icon.barcode:before { + content: "\f02a"; +} + +i.icon.rss:before { + content: "\f09e"; +} + +i.icon.fork:before { + content: "\f126"; +} + +i.icon.html5:before { + content: "\f13b"; +} + +i.icon.css3:before { + content: "\f13c"; +} + +i.icon.rss.square:before { + content: "\f143"; +} + +i.icon.openid:before { + content: "\f19b"; +} + +i.icon.database:before { + content: "\f1c0"; +} + +i.icon.wifi:before { + content: "\f1eb"; +} + +i.icon.server:before { + content: "\f233"; +} + +i.icon.usb:before { + content: "\f287"; +} + +i.icon.bluetooth:before { + content: "\f293"; +} + +i.icon.bluetooth.alternative:before { + content: "\f294"; +} + +i.icon.microchip:before { + content: "\f2db"; +} + +/* Rating */ + +i.icon.heart:before { + content: "\f004"; +} + +i.icon.star:before { + content: "\f005"; +} + +i.icon.empty.star:before { + content: "\f006"; +} + +i.icon.thumbs.outline.up:before { + content: "\f087"; +} + +i.icon.thumbs.outline.down:before { + content: "\f088"; +} + +i.icon.star.half:before { + content: "\f089"; +} + +i.icon.empty.heart:before { + content: "\f08a"; +} + +i.icon.smile:before { + content: "\f118"; +} + +i.icon.frown:before { + content: "\f119"; +} + +i.icon.meh:before { + content: "\f11a"; +} + +i.icon.star.half.empty:before { + content: "\f123"; +} + +i.icon.thumbs.up:before { + content: "\f164"; +} + +i.icon.thumbs.down:before { + content: "\f165"; +} + +/* Audio */ + +i.icon.music:before { + content: "\f001"; +} + +i.icon.video.play.outline:before { + content: "\f01d"; +} + +i.icon.volume.off:before { + content: "\f026"; +} + +i.icon.volume.down:before { + content: "\f027"; +} + +i.icon.volume.up:before { + content: "\f028"; +} + +i.icon.record:before { + content: "\f03d"; +} + +i.icon.step.backward:before { + content: "\f048"; +} + +i.icon.fast.backward:before { + content: "\f049"; +} + +i.icon.backward:before { + content: "\f04a"; +} + +i.icon.play:before { + content: "\f04b"; +} + +i.icon.pause:before { + content: "\f04c"; +} + +i.icon.stop:before { + content: "\f04d"; +} + +i.icon.forward:before { + content: "\f04e"; +} + +i.icon.fast.forward:before { + content: "\f050"; +} + +i.icon.step.forward:before { + content: "\f051"; +} + +i.icon.eject:before { + content: "\f052"; +} + +i.icon.unmute:before { + content: "\f130"; +} + +i.icon.mute:before { + content: "\f131"; +} + +i.icon.video.play:before { + content: "\f144"; +} + +i.icon.closed.captioning:before { + content: "\f20a"; +} + +i.icon.pause.circle:before { + content: "\f28b"; +} + +i.icon.pause.circle.outline:before { + content: "\f28c"; +} + +i.icon.stop.circle:before { + content: "\f28d"; +} + +i.icon.stop.circle.outline:before { + content: "\f28e"; +} + +/* Map, Locations, & Transportation */ + +i.icon.marker:before { + content: "\f041"; +} + +i.icon.coffee:before { + content: "\f0f4"; +} + +i.icon.food:before { + content: "\f0f5"; +} + +i.icon.building.outline:before { + content: "\f0f7"; +} + +i.icon.hospital:before { + content: "\f0f8"; +} + +i.icon.emergency:before { + content: "\f0f9"; +} + +i.icon.first.aid:before { + content: "\f0fa"; +} + +i.icon.military:before { + content: "\f0fb"; +} + +i.icon.h:before { + content: "\f0fd"; +} + +i.icon.location.arrow:before { + content: "\f124"; +} + +i.icon.compass:before { + content: "\f14e"; +} + +i.icon.space.shuttle:before { + content: "\f197"; +} + +i.icon.university:before { + content: "\f19c"; +} + +i.icon.building:before { + content: "\f1ad"; +} + +i.icon.paw:before { + content: "\f1b0"; +} + +i.icon.spoon:before { + content: "\f1b1"; +} + +i.icon.car:before { + content: "\f1b9"; +} + +i.icon.taxi:before { + content: "\f1ba"; +} + +i.icon.tree:before { + content: "\f1bb"; +} + +i.icon.bicycle:before { + content: "\f206"; +} + +i.icon.bus:before { + content: "\f207"; +} + +i.icon.ship:before { + content: "\f21a"; +} + +i.icon.motorcycle:before { + content: "\f21c"; +} + +i.icon.street.view:before { + content: "\f21d"; +} + +i.icon.hotel:before { + content: "\f236"; +} + +i.icon.train:before { + content: "\f238"; +} + +i.icon.subway:before { + content: "\f239"; +} + +i.icon.map.pin:before { + content: "\f276"; +} + +i.icon.map.signs:before { + content: "\f277"; +} + +i.icon.map.outline:before { + content: "\f278"; +} + +i.icon.map:before { + content: "\f279"; +} + +/* Tables */ + +i.icon.table:before { + content: "\f0ce"; +} + +i.icon.columns:before { + content: "\f0db"; +} + +i.icon.sort:before { + content: "\f0dc"; +} + +i.icon.sort.descending:before { + content: "\f0dd"; +} + +i.icon.sort.ascending:before { + content: "\f0de"; +} + +i.icon.sort.alphabet.ascending:before { + content: "\f15d"; +} + +i.icon.sort.alphabet.descending:before { + content: "\f15e"; +} + +i.icon.sort.content.ascending:before { + content: "\f160"; +} + +i.icon.sort.content.descending:before { + content: "\f161"; +} + +i.icon.sort.numeric.ascending:before { + content: "\f162"; +} + +i.icon.sort.numeric.descending:before { + content: "\f163"; +} + +/* Text Editor */ + +i.icon.font:before { + content: "\f031"; +} + +i.icon.bold:before { + content: "\f032"; +} + +i.icon.italic:before { + content: "\f033"; +} + +i.icon.text.height:before { + content: "\f034"; +} + +i.icon.text.width:before { + content: "\f035"; +} + +i.icon.align.left:before { + content: "\f036"; +} + +i.icon.align.center:before { + content: "\f037"; +} + +i.icon.align.right:before { + content: "\f038"; +} + +i.icon.align.justify:before { + content: "\f039"; +} + +i.icon.list:before { + content: "\f03a"; +} + +i.icon.outdent:before { + content: "\f03b"; +} + +i.icon.indent:before { + content: "\f03c"; +} + +i.icon.linkify:before { + content: "\f0c1"; +} + +i.icon.cut:before { + content: "\f0c4"; +} + +i.icon.copy:before { + content: "\f0c5"; +} + +i.icon.attach:before { + content: "\f0c6"; +} + +i.icon.save:before { + content: "\f0c7"; +} + +i.icon.content:before { + content: "\f0c9"; +} + +i.icon.unordered.list:before { + content: "\f0ca"; +} + +i.icon.ordered.list:before { + content: "\f0cb"; +} + +i.icon.strikethrough:before { + content: "\f0cc"; +} + +i.icon.underline:before { + content: "\f0cd"; +} + +i.icon.paste:before { + content: "\f0ea"; +} + +i.icon.unlinkify:before { + content: "\f127"; +} + +i.icon.superscript:before { + content: "\f12b"; +} + +i.icon.subscript:before { + content: "\f12c"; +} + +i.icon.header:before { + content: "\f1dc"; +} + +i.icon.paragraph:before { + content: "\f1dd"; +} + +i.icon.text.cursor:before { + content: "\f246"; +} + +/* Currency */ + +i.icon.euro:before { + content: "\f153"; +} + +i.icon.pound:before { + content: "\f154"; +} + +i.icon.dollar:before { + content: "\f155"; +} + +i.icon.rupee:before { + content: "\f156"; +} + +i.icon.yen:before { + content: "\f157"; +} + +i.icon.ruble:before { + content: "\f158"; +} + +i.icon.won:before { + content: "\f159"; +} + +i.icon.bitcoin:before { + content: "\f15a"; +} + +i.icon.lira:before { + content: "\f195"; +} + +i.icon.shekel:before { + content: "\f20b"; +} + +/* Payment Options */ + +i.icon.paypal:before { + content: "\f1ed"; +} + +i.icon.google.wallet:before { + content: "\f1ee"; +} + +i.icon.visa:before { + content: "\f1f0"; +} + +i.icon.mastercard:before { + content: "\f1f1"; +} + +i.icon.discover:before { + content: "\f1f2"; +} + +i.icon.american.express:before { + content: "\f1f3"; +} + +i.icon.paypal.card:before { + content: "\f1f4"; +} + +i.icon.stripe:before { + content: "\f1f5"; +} + +i.icon.japan.credit.bureau:before { + content: "\f24b"; +} + +i.icon.diners.club:before { + content: "\f24c"; +} + +i.icon.credit.card.alternative:before { + content: "\f283"; +} + +/* Networks and Websites*/ + +i.icon.twitter.square:before { + content: "\f081"; +} + +i.icon.facebook.square:before { + content: "\f082"; +} + +i.icon.linkedin.square:before { + content: "\f08c"; +} + +i.icon.github.square:before { + content: "\f092"; +} + +i.icon.twitter:before { + content: "\f099"; +} + +i.icon.facebook.f:before { + content: "\f09a"; +} + +i.icon.github:before { + content: "\f09b"; +} + +i.icon.pinterest:before { + content: "\f0d2"; +} + +i.icon.pinterest.square:before { + content: "\f0d3"; +} + +i.icon.google.plus.square:before { + content: "\f0d4"; +} + +i.icon.google.plus:before { + content: "\f0d5"; +} + +i.icon.linkedin:before { + content: "\f0e1"; +} + +i.icon.github.alternate:before { + content: "\f113"; +} + +i.icon.maxcdn:before { + content: "\f136"; +} + +i.icon.youtube.square:before { + content: "\f166"; +} + +i.icon.youtube:before { + content: "\f167"; +} + +i.icon.xing:before { + content: "\f168"; +} + +i.icon.xing.square:before { + content: "\f169"; +} + +i.icon.youtube.play:before { + content: "\f16a"; +} + +i.icon.dropbox:before { + content: "\f16b"; +} + +i.icon.stack.overflow:before { + content: "\f16c"; +} + +i.icon.instagram:before { + content: "\f16d"; +} + +i.icon.flickr:before { + content: "\f16e"; +} + +i.icon.adn:before { + content: "\f170"; +} + +i.icon.bitbucket:before { + content: "\f171"; +} + +i.icon.bitbucket.square:before { + content: "\f172"; +} + +i.icon.tumblr:before { + content: "\f173"; +} + +i.icon.tumblr.square:before { + content: "\f174"; +} + +i.icon.apple:before { + content: "\f179"; +} + +i.icon.windows:before { + content: "\f17a"; +} + +i.icon.android:before { + content: "\f17b"; +} + +i.icon.linux:before { + content: "\f17c"; +} + +i.icon.dribble:before { + content: "\f17d"; +} + +i.icon.skype:before { + content: "\f17e"; +} + +i.icon.foursquare:before { + content: "\f180"; +} + +i.icon.trello:before { + content: "\f181"; +} + +i.icon.gittip:before { + content: "\f184"; +} + +i.icon.vk:before { + content: "\f189"; +} + +i.icon.weibo:before { + content: "\f18a"; +} + +i.icon.renren:before { + content: "\f18b"; +} + +i.icon.pagelines:before { + content: "\f18c"; +} + +i.icon.stack.exchange:before { + content: "\f18d"; +} + +i.icon.vimeo.square:before { + content: "\f194"; +} + +i.icon.slack:before { + content: "\f198"; +} + +i.icon.wordpress:before { + content: "\f19a"; +} + +i.icon.yahoo:before { + content: "\f19e"; +} + +i.icon.google:before { + content: "\f1a0"; +} + +i.icon.reddit:before { + content: "\f1a1"; +} + +i.icon.reddit.square:before { + content: "\f1a2"; +} + +i.icon.stumbleupon.circle:before { + content: "\f1a3"; +} + +i.icon.stumbleupon:before { + content: "\f1a4"; +} + +i.icon.delicious:before { + content: "\f1a5"; +} + +i.icon.digg:before { + content: "\f1a6"; +} + +i.icon.pied.piper:before { + content: "\f1a7"; +} + +i.icon.pied.piper.alternate:before { + content: "\f1a8"; +} + +i.icon.drupal:before { + content: "\f1a9"; +} + +i.icon.joomla:before { + content: "\f1aa"; +} + +i.icon.behance:before { + content: "\f1b4"; +} + +i.icon.behance.square:before { + content: "\f1b5"; +} + +i.icon.steam:before { + content: "\f1b6"; +} + +i.icon.steam.square:before { + content: "\f1b7"; +} + +i.icon.spotify:before { + content: "\f1bc"; +} + +i.icon.deviantart:before { + content: "\f1bd"; +} + +i.icon.soundcloud:before { + content: "\f1be"; +} + +i.icon.vine:before { + content: "\f1ca"; +} + +i.icon.codepen:before { + content: "\f1cb"; +} + +i.icon.jsfiddle:before { + content: "\f1cc"; +} + +i.icon.rebel:before { + content: "\f1d0"; +} + +i.icon.empire:before { + content: "\f1d1"; +} + +i.icon.git.square:before { + content: "\f1d2"; +} + +i.icon.git:before { + content: "\f1d3"; +} + +i.icon.hacker.news:before { + content: "\f1d4"; +} + +i.icon.tencent.weibo:before { + content: "\f1d5"; +} + +i.icon.qq:before { + content: "\f1d6"; +} + +i.icon.wechat:before { + content: "\f1d7"; +} + +i.icon.slideshare:before { + content: "\f1e7"; +} + +i.icon.twitch:before { + content: "\f1e8"; +} + +i.icon.yelp:before { + content: "\f1e9"; +} + +i.icon.lastfm:before { + content: "\f202"; +} + +i.icon.lastfm.square:before { + content: "\f203"; +} + +i.icon.ioxhost:before { + content: "\f208"; +} + +i.icon.angellist:before { + content: "\f209"; +} + +i.icon.meanpath:before { + content: "\f20c"; +} + +i.icon.buysellads:before { + content: "\f20d"; +} + +i.icon.connectdevelop:before { + content: "\f20e"; +} + +i.icon.dashcube:before { + content: "\f210"; +} + +i.icon.forumbee:before { + content: "\f211"; +} + +i.icon.leanpub:before { + content: "\f212"; +} + +i.icon.sellsy:before { + content: "\f213"; +} + +i.icon.shirtsinbulk:before { + content: "\f214"; +} + +i.icon.simplybuilt:before { + content: "\f215"; +} + +i.icon.skyatlas:before { + content: "\f216"; +} + +i.icon.facebook:before { + content: "\f230"; +} + +i.icon.pinterest:before { + content: "\f231"; +} + +i.icon.whatsapp:before { + content: "\f232"; +} + +i.icon.viacoin:before { + content: "\f237"; +} + +i.icon.medium:before { + content: "\f23a"; +} + +i.icon.y.combinator:before { + content: "\f23b"; +} + +i.icon.optinmonster:before { + content: "\f23c"; +} + +i.icon.opencart:before { + content: "\f23d"; +} + +i.icon.expeditedssl:before { + content: "\f23e"; +} + +i.icon.gg:before { + content: "\f260"; +} + +i.icon.gg.circle:before { + content: "\f261"; +} + +i.icon.tripadvisor:before { + content: "\f262"; +} + +i.icon.odnoklassniki:before { + content: "\f263"; +} + +i.icon.odnoklassniki.square:before { + content: "\f264"; +} + +i.icon.pocket:before { + content: "\f265"; +} + +i.icon.wikipedia:before { + content: "\f266"; +} + +i.icon.safari:before { + content: "\f267"; +} + +i.icon.chrome:before { + content: "\f268"; +} + +i.icon.firefox:before { + content: "\f269"; +} + +i.icon.opera:before { + content: "\f26a"; +} + +i.icon.internet.explorer:before { + content: "\f26b"; +} + +i.icon.contao:before { + content: "\f26d"; +} + +i.icon.\35 00px:before { + content: "\f26e"; +} + +i.icon.amazon:before { + content: "\f270"; +} + +i.icon.houzz:before { + content: "\f27c"; +} + +i.icon.vimeo:before { + content: "\f27d"; +} + +i.icon.black.tie:before { + content: "\f27e"; +} + +i.icon.fonticons:before { + content: "\f280"; +} + +i.icon.reddit.alien:before { + content: "\f281"; +} + +i.icon.microsoft.edge:before { + content: "\f282"; +} + +i.icon.codiepie:before { + content: "\f284"; +} + +i.icon.modx:before { + content: "\f285"; +} + +i.icon.fort.awesome:before { + content: "\f286"; +} + +i.icon.product.hunt:before { + content: "\f288"; +} + +i.icon.mixcloud:before { + content: "\f289"; +} + +i.icon.scribd:before { + content: "\f28a"; +} + +i.icon.gitlab:before { + content: "\f296"; +} + +i.icon.wpbeginner:before { + content: "\f297"; +} + +i.icon.wpforms:before { + content: "\f298"; +} + +i.icon.envira.gallery:before { + content: "\f299"; +} + +i.icon.glide:before { + content: "\f2a5"; +} + +i.icon.glide.g:before { + content: "\f2a6"; +} + +i.icon.viadeo:before { + content: "\f2a9"; +} + +i.icon.viadeo.square:before { + content: "\f2aa"; +} + +i.icon.snapchat:before { + content: "\f2ab"; +} + +i.icon.snapchat.ghost:before { + content: "\f2ac"; +} + +i.icon.snapchat.square:before { + content: "\f2ad"; +} + +i.icon.pied.piper.hat:before { + content: "\f2ae"; +} + +i.icon.first.order:before { + content: "\f2b0"; +} + +i.icon.yoast:before { + content: "\f2b1"; +} + +i.icon.themeisle:before { + content: "\f2b2"; +} + +i.icon.google.plus.circle:before { + content: "\f2b3"; +} + +i.icon.font.awesome:before { + content: "\f2b4"; +} + +i.icon.linode:before { + content: "\f2b8"; +} + +i.icon.quora:before { + content: "\f2c4"; +} + +i.icon.free.code.camp:before { + content: "\f2c5"; +} + +i.icon.telegram:before { + content: "\f2c6"; +} + +i.icon.bandcamp:before { + content: "\f2d5"; +} + +i.icon.grav:before { + content: "\f2d6"; +} + +i.icon.etsy:before { + content: "\f2d7"; +} + +i.icon.imdb:before { + content: "\f2d8"; +} + +i.icon.ravelry:before { + content: "\f2d9"; +} + +i.icon.eercast:before { + content: "\f2da"; +} + +i.icon.superpowers:before { + content: "\f2dd"; +} + +i.icon.wpexplorer:before { + content: "\f2de"; +} + +i.icon.meetup:before { + content: "\f2e0"; +} + +/******************************* + Aliases +*******************************/ + +i.icon.like:before { + content: "\f004"; +} + +i.icon.favorite:before { + content: "\f005"; +} + +i.icon.video:before { + content: "\f008"; +} + +i.icon.check:before { + content: "\f00c"; +} + +i.icon.close:before { + content: "\f00d"; +} + +i.icon.cancel:before { + content: "\f00d"; +} + +i.icon.delete:before { + content: "\f00d"; +} + +i.icon.x:before { + content: "\f00d"; +} + +i.icon.zoom.in:before { + content: "\f00e"; +} + +i.icon.magnify:before { + content: "\f00e"; +} + +i.icon.shutdown:before { + content: "\f011"; +} + +i.icon.clock:before { + content: "\f017"; +} + +i.icon.time:before { + content: "\f017"; +} + +i.icon.play.circle.outline:before { + content: "\f01d"; +} + +i.icon.headphone:before { + content: "\f025"; +} + +i.icon.camera:before { + content: "\f030"; +} + +i.icon.video.camera:before { + content: "\f03d"; +} + +i.icon.picture:before { + content: "\f03e"; +} + +i.icon.pencil:before { + content: "\f040"; +} + +i.icon.compose:before { + content: "\f040"; +} + +i.icon.point:before { + content: "\f041"; +} + +i.icon.tint:before { + content: "\f043"; +} + +i.icon.signup:before { + content: "\f044"; +} + +i.icon.plus.circle:before { + content: "\f055"; +} + +i.icon.question.circle:before { + content: "\f059"; +} + +i.icon.dont:before { + content: "\f05e"; +} + +i.icon.minimize:before { + content: "\f066"; +} + +i.icon.add:before { + content: "\f067"; +} + +i.icon.exclamation.circle:before { + content: "\f06a"; +} + +i.icon.attention:before { + content: "\f06a"; +} + +i.icon.eye:before { + content: "\f06e"; +} + +i.icon.exclamation.triangle:before { + content: "\f071"; +} + +i.icon.shuffle:before { + content: "\f074"; +} + +i.icon.chat:before { + content: "\f075"; +} + +i.icon.cart:before { + content: "\f07a"; +} + +i.icon.shopping.cart:before { + content: "\f07a"; +} + +i.icon.bar.graph:before { + content: "\f080"; +} + +i.icon.key:before { + content: "\f084"; +} + +i.icon.cogs:before { + content: "\f085"; +} + +i.icon.discussions:before { + content: "\f086"; +} + +i.icon.like.outline:before { + content: "\f087"; +} + +i.icon.dislike.outline:before { + content: "\f088"; +} + +i.icon.heart.outline:before { + content: "\f08a"; +} + +i.icon.log.out:before { + content: "\f08b"; +} + +i.icon.thumb.tack:before { + content: "\f08d"; +} + +i.icon.winner:before { + content: "\f091"; +} + +i.icon.phone:before { + content: "\f095"; +} + +i.icon.bookmark.outline:before { + content: "\f097"; +} + +i.icon.phone.square:before { + content: "\f098"; +} + +i.icon.credit.card:before { + content: "\f09d"; +} + +i.icon.hdd.outline:before { + content: "\f0a0"; +} + +i.icon.bullhorn:before { + content: "\f0a1"; +} + +i.icon.bell.outline:before { + content: "\f0a2"; +} + +i.icon.hand.outline.right:before { + content: "\f0a4"; +} + +i.icon.hand.outline.left:before { + content: "\f0a5"; +} + +i.icon.hand.outline.up:before { + content: "\f0a6"; +} + +i.icon.hand.outline.down:before { + content: "\f0a7"; +} + +i.icon.globe:before { + content: "\f0ac"; +} + +i.icon.wrench:before { + content: "\f0ad"; +} + +i.icon.briefcase:before { + content: "\f0b1"; +} + +i.icon.group:before { + content: "\f0c0"; +} + +i.icon.linkify:before { + content: "\f0c1"; +} + +i.icon.chain:before { + content: "\f0c1"; +} + +i.icon.flask:before { + content: "\f0c3"; +} + +i.icon.sidebar:before { + content: "\f0c9"; +} + +i.icon.bars:before { + content: "\f0c9"; +} + +i.icon.list.ul:before { + content: "\f0ca"; +} + +i.icon.list.ol:before { + content: "\f0cb"; +} + +i.icon.numbered.list:before { + content: "\f0cb"; +} + +i.icon.magic:before { + content: "\f0d0"; +} + +i.icon.truck:before { + content: "\f0d1"; +} + +i.icon.currency:before { + content: "\f0d6"; +} + +i.icon.triangle.down:before { + content: "\f0d7"; +} + +i.icon.dropdown:before { + content: "\f0d7"; +} + +i.icon.triangle.up:before { + content: "\f0d8"; +} + +i.icon.triangle.left:before { + content: "\f0d9"; +} + +i.icon.triangle.right:before { + content: "\f0da"; +} + +i.icon.envelope:before { + content: "\f0e0"; +} + +i.icon.conversation:before { + content: "\f0e6"; +} + +i.icon.rain:before { + content: "\f0e9"; +} + +i.icon.clipboard:before { + content: "\f0ea"; +} + +i.icon.lightbulb:before { + content: "\f0eb"; +} + +i.icon.bell:before { + content: "\f0f3"; +} + +i.icon.ambulance:before { + content: "\f0f9"; +} + +i.icon.medkit:before { + content: "\f0fa"; +} + +i.icon.fighter.jet:before { + content: "\f0fb"; +} + +i.icon.beer:before { + content: "\f0fc"; +} + +i.icon.plus.square:before { + content: "\f0fe"; +} + +i.icon.computer:before { + content: "\f108"; +} + +i.icon.circle.outline:before { + content: "\f10c"; +} + +i.icon.gamepad:before { + content: "\f11b"; +} + +i.icon.star.half.full:before { + content: "\f123"; +} + +i.icon.broken.chain:before { + content: "\f127"; +} + +i.icon.question:before { + content: "\f128"; +} + +i.icon.exclamation:before { + content: "\f12a"; +} + +i.icon.eraser:before { + content: "\f12d"; +} + +i.icon.microphone:before { + content: "\f130"; +} + +i.icon.microphone.slash:before { + content: "\f131"; +} + +i.icon.shield:before { + content: "\f132"; +} + +i.icon.target:before { + content: "\f140"; +} + +i.icon.play.circle:before { + content: "\f144"; +} + +i.icon.pencil.square:before { + content: "\f14b"; +} + +i.icon.eur:before { + content: "\f153"; +} + +i.icon.gbp:before { + content: "\f154"; +} + +i.icon.usd:before { + content: "\f155"; +} + +i.icon.inr:before { + content: "\f156"; +} + +i.icon.cny:before { + content: "\f157"; +} + +i.icon.rmb:before { + content: "\f157"; +} + +i.icon.jpy:before { + content: "\f157"; +} + +i.icon.rouble:before { + content: "\f158"; +} + +i.icon.rub:before { + content: "\f158"; +} + +i.icon.krw:before { + content: "\f159"; +} + +i.icon.btc:before { + content: "\f15a"; +} + +i.icon.gratipay:before { + content: "\f184"; +} + +i.icon.zip:before { + content: "\f187"; +} + +i.icon.dot.circle.outline:before { + content: "\f192"; +} + +i.icon.try:before { + content: "\f195"; +} + +i.icon.graduation:before { + content: "\f19d"; +} + +i.icon.circle.outline:before { + content: "\f1db"; +} + +i.icon.sliders:before { + content: "\f1de"; +} + +i.icon.weixin:before { + content: "\f1d7"; +} + +i.icon.tty:before { + content: "\f1e4"; +} + +i.icon.teletype:before { + content: "\f1e4"; +} + +i.icon.binoculars:before { + content: "\f1e5"; +} + +i.icon.power.cord:before { + content: "\f1e6"; +} + +i.icon.wi-fi:before { + content: "\f1eb"; +} + +i.icon.visa.card:before { + content: "\f1f0"; +} + +i.icon.mastercard.card:before { + content: "\f1f1"; +} + +i.icon.discover.card:before { + content: "\f1f2"; +} + +i.icon.amex:before { + content: "\f1f3"; +} + +i.icon.american.express.card:before { + content: "\f1f3"; +} + +i.icon.stripe.card:before { + content: "\f1f5"; +} + +i.icon.bell.slash:before { + content: "\f1f6"; +} + +i.icon.bell.slash.outline:before { + content: "\f1f7"; +} + +i.icon.area.graph:before { + content: "\f1fe"; +} + +i.icon.pie.graph:before { + content: "\f200"; +} + +i.icon.line.graph:before { + content: "\f201"; +} + +i.icon.cc:before { + content: "\f20a"; +} + +i.icon.sheqel:before { + content: "\f20b"; +} + +i.icon.ils:before { + content: "\f20b"; +} + +i.icon.plus.cart:before { + content: "\f217"; +} + +i.icon.arrow.down.cart:before { + content: "\f218"; +} + +i.icon.detective:before { + content: "\f21b"; +} + +i.icon.venus:before { + content: "\f221"; +} + +i.icon.mars:before { + content: "\f222"; +} + +i.icon.mercury:before { + content: "\f223"; +} + +i.icon.intersex:before { + content: "\f224"; +} + +i.icon.venus.double:before { + content: "\f226"; +} + +i.icon.female.homosexual:before { + content: "\f226"; +} + +i.icon.mars.double:before { + content: "\f227"; +} + +i.icon.male.homosexual:before { + content: "\f227"; +} + +i.icon.venus.mars:before { + content: "\f228"; +} + +i.icon.mars.stroke:before { + content: "\f229"; +} + +i.icon.mars.alternate:before { + content: "\f229"; +} + +i.icon.mars.vertical:before { + content: "\f22a"; +} + +i.icon.mars.stroke.vertical:before { + content: "\f22a"; +} + +i.icon.mars.horizontal:before { + content: "\f22b"; +} + +i.icon.mars.stroke.horizontal:before { + content: "\f22b"; +} + +i.icon.asexual:before { + content: "\f22d"; +} + +i.icon.facebook.official:before { + content: "\f230"; +} + +i.icon.user.plus:before { + content: "\f234"; +} + +i.icon.user.times:before { + content: "\f235"; +} + +i.icon.user.close:before { + content: "\f235"; +} + +i.icon.user.cancel:before { + content: "\f235"; +} + +i.icon.user.delete:before { + content: "\f235"; +} + +i.icon.user.x:before { + content: "\f235"; +} + +i.icon.bed:before { + content: "\f236"; +} + +i.icon.yc:before { + content: "\f23b"; +} + +i.icon.ycombinator:before { + content: "\f23b"; +} + +i.icon.battery.four:before { + content: "\f240"; +} + +i.icon.battery.three:before { + content: "\f241"; +} + +i.icon.battery.three.quarters:before { + content: "\f241"; +} + +i.icon.battery.two:before { + content: "\f242"; +} + +i.icon.battery.half:before { + content: "\f242"; +} + +i.icon.battery.one:before { + content: "\f243"; +} + +i.icon.battery.quarter:before { + content: "\f243"; +} + +i.icon.battery.zero:before { + content: "\f244"; +} + +i.icon.i.cursor:before { + content: "\f246"; +} + +i.icon.jcb:before { + content: "\f24b"; +} + +i.icon.japan.credit.bureau.card:before { + content: "\f24b"; +} + +i.icon.diners.club.card:before { + content: "\f24c"; +} + +i.icon.balance:before { + content: "\f24e"; +} + +i.icon.hourglass.outline:before { + content: "\f250"; +} + +i.icon.hourglass.zero:before { + content: "\f250"; +} + +i.icon.hourglass.one:before { + content: "\f251"; +} + +i.icon.hourglass.two:before { + content: "\f252"; +} + +i.icon.hourglass.three:before { + content: "\f253"; +} + +i.icon.hourglass.four:before { + content: "\f254"; +} + +i.icon.grab:before { + content: "\f255"; +} + +i.icon.hand.victory:before { + content: "\f25b"; +} + +i.icon.tm:before { + content: "\f25c"; +} + +i.icon.r.circle:before { + content: "\f25d"; +} + +i.icon.television:before { + content: "\f26c"; +} + +i.icon.five.hundred.pixels:before { + content: "\f26e"; +} + +i.icon.calendar.plus:before { + content: "\f271"; +} + +i.icon.calendar.minus:before { + content: "\f272"; +} + +i.icon.calendar.times:before { + content: "\f273"; +} + +i.icon.calendar.check:before { + content: "\f274"; +} + +i.icon.factory:before { + content: "\f275"; +} + +i.icon.commenting:before { + content: "\f27a"; +} + +i.icon.commenting.outline:before { + content: "\f27b"; +} + +i.icon.edge:before { + content: "\f282"; +} + +i.icon.ms.edge:before { + content: "\f282"; +} + +i.icon.wordpress.beginner:before { + content: "\f297"; +} + +i.icon.wordpress.forms:before { + content: "\f298"; +} + +i.icon.envira:before { + content: "\f299"; +} + +i.icon.question.circle.outline:before { + content: "\f29c"; +} + +i.icon.assistive.listening.devices:before { + content: "\f2a2"; +} + +i.icon.als:before { + content: "\f2a2"; +} + +i.icon.ald:before { + content: "\f2a2"; +} + +i.icon.asl.interpreting:before { + content: "\f2a3"; +} + +i.icon.deaf:before { + content: "\f2a4"; +} + +i.icon.american.sign.language.interpreting:before { + content: "\f2a3"; +} + +i.icon.hard.of.hearing:before { + content: "\f2a4"; +} + +i.icon.signing:before { + content: "\f2a7"; +} + +i.icon.new.pied.piper:before { + content: "\f2ae"; +} + +i.icon.theme.isle:before { + content: "\f2b2"; +} + +i.icon.google.plus.official:before { + content: "\f2b3"; +} + +i.icon.fa:before { + content: "\f2b4"; +} + +i.icon.vcard:before { + content: "\f2bb"; +} + +i.icon.vcard.outline:before { + content: "\f2bc"; +} + +i.icon.drivers.license:before { + content: "\f2c2"; +} + +i.icon.drivers.license.outline:before { + content: "\f2c3"; +} + +i.icon.thermometer:before { + content: "\f2c7"; +} + +i.icon.s15:before { + content: "\f2cd"; +} + +i.icon.bath:before { + content: "\f2cd"; +} + +i.icon.times.rectangle:before { + content: "\f2d3"; +} + +i.icon.times.rectangle.outline:before { + content: "\f2d4"; +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Image + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Image +*******************************/ + +.ui.image { + position: relative; + display: inline-block; + vertical-align: middle; + max-width: 100%; + background-color: transparent; +} + +img.ui.image { + display: block; +} + +.ui.image svg, +.ui.image img { + display: block; + max-width: 100%; + height: auto; +} + +/******************************* + States +*******************************/ + +.ui.hidden.images, +.ui.hidden.image { + display: none; +} + +.ui.hidden.transition.images, +.ui.hidden.transition.image { + display: block; + visibility: hidden; +} + +.ui.disabled.images, +.ui.disabled.image { + cursor: default; + opacity: 0.45; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Inline +---------------*/ + +.ui.inline.image, +.ui.inline.image svg, +.ui.inline.image img { + display: inline-block; +} + +/*------------------ + Vertical Aligned +-------------------*/ + +.ui.top.aligned.images .image, +.ui.top.aligned.image, +.ui.top.aligned.image svg, +.ui.top.aligned.image img { + display: inline-block; + vertical-align: top; +} + +.ui.middle.aligned.images .image, +.ui.middle.aligned.image, +.ui.middle.aligned.image svg, +.ui.middle.aligned.image img { + display: inline-block; + vertical-align: middle; +} + +.ui.bottom.aligned.images .image, +.ui.bottom.aligned.image, +.ui.bottom.aligned.image svg, +.ui.bottom.aligned.image img { + display: inline-block; + vertical-align: bottom; +} + +/*-------------- + Rounded +---------------*/ + +.ui.rounded.images .image, +.ui.rounded.image, +.ui.rounded.images .image > *, +.ui.rounded.image > * { + border-radius: 0.3125em; +} + +/*-------------- + Bordered +---------------*/ + +.ui.bordered.images .image, +.ui.bordered.images img, +.ui.bordered.images svg, +.ui.bordered.image img, +.ui.bordered.image svg, +img.ui.bordered.image { + border: 1px solid rgba(0, 0, 0, 0.1); +} + +/*-------------- + Circular +---------------*/ + +.ui.circular.images, +.ui.circular.image { + overflow: hidden; +} + +.ui.circular.images .image, +.ui.circular.image, +.ui.circular.images .image > *, +.ui.circular.image > * { + border-radius: 500rem; +} + +/*-------------- + Fluid +---------------*/ + +.ui.fluid.images, +.ui.fluid.image, +.ui.fluid.images img, +.ui.fluid.images svg, +.ui.fluid.image svg, +.ui.fluid.image img { + display: block; + width: 100%; + height: auto; +} + +/*-------------- + Avatar +---------------*/ + +.ui.avatar.images .image, +.ui.avatar.images img, +.ui.avatar.images svg, +.ui.avatar.image img, +.ui.avatar.image svg, +.ui.avatar.image { + margin-right: 0.25em; + display: inline-block; + width: 2em; + height: 2em; + border-radius: 500rem; +} + +/*------------------- + Spaced +--------------------*/ + +.ui.spaced.image { + display: inline-block !important; + margin-left: 0.5em; + margin-right: 0.5em; +} + +.ui[class*="left spaced"].image { + margin-left: 0.5em; + margin-right: 0em; +} + +.ui[class*="right spaced"].image { + margin-left: 0em; + margin-right: 0.5em; +} + +/*------------------- + Floated +--------------------*/ + +.ui.floated.image, +.ui.floated.images { + float: left; + margin-right: 1em; + margin-bottom: 1em; +} + +.ui.right.floated.images, +.ui.right.floated.image { + float: right; + margin-right: 0em; + margin-bottom: 1em; + margin-left: 1em; +} + +.ui.floated.images:last-child, +.ui.floated.image:last-child { + margin-bottom: 0em; +} + +.ui.centered.images, +.ui.centered.image { + margin-left: auto; + margin-right: auto; +} + +/*-------------- + Sizes +---------------*/ + +.ui.mini.images .image, +.ui.mini.images img, +.ui.mini.images svg, +.ui.mini.image { + width: 35px; + height: auto; + font-size: 0.78571429rem; +} + +.ui.tiny.images .image, +.ui.tiny.images img, +.ui.tiny.images svg, +.ui.tiny.image { + width: 80px; + height: auto; + font-size: 0.85714286rem; +} + +.ui.small.images .image, +.ui.small.images img, +.ui.small.images svg, +.ui.small.image { + width: 150px; + height: auto; + font-size: 0.92857143rem; +} + +.ui.medium.images .image, +.ui.medium.images img, +.ui.medium.images svg, +.ui.medium.image { + width: 300px; + height: auto; + font-size: 1rem; +} + +.ui.large.images .image, +.ui.large.images img, +.ui.large.images svg, +.ui.large.image { + width: 450px; + height: auto; + font-size: 1.14285714rem; +} + +.ui.big.images .image, +.ui.big.images img, +.ui.big.images svg, +.ui.big.image { + width: 600px; + height: auto; + font-size: 1.28571429rem; +} + +.ui.huge.images .image, +.ui.huge.images img, +.ui.huge.images svg, +.ui.huge.image { + width: 800px; + height: auto; + font-size: 1.42857143rem; +} + +.ui.massive.images .image, +.ui.massive.images img, +.ui.massive.images svg, +.ui.massive.image { + width: 960px; + height: auto; + font-size: 1.71428571rem; +} + +/******************************* + Groups +*******************************/ + +.ui.images { + font-size: 0em; + margin: 0em -0.25rem 0rem; +} + +.ui.images .image, +.ui.images img, +.ui.images svg { + display: inline-block; + margin: 0em 0.25rem 0.5rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Input + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Standard +*******************************/ + +/*-------------------- + Inputs +---------------------*/ + +.ui.input { + position: relative; + font-weight: normal; + font-style: normal; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + color: rgba(0, 0, 0, 0.87); +} + +.ui.input input { + margin: 0em; + max-width: 100%; + -webkit-box-flex: 1; + -webkit-flex: 1 0 auto; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + outline: none; + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); + text-align: left; + line-height: 1.21428571em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + padding: 0.67857143em 1em; + background: #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + color: rgba(0, 0, 0, 0.87); + border-radius: 0.28571429rem; + -webkit-transition: box-shadow 0.1s ease, border-color 0.1s ease; + transition: box-shadow 0.1s ease, border-color 0.1s ease; + box-shadow: none; +} + +/*-------------------- + Placeholder +---------------------*/ + +/* browsers require these rules separate */ + +.ui.input input::-webkit-input-placeholder { + color: rgba(191, 191, 191, 0.87); +} + +.ui.input input::-moz-placeholder { + color: rgba(191, 191, 191, 0.87); +} + +.ui.input input:-ms-input-placeholder { + color: rgba(191, 191, 191, 0.87); +} + +/******************************* + States +*******************************/ + +/*-------------------- + Disabled +---------------------*/ + +.ui.disabled.input, +.ui.input input[disabled] { + opacity: 0.45; +} + +.ui.disabled.input input, +.ui.input input[disabled] { + pointer-events: none; +} + +/*-------------------- + Active +---------------------*/ + +.ui.input input:active, +.ui.input.down input { + border-color: rgba(0, 0, 0, 0.3); + background: #FAFAFA; + color: rgba(0, 0, 0, 0.87); + box-shadow: none; +} + +/*-------------------- + Loading +---------------------*/ + +.ui.loading.loading.input > i.icon:before { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.1); +} + +.ui.loading.loading.input > i.icon:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + -webkit-animation: button-spin 0.6s linear; + animation: button-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 transparent transparent; + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; +} + +/*-------------------- + Focus +---------------------*/ + +.ui.input.focus input, +.ui.input input:focus { + border-color: #85B7D9; + background: #FFFFFF; + color: rgba(0, 0, 0, 0.8); + box-shadow: none; +} + +.ui.input.focus input::-webkit-input-placeholder, +.ui.input input:focus::-webkit-input-placeholder { + color: rgba(115, 115, 115, 0.87); +} + +.ui.input.focus input::-moz-placeholder, +.ui.input input:focus::-moz-placeholder { + color: rgba(115, 115, 115, 0.87); +} + +.ui.input.focus input:-ms-input-placeholder, +.ui.input input:focus:-ms-input-placeholder { + color: rgba(115, 115, 115, 0.87); +} + +/*-------------------- + Error +---------------------*/ + +.ui.input.error input { + background-color: #FFF6F6; + border-color: #E0B4B4; + color: #9F3A38; + box-shadow: none; +} + +/* Error Placeholder */ + +.ui.input.error input::-webkit-input-placeholder { + color: #e7bdbc; +} + +.ui.input.error input::-moz-placeholder { + color: #e7bdbc; +} + +.ui.input.error input:-ms-input-placeholder { + color: #e7bdbc !important; +} + +/* Focused Error Placeholder */ + +.ui.input.error input:focus::-webkit-input-placeholder { + color: #da9796; +} + +.ui.input.error input:focus::-moz-placeholder { + color: #da9796; +} + +.ui.input.error input:focus:-ms-input-placeholder { + color: #da9796 !important; +} + +/******************************* + Variations +*******************************/ + +/*-------------------- + Transparent +---------------------*/ + +.ui.transparent.input input { + border-color: transparent !important; + background-color: transparent !important; + padding: 0em !important; + box-shadow: none !important; +} + +/* Transparent Icon */ + +.ui.transparent.icon.input > i.icon { + width: 1.1em; +} + +.ui.transparent.icon.input > input { + padding-left: 0em !important; + padding-right: 2em !important; +} + +.ui.transparent[class*="left icon"].input > input { + padding-left: 2em !important; + padding-right: 0em !important; +} + +/* Transparent Inverted */ + +.ui.transparent.inverted.input { + color: #FFFFFF; +} + +.ui.transparent.inverted.input input { + color: inherit; +} + +.ui.transparent.inverted.input input::-webkit-input-placeholder { + color: rgba(255, 255, 255, 0.5); +} + +.ui.transparent.inverted.input input::-moz-placeholder { + color: rgba(255, 255, 255, 0.5); +} + +.ui.transparent.inverted.input input:-ms-input-placeholder { + color: rgba(255, 255, 255, 0.5); +} + +/*-------------------- + Icon +---------------------*/ + +.ui.icon.input > i.icon { + cursor: default; + position: absolute; + line-height: 1; + text-align: center; + top: 0px; + right: 0px; + margin: 0em; + height: 100%; + width: 2.67142857em; + opacity: 0.5; + border-radius: 0em 0.28571429rem 0.28571429rem 0em; + -webkit-transition: opacity 0.3s ease; + transition: opacity 0.3s ease; +} + +.ui.icon.input > i.icon:not(.link) { + pointer-events: none; +} + +.ui.icon.input input { + padding-right: 2.67142857em !important; +} + +.ui.icon.input > i.icon:before, +.ui.icon.input > i.icon:after { + left: 0; + position: absolute; + text-align: center; + top: 50%; + width: 100%; + margin-top: -0.5em; +} + +.ui.icon.input > i.link.icon { + cursor: pointer; +} + +.ui.icon.input > i.circular.icon { + top: 0.35em; + right: 0.5em; +} + +/* Left Icon Input */ + +.ui[class*="left icon"].input > i.icon { + right: auto; + left: 1px; + border-radius: 0.28571429rem 0em 0em 0.28571429rem; +} + +.ui[class*="left icon"].input > i.circular.icon { + right: auto; + left: 0.5em; +} + +.ui[class*="left icon"].input > input { + padding-left: 2.67142857em !important; + padding-right: 1em !important; +} + +/* Focus */ + +.ui.icon.input > input:focus ~ i.icon { + opacity: 1; +} + +/*-------------------- + Labeled +---------------------*/ + +/* Adjacent Label */ + +.ui.labeled.input > .label { + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + margin: 0; + font-size: 1em; +} + +.ui.labeled.input > .label:not(.corner) { + padding-top: 0.78571429em; + padding-bottom: 0.78571429em; +} + +/* Regular Label on Left */ + +.ui.labeled.input:not([class*="corner labeled"]) .label:first-child { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; +} + +.ui.labeled.input:not([class*="corner labeled"]) .label:first-child + input { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-left-color: transparent; +} + +.ui.labeled.input:not([class*="corner labeled"]) .label:first-child + input:focus { + border-left-color: #85B7D9; +} + +/* Regular Label on Right */ + +.ui[class*="right labeled"].input input { + border-top-right-radius: 0px !important; + border-bottom-right-radius: 0px !important; + border-right-color: transparent !important; +} + +.ui[class*="right labeled"].input input + .label { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +.ui[class*="right labeled"].input input:focus { + border-right-color: #85B7D9 !important; +} + +/* Corner Label */ + +.ui.labeled.input .corner.label { + top: 1px; + right: 1px; + font-size: 0.64285714em; + border-radius: 0em 0.28571429rem 0em 0em; +} + +/* Spacing with corner label */ + +.ui[class*="corner labeled"]:not([class*="left corner labeled"]).labeled.input input { + padding-right: 2.5em !important; +} + +.ui[class*="corner labeled"].icon.input:not([class*="left corner labeled"]) > input { + padding-right: 3.25em !important; +} + +.ui[class*="corner labeled"].icon.input:not([class*="left corner labeled"]) > .icon { + margin-right: 1.25em; +} + +/* Left Labeled */ + +.ui[class*="left corner labeled"].labeled.input input { + padding-left: 2.5em !important; +} + +.ui[class*="left corner labeled"].icon.input > input { + padding-left: 3.25em !important; +} + +.ui[class*="left corner labeled"].icon.input > .icon { + margin-left: 1.25em; +} + +/* Corner Label Position */ + +.ui.input > .ui.corner.label { + top: 1px; + right: 1px; +} + +.ui.input > .ui.left.corner.label { + right: auto; + left: 1px; +} + +/*-------------------- + Action +---------------------*/ + +.ui.action.input > .button, +.ui.action.input > .buttons { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} + +.ui.action.input > .button, +.ui.action.input > .buttons > .button { + padding-top: 0.78571429em; + padding-bottom: 0.78571429em; + margin: 0; +} + +/* Button on Right */ + +.ui.action.input:not([class*="left action"]) > input { + border-top-right-radius: 0px !important; + border-bottom-right-radius: 0px !important; + border-right-color: transparent !important; +} + +.ui.action.input:not([class*="left action"]) > .dropdown:not(:first-child), +.ui.action.input:not([class*="left action"]) > .button:not(:first-child), +.ui.action.input:not([class*="left action"]) > .buttons:not(:first-child) > .button { + border-radius: 0px; +} + +.ui.action.input:not([class*="left action"]) > .dropdown:last-child, +.ui.action.input:not([class*="left action"]) > .button:last-child, +.ui.action.input:not([class*="left action"]) > .buttons:last-child > .button { + border-radius: 0px 0.28571429rem 0.28571429rem 0px; +} + +/* Input Focus */ + +.ui.action.input:not([class*="left action"]) input:focus { + border-right-color: #85B7D9 !important; +} + +/* Button on Left */ + +.ui[class*="left action"].input > input { + border-top-left-radius: 0px !important; + border-bottom-left-radius: 0px !important; + border-left-color: transparent !important; +} + +.ui[class*="left action"].input > .dropdown, +.ui[class*="left action"].input > .button, +.ui[class*="left action"].input > .buttons > .button { + border-radius: 0px; +} + +.ui[class*="left action"].input > .dropdown:first-child, +.ui[class*="left action"].input > .button:first-child, +.ui[class*="left action"].input > .buttons:first-child > .button { + border-radius: 0.28571429rem 0px 0px 0.28571429rem; +} + +/* Input Focus */ + +.ui[class*="left action"].input > input:focus { + border-left-color: #85B7D9 !important; +} + +/*-------------------- + Inverted +---------------------*/ + +/* Standard */ + +.ui.inverted.input input { + border: none; +} + +/*-------------------- + Fluid +---------------------*/ + +.ui.fluid.input { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +.ui.fluid.input > input { + width: 0px !important; +} + +/*-------------------- + Size +---------------------*/ + +.ui.mini.input { + font-size: 0.78571429em; +} + +.ui.small.input { + font-size: 0.92857143em; +} + +.ui.input { + font-size: 1em; +} + +.ui.large.input { + font-size: 1.14285714em; +} + +.ui.big.input { + font-size: 1.28571429em; +} + +.ui.huge.input { + font-size: 1.42857143em; +} + +.ui.massive.input { + font-size: 1.71428571em; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Label + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Label +*******************************/ + +.ui.label { + display: inline-block; + line-height: 1; + vertical-align: baseline; + margin: 0em 0.14285714em; + background-color: #E8E8E8; + background-image: none; + padding: 0.5833em 0.833em; + color: rgba(0, 0, 0, 0.6); + text-transform: none; + font-weight: bold; + border: 0px solid transparent; + border-radius: 0.28571429rem; + -webkit-transition: background 0.1s ease; + transition: background 0.1s ease; +} + +.ui.label:first-child { + margin-left: 0em; +} + +.ui.label:last-child { + margin-right: 0em; +} + +/* Link */ + +a.ui.label { + cursor: pointer; +} + +/* Inside Link */ + +.ui.label > a { + cursor: pointer; + color: inherit; + opacity: 0.5; + -webkit-transition: 0.1s opacity ease; + transition: 0.1s opacity ease; +} + +.ui.label > a:hover { + opacity: 1; +} + +/* Image */ + +.ui.label > img { + width: auto !important; + vertical-align: middle; + height: 2.1666em !important; +} + +/* Icon */ + +.ui.label > .icon { + width: auto; + margin: 0em 0.75em 0em 0em; +} + +/* Detail */ + +.ui.label > .detail { + display: inline-block; + vertical-align: top; + font-weight: bold; + margin-left: 1em; + opacity: 0.8; +} + +.ui.label > .detail .icon { + margin: 0em 0.25em 0em 0em; +} + +/* Removable label */ + +.ui.label > .close.icon, +.ui.label > .delete.icon { + cursor: pointer; + margin-right: 0em; + margin-left: 0.5em; + font-size: 0.92857143em; + opacity: 0.5; + -webkit-transition: background 0.1s ease; + transition: background 0.1s ease; +} + +.ui.label > .delete.icon:hover { + opacity: 1; +} + +/*------------------- + Group +--------------------*/ + +.ui.labels > .label { + margin: 0em 0.5em 0.5em 0em; +} + +/*------------------- + Coupling +--------------------*/ + +.ui.header > .ui.label { + margin-top: -0.29165em; +} + +/* Remove border radius on attached segment */ + +.ui.attached.segment > .ui.top.left.attached.label, +.ui.bottom.attached.segment > .ui.top.left.attached.label { + border-top-left-radius: 0; +} + +.ui.attached.segment > .ui.top.right.attached.label, +.ui.bottom.attached.segment > .ui.top.right.attached.label { + border-top-right-radius: 0; +} + +.ui.top.attached.segment > .ui.bottom.left.attached.label { + border-bottom-left-radius: 0; +} + +.ui.top.attached.segment > .ui.bottom.right.attached.label { + border-bottom-right-radius: 0; +} + +/* Padding on next content after a label */ + +.ui.top.attached.label:first-child + :not(.attached), +.ui.top.attached.label + [class*="right floated"] + * { + margin-top: 2rem !important; +} + +.ui.bottom.attached.label:first-child ~ :last-child:not(.attached) { + margin-top: 0em; + margin-bottom: 2rem !important; +} + +/******************************* + Types +*******************************/ + +.ui.image.label { + width: auto !important; + margin-top: 0em; + margin-bottom: 0em; + max-width: 9999px; + vertical-align: baseline; + text-transform: none; + background: #E8E8E8; + padding: 0.5833em 0.833em 0.5833em 0.5em; + border-radius: 0.28571429rem; + box-shadow: none; +} + +.ui.image.label img { + display: inline-block; + vertical-align: top; + height: 2.1666em; + margin: -0.5833em 0.5em -0.5833em -0.5em; + border-radius: 0.28571429rem 0em 0em 0.28571429rem; +} + +.ui.image.label .detail { + background: rgba(0, 0, 0, 0.1); + margin: -0.5833em -0.833em -0.5833em 0.5em; + padding: 0.5833em 0.833em; + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +/*------------------- + Tag +--------------------*/ + +.ui.tag.labels .label, +.ui.tag.label { + margin-left: 1em; + position: relative; + padding-left: 1.5em; + padding-right: 1.5em; + border-radius: 0em 0.28571429rem 0.28571429rem 0em; + -webkit-transition: none; + transition: none; +} + +.ui.tag.labels .label:before, +.ui.tag.label:before { + position: absolute; + -webkit-transform: translateY(-50%) translateX(50%) rotate(-45deg); + transform: translateY(-50%) translateX(50%) rotate(-45deg); + top: 50%; + right: 100%; + content: ''; + background-color: inherit; + background-image: none; + width: 1.56em; + height: 1.56em; + -webkit-transition: none; + transition: none; +} + +.ui.tag.labels .label:after, +.ui.tag.label:after { + position: absolute; + content: ''; + top: 50%; + left: -0.25em; + margin-top: -0.25em; + background-color: #FFFFFF !important; + width: 0.5em; + height: 0.5em; + box-shadow: 0 -1px 1px 0 rgba(0, 0, 0, 0.3); + border-radius: 500rem; +} + +/*------------------- + Corner Label +--------------------*/ + +.ui.corner.label { + position: absolute; + top: 0em; + right: 0em; + margin: 0em; + padding: 0em; + text-align: center; + border-color: #E8E8E8; + width: 4em; + height: 4em; + z-index: 1; + -webkit-transition: border-color 0.1s ease; + transition: border-color 0.1s ease; +} + +/* Icon Label */ + +.ui.corner.label { + background-color: transparent !important; +} + +.ui.corner.label:after { + position: absolute; + content: ""; + right: 0em; + top: 0em; + z-index: -1; + width: 0em; + height: 0em; + background-color: transparent !important; + border-top: 0em solid transparent; + border-right: 4em solid transparent; + border-bottom: 4em solid transparent; + border-left: 0em solid transparent; + border-right-color: inherit; + -webkit-transition: border-color 0.1s ease; + transition: border-color 0.1s ease; +} + +.ui.corner.label .icon { + cursor: default; + position: relative; + top: 0.64285714em; + left: 0.78571429em; + font-size: 1.14285714em; + margin: 0em; +} + +/* Left Corner */ + +.ui.left.corner.label, +.ui.left.corner.label:after { + right: auto; + left: 0em; +} + +.ui.left.corner.label:after { + border-top: 4em solid transparent; + border-right: 4em solid transparent; + border-bottom: 0em solid transparent; + border-left: 0em solid transparent; + border-top-color: inherit; +} + +.ui.left.corner.label .icon { + left: -0.78571429em; +} + +/* Segment */ + +.ui.segment > .ui.corner.label { + top: -1px; + right: -1px; +} + +.ui.segment > .ui.left.corner.label { + right: auto; + left: -1px; +} + +/*------------------- + Ribbon +--------------------*/ + +.ui.ribbon.label { + position: relative; + margin: 0em; + min-width: -webkit-max-content; + min-width: -moz-max-content; + min-width: max-content; + border-radius: 0em 0.28571429rem 0.28571429rem 0em; + border-color: rgba(0, 0, 0, 0.15); +} + +.ui.ribbon.label:after { + position: absolute; + content: ''; + top: 100%; + left: 0%; + background-color: transparent !important; + border-style: solid; + border-width: 0em 1.2em 1.2em 0em; + border-color: transparent; + border-right-color: inherit; + width: 0em; + height: 0em; +} + +/* Positioning */ + +.ui.ribbon.label { + left: calc( -1rem - 1.2em ); + margin-right: -1.2em; + padding-left: calc( 1rem + 1.2em ); + padding-right: 1.2em; +} + +.ui[class*="right ribbon"].label { + left: calc(100% + 1rem + 1.2em ); + padding-left: 1.2em; + padding-right: calc( 1rem + 1.2em ); +} + +/* Right Ribbon */ + +.ui[class*="right ribbon"].label { + text-align: left; + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + border-radius: 0.28571429rem 0em 0em 0.28571429rem; +} + +.ui[class*="right ribbon"].label:after { + left: auto; + right: 0%; + border-style: solid; + border-width: 1.2em 1.2em 0em 0em; + border-color: transparent; + border-top-color: inherit; +} + +/* Inside Table */ + +.ui.image > .ribbon.label, +.ui.card .image > .ribbon.label { + position: absolute; + top: 1rem; +} + +.ui.card .image > .ui.ribbon.label, +.ui.image > .ui.ribbon.label { + left: calc( 0.05rem - 1.2em ); +} + +.ui.card .image > .ui[class*="right ribbon"].label, +.ui.image > .ui[class*="right ribbon"].label { + left: calc(100% + -0.05rem + 1.2em ); + padding-left: 0.833em; +} + +/* Inside Table */ + +.ui.table td > .ui.ribbon.label { + left: calc( -0.78571429em - 1.2em ); +} + +.ui.table td > .ui[class*="right ribbon"].label { + left: calc(100% + 0.78571429em + 1.2em ); + padding-left: 0.833em; +} + +/*------------------- + Attached +--------------------*/ + +.ui[class*="top attached"].label, +.ui.attached.label { + width: 100%; + position: absolute; + margin: 0em; + top: 0em; + left: 0em; + padding: 0.75em 1em; + border-radius: 0.21428571rem 0.21428571rem 0em 0em; +} + +.ui[class*="bottom attached"].label { + top: auto; + bottom: 0em; + border-radius: 0em 0em 0.21428571rem 0.21428571rem; +} + +.ui[class*="top left attached"].label { + width: auto; + margin-top: 0em !important; + border-radius: 0.21428571rem 0em 0.28571429rem 0em; +} + +.ui[class*="top right attached"].label { + width: auto; + left: auto; + right: 0em; + border-radius: 0em 0.21428571rem 0em 0.28571429rem; +} + +.ui[class*="bottom left attached"].label { + width: auto; + top: auto; + bottom: 0em; + border-radius: 0em 0.28571429rem 0em 0.21428571rem; +} + +.ui[class*="bottom right attached"].label { + top: auto; + bottom: 0em; + left: auto; + right: 0em; + width: auto; + border-radius: 0.28571429rem 0em 0.21428571rem 0em; +} + +/******************************* + States +*******************************/ + +/*------------------- + Disabled +--------------------*/ + +.ui.label.disabled { + opacity: 0.5; +} + +/*------------------- + Hover +--------------------*/ + +a.ui.labels .label:hover, +a.ui.label:hover { + background-color: #E0E0E0; + border-color: #E0E0E0; + background-image: none; + color: rgba(0, 0, 0, 0.8); +} + +.ui.labels a.label:hover:before, +a.ui.label:hover:before { + color: rgba(0, 0, 0, 0.8); +} + +/*------------------- + Active +--------------------*/ + +.ui.active.label { + background-color: #D0D0D0; + border-color: #D0D0D0; + background-image: none; + color: rgba(0, 0, 0, 0.95); +} + +.ui.active.label:before { + background-color: #D0D0D0; + background-image: none; + color: rgba(0, 0, 0, 0.95); +} + +/*------------------- + Active Hover +--------------------*/ + +a.ui.labels .active.label:hover, +a.ui.active.label:hover { + background-color: #C8C8C8; + border-color: #C8C8C8; + background-image: none; + color: rgba(0, 0, 0, 0.95); +} + +.ui.labels a.active.label:ActiveHover:before, +a.ui.active.label:ActiveHover:before { + background-color: #C8C8C8; + background-image: none; + color: rgba(0, 0, 0, 0.95); +} + +/*------------------- + Visible +--------------------*/ + +.ui.labels.visible .label, +.ui.label.visible:not(.dropdown) { + display: inline-block !important; +} + +/*------------------- + Hidden +--------------------*/ + +.ui.labels.hidden .label, +.ui.label.hidden { + display: none !important; +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Colors +--------------------*/ + +/*--- Red ---*/ + +.ui.red.labels .label, +.ui.red.label { + background-color: #DB2828 !important; + border-color: #DB2828 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.red.labels .label:hover, +a.ui.red.label:hover { + background-color: #d01919 !important; + border-color: #d01919 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.red.corner.label, +.ui.red.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.red.ribbon.label { + border-color: #b21e1e !important; +} + +/* Basic */ + +.ui.basic.red.label { + background-color: #FFFFFF !important; + color: #DB2828 !important; + border-color: #DB2828 !important; +} + +.ui.basic.red.labels a.label:hover, +a.ui.basic.red.label:hover { + background-color: #FFFFFF !important; + color: #d01919 !important; + border-color: #d01919 !important; +} + +/*--- Orange ---*/ + +.ui.orange.labels .label, +.ui.orange.label { + background-color: #F2711C !important; + border-color: #F2711C !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.orange.labels .label:hover, +a.ui.orange.label:hover { + background-color: #f26202 !important; + border-color: #f26202 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.orange.corner.label, +.ui.orange.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.orange.ribbon.label { + border-color: #cf590c !important; +} + +/* Basic */ + +.ui.basic.orange.label { + background-color: #FFFFFF !important; + color: #F2711C !important; + border-color: #F2711C !important; +} + +.ui.basic.orange.labels a.label:hover, +a.ui.basic.orange.label:hover { + background-color: #FFFFFF !important; + color: #f26202 !important; + border-color: #f26202 !important; +} + +/*--- Yellow ---*/ + +.ui.yellow.labels .label, +.ui.yellow.label { + background-color: #FBBD08 !important; + border-color: #FBBD08 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.yellow.labels .label:hover, +a.ui.yellow.label:hover { + background-color: #eaae00 !important; + border-color: #eaae00 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.yellow.corner.label, +.ui.yellow.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.yellow.ribbon.label { + border-color: #cd9903 !important; +} + +/* Basic */ + +.ui.basic.yellow.label { + background-color: #FFFFFF !important; + color: #FBBD08 !important; + border-color: #FBBD08 !important; +} + +.ui.basic.yellow.labels a.label:hover, +a.ui.basic.yellow.label:hover { + background-color: #FFFFFF !important; + color: #eaae00 !important; + border-color: #eaae00 !important; +} + +/*--- Olive ---*/ + +.ui.olive.labels .label, +.ui.olive.label { + background-color: #B5CC18 !important; + border-color: #B5CC18 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.olive.labels .label:hover, +a.ui.olive.label:hover { + background-color: #a7bd0d !important; + border-color: #a7bd0d !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.olive.corner.label, +.ui.olive.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.olive.ribbon.label { + border-color: #198f35 !important; +} + +/* Basic */ + +.ui.basic.olive.label { + background-color: #FFFFFF !important; + color: #B5CC18 !important; + border-color: #B5CC18 !important; +} + +.ui.basic.olive.labels a.label:hover, +a.ui.basic.olive.label:hover { + background-color: #FFFFFF !important; + color: #a7bd0d !important; + border-color: #a7bd0d !important; +} + +/*--- Green ---*/ + +.ui.green.labels .label, +.ui.green.label { + background-color: #21BA45 !important; + border-color: #21BA45 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.green.labels .label:hover, +a.ui.green.label:hover { + background-color: #16ab39 !important; + border-color: #16ab39 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.green.corner.label, +.ui.green.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.green.ribbon.label { + border-color: #198f35 !important; +} + +/* Basic */ + +.ui.basic.green.label { + background-color: #FFFFFF !important; + color: #21BA45 !important; + border-color: #21BA45 !important; +} + +.ui.basic.green.labels a.label:hover, +a.ui.basic.green.label:hover { + background-color: #FFFFFF !important; + color: #16ab39 !important; + border-color: #16ab39 !important; +} + +/*--- Teal ---*/ + +.ui.teal.labels .label, +.ui.teal.label { + background-color: #00B5AD !important; + border-color: #00B5AD !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.teal.labels .label:hover, +a.ui.teal.label:hover { + background-color: #009c95 !important; + border-color: #009c95 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.teal.corner.label, +.ui.teal.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.teal.ribbon.label { + border-color: #00827c !important; +} + +/* Basic */ + +.ui.basic.teal.label { + background-color: #FFFFFF !important; + color: #00B5AD !important; + border-color: #00B5AD !important; +} + +.ui.basic.teal.labels a.label:hover, +a.ui.basic.teal.label:hover { + background-color: #FFFFFF !important; + color: #009c95 !important; + border-color: #009c95 !important; +} + +/*--- Blue ---*/ + +.ui.blue.labels .label, +.ui.blue.label { + background-color: #2185D0 !important; + border-color: #2185D0 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.blue.labels .label:hover, +a.ui.blue.label:hover { + background-color: #1678c2 !important; + border-color: #1678c2 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.blue.corner.label, +.ui.blue.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.blue.ribbon.label { + border-color: #1a69a4 !important; +} + +/* Basic */ + +.ui.basic.blue.label { + background-color: #FFFFFF !important; + color: #2185D0 !important; + border-color: #2185D0 !important; +} + +.ui.basic.blue.labels a.label:hover, +a.ui.basic.blue.label:hover { + background-color: #FFFFFF !important; + color: #1678c2 !important; + border-color: #1678c2 !important; +} + +/*--- Violet ---*/ + +.ui.violet.labels .label, +.ui.violet.label { + background-color: #6435C9 !important; + border-color: #6435C9 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.violet.labels .label:hover, +a.ui.violet.label:hover { + background-color: #5829bb !important; + border-color: #5829bb !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.violet.corner.label, +.ui.violet.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.violet.ribbon.label { + border-color: #502aa1 !important; +} + +/* Basic */ + +.ui.basic.violet.label { + background-color: #FFFFFF !important; + color: #6435C9 !important; + border-color: #6435C9 !important; +} + +.ui.basic.violet.labels a.label:hover, +a.ui.basic.violet.label:hover { + background-color: #FFFFFF !important; + color: #5829bb !important; + border-color: #5829bb !important; +} + +/*--- Purple ---*/ + +.ui.purple.labels .label, +.ui.purple.label { + background-color: #A333C8 !important; + border-color: #A333C8 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.purple.labels .label:hover, +a.ui.purple.label:hover { + background-color: #9627ba !important; + border-color: #9627ba !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.purple.corner.label, +.ui.purple.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.purple.ribbon.label { + border-color: #82299f !important; +} + +/* Basic */ + +.ui.basic.purple.label { + background-color: #FFFFFF !important; + color: #A333C8 !important; + border-color: #A333C8 !important; +} + +.ui.basic.purple.labels a.label:hover, +a.ui.basic.purple.label:hover { + background-color: #FFFFFF !important; + color: #9627ba !important; + border-color: #9627ba !important; +} + +/*--- Pink ---*/ + +.ui.pink.labels .label, +.ui.pink.label { + background-color: #E03997 !important; + border-color: #E03997 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.pink.labels .label:hover, +a.ui.pink.label:hover { + background-color: #e61a8d !important; + border-color: #e61a8d !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.pink.corner.label, +.ui.pink.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.pink.ribbon.label { + border-color: #c71f7e !important; +} + +/* Basic */ + +.ui.basic.pink.label { + background-color: #FFFFFF !important; + color: #E03997 !important; + border-color: #E03997 !important; +} + +.ui.basic.pink.labels a.label:hover, +a.ui.basic.pink.label:hover { + background-color: #FFFFFF !important; + color: #e61a8d !important; + border-color: #e61a8d !important; +} + +/*--- Brown ---*/ + +.ui.brown.labels .label, +.ui.brown.label { + background-color: #A5673F !important; + border-color: #A5673F !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.brown.labels .label:hover, +a.ui.brown.label:hover { + background-color: #975b33 !important; + border-color: #975b33 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.brown.corner.label, +.ui.brown.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.brown.ribbon.label { + border-color: #805031 !important; +} + +/* Basic */ + +.ui.basic.brown.label { + background-color: #FFFFFF !important; + color: #A5673F !important; + border-color: #A5673F !important; +} + +.ui.basic.brown.labels a.label:hover, +a.ui.basic.brown.label:hover { + background-color: #FFFFFF !important; + color: #975b33 !important; + border-color: #975b33 !important; +} + +/*--- Grey ---*/ + +.ui.grey.labels .label, +.ui.grey.label { + background-color: #767676 !important; + border-color: #767676 !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.grey.labels .label:hover, +a.ui.grey.label:hover { + background-color: #838383 !important; + border-color: #838383 !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.grey.corner.label, +.ui.grey.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.grey.ribbon.label { + border-color: #805031 !important; +} + +/* Basic */ + +.ui.basic.grey.label { + background-color: #FFFFFF !important; + color: #767676 !important; + border-color: #767676 !important; +} + +.ui.basic.grey.labels a.label:hover, +a.ui.basic.grey.label:hover { + background-color: #FFFFFF !important; + color: #838383 !important; + border-color: #838383 !important; +} + +/*--- Black ---*/ + +.ui.black.labels .label, +.ui.black.label { + background-color: #1B1C1D !important; + border-color: #1B1C1D !important; + color: #FFFFFF !important; +} + +/* Link */ + +.ui.black.labels .label:hover, +a.ui.black.label:hover { + background-color: #27292a !important; + border-color: #27292a !important; + color: #FFFFFF !important; +} + +/* Corner */ + +.ui.black.corner.label, +.ui.black.corner.label:hover { + background-color: transparent !important; +} + +/* Ribbon */ + +.ui.black.ribbon.label { + border-color: #805031 !important; +} + +/* Basic */ + +.ui.basic.black.label { + background-color: #FFFFFF !important; + color: #1B1C1D !important; + border-color: #1B1C1D !important; +} + +.ui.basic.black.labels a.label:hover, +a.ui.basic.black.label:hover { + background-color: #FFFFFF !important; + color: #27292a !important; + border-color: #27292a !important; +} + +/*------------------- + Basic +--------------------*/ + +.ui.basic.label { + background: none #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + color: rgba(0, 0, 0, 0.87); + box-shadow: none; +} + +/* Link */ + +a.ui.basic.label:hover { + text-decoration: none; + background: none #FFFFFF; + color: #1e70bf; + box-shadow: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: none; +} + +/* Pointing */ + +.ui.basic.pointing.label:before { + border-color: inherit; +} + +/*------------------- + Fluid +--------------------*/ + +.ui.label.fluid, +.ui.fluid.labels > .label { + width: 100%; + box-sizing: border-box; +} + +/*------------------- + Inverted +--------------------*/ + +.ui.inverted.labels .label, +.ui.inverted.label { + color: rgba(255, 255, 255, 0.9) !important; +} + +/*------------------- + Horizontal +--------------------*/ + +.ui.horizontal.labels .label, +.ui.horizontal.label { + margin: 0em 0.5em 0em 0em; + padding: 0.4em 0.833em; + min-width: 3em; + text-align: center; +} + +/*------------------- + Circular +--------------------*/ + +.ui.circular.labels .label, +.ui.circular.label { + min-width: 2em; + min-height: 2em; + padding: 0.5em !important; + line-height: 1em; + text-align: center; + border-radius: 500rem; +} + +.ui.empty.circular.labels .label, +.ui.empty.circular.label { + min-width: 0em; + min-height: 0em; + overflow: hidden; + width: 0.5em; + height: 0.5em; + vertical-align: baseline; +} + +/*------------------- + Pointing +--------------------*/ + +.ui.pointing.label { + position: relative; +} + +.ui.attached.pointing.label { + position: absolute; +} + +.ui.pointing.label:before { + background-color: inherit; + background-image: inherit; + border-width: none; + border-style: solid; + border-color: inherit; +} + +/* Arrow */ + +.ui.pointing.label:before { + position: absolute; + content: ''; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + background-image: none; + z-index: 2; + width: 0.6666em; + height: 0.6666em; + -webkit-transition: background 0.1s ease; + transition: background 0.1s ease; +} + +/*--- Above ---*/ + +.ui.pointing.label, +.ui[class*="pointing above"].label { + margin-top: 1em; +} + +.ui.pointing.label:before, +.ui[class*="pointing above"].label:before { + border-width: 1px 0px 0px 1px; + -webkit-transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform: translateX(-50%) translateY(-50%) rotate(45deg); + top: 0%; + left: 50%; +} + +/*--- Below ---*/ + +.ui[class*="bottom pointing"].label, +.ui[class*="pointing below"].label { + margin-top: 0em; + margin-bottom: 1em; +} + +.ui[class*="bottom pointing"].label:before, +.ui[class*="pointing below"].label:before { + border-width: 0px 1px 1px 0px; + top: auto; + right: auto; + -webkit-transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform: translateX(-50%) translateY(-50%) rotate(45deg); + top: 100%; + left: 50%; +} + +/*--- Left ---*/ + +.ui[class*="left pointing"].label { + margin-top: 0em; + margin-left: 0.6666em; +} + +.ui[class*="left pointing"].label:before { + border-width: 0px 0px 1px 1px; + -webkit-transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform: translateX(-50%) translateY(-50%) rotate(45deg); + bottom: auto; + right: auto; + top: 50%; + left: 0em; +} + +/*--- Right ---*/ + +.ui[class*="right pointing"].label { + margin-top: 0em; + margin-right: 0.6666em; +} + +.ui[class*="right pointing"].label:before { + border-width: 1px 1px 0px 0px; + -webkit-transform: translateX(50%) translateY(-50%) rotate(45deg); + transform: translateX(50%) translateY(-50%) rotate(45deg); + top: 50%; + right: 0%; + bottom: auto; + left: auto; +} + +/* Basic Pointing */ + +/*--- Above ---*/ + +.ui.basic.pointing.label:before, +.ui.basic[class*="pointing above"].label:before { + margin-top: -1px; +} + +/*--- Below ---*/ + +.ui.basic[class*="bottom pointing"].label:before, +.ui.basic[class*="pointing below"].label:before { + bottom: auto; + top: 100%; + margin-top: 1px; +} + +/*--- Left ---*/ + +.ui.basic[class*="left pointing"].label:before { + top: 50%; + left: -1px; +} + +/*--- Right ---*/ + +.ui.basic[class*="right pointing"].label:before { + top: 50%; + right: -1px; +} + +/*------------------ + Floating Label +-------------------*/ + +.ui.floating.label { + position: absolute; + z-index: 100; + top: -1em; + left: 100%; + margin: 0em 0em 0em -1.5em !important; +} + +/*------------------- + Sizes +--------------------*/ + +.ui.mini.labels .label, +.ui.mini.label { + font-size: 0.64285714rem; +} + +.ui.tiny.labels .label, +.ui.tiny.label { + font-size: 0.71428571rem; +} + +.ui.small.labels .label, +.ui.small.label { + font-size: 0.78571429rem; +} + +.ui.labels .label, +.ui.label { + font-size: 0.85714286rem; +} + +.ui.large.labels .label, +.ui.large.label { + font-size: 1rem; +} + +.ui.big.labels .label, +.ui.big.label { + font-size: 1.28571429rem; +} + +.ui.huge.labels .label, +.ui.huge.label { + font-size: 1.42857143rem; +} + +.ui.massive.labels .label, +.ui.massive.label { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - List + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + List +*******************************/ + +ul.ui.list, +ol.ui.list, +.ui.list { + list-style-type: none; + margin: 1em 0em; + padding: 0em 0em; +} + +ul.ui.list:first-child, +ol.ui.list:first-child, +.ui.list:first-child { + margin-top: 0em; + padding-top: 0em; +} + +ul.ui.list:last-child, +ol.ui.list:last-child, +.ui.list:last-child { + margin-bottom: 0em; + padding-bottom: 0em; +} + +/******************************* + Content +*******************************/ + +/* List Item */ + +ul.ui.list li, +ol.ui.list li, +.ui.list > .item, +.ui.list .list > .item { + display: list-item; + table-layout: fixed; + list-style-type: none; + list-style-position: outside; + padding: 0.21428571em 0em; + line-height: 1.14285714em; +} + +ul.ui.list > li:first-child:after, +ol.ui.list > li:first-child:after, +.ui.list > .list > .item, +.ui.list > .item:after { + content: ''; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +ul.ui.list li:first-child, +ol.ui.list li:first-child, +.ui.list .list > .item:first-child, +.ui.list > .item:first-child { + padding-top: 0em; +} + +ul.ui.list li:last-child, +ol.ui.list li:last-child, +.ui.list .list > .item:last-child, +.ui.list > .item:last-child { + padding-bottom: 0em; +} + +/* Child List */ + +ul.ui.list ul, +ol.ui.list ol, +.ui.list .list { + clear: both; + margin: 0em; + padding: 0.75em 0em 0.25em 0.5em; +} + +/* Child Item */ + +ul.ui.list ul li, +ol.ui.list ol li, +.ui.list .list > .item { + padding: 0.14285714em 0em; + line-height: inherit; +} + +/* Icon */ + +.ui.list .list > .item > i.icon, +.ui.list > .item > i.icon { + display: table-cell; + margin: 0em; + padding-top: 0.07142857em; + padding-right: 0.28571429em; + vertical-align: top; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.list .list > .item > i.icon:only-child, +.ui.list > .item > i.icon:only-child { + display: inline-block; + vertical-align: top; +} + +/* Image */ + +.ui.list .list > .item > .image, +.ui.list > .item > .image { + display: table-cell; + background-color: transparent; + margin: 0em; + vertical-align: top; +} + +.ui.list .list > .item > .image:not(:only-child):not(img), +.ui.list > .item > .image:not(:only-child):not(img) { + padding-right: 0.5em; +} + +.ui.list .list > .item > .image img, +.ui.list > .item > .image img { + vertical-align: top; +} + +.ui.list .list > .item > img.image, +.ui.list .list > .item > .image:only-child, +.ui.list > .item > img.image, +.ui.list > .item > .image:only-child { + display: inline-block; +} + +/* Content */ + +.ui.list .list > .item > .content, +.ui.list > .item > .content { + line-height: 1.14285714em; +} + +.ui.list .list > .item > .image + .content, +.ui.list .list > .item > .icon + .content, +.ui.list > .item > .image + .content, +.ui.list > .item > .icon + .content { + display: table-cell; + padding: 0em 0em 0em 0.5em; + vertical-align: top; +} + +.ui.list .list > .item > img.image + .content, +.ui.list > .item > img.image + .content { + display: inline-block; +} + +.ui.list .list > .item > .content > .list, +.ui.list > .item > .content > .list { + margin-left: 0em; + padding-left: 0em; +} + +/* Header */ + +.ui.list .list > .item .header, +.ui.list > .item .header { + display: block; + margin: 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-weight: bold; + color: rgba(0, 0, 0, 0.87); +} + +/* Description */ + +.ui.list .list > .item .description, +.ui.list > .item .description { + display: block; + color: rgba(0, 0, 0, 0.7); +} + +/* Child Link */ + +.ui.list > .item a, +.ui.list .list > .item a { + cursor: pointer; +} + +/* Linking Item */ + +.ui.list .list > a.item, +.ui.list > a.item { + cursor: pointer; + color: #4183C4; +} + +.ui.list .list > a.item:hover, +.ui.list > a.item:hover { + color: #1e70bf; +} + +/* Linked Item Icons */ + +.ui.list .list > a.item i.icon, +.ui.list > a.item i.icon { + color: rgba(0, 0, 0, 0.4); +} + +/* Header Link */ + +.ui.list .list > .item a.header, +.ui.list > .item a.header { + cursor: pointer; + color: #4183C4 !important; +} + +.ui.list .list > .item a.header:hover, +.ui.list > .item a.header:hover { + color: #1e70bf !important; +} + +/* Floated Content */ + +.ui[class*="left floated"].list { + float: left; +} + +.ui[class*="right floated"].list { + float: right; +} + +.ui.list .list > .item [class*="left floated"], +.ui.list > .item [class*="left floated"] { + float: left; + margin: 0em 1em 0em 0em; +} + +.ui.list .list > .item [class*="right floated"], +.ui.list > .item [class*="right floated"] { + float: right; + margin: 0em 0em 0em 1em; +} + +/******************************* + Coupling +*******************************/ + +.ui.menu .ui.list > .item, +.ui.menu .ui.list .list > .item { + display: list-item; + table-layout: fixed; + background-color: transparent; + list-style-type: none; + list-style-position: outside; + padding: 0.21428571em 0em; + line-height: 1.14285714em; +} + +.ui.menu .ui.list .list > .item:before, +.ui.menu .ui.list > .item:before { + border: none; + background: none; +} + +.ui.menu .ui.list .list > .item:first-child, +.ui.menu .ui.list > .item:first-child { + padding-top: 0em; +} + +.ui.menu .ui.list .list > .item:last-child, +.ui.menu .ui.list > .item:last-child { + padding-bottom: 0em; +} + +/******************************* + Types +*******************************/ + +/*------------------- + Horizontal +--------------------*/ + +.ui.horizontal.list { + display: inline-block; + font-size: 0em; +} + +.ui.horizontal.list > .item { + display: inline-block; + margin-left: 1em; + font-size: 1rem; +} + +.ui.horizontal.list:not(.celled) > .item:first-child { + margin-left: 0em !important; + padding-left: 0em !important; +} + +.ui.horizontal.list .list { + padding-left: 0em; + padding-bottom: 0em; +} + +.ui.horizontal.list > .item > .image, +.ui.horizontal.list .list > .item > .image, +.ui.horizontal.list > .item > .icon, +.ui.horizontal.list .list > .item > .icon, +.ui.horizontal.list > .item > .content, +.ui.horizontal.list .list > .item > .content { + vertical-align: middle; +} + +/* Padding on all elements */ + +.ui.horizontal.list > .item:first-child, +.ui.horizontal.list > .item:last-child { + padding-top: 0.21428571em; + padding-bottom: 0.21428571em; +} + +/* Horizontal List */ + +.ui.horizontal.list > .item > i.icon { + margin: 0em; + padding: 0em 0.25em 0em 0em; +} + +.ui.horizontal.list > .item > .icon, +.ui.horizontal.list > .item > .icon + .content { + float: none; + display: inline-block; +} + +/******************************* + States +*******************************/ + +/*------------------- + Disabled +--------------------*/ + +.ui.list .list > .disabled.item, +.ui.list > .disabled.item { + pointer-events: none; + color: rgba(40, 40, 40, 0.3) !important; +} + +.ui.inverted.list .list > .disabled.item, +.ui.inverted.list > .disabled.item { + color: rgba(225, 225, 225, 0.3) !important; +} + +/*------------------- + Hover +--------------------*/ + +.ui.list .list > a.item:hover .icon, +.ui.list > a.item:hover .icon { + color: rgba(0, 0, 0, 0.87); +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Inverted +--------------------*/ + +.ui.inverted.list .list > a.item > .icon, +.ui.inverted.list > a.item > .icon { + color: rgba(255, 255, 255, 0.7); +} + +.ui.inverted.list .list > .item .header, +.ui.inverted.list > .item .header { + color: rgba(255, 255, 255, 0.9); +} + +.ui.inverted.list .list > .item .description, +.ui.inverted.list > .item .description { + color: rgba(255, 255, 255, 0.7); +} + +/* Item Link */ + +.ui.inverted.list .list > a.item, +.ui.inverted.list > a.item { + cursor: pointer; + color: rgba(255, 255, 255, 0.9); +} + +.ui.inverted.list .list > a.item:hover, +.ui.inverted.list > a.item:hover { + color: #1e70bf; +} + +/* Linking Content */ + +.ui.inverted.list .item a:not(.ui) { + color: rgba(255, 255, 255, 0.9) !important; +} + +.ui.inverted.list .item a:not(.ui):hover { + color: #1e70bf !important; +} + +/*------------------- + Aligned +--------------------*/ + +.ui.list[class*="top aligned"] .image, +.ui.list[class*="top aligned"] .content, +.ui.list [class*="top aligned"] { + vertical-align: top !important; +} + +.ui.list[class*="middle aligned"] .image, +.ui.list[class*="middle aligned"] .content, +.ui.list [class*="middle aligned"] { + vertical-align: middle !important; +} + +.ui.list[class*="bottom aligned"] .image, +.ui.list[class*="bottom aligned"] .content, +.ui.list [class*="bottom aligned"] { + vertical-align: bottom !important; +} + +/*------------------- + Link +--------------------*/ + +.ui.link.list .item, +.ui.link.list a.item, +.ui.link.list .item a:not(.ui) { + color: rgba(0, 0, 0, 0.4); + -webkit-transition: 0.1s color ease; + transition: 0.1s color ease; +} + +.ui.link.list a.item:hover, +.ui.link.list .item a:not(.ui):hover { + color: rgba(0, 0, 0, 0.8); +} + +.ui.link.list a.item:active, +.ui.link.list .item a:not(.ui):active { + color: rgba(0, 0, 0, 0.9); +} + +.ui.link.list .active.item, +.ui.link.list .active.item a:not(.ui) { + color: rgba(0, 0, 0, 0.95); +} + +/* Inverted */ + +.ui.inverted.link.list .item, +.ui.inverted.link.list a.item, +.ui.inverted.link.list .item a:not(.ui) { + color: rgba(255, 255, 255, 0.5); +} + +.ui.inverted.link.list a.item:hover, +.ui.inverted.link.list .item a:not(.ui):hover { + color: #ffffff; +} + +.ui.inverted.link.list a.item:active, +.ui.inverted.link.list .item a:not(.ui):active { + color: #ffffff; +} + +.ui.inverted.link.list a.active.item, +.ui.inverted.link.list .active.item a:not(.ui) { + color: #ffffff; +} + +/*------------------- + Selection +--------------------*/ + +.ui.selection.list .list > .item, +.ui.selection.list > .item { + cursor: pointer; + background: transparent; + padding: 0.5em 0.5em; + margin: 0em; + color: rgba(0, 0, 0, 0.4); + border-radius: 0.5em; + -webkit-transition: 0.1s color ease, 0.1s padding-left ease, 0.1s background-color ease; + transition: 0.1s color ease, 0.1s padding-left ease, 0.1s background-color ease; +} + +.ui.selection.list .list > .item:last-child, +.ui.selection.list > .item:last-child { + margin-bottom: 0em; +} + +.ui.selection.list.list > .item:hover, +.ui.selection.list > .item:hover { + background: rgba(0, 0, 0, 0.03); + color: rgba(0, 0, 0, 0.8); +} + +.ui.selection.list .list > .item:active, +.ui.selection.list > .item:active { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.9); +} + +.ui.selection.list .list > .item.active, +.ui.selection.list > .item.active { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); +} + +/* Inverted */ + +.ui.inverted.selection.list > .item, +.ui.inverted.selection.list > .item { + background: transparent; + color: rgba(255, 255, 255, 0.5); +} + +.ui.inverted.selection.list > .item:hover, +.ui.inverted.selection.list > .item:hover { + background: rgba(255, 255, 255, 0.02); + color: #ffffff; +} + +.ui.inverted.selection.list > .item:active, +.ui.inverted.selection.list > .item:active { + background: rgba(255, 255, 255, 0.08); + color: #ffffff; +} + +.ui.inverted.selection.list > .item.active, +.ui.inverted.selection.list > .item.active { + background: rgba(255, 255, 255, 0.08); + color: #ffffff; +} + +/* Celled / Divided Selection List */ + +.ui.celled.selection.list .list > .item, +.ui.divided.selection.list .list > .item, +.ui.celled.selection.list > .item, +.ui.divided.selection.list > .item { + border-radius: 0em; +} + +/*------------------- + Animated +--------------------*/ + +.ui.animated.list > .item { + -webkit-transition: 0.25s color ease 0.1s, 0.25s padding-left ease 0.1s, 0.25s background-color ease 0.1s; + transition: 0.25s color ease 0.1s, 0.25s padding-left ease 0.1s, 0.25s background-color ease 0.1s; +} + +.ui.animated.list:not(.horizontal) > .item:hover { + padding-left: 1em; +} + +/*------------------- + Fitted +--------------------*/ + +.ui.fitted.list:not(.selection) .list > .item, +.ui.fitted.list:not(.selection) > .item { + padding-left: 0em; + padding-right: 0em; +} + +.ui.fitted.selection.list .list > .item, +.ui.fitted.selection.list > .item { + margin-left: -0.5em; + margin-right: -0.5em; +} + +/*------------------- + Bulleted +--------------------*/ + +ul.ui.list, +.ui.bulleted.list { + margin-left: 1.25rem; +} + +ul.ui.list li, +.ui.bulleted.list .list > .item, +.ui.bulleted.list > .item { + position: relative; +} + +ul.ui.list li:before, +.ui.bulleted.list .list > .item:before, +.ui.bulleted.list > .item:before { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + position: absolute; + top: auto; + left: auto; + font-weight: normal; + margin-left: -1.25rem; + content: '•'; + opacity: 1; + color: inherit; + vertical-align: top; +} + +ul.ui.list li:before, +.ui.bulleted.list .list > a.item:before, +.ui.bulleted.list > a.item:before { + color: rgba(0, 0, 0, 0.87); +} + +ul.ui.list ul, +.ui.bulleted.list .list { + padding-left: 1.25rem; +} + +/* Horizontal Bulleted */ + +ul.ui.horizontal.bulleted.list, +.ui.horizontal.bulleted.list { + margin-left: 0em; +} + +ul.ui.horizontal.bulleted.list li, +.ui.horizontal.bulleted.list > .item { + margin-left: 1.75rem; +} + +ul.ui.horizontal.bulleted.list li:first-child, +.ui.horizontal.bulleted.list > .item:first-child { + margin-left: 0em; +} + +ul.ui.horizontal.bulleted.list li::before, +.ui.horizontal.bulleted.list > .item::before { + color: rgba(0, 0, 0, 0.87); +} + +ul.ui.horizontal.bulleted.list li:first-child::before, +.ui.horizontal.bulleted.list > .item:first-child::before { + display: none; +} + +/*------------------- + Ordered +--------------------*/ + +ol.ui.list, +.ui.ordered.list, +.ui.ordered.list .list, +ol.ui.list ol { + counter-reset: ordered; + margin-left: 1.25rem; + list-style-type: none; +} + +ol.ui.list li, +.ui.ordered.list .list > .item, +.ui.ordered.list > .item { + list-style-type: none; + position: relative; +} + +ol.ui.list li:before, +.ui.ordered.list .list > .item:before, +.ui.ordered.list > .item:before { + position: absolute; + top: auto; + left: auto; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + margin-left: -1.25rem; + counter-increment: ordered; + content: counters(ordered, ".") " "; + text-align: right; + color: rgba(0, 0, 0, 0.87); + vertical-align: middle; + opacity: 0.8; +} + +ol.ui.inverted.list li:before, +.ui.ordered.inverted.list .list > .item:before, +.ui.ordered.inverted.list > .item:before { + color: rgba(255, 255, 255, 0.7); +} + +/* Value */ + +.ui.ordered.list > .list > .item[data-value], +.ui.ordered.list > .item[data-value] { + content: attr(data-value); +} + +ol.ui.list li[value]:before { + content: attr(value); +} + +/* Child Lists */ + +ol.ui.list ol, +.ui.ordered.list .list { + margin-left: 1em; +} + +ol.ui.list ol li:before, +.ui.ordered.list .list > .item:before { + margin-left: -2em; +} + +/* Horizontal Ordered */ + +ol.ui.horizontal.list, +.ui.ordered.horizontal.list { + margin-left: 0em; +} + +ol.ui.horizontal.list li:before, +.ui.ordered.horizontal.list .list > .item:before, +.ui.ordered.horizontal.list > .item:before { + position: static; + margin: 0em 0.5em 0em 0em; +} + +/*------------------- + Divided +--------------------*/ + +.ui.divided.list > .item { + border-top: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.divided.list .list > .item { + border-top: none; +} + +.ui.divided.list .item .list > .item { + border-top: none; +} + +.ui.divided.list .list > .item:first-child, +.ui.divided.list > .item:first-child { + border-top: none; +} + +/* Sub Menu */ + +.ui.divided.list:not(.horizontal) .list > .item:first-child { + border-top-width: 1px; +} + +/* Divided bulleted */ + +.ui.divided.bulleted.list:not(.horizontal), +.ui.divided.bulleted.list .list { + margin-left: 0em; + padding-left: 0em; +} + +.ui.divided.bulleted.list > .item:not(.horizontal) { + padding-left: 1.25rem; +} + +/* Divided Ordered */ + +.ui.divided.ordered.list { + margin-left: 0em; +} + +.ui.divided.ordered.list .list > .item, +.ui.divided.ordered.list > .item { + padding-left: 1.25rem; +} + +.ui.divided.ordered.list .item .list { + margin-left: 0em; + margin-right: 0em; + padding-bottom: 0.21428571em; +} + +.ui.divided.ordered.list .item .list > .item { + padding-left: 1em; +} + +/* Divided Selection */ + +.ui.divided.selection.list .list > .item, +.ui.divided.selection.list > .item { + margin: 0em; + border-radius: 0em; +} + +/* Divided horizontal */ + +.ui.divided.horizontal.list { + margin-left: 0em; +} + +.ui.divided.horizontal.list > .item:not(:first-child) { + padding-left: 0.5em; +} + +.ui.divided.horizontal.list > .item:not(:last-child) { + padding-right: 0.5em; +} + +.ui.divided.horizontal.list > .item { + border-top: none; + border-left: 1px solid rgba(34, 36, 38, 0.15); + margin: 0em; + line-height: 0.6; +} + +.ui.horizontal.divided.list > .item:first-child { + border-left: none; +} + +/* Inverted */ + +.ui.divided.inverted.list > .item, +.ui.divided.inverted.list > .list, +.ui.divided.inverted.horizontal.list > .item { + border-color: rgba(255, 255, 255, 0.1); +} + +/*------------------- + Celled +--------------------*/ + +.ui.celled.list > .item, +.ui.celled.list > .list { + border-top: 1px solid rgba(34, 36, 38, 0.15); + padding-left: 0.5em; + padding-right: 0.5em; +} + +.ui.celled.list > .item:last-child { + border-bottom: 1px solid rgba(34, 36, 38, 0.15); +} + +/* Padding on all elements */ + +.ui.celled.list > .item:first-child, +.ui.celled.list > .item:last-child { + padding-top: 0.21428571em; + padding-bottom: 0.21428571em; +} + +/* Sub Menu */ + +.ui.celled.list .item .list > .item { + border-width: 0px; +} + +.ui.celled.list .list > .item:first-child { + border-top-width: 0px; +} + +/* Celled Bulleted */ + +.ui.celled.bulleted.list { + margin-left: 0em; +} + +.ui.celled.bulleted.list .list > .item, +.ui.celled.bulleted.list > .item { + padding-left: 1.25rem; +} + +.ui.celled.bulleted.list .item .list { + margin-left: -1.25rem; + margin-right: -1.25rem; + padding-bottom: 0.21428571em; +} + +/* Celled Ordered */ + +.ui.celled.ordered.list { + margin-left: 0em; +} + +.ui.celled.ordered.list .list > .item, +.ui.celled.ordered.list > .item { + padding-left: 1.25rem; +} + +.ui.celled.ordered.list .item .list { + margin-left: 0em; + margin-right: 0em; + padding-bottom: 0.21428571em; +} + +.ui.celled.ordered.list .list > .item { + padding-left: 1em; +} + +/* Celled Horizontal */ + +.ui.horizontal.celled.list { + margin-left: 0em; +} + +.ui.horizontal.celled.list .list > .item, +.ui.horizontal.celled.list > .item { + border-top: none; + border-left: 1px solid rgba(34, 36, 38, 0.15); + margin: 0em; + padding-left: 0.5em; + padding-right: 0.5em; + line-height: 0.6; +} + +.ui.horizontal.celled.list .list > .item:last-child, +.ui.horizontal.celled.list > .item:last-child { + border-bottom: none; + border-right: 1px solid rgba(34, 36, 38, 0.15); +} + +/* Inverted */ + +.ui.celled.inverted.list > .item, +.ui.celled.inverted.list > .list { + border-color: 1px solid rgba(255, 255, 255, 0.1); +} + +.ui.celled.inverted.horizontal.list .list > .item, +.ui.celled.inverted.horizontal.list > .item { + border-color: 1px solid rgba(255, 255, 255, 0.1); +} + +/*------------------- + Relaxed +--------------------*/ + +.ui.relaxed.list:not(.horizontal) > .item:not(:first-child) { + padding-top: 0.42857143em; +} + +.ui.relaxed.list:not(.horizontal) > .item:not(:last-child) { + padding-bottom: 0.42857143em; +} + +.ui.horizontal.relaxed.list .list > .item:not(:first-child), +.ui.horizontal.relaxed.list > .item:not(:first-child) { + padding-left: 1rem; +} + +.ui.horizontal.relaxed.list .list > .item:not(:last-child), +.ui.horizontal.relaxed.list > .item:not(:last-child) { + padding-right: 1rem; +} + +/* Very Relaxed */ + +.ui[class*="very relaxed"].list:not(.horizontal) > .item:not(:first-child) { + padding-top: 0.85714286em; +} + +.ui[class*="very relaxed"].list:not(.horizontal) > .item:not(:last-child) { + padding-bottom: 0.85714286em; +} + +.ui.horizontal[class*="very relaxed"].list .list > .item:not(:first-child), +.ui.horizontal[class*="very relaxed"].list > .item:not(:first-child) { + padding-left: 1.5rem; +} + +.ui.horizontal[class*="very relaxed"].list .list > .item:not(:last-child), +.ui.horizontal[class*="very relaxed"].list > .item:not(:last-child) { + padding-right: 1.5rem; +} + +/*------------------- + Sizes +--------------------*/ + +.ui.mini.list { + font-size: 0.78571429em; +} + +.ui.tiny.list { + font-size: 0.85714286em; +} + +.ui.small.list { + font-size: 0.92857143em; +} + +.ui.list { + font-size: 1em; +} + +.ui.large.list { + font-size: 1.14285714em; +} + +.ui.big.list { + font-size: 1.28571429em; +} + +.ui.huge.list { + font-size: 1.42857143em; +} + +.ui.massive.list { + font-size: 1.71428571em; +} + +.ui.mini.horizontal.list .list > .item, +.ui.mini.horizontal.list > .item { + font-size: 0.78571429rem; +} + +.ui.tiny.horizontal.list .list > .item, +.ui.tiny.horizontal.list > .item { + font-size: 0.85714286rem; +} + +.ui.small.horizontal.list .list > .item, +.ui.small.horizontal.list > .item { + font-size: 0.92857143rem; +} + +.ui.horizontal.list .list > .item, +.ui.horizontal.list > .item { + font-size: 1rem; +} + +.ui.large.horizontal.list .list > .item, +.ui.large.horizontal.list > .item { + font-size: 1.14285714rem; +} + +.ui.big.horizontal.list .list > .item, +.ui.big.horizontal.list > .item { + font-size: 1.28571429rem; +} + +.ui.huge.horizontal.list .list > .item, +.ui.huge.horizontal.list > .item { + font-size: 1.42857143rem; +} + +.ui.massive.horizontal.list .list > .item, +.ui.massive.horizontal.list > .item { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Loader + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Loader +*******************************/ + +/* Standard Size */ + +.ui.loader { + display: none; + position: absolute; + top: 50%; + left: 50%; + margin: 0px; + text-align: center; + z-index: 1000; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); +} + +/* Static Shape */ + +.ui.loader:before { + position: absolute; + content: ''; + top: 0%; + left: 50%; + width: 100%; + height: 100%; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.1); +} + +/* Active Shape */ + +.ui.loader:after { + position: absolute; + content: ''; + top: 0%; + left: 50%; + width: 100%; + height: 100%; + -webkit-animation: loader 0.6s linear; + animation: loader 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 transparent transparent; + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; +} + +/* Active Animation */ + +@-webkit-keyframes loader { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes loader { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/* Sizes */ + +.ui.mini.loader:before, +.ui.mini.loader:after { + width: 1rem; + height: 1rem; + margin: 0em 0em 0em -0.5rem; +} + +.ui.tiny.loader:before, +.ui.tiny.loader:after { + width: 1.14285714rem; + height: 1.14285714rem; + margin: 0em 0em 0em -0.57142857rem; +} + +.ui.small.loader:before, +.ui.small.loader:after { + width: 1.71428571rem; + height: 1.71428571rem; + margin: 0em 0em 0em -0.85714286rem; +} + +.ui.loader:before, +.ui.loader:after { + width: 2.28571429rem; + height: 2.28571429rem; + margin: 0em 0em 0em -1.14285714rem; +} + +.ui.large.loader:before, +.ui.large.loader:after { + width: 3.42857143rem; + height: 3.42857143rem; + margin: 0em 0em 0em -1.71428571rem; +} + +.ui.big.loader:before, +.ui.big.loader:after { + width: 3.71428571rem; + height: 3.71428571rem; + margin: 0em 0em 0em -1.85714286rem; +} + +.ui.huge.loader:before, +.ui.huge.loader:after { + width: 4.14285714rem; + height: 4.14285714rem; + margin: 0em 0em 0em -2.07142857rem; +} + +.ui.massive.loader:before, +.ui.massive.loader:after { + width: 4.57142857rem; + height: 4.57142857rem; + margin: 0em 0em 0em -2.28571429rem; +} + +/*------------------- + Coupling +--------------------*/ + +/* Show inside active dimmer */ + +.ui.dimmer .loader { + display: block; +} + +/* Black Dimmer */ + +.ui.dimmer .ui.loader { + color: rgba(255, 255, 255, 0.9); +} + +.ui.dimmer .ui.loader:before { + border-color: rgba(255, 255, 255, 0.15); +} + +.ui.dimmer .ui.loader:after { + border-color: #FFFFFF transparent transparent; +} + +/* White Dimmer (Inverted) */ + +.ui.inverted.dimmer .ui.loader { + color: rgba(0, 0, 0, 0.87); +} + +.ui.inverted.dimmer .ui.loader:before { + border-color: rgba(0, 0, 0, 0.1); +} + +.ui.inverted.dimmer .ui.loader:after { + border-color: #767676 transparent transparent; +} + +/******************************* + Types +*******************************/ + +/*------------------- + Text +--------------------*/ + +.ui.text.loader { + width: auto !important; + height: auto !important; + text-align: center; + font-style: normal; +} + +/******************************* + States +*******************************/ + +.ui.indeterminate.loader:after { + -webkit-animation-direction: reverse; + animation-direction: reverse; + -webkit-animation-duration: 1.2s; + animation-duration: 1.2s; +} + +.ui.loader.active, +.ui.loader.visible { + display: block; +} + +.ui.loader.disabled, +.ui.loader.hidden { + display: none; +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Sizes +--------------------*/ + +/* Loader */ + +.ui.inverted.dimmer .ui.mini.loader, +.ui.mini.loader { + width: 1rem; + height: 1rem; + font-size: 0.78571429em; +} + +.ui.inverted.dimmer .ui.tiny.loader, +.ui.tiny.loader { + width: 1.14285714rem; + height: 1.14285714rem; + font-size: 0.85714286em; +} + +.ui.inverted.dimmer .ui.small.loader, +.ui.small.loader { + width: 1.71428571rem; + height: 1.71428571rem; + font-size: 0.92857143em; +} + +.ui.inverted.dimmer .ui.loader, +.ui.loader { + width: 2.28571429rem; + height: 2.28571429rem; + font-size: 1em; +} + +.ui.inverted.dimmer .ui.large.loader, +.ui.large.loader { + width: 3.42857143rem; + height: 3.42857143rem; + font-size: 1.14285714em; +} + +.ui.inverted.dimmer .ui.big.loader, +.ui.big.loader { + width: 3.71428571rem; + height: 3.71428571rem; + font-size: 1.28571429em; +} + +.ui.inverted.dimmer .ui.huge.loader, +.ui.huge.loader { + width: 4.14285714rem; + height: 4.14285714rem; + font-size: 1.42857143em; +} + +.ui.inverted.dimmer .ui.massive.loader, +.ui.massive.loader { + width: 4.57142857rem; + height: 4.57142857rem; + font-size: 1.71428571em; +} + +/* Text Loader */ + +.ui.mini.text.loader { + min-width: 1rem; + padding-top: 1.78571429rem; +} + +.ui.tiny.text.loader { + min-width: 1.14285714rem; + padding-top: 1.92857143rem; +} + +.ui.small.text.loader { + min-width: 1.71428571rem; + padding-top: 2.5rem; +} + +.ui.text.loader { + min-width: 2.28571429rem; + padding-top: 3.07142857rem; +} + +.ui.large.text.loader { + min-width: 3.42857143rem; + padding-top: 4.21428571rem; +} + +.ui.big.text.loader { + min-width: 3.71428571rem; + padding-top: 4.5rem; +} + +.ui.huge.text.loader { + min-width: 4.14285714rem; + padding-top: 4.92857143rem; +} + +.ui.massive.text.loader { + min-width: 4.57142857rem; + padding-top: 5.35714286rem; +} + +/*------------------- + Inverted +--------------------*/ + +.ui.inverted.loader { + color: rgba(255, 255, 255, 0.9); +} + +.ui.inverted.loader:before { + border-color: rgba(255, 255, 255, 0.15); +} + +.ui.inverted.loader:after { + border-top-color: #FFFFFF; +} + +/*------------------- + Inline +--------------------*/ + +.ui.inline.loader { + position: relative; + vertical-align: middle; + margin: 0em; + left: 0em; + top: 0em; + -webkit-transform: none; + transform: none; +} + +.ui.inline.loader.active, +.ui.inline.loader.visible { + display: inline-block; +} + +/* Centered Inline */ + +.ui.centered.inline.loader.active, +.ui.centered.inline.loader.visible { + display: block; + margin-left: auto; + margin-right: auto; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Rail + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Rails +*******************************/ + +.ui.rail { + position: absolute; + top: 0%; + width: 300px; + height: 100%; +} + +.ui.left.rail { + left: auto; + right: 100%; + padding: 0em 2rem 0em 0em; + margin: 0em 2rem 0em 0em; +} + +.ui.right.rail { + left: 100%; + right: auto; + padding: 0em 0em 0em 2rem; + margin: 0em 0em 0em 2rem; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Internal +---------------*/ + +.ui.left.internal.rail { + left: 0%; + right: auto; + padding: 0em 0em 0em 2rem; + margin: 0em 0em 0em 2rem; +} + +.ui.right.internal.rail { + left: auto; + right: 0%; + padding: 0em 2rem 0em 0em; + margin: 0em 2rem 0em 0em; +} + +/*-------------- + Dividing +---------------*/ + +.ui.dividing.rail { + width: 302.5px; +} + +.ui.left.dividing.rail { + padding: 0em 2.5rem 0em 0em; + margin: 0em 2.5rem 0em 0em; + border-right: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.right.dividing.rail { + border-left: 1px solid rgba(34, 36, 38, 0.15); + padding: 0em 0em 0em 2.5rem; + margin: 0em 0em 0em 2.5rem; +} + +/*-------------- + Distance +---------------*/ + +.ui.close.rail { + width: calc( 300px + 1em ); +} + +.ui.close.left.rail { + padding: 0em 1em 0em 0em; + margin: 0em 1em 0em 0em; +} + +.ui.close.right.rail { + padding: 0em 0em 0em 1em; + margin: 0em 0em 0em 1em; +} + +.ui.very.close.rail { + width: calc( 300px + 0.5em ); +} + +.ui.very.close.left.rail { + padding: 0em 0.5em 0em 0em; + margin: 0em 0.5em 0em 0em; +} + +.ui.very.close.right.rail { + padding: 0em 0em 0em 0.5em; + margin: 0em 0em 0em 0.5em; +} + +/*-------------- + Attached +---------------*/ + +.ui.attached.left.rail, +.ui.attached.right.rail { + padding: 0em; + margin: 0em; +} + +/*-------------- + Sizing +---------------*/ + +.ui.mini.rail { + font-size: 0.78571429rem; +} + +.ui.tiny.rail { + font-size: 0.85714286rem; +} + +.ui.small.rail { + font-size: 0.92857143rem; +} + +.ui.rail { + font-size: 1rem; +} + +.ui.large.rail { + font-size: 1.14285714rem; +} + +.ui.big.rail { + font-size: 1.28571429rem; +} + +.ui.huge.rail { + font-size: 1.42857143rem; +} + +.ui.massive.rail { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Reveal + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Reveal +*******************************/ + +.ui.reveal { + display: inherit; + position: relative !important; + font-size: 0em !important; +} + +.ui.reveal > .visible.content { + position: absolute !important; + top: 0em !important; + left: 0em !important; + z-index: 3 !important; + -webkit-transition: all 0.5s ease 0.1s; + transition: all 0.5s ease 0.1s; +} + +.ui.reveal > .hidden.content { + position: relative !important; + z-index: 2 !important; +} + +/* Make sure hovered element is on top of other reveal */ + +.ui.active.reveal .visible.content, +.ui.reveal:hover .visible.content { + z-index: 4 !important; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Slide +---------------*/ + +.ui.slide.reveal { + position: relative !important; + overflow: hidden !important; + white-space: nowrap; +} + +.ui.slide.reveal > .content { + display: block; + width: 100%; + float: left; + margin: 0em; + -webkit-transition: -webkit-transform 0.5s ease 0.1s; + transition: -webkit-transform 0.5s ease 0.1s; + transition: transform 0.5s ease 0.1s; + transition: transform 0.5s ease 0.1s, -webkit-transform 0.5s ease 0.1s; +} + +.ui.slide.reveal > .visible.content { + position: relative !important; +} + +.ui.slide.reveal > .hidden.content { + position: absolute !important; + left: 0% !important; + width: 100% !important; + -webkit-transform: translateX(100%) !important; + transform: translateX(100%) !important; +} + +.ui.slide.active.reveal > .visible.content, +.ui.slide.reveal:hover > .visible.content { + -webkit-transform: translateX(-100%) !important; + transform: translateX(-100%) !important; +} + +.ui.slide.active.reveal > .hidden.content, +.ui.slide.reveal:hover > .hidden.content { + -webkit-transform: translateX(0%) !important; + transform: translateX(0%) !important; +} + +.ui.slide.right.reveal > .visible.content { + -webkit-transform: translateX(0%) !important; + transform: translateX(0%) !important; +} + +.ui.slide.right.reveal > .hidden.content { + -webkit-transform: translateX(-100%) !important; + transform: translateX(-100%) !important; +} + +.ui.slide.right.active.reveal > .visible.content, +.ui.slide.right.reveal:hover > .visible.content { + -webkit-transform: translateX(100%) !important; + transform: translateX(100%) !important; +} + +.ui.slide.right.active.reveal > .hidden.content, +.ui.slide.right.reveal:hover > .hidden.content { + -webkit-transform: translateX(0%) !important; + transform: translateX(0%) !important; +} + +.ui.slide.up.reveal > .hidden.content { + -webkit-transform: translateY(100%) !important; + transform: translateY(100%) !important; +} + +.ui.slide.up.active.reveal > .visible.content, +.ui.slide.up.reveal:hover > .visible.content { + -webkit-transform: translateY(-100%) !important; + transform: translateY(-100%) !important; +} + +.ui.slide.up.active.reveal > .hidden.content, +.ui.slide.up.reveal:hover > .hidden.content { + -webkit-transform: translateY(0%) !important; + transform: translateY(0%) !important; +} + +.ui.slide.down.reveal > .hidden.content { + -webkit-transform: translateY(-100%) !important; + transform: translateY(-100%) !important; +} + +.ui.slide.down.active.reveal > .visible.content, +.ui.slide.down.reveal:hover > .visible.content { + -webkit-transform: translateY(100%) !important; + transform: translateY(100%) !important; +} + +.ui.slide.down.active.reveal > .hidden.content, +.ui.slide.down.reveal:hover > .hidden.content { + -webkit-transform: translateY(0%) !important; + transform: translateY(0%) !important; +} + +/*-------------- + Fade +---------------*/ + +.ui.fade.reveal > .visible.content { + opacity: 1; +} + +.ui.fade.active.reveal > .visible.content, +.ui.fade.reveal:hover > .visible.content { + opacity: 0; +} + +/*-------------- + Move +---------------*/ + +.ui.move.reveal { + position: relative !important; + overflow: hidden !important; + white-space: nowrap; +} + +.ui.move.reveal > .content { + display: block; + float: left; + margin: 0em; + -webkit-transition: -webkit-transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1) 0.1s; + transition: -webkit-transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1) 0.1s; + transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1) 0.1s; + transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1) 0.1s, -webkit-transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1) 0.1s; +} + +.ui.move.reveal > .visible.content { + position: relative !important; +} + +.ui.move.reveal > .hidden.content { + position: absolute !important; + left: 0% !important; + width: 100% !important; +} + +.ui.move.active.reveal > .visible.content, +.ui.move.reveal:hover > .visible.content { + -webkit-transform: translateX(-100%) !important; + transform: translateX(-100%) !important; +} + +.ui.move.right.active.reveal > .visible.content, +.ui.move.right.reveal:hover > .visible.content { + -webkit-transform: translateX(100%) !important; + transform: translateX(100%) !important; +} + +.ui.move.up.active.reveal > .visible.content, +.ui.move.up.reveal:hover > .visible.content { + -webkit-transform: translateY(-100%) !important; + transform: translateY(-100%) !important; +} + +.ui.move.down.active.reveal > .visible.content, +.ui.move.down.reveal:hover > .visible.content { + -webkit-transform: translateY(100%) !important; + transform: translateY(100%) !important; +} + +/*-------------- + Rotate +---------------*/ + +.ui.rotate.reveal > .visible.content { + -webkit-transition-duration: 0.5s; + transition-duration: 0.5s; + -webkit-transform: rotate(0deg); + transform: rotate(0deg); +} + +.ui.rotate.reveal > .visible.content, +.ui.rotate.right.reveal > .visible.content { + -webkit-transform-origin: bottom right; + transform-origin: bottom right; +} + +.ui.rotate.active.reveal > .visible.content, +.ui.rotate.reveal:hover > .visible.content, +.ui.rotate.right.active.reveal > .visible.content, +.ui.rotate.right.reveal:hover > .visible.content { + -webkit-transform: rotate(110deg); + transform: rotate(110deg); +} + +.ui.rotate.left.reveal > .visible.content { + -webkit-transform-origin: bottom left; + transform-origin: bottom left; +} + +.ui.rotate.left.active.reveal > .visible.content, +.ui.rotate.left.reveal:hover > .visible.content { + -webkit-transform: rotate(-110deg); + transform: rotate(-110deg); +} + +/******************************* + States +*******************************/ + +.ui.disabled.reveal:hover > .visible.visible.content { + position: static !important; + display: block !important; + opacity: 1 !important; + top: 0 !important; + left: 0 !important; + right: auto !important; + bottom: auto !important; + -webkit-transform: none !important; + transform: none !important; +} + +.ui.disabled.reveal:hover > .hidden.hidden.content { + display: none !important; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Visible +---------------*/ + +.ui.visible.reveal { + overflow: visible; +} + +/*-------------- + Instant +---------------*/ + +.ui.instant.reveal > .content { + -webkit-transition-delay: 0s !important; + transition-delay: 0s !important; +} + +/*-------------- + Sizing +---------------*/ + +.ui.reveal > .content { + font-size: 1rem !important; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Segment + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Segment +*******************************/ + +.ui.segment { + position: relative; + background: #FFFFFF; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15); + margin: 1rem 0em; + padding: 1em 1em; + border-radius: 0.28571429rem; + border: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.segment:first-child { + margin-top: 0em; +} + +.ui.segment:last-child { + margin-bottom: 0em; +} + +/* Vertical */ + +.ui.vertical.segment { + margin: 0em; + padding-left: 0em; + padding-right: 0em; + background: none transparent; + border-radius: 0px; + box-shadow: none; + border: none; + border-bottom: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.vertical.segment:last-child { + border-bottom: none; +} + +/*------------------- + Loose Coupling +--------------------*/ + +/* Header */ + +.ui.inverted.segment > .ui.header { + color: #FFFFFF; +} + +/* Label */ + +.ui[class*="bottom attached"].segment > [class*="top attached"].label { + border-top-left-radius: 0em; + border-top-right-radius: 0em; +} + +.ui[class*="top attached"].segment > [class*="bottom attached"].label { + border-bottom-left-radius: 0em; + border-bottom-right-radius: 0em; +} + +.ui.attached.segment:not(.top):not(.bottom) > [class*="top attached"].label { + border-top-left-radius: 0em; + border-top-right-radius: 0em; +} + +.ui.attached.segment:not(.top):not(.bottom) > [class*="bottom attached"].label { + border-bottom-left-radius: 0em; + border-bottom-right-radius: 0em; +} + +/* Grid */ + +.ui.page.grid.segment, +.ui.grid > .row > .ui.segment.column, +.ui.grid > .ui.segment.column { + padding-top: 2em; + padding-bottom: 2em; +} + +.ui.grid.segment { + margin: 1rem 0em; + border-radius: 0.28571429rem; +} + +/* Table */ + +.ui.basic.table.segment { + background: #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15); +} + +.ui[class*="very basic"].table.segment { + padding: 1em 1em; +} + +/******************************* + Types +*******************************/ + +/*------------------- + Piled +--------------------*/ + +.ui.piled.segments, +.ui.piled.segment { + margin: 3em 0em; + box-shadow: ''; + z-index: auto; +} + +.ui.piled.segment:first-child { + margin-top: 0em; +} + +.ui.piled.segment:last-child { + margin-bottom: 0em; +} + +.ui.piled.segments:after, +.ui.piled.segments:before, +.ui.piled.segment:after, +.ui.piled.segment:before { + background-color: #FFFFFF; + visibility: visible; + content: ''; + display: block; + height: 100%; + left: 0px; + position: absolute; + width: 100%; + border: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: ''; +} + +.ui.piled.segments:before, +.ui.piled.segment:before { + -webkit-transform: rotate(-1.2deg); + transform: rotate(-1.2deg); + top: 0; + z-index: -2; +} + +.ui.piled.segments:after, +.ui.piled.segment:after { + -webkit-transform: rotate(1.2deg); + transform: rotate(1.2deg); + top: 0; + z-index: -1; +} + +/* Piled Attached */ + +.ui[class*="top attached"].piled.segment { + margin-top: 3em; + margin-bottom: 0em; +} + +.ui.piled.segment[class*="top attached"]:first-child { + margin-top: 0em; +} + +.ui.piled.segment[class*="bottom attached"] { + margin-top: 0em; + margin-bottom: 3em; +} + +.ui.piled.segment[class*="bottom attached"]:last-child { + margin-bottom: 0em; +} + +/*------------------- + Stacked +--------------------*/ + +.ui.stacked.segment { + padding-bottom: 1.4em; +} + +.ui.stacked.segments:before, +.ui.stacked.segments:after, +.ui.stacked.segment:before, +.ui.stacked.segment:after { + content: ''; + position: absolute; + bottom: -3px; + left: 0%; + border-top: 1px solid rgba(34, 36, 38, 0.15); + background: rgba(0, 0, 0, 0.03); + width: 100%; + height: 6px; + visibility: visible; +} + +.ui.stacked.segments:before, +.ui.stacked.segment:before { + display: none; +} + +/* Add additional page */ + +.ui.tall.stacked.segments:before, +.ui.tall.stacked.segment:before { + display: block; + bottom: 0px; +} + +/* Inverted */ + +.ui.stacked.inverted.segments:before, +.ui.stacked.inverted.segments:after, +.ui.stacked.inverted.segment:before, +.ui.stacked.inverted.segment:after { + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(34, 36, 38, 0.35); +} + +/*------------------- + Padded +--------------------*/ + +.ui.padded.segment { + padding: 1.5em; +} + +.ui[class*="very padded"].segment { + padding: 3em; +} + +/* Padded vertical */ + +.ui.padded.segment.vertical.segment, +.ui[class*="very padded"].vertical.segment { + padding-left: 0px; + padding-right: 0px; +} + +/*------------------- + Compact +--------------------*/ + +.ui.compact.segment { + display: table; +} + +/* Compact Group */ + +.ui.compact.segments { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.ui.compact.segments .segment, +.ui.segments .compact.segment { + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + -ms-flex: 0 1 auto; + flex: 0 1 auto; +} + +/*------------------- + Circular +--------------------*/ + +.ui.circular.segment { + display: table-cell; + padding: 2em; + text-align: center; + vertical-align: middle; + border-radius: 500em; +} + +/*------------------- + Raised +--------------------*/ + +.ui.raised.segments, +.ui.raised.segment { + box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); +} + +/******************************* + Groups +*******************************/ + +/* Group */ + +.ui.segments { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + margin: 1rem 0em; + border: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15); + border-radius: 0.28571429rem; +} + +.ui.segments:first-child { + margin-top: 0em; +} + +.ui.segments:last-child { + margin-bottom: 0em; +} + +/* Nested Segment */ + +.ui.segments > .segment { + top: 0px; + bottom: 0px; + border-radius: 0px; + margin: 0em; + width: auto; + box-shadow: none; + border: none; + border-top: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.segments:not(.horizontal) > .segment:first-child { + border-top: none; + margin-top: 0em; + bottom: 0px; + margin-bottom: 0em; + top: 0px; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +/* Bottom */ + +.ui.segments:not(.horizontal) > .segment:last-child { + top: 0px; + bottom: 0px; + margin-top: 0em; + margin-bottom: 0em; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +/* Only */ + +.ui.segments:not(.horizontal) > .segment:only-child { + border-radius: 0.28571429rem; +} + +/* Nested Group */ + +.ui.segments > .ui.segments { + border-top: 1px solid rgba(34, 36, 38, 0.15); + margin: 1rem 1rem; +} + +.ui.segments > .segments:first-child { + border-top: none; +} + +.ui.segments > .segment + .segments:not(.horizontal) { + margin-top: 0em; +} + +/* Horizontal Group */ + +.ui.horizontal.segments { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + background-color: transparent; + border-radius: 0px; + padding: 0em; + background-color: #FFFFFF; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15); + margin: 1rem 0em; + border-radius: 0.28571429rem; + border: 1px solid rgba(34, 36, 38, 0.15); +} + +/* Nested Horizontal Group */ + +.ui.segments > .horizontal.segments { + margin: 0em; + background-color: transparent; + border-radius: 0px; + border: none; + box-shadow: none; + border-top: 1px solid rgba(34, 36, 38, 0.15); +} + +/* Horizontal Segment */ + +.ui.horizontal.segments > .segment { + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + -ms-flex: 1 1 0px; + /* Solves #2550 MS Flex */ + margin: 0em; + min-width: 0px; + background-color: transparent; + border-radius: 0px; + border: none; + box-shadow: none; + border-left: 1px solid rgba(34, 36, 38, 0.15); +} + +/* Border Fixes */ + +.ui.segments > .horizontal.segments:first-child { + border-top: none; +} + +.ui.horizontal.segments > .segment:first-child { + border-left: none; +} + +/******************************* + States +*******************************/ + +/*-------------- + Disabled +---------------*/ + +.ui.disabled.segment { + opacity: 0.45; + color: rgba(40, 40, 40, 0.3); +} + +/*-------------- + Loading +---------------*/ + +.ui.loading.segment { + position: relative; + cursor: default; + pointer-events: none; + text-shadow: none !important; + color: transparent !important; + -webkit-transition: all 0s linear; + transition: all 0s linear; +} + +.ui.loading.segment:before { + position: absolute; + content: ''; + top: 0%; + left: 0%; + background: rgba(255, 255, 255, 0.8); + width: 100%; + height: 100%; + border-radius: 0.28571429rem; + z-index: 100; +} + +.ui.loading.segment:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -1.5em 0em 0em -1.5em; + width: 3em; + height: 3em; + -webkit-animation: segment-spin 0.6s linear; + animation: segment-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1); + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; + visibility: visible; + z-index: 101; +} + +@-webkit-keyframes segment-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes segment-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Basic +--------------------*/ + +.ui.basic.segment { + background: none transparent; + box-shadow: none; + border: none; + border-radius: 0px; +} + +/*------------------- + Clearing +--------------------*/ + +.ui.clearing.segment:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +/*------------------- + Colors +--------------------*/ + +/* Red */ + +.ui.red.segment:not(.inverted) { + border-top: 2px solid #DB2828; +} + +.ui.inverted.red.segment { + background-color: #DB2828 !important; + color: #FFFFFF !important; +} + +/* Orange */ + +.ui.orange.segment:not(.inverted) { + border-top: 2px solid #F2711C; +} + +.ui.inverted.orange.segment { + background-color: #F2711C !important; + color: #FFFFFF !important; +} + +/* Yellow */ + +.ui.yellow.segment:not(.inverted) { + border-top: 2px solid #FBBD08; +} + +.ui.inverted.yellow.segment { + background-color: #FBBD08 !important; + color: #FFFFFF !important; +} + +/* Olive */ + +.ui.olive.segment:not(.inverted) { + border-top: 2px solid #B5CC18; +} + +.ui.inverted.olive.segment { + background-color: #B5CC18 !important; + color: #FFFFFF !important; +} + +/* Green */ + +.ui.green.segment:not(.inverted) { + border-top: 2px solid #21BA45; +} + +.ui.inverted.green.segment { + background-color: #21BA45 !important; + color: #FFFFFF !important; +} + +/* Teal */ + +.ui.teal.segment:not(.inverted) { + border-top: 2px solid #00B5AD; +} + +.ui.inverted.teal.segment { + background-color: #00B5AD !important; + color: #FFFFFF !important; +} + +/* Blue */ + +.ui.blue.segment:not(.inverted) { + border-top: 2px solid #2185D0; +} + +.ui.inverted.blue.segment { + background-color: #2185D0 !important; + color: #FFFFFF !important; +} + +/* Violet */ + +.ui.violet.segment:not(.inverted) { + border-top: 2px solid #6435C9; +} + +.ui.inverted.violet.segment { + background-color: #6435C9 !important; + color: #FFFFFF !important; +} + +/* Purple */ + +.ui.purple.segment:not(.inverted) { + border-top: 2px solid #A333C8; +} + +.ui.inverted.purple.segment { + background-color: #A333C8 !important; + color: #FFFFFF !important; +} + +/* Pink */ + +.ui.pink.segment:not(.inverted) { + border-top: 2px solid #E03997; +} + +.ui.inverted.pink.segment { + background-color: #E03997 !important; + color: #FFFFFF !important; +} + +/* Brown */ + +.ui.brown.segment:not(.inverted) { + border-top: 2px solid #A5673F; +} + +.ui.inverted.brown.segment { + background-color: #A5673F !important; + color: #FFFFFF !important; +} + +/* Grey */ + +.ui.grey.segment:not(.inverted) { + border-top: 2px solid #767676; +} + +.ui.inverted.grey.segment { + background-color: #767676 !important; + color: #FFFFFF !important; +} + +/* Black */ + +.ui.black.segment:not(.inverted) { + border-top: 2px solid #1B1C1D; +} + +.ui.inverted.black.segment { + background-color: #1B1C1D !important; + color: #FFFFFF !important; +} + +/*------------------- + Aligned +--------------------*/ + +.ui[class*="left aligned"].segment { + text-align: left; +} + +.ui[class*="right aligned"].segment { + text-align: right; +} + +.ui[class*="center aligned"].segment { + text-align: center; +} + +/*------------------- + Floated +--------------------*/ + +.ui.floated.segment, +.ui[class*="left floated"].segment { + float: left; + margin-right: 1em; +} + +.ui[class*="right floated"].segment { + float: right; + margin-left: 1em; +} + +/*------------------- + Inverted +--------------------*/ + +.ui.inverted.segment { + border: none; + box-shadow: none; +} + +.ui.inverted.segment, +.ui.primary.inverted.segment { + background: #1B1C1D; + color: rgba(255, 255, 255, 0.9); +} + +/* Nested */ + +.ui.inverted.segment .segment { + color: rgba(0, 0, 0, 0.87); +} + +.ui.inverted.segment .inverted.segment { + color: rgba(255, 255, 255, 0.9); +} + +/* Attached */ + +.ui.inverted.attached.segment { + border-color: #555555; +} + +/*------------------- + Emphasis +--------------------*/ + +/* Secondary */ + +.ui.secondary.segment { + background: #F3F4F5; + color: rgba(0, 0, 0, 0.6); +} + +.ui.secondary.inverted.segment { + background: #4c4f52 -webkit-linear-gradient(rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%); + background: #4c4f52 linear-gradient(rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%); + color: rgba(255, 255, 255, 0.8); +} + +/* Tertiary */ + +.ui.tertiary.segment { + background: #DCDDDE; + color: rgba(0, 0, 0, 0.6); +} + +.ui.tertiary.inverted.segment { + background: #717579 -webkit-linear-gradient(rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.35) 100%); + background: #717579 linear-gradient(rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.35) 100%); + color: rgba(255, 255, 255, 0.8); +} + +/*------------------- + Attached +--------------------*/ + +/* Middle */ + +.ui.attached.segment { + top: 0px; + bottom: 0px; + border-radius: 0px; + margin: 0em -1px; + width: calc(100% + 2px ); + max-width: calc(100% + 2px ); + box-shadow: none; + border: 1px solid #D4D4D5; +} + +.ui.attached:not(.message) + .ui.attached.segment:not(.top) { + border-top: none; +} + +/* Top */ + +.ui[class*="top attached"].segment { + bottom: 0px; + margin-bottom: 0em; + top: 0px; + margin-top: 1rem; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.segment[class*="top attached"]:first-child { + margin-top: 0em; +} + +/* Bottom */ + +.ui.segment[class*="bottom attached"] { + bottom: 0px; + margin-top: 0em; + top: 0px; + margin-bottom: 1rem; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui.segment[class*="bottom attached"]:last-child { + margin-bottom: 0em; +} + +/*------------------- + Size +--------------------*/ + +.ui.mini.segments .segment, +.ui.mini.segment { + font-size: 0.78571429rem; +} + +.ui.tiny.segments .segment, +.ui.tiny.segment { + font-size: 0.85714286rem; +} + +.ui.small.segments .segment, +.ui.small.segment { + font-size: 0.92857143rem; +} + +.ui.segments .segment, +.ui.segment { + font-size: 1rem; +} + +.ui.large.segments .segment, +.ui.large.segment { + font-size: 1.14285714rem; +} + +.ui.big.segments .segment, +.ui.big.segment { + font-size: 1.28571429rem; +} + +.ui.huge.segments .segment, +.ui.huge.segment { + font-size: 1.42857143rem; +} + +.ui.massive.segments .segment, +.ui.massive.segment { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Step + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Plural +*******************************/ + +.ui.steps { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; + margin: 1em 0em; + background: ''; + box-shadow: none; + line-height: 1.14285714em; + border-radius: 0.28571429rem; + border: 1px solid rgba(34, 36, 38, 0.15); +} + +/* First Steps */ + +.ui.steps:first-child { + margin-top: 0em; +} + +/* Last Steps */ + +.ui.steps:last-child { + margin-bottom: 0em; +} + +/******************************* + Singular +*******************************/ + +.ui.steps .step { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -webkit-flex: 1 0 auto; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + vertical-align: middle; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + margin: 0em 0em; + padding: 1.14285714em 2em; + background: #FFFFFF; + color: rgba(0, 0, 0, 0.87); + box-shadow: none; + border-radius: 0em; + border: none; + border-right: 1px solid rgba(34, 36, 38, 0.15); + -webkit-transition: background-color 0.1s ease, opacity 0.1s ease, color 0.1s ease, box-shadow 0.1s ease; + transition: background-color 0.1s ease, opacity 0.1s ease, color 0.1s ease, box-shadow 0.1s ease; +} + +/* Arrow */ + +.ui.steps .step:after { + display: none; + position: absolute; + z-index: 2; + content: ''; + top: 50%; + right: 0%; + border: medium none; + background-color: #FFFFFF; + width: 1.14285714em; + height: 1.14285714em; + border-style: solid; + border-color: rgba(34, 36, 38, 0.15); + border-width: 0px 1px 1px 0px; + -webkit-transition: background-color 0.1s ease, opacity 0.1s ease, color 0.1s ease, box-shadow 0.1s ease; + transition: background-color 0.1s ease, opacity 0.1s ease, color 0.1s ease, box-shadow 0.1s ease; + -webkit-transform: translateY(-50%) translateX(50%) rotate(-45deg); + transform: translateY(-50%) translateX(50%) rotate(-45deg); +} + +/* First Step */ + +.ui.steps .step:first-child { + padding-left: 2em; + border-radius: 0.28571429rem 0em 0em 0.28571429rem; +} + +/* Last Step */ + +.ui.steps .step:last-child { + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +.ui.steps .step:last-child { + border-right: none; + margin-right: 0em; +} + +/* Only Step */ + +.ui.steps .step:only-child { + border-radius: 0.28571429rem; +} + +/******************************* + Content +*******************************/ + +/* Title */ + +.ui.steps .step .title { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 1.14285714em; + font-weight: bold; +} + +.ui.steps .step > .title { + width: 100%; +} + +/* Description */ + +.ui.steps .step .description { + font-weight: normal; + font-size: 0.92857143em; + color: rgba(0, 0, 0, 0.87); +} + +.ui.steps .step > .description { + width: 100%; +} + +.ui.steps .step .title ~ .description { + margin-top: 0.25em; +} + +/* Icon */ + +.ui.steps .step > .icon { + line-height: 1; + font-size: 2.5em; + margin: 0em 1rem 0em 0em; +} + +.ui.steps .step > .icon, +.ui.steps .step > .icon ~ .content { + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + -webkit-align-self: middle; + -ms-flex-item-align: middle; + align-self: middle; +} + +.ui.steps .step > .icon ~ .content { + -webkit-box-flex: 1 0 auto; + -webkit-flex-grow: 1 0 auto; + -ms-flex-positive: 1 0 auto; + flex-grow: 1 0 auto; +} + +/* Horizontal Icon */ + +.ui.steps:not(.vertical) .step > .icon { + width: auto; +} + +/* Link */ + +.ui.steps .link.step, +.ui.steps a.step { + cursor: pointer; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Ordered +---------------*/ + +.ui.ordered.steps { + counter-reset: ordered; +} + +.ui.ordered.steps .step:before { + display: block; + position: static; + text-align: center; + content: counters(ordered, "."); + -webkit-align-self: middle; + -ms-flex-item-align: middle; + align-self: middle; + margin-right: 1rem; + font-size: 2.5em; + counter-increment: ordered; + font-family: inherit; + font-weight: bold; +} + +.ui.ordered.steps .step > * { + display: block; + -webkit-align-self: middle; + -ms-flex-item-align: middle; + align-self: middle; +} + +/*-------------- + Vertical +---------------*/ + +.ui.vertical.steps { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + overflow: visible; +} + +.ui.vertical.steps .step { + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + border-radius: 0em; + padding: 1.14285714em 2em; + border-right: none; + border-bottom: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.vertical.steps .step:first-child { + padding: 1.14285714em 2em; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.vertical.steps .step:last-child { + border-bottom: none; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui.vertical.steps .step:only-child { + border-radius: 0.28571429rem; +} + +/* Arrow */ + +.ui.vertical.steps .step:after { + display: none; +} + +.ui.vertical.steps .step:after { + top: 50%; + right: 0%; + border-width: 0px 1px 1px 0px; +} + +.ui.vertical.steps .step:after { + display: none; +} + +.ui.vertical.steps .active.step:after { + display: block; +} + +.ui.vertical.steps .step:last-child:after { + display: none; +} + +.ui.vertical.steps .active.step:last-child:after { + display: block; +} + +/*--------------- + Responsive +----------------*/ + +/* Mobile (Default) */ + +@media only screen and (max-width: 767px) { + .ui.steps { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + overflow: visible; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } + + .ui.steps .step { + width: 100% !important; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + border-radius: 0em; + padding: 1.14285714em 2em; + } + + .ui.steps .step:first-child { + padding: 1.14285714em 2em; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; + } + + .ui.steps .step:last-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; + } + + /* Arrow */ + + .ui.steps .step:after { + display: none !important; + } + + /* Content */ + + .ui.steps .step .content { + text-align: center; + } + + /* Icon */ + + .ui.steps .step > .icon, + .ui.ordered.steps .step:before { + margin: 0em 0em 1rem 0em; + } +} + +/******************************* + States +*******************************/ + +/* Link Hover */ + +.ui.steps .link.step:hover::after, +.ui.steps .link.step:hover, +.ui.steps a.step:hover::after, +.ui.steps a.step:hover { + background: #F9FAFB; + color: rgba(0, 0, 0, 0.8); +} + +/* Link Down */ + +.ui.steps .link.step:active::after, +.ui.steps .link.step:active, +.ui.steps a.step:active::after, +.ui.steps a.step:active { + background: #F3F4F5; + color: rgba(0, 0, 0, 0.9); +} + +/* Active */ + +.ui.steps .step.active { + cursor: auto; + background: #F3F4F5; +} + +.ui.steps .step.active:after { + background: #F3F4F5; +} + +.ui.steps .step.active .title { + color: #4183C4; +} + +.ui.ordered.steps .step.active:before, +.ui.steps .active.step .icon { + color: rgba(0, 0, 0, 0.85); +} + +/* Active Arrow */ + +.ui.steps .step:after { + display: block; +} + +.ui.steps .active.step:after { + display: block; +} + +.ui.steps .step:last-child:after { + display: none; +} + +.ui.steps .active.step:last-child:after { + display: none; +} + +/* Active Hover */ + +.ui.steps .link.active.step:hover::after, +.ui.steps .link.active.step:hover, +.ui.steps a.active.step:hover::after, +.ui.steps a.active.step:hover { + cursor: pointer; + background: #DCDDDE; + color: rgba(0, 0, 0, 0.87); +} + +/* Completed */ + +.ui.steps .step.completed > .icon:before, +.ui.ordered.steps .step.completed:before { + color: #21BA45; +} + +/* Disabled */ + +.ui.steps .disabled.step { + cursor: auto; + background: #FFFFFF; + pointer-events: none; +} + +.ui.steps .disabled.step, +.ui.steps .disabled.step .title, +.ui.steps .disabled.step .description { + color: rgba(40, 40, 40, 0.3); +} + +.ui.steps .disabled.step:after { + background: #FFFFFF; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Stackable +---------------*/ + +/* Tablet Or Below */ + +@media only screen and (max-width: 991px) { + .ui[class*="tablet stackable"].steps { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + overflow: visible; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } + + /* Steps */ + + .ui[class*="tablet stackable"].steps .step { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + border-radius: 0em; + padding: 1.14285714em 2em; + } + + .ui[class*="tablet stackable"].steps .step:first-child { + padding: 1.14285714em 2em; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; + } + + .ui[class*="tablet stackable"].steps .step:last-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; + } + + /* Arrow */ + + .ui[class*="tablet stackable"].steps .step:after { + display: none !important; + } + + /* Content */ + + .ui[class*="tablet stackable"].steps .step .content { + text-align: center; + } + + /* Icon */ + + .ui[class*="tablet stackable"].steps .step > .icon, + .ui[class*="tablet stackable"].ordered.steps .step:before { + margin: 0em 0em 1rem 0em; + } +} + +/*-------------- + Fluid +---------------*/ + +/* Fluid */ + +.ui.fluid.steps { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; +} + +/*-------------- + Attached +---------------*/ + +/* Top */ + +.ui.attached.steps { + width: calc(100% + 2px ) !important; + margin: 0em -1px 0; + max-width: calc(100% + 2px ); + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.attached.steps .step:first-child { + border-radius: 0.28571429rem 0em 0em 0em; +} + +.ui.attached.steps .step:last-child { + border-radius: 0em 0.28571429rem 0em 0em; +} + +/* Bottom */ + +.ui.bottom.attached.steps { + margin: 0 -1px 0em; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui.bottom.attached.steps .step:first-child { + border-radius: 0em 0em 0em 0.28571429rem; +} + +.ui.bottom.attached.steps .step:last-child { + border-radius: 0em 0em 0.28571429rem 0em; +} + +/*------------------- + Evenly Divided +--------------------*/ + +.ui.one.steps, +.ui.two.steps, +.ui.three.steps, +.ui.four.steps, +.ui.five.steps, +.ui.six.steps, +.ui.seven.steps, +.ui.eight.steps { + width: 100%; +} + +.ui.one.steps > .step, +.ui.two.steps > .step, +.ui.three.steps > .step, +.ui.four.steps > .step, +.ui.five.steps > .step, +.ui.six.steps > .step, +.ui.seven.steps > .step, +.ui.eight.steps > .step { + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} + +.ui.one.steps > .step { + width: 100%; +} + +.ui.two.steps > .step { + width: 50%; +} + +.ui.three.steps > .step { + width: 33.333%; +} + +.ui.four.steps > .step { + width: 25%; +} + +.ui.five.steps > .step { + width: 20%; +} + +.ui.six.steps > .step { + width: 16.666%; +} + +.ui.seven.steps > .step { + width: 14.285%; +} + +.ui.eight.steps > .step { + width: 12.500%; +} + +/*------------------- + Sizes +--------------------*/ + +.ui.mini.steps .step, +.ui.mini.step { + font-size: 0.78571429rem; +} + +.ui.tiny.steps .step, +.ui.tiny.step { + font-size: 0.85714286rem; +} + +.ui.small.steps .step, +.ui.small.step { + font-size: 0.92857143rem; +} + +.ui.steps .step, +.ui.step { + font-size: 1rem; +} + +.ui.large.steps .step, +.ui.large.step { + font-size: 1.14285714rem; +} + +.ui.big.steps .step, +.ui.big.step { + font-size: 1.28571429rem; +} + +.ui.huge.steps .step, +.ui.huge.step { + font-size: 1.42857143rem; +} + +.ui.massive.steps .step, +.ui.massive.step { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +@font-face { + font-family: 'Step'; + src: url(data:application/x-font-ttf;charset=utf-8;;base64,AAEAAAAOAIAAAwBgT1MvMj3hSQEAAADsAAAAVmNtYXDQEhm3AAABRAAAAUpjdnQgBkn/lAAABuwAAAAcZnBnbYoKeDsAAAcIAAAJkWdhc3AAAAAQAAAG5AAAAAhnbHlm32cEdgAAApAAAAC2aGVhZAErPHsAAANIAAAANmhoZWEHUwNNAAADgAAAACRobXR4CykAAAAAA6QAAAAMbG9jYQA4AFsAAAOwAAAACG1heHAApgm8AAADuAAAACBuYW1lzJ0aHAAAA9gAAALNcG9zdK69QJgAAAaoAAAAO3ByZXCSoZr/AAAQnAAAAFYAAQO4AZAABQAIAnoCvAAAAIwCegK8AAAB4AAxAQIAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA6ADoAQNS/2oAWgMLAE8AAAABAAAAAAAAAAAAAwAAAAMAAAAcAAEAAAAAAEQAAwABAAAAHAAEACgAAAAGAAQAAQACAADoAf//AAAAAOgA//8AABgBAAEAAAAAAAAAAAEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAADpAKYABUAHEAZDwEAAQFCAAIBAmoAAQABagAAAGEUFxQDEisBFAcBBiInASY0PwE2Mh8BATYyHwEWA6QP/iAQLBD+6g8PTBAsEKQBbhAsEEwPAhYWEP4gDw8BFhAsEEwQEKUBbxAQTBAAAAH//f+xA18DCwAMABJADwABAQpDAAAACwBEFRMCESsBFA4BIi4CPgEyHgEDWXLG6MhuBnq89Lp+AV51xHR0xOrEdHTEAAAAAAEAAAABAADDeRpdXw889QALA+gAAAAAzzWYjQAAAADPNWBN//3/sQOkAwsAAAAIAAIAAAAAAAAAAQAAA1L/agBaA+gAAP/3A6QAAQAAAAAAAAAAAAAAAAAAAAMD6AAAA+gAAANZAAAAAAAAADgAWwABAAAAAwAWAAEAAAAAAAIABgATAG4AAAAtCZEAAAAAAAAAEgDeAAEAAAAAAAAANQAAAAEAAAAAAAEACAA1AAEAAAAAAAIABwA9AAEAAAAAAAMACABEAAEAAAAAAAQACABMAAEAAAAAAAUACwBUAAEAAAAAAAYACABfAAEAAAAAAAoAKwBnAAEAAAAAAAsAEwCSAAMAAQQJAAAAagClAAMAAQQJAAEAEAEPAAMAAQQJAAIADgEfAAMAAQQJAAMAEAEtAAMAAQQJAAQAEAE9AAMAAQQJAAUAFgFNAAMAAQQJAAYAEAFjAAMAAQQJAAoAVgFzAAMAAQQJAAsAJgHJQ29weXJpZ2h0IChDKSAyMDE0IGJ5IG9yaWdpbmFsIGF1dGhvcnMgQCBmb250ZWxsby5jb21mb250ZWxsb1JlZ3VsYXJmb250ZWxsb2ZvbnRlbGxvVmVyc2lvbiAxLjBmb250ZWxsb0dlbmVyYXRlZCBieSBzdmcydHRmIGZyb20gRm9udGVsbG8gcHJvamVjdC5odHRwOi8vZm9udGVsbG8uY29tAEMAbwBwAHkAcgBpAGcAaAB0ACAAKABDACkAIAAyADAAMQA0ACAAYgB5ACAAbwByAGkAZwBpAG4AYQBsACAAYQB1AHQAaABvAHIAcwAgAEAAIABmAG8AbgB0AGUAbABsAG8ALgBjAG8AbQBmAG8AbgB0AGUAbABsAG8AUgBlAGcAdQBsAGEAcgBmAG8AbgB0AGUAbABsAG8AZgBvAG4AdABlAGwAbABvAFYAZQByAHMAaQBvAG4AIAAxAC4AMABmAG8AbgB0AGUAbABsAG8ARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAQIBAwljaGVja21hcmsGY2lyY2xlAAAAAAEAAf//AA8AAAAAAAAAAAAAAAAAAAAAADIAMgML/7EDC/+xsAAssCBgZi2wASwgZCCwwFCwBCZasARFW1ghIyEbilggsFBQWCGwQFkbILA4UFghsDhZWSCwCkVhZLAoUFghsApFILAwUFghsDBZGyCwwFBYIGYgiophILAKUFhgGyCwIFBYIbAKYBsgsDZQWCGwNmAbYFlZWRuwACtZWSOwAFBYZVlZLbACLCBFILAEJWFkILAFQ1BYsAUjQrAGI0IbISFZsAFgLbADLCMhIyEgZLEFYkIgsAYjQrIKAAIqISCwBkMgiiCKsAArsTAFJYpRWGBQG2FSWVgjWSEgsEBTWLAAKxshsEBZI7AAUFhlWS2wBCywB0MrsgACAENgQi2wBSywByNCIyCwACNCYbCAYrABYLAEKi2wBiwgIEUgsAJFY7ABRWJgRLABYC2wBywgIEUgsAArI7ECBCVgIEWKI2EgZCCwIFBYIbAAG7AwUFiwIBuwQFlZI7AAUFhlWbADJSNhRESwAWAtsAgssQUFRbABYUQtsAkssAFgICCwCUNKsABQWCCwCSNCWbAKQ0qwAFJYILAKI0JZLbAKLCC4BABiILgEAGOKI2GwC0NgIIpgILALI0IjLbALLEtUWLEHAURZJLANZSN4LbAMLEtRWEtTWLEHAURZGyFZJLATZSN4LbANLLEADENVWLEMDEOwAWFCsAorWbAAQ7ACJUKxCQIlQrEKAiVCsAEWIyCwAyVQWLEBAENgsAQlQoqKIIojYbAJKiEjsAFhIIojYbAJKiEbsQEAQ2CwAiVCsAIlYbAJKiFZsAlDR7AKQ0dgsIBiILACRWOwAUViYLEAABMjRLABQ7AAPrIBAQFDYEItsA4ssQAFRVRYALAMI0IgYLABYbUNDQEACwBCQopgsQ0FK7BtKxsiWS2wDyyxAA4rLbAQLLEBDistsBEssQIOKy2wEiyxAw4rLbATLLEEDistsBQssQUOKy2wFSyxBg4rLbAWLLEHDistsBcssQgOKy2wGCyxCQ4rLbAZLLAIK7EABUVUWACwDCNCIGCwAWG1DQ0BAAsAQkKKYLENBSuwbSsbIlktsBossQAZKy2wGyyxARkrLbAcLLECGSstsB0ssQMZKy2wHiyxBBkrLbAfLLEFGSstsCAssQYZKy2wISyxBxkrLbAiLLEIGSstsCMssQkZKy2wJCwgPLABYC2wJSwgYLANYCBDI7ABYEOwAiVhsAFgsCQqIS2wJiywJSuwJSotsCcsICBHICCwAkVjsAFFYmAjYTgjIIpVWCBHICCwAkVjsAFFYmAjYTgbIVktsCgssQAFRVRYALABFrAnKrABFTAbIlktsCkssAgrsQAFRVRYALABFrAnKrABFTAbIlktsCosIDWwAWAtsCssALADRWOwAUVisAArsAJFY7ABRWKwACuwABa0AAAAAABEPiM4sSoBFSotsCwsIDwgRyCwAkVjsAFFYmCwAENhOC2wLSwuFzwtsC4sIDwgRyCwAkVjsAFFYmCwAENhsAFDYzgtsC8ssQIAFiUgLiBHsAAjQrACJUmKikcjRyNhIFhiGyFZsAEjQrIuAQEVFCotsDAssAAWsAQlsAQlRyNHI2GwBkUrZYouIyAgPIo4LbAxLLAAFrAEJbAEJSAuRyNHI2EgsAQjQrAGRSsgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjILAIQyCKI0cjRyNhI0ZgsARDsIBiYCCwACsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsIBiYSMgILAEJiNGYTgbI7AIQ0awAiWwCENHI0cjYWAgsARDsIBiYCMgsAArI7AEQ2CwACuwBSVhsAUlsIBisAQmYSCwBCVgZCOwAyVgZFBYIRsjIVkjICCwBCYjRmE4WS2wMiywABYgICCwBSYgLkcjRyNhIzw4LbAzLLAAFiCwCCNCICAgRiNHsAArI2E4LbA0LLAAFrADJbACJUcjRyNhsABUWC4gPCMhG7ACJbACJUcjRyNhILAFJbAEJUcjRyNhsAYlsAUlSbACJWGwAUVjIyBYYhshWWOwAUViYCMuIyAgPIo4IyFZLbA1LLAAFiCwCEMgLkcjRyNhIGCwIGBmsIBiIyAgPIo4LbA2LCMgLkawAiVGUlggPFkusSYBFCstsDcsIyAuRrACJUZQWCA8WS6xJgEUKy2wOCwjIC5GsAIlRlJYIDxZIyAuRrACJUZQWCA8WS6xJgEUKy2wOSywMCsjIC5GsAIlRlJYIDxZLrEmARQrLbA6LLAxK4ogIDywBCNCijgjIC5GsAIlRlJYIDxZLrEmARQrsARDLrAmKy2wOyywABawBCWwBCYgLkcjRyNhsAZFKyMgPCAuIzixJgEUKy2wPCyxCAQlQrAAFrAEJbAEJSAuRyNHI2EgsAQjQrAGRSsgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjIEewBEOwgGJgILAAKyCKimEgsAJDYGQjsANDYWRQWLACQ2EbsANDYFmwAyWwgGJhsAIlRmE4IyA8IzgbISAgRiNHsAArI2E4IVmxJgEUKy2wPSywMCsusSYBFCstsD4ssDErISMgIDywBCNCIzixJgEUK7AEQy6wJistsD8ssAAVIEewACNCsgABARUUEy6wLCotsEAssAAVIEewACNCsgABARUUEy6wLCotsEEssQABFBOwLSotsEIssC8qLbBDLLAAFkUjIC4gRoojYTixJgEUKy2wRCywCCNCsEMrLbBFLLIAADwrLbBGLLIAATwrLbBHLLIBADwrLbBILLIBATwrLbBJLLIAAD0rLbBKLLIAAT0rLbBLLLIBAD0rLbBMLLIBAT0rLbBNLLIAADkrLbBOLLIAATkrLbBPLLIBADkrLbBQLLIBATkrLbBRLLIAADsrLbBSLLIAATsrLbBTLLIBADsrLbBULLIBATsrLbBVLLIAAD4rLbBWLLIAAT4rLbBXLLIBAD4rLbBYLLIBAT4rLbBZLLIAADorLbBaLLIAATorLbBbLLIBADorLbBcLLIBATorLbBdLLAyKy6xJgEUKy2wXiywMiuwNistsF8ssDIrsDcrLbBgLLAAFrAyK7A4Ky2wYSywMysusSYBFCstsGIssDMrsDYrLbBjLLAzK7A3Ky2wZCywMyuwOCstsGUssDQrLrEmARQrLbBmLLA0K7A2Ky2wZyywNCuwNystsGgssDQrsDgrLbBpLLA1Ky6xJgEUKy2waiywNSuwNistsGsssDUrsDcrLbBsLLA1K7A4Ky2wbSwrsAhlsAMkUHiwARUwLQAAAEu4AMhSWLEBAY5ZuQgACABjILABI0SwAyNwsgQoCUVSRLIKAgcqsQYBRLEkAYhRWLBAiFixBgNEsSYBiFFYuAQAiFixBgFEWVlZWbgB/4WwBI2xBQBEAAA=) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAoUAA4AAAAAEPQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABRAAAAEQAAABWPeFJAWNtYXAAAAGIAAAAOgAAAUrQEhm3Y3Z0IAAAAcQAAAAUAAAAHAZJ/5RmcGdtAAAB2AAABPkAAAmRigp4O2dhc3AAAAbUAAAACAAAAAgAAAAQZ2x5ZgAABtwAAACuAAAAtt9nBHZoZWFkAAAHjAAAADUAAAA2ASs8e2hoZWEAAAfEAAAAIAAAACQHUwNNaG10eAAAB+QAAAAMAAAADAspAABsb2NhAAAH8AAAAAgAAAAIADgAW21heHAAAAf4AAAAIAAAACAApgm8bmFtZQAACBgAAAF3AAACzcydGhxwb3N0AAAJkAAAACoAAAA7rr1AmHByZXAAAAm8AAAAVgAAAFaSoZr/eJxjYGTewTiBgZWBg6mKaQ8DA0MPhGZ8wGDIyMTAwMTAysyAFQSkuaYwOLxgeMHIHPQ/iyGKmZvBHyjMCJIDAPe9C2B4nGNgYGBmgGAZBkYGEHAB8hjBfBYGDSDNBqQZGZgYGF4w/v8PUvCCAURLMELVAwEjG8OIBwBk5AavAAB4nGNgQANGDEbM3P83gjAAELQD4XicnVXZdtNWFJU8ZHASOmSgoA7X3DhQ68qEKRgwaSrFdiEdHAitBB2kDHTkncc+62uOQrtWH/m07n09JLR0rbYsls++R1tn2DrnRhwjKn0aiGvUoZKXA6msPZZK90lc13Uvj5UMBnFdthJPSZuonSRKat3sUC7xWOsqWSdYJ+PlIFZPVZ5noAziFB5lSUQbRBuplyZJ4onjJ4kWZxAfJUkgJaMQp9LIUEI1GsRS1aFM6dCr1xNx00DKRqMedVhU90PFJ8c1p9SsA0YqVznCFevVRr4bpwMve5DEOsGzrYcxHnisfpQqkIqR6cg/dkpOlIaBVHHUoVbi6DCTX/eRTCrNQKaMYkWl7oG43f102xYxPXQ6vi5KlUaqurnOKJrt0fGogygP2cbppNzQ2fbw5RlTVKtdcbPtQGYNXErJbHSfRAAdJlLj6QFONZwCqRn1R8XZ588BEslclKo8VTKHegOZMzt7cTHtbiersnCknwcyb3Z2452HQ6dXh3/R+hdM4cxHj+Jifj5C+lBqfiJOJKVGWMzyp4YfcVcgQrkxiAsXyuBThDl0RdrZZl3jtTH2hs/5SqlhPQna6KP4fgr9TiQrHGdRo/VInM1j13Wt3GdQS7W7Fzsyr0OVIu7vCwuuM+eEYZ4WC1VfnvneBTT/Bohn/EDeNIVL+5YpSrRvm6JMu2iKCu0SVKVdNsUU7YoppmnPmmKG9h1TzNKeMzLj/8vc55H7HN7xkJv2XeSmfQ+5ad9HbtoPkJtWITdtHblpLyA3rUZu2lWjOnYEGgZpF1IVQdA0svph3Fab9UDWjDR8aWDyLmLI+upER521tcofxX914gsHcmmip7siF5viLq/bFj483e6rj5pG3bDV+MaR8jAeRnocmtBZ+c3hv+1N3S6a7jKqMugBFUwKwABl7UAC0zrbCaT1mqf48gdgXIZ4zkpDtVSfO4am7+V5X/exOfG+x+3GLrdcd3kJWdYNcmP28N9SZKrrH+UtrVQnR6wrJ49VaxhDKrwour6SlHu0tRu/KKmy8l6U1srnk5CbPYMbQlu27mGwI0xpyiUeXlOlKD3UUo6yQyxvKco84JSLC1qGxLgOdQ9qa8TpoXoYGwshhqG0vRBwSCldFd+0ynfxHqtr2Oj4xRXh6XpyEhGf4ir7UfBU10b96A7avGbdMoMpVaqn+4xPsa/b9lFZaaSOsxe3VAfXNOsaORXTT+Rr4HRvOGjdAz1UfDRBI1U1x+jGKGM0ljXl3wR0MVZ+w2jVYvs93E+dpFWsuUuY7JsT9+C0u/0q+7WcW0bW/dcGvW3kip8jMb8tCvw7B2K3ZA3UO5OBGAvIWdAYxhYmdxiug23EbfY/Jqf/34aFRXJXOxq7eerD1ZNRJXfZ8rjLTXZZ16M2R9VOGvsIjS0PN+bY4XIstsRgQbb+wf8x7gF3aVEC4NDIZZiI2nShnurh6h6rsW04VxIBds2x43QAegAuQd8cu9bzCYD13CPnLsB9cgh2yCH4lByCz8i5BfA5OQRfkEMwIIdgl5w7AA/IIXhIDsEeOQSPyNkE+JIcgq/IIYjJIUjIuQ3wmByCJ+QQfE0OwTdGrk5k/pYH2QD6zqKbQKmdGhzaOGRGrk3Y+zxY9oFFZB9aROqRkesT6lMeLPV7i0j9wSJSfzRyY0L9iQdL/dkiUn+xiNRnxpeZIymvDp7zjg7+BJfqrV4AAAAAAQAB//8AD3icY2BkAALmJUwzGEQZZBwk+RkZGBmdGJgYmbIYgMwsoGSiiLgIs5A2owg7I5uSOqOaiT2jmZE8I5gQY17C/09BQEfg3yt+fh8gvYQxD0j68DOJiQn8U+DnZxQDcQUEljLmCwBpBgbG/3//b2SOZ+Zm4GEQcuAH2sblDLSEm8FFVJhJEGgLH6OSHpMdo5EcI3Nk0bEXJ/LYqvZ82VXHGFd6pKTkyCsQwQAAq+QkqAAAeJxjYGRgYADiw5VSsfH8Nl8ZuJlfAEUYzpvO6IXQCb7///7fyLyEmRvI5WBgAokCAFb/DJAAAAB4nGNgZGBgDvqfxRDF/IKB4f935iUMQBEUwAwAi5YFpgPoAAAD6AAAA1kAAAAAAAAAOABbAAEAAAADABYAAQAAAAAAAgAGABMAbgAAAC0JkQAAAAB4nHWQy2rCQBSG//HSi0JbWui2sypKabxgN4IgWHTTbqS4LTHGJBIzMhkFX6Pv0IfpS/RZ+puMpShNmMx3vjlz5mQAXOMbAvnzxJGzwBmjnAs4Rc9ykf7Zcon8YrmMKt4sn9C/W67gAYHlKm7wwQqidM5ogU/LAlfi0nIBF+LOcpH+0XKJ3LNcxq14tXxC71muYCJSy1Xci6+BWm11FIRG1gZ12W62OnK6lYoqStxYumsTKp3KvpyrxPhxrBxPLfc89oN17Op9uJ8nvk4jlciW09yrkZ/42jX+bFc93QRtY+ZyrtVSDm2GXGm18D3jhMasuo3G3/MwgMIKW2hEvKoQBhI12jrnNppooUOaMkMyM8+KkMBFTONizR1htpIy7nPMGSW0PjNisgOP3+WRH5MC7o9ZRR+tHsYT0u6MKPOSfTns7jBrREqyTDezs9/eU2x4WpvWcNeuS511JTE8qCF5H7u1BY1H72S3Ymi7aPD95/9+AN1fhEsAeJxjYGKAAC4G7ICZgYGRiZGZMzkjNTk7N7Eomy05syg5J5WBAQBE1QZBAABLuADIUlixAQGOWbkIAAgAYyCwASNEsAMjcLIEKAlFUkSyCgIHKrEGAUSxJAGIUViwQIhYsQYDRLEmAYhRWLgEAIhYsQYBRFlZWVm4Af+FsASNsQUARAAA) format('woff'); +} + +.ui.steps .step.completed > .icon:before, +.ui.ordered.steps .step.completed:before { + font-family: 'Step'; + content: '\e800'; + /* '' */ +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Breadcrumb + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Breadcrumb +*******************************/ + +.ui.breadcrumb { + line-height: 1; + display: inline-block; + margin: 0em 0em; + vertical-align: middle; +} + +.ui.breadcrumb:first-child { + margin-top: 0em; +} + +.ui.breadcrumb:last-child { + margin-bottom: 0em; +} + +/******************************* + Content +*******************************/ + +/* Divider */ + +.ui.breadcrumb .divider { + display: inline-block; + opacity: 0.7; + margin: 0em 0.21428571rem 0em; + font-size: 0.92857143em; + color: rgba(0, 0, 0, 0.4); + vertical-align: baseline; +} + +/* Link */ + +.ui.breadcrumb a { + color: #4183C4; +} + +.ui.breadcrumb a:hover { + color: #1e70bf; +} + +/* Icon Divider */ + +.ui.breadcrumb .icon.divider { + font-size: 0.85714286em; + vertical-align: baseline; +} + +/* Section */ + +.ui.breadcrumb a.section { + cursor: pointer; +} + +.ui.breadcrumb .section { + display: inline-block; + margin: 0em; + padding: 0em; +} + +/* Loose Coupling */ + +.ui.breadcrumb.segment { + display: inline-block; + padding: 0.78571429em 1em; +} + +/******************************* + States +*******************************/ + +.ui.breadcrumb .active.section { + font-weight: bold; +} + +/******************************* + Variations +*******************************/ + +.ui.mini.breadcrumb { + font-size: 0.78571429rem; +} + +.ui.tiny.breadcrumb { + font-size: 0.85714286rem; +} + +.ui.small.breadcrumb { + font-size: 0.92857143rem; +} + +.ui.breadcrumb { + font-size: 1rem; +} + +.ui.large.breadcrumb { + font-size: 1.14285714rem; +} + +.ui.big.breadcrumb { + font-size: 1.28571429rem; +} + +.ui.huge.breadcrumb { + font-size: 1.42857143rem; +} + +.ui.massive.breadcrumb { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Form + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Elements +*******************************/ + +/*-------------------- + Form +---------------------*/ + +.ui.form { + position: relative; + max-width: 100%; +} + +/*-------------------- + Content +---------------------*/ + +.ui.form > p { + margin: 1em 0em; +} + +/*-------------------- + Field +---------------------*/ + +.ui.form .field { + clear: both; + margin: 0em 0em 1em; +} + +.ui.form .field:last-child, +.ui.form .fields:last-child .field { + margin-bottom: 0em; +} + +.ui.form .fields .field { + clear: both; + margin: 0em; +} + +/*-------------------- + Labels +---------------------*/ + +.ui.form .field > label { + display: block; + margin: 0em 0em 0.28571429rem 0em; + color: rgba(0, 0, 0, 0.87); + font-size: 0.92857143em; + font-weight: bold; + text-transform: none; +} + +/*-------------------- + Standard Inputs +---------------------*/ + +.ui.form textarea, +.ui.form input:not([type]), +.ui.form input[type="date"], +.ui.form input[type="datetime-local"], +.ui.form input[type="email"], +.ui.form input[type="number"], +.ui.form input[type="password"], +.ui.form input[type="search"], +.ui.form input[type="tel"], +.ui.form input[type="time"], +.ui.form input[type="text"], +.ui.form input[type="file"], +.ui.form input[type="url"] { + width: 100%; + vertical-align: top; +} + +/* Set max height on unusual input */ + +.ui.form ::-webkit-datetime-edit, +.ui.form ::-webkit-inner-spin-button { + height: 1.21428571em; +} + +.ui.form input:not([type]), +.ui.form input[type="date"], +.ui.form input[type="datetime-local"], +.ui.form input[type="email"], +.ui.form input[type="number"], +.ui.form input[type="password"], +.ui.form input[type="search"], +.ui.form input[type="tel"], +.ui.form input[type="time"], +.ui.form input[type="text"], +.ui.form input[type="file"], +.ui.form input[type="url"] { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + margin: 0em; + outline: none; + -webkit-appearance: none; + tap-highlight-color: rgba(255, 255, 255, 0); + line-height: 1.21428571em; + padding: 0.67857143em 1em; + font-size: 1em; + background: #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + color: rgba(0, 0, 0, 0.87); + border-radius: 0.28571429rem; + box-shadow: 0em 0em 0em 0em transparent inset; + -webkit-transition: color 0.1s ease, border-color 0.1s ease; + transition: color 0.1s ease, border-color 0.1s ease; +} + +/* Text Area */ + +.ui.form textarea { + margin: 0em; + -webkit-appearance: none; + tap-highlight-color: rgba(255, 255, 255, 0); + padding: 0.78571429em 1em; + background: #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + outline: none; + color: rgba(0, 0, 0, 0.87); + border-radius: 0.28571429rem; + box-shadow: 0em 0em 0em 0em transparent inset; + -webkit-transition: color 0.1s ease, border-color 0.1s ease; + transition: color 0.1s ease, border-color 0.1s ease; + font-size: 1em; + line-height: 1.2857; + resize: vertical; +} + +.ui.form textarea:not([rows]) { + height: 12em; + min-height: 8em; + max-height: 24em; +} + +.ui.form textarea, +.ui.form input[type="checkbox"] { + vertical-align: top; +} + +/*-------------------------- + Input w/ attached Button +---------------------------*/ + +.ui.form input.attached { + width: auto; +} + +/*-------------------- + Basic Select +---------------------*/ + +.ui.form select { + display: block; + height: auto; + width: 100%; + background: #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + border-radius: 0.28571429rem; + box-shadow: 0em 0em 0em 0em transparent inset; + padding: 0.62em 1em; + color: rgba(0, 0, 0, 0.87); + -webkit-transition: color 0.1s ease, border-color 0.1s ease; + transition: color 0.1s ease, border-color 0.1s ease; +} + +/*-------------------- + Dropdown +---------------------*/ + +/* Block */ + +.ui.form .field > .selection.dropdown { + width: 100%; +} + +.ui.form .field > .selection.dropdown > .dropdown.icon { + float: right; +} + +/* Inline */ + +.ui.form .inline.fields .field > .selection.dropdown, +.ui.form .inline.field > .selection.dropdown { + width: auto; +} + +.ui.form .inline.fields .field > .selection.dropdown > .dropdown.icon, +.ui.form .inline.field > .selection.dropdown > .dropdown.icon { + float: none; +} + +/*-------------------- + UI Input +---------------------*/ + +/* Block */ + +.ui.form .field .ui.input, +.ui.form .fields .field .ui.input, +.ui.form .wide.field .ui.input { + width: 100%; +} + +/* Inline */ + +.ui.form .inline.fields .field:not(.wide) .ui.input, +.ui.form .inline.field:not(.wide) .ui.input { + width: auto; + vertical-align: middle; +} + +/* Auto Input */ + +.ui.form .fields .field .ui.input input, +.ui.form .field .ui.input input { + width: auto; +} + +/* Full Width Input */ + +.ui.form .ten.fields .ui.input input, +.ui.form .nine.fields .ui.input input, +.ui.form .eight.fields .ui.input input, +.ui.form .seven.fields .ui.input input, +.ui.form .six.fields .ui.input input, +.ui.form .five.fields .ui.input input, +.ui.form .four.fields .ui.input input, +.ui.form .three.fields .ui.input input, +.ui.form .two.fields .ui.input input, +.ui.form .wide.field .ui.input input { + -webkit-box-flex: 1; + -webkit-flex: 1 0 auto; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + width: 0px; +} + +/*-------------------- + Types of Messages +---------------------*/ + +.ui.form .success.message, +.ui.form .warning.message, +.ui.form .error.message { + display: none; +} + +/* Assumptions */ + +.ui.form .message:first-child { + margin-top: 0px; +} + +/*-------------------- + Validation Prompt +---------------------*/ + +.ui.form .field .prompt.label { + white-space: normal; + background: #FFFFFF !important; + border: 1px solid #E0B4B4 !important; + color: #9F3A38 !important; +} + +.ui.form .inline.fields .field .prompt, +.ui.form .inline.field .prompt { + vertical-align: top; + margin: -0.25em 0em -0.5em 0.5em; +} + +.ui.form .inline.fields .field .prompt:before, +.ui.form .inline.field .prompt:before { + border-width: 0px 0px 1px 1px; + bottom: auto; + right: auto; + top: 50%; + left: 0em; +} + +/******************************* + States +*******************************/ + +/*-------------------- + Autofilled +---------------------*/ + +.ui.form .field.field input:-webkit-autofill { + box-shadow: 0px 0px 0px 100px #FFFFF0 inset !important; + border-color: #E5DFA1 !important; +} + +/* Focus */ + +.ui.form .field.field input:-webkit-autofill:focus { + box-shadow: 0px 0px 0px 100px #FFFFF0 inset !important; + border-color: #D5C315 !important; +} + +/* Error */ + +.ui.form .error.error input:-webkit-autofill { + box-shadow: 0px 0px 0px 100px #FFFAF0 inset !important; + border-color: #E0B4B4 !important; +} + +/*-------------------- + Placeholder +---------------------*/ + +/* browsers require these rules separate */ + +.ui.form ::-webkit-input-placeholder { + color: rgba(191, 191, 191, 0.87); +} + +.ui.form :-ms-input-placeholder { + color: rgba(191, 191, 191, 0.87); +} + +.ui.form ::-moz-placeholder { + color: rgba(191, 191, 191, 0.87); +} + +.ui.form :focus::-webkit-input-placeholder { + color: rgba(115, 115, 115, 0.87); +} + +.ui.form :focus:-ms-input-placeholder { + color: rgba(115, 115, 115, 0.87); +} + +.ui.form :focus::-moz-placeholder { + color: rgba(115, 115, 115, 0.87); +} + +/* Error Placeholder */ + +.ui.form .error ::-webkit-input-placeholder { + color: #e7bdbc; +} + +.ui.form .error :-ms-input-placeholder { + color: #e7bdbc !important; +} + +.ui.form .error ::-moz-placeholder { + color: #e7bdbc; +} + +.ui.form .error :focus::-webkit-input-placeholder { + color: #da9796; +} + +.ui.form .error :focus:-ms-input-placeholder { + color: #da9796 !important; +} + +.ui.form .error :focus::-moz-placeholder { + color: #da9796; +} + +/*-------------------- + Focus +---------------------*/ + +.ui.form input:not([type]):focus, +.ui.form input[type="date"]:focus, +.ui.form input[type="datetime-local"]:focus, +.ui.form input[type="email"]:focus, +.ui.form input[type="number"]:focus, +.ui.form input[type="password"]:focus, +.ui.form input[type="search"]:focus, +.ui.form input[type="tel"]:focus, +.ui.form input[type="time"]:focus, +.ui.form input[type="text"]:focus, +.ui.form input[type="file"]:focus, +.ui.form input[type="url"]:focus { + color: rgba(0, 0, 0, 0.95); + border-color: #85B7D9; + border-radius: 0.28571429rem; + background: #FFFFFF; + box-shadow: 0px 0em 0em 0em rgba(34, 36, 38, 0.35) inset; +} + +.ui.form textarea:focus { + color: rgba(0, 0, 0, 0.95); + border-color: #85B7D9; + border-radius: 0.28571429rem; + background: #FFFFFF; + box-shadow: 0px 0em 0em 0em rgba(34, 36, 38, 0.35) inset; + -webkit-appearance: none; +} + +/*-------------------- + Success +---------------------*/ + +/* On Form */ + +.ui.form.success .success.message:not(:empty) { + display: block; +} + +.ui.form.success .compact.success.message:not(:empty) { + display: inline-block; +} + +.ui.form.success .icon.success.message:not(:empty) { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +/*-------------------- + Warning +---------------------*/ + +/* On Form */ + +.ui.form.warning .warning.message:not(:empty) { + display: block; +} + +.ui.form.warning .compact.warning.message:not(:empty) { + display: inline-block; +} + +.ui.form.warning .icon.warning.message:not(:empty) { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +/*-------------------- + Error +---------------------*/ + +/* On Form */ + +.ui.form.error .error.message:not(:empty) { + display: block; +} + +.ui.form.error .compact.error.message:not(:empty) { + display: inline-block; +} + +.ui.form.error .icon.error.message:not(:empty) { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +/* On Field(s) */ + +.ui.form .fields.error .field label, +.ui.form .field.error label, +.ui.form .fields.error .field .input, +.ui.form .field.error .input { + color: #9F3A38; +} + +.ui.form .fields.error .field .corner.label, +.ui.form .field.error .corner.label { + border-color: #9F3A38; + color: #FFFFFF; +} + +.ui.form .fields.error .field textarea, +.ui.form .fields.error .field select, +.ui.form .fields.error .field input:not([type]), +.ui.form .fields.error .field input[type="date"], +.ui.form .fields.error .field input[type="datetime-local"], +.ui.form .fields.error .field input[type="email"], +.ui.form .fields.error .field input[type="number"], +.ui.form .fields.error .field input[type="password"], +.ui.form .fields.error .field input[type="search"], +.ui.form .fields.error .field input[type="tel"], +.ui.form .fields.error .field input[type="time"], +.ui.form .fields.error .field input[type="text"], +.ui.form .fields.error .field input[type="file"], +.ui.form .fields.error .field input[type="url"], +.ui.form .field.error textarea, +.ui.form .field.error select, +.ui.form .field.error input:not([type]), +.ui.form .field.error input[type="date"], +.ui.form .field.error input[type="datetime-local"], +.ui.form .field.error input[type="email"], +.ui.form .field.error input[type="number"], +.ui.form .field.error input[type="password"], +.ui.form .field.error input[type="search"], +.ui.form .field.error input[type="tel"], +.ui.form .field.error input[type="time"], +.ui.form .field.error input[type="text"], +.ui.form .field.error input[type="file"], +.ui.form .field.error input[type="url"] { + background: #FFF6F6; + border-color: #E0B4B4; + color: #9F3A38; + border-radius: ''; + box-shadow: none; +} + +.ui.form .field.error textarea:focus, +.ui.form .field.error select:focus, +.ui.form .field.error input:not([type]):focus, +.ui.form .field.error input[type="date"]:focus, +.ui.form .field.error input[type="datetime-local"]:focus, +.ui.form .field.error input[type="email"]:focus, +.ui.form .field.error input[type="number"]:focus, +.ui.form .field.error input[type="password"]:focus, +.ui.form .field.error input[type="search"]:focus, +.ui.form .field.error input[type="tel"]:focus, +.ui.form .field.error input[type="time"]:focus, +.ui.form .field.error input[type="text"]:focus, +.ui.form .field.error input[type="file"]:focus, +.ui.form .field.error input[type="url"]:focus { + background: #FFF6F6; + border-color: #E0B4B4; + color: #9F3A38; + -webkit-appearance: none; + box-shadow: none; +} + +/* Preserve Native Select Stylings */ + +.ui.form .field.error select { + -webkit-appearance: menulist-button; +} + +/*------------------ + Dropdown Error +--------------------*/ + +.ui.form .fields.error .field .ui.dropdown, +.ui.form .fields.error .field .ui.dropdown .item, +.ui.form .field.error .ui.dropdown, +.ui.form .field.error .ui.dropdown .text, +.ui.form .field.error .ui.dropdown .item { + background: #FFF6F6; + color: #9F3A38; +} + +.ui.form .fields.error .field .ui.dropdown, +.ui.form .field.error .ui.dropdown { + border-color: #E0B4B4 !important; +} + +.ui.form .fields.error .field .ui.dropdown:hover, +.ui.form .field.error .ui.dropdown:hover { + border-color: #E0B4B4 !important; +} + +.ui.form .fields.error .field .ui.dropdown:hover .menu, +.ui.form .field.error .ui.dropdown:hover .menu { + border-color: #E0B4B4; +} + +.ui.form .fields.error .field .ui.multiple.selection.dropdown > .label, +.ui.form .field.error .ui.multiple.selection.dropdown > .label { + background-color: #EACBCB; + color: #9F3A38; +} + +/* Hover */ + +.ui.form .fields.error .field .ui.dropdown .menu .item:hover, +.ui.form .field.error .ui.dropdown .menu .item:hover { + background-color: #FBE7E7; +} + +/* Selected */ + +.ui.form .fields.error .field .ui.dropdown .menu .selected.item, +.ui.form .field.error .ui.dropdown .menu .selected.item { + background-color: #FBE7E7; +} + +/* Active */ + +.ui.form .fields.error .field .ui.dropdown .menu .active.item, +.ui.form .field.error .ui.dropdown .menu .active.item { + background-color: #FDCFCF !important; +} + +/*-------------------- + Checkbox Error +---------------------*/ + +.ui.form .fields.error .field .checkbox:not(.toggle):not(.slider) label, +.ui.form .field.error .checkbox:not(.toggle):not(.slider) label, +.ui.form .fields.error .field .checkbox:not(.toggle):not(.slider) .box, +.ui.form .field.error .checkbox:not(.toggle):not(.slider) .box { + color: #9F3A38; +} + +.ui.form .fields.error .field .checkbox:not(.toggle):not(.slider) label:before, +.ui.form .field.error .checkbox:not(.toggle):not(.slider) label:before, +.ui.form .fields.error .field .checkbox:not(.toggle):not(.slider) .box:before, +.ui.form .field.error .checkbox:not(.toggle):not(.slider) .box:before { + background: #FFF6F6; + border-color: #E0B4B4; +} + +.ui.form .fields.error .field .checkbox label:after, +.ui.form .field.error .checkbox label:after, +.ui.form .fields.error .field .checkbox .box:after, +.ui.form .field.error .checkbox .box:after { + color: #9F3A38; +} + +/*-------------------- + Disabled +---------------------*/ + +.ui.form .disabled.fields .field, +.ui.form .disabled.field, +.ui.form .field :disabled { + pointer-events: none; + opacity: 0.45; +} + +.ui.form .field.disabled > label, +.ui.form .fields.disabled > label { + opacity: 0.45; +} + +.ui.form .field.disabled :disabled { + opacity: 1; +} + +/*-------------- + Loading +---------------*/ + +.ui.loading.form { + position: relative; + cursor: default; + pointer-events: none; +} + +.ui.loading.form:before { + position: absolute; + content: ''; + top: 0%; + left: 0%; + background: rgba(255, 255, 255, 0.8); + width: 100%; + height: 100%; + z-index: 100; +} + +.ui.loading.form:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -1.5em 0em 0em -1.5em; + width: 3em; + height: 3em; + -webkit-animation: form-spin 0.6s linear; + animation: form-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1); + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; + visibility: visible; + z-index: 101; +} + +@-webkit-keyframes form-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes form-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/******************************* + Element Types +*******************************/ + +/*-------------------- + Required Field +---------------------*/ + +.ui.form .required.fields:not(.grouped) > .field > label:after, +.ui.form .required.fields.grouped > label:after, +.ui.form .required.field > label:after, +.ui.form .required.fields:not(.grouped) > .field > .checkbox:after, +.ui.form .required.field > .checkbox:after { + margin: -0.2em 0em 0em 0.2em; + content: '*'; + color: #DB2828; +} + +.ui.form .required.fields:not(.grouped) > .field > label:after, +.ui.form .required.fields.grouped > label:after, +.ui.form .required.field > label:after { + display: inline-block; + vertical-align: top; +} + +.ui.form .required.fields:not(.grouped) > .field > .checkbox:after, +.ui.form .required.field > .checkbox:after { + position: absolute; + top: 0%; + left: 100%; +} + +/******************************* + Variations +*******************************/ + +/*-------------------- + Inverted Colors +---------------------*/ + +.ui.inverted.form label, +.ui.form .inverted.segment label, +.ui.form .inverted.segment .ui.checkbox label, +.ui.form .inverted.segment .ui.checkbox .box, +.ui.inverted.form .ui.checkbox label, +.ui.inverted.form .ui.checkbox .box, +.ui.inverted.form .inline.fields > label, +.ui.inverted.form .inline.fields .field > label, +.ui.inverted.form .inline.fields .field > p, +.ui.inverted.form .inline.field > label, +.ui.inverted.form .inline.field > p { + color: rgba(255, 255, 255, 0.9); +} + +/* Inverted Field */ + +.ui.inverted.form input:not([type]), +.ui.inverted.form input[type="date"], +.ui.inverted.form input[type="datetime-local"], +.ui.inverted.form input[type="email"], +.ui.inverted.form input[type="number"], +.ui.inverted.form input[type="password"], +.ui.inverted.form input[type="search"], +.ui.inverted.form input[type="tel"], +.ui.inverted.form input[type="time"], +.ui.inverted.form input[type="text"], +.ui.inverted.form input[type="file"], +.ui.inverted.form input[type="url"] { + background: #FFFFFF; + border-color: rgba(255, 255, 255, 0.1); + color: rgba(0, 0, 0, 0.87); + box-shadow: none; +} + +/*-------------------- + Field Groups +---------------------*/ + +/* Grouped Vertically */ + +.ui.form .grouped.fields { + display: block; + margin: 0em 0em 1em; +} + +.ui.form .grouped.fields:last-child { + margin-bottom: 0em; +} + +.ui.form .grouped.fields > label { + margin: 0em 0em 0.28571429rem 0em; + color: rgba(0, 0, 0, 0.87); + font-size: 0.92857143em; + font-weight: bold; + text-transform: none; +} + +.ui.form .grouped.fields .field, +.ui.form .grouped.inline.fields .field { + display: block; + margin: 0.5em 0em; + padding: 0em; +} + +/*-------------------- + Fields +---------------------*/ + +/* Split fields */ + +.ui.form .fields { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + margin: 0em -0.5em 1em; +} + +.ui.form .fields > .field { + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + padding-left: 0.5em; + padding-right: 0.5em; +} + +.ui.form .fields > .field:first-child { + border-left: none; + box-shadow: none; +} + +/* Other Combinations */ + +.ui.form .two.fields > .fields, +.ui.form .two.fields > .field { + width: 50%; +} + +.ui.form .three.fields > .fields, +.ui.form .three.fields > .field { + width: 33.33333333%; +} + +.ui.form .four.fields > .fields, +.ui.form .four.fields > .field { + width: 25%; +} + +.ui.form .five.fields > .fields, +.ui.form .five.fields > .field { + width: 20%; +} + +.ui.form .six.fields > .fields, +.ui.form .six.fields > .field { + width: 16.66666667%; +} + +.ui.form .seven.fields > .fields, +.ui.form .seven.fields > .field { + width: 14.28571429%; +} + +.ui.form .eight.fields > .fields, +.ui.form .eight.fields > .field { + width: 12.5%; +} + +.ui.form .nine.fields > .fields, +.ui.form .nine.fields > .field { + width: 11.11111111%; +} + +.ui.form .ten.fields > .fields, +.ui.form .ten.fields > .field { + width: 10%; +} + +/* Swap to full width on mobile */ + +@media only screen and (max-width: 767px) { + .ui.form .fields { + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + } + + .ui[class*="equal width"].form .fields > .field, + .ui.form [class*="equal width"].fields > .field, + .ui.form .two.fields > .fields, + .ui.form .two.fields > .field, + .ui.form .three.fields > .fields, + .ui.form .three.fields > .field, + .ui.form .four.fields > .fields, + .ui.form .four.fields > .field, + .ui.form .five.fields > .fields, + .ui.form .five.fields > .field, + .ui.form .six.fields > .fields, + .ui.form .six.fields > .field, + .ui.form .seven.fields > .fields, + .ui.form .seven.fields > .field, + .ui.form .eight.fields > .fields, + .ui.form .eight.fields > .field, + .ui.form .nine.fields > .fields, + .ui.form .nine.fields > .field, + .ui.form .ten.fields > .fields, + .ui.form .ten.fields > .field { + width: 100% !important; + margin: 0em 0em 1em; + } +} + +/* Sizing Combinations */ + +.ui.form .fields .wide.field { + width: 6.25%; + padding-left: 0.5em; + padding-right: 0.5em; +} + +.ui.form .one.wide.field { + width: 6.25% !important; +} + +.ui.form .two.wide.field { + width: 12.5% !important; +} + +.ui.form .three.wide.field { + width: 18.75% !important; +} + +.ui.form .four.wide.field { + width: 25% !important; +} + +.ui.form .five.wide.field { + width: 31.25% !important; +} + +.ui.form .six.wide.field { + width: 37.5% !important; +} + +.ui.form .seven.wide.field { + width: 43.75% !important; +} + +.ui.form .eight.wide.field { + width: 50% !important; +} + +.ui.form .nine.wide.field { + width: 56.25% !important; +} + +.ui.form .ten.wide.field { + width: 62.5% !important; +} + +.ui.form .eleven.wide.field { + width: 68.75% !important; +} + +.ui.form .twelve.wide.field { + width: 75% !important; +} + +.ui.form .thirteen.wide.field { + width: 81.25% !important; +} + +.ui.form .fourteen.wide.field { + width: 87.5% !important; +} + +.ui.form .fifteen.wide.field { + width: 93.75% !important; +} + +.ui.form .sixteen.wide.field { + width: 100% !important; +} + +/* Swap to full width on mobile */ + +@media only screen and (max-width: 767px) { + .ui.form .two.fields > .fields, + .ui.form .two.fields > .field, + .ui.form .three.fields > .fields, + .ui.form .three.fields > .field, + .ui.form .four.fields > .fields, + .ui.form .four.fields > .field, + .ui.form .five.fields > .fields, + .ui.form .five.fields > .field, + .ui.form .fields > .two.wide.field, + .ui.form .fields > .three.wide.field, + .ui.form .fields > .four.wide.field, + .ui.form .fields > .five.wide.field, + .ui.form .fields > .six.wide.field, + .ui.form .fields > .seven.wide.field, + .ui.form .fields > .eight.wide.field, + .ui.form .fields > .nine.wide.field, + .ui.form .fields > .ten.wide.field, + .ui.form .fields > .eleven.wide.field, + .ui.form .fields > .twelve.wide.field, + .ui.form .fields > .thirteen.wide.field, + .ui.form .fields > .fourteen.wide.field, + .ui.form .fields > .fifteen.wide.field, + .ui.form .fields > .sixteen.wide.field { + width: 100% !important; + } + + .ui.form .fields { + margin-bottom: 0em; + } +} + +/*-------------------- + Equal Width +---------------------*/ + +.ui[class*="equal width"].form .fields > .field, +.ui.form [class*="equal width"].fields > .field { + width: 100%; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; +} + +/*-------------------- + Inline Fields +---------------------*/ + +.ui.form .inline.fields { + margin: 0em 0em 1em; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + -ms-grid-row-align: center; + align-items: center; +} + +.ui.form .inline.fields .field { + margin: 0em; + padding: 0em 1em 0em 0em; +} + +/* Inline Label */ + +.ui.form .inline.fields > label, +.ui.form .inline.fields .field > label, +.ui.form .inline.fields .field > p, +.ui.form .inline.field > label, +.ui.form .inline.field > p { + display: inline-block; + width: auto; + margin-top: 0em; + margin-bottom: 0em; + vertical-align: baseline; + font-size: 0.92857143em; + font-weight: bold; + color: rgba(0, 0, 0, 0.87); + text-transform: none; +} + +/* Grouped Inline Label */ + +.ui.form .inline.fields > label { + margin: 0.035714em 1em 0em 0em; +} + +/* Inline Input */ + +.ui.form .inline.fields .field > input, +.ui.form .inline.fields .field > select, +.ui.form .inline.field > input, +.ui.form .inline.field > select { + display: inline-block; + width: auto; + margin-top: 0em; + margin-bottom: 0em; + vertical-align: middle; + font-size: 1em; +} + +/* Label */ + +.ui.form .inline.fields .field > :first-child, +.ui.form .inline.field > :first-child { + margin: 0em 0.85714286em 0em 0em; +} + +.ui.form .inline.fields .field > :only-child, +.ui.form .inline.field > :only-child { + margin: 0em; +} + +/* Wide */ + +.ui.form .inline.fields .wide.field { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; +} + +.ui.form .inline.fields .wide.field > input, +.ui.form .inline.fields .wide.field > select { + width: 100%; +} + +/*-------------------- + Sizes +---------------------*/ + +.ui.mini.form { + font-size: 0.78571429rem; +} + +.ui.tiny.form { + font-size: 0.85714286rem; +} + +.ui.small.form { + font-size: 0.92857143rem; +} + +.ui.form { + font-size: 1rem; +} + +.ui.large.form { + font-size: 1.14285714rem; +} + +.ui.big.form { + font-size: 1.28571429rem; +} + +.ui.huge.form { + font-size: 1.42857143rem; +} + +.ui.massive.form { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Grid + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Standard +*******************************/ + +.ui.grid { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; + padding: 0em; +} + +/*---------------------- + Remove Gutters +-----------------------*/ + +.ui.grid { + margin-top: -1rem; + margin-bottom: -1rem; + margin-left: -1rem; + margin-right: -1rem; +} + +.ui.relaxed.grid { + margin-left: -1.5rem; + margin-right: -1.5rem; +} + +.ui[class*="very relaxed"].grid { + margin-left: -2.5rem; + margin-right: -2.5rem; +} + +/* Preserve Rows Spacing on Consecutive Grids */ + +.ui.grid + .grid { + margin-top: 1rem; +} + +/*------------------- + Columns +--------------------*/ + +/* Standard 16 column */ + +.ui.grid > .column:not(.row), +.ui.grid > .row > .column { + position: relative; + display: inline-block; + width: 6.25%; + padding-left: 1rem; + padding-right: 1rem; + vertical-align: top; +} + +.ui.grid > * { + padding-left: 1rem; + padding-right: 1rem; +} + +/*------------------- + Rows +--------------------*/ + +.ui.grid > .row { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: inherit; + -webkit-justify-content: inherit; + -ms-flex-pack: inherit; + justify-content: inherit; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; + width: 100% !important; + padding: 0rem; + padding-top: 1rem; + padding-bottom: 1rem; +} + +/*------------------- + Columns +--------------------*/ + +/* Vertical padding when no rows */ + +.ui.grid > .column:not(.row) { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.ui.grid > .row > .column { + margin-top: 0em; + margin-bottom: 0em; +} + +/*------------------- + Content +--------------------*/ + +.ui.grid > .row > img, +.ui.grid > .row > .column > img { + max-width: 100%; +} + +/*------------------- + Loose Coupling +--------------------*/ + +/* Collapse Margin on Consecutive Grid */ + +.ui.grid > .ui.grid:first-child { + margin-top: 0em; +} + +.ui.grid > .ui.grid:last-child { + margin-bottom: 0em; +} + +/* Segment inside Aligned Grid */ + +.ui.grid .aligned.row > .column > .segment:not(.compact):not(.attached), +.ui.aligned.grid .column > .segment:not(.compact):not(.attached) { + width: 100%; +} + +/* Align Dividers with Gutter */ + +.ui.grid .row + .ui.divider { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + margin: 1rem 1rem; +} + +.ui.grid .column + .ui.vertical.divider { + height: calc(50% - 1rem ); +} + +/* Remove Border on Last Horizontal Segment */ + +.ui.grid > .row > .column:last-child > .horizontal.segment, +.ui.grid > .column:last-child > .horizontal.segment { + box-shadow: none; +} + +/******************************* + Variations +*******************************/ + +/*----------------------- + Page Grid +-------------------------*/ + +@media only screen and (max-width: 767px) { + .ui.page.grid { + width: auto; + padding-left: 0em; + padding-right: 0em; + margin-left: 0em; + margin-right: 0em; + } +} + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui.page.grid { + width: auto; + margin-left: 0em; + margin-right: 0em; + padding-left: 2em; + padding-right: 2em; + } +} + +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .ui.page.grid { + width: auto; + margin-left: 0em; + margin-right: 0em; + padding-left: 3%; + padding-right: 3%; + } +} + +@media only screen and (min-width: 1200px) and (max-width: 1919px) { + .ui.page.grid { + width: auto; + margin-left: 0em; + margin-right: 0em; + padding-left: 15%; + padding-right: 15%; + } +} + +@media only screen and (min-width: 1920px) { + .ui.page.grid { + width: auto; + margin-left: 0em; + margin-right: 0em; + padding-left: 23%; + padding-right: 23%; + } +} + +/*------------------- + Column Count +--------------------*/ + +/* Assume full width with one column */ + +.ui.grid > .column:only-child, +.ui.grid > .row > .column:only-child { + width: 100%; +} + +/* Grid Based */ + +.ui[class*="one column"].grid > .row > .column, +.ui[class*="one column"].grid > .column:not(.row) { + width: 100%; +} + +.ui[class*="two column"].grid > .row > .column, +.ui[class*="two column"].grid > .column:not(.row) { + width: 50%; +} + +.ui[class*="three column"].grid > .row > .column, +.ui[class*="three column"].grid > .column:not(.row) { + width: 33.33333333%; +} + +.ui[class*="four column"].grid > .row > .column, +.ui[class*="four column"].grid > .column:not(.row) { + width: 25%; +} + +.ui[class*="five column"].grid > .row > .column, +.ui[class*="five column"].grid > .column:not(.row) { + width: 20%; +} + +.ui[class*="six column"].grid > .row > .column, +.ui[class*="six column"].grid > .column:not(.row) { + width: 16.66666667%; +} + +.ui[class*="seven column"].grid > .row > .column, +.ui[class*="seven column"].grid > .column:not(.row) { + width: 14.28571429%; +} + +.ui[class*="eight column"].grid > .row > .column, +.ui[class*="eight column"].grid > .column:not(.row) { + width: 12.5%; +} + +.ui[class*="nine column"].grid > .row > .column, +.ui[class*="nine column"].grid > .column:not(.row) { + width: 11.11111111%; +} + +.ui[class*="ten column"].grid > .row > .column, +.ui[class*="ten column"].grid > .column:not(.row) { + width: 10%; +} + +.ui[class*="eleven column"].grid > .row > .column, +.ui[class*="eleven column"].grid > .column:not(.row) { + width: 9.09090909%; +} + +.ui[class*="twelve column"].grid > .row > .column, +.ui[class*="twelve column"].grid > .column:not(.row) { + width: 8.33333333%; +} + +.ui[class*="thirteen column"].grid > .row > .column, +.ui[class*="thirteen column"].grid > .column:not(.row) { + width: 7.69230769%; +} + +.ui[class*="fourteen column"].grid > .row > .column, +.ui[class*="fourteen column"].grid > .column:not(.row) { + width: 7.14285714%; +} + +.ui[class*="fifteen column"].grid > .row > .column, +.ui[class*="fifteen column"].grid > .column:not(.row) { + width: 6.66666667%; +} + +.ui[class*="sixteen column"].grid > .row > .column, +.ui[class*="sixteen column"].grid > .column:not(.row) { + width: 6.25%; +} + +/* Row Based Overrides */ + +.ui.grid > [class*="one column"].row > .column { + width: 100% !important; +} + +.ui.grid > [class*="two column"].row > .column { + width: 50% !important; +} + +.ui.grid > [class*="three column"].row > .column { + width: 33.33333333% !important; +} + +.ui.grid > [class*="four column"].row > .column { + width: 25% !important; +} + +.ui.grid > [class*="five column"].row > .column { + width: 20% !important; +} + +.ui.grid > [class*="six column"].row > .column { + width: 16.66666667% !important; +} + +.ui.grid > [class*="seven column"].row > .column { + width: 14.28571429% !important; +} + +.ui.grid > [class*="eight column"].row > .column { + width: 12.5% !important; +} + +.ui.grid > [class*="nine column"].row > .column { + width: 11.11111111% !important; +} + +.ui.grid > [class*="ten column"].row > .column { + width: 10% !important; +} + +.ui.grid > [class*="eleven column"].row > .column { + width: 9.09090909% !important; +} + +.ui.grid > [class*="twelve column"].row > .column { + width: 8.33333333% !important; +} + +.ui.grid > [class*="thirteen column"].row > .column { + width: 7.69230769% !important; +} + +.ui.grid > [class*="fourteen column"].row > .column { + width: 7.14285714% !important; +} + +.ui.grid > [class*="fifteen column"].row > .column { + width: 6.66666667% !important; +} + +.ui.grid > [class*="sixteen column"].row > .column { + width: 6.25% !important; +} + +/* Celled Page */ + +.ui.celled.page.grid { + box-shadow: none; +} + +/*------------------- + Column Width +--------------------*/ + +/* Sizing Combinations */ + +.ui.grid > .row > [class*="one wide"].column, +.ui.grid > .column.row > [class*="one wide"].column, +.ui.grid > [class*="one wide"].column, +.ui.column.grid > [class*="one wide"].column { + width: 6.25% !important; +} + +.ui.grid > .row > [class*="two wide"].column, +.ui.grid > .column.row > [class*="two wide"].column, +.ui.grid > [class*="two wide"].column, +.ui.column.grid > [class*="two wide"].column { + width: 12.5% !important; +} + +.ui.grid > .row > [class*="three wide"].column, +.ui.grid > .column.row > [class*="three wide"].column, +.ui.grid > [class*="three wide"].column, +.ui.column.grid > [class*="three wide"].column { + width: 18.75% !important; +} + +.ui.grid > .row > [class*="four wide"].column, +.ui.grid > .column.row > [class*="four wide"].column, +.ui.grid > [class*="four wide"].column, +.ui.column.grid > [class*="four wide"].column { + width: 25% !important; +} + +.ui.grid > .row > [class*="five wide"].column, +.ui.grid > .column.row > [class*="five wide"].column, +.ui.grid > [class*="five wide"].column, +.ui.column.grid > [class*="five wide"].column { + width: 31.25% !important; +} + +.ui.grid > .row > [class*="six wide"].column, +.ui.grid > .column.row > [class*="six wide"].column, +.ui.grid > [class*="six wide"].column, +.ui.column.grid > [class*="six wide"].column { + width: 37.5% !important; +} + +.ui.grid > .row > [class*="seven wide"].column, +.ui.grid > .column.row > [class*="seven wide"].column, +.ui.grid > [class*="seven wide"].column, +.ui.column.grid > [class*="seven wide"].column { + width: 43.75% !important; +} + +.ui.grid > .row > [class*="eight wide"].column, +.ui.grid > .column.row > [class*="eight wide"].column, +.ui.grid > [class*="eight wide"].column, +.ui.column.grid > [class*="eight wide"].column { + width: 50% !important; +} + +.ui.grid > .row > [class*="nine wide"].column, +.ui.grid > .column.row > [class*="nine wide"].column, +.ui.grid > [class*="nine wide"].column, +.ui.column.grid > [class*="nine wide"].column { + width: 56.25% !important; +} + +.ui.grid > .row > [class*="ten wide"].column, +.ui.grid > .column.row > [class*="ten wide"].column, +.ui.grid > [class*="ten wide"].column, +.ui.column.grid > [class*="ten wide"].column { + width: 62.5% !important; +} + +.ui.grid > .row > [class*="eleven wide"].column, +.ui.grid > .column.row > [class*="eleven wide"].column, +.ui.grid > [class*="eleven wide"].column, +.ui.column.grid > [class*="eleven wide"].column { + width: 68.75% !important; +} + +.ui.grid > .row > [class*="twelve wide"].column, +.ui.grid > .column.row > [class*="twelve wide"].column, +.ui.grid > [class*="twelve wide"].column, +.ui.column.grid > [class*="twelve wide"].column { + width: 75% !important; +} + +.ui.grid > .row > [class*="thirteen wide"].column, +.ui.grid > .column.row > [class*="thirteen wide"].column, +.ui.grid > [class*="thirteen wide"].column, +.ui.column.grid > [class*="thirteen wide"].column { + width: 81.25% !important; +} + +.ui.grid > .row > [class*="fourteen wide"].column, +.ui.grid > .column.row > [class*="fourteen wide"].column, +.ui.grid > [class*="fourteen wide"].column, +.ui.column.grid > [class*="fourteen wide"].column { + width: 87.5% !important; +} + +.ui.grid > .row > [class*="fifteen wide"].column, +.ui.grid > .column.row > [class*="fifteen wide"].column, +.ui.grid > [class*="fifteen wide"].column, +.ui.column.grid > [class*="fifteen wide"].column { + width: 93.75% !important; +} + +.ui.grid > .row > [class*="sixteen wide"].column, +.ui.grid > .column.row > [class*="sixteen wide"].column, +.ui.grid > [class*="sixteen wide"].column, +.ui.column.grid > [class*="sixteen wide"].column { + width: 100% !important; +} + +/*---------------------- + Width per Device +-----------------------*/ + +/* Mobile Sizing Combinations */ + +@media only screen and (min-width: 320px) and (max-width: 767px) { + .ui.grid > .row > [class*="one wide mobile"].column, + .ui.grid > .column.row > [class*="one wide mobile"].column, + .ui.grid > [class*="one wide mobile"].column, + .ui.column.grid > [class*="one wide mobile"].column { + width: 6.25% !important; + } + + .ui.grid > .row > [class*="two wide mobile"].column, + .ui.grid > .column.row > [class*="two wide mobile"].column, + .ui.grid > [class*="two wide mobile"].column, + .ui.column.grid > [class*="two wide mobile"].column { + width: 12.5% !important; + } + + .ui.grid > .row > [class*="three wide mobile"].column, + .ui.grid > .column.row > [class*="three wide mobile"].column, + .ui.grid > [class*="three wide mobile"].column, + .ui.column.grid > [class*="three wide mobile"].column { + width: 18.75% !important; + } + + .ui.grid > .row > [class*="four wide mobile"].column, + .ui.grid > .column.row > [class*="four wide mobile"].column, + .ui.grid > [class*="four wide mobile"].column, + .ui.column.grid > [class*="four wide mobile"].column { + width: 25% !important; + } + + .ui.grid > .row > [class*="five wide mobile"].column, + .ui.grid > .column.row > [class*="five wide mobile"].column, + .ui.grid > [class*="five wide mobile"].column, + .ui.column.grid > [class*="five wide mobile"].column { + width: 31.25% !important; + } + + .ui.grid > .row > [class*="six wide mobile"].column, + .ui.grid > .column.row > [class*="six wide mobile"].column, + .ui.grid > [class*="six wide mobile"].column, + .ui.column.grid > [class*="six wide mobile"].column { + width: 37.5% !important; + } + + .ui.grid > .row > [class*="seven wide mobile"].column, + .ui.grid > .column.row > [class*="seven wide mobile"].column, + .ui.grid > [class*="seven wide mobile"].column, + .ui.column.grid > [class*="seven wide mobile"].column { + width: 43.75% !important; + } + + .ui.grid > .row > [class*="eight wide mobile"].column, + .ui.grid > .column.row > [class*="eight wide mobile"].column, + .ui.grid > [class*="eight wide mobile"].column, + .ui.column.grid > [class*="eight wide mobile"].column { + width: 50% !important; + } + + .ui.grid > .row > [class*="nine wide mobile"].column, + .ui.grid > .column.row > [class*="nine wide mobile"].column, + .ui.grid > [class*="nine wide mobile"].column, + .ui.column.grid > [class*="nine wide mobile"].column { + width: 56.25% !important; + } + + .ui.grid > .row > [class*="ten wide mobile"].column, + .ui.grid > .column.row > [class*="ten wide mobile"].column, + .ui.grid > [class*="ten wide mobile"].column, + .ui.column.grid > [class*="ten wide mobile"].column { + width: 62.5% !important; + } + + .ui.grid > .row > [class*="eleven wide mobile"].column, + .ui.grid > .column.row > [class*="eleven wide mobile"].column, + .ui.grid > [class*="eleven wide mobile"].column, + .ui.column.grid > [class*="eleven wide mobile"].column { + width: 68.75% !important; + } + + .ui.grid > .row > [class*="twelve wide mobile"].column, + .ui.grid > .column.row > [class*="twelve wide mobile"].column, + .ui.grid > [class*="twelve wide mobile"].column, + .ui.column.grid > [class*="twelve wide mobile"].column { + width: 75% !important; + } + + .ui.grid > .row > [class*="thirteen wide mobile"].column, + .ui.grid > .column.row > [class*="thirteen wide mobile"].column, + .ui.grid > [class*="thirteen wide mobile"].column, + .ui.column.grid > [class*="thirteen wide mobile"].column { + width: 81.25% !important; + } + + .ui.grid > .row > [class*="fourteen wide mobile"].column, + .ui.grid > .column.row > [class*="fourteen wide mobile"].column, + .ui.grid > [class*="fourteen wide mobile"].column, + .ui.column.grid > [class*="fourteen wide mobile"].column { + width: 87.5% !important; + } + + .ui.grid > .row > [class*="fifteen wide mobile"].column, + .ui.grid > .column.row > [class*="fifteen wide mobile"].column, + .ui.grid > [class*="fifteen wide mobile"].column, + .ui.column.grid > [class*="fifteen wide mobile"].column { + width: 93.75% !important; + } + + .ui.grid > .row > [class*="sixteen wide mobile"].column, + .ui.grid > .column.row > [class*="sixteen wide mobile"].column, + .ui.grid > [class*="sixteen wide mobile"].column, + .ui.column.grid > [class*="sixteen wide mobile"].column { + width: 100% !important; + } +} + +/* Tablet Sizing Combinations */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui.grid > .row > [class*="one wide tablet"].column, + .ui.grid > .column.row > [class*="one wide tablet"].column, + .ui.grid > [class*="one wide tablet"].column, + .ui.column.grid > [class*="one wide tablet"].column { + width: 6.25% !important; + } + + .ui.grid > .row > [class*="two wide tablet"].column, + .ui.grid > .column.row > [class*="two wide tablet"].column, + .ui.grid > [class*="two wide tablet"].column, + .ui.column.grid > [class*="two wide tablet"].column { + width: 12.5% !important; + } + + .ui.grid > .row > [class*="three wide tablet"].column, + .ui.grid > .column.row > [class*="three wide tablet"].column, + .ui.grid > [class*="three wide tablet"].column, + .ui.column.grid > [class*="three wide tablet"].column { + width: 18.75% !important; + } + + .ui.grid > .row > [class*="four wide tablet"].column, + .ui.grid > .column.row > [class*="four wide tablet"].column, + .ui.grid > [class*="four wide tablet"].column, + .ui.column.grid > [class*="four wide tablet"].column { + width: 25% !important; + } + + .ui.grid > .row > [class*="five wide tablet"].column, + .ui.grid > .column.row > [class*="five wide tablet"].column, + .ui.grid > [class*="five wide tablet"].column, + .ui.column.grid > [class*="five wide tablet"].column { + width: 31.25% !important; + } + + .ui.grid > .row > [class*="six wide tablet"].column, + .ui.grid > .column.row > [class*="six wide tablet"].column, + .ui.grid > [class*="six wide tablet"].column, + .ui.column.grid > [class*="six wide tablet"].column { + width: 37.5% !important; + } + + .ui.grid > .row > [class*="seven wide tablet"].column, + .ui.grid > .column.row > [class*="seven wide tablet"].column, + .ui.grid > [class*="seven wide tablet"].column, + .ui.column.grid > [class*="seven wide tablet"].column { + width: 43.75% !important; + } + + .ui.grid > .row > [class*="eight wide tablet"].column, + .ui.grid > .column.row > [class*="eight wide tablet"].column, + .ui.grid > [class*="eight wide tablet"].column, + .ui.column.grid > [class*="eight wide tablet"].column { + width: 50% !important; + } + + .ui.grid > .row > [class*="nine wide tablet"].column, + .ui.grid > .column.row > [class*="nine wide tablet"].column, + .ui.grid > [class*="nine wide tablet"].column, + .ui.column.grid > [class*="nine wide tablet"].column { + width: 56.25% !important; + } + + .ui.grid > .row > [class*="ten wide tablet"].column, + .ui.grid > .column.row > [class*="ten wide tablet"].column, + .ui.grid > [class*="ten wide tablet"].column, + .ui.column.grid > [class*="ten wide tablet"].column { + width: 62.5% !important; + } + + .ui.grid > .row > [class*="eleven wide tablet"].column, + .ui.grid > .column.row > [class*="eleven wide tablet"].column, + .ui.grid > [class*="eleven wide tablet"].column, + .ui.column.grid > [class*="eleven wide tablet"].column { + width: 68.75% !important; + } + + .ui.grid > .row > [class*="twelve wide tablet"].column, + .ui.grid > .column.row > [class*="twelve wide tablet"].column, + .ui.grid > [class*="twelve wide tablet"].column, + .ui.column.grid > [class*="twelve wide tablet"].column { + width: 75% !important; + } + + .ui.grid > .row > [class*="thirteen wide tablet"].column, + .ui.grid > .column.row > [class*="thirteen wide tablet"].column, + .ui.grid > [class*="thirteen wide tablet"].column, + .ui.column.grid > [class*="thirteen wide tablet"].column { + width: 81.25% !important; + } + + .ui.grid > .row > [class*="fourteen wide tablet"].column, + .ui.grid > .column.row > [class*="fourteen wide tablet"].column, + .ui.grid > [class*="fourteen wide tablet"].column, + .ui.column.grid > [class*="fourteen wide tablet"].column { + width: 87.5% !important; + } + + .ui.grid > .row > [class*="fifteen wide tablet"].column, + .ui.grid > .column.row > [class*="fifteen wide tablet"].column, + .ui.grid > [class*="fifteen wide tablet"].column, + .ui.column.grid > [class*="fifteen wide tablet"].column { + width: 93.75% !important; + } + + .ui.grid > .row > [class*="sixteen wide tablet"].column, + .ui.grid > .column.row > [class*="sixteen wide tablet"].column, + .ui.grid > [class*="sixteen wide tablet"].column, + .ui.column.grid > [class*="sixteen wide tablet"].column { + width: 100% !important; + } +} + +/* Computer/Desktop Sizing Combinations */ + +@media only screen and (min-width: 992px) { + .ui.grid > .row > [class*="one wide computer"].column, + .ui.grid > .column.row > [class*="one wide computer"].column, + .ui.grid > [class*="one wide computer"].column, + .ui.column.grid > [class*="one wide computer"].column { + width: 6.25% !important; + } + + .ui.grid > .row > [class*="two wide computer"].column, + .ui.grid > .column.row > [class*="two wide computer"].column, + .ui.grid > [class*="two wide computer"].column, + .ui.column.grid > [class*="two wide computer"].column { + width: 12.5% !important; + } + + .ui.grid > .row > [class*="three wide computer"].column, + .ui.grid > .column.row > [class*="three wide computer"].column, + .ui.grid > [class*="three wide computer"].column, + .ui.column.grid > [class*="three wide computer"].column { + width: 18.75% !important; + } + + .ui.grid > .row > [class*="four wide computer"].column, + .ui.grid > .column.row > [class*="four wide computer"].column, + .ui.grid > [class*="four wide computer"].column, + .ui.column.grid > [class*="four wide computer"].column { + width: 25% !important; + } + + .ui.grid > .row > [class*="five wide computer"].column, + .ui.grid > .column.row > [class*="five wide computer"].column, + .ui.grid > [class*="five wide computer"].column, + .ui.column.grid > [class*="five wide computer"].column { + width: 31.25% !important; + } + + .ui.grid > .row > [class*="six wide computer"].column, + .ui.grid > .column.row > [class*="six wide computer"].column, + .ui.grid > [class*="six wide computer"].column, + .ui.column.grid > [class*="six wide computer"].column { + width: 37.5% !important; + } + + .ui.grid > .row > [class*="seven wide computer"].column, + .ui.grid > .column.row > [class*="seven wide computer"].column, + .ui.grid > [class*="seven wide computer"].column, + .ui.column.grid > [class*="seven wide computer"].column { + width: 43.75% !important; + } + + .ui.grid > .row > [class*="eight wide computer"].column, + .ui.grid > .column.row > [class*="eight wide computer"].column, + .ui.grid > [class*="eight wide computer"].column, + .ui.column.grid > [class*="eight wide computer"].column { + width: 50% !important; + } + + .ui.grid > .row > [class*="nine wide computer"].column, + .ui.grid > .column.row > [class*="nine wide computer"].column, + .ui.grid > [class*="nine wide computer"].column, + .ui.column.grid > [class*="nine wide computer"].column { + width: 56.25% !important; + } + + .ui.grid > .row > [class*="ten wide computer"].column, + .ui.grid > .column.row > [class*="ten wide computer"].column, + .ui.grid > [class*="ten wide computer"].column, + .ui.column.grid > [class*="ten wide computer"].column { + width: 62.5% !important; + } + + .ui.grid > .row > [class*="eleven wide computer"].column, + .ui.grid > .column.row > [class*="eleven wide computer"].column, + .ui.grid > [class*="eleven wide computer"].column, + .ui.column.grid > [class*="eleven wide computer"].column { + width: 68.75% !important; + } + + .ui.grid > .row > [class*="twelve wide computer"].column, + .ui.grid > .column.row > [class*="twelve wide computer"].column, + .ui.grid > [class*="twelve wide computer"].column, + .ui.column.grid > [class*="twelve wide computer"].column { + width: 75% !important; + } + + .ui.grid > .row > [class*="thirteen wide computer"].column, + .ui.grid > .column.row > [class*="thirteen wide computer"].column, + .ui.grid > [class*="thirteen wide computer"].column, + .ui.column.grid > [class*="thirteen wide computer"].column { + width: 81.25% !important; + } + + .ui.grid > .row > [class*="fourteen wide computer"].column, + .ui.grid > .column.row > [class*="fourteen wide computer"].column, + .ui.grid > [class*="fourteen wide computer"].column, + .ui.column.grid > [class*="fourteen wide computer"].column { + width: 87.5% !important; + } + + .ui.grid > .row > [class*="fifteen wide computer"].column, + .ui.grid > .column.row > [class*="fifteen wide computer"].column, + .ui.grid > [class*="fifteen wide computer"].column, + .ui.column.grid > [class*="fifteen wide computer"].column { + width: 93.75% !important; + } + + .ui.grid > .row > [class*="sixteen wide computer"].column, + .ui.grid > .column.row > [class*="sixteen wide computer"].column, + .ui.grid > [class*="sixteen wide computer"].column, + .ui.column.grid > [class*="sixteen wide computer"].column { + width: 100% !important; + } +} + +/* Large Monitor Sizing Combinations */ + +@media only screen and (min-width: 1200px) and (max-width: 1919px) { + .ui.grid > .row > [class*="one wide large screen"].column, + .ui.grid > .column.row > [class*="one wide large screen"].column, + .ui.grid > [class*="one wide large screen"].column, + .ui.column.grid > [class*="one wide large screen"].column { + width: 6.25% !important; + } + + .ui.grid > .row > [class*="two wide large screen"].column, + .ui.grid > .column.row > [class*="two wide large screen"].column, + .ui.grid > [class*="two wide large screen"].column, + .ui.column.grid > [class*="two wide large screen"].column { + width: 12.5% !important; + } + + .ui.grid > .row > [class*="three wide large screen"].column, + .ui.grid > .column.row > [class*="three wide large screen"].column, + .ui.grid > [class*="three wide large screen"].column, + .ui.column.grid > [class*="three wide large screen"].column { + width: 18.75% !important; + } + + .ui.grid > .row > [class*="four wide large screen"].column, + .ui.grid > .column.row > [class*="four wide large screen"].column, + .ui.grid > [class*="four wide large screen"].column, + .ui.column.grid > [class*="four wide large screen"].column { + width: 25% !important; + } + + .ui.grid > .row > [class*="five wide large screen"].column, + .ui.grid > .column.row > [class*="five wide large screen"].column, + .ui.grid > [class*="five wide large screen"].column, + .ui.column.grid > [class*="five wide large screen"].column { + width: 31.25% !important; + } + + .ui.grid > .row > [class*="six wide large screen"].column, + .ui.grid > .column.row > [class*="six wide large screen"].column, + .ui.grid > [class*="six wide large screen"].column, + .ui.column.grid > [class*="six wide large screen"].column { + width: 37.5% !important; + } + + .ui.grid > .row > [class*="seven wide large screen"].column, + .ui.grid > .column.row > [class*="seven wide large screen"].column, + .ui.grid > [class*="seven wide large screen"].column, + .ui.column.grid > [class*="seven wide large screen"].column { + width: 43.75% !important; + } + + .ui.grid > .row > [class*="eight wide large screen"].column, + .ui.grid > .column.row > [class*="eight wide large screen"].column, + .ui.grid > [class*="eight wide large screen"].column, + .ui.column.grid > [class*="eight wide large screen"].column { + width: 50% !important; + } + + .ui.grid > .row > [class*="nine wide large screen"].column, + .ui.grid > .column.row > [class*="nine wide large screen"].column, + .ui.grid > [class*="nine wide large screen"].column, + .ui.column.grid > [class*="nine wide large screen"].column { + width: 56.25% !important; + } + + .ui.grid > .row > [class*="ten wide large screen"].column, + .ui.grid > .column.row > [class*="ten wide large screen"].column, + .ui.grid > [class*="ten wide large screen"].column, + .ui.column.grid > [class*="ten wide large screen"].column { + width: 62.5% !important; + } + + .ui.grid > .row > [class*="eleven wide large screen"].column, + .ui.grid > .column.row > [class*="eleven wide large screen"].column, + .ui.grid > [class*="eleven wide large screen"].column, + .ui.column.grid > [class*="eleven wide large screen"].column { + width: 68.75% !important; + } + + .ui.grid > .row > [class*="twelve wide large screen"].column, + .ui.grid > .column.row > [class*="twelve wide large screen"].column, + .ui.grid > [class*="twelve wide large screen"].column, + .ui.column.grid > [class*="twelve wide large screen"].column { + width: 75% !important; + } + + .ui.grid > .row > [class*="thirteen wide large screen"].column, + .ui.grid > .column.row > [class*="thirteen wide large screen"].column, + .ui.grid > [class*="thirteen wide large screen"].column, + .ui.column.grid > [class*="thirteen wide large screen"].column { + width: 81.25% !important; + } + + .ui.grid > .row > [class*="fourteen wide large screen"].column, + .ui.grid > .column.row > [class*="fourteen wide large screen"].column, + .ui.grid > [class*="fourteen wide large screen"].column, + .ui.column.grid > [class*="fourteen wide large screen"].column { + width: 87.5% !important; + } + + .ui.grid > .row > [class*="fifteen wide large screen"].column, + .ui.grid > .column.row > [class*="fifteen wide large screen"].column, + .ui.grid > [class*="fifteen wide large screen"].column, + .ui.column.grid > [class*="fifteen wide large screen"].column { + width: 93.75% !important; + } + + .ui.grid > .row > [class*="sixteen wide large screen"].column, + .ui.grid > .column.row > [class*="sixteen wide large screen"].column, + .ui.grid > [class*="sixteen wide large screen"].column, + .ui.column.grid > [class*="sixteen wide large screen"].column { + width: 100% !important; + } +} + +/* Widescreen Sizing Combinations */ + +@media only screen and (min-width: 1920px) { + .ui.grid > .row > [class*="one wide widescreen"].column, + .ui.grid > .column.row > [class*="one wide widescreen"].column, + .ui.grid > [class*="one wide widescreen"].column, + .ui.column.grid > [class*="one wide widescreen"].column { + width: 6.25% !important; + } + + .ui.grid > .row > [class*="two wide widescreen"].column, + .ui.grid > .column.row > [class*="two wide widescreen"].column, + .ui.grid > [class*="two wide widescreen"].column, + .ui.column.grid > [class*="two wide widescreen"].column { + width: 12.5% !important; + } + + .ui.grid > .row > [class*="three wide widescreen"].column, + .ui.grid > .column.row > [class*="three wide widescreen"].column, + .ui.grid > [class*="three wide widescreen"].column, + .ui.column.grid > [class*="three wide widescreen"].column { + width: 18.75% !important; + } + + .ui.grid > .row > [class*="four wide widescreen"].column, + .ui.grid > .column.row > [class*="four wide widescreen"].column, + .ui.grid > [class*="four wide widescreen"].column, + .ui.column.grid > [class*="four wide widescreen"].column { + width: 25% !important; + } + + .ui.grid > .row > [class*="five wide widescreen"].column, + .ui.grid > .column.row > [class*="five wide widescreen"].column, + .ui.grid > [class*="five wide widescreen"].column, + .ui.column.grid > [class*="five wide widescreen"].column { + width: 31.25% !important; + } + + .ui.grid > .row > [class*="six wide widescreen"].column, + .ui.grid > .column.row > [class*="six wide widescreen"].column, + .ui.grid > [class*="six wide widescreen"].column, + .ui.column.grid > [class*="six wide widescreen"].column { + width: 37.5% !important; + } + + .ui.grid > .row > [class*="seven wide widescreen"].column, + .ui.grid > .column.row > [class*="seven wide widescreen"].column, + .ui.grid > [class*="seven wide widescreen"].column, + .ui.column.grid > [class*="seven wide widescreen"].column { + width: 43.75% !important; + } + + .ui.grid > .row > [class*="eight wide widescreen"].column, + .ui.grid > .column.row > [class*="eight wide widescreen"].column, + .ui.grid > [class*="eight wide widescreen"].column, + .ui.column.grid > [class*="eight wide widescreen"].column { + width: 50% !important; + } + + .ui.grid > .row > [class*="nine wide widescreen"].column, + .ui.grid > .column.row > [class*="nine wide widescreen"].column, + .ui.grid > [class*="nine wide widescreen"].column, + .ui.column.grid > [class*="nine wide widescreen"].column { + width: 56.25% !important; + } + + .ui.grid > .row > [class*="ten wide widescreen"].column, + .ui.grid > .column.row > [class*="ten wide widescreen"].column, + .ui.grid > [class*="ten wide widescreen"].column, + .ui.column.grid > [class*="ten wide widescreen"].column { + width: 62.5% !important; + } + + .ui.grid > .row > [class*="eleven wide widescreen"].column, + .ui.grid > .column.row > [class*="eleven wide widescreen"].column, + .ui.grid > [class*="eleven wide widescreen"].column, + .ui.column.grid > [class*="eleven wide widescreen"].column { + width: 68.75% !important; + } + + .ui.grid > .row > [class*="twelve wide widescreen"].column, + .ui.grid > .column.row > [class*="twelve wide widescreen"].column, + .ui.grid > [class*="twelve wide widescreen"].column, + .ui.column.grid > [class*="twelve wide widescreen"].column { + width: 75% !important; + } + + .ui.grid > .row > [class*="thirteen wide widescreen"].column, + .ui.grid > .column.row > [class*="thirteen wide widescreen"].column, + .ui.grid > [class*="thirteen wide widescreen"].column, + .ui.column.grid > [class*="thirteen wide widescreen"].column { + width: 81.25% !important; + } + + .ui.grid > .row > [class*="fourteen wide widescreen"].column, + .ui.grid > .column.row > [class*="fourteen wide widescreen"].column, + .ui.grid > [class*="fourteen wide widescreen"].column, + .ui.column.grid > [class*="fourteen wide widescreen"].column { + width: 87.5% !important; + } + + .ui.grid > .row > [class*="fifteen wide widescreen"].column, + .ui.grid > .column.row > [class*="fifteen wide widescreen"].column, + .ui.grid > [class*="fifteen wide widescreen"].column, + .ui.column.grid > [class*="fifteen wide widescreen"].column { + width: 93.75% !important; + } + + .ui.grid > .row > [class*="sixteen wide widescreen"].column, + .ui.grid > .column.row > [class*="sixteen wide widescreen"].column, + .ui.grid > [class*="sixteen wide widescreen"].column, + .ui.column.grid > [class*="sixteen wide widescreen"].column { + width: 100% !important; + } +} + +/*---------------------- + Centered +-----------------------*/ + +.ui.centered.grid, +.ui.centered.grid > .row, +.ui.grid > .centered.row { + text-align: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +.ui.centered.grid > .column:not(.aligned):not(.justified):not(.row), +.ui.centered.grid > .row > .column:not(.aligned):not(.justified), +.ui.grid .centered.row > .column:not(.aligned):not(.justified) { + text-align: left; +} + +.ui.grid > .centered.column, +.ui.grid > .row > .centered.column { + display: block; + margin-left: auto; + margin-right: auto; +} + +/*---------------------- + Relaxed +-----------------------*/ + +.ui.relaxed.grid > .column:not(.row), +.ui.relaxed.grid > .row > .column, +.ui.grid > .relaxed.row > .column { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.ui[class*="very relaxed"].grid > .column:not(.row), +.ui[class*="very relaxed"].grid > .row > .column, +.ui.grid > [class*="very relaxed"].row > .column { + padding-left: 2.5rem; + padding-right: 2.5rem; +} + +/* Coupling with UI Divider */ + +.ui.relaxed.grid .row + .ui.divider, +.ui.grid .relaxed.row + .ui.divider { + margin-left: 1.5rem; + margin-right: 1.5rem; +} + +.ui[class*="very relaxed"].grid .row + .ui.divider, +.ui.grid [class*="very relaxed"].row + .ui.divider { + margin-left: 2.5rem; + margin-right: 2.5rem; +} + +/*---------------------- + Padded +-----------------------*/ + +.ui.padded.grid:not(.vertically):not(.horizontally) { + margin: 0em !important; +} + +[class*="horizontally padded"].ui.grid { + margin-left: 0em !important; + margin-right: 0em !important; +} + +[class*="vertically padded"].ui.grid { + margin-top: 0em !important; + margin-bottom: 0em !important; +} + +/*---------------------- + "Floated" +-----------------------*/ + +.ui.grid [class*="left floated"].column { + margin-right: auto; +} + +.ui.grid [class*="right floated"].column { + margin-left: auto; +} + +/*---------------------- + Divided +-----------------------*/ + +.ui.divided.grid:not([class*="vertically divided"]) > .column:not(.row), +.ui.divided.grid:not([class*="vertically divided"]) > .row > .column { + box-shadow: -1px 0px 0px 0px rgba(34, 36, 38, 0.15); +} + +/* Swap from padding to margin on columns to have dividers align */ + +.ui[class*="vertically divided"].grid > .column:not(.row), +.ui[class*="vertically divided"].grid > .row > .column { + margin-top: 1rem; + margin-bottom: 1rem; + padding-top: 0rem; + padding-bottom: 0rem; +} + +.ui[class*="vertically divided"].grid > .row { + margin-top: 0em; + margin-bottom: 0em; +} + +/* No divider on first column on row */ + +.ui.divided.grid:not([class*="vertically divided"]) > .column:first-child, +.ui.divided.grid:not([class*="vertically divided"]) > .row > .column:first-child { + box-shadow: none; +} + +/* No space on top of first row */ + +.ui[class*="vertically divided"].grid > .row:first-child > .column { + margin-top: 0em; +} + +/* Divided Row */ + +.ui.grid > .divided.row > .column { + box-shadow: -1px 0px 0px 0px rgba(34, 36, 38, 0.15); +} + +.ui.grid > .divided.row > .column:first-child { + box-shadow: none; +} + +/* Vertically Divided */ + +.ui[class*="vertically divided"].grid > .row { + position: relative; +} + +.ui[class*="vertically divided"].grid > .row:before { + position: absolute; + content: ""; + top: 0em; + left: 0px; + width: calc(100% - 2rem ); + height: 1px; + margin: 0% 1rem; + box-shadow: 0px -1px 0px 0px rgba(34, 36, 38, 0.15); +} + +/* Padded Horizontally Divided */ + +[class*="horizontally padded"].ui.divided.grid, +.ui.padded.divided.grid:not(.vertically):not(.horizontally) { + width: 100%; +} + +/* First Row Vertically Divided */ + +.ui[class*="vertically divided"].grid > .row:first-child:before { + box-shadow: none; +} + +/* Inverted Divided */ + +.ui.inverted.divided.grid:not([class*="vertically divided"]) > .column:not(.row), +.ui.inverted.divided.grid:not([class*="vertically divided"]) > .row > .column { + box-shadow: -1px 0px 0px 0px rgba(255, 255, 255, 0.1); +} + +.ui.inverted.divided.grid:not([class*="vertically divided"]) > .column:not(.row):first-child, +.ui.inverted.divided.grid:not([class*="vertically divided"]) > .row > .column:first-child { + box-shadow: none; +} + +.ui.inverted[class*="vertically divided"].grid > .row:before { + box-shadow: 0px -1px 0px 0px rgba(255, 255, 255, 0.1); +} + +/* Relaxed */ + +.ui.relaxed[class*="vertically divided"].grid > .row:before { + margin-left: 1.5rem; + margin-right: 1.5rem; + width: calc(100% - 3rem ); +} + +.ui[class*="very relaxed"][class*="vertically divided"].grid > .row:before { + margin-left: 5rem; + margin-right: 5rem; + width: calc(100% - 5rem ); +} + +/*---------------------- + Celled +-----------------------*/ + +.ui.celled.grid { + width: 100%; + margin: 1em 0em; + box-shadow: 0px 0px 0px 1px #D4D4D5; +} + +.ui.celled.grid > .row { + width: 100% !important; + margin: 0em; + padding: 0em; + box-shadow: 0px -1px 0px 0px #D4D4D5; +} + +.ui.celled.grid > .column:not(.row), +.ui.celled.grid > .row > .column { + box-shadow: -1px 0px 0px 0px #D4D4D5; +} + +.ui.celled.grid > .column:first-child, +.ui.celled.grid > .row > .column:first-child { + box-shadow: none; +} + +.ui.celled.grid > .column:not(.row), +.ui.celled.grid > .row > .column { + padding: 1em; +} + +.ui.relaxed.celled.grid > .column:not(.row), +.ui.relaxed.celled.grid > .row > .column { + padding: 1.5em; +} + +.ui[class*="very relaxed"].celled.grid > .column:not(.row), +.ui[class*="very relaxed"].celled.grid > .row > .column { + padding: 2em; +} + +/* Internally Celled */ + +.ui[class*="internally celled"].grid { + box-shadow: none; + margin: 0em; +} + +.ui[class*="internally celled"].grid > .row:first-child { + box-shadow: none; +} + +.ui[class*="internally celled"].grid > .row > .column:first-child { + box-shadow: none; +} + +/*---------------------- + Vertically Aligned +-----------------------*/ + +/* Top Aligned */ + +.ui[class*="top aligned"].grid > .column:not(.row), +.ui[class*="top aligned"].grid > .row > .column, +.ui.grid > [class*="top aligned"].row > .column, +.ui.grid > [class*="top aligned"].column:not(.row), +.ui.grid > .row > [class*="top aligned"].column { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + vertical-align: top; + -webkit-align-self: flex-start !important; + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +/* Middle Aligned */ + +.ui[class*="middle aligned"].grid > .column:not(.row), +.ui[class*="middle aligned"].grid > .row > .column, +.ui.grid > [class*="middle aligned"].row > .column, +.ui.grid > [class*="middle aligned"].column:not(.row), +.ui.grid > .row > [class*="middle aligned"].column { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + vertical-align: middle; + -webkit-align-self: center !important; + -ms-flex-item-align: center !important; + align-self: center !important; +} + +/* Bottom Aligned */ + +.ui[class*="bottom aligned"].grid > .column:not(.row), +.ui[class*="bottom aligned"].grid > .row > .column, +.ui.grid > [class*="bottom aligned"].row > .column, +.ui.grid > [class*="bottom aligned"].column:not(.row), +.ui.grid > .row > [class*="bottom aligned"].column { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + vertical-align: bottom; + -webkit-align-self: flex-end !important; + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +/* Stretched */ + +.ui.stretched.grid > .row > .column, +.ui.stretched.grid > .column, +.ui.grid > .stretched.row > .column, +.ui.grid > .stretched.column:not(.row), +.ui.grid > .row > .stretched.column { + display: -webkit-inline-box !important; + display: -webkit-inline-flex !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +.ui.stretched.grid > .row > .column > *, +.ui.stretched.grid > .column > *, +.ui.grid > .stretched.row > .column > *, +.ui.grid > .stretched.column:not(.row) > *, +.ui.grid > .row > .stretched.column > * { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +/*---------------------- + Horizontally Centered +-----------------------*/ + +/* Left Aligned */ + +.ui[class*="left aligned"].grid > .column, +.ui[class*="left aligned"].grid > .row > .column, +.ui.grid > [class*="left aligned"].row > .column, +.ui.grid > [class*="left aligned"].column.column, +.ui.grid > .row > [class*="left aligned"].column.column { + text-align: left; + -webkit-align-self: inherit; + -ms-flex-item-align: inherit; + align-self: inherit; +} + +/* Center Aligned */ + +.ui[class*="center aligned"].grid > .column, +.ui[class*="center aligned"].grid > .row > .column, +.ui.grid > [class*="center aligned"].row > .column, +.ui.grid > [class*="center aligned"].column.column, +.ui.grid > .row > [class*="center aligned"].column.column { + text-align: center; + -webkit-align-self: inherit; + -ms-flex-item-align: inherit; + align-self: inherit; +} + +.ui[class*="center aligned"].grid { + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +/* Right Aligned */ + +.ui[class*="right aligned"].grid > .column, +.ui[class*="right aligned"].grid > .row > .column, +.ui.grid > [class*="right aligned"].row > .column, +.ui.grid > [class*="right aligned"].column.column, +.ui.grid > .row > [class*="right aligned"].column.column { + text-align: right; + -webkit-align-self: inherit; + -ms-flex-item-align: inherit; + align-self: inherit; +} + +/* Justified */ + +.ui.justified.grid > .column, +.ui.justified.grid > .row > .column, +.ui.grid > .justified.row > .column, +.ui.grid > .justified.column.column, +.ui.grid > .row > .justified.column.column { + text-align: justify; + -webkit-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; +} + +/*---------------------- + Colored +-----------------------*/ + +.ui.grid > .row > .red.column, +.ui.grid > .row > .orange.column, +.ui.grid > .row > .yellow.column, +.ui.grid > .row > .olive.column, +.ui.grid > .row > .green.column, +.ui.grid > .row > .teal.column, +.ui.grid > .row > .blue.column, +.ui.grid > .row > .violet.column, +.ui.grid > .row > .purple.column, +.ui.grid > .row > .pink.column, +.ui.grid > .row > .brown.column, +.ui.grid > .row > .grey.column, +.ui.grid > .row > .black.column { + margin-top: -1rem; + margin-bottom: -1rem; + padding-top: 1rem; + padding-bottom: 1rem; +} + +/* Red */ + +.ui.grid > .red.row, +.ui.grid > .red.column, +.ui.grid > .row > .red.column { + background-color: #DB2828 !important; + color: #FFFFFF; +} + +/* Orange */ + +.ui.grid > .orange.row, +.ui.grid > .orange.column, +.ui.grid > .row > .orange.column { + background-color: #F2711C !important; + color: #FFFFFF; +} + +/* Yellow */ + +.ui.grid > .yellow.row, +.ui.grid > .yellow.column, +.ui.grid > .row > .yellow.column { + background-color: #FBBD08 !important; + color: #FFFFFF; +} + +/* Olive */ + +.ui.grid > .olive.row, +.ui.grid > .olive.column, +.ui.grid > .row > .olive.column { + background-color: #B5CC18 !important; + color: #FFFFFF; +} + +/* Green */ + +.ui.grid > .green.row, +.ui.grid > .green.column, +.ui.grid > .row > .green.column { + background-color: #21BA45 !important; + color: #FFFFFF; +} + +/* Teal */ + +.ui.grid > .teal.row, +.ui.grid > .teal.column, +.ui.grid > .row > .teal.column { + background-color: #00B5AD !important; + color: #FFFFFF; +} + +/* Blue */ + +.ui.grid > .blue.row, +.ui.grid > .blue.column, +.ui.grid > .row > .blue.column { + background-color: #2185D0 !important; + color: #FFFFFF; +} + +/* Violet */ + +.ui.grid > .violet.row, +.ui.grid > .violet.column, +.ui.grid > .row > .violet.column { + background-color: #6435C9 !important; + color: #FFFFFF; +} + +/* Purple */ + +.ui.grid > .purple.row, +.ui.grid > .purple.column, +.ui.grid > .row > .purple.column { + background-color: #A333C8 !important; + color: #FFFFFF; +} + +/* Pink */ + +.ui.grid > .pink.row, +.ui.grid > .pink.column, +.ui.grid > .row > .pink.column { + background-color: #E03997 !important; + color: #FFFFFF; +} + +/* Brown */ + +.ui.grid > .brown.row, +.ui.grid > .brown.column, +.ui.grid > .row > .brown.column { + background-color: #A5673F !important; + color: #FFFFFF; +} + +/* Grey */ + +.ui.grid > .grey.row, +.ui.grid > .grey.column, +.ui.grid > .row > .grey.column { + background-color: #767676 !important; + color: #FFFFFF; +} + +/* Black */ + +.ui.grid > .black.row, +.ui.grid > .black.column, +.ui.grid > .row > .black.column { + background-color: #1B1C1D !important; + color: #FFFFFF; +} + +/*---------------------- + Equal Width +-----------------------*/ + +.ui[class*="equal width"].grid > .column:not(.row), +.ui[class*="equal width"].grid > .row > .column, +.ui.grid > [class*="equal width"].row > .column { + display: inline-block; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.ui[class*="equal width"].grid > .wide.column, +.ui[class*="equal width"].grid > .row > .wide.column, +.ui.grid > [class*="equal width"].row > .wide.column { + -webkit-box-flex: 0; + -webkit-flex-grow: 0; + -ms-flex-positive: 0; + flex-grow: 0; +} + +/*---------------------- + Reverse +-----------------------*/ + +/* Mobile */ + +@media only screen and (max-width: 767px) { + .ui[class*="mobile reversed"].grid, + .ui[class*="mobile reversed"].grid > .row, + .ui.grid > [class*="mobile reversed"].row { + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + .ui[class*="mobile vertically reversed"].grid, + .ui.stackable[class*="mobile reversed"] { + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + /* Divided Reversed */ + + .ui[class*="mobile reversed"].divided.grid:not([class*="vertically divided"]) > .column:first-child, + .ui[class*="mobile reversed"].divided.grid:not([class*="vertically divided"]) > .row > .column:first-child { + box-shadow: -1px 0px 0px 0px rgba(34, 36, 38, 0.15); + } + + .ui[class*="mobile reversed"].divided.grid:not([class*="vertically divided"]) > .column:last-child, + .ui[class*="mobile reversed"].divided.grid:not([class*="vertically divided"]) > .row > .column:last-child { + box-shadow: none; + } + + /* Vertically Divided Reversed */ + + .ui.grid[class*="vertically divided"][class*="mobile vertically reversed"] > .row:first-child:before { + box-shadow: 0px -1px 0px 0px rgba(34, 36, 38, 0.15); + } + + .ui.grid[class*="vertically divided"][class*="mobile vertically reversed"] > .row:last-child:before { + box-shadow: none; + } + + /* Celled Reversed */ + + .ui[class*="mobile reversed"].celled.grid > .row > .column:first-child { + box-shadow: -1px 0px 0px 0px #D4D4D5; + } + + .ui[class*="mobile reversed"].celled.grid > .row > .column:last-child { + box-shadow: none; + } +} + +/* Tablet */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui[class*="tablet reversed"].grid, + .ui[class*="tablet reversed"].grid > .row, + .ui.grid > [class*="tablet reversed"].row { + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + .ui[class*="tablet vertically reversed"].grid { + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + /* Divided Reversed */ + + .ui[class*="tablet reversed"].divided.grid:not([class*="vertically divided"]) > .column:first-child, + .ui[class*="tablet reversed"].divided.grid:not([class*="vertically divided"]) > .row > .column:first-child { + box-shadow: -1px 0px 0px 0px rgba(34, 36, 38, 0.15); + } + + .ui[class*="tablet reversed"].divided.grid:not([class*="vertically divided"]) > .column:last-child, + .ui[class*="tablet reversed"].divided.grid:not([class*="vertically divided"]) > .row > .column:last-child { + box-shadow: none; + } + + /* Vertically Divided Reversed */ + + .ui.grid[class*="vertically divided"][class*="tablet vertically reversed"] > .row:first-child:before { + box-shadow: 0px -1px 0px 0px rgba(34, 36, 38, 0.15); + } + + .ui.grid[class*="vertically divided"][class*="tablet vertically reversed"] > .row:last-child:before { + box-shadow: none; + } + + /* Celled Reversed */ + + .ui[class*="tablet reversed"].celled.grid > .row > .column:first-child { + box-shadow: -1px 0px 0px 0px #D4D4D5; + } + + .ui[class*="tablet reversed"].celled.grid > .row > .column:last-child { + box-shadow: none; + } +} + +/* Computer */ + +@media only screen and (min-width: 992px) { + .ui[class*="computer reversed"].grid, + .ui[class*="computer reversed"].grid > .row, + .ui.grid > [class*="computer reversed"].row { + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + .ui[class*="computer vertically reversed"].grid { + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + /* Divided Reversed */ + + .ui[class*="computer reversed"].divided.grid:not([class*="vertically divided"]) > .column:first-child, + .ui[class*="computer reversed"].divided.grid:not([class*="vertically divided"]) > .row > .column:first-child { + box-shadow: -1px 0px 0px 0px rgba(34, 36, 38, 0.15); + } + + .ui[class*="computer reversed"].divided.grid:not([class*="vertically divided"]) > .column:last-child, + .ui[class*="computer reversed"].divided.grid:not([class*="vertically divided"]) > .row > .column:last-child { + box-shadow: none; + } + + /* Vertically Divided Reversed */ + + .ui.grid[class*="vertically divided"][class*="computer vertically reversed"] > .row:first-child:before { + box-shadow: 0px -1px 0px 0px rgba(34, 36, 38, 0.15); + } + + .ui.grid[class*="vertically divided"][class*="computer vertically reversed"] > .row:last-child:before { + box-shadow: none; + } + + /* Celled Reversed */ + + .ui[class*="computer reversed"].celled.grid > .row > .column:first-child { + box-shadow: -1px 0px 0px 0px #D4D4D5; + } + + .ui[class*="computer reversed"].celled.grid > .row > .column:last-child { + box-shadow: none; + } +} + +/*------------------- + Doubling +--------------------*/ + +/* Tablet Only */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui.doubling.grid { + width: auto; + } + + .ui.grid > .doubling.row, + .ui.doubling.grid > .row { + margin: 0em !important; + padding: 0em !important; + } + + .ui.grid > .doubling.row > .column, + .ui.doubling.grid > .row > .column { + display: inline-block !important; + padding-top: 1rem !important; + padding-bottom: 1rem !important; + box-shadow: none !important; + margin: 0em; + } + + .ui[class*="two column"].doubling.grid > .row > .column, + .ui[class*="two column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="two column"].doubling.row.row > .column { + width: 100% !important; + } + + .ui[class*="three column"].doubling.grid > .row > .column, + .ui[class*="three column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="three column"].doubling.row.row > .column { + width: 50% !important; + } + + .ui[class*="four column"].doubling.grid > .row > .column, + .ui[class*="four column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="four column"].doubling.row.row > .column { + width: 50% !important; + } + + .ui[class*="five column"].doubling.grid > .row > .column, + .ui[class*="five column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="five column"].doubling.row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="six column"].doubling.grid > .row > .column, + .ui[class*="six column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="six column"].doubling.row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="seven column"].doubling.grid > .row > .column, + .ui[class*="seven column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="seven column"].doubling.row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="eight column"].doubling.grid > .row > .column, + .ui[class*="eight column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="eight column"].doubling.row.row > .column { + width: 25% !important; + } + + .ui[class*="nine column"].doubling.grid > .row > .column, + .ui[class*="nine column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="nine column"].doubling.row.row > .column { + width: 25% !important; + } + + .ui[class*="ten column"].doubling.grid > .row > .column, + .ui[class*="ten column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="ten column"].doubling.row.row > .column { + width: 20% !important; + } + + .ui[class*="eleven column"].doubling.grid > .row > .column, + .ui[class*="eleven column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="eleven column"].doubling.row.row > .column { + width: 20% !important; + } + + .ui[class*="twelve column"].doubling.grid > .row > .column, + .ui[class*="twelve column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="twelve column"].doubling.row.row > .column { + width: 16.66666667% !important; + } + + .ui[class*="thirteen column"].doubling.grid > .row > .column, + .ui[class*="thirteen column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="thirteen column"].doubling.row.row > .column { + width: 16.66666667% !important; + } + + .ui[class*="fourteen column"].doubling.grid > .row > .column, + .ui[class*="fourteen column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="fourteen column"].doubling.row.row > .column { + width: 14.28571429% !important; + } + + .ui[class*="fifteen column"].doubling.grid > .row > .column, + .ui[class*="fifteen column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="fifteen column"].doubling.row.row > .column { + width: 14.28571429% !important; + } + + .ui[class*="sixteen column"].doubling.grid > .row > .column, + .ui[class*="sixteen column"].doubling.grid > .column:not(.row), + .ui.grid > [class*="sixteen column"].doubling.row.row > .column { + width: 12.5% !important; + } +} + +/* Mobile Only */ + +@media only screen and (max-width: 767px) { + .ui.grid > .doubling.row, + .ui.doubling.grid > .row { + margin: 0em !important; + padding: 0em !important; + } + + .ui.grid > .doubling.row > .column, + .ui.doubling.grid > .row > .column { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + margin: 0em !important; + box-shadow: none !important; + } + + .ui[class*="two column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="two column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="two column"].doubling:not(.stackable).row.row > .column { + width: 100% !important; + } + + .ui[class*="three column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="three column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="three column"].doubling:not(.stackable).row.row > .column { + width: 50% !important; + } + + .ui[class*="four column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="four column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="four column"].doubling:not(.stackable).row.row > .column { + width: 50% !important; + } + + .ui[class*="five column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="five column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="five column"].doubling:not(.stackable).row.row > .column { + width: 50% !important; + } + + .ui[class*="six column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="six column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="six column"].doubling:not(.stackable).row.row > .column { + width: 50% !important; + } + + .ui[class*="seven column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="seven column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="seven column"].doubling:not(.stackable).row.row > .column { + width: 50% !important; + } + + .ui[class*="eight column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="eight column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="eight column"].doubling:not(.stackable).row.row > .column { + width: 50% !important; + } + + .ui[class*="nine column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="nine column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="nine column"].doubling:not(.stackable).row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="ten column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="ten column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="ten column"].doubling:not(.stackable).row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="eleven column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="eleven column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="eleven column"].doubling:not(.stackable).row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="twelve column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="twelve column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="twelve column"].doubling:not(.stackable).row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="thirteen column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="thirteen column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="thirteen column"].doubling:not(.stackable).row.row > .column { + width: 33.33333333% !important; + } + + .ui[class*="fourteen column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="fourteen column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="fourteen column"].doubling:not(.stackable).row.row > .column { + width: 25% !important; + } + + .ui[class*="fifteen column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="fifteen column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="fifteen column"].doubling:not(.stackable).row.row > .column { + width: 25% !important; + } + + .ui[class*="sixteen column"].doubling:not(.stackable).grid > .row > .column, + .ui[class*="sixteen column"].doubling:not(.stackable).grid > .column:not(.row), + .ui.grid > [class*="sixteen column"].doubling:not(.stackable).row.row > .column { + width: 25% !important; + } +} + +/*------------------- + Stackable +--------------------*/ + +@media only screen and (max-width: 767px) { + .ui.stackable.grid { + width: auto; + margin-left: 0em !important; + margin-right: 0em !important; + } + + .ui.stackable.grid > .row > .wide.column, + .ui.stackable.grid > .wide.column, + .ui.stackable.grid > .column.grid > .column, + .ui.stackable.grid > .column.row > .column, + .ui.stackable.grid > .row > .column, + .ui.stackable.grid > .column:not(.row), + .ui.grid > .stackable.stackable.row > .column { + width: 100% !important; + margin: 0em 0em !important; + box-shadow: none !important; + padding: 1rem 1rem !important; + } + + .ui.stackable.grid:not(.vertically) > .row { + margin: 0em; + padding: 0em; + } + + /* Coupling */ + + .ui.container > .ui.stackable.grid > .column, + .ui.container > .ui.stackable.grid > .row > .column { + padding-left: 0em !important; + padding-right: 0em !important; + } + + /* Don't pad inside segment or nested grid */ + + .ui.grid .ui.stackable.grid, + .ui.segment:not(.vertical) .ui.stackable.page.grid { + margin-left: -1rem !important; + margin-right: -1rem !important; + } + + /* Divided Stackable */ + + .ui.stackable.divided.grid > .row:first-child > .column:first-child, + .ui.stackable.celled.grid > .row:first-child > .column:first-child, + .ui.stackable.divided.grid > .column:not(.row):first-child, + .ui.stackable.celled.grid > .column:not(.row):first-child { + border-top: none !important; + } + + .ui.inverted.stackable.celled.grid > .column:not(.row), + .ui.inverted.stackable.divided.grid > .column:not(.row), + .ui.inverted.stackable.celled.grid > .row > .column, + .ui.inverted.stackable.divided.grid > .row > .column { + border-top: 1px solid rgba(255, 255, 255, 0.1); + } + + .ui.stackable.celled.grid > .column:not(.row), + .ui.stackable.divided:not(.vertically).grid > .column:not(.row), + .ui.stackable.celled.grid > .row > .column, + .ui.stackable.divided:not(.vertically).grid > .row > .column { + border-top: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: none !important; + padding-top: 2rem !important; + padding-bottom: 2rem !important; + } + + .ui.stackable.celled.grid > .row { + box-shadow: none !important; + } + + .ui.stackable.divided:not(.vertically).grid > .column:not(.row), + .ui.stackable.divided:not(.vertically).grid > .row > .column { + padding-left: 0em !important; + padding-right: 0em !important; + } +} + +/*---------------------- + Only (Device) +-----------------------*/ + +/* These include arbitrary class repetitions for forced specificity */ + +/* Mobile Only Hide */ + +@media only screen and (max-width: 767px) { + .ui[class*="tablet only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="tablet only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="tablet only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="tablet only"].column:not(.mobile) { + display: none !important; + } + + .ui[class*="computer only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="computer only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="computer only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="computer only"].column:not(.mobile) { + display: none !important; + } + + .ui[class*="large screen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="large screen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="large screen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="large screen only"].column:not(.mobile) { + display: none !important; + } + + .ui[class*="widescreen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="widescreen only"].column:not(.mobile) { + display: none !important; + } +} + +/* Tablet Only Hide */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui[class*="mobile only"].grid.grid.grid:not(.tablet), + .ui.grid.grid.grid > [class*="mobile only"].row:not(.tablet), + .ui.grid.grid.grid > [class*="mobile only"].column:not(.tablet), + .ui.grid.grid.grid > .row > [class*="mobile only"].column:not(.tablet) { + display: none !important; + } + + .ui[class*="computer only"].grid.grid.grid:not(.tablet), + .ui.grid.grid.grid > [class*="computer only"].row:not(.tablet), + .ui.grid.grid.grid > [class*="computer only"].column:not(.tablet), + .ui.grid.grid.grid > .row > [class*="computer only"].column:not(.tablet) { + display: none !important; + } + + .ui[class*="large screen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="large screen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="large screen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="large screen only"].column:not(.mobile) { + display: none !important; + } + + .ui[class*="widescreen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="widescreen only"].column:not(.mobile) { + display: none !important; + } +} + +/* Computer Only Hide */ + +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .ui[class*="mobile only"].grid.grid.grid:not(.computer), + .ui.grid.grid.grid > [class*="mobile only"].row:not(.computer), + .ui.grid.grid.grid > [class*="mobile only"].column:not(.computer), + .ui.grid.grid.grid > .row > [class*="mobile only"].column:not(.computer) { + display: none !important; + } + + .ui[class*="tablet only"].grid.grid.grid:not(.computer), + .ui.grid.grid.grid > [class*="tablet only"].row:not(.computer), + .ui.grid.grid.grid > [class*="tablet only"].column:not(.computer), + .ui.grid.grid.grid > .row > [class*="tablet only"].column:not(.computer) { + display: none !important; + } + + .ui[class*="large screen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="large screen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="large screen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="large screen only"].column:not(.mobile) { + display: none !important; + } + + .ui[class*="widescreen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="widescreen only"].column:not(.mobile) { + display: none !important; + } +} + +/* Large Screen Only Hide */ + +@media only screen and (min-width: 1200px) and (max-width: 1919px) { + .ui[class*="mobile only"].grid.grid.grid:not(.computer), + .ui.grid.grid.grid > [class*="mobile only"].row:not(.computer), + .ui.grid.grid.grid > [class*="mobile only"].column:not(.computer), + .ui.grid.grid.grid > .row > [class*="mobile only"].column:not(.computer) { + display: none !important; + } + + .ui[class*="tablet only"].grid.grid.grid:not(.computer), + .ui.grid.grid.grid > [class*="tablet only"].row:not(.computer), + .ui.grid.grid.grid > [class*="tablet only"].column:not(.computer), + .ui.grid.grid.grid > .row > [class*="tablet only"].column:not(.computer) { + display: none !important; + } + + .ui[class*="widescreen only"].grid.grid.grid:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].row:not(.mobile), + .ui.grid.grid.grid > [class*="widescreen only"].column:not(.mobile), + .ui.grid.grid.grid > .row > [class*="widescreen only"].column:not(.mobile) { + display: none !important; + } +} + +/* Widescreen Only Hide */ + +@media only screen and (min-width: 1920px) { + .ui[class*="mobile only"].grid.grid.grid:not(.computer), + .ui.grid.grid.grid > [class*="mobile only"].row:not(.computer), + .ui.grid.grid.grid > [class*="mobile only"].column:not(.computer), + .ui.grid.grid.grid > .row > [class*="mobile only"].column:not(.computer) { + display: none !important; + } + + .ui[class*="tablet only"].grid.grid.grid:not(.computer), + .ui.grid.grid.grid > [class*="tablet only"].row:not(.computer), + .ui.grid.grid.grid > [class*="tablet only"].column:not(.computer), + .ui.grid.grid.grid > .row > [class*="tablet only"].column:not(.computer) { + display: none !important; + } +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/* + * # Semantic - Menu + * http://github.com/semantic-org/semantic-ui/ + * + * + * Copyright 2015 Contributor + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Standard +*******************************/ + +/*-------------- + Menu +---------------*/ + +.ui.menu { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin: 1rem 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + background: #FFFFFF; + font-weight: normal; + border: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15); + border-radius: 0.28571429rem; + min-height: 2.85714286em; +} + +.ui.menu:after { + content: ''; + display: block; + height: 0px; + clear: both; + visibility: hidden; +} + +.ui.menu:first-child { + margin-top: 0rem; +} + +.ui.menu:last-child { + margin-bottom: 0rem; +} + +/*-------------- + Sub-Menu +---------------*/ + +.ui.menu .menu { + margin: 0em; +} + +.ui.menu:not(.vertical) > .menu { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +/*-------------- + Item +---------------*/ + +.ui.menu:not(.vertical) .item { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; +} + +.ui.menu .item { + position: relative; + vertical-align: middle; + line-height: 1; + text-decoration: none; + -webkit-tap-highlight-color: transparent; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background: none; + padding: 0.92857143em 1.14285714em; + text-transform: none; + color: rgba(0, 0, 0, 0.87); + font-weight: normal; + -webkit-transition: background 0.1s ease, box-shadow 0.1s ease, color 0.1s ease; + transition: background 0.1s ease, box-shadow 0.1s ease, color 0.1s ease; +} + +.ui.menu > .item:first-child { + border-radius: 0.28571429rem 0px 0px 0.28571429rem; +} + +/* Border */ + +.ui.menu .item:before { + position: absolute; + content: ''; + top: 0%; + right: 0px; + height: 100%; + width: 1px; + background: rgba(34, 36, 38, 0.1); +} + +/*-------------- + Text Content +---------------*/ + +.ui.menu .text.item > *, +.ui.menu .item > a:not(.ui), +.ui.menu .item > p:only-child { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + line-height: 1.3; +} + +.ui.menu .item > p:first-child { + margin-top: 0; +} + +.ui.menu .item > p:last-child { + margin-bottom: 0; +} + +/*-------------- + Icons +---------------*/ + +.ui.menu .item > i.icon { + opacity: 0.9; + float: none; + margin: 0em 0.35714286em 0em 0em; +} + +/*-------------- + Button +---------------*/ + +.ui.menu:not(.vertical) .item > .button { + position: relative; + top: 0em; + margin: -0.5em 0em; + padding-bottom: 0.78571429em; + padding-top: 0.78571429em; + font-size: 1em; +} + +/*---------------- + Grid / Container +-----------------*/ + +.ui.menu > .grid, +.ui.menu > .container { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: inherit; + -webkit-align-items: inherit; + -ms-flex-align: inherit; + align-items: inherit; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: inherit; + -ms-flex-direction: inherit; + flex-direction: inherit; +} + +/*-------------- + Inputs +---------------*/ + +.ui.menu .item > .input { + width: 100%; +} + +.ui.menu:not(.vertical) .item > .input { + position: relative; + top: 0em; + margin: -0.5em 0em; +} + +.ui.menu .item > .input input { + font-size: 1em; + padding-top: 0.57142857em; + padding-bottom: 0.57142857em; +} + +/*-------------- + Header +---------------*/ + +.ui.menu .header.item, +.ui.vertical.menu .header.item { + margin: 0em; + background: ''; + text-transform: normal; + font-weight: bold; +} + +.ui.vertical.menu .item > .header:not(.ui) { + margin: 0em 0em 0.5em; + font-size: 1em; + font-weight: bold; +} + +/*-------------- + Dropdowns +---------------*/ + +/* Dropdown Icon */ + +.ui.menu .item > i.dropdown.icon { + padding: 0em; + float: right; + margin: 0em 0em 0em 1em; +} + +/* Menu */ + +.ui.menu .dropdown.item .menu { + left: 0px; + min-width: calc(100% - 1px); + border-radius: 0em 0em 0.28571429rem 0.28571429rem; + background: #FFFFFF; + margin: 0em 0px 0px; + box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.08); + -webkit-box-orient: vertical !important; + -webkit-box-direction: normal !important; + -webkit-flex-direction: column !important; + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +/* Menu Items */ + +.ui.menu .ui.dropdown .menu > .item { + margin: 0; + text-align: left; + font-size: 1em !important; + padding: 0.78571429em 1.14285714em !important; + background: transparent !important; + color: rgba(0, 0, 0, 0.87) !important; + text-transform: none !important; + font-weight: normal !important; + box-shadow: none !important; + -webkit-transition: none !important; + transition: none !important; +} + +.ui.menu .ui.dropdown .menu > .item:hover { + background: rgba(0, 0, 0, 0.05) !important; + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.menu .ui.dropdown .menu > .selected.item { + background: rgba(0, 0, 0, 0.05) !important; + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.menu .ui.dropdown .menu > .active.item { + background: rgba(0, 0, 0, 0.03) !important; + font-weight: bold !important; + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.menu .ui.dropdown.item .menu .item:not(.filtered) { + display: block; +} + +.ui.menu .ui.dropdown .menu > .item .icon:not(.dropdown) { + display: inline-block; + font-size: 1em !important; + float: none; + margin: 0em 0.75em 0em 0em; +} + +/* Secondary */ + +.ui.secondary.menu .dropdown.item > .menu, +.ui.text.menu .dropdown.item > .menu { + border-radius: 0.28571429rem; + margin-top: 0.35714286em; +} + +/* Pointing */ + +.ui.menu .pointing.dropdown.item .menu { + margin-top: 0.75em; +} + +/* Inverted */ + +.ui.inverted.menu .search.dropdown.item > .search, +.ui.inverted.menu .search.dropdown.item > .text { + color: rgba(255, 255, 255, 0.9); +} + +/* Vertical */ + +.ui.vertical.menu .dropdown.item > .icon { + float: right; + content: "\f0da"; + margin-left: 1em; +} + +.ui.vertical.menu .dropdown.item .menu { + left: 100%; + min-width: 0; + margin: 0em 0em 0em 0em; + box-shadow: 0 1px 3px 0px rgba(0, 0, 0, 0.08); + border-radius: 0em 0.28571429rem 0.28571429rem 0.28571429rem; +} + +.ui.vertical.menu .dropdown.item.upward .menu { + bottom: 0; +} + +.ui.vertical.menu .dropdown.item:not(.upward) .menu { + top: 0; +} + +.ui.vertical.menu .active.dropdown.item { + border-top-right-radius: 0em; + border-bottom-right-radius: 0em; +} + +.ui.vertical.menu .dropdown.active.item { + box-shadow: none; +} + +/* Evenly Divided */ + +.ui.item.menu .dropdown .menu .item { + width: 100%; +} + +/*-------------- + Labels +---------------*/ + +.ui.menu .item > .label { + background: #999999; + color: #FFFFFF; + margin-left: 1em; + padding: 0.3em 0.78571429em; +} + +.ui.vertical.menu .item > .label { + background: #999999; + color: #FFFFFF; + margin-top: -0.15em; + margin-bottom: -0.15em; + padding: 0.3em 0.78571429em; +} + +.ui.menu .item > .floating.label { + padding: 0.3em 0.78571429em; +} + +/*-------------- + Images +---------------*/ + +.ui.menu .item > img:not(.ui) { + display: inline-block; + vertical-align: middle; + margin: -0.3em 0em; + width: 2.5em; +} + +.ui.vertical.menu .item > img:not(.ui):only-child { + display: block; + max-width: 100%; + width: auto; +} + +/******************************* + Coupling +*******************************/ + +/*-------------- + Sidebar +---------------*/ + +/* Show vertical dividers below last */ + +.ui.vertical.sidebar.menu > .item:first-child:before { + display: block !important; +} + +.ui.vertical.sidebar.menu > .item::before { + top: auto; + bottom: 0px; +} + +/*-------------- + Container +---------------*/ + +@media only screen and (max-width: 767px) { + .ui.menu > .ui.container { + width: 100% !important; + margin-left: 0em !important; + margin-right: 0em !important; + } +} + +@media only screen and (min-width: 768px) { + .ui.menu:not(.secondary):not(.text):not(.tabular):not(.borderless) > .container > .item:not(.right):not(.borderless):first-child { + border-left: 1px solid rgba(34, 36, 38, 0.1); + } +} + +/******************************* + States +*******************************/ + +/*-------------- + Hover +---------------*/ + +.ui.link.menu .item:hover, +.ui.menu .dropdown.item:hover, +.ui.menu .link.item:hover, +.ui.menu a.item:hover { + cursor: pointer; + background: rgba(0, 0, 0, 0.03); + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Pressed +---------------*/ + +.ui.link.menu .item:active, +.ui.menu .link.item:active, +.ui.menu a.item:active { + background: rgba(0, 0, 0, 0.03); + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Active +---------------*/ + +.ui.menu .active.item { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); + font-weight: normal; + box-shadow: none; +} + +.ui.menu .active.item > i.icon { + opacity: 1; +} + +/*-------------- + Active Hover +---------------*/ + +.ui.menu .active.item:hover, +.ui.vertical.menu .active.item:hover { + background-color: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Disabled +---------------*/ + +.ui.menu .item.disabled, +.ui.menu .item.disabled:hover { + cursor: default; + background-color: transparent !important; + color: rgba(40, 40, 40, 0.3); +} + +/******************************* + Types +*******************************/ + +/*------------------ +Floated Menu / Item +-------------------*/ + +/* Left Floated */ + +.ui.menu:not(.vertical) .left.item, +.ui.menu:not(.vertical) .left.menu { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin-right: auto !important; +} + +/* Right Floated */ + +.ui.menu:not(.vertical) .right.item, +.ui.menu:not(.vertical) .right.menu { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin-left: auto !important; +} + +/* Swapped Borders */ + +.ui.menu .right.item::before, +.ui.menu .right.menu > .item::before { + right: auto; + left: 0; +} + +/*-------------- + Vertical +---------------*/ + +.ui.vertical.menu { + display: block; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + background: #FFFFFF; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15); +} + +/*--- Item ---*/ + +.ui.vertical.menu .item { + display: block; + background: none; + border-top: none; + border-right: none; +} + +.ui.vertical.menu > .item:first-child { + border-radius: 0.28571429rem 0.28571429rem 0px 0px; +} + +.ui.vertical.menu > .item:last-child { + border-radius: 0px 0px 0.28571429rem 0.28571429rem; +} + +/*--- Label ---*/ + +.ui.vertical.menu .item > .label { + float: right; + text-align: center; +} + +/*--- Icon ---*/ + +.ui.vertical.menu .item > i.icon { + width: 1.18em; + float: right; + margin: 0em 0em 0em 0.5em; +} + +.ui.vertical.menu .item > .label + i.icon { + float: none; + margin: 0em 0.5em 0em 0em; +} + +/*--- Border ---*/ + +.ui.vertical.menu .item:before { + position: absolute; + content: ''; + top: 0%; + left: 0px; + width: 100%; + height: 1px; + background: rgba(34, 36, 38, 0.1); +} + +.ui.vertical.menu .item:first-child:before { + display: none !important; +} + +/*--- Sub Menu ---*/ + +.ui.vertical.menu .item > .menu { + margin: 0.5em -1.14285714em 0em; +} + +.ui.vertical.menu .menu .item { + background: none; + padding: 0.5em 1.33333333em; + font-size: 0.85714286em; + color: rgba(0, 0, 0, 0.5); +} + +.ui.vertical.menu .item .menu a.item:hover, +.ui.vertical.menu .item .menu .link.item:hover { + color: rgba(0, 0, 0, 0.85); +} + +.ui.vertical.menu .menu .item:before { + display: none; +} + +/* Vertical Active */ + +.ui.vertical.menu .active.item { + background: rgba(0, 0, 0, 0.05); + border-radius: 0em; + box-shadow: none; +} + +.ui.vertical.menu > .active.item:first-child { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.vertical.menu > .active.item:last-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui.vertical.menu > .active.item:only-child { + border-radius: 0.28571429rem; +} + +.ui.vertical.menu .active.item .menu .active.item { + border-left: none; +} + +.ui.vertical.menu .item .menu .active.item { + background-color: transparent; + font-weight: bold; + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Tabular +---------------*/ + +.ui.tabular.menu { + border-radius: 0em; + box-shadow: none !important; + border: none; + background: none transparent; + border-bottom: 1px solid #D4D4D5; +} + +.ui.tabular.fluid.menu { + width: calc(100% + 2px ) !important; +} + +.ui.tabular.menu .item { + background: transparent; + border-bottom: none; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-top: 2px solid transparent; + padding: 0.92857143em 1.42857143em; + color: rgba(0, 0, 0, 0.87); +} + +.ui.tabular.menu .item:before { + display: none; +} + +/* Hover */ + +.ui.tabular.menu .item:hover { + background-color: transparent; + color: rgba(0, 0, 0, 0.8); +} + +/* Active */ + +.ui.tabular.menu .active.item { + background: none #FFFFFF; + color: rgba(0, 0, 0, 0.95); + border-top-width: 1px; + border-color: #D4D4D5; + font-weight: bold; + margin-bottom: -1px; + box-shadow: none; + border-radius: 0.28571429rem 0.28571429rem 0px 0px !important; +} + +/* Coupling with segment for attachment */ + +.ui.tabular.menu + .attached:not(.top).segment, +.ui.tabular.menu + .attached:not(.top).segment + .attached:not(.top).segment { + border-top: none; + margin-left: 0px; + margin-top: 0px; + margin-right: 0px; + width: 100%; +} + +.top.attached.segment + .ui.bottom.tabular.menu { + position: relative; + width: calc(100% + 2px ); + left: -1px; +} + +/* Bottom Vertical Tabular */ + +.ui.bottom.tabular.menu { + background: none transparent; + border-radius: 0em; + box-shadow: none !important; + border-bottom: none; + border-top: 1px solid #D4D4D5; +} + +.ui.bottom.tabular.menu .item { + background: none; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-bottom: 1px solid transparent; + border-top: none; +} + +.ui.bottom.tabular.menu .active.item { + background: none #FFFFFF; + color: rgba(0, 0, 0, 0.95); + border-color: #D4D4D5; + margin: -1px 0px 0px 0px; + border-radius: 0px 0px 0.28571429rem 0.28571429rem !important; +} + +/* Vertical Tabular (Left) */ + +.ui.vertical.tabular.menu { + background: none transparent; + border-radius: 0em; + box-shadow: none !important; + border-bottom: none; + border-right: 1px solid #D4D4D5; +} + +.ui.vertical.tabular.menu .item { + background: none; + border-left: 1px solid transparent; + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; + border-right: none; +} + +.ui.vertical.tabular.menu .active.item { + background: none #FFFFFF; + color: rgba(0, 0, 0, 0.95); + border-color: #D4D4D5; + margin: 0px -1px 0px 0px; + border-radius: 0.28571429rem 0px 0px 0.28571429rem !important; +} + +/* Vertical Right Tabular */ + +.ui.vertical.right.tabular.menu { + background: none transparent; + border-radius: 0em; + box-shadow: none !important; + border-bottom: none; + border-right: none; + border-left: 1px solid #D4D4D5; +} + +.ui.vertical.right.tabular.menu .item { + background: none; + border-right: 1px solid transparent; + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; + border-left: none; +} + +.ui.vertical.right.tabular.menu .active.item { + background: none #FFFFFF; + color: rgba(0, 0, 0, 0.95); + border-color: #D4D4D5; + margin: 0px 0px 0px -1px; + border-radius: 0px 0.28571429rem 0.28571429rem 0px !important; +} + +/* Dropdown */ + +.ui.tabular.menu .active.dropdown.item { + margin-bottom: 0px; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-top: 2px solid transparent; + border-bottom: none; +} + +/*-------------- + Pagination +---------------*/ + +.ui.pagination.menu { + margin: 0em; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + vertical-align: middle; +} + +.ui.pagination.menu .item:last-child { + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +.ui.compact.menu .item:last-child { + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +.ui.pagination.menu .item:last-child:before { + display: none; +} + +.ui.pagination.menu .item { + min-width: 3em; + text-align: center; +} + +.ui.pagination.menu .icon.item i.icon { + vertical-align: top; +} + +/* Active */ + +.ui.pagination.menu .active.item { + border-top: none; + padding-top: 0.92857143em; + background-color: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); + box-shadow: none; +} + +/*-------------- + Secondary +---------------*/ + +.ui.secondary.menu { + background: none; + margin-left: -0.35714286em; + margin-right: -0.35714286em; + border-radius: 0em; + border: none; + box-shadow: none; +} + +/* Item */ + +.ui.secondary.menu .item { + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + box-shadow: none; + border: none; + padding: 0.78571429em 0.92857143em; + margin: 0em 0.35714286em; + background: none; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; + border-radius: 0.28571429rem; +} + +/* No Divider */ + +.ui.secondary.menu .item:before { + display: none !important; +} + +/* Header */ + +.ui.secondary.menu .header.item { + border-radius: 0em; + border-right: none; + background: none transparent; +} + +/* Image */ + +.ui.secondary.menu .item > img:not(.ui) { + margin: 0em; +} + +/* Hover */ + +.ui.secondary.menu .dropdown.item:hover, +.ui.secondary.menu .link.item:hover, +.ui.secondary.menu a.item:hover { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); +} + +/* Active */ + +.ui.secondary.menu .active.item { + box-shadow: none; + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); + border-radius: 0.28571429rem; +} + +/* Active Hover */ + +.ui.secondary.menu .active.item:hover { + box-shadow: none; + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); +} + +/* Inverted */ + +.ui.secondary.inverted.menu .link.item, +.ui.secondary.inverted.menu a.item { + color: rgba(255, 255, 255, 0.7) !important; +} + +.ui.secondary.inverted.menu .dropdown.item:hover, +.ui.secondary.inverted.menu .link.item:hover, +.ui.secondary.inverted.menu a.item:hover { + background: rgba(255, 255, 255, 0.08); + color: #ffffff !important; +} + +.ui.secondary.inverted.menu .active.item { + background: rgba(255, 255, 255, 0.15); + color: #ffffff !important; +} + +/* Fix item margins */ + +.ui.secondary.item.menu { + margin-left: 0em; + margin-right: 0em; +} + +.ui.secondary.item.menu .item:last-child { + margin-right: 0em; +} + +.ui.secondary.attached.menu { + box-shadow: none; +} + +/* Sub Menu */ + +.ui.vertical.secondary.menu .item:not(.dropdown) > .menu { + margin: 0em -0.92857143em; +} + +.ui.vertical.secondary.menu .item:not(.dropdown) > .menu > .item { + margin: 0em; + padding: 0.5em 1.33333333em; +} + +/*--------------------- + Secondary Vertical +-----------------------*/ + +.ui.secondary.vertical.menu > .item { + border: none; + margin: 0em 0em 0.35714286em; + border-radius: 0.28571429rem !important; +} + +.ui.secondary.vertical.menu > .header.item { + border-radius: 0em; +} + +/* Sub Menu */ + +.ui.vertical.secondary.menu .item > .menu .item { + background-color: transparent; +} + +/* Inverted */ + +.ui.secondary.inverted.menu { + background-color: transparent; +} + +/*--------------------- + Secondary Pointing +-----------------------*/ + +.ui.secondary.pointing.menu { + margin-left: 0em; + margin-right: 0em; + border-bottom: 2px solid rgba(34, 36, 38, 0.15); +} + +.ui.secondary.pointing.menu .item { + border-bottom-color: transparent; + border-bottom-style: solid; + border-radius: 0em; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; + margin: 0em 0em -2px; + padding: 0.85714286em 1.14285714em; + border-bottom-width: 2px; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +/* Item Types */ + +.ui.secondary.pointing.menu .header.item { + color: rgba(0, 0, 0, 0.85) !important; +} + +.ui.secondary.pointing.menu .text.item { + box-shadow: none !important; +} + +.ui.secondary.pointing.menu .item:after { + display: none; +} + +/* Hover */ + +.ui.secondary.pointing.menu .dropdown.item:hover, +.ui.secondary.pointing.menu .link.item:hover, +.ui.secondary.pointing.menu a.item:hover { + background-color: transparent; + color: rgba(0, 0, 0, 0.87); +} + +/* Pressed */ + +.ui.secondary.pointing.menu .dropdown.item:active, +.ui.secondary.pointing.menu .link.item:active, +.ui.secondary.pointing.menu a.item:active { + background-color: transparent; + border-color: rgba(34, 36, 38, 0.15); +} + +/* Active */ + +.ui.secondary.pointing.menu .active.item { + background-color: transparent; + box-shadow: none; + border-color: #1B1C1D; + font-weight: bold; + color: rgba(0, 0, 0, 0.95); +} + +/* Active Hover */ + +.ui.secondary.pointing.menu .active.item:hover { + border-color: #1B1C1D; + color: rgba(0, 0, 0, 0.95); +} + +/* Active Dropdown */ + +.ui.secondary.pointing.menu .active.dropdown.item { + border-color: transparent; +} + +/* Vertical Pointing */ + +.ui.secondary.vertical.pointing.menu { + border-bottom-width: 0px; + border-right-width: 2px; + border-right-style: solid; + border-right-color: rgba(34, 36, 38, 0.15); +} + +.ui.secondary.vertical.pointing.menu .item { + border-bottom: none; + border-right-style: solid; + border-right-color: transparent; + border-radius: 0em !important; + margin: 0em -2px 0em 0em; + border-right-width: 2px; +} + +/* Vertical Active */ + +.ui.secondary.vertical.pointing.menu .active.item { + border-color: #1B1C1D; +} + +/* Inverted */ + +.ui.secondary.inverted.pointing.menu { + border-color: rgba(255, 255, 255, 0.1); +} + +.ui.secondary.inverted.pointing.menu { + border-width: 2px; + border-color: rgba(34, 36, 38, 0.15); +} + +.ui.secondary.inverted.pointing.menu .item { + color: rgba(255, 255, 255, 0.9); +} + +.ui.secondary.inverted.pointing.menu .header.item { + color: #FFFFFF !important; +} + +/* Hover */ + +.ui.secondary.inverted.pointing.menu .link.item:hover, +.ui.secondary.inverted.pointing.menu a.item:hover { + color: rgba(0, 0, 0, 0.95); +} + +/* Active */ + +.ui.secondary.inverted.pointing.menu .active.item { + border-color: #FFFFFF; + color: #ffffff; +} + +/*-------------- + Text Menu +---------------*/ + +.ui.text.menu { + background: none transparent; + border-radius: 0px; + box-shadow: none; + border: none; + margin: 1em -0.5em; +} + +.ui.text.menu .item { + border-radius: 0px; + box-shadow: none; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + margin: 0em 0em; + padding: 0.35714286em 0.5em; + font-weight: normal; + color: rgba(0, 0, 0, 0.6); + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; +} + +/* Border */ + +.ui.text.menu .item:before, +.ui.text.menu .menu .item:before { + display: none !important; +} + +/* Header */ + +.ui.text.menu .header.item { + background-color: transparent; + opacity: 1; + color: rgba(0, 0, 0, 0.85); + font-size: 0.92857143em; + text-transform: uppercase; + font-weight: bold; +} + +/* Image */ + +.ui.text.menu .item > img:not(.ui) { + margin: 0em; +} + +/*--- fluid text ---*/ + +.ui.text.item.menu .item { + margin: 0em; +} + +/*--- vertical text ---*/ + +.ui.vertical.text.menu { + margin: 1em 0em; +} + +.ui.vertical.text.menu:first-child { + margin-top: 0rem; +} + +.ui.vertical.text.menu:last-child { + margin-bottom: 0rem; +} + +.ui.vertical.text.menu .item { + margin: 0.57142857em 0em; + padding-left: 0em; + padding-right: 0em; +} + +.ui.vertical.text.menu .item > i.icon { + float: none; + margin: 0em 0.35714286em 0em 0em; +} + +.ui.vertical.text.menu .header.item { + margin: 0.57142857em 0em 0.71428571em; +} + +/* Vertical Sub Menu */ + +.ui.vertical.text.menu .item:not(.dropdown) > .menu { + margin: 0em; +} + +.ui.vertical.text.menu .item:not(.dropdown) > .menu > .item { + margin: 0em; + padding: 0.5em 0em; +} + +/*--- hover ---*/ + +.ui.text.menu .item:hover { + opacity: 1; + background-color: transparent; +} + +/*--- active ---*/ + +.ui.text.menu .active.item { + background-color: transparent; + border: none; + box-shadow: none; + font-weight: normal; + color: rgba(0, 0, 0, 0.95); +} + +/*--- active hover ---*/ + +.ui.text.menu .active.item:hover { + background-color: transparent; +} + +/* Disable Bariations */ + +.ui.text.pointing.menu .active.item:after { + box-shadow: none; +} + +.ui.text.attached.menu { + box-shadow: none; +} + +/* Inverted */ + +.ui.inverted.text.menu, +.ui.inverted.text.menu .item, +.ui.inverted.text.menu .item:hover, +.ui.inverted.text.menu .active.item { + background-color: transparent !important; +} + +/* Fluid */ + +.ui.fluid.text.menu { + margin-left: 0em; + margin-right: 0em; +} + +/*-------------- + Icon Only +---------------*/ + +/* Vertical Menu */ + +.ui.vertical.icon.menu { + display: inline-block; + width: auto; +} + +/* Item */ + +.ui.icon.menu .item { + height: auto; + text-align: center; + color: #1B1C1D; +} + +/* Icon */ + +.ui.icon.menu .item > .icon:not(.dropdown) { + margin: 0; + opacity: 1; +} + +/* Icon Gylph */ + +.ui.icon.menu .icon:before { + opacity: 1; +} + +/* (x) Item Icon */ + +.ui.menu .icon.item > .icon { + width: auto; + margin: 0em auto; +} + +/* Vertical Icon */ + +.ui.vertical.icon.menu .item > .icon:not(.dropdown) { + display: block; + opacity: 1; + margin: 0em auto; + float: none; +} + +/* Inverted */ + +.ui.inverted.icon.menu .item { + color: #FFFFFF; +} + +/*-------------- + Labeled Icon +---------------*/ + +/* Menu */ + +.ui.labeled.icon.menu { + text-align: center; +} + +/* Item */ + +.ui.labeled.icon.menu .item { + min-width: 6em; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +/* Icon */ + +.ui.labeled.icon.menu .item > .icon:not(.dropdown) { + height: 1em; + display: block; + font-size: 1.71428571em !important; + margin: 0em auto 0.5rem !important; +} + +/* Fluid */ + +.ui.fluid.labeled.icon.menu > .item { + min-width: 0em; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Stackable +---------------*/ + +@media only screen and (max-width: 767px) { + .ui.stackable.menu { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } + + .ui.stackable.menu .item { + width: 100% !important; + } + + .ui.stackable.menu .item:before { + position: absolute; + content: ''; + top: auto; + bottom: 0px; + left: 0px; + width: 100%; + height: 1px; + background: rgba(34, 36, 38, 0.1); + } + + .ui.stackable.menu .left.menu, + .ui.stackable.menu .left.item { + margin-right: 0 !important; + } + + .ui.stackable.menu .right.menu, + .ui.stackable.menu .right.item { + margin-left: 0 !important; + } +} + +/*-------------- + Colors +---------------*/ + +/*--- Standard Colors ---*/ + +.ui.menu .red.active.item, +.ui.red.menu .active.item { + border-color: #DB2828 !important; + color: #DB2828 !important; +} + +.ui.menu .orange.active.item, +.ui.orange.menu .active.item { + border-color: #F2711C !important; + color: #F2711C !important; +} + +.ui.menu .yellow.active.item, +.ui.yellow.menu .active.item { + border-color: #FBBD08 !important; + color: #FBBD08 !important; +} + +.ui.menu .olive.active.item, +.ui.olive.menu .active.item { + border-color: #B5CC18 !important; + color: #B5CC18 !important; +} + +.ui.menu .green.active.item, +.ui.green.menu .active.item { + border-color: #21BA45 !important; + color: #21BA45 !important; +} + +.ui.menu .teal.active.item, +.ui.teal.menu .active.item { + border-color: #00B5AD !important; + color: #00B5AD !important; +} + +.ui.menu .blue.active.item, +.ui.blue.menu .active.item { + border-color: #2185D0 !important; + color: #2185D0 !important; +} + +.ui.menu .violet.active.item, +.ui.violet.menu .active.item { + border-color: #6435C9 !important; + color: #6435C9 !important; +} + +.ui.menu .purple.active.item, +.ui.purple.menu .active.item { + border-color: #A333C8 !important; + color: #A333C8 !important; +} + +.ui.menu .pink.active.item, +.ui.pink.menu .active.item { + border-color: #E03997 !important; + color: #E03997 !important; +} + +.ui.menu .brown.active.item, +.ui.brown.menu .active.item { + border-color: #A5673F !important; + color: #A5673F !important; +} + +.ui.menu .grey.active.item, +.ui.grey.menu .active.item { + border-color: #767676 !important; + color: #767676 !important; +} + +/*-------------- + Inverted +---------------*/ + +.ui.inverted.menu { + border: 0px solid transparent; + background: #1B1C1D; + box-shadow: none; +} + +/* Menu Item */ + +.ui.inverted.menu .item, +.ui.inverted.menu .item > a:not(.ui) { + background: transparent; + color: rgba(255, 255, 255, 0.9); +} + +.ui.inverted.menu .item.menu { + background: transparent; +} + +/*--- Border ---*/ + +.ui.inverted.menu .item:before { + background: rgba(255, 255, 255, 0.08); +} + +.ui.vertical.inverted.menu .item:before { + background: rgba(255, 255, 255, 0.08); +} + +/* Sub Menu */ + +.ui.vertical.inverted.menu .menu .item, +.ui.vertical.inverted.menu .menu .item a:not(.ui) { + color: rgba(255, 255, 255, 0.5); +} + +/* Header */ + +.ui.inverted.menu .header.item { + margin: 0em; + background: transparent; + box-shadow: none; +} + +/* Disabled */ + +.ui.inverted.menu .item.disabled, +.ui.inverted.menu .item.disabled:hover { + color: rgba(225, 225, 225, 0.3); +} + +/*--- Hover ---*/ + +.ui.link.inverted.menu .item:hover, +.ui.inverted.menu .dropdown.item:hover, +.ui.inverted.menu .link.item:hover, +.ui.inverted.menu a.item:hover { + background: rgba(255, 255, 255, 0.08); + color: #ffffff; +} + +.ui.vertical.inverted.menu .item .menu a.item:hover, +.ui.vertical.inverted.menu .item .menu .link.item:hover { + background: transparent; + color: #ffffff; +} + +/*--- Pressed ---*/ + +.ui.inverted.menu a.item:active, +.ui.inverted.menu .link.item:active { + background: rgba(255, 255, 255, 0.08); + color: #ffffff; +} + +/*--- Active ---*/ + +.ui.inverted.menu .active.item { + background: rgba(255, 255, 255, 0.15); + color: #ffffff !important; +} + +.ui.inverted.vertical.menu .item .menu .active.item { + background: transparent; + color: #FFFFFF; +} + +.ui.inverted.pointing.menu .active.item:after { + background: #3D3E3F !important; + margin: 0em !important; + box-shadow: none !important; + border: none !important; +} + +/*--- Active Hover ---*/ + +.ui.inverted.menu .active.item:hover { + background: rgba(255, 255, 255, 0.15); + color: #FFFFFF !important; +} + +.ui.inverted.pointing.menu .active.item:hover:after { + background: #3D3E3F !important; +} + +/*-------------- + Floated +---------------*/ + +.ui.floated.menu { + float: left; + margin: 0rem 0.5rem 0rem 0rem; +} + +.ui.floated.menu .item:last-child:before { + display: none; +} + +.ui.right.floated.menu { + float: right; + margin: 0rem 0rem 0rem 0.5rem; +} + +/*-------------- + Inverted +---------------*/ + +/* Red */ + +.ui.inverted.menu .red.active.item, +.ui.inverted.red.menu { + background-color: #DB2828; +} + +.ui.inverted.red.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.red.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Orange */ + +.ui.inverted.menu .orange.active.item, +.ui.inverted.orange.menu { + background-color: #F2711C; +} + +.ui.inverted.orange.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.orange.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Yellow */ + +.ui.inverted.menu .yellow.active.item, +.ui.inverted.yellow.menu { + background-color: #FBBD08; +} + +.ui.inverted.yellow.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.yellow.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Olive */ + +.ui.inverted.menu .olive.active.item, +.ui.inverted.olive.menu { + background-color: #B5CC18; +} + +.ui.inverted.olive.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.olive.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Green */ + +.ui.inverted.menu .green.active.item, +.ui.inverted.green.menu { + background-color: #21BA45; +} + +.ui.inverted.green.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.green.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Teal */ + +.ui.inverted.menu .teal.active.item, +.ui.inverted.teal.menu { + background-color: #00B5AD; +} + +.ui.inverted.teal.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.teal.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Blue */ + +.ui.inverted.menu .blue.active.item, +.ui.inverted.blue.menu { + background-color: #2185D0; +} + +.ui.inverted.blue.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.blue.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Violet */ + +.ui.inverted.menu .violet.active.item, +.ui.inverted.violet.menu { + background-color: #6435C9; +} + +.ui.inverted.violet.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.violet.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Purple */ + +.ui.inverted.menu .purple.active.item, +.ui.inverted.purple.menu { + background-color: #A333C8; +} + +.ui.inverted.purple.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.purple.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Pink */ + +.ui.inverted.menu .pink.active.item, +.ui.inverted.pink.menu { + background-color: #E03997; +} + +.ui.inverted.pink.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.pink.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Brown */ + +.ui.inverted.menu .brown.active.item, +.ui.inverted.brown.menu { + background-color: #A5673F; +} + +.ui.inverted.brown.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.brown.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* Grey */ + +.ui.inverted.menu .grey.active.item, +.ui.inverted.grey.menu { + background-color: #767676; +} + +.ui.inverted.grey.menu .item:before { + background-color: rgba(34, 36, 38, 0.1); +} + +.ui.inverted.grey.menu .active.item { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/*-------------- + Fitted +---------------*/ + +.ui.fitted.menu .item, +.ui.fitted.menu .item .menu .item, +.ui.menu .fitted.item { + padding: 0em; +} + +.ui.horizontally.fitted.menu .item, +.ui.horizontally.fitted.menu .item .menu .item, +.ui.menu .horizontally.fitted.item { + padding-top: 0.92857143em; + padding-bottom: 0.92857143em; +} + +.ui.vertically.fitted.menu .item, +.ui.vertically.fitted.menu .item .menu .item, +.ui.menu .vertically.fitted.item { + padding-left: 1.14285714em; + padding-right: 1.14285714em; +} + +/*-------------- + Borderless +---------------*/ + +.ui.borderless.menu .item:before, +.ui.borderless.menu .item .menu .item:before, +.ui.menu .borderless.item:before { + background: none !important; +} + +/*------------------- + Compact +--------------------*/ + +.ui.compact.menu { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + margin: 0em; + vertical-align: middle; +} + +.ui.compact.vertical.menu { + display: inline-block; +} + +.ui.compact.menu .item:last-child { + border-radius: 0em 0.28571429rem 0.28571429rem 0em; +} + +.ui.compact.menu .item:last-child:before { + display: none; +} + +.ui.compact.vertical.menu { + width: auto !important; +} + +.ui.compact.vertical.menu .item:last-child::before { + display: block; +} + +/*------------------- + Fluid +--------------------*/ + +.ui.menu.fluid, +.ui.vertical.menu.fluid { + width: 100% !important; +} + +/*------------------- + Evenly Sized +--------------------*/ + +.ui.item.menu, +.ui.item.menu .item { + width: 100%; + padding-left: 0em !important; + padding-right: 0em !important; + margin-left: 0em !important; + margin-right: 0em !important; + text-align: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +.ui.item.menu .item:last-child:before { + display: none; +} + +.ui.menu.two.item .item { + width: 50%; +} + +.ui.menu.three.item .item { + width: 33.333%; +} + +.ui.menu.four.item .item { + width: 25%; +} + +.ui.menu.five.item .item { + width: 20%; +} + +.ui.menu.six.item .item { + width: 16.666%; +} + +.ui.menu.seven.item .item { + width: 14.285%; +} + +.ui.menu.eight.item .item { + width: 12.500%; +} + +.ui.menu.nine.item .item { + width: 11.11%; +} + +.ui.menu.ten.item .item { + width: 10.0%; +} + +.ui.menu.eleven.item .item { + width: 9.09%; +} + +.ui.menu.twelve.item .item { + width: 8.333%; +} + +/*-------------- + Fixed +---------------*/ + +.ui.menu.fixed { + position: fixed; + z-index: 101; + margin: 0em; + width: 100%; +} + +.ui.menu.fixed, +.ui.menu.fixed .item:first-child, +.ui.menu.fixed .item:last-child { + border-radius: 0px !important; +} + +.ui.fixed.menu, +.ui[class*="top fixed"].menu { + top: 0px; + left: 0px; + right: auto; + bottom: auto; +} + +.ui[class*="top fixed"].menu { + border-top: none; + border-left: none; + border-right: none; +} + +.ui[class*="right fixed"].menu { + border-top: none; + border-bottom: none; + border-right: none; + top: 0px; + right: 0px; + left: auto; + bottom: auto; + width: auto; + height: 100%; +} + +.ui[class*="bottom fixed"].menu { + border-bottom: none; + border-left: none; + border-right: none; + bottom: 0px; + left: 0px; + top: auto; + right: auto; +} + +.ui[class*="left fixed"].menu { + border-top: none; + border-bottom: none; + border-left: none; + top: 0px; + left: 0px; + right: auto; + bottom: auto; + width: auto; + height: 100%; +} + +/* Coupling with Grid */ + +.ui.fixed.menu + .ui.grid { + padding-top: 2.75rem; +} + +/*------------------- + Pointing +--------------------*/ + +.ui.pointing.menu .item:after { + visibility: hidden; + position: absolute; + content: ''; + top: 100%; + left: 50%; + -webkit-transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform: translateX(-50%) translateY(-50%) rotate(45deg); + background: none; + margin: 0.5px 0em 0em; + width: 0.57142857em; + height: 0.57142857em; + border: none; + border-bottom: 1px solid #D4D4D5; + border-right: 1px solid #D4D4D5; + z-index: 2; + -webkit-transition: background 0.1s ease; + transition: background 0.1s ease; +} + +.ui.vertical.pointing.menu .item:after { + position: absolute; + top: 50%; + right: 0%; + bottom: auto; + left: auto; + -webkit-transform: translateX(50%) translateY(-50%) rotate(45deg); + transform: translateX(50%) translateY(-50%) rotate(45deg); + margin: 0em -0.5px 0em 0em; + border: none; + border-top: 1px solid #D4D4D5; + border-right: 1px solid #D4D4D5; +} + +/* Active */ + +.ui.pointing.menu .active.item:after { + visibility: visible; +} + +.ui.pointing.menu .active.dropdown.item:after { + visibility: hidden; +} + +/* Don't double up pointers */ + +.ui.pointing.menu .dropdown.active.item:after, +.ui.pointing.menu .active.item .menu .active.item:after { + display: none; +} + +/* Colors */ + +.ui.pointing.menu .active.item:hover:after { + background-color: #F2F2F2; +} + +.ui.pointing.menu .active.item:after { + background-color: #F2F2F2; +} + +.ui.pointing.menu .active.item:hover:after { + background-color: #F2F2F2; +} + +.ui.vertical.pointing.menu .active.item:hover:after { + background-color: #F2F2F2; +} + +.ui.vertical.pointing.menu .active.item:after { + background-color: #F2F2F2; +} + +.ui.vertical.pointing.menu .menu .active.item:after { + background-color: #FFFFFF; +} + +/*-------------- + Attached +---------------*/ + +/* Middle */ + +.ui.attached.menu { + top: 0px; + bottom: 0px; + border-radius: 0px; + margin: 0em -1px; + width: calc(100% + 2px ); + max-width: calc(100% + 2px ); + box-shadow: none; +} + +.ui.attached + .ui.attached.menu:not(.top) { + border-top: none; +} + +/* Top */ + +.ui[class*="top attached"].menu { + bottom: 0px; + margin-bottom: 0em; + top: 0px; + margin-top: 1rem; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.menu[class*="top attached"]:first-child { + margin-top: 0em; +} + +/* Bottom */ + +.ui[class*="bottom attached"].menu { + bottom: 0px; + margin-top: 0em; + top: 0px; + margin-bottom: 1rem; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui[class*="bottom attached"].menu:last-child { + margin-bottom: 0em; +} + +/* Attached Menu Item */ + +.ui.top.attached.menu > .item:first-child { + border-radius: 0.28571429rem 0em 0em 0em; +} + +.ui.bottom.attached.menu > .item:first-child { + border-radius: 0em 0em 0em 0.28571429rem; +} + +/* Tabular Attached */ + +.ui.attached.menu:not(.tabular) { + border: 1px solid #D4D4D5; +} + +.ui.attached.inverted.menu { + border: none; +} + +.ui.attached.tabular.menu { + margin-left: 0; + margin-right: 0; + width: 100%; +} + +/*-------------- + Sizes +---------------*/ + +/* Mini */ + +.ui.mini.menu { + font-size: 0.78571429rem; +} + +.ui.mini.vertical.menu { + width: 9rem; +} + +/* Tiny */ + +.ui.tiny.menu { + font-size: 0.85714286rem; +} + +.ui.tiny.vertical.menu { + width: 11rem; +} + +/* Small */ + +.ui.small.menu { + font-size: 0.92857143rem; +} + +.ui.small.vertical.menu { + width: 13rem; +} + +/* Medium */ + +.ui.menu { + font-size: 1rem; +} + +.ui.vertical.menu { + width: 15rem; +} + +/* Large */ + +.ui.large.menu { + font-size: 1.07142857rem; +} + +.ui.large.vertical.menu { + width: 18rem; +} + +/* Huge */ + +.ui.huge.menu { + font-size: 1.14285714rem; +} + +.ui.huge.vertical.menu { + width: 20rem; +} + +/* Big */ + +.ui.big.menu { + font-size: 1.21428571rem; +} + +.ui.big.vertical.menu { + width: 22rem; +} + +/* Massive */ + +.ui.massive.menu { + font-size: 1.28571429rem; +} + +.ui.massive.vertical.menu { + width: 25rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Message + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Message +*******************************/ + +.ui.message { + position: relative; + min-height: 1em; + margin: 1em 0em; + background: #F8F8F9; + padding: 1em 1.5em; + line-height: 1.4285em; + color: rgba(0, 0, 0, 0.87); + -webkit-transition: opacity 0.1s ease, color 0.1s ease, background 0.1s ease, box-shadow 0.1s ease; + transition: opacity 0.1s ease, color 0.1s ease, background 0.1s ease, box-shadow 0.1s ease; + border-radius: 0.28571429rem; + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.22) inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.message:first-child { + margin-top: 0em; +} + +.ui.message:last-child { + margin-bottom: 0em; +} + +/*-------------- + Content +---------------*/ + +/* Header */ + +.ui.message .header { + display: block; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-weight: bold; + margin: -0.14285714em 0em 0rem 0em; +} + +/* Default font size */ + +.ui.message .header:not(.ui) { + font-size: 1.14285714em; +} + +/* Paragraph */ + +.ui.message p { + opacity: 0.85; + margin: 0.75em 0em; +} + +.ui.message p:first-child { + margin-top: 0em; +} + +.ui.message p:last-child { + margin-bottom: 0em; +} + +.ui.message .header + p { + margin-top: 0.25em; +} + +/* List */ + +.ui.message .list:not(.ui) { + text-align: left; + padding: 0em; + opacity: 0.85; + list-style-position: inside; + margin: 0.5em 0em 0em; +} + +.ui.message .list:not(.ui):first-child { + margin-top: 0em; +} + +.ui.message .list:not(.ui):last-child { + margin-bottom: 0em; +} + +.ui.message .list:not(.ui) li { + position: relative; + list-style-type: none; + margin: 0em 0em 0.3em 1em; + padding: 0em; +} + +.ui.message .list:not(.ui) li:before { + position: absolute; + content: '•'; + left: -1em; + height: 100%; + vertical-align: baseline; +} + +.ui.message .list:not(.ui) li:last-child { + margin-bottom: 0em; +} + +/* Icon */ + +.ui.message > .icon { + margin-right: 0.6em; +} + +/* Close Icon */ + +.ui.message > .close.icon { + cursor: pointer; + position: absolute; + margin: 0em; + top: 0.78575em; + right: 0.5em; + opacity: 0.7; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; +} + +.ui.message > .close.icon:hover { + opacity: 1; +} + +/* First / Last Element */ + +.ui.message > :first-child { + margin-top: 0em; +} + +.ui.message > :last-child { + margin-bottom: 0em; +} + +/******************************* + Coupling +*******************************/ + +.ui.dropdown .menu > .message { + margin: 0px -1px; +} + +/******************************* + States +*******************************/ + +/*-------------- + Visible +---------------*/ + +.ui.visible.visible.visible.visible.message { + display: block; +} + +.ui.icon.visible.visible.visible.visible.message { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +/*-------------- + Hidden +---------------*/ + +.ui.hidden.hidden.hidden.hidden.message { + display: none; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Compact +---------------*/ + +.ui.compact.message { + display: inline-block; +} + +/*-------------- + Attached +---------------*/ + +.ui.attached.message { + margin-bottom: -1px; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; + box-shadow: 0em 0em 0em 1px rgba(34, 36, 38, 0.15) inset; + margin-left: -1px; + margin-right: -1px; +} + +.ui.attached + .ui.attached.message:not(.top):not(.bottom) { + margin-top: -1px; + border-radius: 0em; +} + +.ui.bottom.attached.message { + margin-top: -1px; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; + box-shadow: 0em 0em 0em 1px rgba(34, 36, 38, 0.15) inset, 0px 1px 2px 0 rgba(34, 36, 38, 0.15); +} + +.ui.bottom.attached.message:not(:last-child) { + margin-bottom: 1em; +} + +.ui.attached.icon.message { + width: auto; +} + +/*-------------- + Icon +---------------*/ + +.ui.icon.message { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; +} + +.ui.icon.message > .icon:not(.close) { + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + line-height: 1; + vertical-align: middle; + font-size: 3em; + opacity: 0.8; +} + +.ui.icon.message > .content { + display: block; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + vertical-align: middle; +} + +.ui.icon.message .icon:not(.close) + .content { + padding-left: 0rem; +} + +.ui.icon.message .circular.icon { + width: 1em; +} + +/*-------------- + Floating +---------------*/ + +.ui.floating.message { + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.22) inset, 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); +} + +/*-------------- + Colors +---------------*/ + +.ui.black.message { + background-color: #1B1C1D; + color: rgba(255, 255, 255, 0.9); +} + +/*-------------- + Types +---------------*/ + +/* Positive */ + +.ui.positive.message { + background-color: #FCFFF5; + color: #2C662D; +} + +.ui.positive.message, +.ui.attached.positive.message { + box-shadow: 0px 0px 0px 1px #A3C293 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.positive.message .header { + color: #1A531B; +} + +/* Negative */ + +.ui.negative.message { + background-color: #FFF6F6; + color: #9F3A38; +} + +.ui.negative.message, +.ui.attached.negative.message { + box-shadow: 0px 0px 0px 1px #E0B4B4 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.negative.message .header { + color: #912D2B; +} + +/* Info */ + +.ui.info.message { + background-color: #F8FFFF; + color: #276F86; +} + +.ui.info.message, +.ui.attached.info.message { + box-shadow: 0px 0px 0px 1px #A9D5DE inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.info.message .header { + color: #0E566C; +} + +/* Warning */ + +.ui.warning.message { + background-color: #FFFAF3; + color: #573A08; +} + +.ui.warning.message, +.ui.attached.warning.message { + box-shadow: 0px 0px 0px 1px #C9BA9B inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.warning.message .header { + color: #794B02; +} + +/* Error */ + +.ui.error.message { + background-color: #FFF6F6; + color: #9F3A38; +} + +.ui.error.message, +.ui.attached.error.message { + box-shadow: 0px 0px 0px 1px #E0B4B4 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.error.message .header { + color: #912D2B; +} + +/* Success */ + +.ui.success.message { + background-color: #FCFFF5; + color: #2C662D; +} + +.ui.success.message, +.ui.attached.success.message { + box-shadow: 0px 0px 0px 1px #A3C293 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.success.message .header { + color: #1A531B; +} + +/* Colors */ + +.ui.inverted.message, +.ui.black.message { + background-color: #1B1C1D; + color: rgba(255, 255, 255, 0.9); +} + +.ui.red.message { + background-color: #FFE8E6; + color: #DB2828; + box-shadow: 0px 0px 0px 1px #DB2828 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.red.message .header { + color: #c82121; +} + +.ui.orange.message { + background-color: #FFEDDE; + color: #F2711C; + box-shadow: 0px 0px 0px 1px #F2711C inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.orange.message .header { + color: #e7640d; +} + +.ui.yellow.message { + background-color: #FFF8DB; + color: #B58105; + box-shadow: 0px 0px 0px 1px #B58105 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.yellow.message .header { + color: #9c6f04; +} + +.ui.olive.message { + background-color: #FBFDEF; + color: #8ABC1E; + box-shadow: 0px 0px 0px 1px #8ABC1E inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.olive.message .header { + color: #7aa61a; +} + +.ui.green.message { + background-color: #E5F9E7; + color: #1EBC30; + box-shadow: 0px 0px 0px 1px #1EBC30 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.green.message .header { + color: #1aa62a; +} + +.ui.teal.message { + background-color: #E1F7F7; + color: #10A3A3; + box-shadow: 0px 0px 0px 1px #10A3A3 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.teal.message .header { + color: #0e8c8c; +} + +.ui.blue.message { + background-color: #DFF0FF; + color: #2185D0; + box-shadow: 0px 0px 0px 1px #2185D0 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.blue.message .header { + color: #1e77ba; +} + +.ui.violet.message { + background-color: #EAE7FF; + color: #6435C9; + box-shadow: 0px 0px 0px 1px #6435C9 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.violet.message .header { + color: #5a30b5; +} + +.ui.purple.message { + background-color: #F6E7FF; + color: #A333C8; + box-shadow: 0px 0px 0px 1px #A333C8 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.purple.message .header { + color: #922eb4; +} + +.ui.pink.message { + background-color: #FFE3FB; + color: #E03997; + box-shadow: 0px 0px 0px 1px #E03997 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.pink.message .header { + color: #dd238b; +} + +.ui.brown.message { + background-color: #F1E2D3; + color: #A5673F; + box-shadow: 0px 0px 0px 1px #A5673F inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); +} + +.ui.brown.message .header { + color: #935b38; +} + +/*-------------- + Sizes +---------------*/ + +.ui.mini.message { + font-size: 0.78571429em; +} + +.ui.tiny.message { + font-size: 0.85714286em; +} + +.ui.small.message { + font-size: 0.92857143em; +} + +.ui.message { + font-size: 1em; +} + +.ui.large.message { + font-size: 1.14285714em; +} + +.ui.big.message { + font-size: 1.28571429em; +} + +.ui.huge.message { + font-size: 1.42857143em; +} + +.ui.massive.message { + font-size: 1.71428571em; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Table + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Table +*******************************/ + +/* Prototype */ + +.ui.table { + width: 100%; + background: #FFFFFF; + margin: 1em 0em; + border: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: none; + border-radius: 0.28571429rem; + text-align: left; + color: rgba(0, 0, 0, 0.87); + border-collapse: separate; + border-spacing: 0px; +} + +.ui.table:first-child { + margin-top: 0em; +} + +.ui.table:last-child { + margin-bottom: 0em; +} + +/******************************* + Parts +*******************************/ + +/* Table Content */ + +.ui.table th, +.ui.table td { + -webkit-transition: background 0.1s ease, color 0.1s ease; + transition: background 0.1s ease, color 0.1s ease; +} + +/* Headers */ + +.ui.table thead { + box-shadow: none; +} + +.ui.table thead th { + cursor: auto; + background: #F9FAFB; + text-align: inherit; + color: rgba(0, 0, 0, 0.87); + padding: 0.92857143em 0.78571429em; + vertical-align: inherit; + font-style: none; + font-weight: bold; + text-transform: none; + border-bottom: 1px solid rgba(34, 36, 38, 0.1); + border-left: none; +} + +.ui.table thead tr > th:first-child { + border-left: none; +} + +.ui.table thead tr:first-child > th:first-child { + border-radius: 0.28571429rem 0em 0em 0em; +} + +.ui.table thead tr:first-child > th:last-child { + border-radius: 0em 0.28571429rem 0em 0em; +} + +.ui.table thead tr:first-child > th:only-child { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +/* Footer */ + +.ui.table tfoot { + box-shadow: none; +} + +.ui.table tfoot th { + cursor: auto; + border-top: 1px solid rgba(34, 36, 38, 0.15); + background: #F9FAFB; + text-align: inherit; + color: rgba(0, 0, 0, 0.87); + padding: 0.78571429em 0.78571429em; + vertical-align: middle; + font-style: normal; + font-weight: normal; + text-transform: none; +} + +.ui.table tfoot tr > th:first-child { + border-left: none; +} + +.ui.table tfoot tr:first-child > th:first-child { + border-radius: 0em 0em 0em 0.28571429rem; +} + +.ui.table tfoot tr:first-child > th:last-child { + border-radius: 0em 0em 0.28571429rem 0em; +} + +.ui.table tfoot tr:first-child > th:only-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +/* Table Row */ + +.ui.table tr td { + border-top: 1px solid rgba(34, 36, 38, 0.1); +} + +.ui.table tr:first-child td { + border-top: none; +} + +/* Table Cells */ + +.ui.table td { + padding: 0.78571429em 0.78571429em; + text-align: inherit; +} + +/* Icons */ + +.ui.table > .icon { + vertical-align: baseline; +} + +.ui.table > .icon:only-child { + margin: 0em; +} + +/* Table Segment */ + +.ui.table.segment { + padding: 0em; +} + +.ui.table.segment:after { + display: none; +} + +.ui.table.segment.stacked:after { + display: block; +} + +/* Responsive */ + +@media only screen and (max-width: 767px) { + .ui.table:not(.unstackable) { + width: 100%; + } + + .ui.table:not(.unstackable) tbody, + .ui.table:not(.unstackable) tr, + .ui.table:not(.unstackable) tr > th, + .ui.table:not(.unstackable) tr > td { + width: auto !important; + display: block !important; + } + + .ui.table:not(.unstackable) { + padding: 0em; + } + + .ui.table:not(.unstackable) thead { + display: block; + } + + .ui.table:not(.unstackable) tfoot { + display: block; + } + + .ui.table:not(.unstackable) tr { + padding-top: 1em; + padding-bottom: 1em; + box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.1) inset !important; + } + + .ui.table:not(.unstackable) tr > th, + .ui.table:not(.unstackable) tr > td { + background: none; + border: none !important; + padding: 0.25em 0.75em !important; + box-shadow: none !important; + } + + .ui.table:not(.unstackable) th:first-child, + .ui.table:not(.unstackable) td:first-child { + font-weight: bold; + } + + /* Definition Table */ + + .ui.definition.table:not(.unstackable) thead th:first-child { + box-shadow: none !important; + } +} + +/******************************* + Coupling +*******************************/ + +/* UI Image */ + +.ui.table th .image, +.ui.table th .image img, +.ui.table td .image, +.ui.table td .image img { + max-width: none; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Complex +---------------*/ + +.ui.structured.table { + border-collapse: collapse; +} + +.ui.structured.table thead th { + border-left: none; + border-right: none; +} + +.ui.structured.sortable.table thead th { + border-left: 1px solid rgba(34, 36, 38, 0.15); + border-right: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.structured.basic.table th { + border-left: none; + border-right: none; +} + +.ui.structured.celled.table tr th, +.ui.structured.celled.table tr td { + border-left: 1px solid rgba(34, 36, 38, 0.1); + border-right: 1px solid rgba(34, 36, 38, 0.1); +} + +/*-------------- + Definition +---------------*/ + +.ui.definition.table thead:not(.full-width) th:first-child { + pointer-events: none; + background: transparent; + font-weight: normal; + color: rgba(0, 0, 0, 0.4); + box-shadow: -1px -1px 0px 1px #FFFFFF; +} + +.ui.definition.table tfoot:not(.full-width) th:first-child { + pointer-events: none; + background: transparent; + font-weight: rgba(0, 0, 0, 0.4); + color: normal; + box-shadow: 1px 1px 0px 1px #FFFFFF; +} + +/* Remove Border */ + +.ui.celled.definition.table thead:not(.full-width) th:first-child { + box-shadow: 0px -1px 0px 1px #FFFFFF; +} + +.ui.celled.definition.table tfoot:not(.full-width) th:first-child { + box-shadow: 0px 1px 0px 1px #FFFFFF; +} + +/* Highlight Defining Column */ + +.ui.definition.table tr td:first-child:not(.ignored), +.ui.definition.table tr td.definition { + background: rgba(0, 0, 0, 0.03); + font-weight: bold; + color: rgba(0, 0, 0, 0.95); + text-transform: ''; + box-shadow: ''; + text-align: ''; + font-size: 1em; + padding-left: ''; + padding-right: ''; +} + +/* Fix 2nd Column */ + +.ui.definition.table thead:not(.full-width) th:nth-child(2) { + border-left: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.definition.table tfoot:not(.full-width) th:nth-child(2) { + border-left: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.definition.table td:nth-child(2) { + border-left: 1px solid rgba(34, 36, 38, 0.15); +} + +/******************************* + States +*******************************/ + +/*-------------- + Positive +---------------*/ + +.ui.table tr.positive, +.ui.table td.positive { + box-shadow: 0px 0px 0px #A3C293 inset; +} + +.ui.table tr.positive, +.ui.table td.positive { + background: #FCFFF5 !important; + color: #2C662D !important; +} + +/*-------------- + Negative +---------------*/ + +.ui.table tr.negative, +.ui.table td.negative { + box-shadow: 0px 0px 0px #E0B4B4 inset; +} + +.ui.table tr.negative, +.ui.table td.negative { + background: #FFF6F6 !important; + color: #9F3A38 !important; +} + +/*-------------- + Error +---------------*/ + +.ui.table tr.error, +.ui.table td.error { + box-shadow: 0px 0px 0px #E0B4B4 inset; +} + +.ui.table tr.error, +.ui.table td.error { + background: #FFF6F6 !important; + color: #9F3A38 !important; +} + +/*-------------- + Warning +---------------*/ + +.ui.table tr.warning, +.ui.table td.warning { + box-shadow: 0px 0px 0px #C9BA9B inset; +} + +.ui.table tr.warning, +.ui.table td.warning { + background: #FFFAF3 !important; + color: #573A08 !important; +} + +/*-------------- + Active +---------------*/ + +.ui.table tr.active, +.ui.table td.active { + box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.87) inset; +} + +.ui.table tr.active, +.ui.table td.active { + background: #E0E0E0 !important; + color: rgba(0, 0, 0, 0.87) !important; +} + +/*-------------- + Disabled +---------------*/ + +.ui.table tr.disabled td, +.ui.table tr td.disabled, +.ui.table tr.disabled:hover, +.ui.table tr:hover td.disabled { + pointer-events: none; + color: rgba(40, 40, 40, 0.3); +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Stackable +---------------*/ + +@media only screen and (max-width: 991px) { + .ui[class*="tablet stackable"].table, + .ui[class*="tablet stackable"].table tbody, + .ui[class*="tablet stackable"].table tr, + .ui[class*="tablet stackable"].table tr > th, + .ui[class*="tablet stackable"].table tr > td { + width: 100% !important; + display: block !important; + } + + .ui[class*="tablet stackable"].table { + padding: 0em; + } + + .ui[class*="tablet stackable"].table thead { + display: block; + } + + .ui[class*="tablet stackable"].table tfoot { + display: block; + } + + .ui[class*="tablet stackable"].table tr { + padding-top: 1em; + padding-bottom: 1em; + box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.1) inset !important; + } + + .ui[class*="tablet stackable"].table tr > th, + .ui[class*="tablet stackable"].table tr > td { + background: none; + border: none !important; + padding: 0.25em 0.75em; + box-shadow: none !important; + } + + /* Definition Table */ + + .ui.definition[class*="tablet stackable"].table thead th:first-child { + box-shadow: none !important; + } +} + +/*-------------- + Text Alignment +---------------*/ + +.ui.table[class*="left aligned"], +.ui.table [class*="left aligned"] { + text-align: left; +} + +.ui.table[class*="center aligned"], +.ui.table [class*="center aligned"] { + text-align: center; +} + +.ui.table[class*="right aligned"], +.ui.table [class*="right aligned"] { + text-align: right; +} + +/*------------------ + Vertical Alignment +------------------*/ + +.ui.table[class*="top aligned"], +.ui.table [class*="top aligned"] { + vertical-align: top; +} + +.ui.table[class*="middle aligned"], +.ui.table [class*="middle aligned"] { + vertical-align: middle; +} + +.ui.table[class*="bottom aligned"], +.ui.table [class*="bottom aligned"] { + vertical-align: bottom; +} + +/*-------------- + Collapsing +---------------*/ + +.ui.table th.collapsing, +.ui.table td.collapsing { + width: 1px; + white-space: nowrap; +} + +/*-------------- + Fixed +---------------*/ + +.ui.fixed.table { + table-layout: fixed; +} + +.ui.fixed.table th, +.ui.fixed.table td { + overflow: hidden; + text-overflow: ellipsis; +} + +/*-------------- + Selectable +---------------*/ + +.ui.selectable.table tbody tr:hover, +.ui.table tbody tr td.selectable:hover { + background: rgba(0, 0, 0, 0.05) !important; + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.selectable.inverted.table tbody tr:hover, +.ui.inverted.table tbody tr td.selectable:hover { + background: rgba(255, 255, 255, 0.08) !important; + color: #ffffff !important; +} + +/* Selectable Cell Link */ + +.ui.table tbody tr td.selectable { + padding: 0em; +} + +.ui.table tbody tr td.selectable > a:not(.ui) { + display: block; + color: inherit; + padding: 0.78571429em 0.78571429em; +} + +/* Other States */ + +.ui.selectable.table tr.error:hover, +.ui.table tr td.selectable.error:hover, +.ui.selectable.table tr:hover td.error { + background: #ffe7e7 !important; + color: #943634 !important; +} + +.ui.selectable.table tr.warning:hover, +.ui.table tr td.selectable.warning:hover, +.ui.selectable.table tr:hover td.warning { + background: #fff4e4 !important; + color: #493107 !important; +} + +.ui.selectable.table tr.active:hover, +.ui.table tr td.selectable.active:hover, +.ui.selectable.table tr:hover td.active { + background: #E0E0E0 !important; + color: rgba(0, 0, 0, 0.87) !important; +} + +.ui.selectable.table tr.positive:hover, +.ui.table tr td.selectable.positive:hover, +.ui.selectable.table tr:hover td.positive { + background: #f7ffe6 !important; + color: #275b28 !important; +} + +.ui.selectable.table tr.negative:hover, +.ui.table tr td.selectable.negative:hover, +.ui.selectable.table tr:hover td.negative { + background: #ffe7e7 !important; + color: #943634 !important; +} + +/*------------------- + Attached +--------------------*/ + +/* Middle */ + +.ui.attached.table { + top: 0px; + bottom: 0px; + border-radius: 0px; + margin: 0em -1px; + width: calc(100% + 2px ); + max-width: calc(100% + 2px ); + box-shadow: none; + border: 1px solid #D4D4D5; +} + +.ui.attached + .ui.attached.table:not(.top) { + border-top: none; +} + +/* Top */ + +.ui[class*="top attached"].table { + bottom: 0px; + margin-bottom: 0em; + top: 0px; + margin-top: 1em; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.table[class*="top attached"]:first-child { + margin-top: 0em; +} + +/* Bottom */ + +.ui[class*="bottom attached"].table { + bottom: 0px; + margin-top: 0em; + top: 0px; + margin-bottom: 1em; + box-shadow: none, none; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui[class*="bottom attached"].table:last-child { + margin-bottom: 0em; +} + +/*-------------- + Striped +---------------*/ + +/* Table Striping */ + +.ui.striped.table > tr:nth-child(2n), +.ui.striped.table tbody tr:nth-child(2n) { + background-color: rgba(0, 0, 50, 0.02); +} + +/* Stripes */ + +.ui.inverted.striped.table > tr:nth-child(2n), +.ui.inverted.striped.table tbody tr:nth-child(2n) { + background-color: rgba(255, 255, 255, 0.05); +} + +/* Allow striped active hover */ + +.ui.striped.selectable.selectable.selectable.table tbody tr.active:hover { + background: #EFEFEF !important; + color: rgba(0, 0, 0, 0.95) !important; +} + +/*-------------- + Single Line +---------------*/ + +.ui.table[class*="single line"], +.ui.table [class*="single line"] { + white-space: nowrap; +} + +.ui.table[class*="single line"], +.ui.table [class*="single line"] { + white-space: nowrap; +} + +/*------------------- + Colors +--------------------*/ + +/* Red */ + +.ui.red.table { + border-top: 0.2em solid #DB2828; +} + +.ui.inverted.red.table { + background-color: #DB2828 !important; + color: #FFFFFF !important; +} + +/* Orange */ + +.ui.orange.table { + border-top: 0.2em solid #F2711C; +} + +.ui.inverted.orange.table { + background-color: #F2711C !important; + color: #FFFFFF !important; +} + +/* Yellow */ + +.ui.yellow.table { + border-top: 0.2em solid #FBBD08; +} + +.ui.inverted.yellow.table { + background-color: #FBBD08 !important; + color: #FFFFFF !important; +} + +/* Olive */ + +.ui.olive.table { + border-top: 0.2em solid #B5CC18; +} + +.ui.inverted.olive.table { + background-color: #B5CC18 !important; + color: #FFFFFF !important; +} + +/* Green */ + +.ui.green.table { + border-top: 0.2em solid #21BA45; +} + +.ui.inverted.green.table { + background-color: #21BA45 !important; + color: #FFFFFF !important; +} + +/* Teal */ + +.ui.teal.table { + border-top: 0.2em solid #00B5AD; +} + +.ui.inverted.teal.table { + background-color: #00B5AD !important; + color: #FFFFFF !important; +} + +/* Blue */ + +.ui.blue.table { + border-top: 0.2em solid #2185D0; +} + +.ui.inverted.blue.table { + background-color: #2185D0 !important; + color: #FFFFFF !important; +} + +/* Violet */ + +.ui.violet.table { + border-top: 0.2em solid #6435C9; +} + +.ui.inverted.violet.table { + background-color: #6435C9 !important; + color: #FFFFFF !important; +} + +/* Purple */ + +.ui.purple.table { + border-top: 0.2em solid #A333C8; +} + +.ui.inverted.purple.table { + background-color: #A333C8 !important; + color: #FFFFFF !important; +} + +/* Pink */ + +.ui.pink.table { + border-top: 0.2em solid #E03997; +} + +.ui.inverted.pink.table { + background-color: #E03997 !important; + color: #FFFFFF !important; +} + +/* Brown */ + +.ui.brown.table { + border-top: 0.2em solid #A5673F; +} + +.ui.inverted.brown.table { + background-color: #A5673F !important; + color: #FFFFFF !important; +} + +/* Grey */ + +.ui.grey.table { + border-top: 0.2em solid #767676; +} + +.ui.inverted.grey.table { + background-color: #767676 !important; + color: #FFFFFF !important; +} + +/* Black */ + +.ui.black.table { + border-top: 0.2em solid #1B1C1D; +} + +.ui.inverted.black.table { + background-color: #1B1C1D !important; + color: #FFFFFF !important; +} + +/*-------------- + Column Count +---------------*/ + +/* Grid Based */ + +.ui.one.column.table td { + width: 100%; +} + +.ui.two.column.table td { + width: 50%; +} + +.ui.three.column.table td { + width: 33.33333333%; +} + +.ui.four.column.table td { + width: 25%; +} + +.ui.five.column.table td { + width: 20%; +} + +.ui.six.column.table td { + width: 16.66666667%; +} + +.ui.seven.column.table td { + width: 14.28571429%; +} + +.ui.eight.column.table td { + width: 12.5%; +} + +.ui.nine.column.table td { + width: 11.11111111%; +} + +.ui.ten.column.table td { + width: 10%; +} + +.ui.eleven.column.table td { + width: 9.09090909%; +} + +.ui.twelve.column.table td { + width: 8.33333333%; +} + +.ui.thirteen.column.table td { + width: 7.69230769%; +} + +.ui.fourteen.column.table td { + width: 7.14285714%; +} + +.ui.fifteen.column.table td { + width: 6.66666667%; +} + +.ui.sixteen.column.table td { + width: 6.25%; +} + +/* Column Width */ + +.ui.table th.one.wide, +.ui.table td.one.wide { + width: 6.25%; +} + +.ui.table th.two.wide, +.ui.table td.two.wide { + width: 12.5%; +} + +.ui.table th.three.wide, +.ui.table td.three.wide { + width: 18.75%; +} + +.ui.table th.four.wide, +.ui.table td.four.wide { + width: 25%; +} + +.ui.table th.five.wide, +.ui.table td.five.wide { + width: 31.25%; +} + +.ui.table th.six.wide, +.ui.table td.six.wide { + width: 37.5%; +} + +.ui.table th.seven.wide, +.ui.table td.seven.wide { + width: 43.75%; +} + +.ui.table th.eight.wide, +.ui.table td.eight.wide { + width: 50%; +} + +.ui.table th.nine.wide, +.ui.table td.nine.wide { + width: 56.25%; +} + +.ui.table th.ten.wide, +.ui.table td.ten.wide { + width: 62.5%; +} + +.ui.table th.eleven.wide, +.ui.table td.eleven.wide { + width: 68.75%; +} + +.ui.table th.twelve.wide, +.ui.table td.twelve.wide { + width: 75%; +} + +.ui.table th.thirteen.wide, +.ui.table td.thirteen.wide { + width: 81.25%; +} + +.ui.table th.fourteen.wide, +.ui.table td.fourteen.wide { + width: 87.5%; +} + +.ui.table th.fifteen.wide, +.ui.table td.fifteen.wide { + width: 93.75%; +} + +.ui.table th.sixteen.wide, +.ui.table td.sixteen.wide { + width: 100%; +} + +/*-------------- + Sortable +---------------*/ + +.ui.sortable.table thead th { + cursor: pointer; + white-space: nowrap; + border-left: 1px solid rgba(34, 36, 38, 0.15); + color: rgba(0, 0, 0, 0.87); +} + +.ui.sortable.table thead th:first-child { + border-left: none; +} + +.ui.sortable.table thead th.sorted, +.ui.sortable.table thead th.sorted:hover { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.ui.sortable.table thead th:after { + display: none; + font-style: normal; + font-weight: normal; + text-decoration: inherit; + content: ''; + height: 1em; + width: auto; + opacity: 0.8; + margin: 0em 0em 0em 0.5em; + font-family: 'Icons'; +} + +.ui.sortable.table thead th.ascending:after { + content: '\f0d8'; +} + +.ui.sortable.table thead th.descending:after { + content: '\f0d7'; +} + +/* Hover */ + +.ui.sortable.table th.disabled:hover { + cursor: auto; + color: rgba(40, 40, 40, 0.3); +} + +.ui.sortable.table thead th:hover { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.8); +} + +/* Sorted */ + +.ui.sortable.table thead th.sorted { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); +} + +.ui.sortable.table thead th.sorted:after { + display: inline-block; +} + +/* Sorted Hover */ + +.ui.sortable.table thead th.sorted:hover { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); +} + +/* Inverted */ + +.ui.inverted.sortable.table thead th.sorted { + background: rgba(255, 255, 255, 0.15) -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + background: rgba(255, 255, 255, 0.15) linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + color: #ffffff; +} + +.ui.inverted.sortable.table thead th:hover { + background: rgba(255, 255, 255, 0.08) -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + background: rgba(255, 255, 255, 0.08) linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + color: #ffffff; +} + +.ui.inverted.sortable.table thead th { + border-left-color: transparent; + border-right-color: transparent; +} + +/*-------------- + Inverted +---------------*/ + +/* Text Color */ + +.ui.inverted.table { + background: #333333; + color: rgba(255, 255, 255, 0.9); + border: none; +} + +.ui.inverted.table th { + background-color: rgba(0, 0, 0, 0.15); + border-color: rgba(255, 255, 255, 0.1) !important; + color: rgba(255, 255, 255, 0.9); +} + +.ui.inverted.table tr td { + border-color: rgba(255, 255, 255, 0.1) !important; +} + +.ui.inverted.table tr.disabled td, +.ui.inverted.table tr td.disabled, +.ui.inverted.table tr.disabled:hover td, +.ui.inverted.table tr:hover td.disabled { + pointer-events: none; + color: rgba(225, 225, 225, 0.3); +} + +/* Definition */ + +.ui.inverted.definition.table tfoot:not(.full-width) th:first-child, +.ui.inverted.definition.table thead:not(.full-width) th:first-child { + background: #FFFFFF; +} + +.ui.inverted.definition.table tr td:first-child { + background: rgba(255, 255, 255, 0.02); + color: #ffffff; +} + +/*-------------- + Collapsing +---------------*/ + +.ui.collapsing.table { + width: auto; +} + +/*-------------- + Basic +---------------*/ + +.ui.basic.table { + background: transparent; + border: 1px solid rgba(34, 36, 38, 0.15); + box-shadow: none; +} + +.ui.basic.table thead, +.ui.basic.table tfoot { + box-shadow: none; +} + +.ui.basic.table th { + background: transparent; + border-left: none; +} + +.ui.basic.table tbody tr { + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.ui.basic.table td { + background: transparent; +} + +.ui.basic.striped.table tbody tr:nth-child(2n) { + background-color: rgba(0, 0, 0, 0.05) !important; +} + +/* Very Basic */ + +.ui[class*="very basic"].table { + border: none; +} + +.ui[class*="very basic"].table:not(.sortable):not(.striped) th, +.ui[class*="very basic"].table:not(.sortable):not(.striped) td { + padding: ''; +} + +.ui[class*="very basic"].table:not(.sortable):not(.striped) th:first-child, +.ui[class*="very basic"].table:not(.sortable):not(.striped) td:first-child { + padding-left: 0em; +} + +.ui[class*="very basic"].table:not(.sortable):not(.striped) th:last-child, +.ui[class*="very basic"].table:not(.sortable):not(.striped) td:last-child { + padding-right: 0em; +} + +.ui[class*="very basic"].table:not(.sortable):not(.striped) thead tr:first-child th { + padding-top: 0em; +} + +/*-------------- + Celled +---------------*/ + +.ui.celled.table tr th, +.ui.celled.table tr td { + border-left: 1px solid rgba(34, 36, 38, 0.1); +} + +.ui.celled.table tr th:first-child, +.ui.celled.table tr td:first-child { + border-left: none; +} + +/*-------------- + Padded +---------------*/ + +.ui.padded.table th { + padding-left: 1em; + padding-right: 1em; +} + +.ui.padded.table th, +.ui.padded.table td { + padding: 1em 1em; +} + +/* Very */ + +.ui[class*="very padded"].table th { + padding-left: 1.5em; + padding-right: 1.5em; +} + +.ui[class*="very padded"].table td { + padding: 1.5em 1.5em; +} + +/*-------------- + Compact +---------------*/ + +.ui.compact.table th { + padding-left: 0.7em; + padding-right: 0.7em; +} + +.ui.compact.table td { + padding: 0.5em 0.7em; +} + +/* Very */ + +.ui[class*="very compact"].table th { + padding-left: 0.6em; + padding-right: 0.6em; +} + +.ui[class*="very compact"].table td { + padding: 0.4em 0.6em; +} + +/*-------------- + Sizes +---------------*/ + +/* Small */ + +.ui.small.table { + font-size: 0.9em; +} + +/* Standard */ + +.ui.table { + font-size: 1em; +} + +/* Large */ + +.ui.large.table { + font-size: 1.1em; +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Ad + * http://github.com/semantic-org/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Advertisement +*******************************/ + +.ui.ad { + display: block; + overflow: hidden; + margin: 1em 0em; +} + +.ui.ad:first-child { + margin: 0em; +} + +.ui.ad:last-child { + margin: 0em; +} + +.ui.ad iframe { + margin: 0em; + padding: 0em; + border: none; + overflow: hidden; +} + +/*-------------- + Common +---------------*/ + +/* Leaderboard */ + +.ui.leaderboard.ad { + width: 728px; + height: 90px; +} + +/* Medium Rectangle */ + +.ui[class*="medium rectangle"].ad { + width: 300px; + height: 250px; +} + +/* Large Rectangle */ + +.ui[class*="large rectangle"].ad { + width: 336px; + height: 280px; +} + +/* Half Page */ + +.ui[class*="half page"].ad { + width: 300px; + height: 600px; +} + +/*-------------- + Square +---------------*/ + +/* Square */ + +.ui.square.ad { + width: 250px; + height: 250px; +} + +/* Small Square */ + +.ui[class*="small square"].ad { + width: 200px; + height: 200px; +} + +/*-------------- + Rectangle +---------------*/ + +/* Small Rectangle */ + +.ui[class*="small rectangle"].ad { + width: 180px; + height: 150px; +} + +/* Vertical Rectangle */ + +.ui[class*="vertical rectangle"].ad { + width: 240px; + height: 400px; +} + +/*-------------- + Button +---------------*/ + +.ui.button.ad { + width: 120px; + height: 90px; +} + +.ui[class*="square button"].ad { + width: 125px; + height: 125px; +} + +.ui[class*="small button"].ad { + width: 120px; + height: 60px; +} + +/*-------------- + Skyscrapers +---------------*/ + +/* Skyscraper */ + +.ui.skyscraper.ad { + width: 120px; + height: 600px; +} + +/* Wide Skyscraper */ + +.ui[class*="wide skyscraper"].ad { + width: 160px; +} + +/*-------------- + Banners +---------------*/ + +/* Banner */ + +.ui.banner.ad { + width: 468px; + height: 60px; +} + +/* Vertical Banner */ + +.ui[class*="vertical banner"].ad { + width: 120px; + height: 240px; +} + +/* Top Banner */ + +.ui[class*="top banner"].ad { + width: 930px; + height: 180px; +} + +/* Half Banner */ + +.ui[class*="half banner"].ad { + width: 234px; + height: 60px; +} + +/*-------------- + Boards +---------------*/ + +/* Leaderboard */ + +.ui[class*="large leaderboard"].ad { + width: 970px; + height: 90px; +} + +/* Billboard */ + +.ui.billboard.ad { + width: 970px; + height: 250px; +} + +/*-------------- + Panorama +---------------*/ + +/* Panorama */ + +.ui.panorama.ad { + width: 980px; + height: 120px; +} + +/*-------------- + Netboard +---------------*/ + +/* Netboard */ + +.ui.netboard.ad { + width: 580px; + height: 400px; +} + +/*-------------- + Mobile +---------------*/ + +/* Large Mobile Banner */ + +.ui[class*="large mobile banner"].ad { + width: 320px; + height: 100px; +} + +/* Mobile Leaderboard */ + +.ui[class*="mobile leaderboard"].ad { + width: 320px; + height: 50px; +} + +/******************************* + Types +*******************************/ + +/* Mobile Sizes */ + +.ui.mobile.ad { + display: none; +} + +@media only screen and (max-width: 767px) { + .ui.mobile.ad { + display: block; + } +} + +/******************************* + Variations +*******************************/ + +.ui.centered.ad { + margin-left: auto; + margin-right: auto; +} + +.ui.test.ad { + position: relative; + background: #545454; +} + +.ui.test.ad:after { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + text-align: center; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + content: 'Ad'; + color: #FFFFFF; + font-size: 1em; + font-weight: bold; +} + +.ui.mobile.test.ad:after { + font-size: 0.85714286em; +} + +.ui.test.ad[data-text]:after { + content: attr(data-text); +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Item + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Standard +*******************************/ + +/*-------------- + Card +---------------*/ + +.ui.cards > .card, +.ui.card { + max-width: 100%; + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: 290px; + min-height: 0px; + background: #FFFFFF; + padding: 0em; + border: none; + border-radius: 0.28571429rem; + box-shadow: 0px 1px 3px 0px #D4D4D5, 0px 0px 0px 1px #D4D4D5; + -webkit-transition: box-shadow 0.1s ease, -webkit-transform 0.1s ease; + transition: box-shadow 0.1s ease, -webkit-transform 0.1s ease; + transition: box-shadow 0.1s ease, transform 0.1s ease; + transition: box-shadow 0.1s ease, transform 0.1s ease, -webkit-transform 0.1s ease; + z-index: ''; +} + +.ui.card { + margin: 1em 0em; +} + +.ui.cards > .card a, +.ui.card a { + cursor: pointer; +} + +.ui.card:first-child { + margin-top: 0em; +} + +.ui.card:last-child { + margin-bottom: 0em; +} + +/*-------------- + Cards +---------------*/ + +.ui.cards { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin: -0.875em -0.5em; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.ui.cards > .card { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin: 0.875em 0.5em; + float: none; +} + +/* Clearing */ + +.ui.cards:after, +.ui.card:after { + display: block; + content: ' '; + height: 0px; + clear: both; + overflow: hidden; + visibility: hidden; +} + +/* Consecutive Card Groups Preserve Row Spacing */ + +.ui.cards ~ .ui.cards { + margin-top: 0.875em; +} + +/*-------------- + Rounded Edges +---------------*/ + +.ui.cards > .card > :first-child, +.ui.card > :first-child { + border-radius: 0.28571429rem 0.28571429rem 0em 0em !important; + border-top: none !important; +} + +.ui.cards > .card > :last-child, +.ui.card > :last-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem !important; +} + +.ui.cards > .card > :only-child, +.ui.card > :only-child { + border-radius: 0.28571429rem !important; +} + +/*-------------- + Images +---------------*/ + +.ui.cards > .card > .image, +.ui.card > .image { + position: relative; + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + padding: 0em; + background: rgba(0, 0, 0, 0.05); +} + +.ui.cards > .card > .image > img, +.ui.card > .image > img { + display: block; + width: 100%; + height: auto; + border-radius: inherit; +} + +.ui.cards > .card > .image:not(.ui) > img, +.ui.card > .image:not(.ui) > img { + border: none; +} + +/*-------------- + Content +---------------*/ + +.ui.cards > .card > .content, +.ui.card > .content { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + border: none; + border-top: 1px solid rgba(34, 36, 38, 0.1); + background: none; + margin: 0em; + padding: 1em 1em; + box-shadow: none; + font-size: 1em; + border-radius: 0em; +} + +.ui.cards > .card > .content:after, +.ui.card > .content:after { + display: block; + content: ' '; + height: 0px; + clear: both; + overflow: hidden; + visibility: hidden; +} + +.ui.cards > .card > .content > .header, +.ui.card > .content > .header { + display: block; + margin: ''; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + color: rgba(0, 0, 0, 0.85); +} + +/* Default Header Size */ + +.ui.cards > .card > .content > .header:not(.ui), +.ui.card > .content > .header:not(.ui) { + font-weight: bold; + font-size: 1.28571429em; + margin-top: -0.21425em; + line-height: 1.28571429em; +} + +.ui.cards > .card > .content > .meta + .description, +.ui.cards > .card > .content > .header + .description, +.ui.card > .content > .meta + .description, +.ui.card > .content > .header + .description { + margin-top: 0.5em; +} + +/*---------------- + Floated Content +-----------------*/ + +.ui.cards > .card [class*="left floated"], +.ui.card [class*="left floated"] { + float: left; +} + +.ui.cards > .card [class*="right floated"], +.ui.card [class*="right floated"] { + float: right; +} + +/*-------------- + Aligned +---------------*/ + +.ui.cards > .card [class*="left aligned"], +.ui.card [class*="left aligned"] { + text-align: left; +} + +.ui.cards > .card [class*="center aligned"], +.ui.card [class*="center aligned"] { + text-align: center; +} + +.ui.cards > .card [class*="right aligned"], +.ui.card [class*="right aligned"] { + text-align: right; +} + +/*-------------- + Content Image +---------------*/ + +.ui.cards > .card .content img, +.ui.card .content img { + display: inline-block; + vertical-align: middle; + width: ''; +} + +.ui.cards > .card img.avatar, +.ui.cards > .card .avatar img, +.ui.card img.avatar, +.ui.card .avatar img { + width: 2em; + height: 2em; + border-radius: 500rem; +} + +/*-------------- + Description +---------------*/ + +.ui.cards > .card > .content > .description, +.ui.card > .content > .description { + clear: both; + color: rgba(0, 0, 0, 0.68); +} + +/*-------------- + Paragraph +---------------*/ + +.ui.cards > .card > .content p, +.ui.card > .content p { + margin: 0em 0em 0.5em; +} + +.ui.cards > .card > .content p:last-child, +.ui.card > .content p:last-child { + margin-bottom: 0em; +} + +/*-------------- + Meta +---------------*/ + +.ui.cards > .card .meta, +.ui.card .meta { + font-size: 1em; + color: rgba(0, 0, 0, 0.4); +} + +.ui.cards > .card .meta *, +.ui.card .meta * { + margin-right: 0.3em; +} + +.ui.cards > .card .meta :last-child, +.ui.card .meta :last-child { + margin-right: 0em; +} + +.ui.cards > .card .meta [class*="right floated"], +.ui.card .meta [class*="right floated"] { + margin-right: 0em; + margin-left: 0.3em; +} + +/*-------------- + Links +---------------*/ + +/* Generic */ + +.ui.cards > .card > .content a:not(.ui), +.ui.card > .content a:not(.ui) { + color: ''; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.cards > .card > .content a:not(.ui):hover, +.ui.card > .content a:not(.ui):hover { + color: ''; +} + +/* Header */ + +.ui.cards > .card > .content > a.header, +.ui.card > .content > a.header { + color: rgba(0, 0, 0, 0.85); +} + +.ui.cards > .card > .content > a.header:hover, +.ui.card > .content > a.header:hover { + color: #1e70bf; +} + +/* Meta */ + +.ui.cards > .card .meta > a:not(.ui), +.ui.card .meta > a:not(.ui) { + color: rgba(0, 0, 0, 0.4); +} + +.ui.cards > .card .meta > a:not(.ui):hover, +.ui.card .meta > a:not(.ui):hover { + color: rgba(0, 0, 0, 0.87); +} + +/*-------------- + Buttons +---------------*/ + +.ui.cards > .card > .buttons, +.ui.card > .buttons, +.ui.cards > .card > .button, +.ui.card > .button { + margin: 0px -1px; + width: calc(100% + 2px ); +} + +/*-------------- + Dimmer +---------------*/ + +.ui.cards > .card .dimmer, +.ui.card .dimmer { + background-color: ''; + z-index: 10; +} + +/*-------------- + Labels +---------------*/ + +/*-----Star----- */ + +/* Icon */ + +.ui.cards > .card > .content .star.icon, +.ui.card > .content .star.icon { + cursor: pointer; + opacity: 0.75; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.cards > .card > .content .star.icon:hover, +.ui.card > .content .star.icon:hover { + opacity: 1; + color: #FFB70A; +} + +.ui.cards > .card > .content .active.star.icon, +.ui.card > .content .active.star.icon { + color: #FFE623; +} + +/*-----Like----- */ + +/* Icon */ + +.ui.cards > .card > .content .like.icon, +.ui.card > .content .like.icon { + cursor: pointer; + opacity: 0.75; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.cards > .card > .content .like.icon:hover, +.ui.card > .content .like.icon:hover { + opacity: 1; + color: #FF2733; +} + +.ui.cards > .card > .content .active.like.icon, +.ui.card > .content .active.like.icon { + color: #FF2733; +} + +/*---------------- + Extra Content +-----------------*/ + +.ui.cards > .card > .extra, +.ui.card > .extra { + max-width: 100%; + min-height: 0em !important; + -webkit-box-flex: 0; + -webkit-flex-grow: 0; + -ms-flex-positive: 0; + flex-grow: 0; + border-top: 1px solid rgba(0, 0, 0, 0.05) !important; + position: static; + background: none; + width: auto; + margin: 0em 0em; + padding: 0.75em 1em; + top: 0em; + left: 0em; + color: rgba(0, 0, 0, 0.4); + box-shadow: none; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.cards > .card > .extra a:not(.ui), +.ui.card > .extra a:not(.ui) { + color: rgba(0, 0, 0, 0.4); +} + +.ui.cards > .card > .extra a:not(.ui):hover, +.ui.card > .extra a:not(.ui):hover { + color: #1e70bf; +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Raised +--------------------*/ + +.ui.raised.cards > .card, +.ui.raised.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); +} + +.ui.raised.cards a.card:hover, +.ui.link.cards .raised.card:hover, +a.ui.raised.card:hover, +.ui.link.raised.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 4px 0px rgba(34, 36, 38, 0.15), 0px 2px 10px 0px rgba(34, 36, 38, 0.25); +} + +.ui.raised.cards > .card, +.ui.raised.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); +} + +/*------------------- + Centered +--------------------*/ + +.ui.centered.cards { + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +.ui.centered.card { + margin-left: auto; + margin-right: auto; +} + +/*------------------- + Fluid +--------------------*/ + +.ui.fluid.card { + width: 100%; + max-width: 9999px; +} + +/*------------------- + Link +--------------------*/ + +.ui.cards a.card, +.ui.link.cards .card, +a.ui.card, +.ui.link.card { + -webkit-transform: none; + transform: none; +} + +.ui.cards a.card:hover, +.ui.link.cards .card:hover, +a.ui.card:hover, +.ui.link.card:hover { + cursor: pointer; + z-index: 5; + background: #FFFFFF; + border: none; + box-shadow: 0px 1px 3px 0px #BCBDBD, 0px 0px 0px 1px #D4D4D5; + -webkit-transform: translateY(-3px); + transform: translateY(-3px); +} + +/*------------------- + Colors +--------------------*/ + +/* Red */ + +.ui.red.cards > .card, +.ui.cards > .red.card, +.ui.red.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #DB2828, 0px 1px 3px 0px #D4D4D5; +} + +.ui.red.cards > .card:hover, +.ui.cards > .red.card:hover, +.ui.red.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #d01919, 0px 1px 3px 0px #BCBDBD; +} + +/* Orange */ + +.ui.orange.cards > .card, +.ui.cards > .orange.card, +.ui.orange.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #F2711C, 0px 1px 3px 0px #D4D4D5; +} + +.ui.orange.cards > .card:hover, +.ui.cards > .orange.card:hover, +.ui.orange.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #f26202, 0px 1px 3px 0px #BCBDBD; +} + +/* Yellow */ + +.ui.yellow.cards > .card, +.ui.cards > .yellow.card, +.ui.yellow.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #FBBD08, 0px 1px 3px 0px #D4D4D5; +} + +.ui.yellow.cards > .card:hover, +.ui.cards > .yellow.card:hover, +.ui.yellow.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #eaae00, 0px 1px 3px 0px #BCBDBD; +} + +/* Olive */ + +.ui.olive.cards > .card, +.ui.cards > .olive.card, +.ui.olive.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #B5CC18, 0px 1px 3px 0px #D4D4D5; +} + +.ui.olive.cards > .card:hover, +.ui.cards > .olive.card:hover, +.ui.olive.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #a7bd0d, 0px 1px 3px 0px #BCBDBD; +} + +/* Green */ + +.ui.green.cards > .card, +.ui.cards > .green.card, +.ui.green.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #21BA45, 0px 1px 3px 0px #D4D4D5; +} + +.ui.green.cards > .card:hover, +.ui.cards > .green.card:hover, +.ui.green.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #16ab39, 0px 1px 3px 0px #BCBDBD; +} + +/* Teal */ + +.ui.teal.cards > .card, +.ui.cards > .teal.card, +.ui.teal.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #00B5AD, 0px 1px 3px 0px #D4D4D5; +} + +.ui.teal.cards > .card:hover, +.ui.cards > .teal.card:hover, +.ui.teal.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #009c95, 0px 1px 3px 0px #BCBDBD; +} + +/* Blue */ + +.ui.blue.cards > .card, +.ui.cards > .blue.card, +.ui.blue.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #2185D0, 0px 1px 3px 0px #D4D4D5; +} + +.ui.blue.cards > .card:hover, +.ui.cards > .blue.card:hover, +.ui.blue.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #1678c2, 0px 1px 3px 0px #BCBDBD; +} + +/* Violet */ + +.ui.violet.cards > .card, +.ui.cards > .violet.card, +.ui.violet.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #6435C9, 0px 1px 3px 0px #D4D4D5; +} + +.ui.violet.cards > .card:hover, +.ui.cards > .violet.card:hover, +.ui.violet.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #5829bb, 0px 1px 3px 0px #BCBDBD; +} + +/* Purple */ + +.ui.purple.cards > .card, +.ui.cards > .purple.card, +.ui.purple.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #A333C8, 0px 1px 3px 0px #D4D4D5; +} + +.ui.purple.cards > .card:hover, +.ui.cards > .purple.card:hover, +.ui.purple.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #9627ba, 0px 1px 3px 0px #BCBDBD; +} + +/* Pink */ + +.ui.pink.cards > .card, +.ui.cards > .pink.card, +.ui.pink.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #E03997, 0px 1px 3px 0px #D4D4D5; +} + +.ui.pink.cards > .card:hover, +.ui.cards > .pink.card:hover, +.ui.pink.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #e61a8d, 0px 1px 3px 0px #BCBDBD; +} + +/* Brown */ + +.ui.brown.cards > .card, +.ui.cards > .brown.card, +.ui.brown.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #A5673F, 0px 1px 3px 0px #D4D4D5; +} + +.ui.brown.cards > .card:hover, +.ui.cards > .brown.card:hover, +.ui.brown.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #975b33, 0px 1px 3px 0px #BCBDBD; +} + +/* Grey */ + +.ui.grey.cards > .card, +.ui.cards > .grey.card, +.ui.grey.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #767676, 0px 1px 3px 0px #D4D4D5; +} + +.ui.grey.cards > .card:hover, +.ui.cards > .grey.card:hover, +.ui.grey.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #838383, 0px 1px 3px 0px #BCBDBD; +} + +/* Black */ + +.ui.black.cards > .card, +.ui.cards > .black.card, +.ui.black.card { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #1B1C1D, 0px 1px 3px 0px #D4D4D5; +} + +.ui.black.cards > .card:hover, +.ui.cards > .black.card:hover, +.ui.black.card:hover { + box-shadow: 0px 0px 0px 1px #D4D4D5, 0px 2px 0px 0px #27292a, 0px 1px 3px 0px #BCBDBD; +} + +/*-------------- + Card Count +---------------*/ + +.ui.one.cards { + margin-left: 0em; + margin-right: 0em; +} + +.ui.one.cards > .card { + width: 100%; +} + +.ui.two.cards { + margin-left: -1em; + margin-right: -1em; +} + +.ui.two.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; +} + +.ui.three.cards { + margin-left: -1em; + margin-right: -1em; +} + +.ui.three.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; +} + +.ui.four.cards { + margin-left: -0.75em; + margin-right: -0.75em; +} + +.ui.four.cards > .card { + width: calc( 25% - 1.5em ); + margin-left: 0.75em; + margin-right: 0.75em; +} + +.ui.five.cards { + margin-left: -0.75em; + margin-right: -0.75em; +} + +.ui.five.cards > .card { + width: calc( 20% - 1.5em ); + margin-left: 0.75em; + margin-right: 0.75em; +} + +.ui.six.cards { + margin-left: -0.75em; + margin-right: -0.75em; +} + +.ui.six.cards > .card { + width: calc( 16.66666667% - 1.5em ); + margin-left: 0.75em; + margin-right: 0.75em; +} + +.ui.seven.cards { + margin-left: -0.5em; + margin-right: -0.5em; +} + +.ui.seven.cards > .card { + width: calc( 14.28571429% - 1em ); + margin-left: 0.5em; + margin-right: 0.5em; +} + +.ui.eight.cards { + margin-left: -0.5em; + margin-right: -0.5em; +} + +.ui.eight.cards > .card { + width: calc( 12.5% - 1em ); + margin-left: 0.5em; + margin-right: 0.5em; + font-size: 11px; +} + +.ui.nine.cards { + margin-left: -0.5em; + margin-right: -0.5em; +} + +.ui.nine.cards > .card { + width: calc( 11.11111111% - 1em ); + margin-left: 0.5em; + margin-right: 0.5em; + font-size: 10px; +} + +.ui.ten.cards { + margin-left: -0.5em; + margin-right: -0.5em; +} + +.ui.ten.cards > .card { + width: calc( 10% - 1em ); + margin-left: 0.5em; + margin-right: 0.5em; +} + +/*------------------- + Doubling +--------------------*/ + +/* Mobile Only */ + +@media only screen and (max-width: 767px) { + .ui.two.doubling.cards { + margin-left: 0em; + margin-right: 0em; + } + + .ui.two.doubling.cards > .card { + width: 100%; + margin-left: 0em; + margin-right: 0em; + } + + .ui.three.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.three.doubling.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.four.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.four.doubling.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.five.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.five.doubling.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.six.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.six.doubling.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.seven.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.seven.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.eight.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.eight.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.nine.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.nine.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.ten.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.ten.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } +} + +/* Tablet Only */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui.two.doubling.cards { + margin-left: 0em; + margin-right: 0em; + } + + .ui.two.doubling.cards > .card { + width: 100%; + margin-left: 0em; + margin-right: 0em; + } + + .ui.three.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.three.doubling.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.four.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.four.doubling.cards > .card { + width: calc( 50% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.five.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.five.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.six.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.six.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.eight.doubling.cards { + margin-left: -1em; + margin-right: -1em; + } + + .ui.eight.doubling.cards > .card { + width: calc( 33.33333333% - 2em ); + margin-left: 1em; + margin-right: 1em; + } + + .ui.eight.doubling.cards { + margin-left: -0.75em; + margin-right: -0.75em; + } + + .ui.eight.doubling.cards > .card { + width: calc( 25% - 1.5em ); + margin-left: 0.75em; + margin-right: 0.75em; + } + + .ui.nine.doubling.cards { + margin-left: -0.75em; + margin-right: -0.75em; + } + + .ui.nine.doubling.cards > .card { + width: calc( 25% - 1.5em ); + margin-left: 0.75em; + margin-right: 0.75em; + } + + .ui.ten.doubling.cards { + margin-left: -0.75em; + margin-right: -0.75em; + } + + .ui.ten.doubling.cards > .card { + width: calc( 20% - 1.5em ); + margin-left: 0.75em; + margin-right: 0.75em; + } +} + +/*------------------- + Stackable +--------------------*/ + +@media only screen and (max-width: 767px) { + .ui.stackable.cards { + display: block !important; + } + + .ui.stackable.cards .card:first-child { + margin-top: 0em !important; + } + + .ui.stackable.cards > .card { + display: block !important; + height: auto !important; + margin: 1em 1em; + padding: 0 !important; + width: calc( 100% - 2em ) !important; + } +} + +/*-------------- + Size +---------------*/ + +.ui.cards > .card { + font-size: 1em; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Comment + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Standard +*******************************/ + +/*-------------- + Comments +---------------*/ + +.ui.comments { + margin: 1.5em 0em; + max-width: 650px; +} + +.ui.comments:first-child { + margin-top: 0em; +} + +.ui.comments:last-child { + margin-bottom: 0em; +} + +/*-------------- + Comment +---------------*/ + +.ui.comments .comment { + position: relative; + background: none; + margin: 0.5em 0em 0em; + padding: 0.5em 0em 0em; + border: none; + border-top: none; + line-height: 1.2; +} + +.ui.comments .comment:first-child { + margin-top: 0em; + padding-top: 0em; +} + +/*-------------------- + Nested Comments +---------------------*/ + +.ui.comments .comment .comments { + margin: 0em 0em 0.5em 0.5em; + padding: 1em 0em 1em 1em; +} + +.ui.comments .comment .comments:before { + position: absolute; + top: 0px; + left: 0px; +} + +.ui.comments .comment .comments .comment { + border: none; + border-top: none; + background: none; +} + +/*-------------- + Avatar +---------------*/ + +.ui.comments .comment .avatar { + display: block; + width: 2.5em; + height: auto; + float: left; + margin: 0.2em 0em 0em; +} + +.ui.comments .comment img.avatar, +.ui.comments .comment .avatar img { + display: block; + margin: 0em auto; + width: 100%; + height: 100%; + border-radius: 0.25rem; +} + +/*-------------- + Content +---------------*/ + +.ui.comments .comment > .content { + display: block; +} + +/* If there is an avatar move content over */ + +.ui.comments .comment > .avatar ~ .content { + margin-left: 3.5em; +} + +/*-------------- + Author +---------------*/ + +.ui.comments .comment .author { + font-size: 1em; + color: rgba(0, 0, 0, 0.87); + font-weight: bold; +} + +.ui.comments .comment a.author { + cursor: pointer; +} + +.ui.comments .comment a.author:hover { + color: #1e70bf; +} + +/*-------------- + Metadata +---------------*/ + +.ui.comments .comment .metadata { + display: inline-block; + margin-left: 0.5em; + color: rgba(0, 0, 0, 0.4); + font-size: 0.875em; +} + +.ui.comments .comment .metadata > * { + display: inline-block; + margin: 0em 0.5em 0em 0em; +} + +.ui.comments .comment .metadata > :last-child { + margin-right: 0em; +} + +/*-------------------- + Comment Text +---------------------*/ + +.ui.comments .comment .text { + margin: 0.25em 0em 0.5em; + font-size: 1em; + word-wrap: break-word; + color: rgba(0, 0, 0, 0.87); + line-height: 1.3; +} + +/*-------------------- + User Actions +---------------------*/ + +.ui.comments .comment .actions { + font-size: 0.875em; +} + +.ui.comments .comment .actions a { + cursor: pointer; + display: inline-block; + margin: 0em 0.75em 0em 0em; + color: rgba(0, 0, 0, 0.4); +} + +.ui.comments .comment .actions a:last-child { + margin-right: 0em; +} + +.ui.comments .comment .actions a.active, +.ui.comments .comment .actions a:hover { + color: rgba(0, 0, 0, 0.8); +} + +/*-------------------- + Reply Form +---------------------*/ + +.ui.comments > .reply.form { + margin-top: 1em; +} + +.ui.comments .comment .reply.form { + width: 100%; + margin-top: 1em; +} + +.ui.comments .reply.form textarea { + font-size: 1em; + height: 12em; +} + +/******************************* + State +*******************************/ + +.ui.collapsed.comments, +.ui.comments .collapsed.comments, +.ui.comments .collapsed.comment { + display: none; +} + +/******************************* + Variations +*******************************/ + +/*-------------------- + Threaded +---------------------*/ + +.ui.threaded.comments .comment .comments { + margin: -1.5em 0 -1em 1.25em; + padding: 3em 0em 2em 2.25em; + box-shadow: -1px 0px 0px rgba(34, 36, 38, 0.15); +} + +/*-------------------- + Minimal +---------------------*/ + +.ui.minimal.comments .comment .actions { + opacity: 0; + position: absolute; + top: 0px; + right: 0px; + left: auto; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; + -webkit-transition-delay: 0.1s; + transition-delay: 0.1s; +} + +.ui.minimal.comments .comment > .content:hover > .actions { + opacity: 1; +} + +/*------------------- + Sizes +--------------------*/ + +.ui.mini.comments { + font-size: 0.78571429rem; +} + +.ui.tiny.comments { + font-size: 0.85714286rem; +} + +.ui.small.comments { + font-size: 0.92857143rem; +} + +.ui.comments { + font-size: 1rem; +} + +.ui.large.comments { + font-size: 1.14285714rem; +} + +.ui.big.comments { + font-size: 1.28571429rem; +} + +.ui.huge.comments { + font-size: 1.42857143rem; +} + +.ui.massive.comments { + font-size: 1.71428571rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Feed + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Activity Feed +*******************************/ + +.ui.feed { + margin: 1em 0em; +} + +.ui.feed:first-child { + margin-top: 0em; +} + +.ui.feed:last-child { + margin-bottom: 0em; +} + +/******************************* + Content +*******************************/ + +/* Event */ + +.ui.feed > .event { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + width: 100%; + padding: 0.21428571rem 0em; + margin: 0em; + background: none; + border-top: none; +} + +.ui.feed > .event:first-child { + border-top: 0px; + padding-top: 0em; +} + +.ui.feed > .event:last-child { + padding-bottom: 0em; +} + +/* Event Label */ + +.ui.feed > .event > .label { + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 2.5em; + height: auto; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + text-align: left; +} + +.ui.feed > .event > .label .icon { + opacity: 1; + font-size: 1.5em; + width: 100%; + padding: 0.25em; + background: none; + border: none; + border-radius: none; + color: rgba(0, 0, 0, 0.6); +} + +.ui.feed > .event > .label img { + width: 100%; + height: auto; + border-radius: 500rem; +} + +.ui.feed > .event > .label + .content { + margin: 0.5em 0em 0.35714286em 1.14285714em; +} + +/*-------------- + Content +---------------*/ + +/* Content */ + +.ui.feed > .event > .content { + display: block; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + text-align: left; + word-wrap: break-word; +} + +.ui.feed > .event:last-child > .content { + padding-bottom: 0em; +} + +/* Link */ + +.ui.feed > .event > .content a { + cursor: pointer; +} + +/*-------------- + Date +---------------*/ + +.ui.feed > .event > .content .date { + margin: -0.5rem 0em 0em; + padding: 0em; + font-weight: normal; + font-size: 1em; + font-style: normal; + color: rgba(0, 0, 0, 0.4); +} + +/*-------------- + Summary +---------------*/ + +.ui.feed > .event > .content .summary { + margin: 0em; + font-size: 1em; + font-weight: bold; + color: rgba(0, 0, 0, 0.87); +} + +/* Summary Image */ + +.ui.feed > .event > .content .summary img { + display: inline-block; + width: auto; + height: 10em; + margin: -0.25em 0.25em 0em 0em; + border-radius: 0.25em; + vertical-align: middle; +} + +/*-------------- + User +---------------*/ + +.ui.feed > .event > .content .user { + display: inline-block; + font-weight: bold; + margin-right: 0em; + vertical-align: baseline; +} + +.ui.feed > .event > .content .user img { + margin: -0.25em 0.25em 0em 0em; + width: auto; + height: 10em; + vertical-align: middle; +} + +/*-------------- + Inline Date +---------------*/ + +/* Date inside Summary */ + +.ui.feed > .event > .content .summary > .date { + display: inline-block; + float: none; + font-weight: normal; + font-size: 0.85714286em; + font-style: normal; + margin: 0em 0em 0em 0.5em; + padding: 0em; + color: rgba(0, 0, 0, 0.4); +} + +/*-------------- + Extra Summary +---------------*/ + +.ui.feed > .event > .content .extra { + margin: 0.5em 0em 0em; + background: none; + padding: 0em; + color: rgba(0, 0, 0, 0.87); +} + +/* Images */ + +.ui.feed > .event > .content .extra.images img { + display: inline-block; + margin: 0em 0.25em 0em 0em; + width: 6em; +} + +/* Text */ + +.ui.feed > .event > .content .extra.text { + padding: 0em; + border-left: none; + font-size: 1em; + max-width: 500px; + line-height: 1.4285em; +} + +/*-------------- + Meta +---------------*/ + +.ui.feed > .event > .content .meta { + display: inline-block; + font-size: 0.85714286em; + margin: 0.5em 0em 0em; + background: none; + border: none; + border-radius: 0; + box-shadow: none; + padding: 0em; + color: rgba(0, 0, 0, 0.6); +} + +.ui.feed > .event > .content .meta > * { + position: relative; + margin-left: 0.75em; +} + +.ui.feed > .event > .content .meta > *:after { + content: ''; + color: rgba(0, 0, 0, 0.2); + top: 0em; + left: -1em; + opacity: 1; + position: absolute; + vertical-align: top; +} + +.ui.feed > .event > .content .meta .like { + color: ''; + -webkit-transition: 0.2s color ease; + transition: 0.2s color ease; +} + +.ui.feed > .event > .content .meta .like:hover .icon { + color: #FF2733; +} + +.ui.feed > .event > .content .meta .active.like .icon { + color: #EF404A; +} + +/* First element */ + +.ui.feed > .event > .content .meta > :first-child { + margin-left: 0em; +} + +.ui.feed > .event > .content .meta > :first-child::after { + display: none; +} + +/* Action */ + +.ui.feed > .event > .content .meta a, +.ui.feed > .event > .content .meta > .icon { + cursor: pointer; + opacity: 1; + color: rgba(0, 0, 0, 0.5); + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.feed > .event > .content .meta a:hover, +.ui.feed > .event > .content .meta a:hover .icon, +.ui.feed > .event > .content .meta > .icon:hover { + color: rgba(0, 0, 0, 0.95); +} + +/******************************* + Variations +*******************************/ + +.ui.small.feed { + font-size: 0.92857143rem; +} + +.ui.feed { + font-size: 1rem; +} + +.ui.large.feed { + font-size: 1.14285714rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Item + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Standard +*******************************/ + +/*-------------- + Item +---------------*/ + +.ui.items > .item { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin: 1em 0em; + width: 100%; + min-height: 0px; + background: transparent; + padding: 0em; + border: none; + border-radius: 0rem; + box-shadow: none; + -webkit-transition: box-shadow 0.1s ease; + transition: box-shadow 0.1s ease; + z-index: ''; +} + +.ui.items > .item a { + cursor: pointer; +} + +/*-------------- + Items +---------------*/ + +.ui.items { + margin: 1.5em 0em; +} + +.ui.items:first-child { + margin-top: 0em !important; +} + +.ui.items:last-child { + margin-bottom: 0em !important; +} + +/*-------------- + Item +---------------*/ + +.ui.items > .item:after { + display: block; + content: ' '; + height: 0px; + clear: both; + overflow: hidden; + visibility: hidden; +} + +.ui.items > .item:first-child { + margin-top: 0em; +} + +.ui.items > .item:last-child { + margin-bottom: 0em; +} + +/*-------------- + Images +---------------*/ + +.ui.items > .item > .image { + position: relative; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + display: block; + float: none; + margin: 0em; + padding: 0em; + max-height: ''; + -webkit-align-self: top; + -ms-flex-item-align: top; + align-self: top; +} + +.ui.items > .item > .image > img { + display: block; + width: 100%; + height: auto; + border-radius: 0.125rem; + border: none; +} + +.ui.items > .item > .image:only-child > img { + border-radius: 0rem; +} + +/*-------------- + Content +---------------*/ + +.ui.items > .item > .content { + display: block; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + background: none; + margin: 0em; + padding: 0em; + box-shadow: none; + font-size: 1em; + border: none; + border-radius: 0em; +} + +.ui.items > .item > .content:after { + display: block; + content: ' '; + height: 0px; + clear: both; + overflow: hidden; + visibility: hidden; +} + +.ui.items > .item > .image + .content { + min-width: 0; + width: auto; + display: block; + margin-left: 0em; + -webkit-align-self: top; + -ms-flex-item-align: top; + align-self: top; + padding-left: 1.5em; +} + +.ui.items > .item > .content > .header { + display: inline-block; + margin: -0.21425em 0em 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-weight: bold; + color: rgba(0, 0, 0, 0.85); +} + +/* Default Header Size */ + +.ui.items > .item > .content > .header:not(.ui) { + font-size: 1.28571429em; +} + +/*-------------- + Floated +---------------*/ + +.ui.items > .item [class*="left floated"] { + float: left; +} + +.ui.items > .item [class*="right floated"] { + float: right; +} + +/*-------------- + Content Image +---------------*/ + +.ui.items > .item .content img { + -webkit-align-self: middle; + -ms-flex-item-align: middle; + align-self: middle; + width: ''; +} + +.ui.items > .item img.avatar, +.ui.items > .item .avatar img { + width: ''; + height: ''; + border-radius: 500rem; +} + +/*-------------- + Description +---------------*/ + +.ui.items > .item > .content > .description { + margin-top: 0.6em; + max-width: auto; + font-size: 1em; + line-height: 1.4285em; + color: rgba(0, 0, 0, 0.87); +} + +/*-------------- + Paragraph +---------------*/ + +.ui.items > .item > .content p { + margin: 0em 0em 0.5em; +} + +.ui.items > .item > .content p:last-child { + margin-bottom: 0em; +} + +/*-------------- + Meta +---------------*/ + +.ui.items > .item .meta { + margin: 0.5em 0em 0.5em; + font-size: 1em; + line-height: 1em; + color: rgba(0, 0, 0, 0.6); +} + +.ui.items > .item .meta * { + margin-right: 0.3em; +} + +.ui.items > .item .meta :last-child { + margin-right: 0em; +} + +.ui.items > .item .meta [class*="right floated"] { + margin-right: 0em; + margin-left: 0.3em; +} + +/*-------------- + Links +---------------*/ + +/* Generic */ + +.ui.items > .item > .content a:not(.ui) { + color: ''; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.items > .item > .content a:not(.ui):hover { + color: ''; +} + +/* Header */ + +.ui.items > .item > .content > a.header { + color: rgba(0, 0, 0, 0.85); +} + +.ui.items > .item > .content > a.header:hover { + color: #1e70bf; +} + +/* Meta */ + +.ui.items > .item .meta > a:not(.ui) { + color: rgba(0, 0, 0, 0.4); +} + +.ui.items > .item .meta > a:not(.ui):hover { + color: rgba(0, 0, 0, 0.87); +} + +/*-------------- + Labels +---------------*/ + +/*-----Star----- */ + +/* Icon */ + +.ui.items > .item > .content .favorite.icon { + cursor: pointer; + opacity: 0.75; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.items > .item > .content .favorite.icon:hover { + opacity: 1; + color: #FFB70A; +} + +.ui.items > .item > .content .active.favorite.icon { + color: #FFE623; +} + +/*-----Like----- */ + +/* Icon */ + +.ui.items > .item > .content .like.icon { + cursor: pointer; + opacity: 0.75; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +.ui.items > .item > .content .like.icon:hover { + opacity: 1; + color: #FF2733; +} + +.ui.items > .item > .content .active.like.icon { + color: #FF2733; +} + +/*---------------- + Extra Content +-----------------*/ + +.ui.items > .item .extra { + display: block; + position: relative; + background: none; + margin: 0.5rem 0em 0em; + width: 100%; + padding: 0em 0em 0em; + top: 0em; + left: 0em; + color: rgba(0, 0, 0, 0.4); + box-shadow: none; + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; + border-top: none; +} + +.ui.items > .item .extra > * { + margin: 0.25rem 0.5rem 0.25rem 0em; +} + +.ui.items > .item .extra > [class*="right floated"] { + margin: 0.25rem 0em 0.25rem 0.5rem; +} + +.ui.items > .item .extra:after { + display: block; + content: ' '; + height: 0px; + clear: both; + overflow: hidden; + visibility: hidden; +} + +/******************************* + Responsive +*******************************/ + +/* Default Image Width */ + +.ui.items > .item > .image:not(.ui) { + width: 175px; +} + +/* Tablet Only */ + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .ui.items > .item { + margin: 1em 0em; + } + + .ui.items > .item > .image:not(.ui) { + width: 150px; + } + + .ui.items > .item > .image + .content { + display: block; + padding: 0em 0em 0em 1em; + } +} + +/* Mobile Only */ + +@media only screen and (max-width: 767px) { + .ui.items:not(.unstackable) > .item { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + margin: 2em 0em; + } + + .ui.items:not(.unstackable) > .item > .image { + display: block; + margin-left: auto; + margin-right: auto; + } + + .ui.items:not(.unstackable) > .item > .image, + .ui.items:not(.unstackable) > .item > .image > img { + max-width: 100% !important; + width: auto !important; + max-height: 250px !important; + } + + .ui.items:not(.unstackable) > .item > .image + .content { + display: block; + padding: 1.5em 0em 0em; + } +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Aligned +--------------------*/ + +.ui.items > .item > .image + [class*="top aligned"].content { + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; +} + +.ui.items > .item > .image + [class*="middle aligned"].content { + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; +} + +.ui.items > .item > .image + [class*="bottom aligned"].content { + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; +} + +/*-------------- + Relaxed +---------------*/ + +.ui.relaxed.items > .item { + margin: 1.5em 0em; +} + +.ui[class*="very relaxed"].items > .item { + margin: 2em 0em; +} + +/*------------------- + Divided +--------------------*/ + +.ui.divided.items > .item { + border-top: 1px solid rgba(34, 36, 38, 0.15); + margin: 0em; + padding: 1em 0em; +} + +.ui.divided.items > .item:first-child { + border-top: none; + margin-top: 0em !important; + padding-top: 0em !important; +} + +.ui.divided.items > .item:last-child { + margin-bottom: 0em !important; + padding-bottom: 0em !important; +} + +/* Relaxed Divided */ + +.ui.relaxed.divided.items > .item { + margin: 0em; + padding: 1.5em 0em; +} + +.ui[class*="very relaxed"].divided.items > .item { + margin: 0em; + padding: 2em 0em; +} + +/*------------------- + Link +--------------------*/ + +.ui.items a.item:hover, +.ui.link.items > .item:hover { + cursor: pointer; +} + +.ui.items a.item:hover .content .header, +.ui.link.items > .item:hover .content .header { + color: #1e70bf; +} + +/*-------------- + Size +---------------*/ + +.ui.items > .item { + font-size: 1em; +} + +/*--------------- + Unstackable +----------------*/ + +@media only screen and (max-width: 767px) { + .ui.unstackable.items > .item > .image, + .ui.unstackable.items > .item > .image > img { + width: 125px !important; + } +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Statistic + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Statistic +*******************************/ + +/* Standalone */ + +.ui.statistic { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + margin: 1em 0em; + max-width: auto; +} + +.ui.statistic + .ui.statistic { + margin: 0em 0em 0em 1.5em; +} + +.ui.statistic:first-child { + margin-top: 0em; +} + +.ui.statistic:last-child { + margin-bottom: 0em; +} + +/******************************* + Group +*******************************/ + +/* Grouped */ + +.ui.statistics { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -webkit-align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.ui.statistics > .statistic { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + margin: 0em 1.5em 2em; + max-width: auto; +} + +.ui.statistics { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin: 1em -1.5em -2em; +} + +/* Clearing */ + +.ui.statistics:after { + display: block; + content: ' '; + height: 0px; + clear: both; + overflow: hidden; + visibility: hidden; +} + +.ui.statistics:first-child { + margin-top: 0em; +} + +.ui.statistics:last-child { + margin-bottom: 0em; +} + +/******************************* + Content +*******************************/ + +/*-------------- + Value +---------------*/ + +.ui.statistics .statistic > .value, +.ui.statistic > .value { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 4rem; + font-weight: normal; + line-height: 1em; + color: #1B1C1D; + text-transform: uppercase; + text-align: center; +} + +/*-------------- + Label +---------------*/ + +.ui.statistics .statistic > .label, +.ui.statistic > .label { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 1em; + font-weight: bold; + color: rgba(0, 0, 0, 0.87); + text-transform: uppercase; + text-align: center; +} + +/* Top Label */ + +.ui.statistics .statistic > .label ~ .value, +.ui.statistic > .label ~ .value { + margin-top: 0rem; +} + +/* Bottom Label */ + +.ui.statistics .statistic > .value ~ .label, +.ui.statistic > .value ~ .label { + margin-top: 0rem; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Icon Value +---------------*/ + +.ui.statistics .statistic > .value .icon, +.ui.statistic > .value .icon { + opacity: 1; + width: auto; + margin: 0em; +} + +/*-------------- + Text Value +---------------*/ + +.ui.statistics .statistic > .text.value, +.ui.statistic > .text.value { + line-height: 1em; + min-height: 2em; + font-weight: bold; + text-align: center; +} + +.ui.statistics .statistic > .text.value + .label, +.ui.statistic > .text.value + .label { + text-align: center; +} + +/*-------------- + Image Value +---------------*/ + +.ui.statistics .statistic > .value img, +.ui.statistic > .value img { + max-height: 3rem; + vertical-align: baseline; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Count +---------------*/ + +.ui.ten.statistics { + margin: 0em 0em -2em; +} + +.ui.ten.statistics .statistic { + min-width: 10%; + margin: 0em 0em 2em; +} + +.ui.nine.statistics { + margin: 0em 0em -2em; +} + +.ui.nine.statistics .statistic { + min-width: 11.11111111%; + margin: 0em 0em 2em; +} + +.ui.eight.statistics { + margin: 0em 0em -2em; +} + +.ui.eight.statistics .statistic { + min-width: 12.5%; + margin: 0em 0em 2em; +} + +.ui.seven.statistics { + margin: 0em 0em -2em; +} + +.ui.seven.statistics .statistic { + min-width: 14.28571429%; + margin: 0em 0em 2em; +} + +.ui.six.statistics { + margin: 0em 0em -2em; +} + +.ui.six.statistics .statistic { + min-width: 16.66666667%; + margin: 0em 0em 2em; +} + +.ui.five.statistics { + margin: 0em 0em -2em; +} + +.ui.five.statistics .statistic { + min-width: 20%; + margin: 0em 0em 2em; +} + +.ui.four.statistics { + margin: 0em 0em -2em; +} + +.ui.four.statistics .statistic { + min-width: 25%; + margin: 0em 0em 2em; +} + +.ui.three.statistics { + margin: 0em 0em -2em; +} + +.ui.three.statistics .statistic { + min-width: 33.33333333%; + margin: 0em 0em 2em; +} + +.ui.two.statistics { + margin: 0em 0em -2em; +} + +.ui.two.statistics .statistic { + min-width: 50%; + margin: 0em 0em 2em; +} + +.ui.one.statistics { + margin: 0em 0em -2em; +} + +.ui.one.statistics .statistic { + min-width: 100%; + margin: 0em 0em 2em; +} + +/*-------------- + Horizontal +---------------*/ + +.ui.horizontal.statistic { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + -ms-grid-row-align: center; + align-items: center; +} + +.ui.horizontal.statistics { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + margin: 0em; + max-width: none; +} + +.ui.horizontal.statistics .statistic { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + -ms-grid-row-align: center; + align-items: center; + max-width: none; + margin: 1em 0em; +} + +.ui.horizontal.statistic > .text.value, +.ui.horizontal.statistics > .statistic > .text.value { + min-height: 0em !important; +} + +.ui.horizontal.statistics .statistic > .value .icon, +.ui.horizontal.statistic > .value .icon { + width: 1.18em; +} + +.ui.horizontal.statistics .statistic > .value, +.ui.horizontal.statistic > .value { + display: inline-block; + vertical-align: middle; +} + +.ui.horizontal.statistics .statistic > .label, +.ui.horizontal.statistic > .label { + display: inline-block; + vertical-align: middle; + margin: 0em 0em 0em 0.75em; +} + +/*-------------- + Colors +---------------*/ + +.ui.red.statistics .statistic > .value, +.ui.statistics .red.statistic > .value, +.ui.red.statistic > .value { + color: #DB2828; +} + +.ui.orange.statistics .statistic > .value, +.ui.statistics .orange.statistic > .value, +.ui.orange.statistic > .value { + color: #F2711C; +} + +.ui.yellow.statistics .statistic > .value, +.ui.statistics .yellow.statistic > .value, +.ui.yellow.statistic > .value { + color: #FBBD08; +} + +.ui.olive.statistics .statistic > .value, +.ui.statistics .olive.statistic > .value, +.ui.olive.statistic > .value { + color: #B5CC18; +} + +.ui.green.statistics .statistic > .value, +.ui.statistics .green.statistic > .value, +.ui.green.statistic > .value { + color: #21BA45; +} + +.ui.teal.statistics .statistic > .value, +.ui.statistics .teal.statistic > .value, +.ui.teal.statistic > .value { + color: #00B5AD; +} + +.ui.blue.statistics .statistic > .value, +.ui.statistics .blue.statistic > .value, +.ui.blue.statistic > .value { + color: #2185D0; +} + +.ui.violet.statistics .statistic > .value, +.ui.statistics .violet.statistic > .value, +.ui.violet.statistic > .value { + color: #6435C9; +} + +.ui.purple.statistics .statistic > .value, +.ui.statistics .purple.statistic > .value, +.ui.purple.statistic > .value { + color: #A333C8; +} + +.ui.pink.statistics .statistic > .value, +.ui.statistics .pink.statistic > .value, +.ui.pink.statistic > .value { + color: #E03997; +} + +.ui.brown.statistics .statistic > .value, +.ui.statistics .brown.statistic > .value, +.ui.brown.statistic > .value { + color: #A5673F; +} + +.ui.grey.statistics .statistic > .value, +.ui.statistics .grey.statistic > .value, +.ui.grey.statistic > .value { + color: #767676; +} + +/*-------------- + Inverted +---------------*/ + +.ui.inverted.statistics .statistic > .value, +.ui.inverted.statistic .value { + color: #FFFFFF; +} + +.ui.inverted.statistics .statistic > .label, +.ui.inverted.statistic .label { + color: rgba(255, 255, 255, 0.9); +} + +.ui.inverted.red.statistics .statistic > .value, +.ui.statistics .inverted.red.statistic > .value, +.ui.inverted.red.statistic > .value { + color: #FF695E; +} + +.ui.inverted.orange.statistics .statistic > .value, +.ui.statistics .inverted.orange.statistic > .value, +.ui.inverted.orange.statistic > .value { + color: #FF851B; +} + +.ui.inverted.yellow.statistics .statistic > .value, +.ui.statistics .inverted.yellow.statistic > .value, +.ui.inverted.yellow.statistic > .value { + color: #FFE21F; +} + +.ui.inverted.olive.statistics .statistic > .value, +.ui.statistics .inverted.olive.statistic > .value, +.ui.inverted.olive.statistic > .value { + color: #D9E778; +} + +.ui.inverted.green.statistics .statistic > .value, +.ui.statistics .inverted.green.statistic > .value, +.ui.inverted.green.statistic > .value { + color: #2ECC40; +} + +.ui.inverted.teal.statistics .statistic > .value, +.ui.statistics .inverted.teal.statistic > .value, +.ui.inverted.teal.statistic > .value { + color: #6DFFFF; +} + +.ui.inverted.blue.statistics .statistic > .value, +.ui.statistics .inverted.blue.statistic > .value, +.ui.inverted.blue.statistic > .value { + color: #54C8FF; +} + +.ui.inverted.violet.statistics .statistic > .value, +.ui.statistics .inverted.violet.statistic > .value, +.ui.inverted.violet.statistic > .value { + color: #A291FB; +} + +.ui.inverted.purple.statistics .statistic > .value, +.ui.statistics .inverted.purple.statistic > .value, +.ui.inverted.purple.statistic > .value { + color: #DC73FF; +} + +.ui.inverted.pink.statistics .statistic > .value, +.ui.statistics .inverted.pink.statistic > .value, +.ui.inverted.pink.statistic > .value { + color: #FF8EDF; +} + +.ui.inverted.brown.statistics .statistic > .value, +.ui.statistics .inverted.brown.statistic > .value, +.ui.inverted.brown.statistic > .value { + color: #D67C1C; +} + +.ui.inverted.grey.statistics .statistic > .value, +.ui.statistics .inverted.grey.statistic > .value, +.ui.inverted.grey.statistic > .value { + color: #DCDDDE; +} + +/*-------------- + Floated +---------------*/ + +.ui[class*="left floated"].statistic { + float: left; + margin: 0em 2em 1em 0em; +} + +.ui[class*="right floated"].statistic { + float: right; + margin: 0em 0em 1em 2em; +} + +.ui.floated.statistic:last-child { + margin-bottom: 0em; +} + +/*-------------- + Sizes +---------------*/ + +/* Mini */ + +.ui.mini.statistics .statistic > .value, +.ui.mini.statistic > .value { + font-size: 1.5rem !important; +} + +.ui.mini.horizontal.statistics .statistic > .value, +.ui.mini.horizontal.statistic > .value { + font-size: 1.5rem !important; +} + +.ui.mini.statistics .statistic > .text.value, +.ui.mini.statistic > .text.value { + font-size: 1rem !important; +} + +/* Tiny */ + +.ui.tiny.statistics .statistic > .value, +.ui.tiny.statistic > .value { + font-size: 2rem !important; +} + +.ui.tiny.horizontal.statistics .statistic > .value, +.ui.tiny.horizontal.statistic > .value { + font-size: 2rem !important; +} + +.ui.tiny.statistics .statistic > .text.value, +.ui.tiny.statistic > .text.value { + font-size: 1rem !important; +} + +/* Small */ + +.ui.small.statistics .statistic > .value, +.ui.small.statistic > .value { + font-size: 3rem !important; +} + +.ui.small.horizontal.statistics .statistic > .value, +.ui.small.horizontal.statistic > .value { + font-size: 2rem !important; +} + +.ui.small.statistics .statistic > .text.value, +.ui.small.statistic > .text.value { + font-size: 1rem !important; +} + +/* Medium */ + +.ui.statistics .statistic > .value, +.ui.statistic > .value { + font-size: 4rem !important; +} + +.ui.horizontal.statistics .statistic > .value, +.ui.horizontal.statistic > .value { + font-size: 3rem !important; +} + +.ui.statistics .statistic > .text.value, +.ui.statistic > .text.value { + font-size: 2rem !important; +} + +/* Large */ + +.ui.large.statistics .statistic > .value, +.ui.large.statistic > .value { + font-size: 5rem !important; +} + +.ui.large.horizontal.statistics .statistic > .value, +.ui.large.horizontal.statistic > .value { + font-size: 4rem !important; +} + +.ui.large.statistics .statistic > .text.value, +.ui.large.statistic > .text.value { + font-size: 2.5rem !important; +} + +/* Huge */ + +.ui.huge.statistics .statistic > .value, +.ui.huge.statistic > .value { + font-size: 6rem !important; +} + +.ui.huge.horizontal.statistics .statistic > .value, +.ui.huge.horizontal.statistic > .value { + font-size: 5rem !important; +} + +.ui.huge.statistics .statistic > .text.value, +.ui.huge.statistic > .text.value { + font-size: 2.5rem !important; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Variable Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Accordion + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Accordion +*******************************/ + +.ui.accordion, +.ui.accordion .accordion { + max-width: 100%; +} + +.ui.accordion .accordion { + margin: 1em 0em 0em; + padding: 0em; +} + +/* Title */ + +.ui.accordion .title, +.ui.accordion .accordion .title { + cursor: pointer; +} + +/* Default Styling */ + +.ui.accordion .title:not(.ui) { + padding: 0.5em 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 1em; + color: rgba(0, 0, 0, 0.87); +} + +/* Content */ + +.ui.accordion .title ~ .content, +.ui.accordion .accordion .title ~ .content { + display: none; +} + +/* Default Styling */ + +.ui.accordion:not(.styled) .title ~ .content:not(.ui), +.ui.accordion:not(.styled) .accordion .title ~ .content:not(.ui) { + margin: ''; + padding: 0.5em 0em 1em; +} + +.ui.accordion:not(.styled) .title ~ .content:not(.ui):last-child { + padding-bottom: 0em; +} + +/* Arrow */ + +.ui.accordion .title .dropdown.icon, +.ui.accordion .accordion .title .dropdown.icon { + display: inline-block; + float: none; + opacity: 1; + width: 1.25em; + height: 1em; + margin: 0em 0.25rem 0em 0rem; + padding: 0em; + font-size: 1em; + -webkit-transition: opacity 0.1s ease, -webkit-transform 0.1s ease; + transition: opacity 0.1s ease, -webkit-transform 0.1s ease; + transition: transform 0.1s ease, opacity 0.1s ease; + transition: transform 0.1s ease, opacity 0.1s ease, -webkit-transform 0.1s ease; + vertical-align: baseline; + -webkit-transform: none; + transform: none; +} + +/*-------------- + Coupling +---------------*/ + +/* Menu */ + +.ui.accordion.menu .item .title { + display: block; + padding: 0em; +} + +.ui.accordion.menu .item .title > .dropdown.icon { + float: right; + margin: 0.21425em 0em 0em 1em; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} + +/* Header */ + +.ui.accordion .ui.header .dropdown.icon { + font-size: 1em; + margin: 0em 0.25rem 0em 0rem; +} + +/******************************* + States +*******************************/ + +.ui.accordion .active.title .dropdown.icon, +.ui.accordion .accordion .active.title .dropdown.icon { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} + +.ui.accordion.menu .item .active.title > .dropdown.icon { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} + +/******************************* + Types +*******************************/ + +/*-------------- + Styled +---------------*/ + +.ui.styled.accordion { + width: 600px; +} + +.ui.styled.accordion, +.ui.styled.accordion .accordion { + border-radius: 0.28571429rem; + background: #FFFFFF; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), 0px 0px 0px 1px rgba(34, 36, 38, 0.15); +} + +.ui.styled.accordion .title, +.ui.styled.accordion .accordion .title { + margin: 0em; + padding: 0.75em 1em; + color: rgba(0, 0, 0, 0.4); + font-weight: bold; + border-top: 1px solid rgba(34, 36, 38, 0.15); + -webkit-transition: background 0.1s ease, color 0.1s ease; + transition: background 0.1s ease, color 0.1s ease; +} + +.ui.styled.accordion > .title:first-child, +.ui.styled.accordion .accordion .title:first-child { + border-top: none; +} + +/* Content */ + +.ui.styled.accordion .content, +.ui.styled.accordion .accordion .content { + margin: 0em; + padding: 0.5em 1em 1.5em; +} + +.ui.styled.accordion .accordion .content { + padding: 0em; + padding: 0.5em 1em 1.5em; +} + +/* Hover */ + +.ui.styled.accordion .title:hover, +.ui.styled.accordion .active.title, +.ui.styled.accordion .accordion .title:hover, +.ui.styled.accordion .accordion .active.title { + background: transparent; + color: rgba(0, 0, 0, 0.87); +} + +.ui.styled.accordion .accordion .title:hover, +.ui.styled.accordion .accordion .active.title { + background: transparent; + color: rgba(0, 0, 0, 0.87); +} + +/* Active */ + +.ui.styled.accordion .active.title { + background: transparent; + color: rgba(0, 0, 0, 0.95); +} + +.ui.styled.accordion .accordion .active.title { + background: transparent; + color: rgba(0, 0, 0, 0.95); +} + +/******************************* + States +*******************************/ + +/*-------------- + Active +---------------*/ + +.ui.accordion .active.content, +.ui.accordion .accordion .active.content { + display: block; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Fluid +---------------*/ + +.ui.fluid.accordion, +.ui.fluid.accordion .accordion { + width: 100%; +} + +/*-------------- + Inverted +---------------*/ + +.ui.inverted.accordion .title:not(.ui) { + color: rgba(255, 255, 255, 0.9); +} + +/******************************* + Theme Overrides +*******************************/ + +@font-face { + font-family: 'Accordion'; + src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggjB5AAAAC8AAAAYGNtYXAPfOIKAAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zryj6HgAAAFwAAAAyGhlYWT/0IhHAAACOAAAADZoaGVhApkB5wAAAnAAAAAkaG10eAJuABIAAAKUAAAAGGxvY2EAjABWAAACrAAAAA5tYXhwAAgAFgAAArwAAAAgbmFtZfC1n04AAALcAAABPHBvc3QAAwAAAAAEGAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADw2gHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIPDa//3//wAAAAAAIPDZ//3//wAB/+MPKwADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQASAEkAtwFuABMAADc0PwE2FzYXFh0BFAcGJwYvASY1EgaABQgHBQYGBQcIBYAG2wcGfwcBAQcECf8IBAcBAQd/BgYAAAAAAQAAAEkApQFuABMAADcRNDc2MzIfARYVFA8BBiMiJyY1AAUGBwgFgAYGgAUIBwYFWwEACAUGBoAFCAcFgAYGBQcAAAABAAAAAQAAqWYls18PPPUACwIAAAAAAM/9o+4AAAAAz/2j7gAAAAAAtwFuAAAACAACAAAAAAAAAAEAAAHg/+AAAAIAAAAAAAC3AAEAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAQAAAAC3ABIAtwAAAAAAAAAKABQAHgBCAGQAAAABAAAABgAUAAEAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADAAAAAEAAAAAAAIADgBAAAEAAAAAAAMADAAiAAEAAAAAAAQADABOAAEAAAAAAAUAFgAMAAEAAAAAAAYABgAuAAEAAAAAAAoANABaAAMAAQQJAAEADAAAAAMAAQQJAAIADgBAAAMAAQQJAAMADAAiAAMAAQQJAAQADABOAAMAAQQJAAUAFgAMAAMAAQQJAAYADAA0AAMAAQQJAAoANABaAHIAYQB0AGkAbgBnAFYAZQByAHMAaQBvAG4AIAAxAC4AMAByAGEAdABpAG4AZ3JhdGluZwByAGEAdABpAG4AZwBSAGUAZwB1AGwAYQByAHIAYQB0AGkAbgBnAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAASwAAoAAAAABGgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAAAS0AAAEtFpovuE9TLzIAAAIkAAAAYAAAAGAIIweQY21hcAAAAoQAAABMAAAATA984gpnYXNwAAAC0AAAAAgAAAAIAAAAEGhlYWQAAALYAAAANgAAADb/0IhHaGhlYQAAAxAAAAAkAAAAJAKZAedobXR4AAADNAAAABgAAAAYAm4AEm1heHAAAANMAAAABgAAAAYABlAAbmFtZQAAA1QAAAE8AAABPPC1n05wb3N0AAAEkAAAACAAAAAgAAMAAAEABAQAAQEBB3JhdGluZwABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeLa/iU+HQFHQAAAHkPHQAAAH4RHQAAAAkdAAABJBIABwEBBw0PERQZHnJhdGluZ3JhdGluZ3UwdTF1MjB1RjBEOXVGMERBAAACAYkABAAGAQEEBwoNVp38lA78lA78lA77lA773Z33bxWLkI2Qj44I9xT3FAWOj5CNkIuQi4+JjoePiI2Gi4YIi/uUBYuGiYeHiIiHh4mGi4aLho2Ijwj7FPcUBYeOiY+LkAgO+92L5hWL95QFi5CNkI6Oj4+PjZCLkIuQiY6HCPcU+xQFj4iNhouGi4aJh4eICPsU+xQFiIeGiYaLhouHjYePiI6Jj4uQCA74lBT4lBWLDAoAAAAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADw2gHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIPDa//3//wAAAAAAIPDZ//3//wAB/+MPKwADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAEAADfYOJZfDzz1AAsCAAAAAADP/aPuAAAAAM/9o+4AAAAAALcBbgAAAAgAAgAAAAAAAAABAAAB4P/gAAACAAAAAAAAtwABAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAEAAAAAtwASALcAAAAAUAAABgAAAAAADgCuAAEAAAAAAAEADAAAAAEAAAAAAAIADgBAAAEAAAAAAAMADAAiAAEAAAAAAAQADABOAAEAAAAAAAUAFgAMAAEAAAAAAAYABgAuAAEAAAAAAAoANABaAAMAAQQJAAEADAAAAAMAAQQJAAIADgBAAAMAAQQJAAMADAAiAAMAAQQJAAQADABOAAMAAQQJAAUAFgAMAAMAAQQJAAYADAA0AAMAAQQJAAoANABaAHIAYQB0AGkAbgBnAFYAZQByAHMAaQBvAG4AIAAxAC4AMAByAGEAdABpAG4AZ3JhdGluZwByAGEAdABpAG4AZwBSAGUAZwB1AGwAYQByAHIAYQB0AGkAbgBnAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('woff'); + font-weight: normal; + font-style: normal; +} + +/* Dropdown Icon */ + +.ui.accordion .title .dropdown.icon, +.ui.accordion .accordion .title .dropdown.icon { + font-family: Accordion; + line-height: 1; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + font-weight: normal; + font-style: normal; + text-align: center; +} + +.ui.accordion .title .dropdown.icon:before, +.ui.accordion .accordion .title .dropdown.icon:before { + content: '\f0da' ; +} + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Checkbox + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Checkbox +*******************************/ + +/*-------------- + Content +---------------*/ + +.ui.checkbox { + position: relative; + display: inline-block; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + outline: none; + vertical-align: baseline; + font-style: normal; + min-height: 17px; + font-size: 1rem; + line-height: 17px; + min-width: 17px; +} + +/* HTML Checkbox */ + +.ui.checkbox input[type="checkbox"], +.ui.checkbox input[type="radio"] { + cursor: pointer; + position: absolute; + top: 0px; + left: 0px; + opacity: 0 !important; + outline: none; + z-index: 3; + width: 17px; + height: 17px; +} + +/*-------------- + Box +---------------*/ + +.ui.checkbox .box, +.ui.checkbox label { + cursor: auto; + position: relative; + display: block; + padding-left: 1.85714em; + outline: none; + font-size: 1em; +} + +.ui.checkbox .box:before, +.ui.checkbox label:before { + position: absolute; + top: 0px; + left: 0px; + width: 17px; + height: 17px; + content: ''; + background: #FFFFFF; + border-radius: 0.21428571rem; + -webkit-transition: border 0.1s ease, opacity 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease; + transition: border 0.1s ease, opacity 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease; + transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease; + transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease; + border: 1px solid #D4D4D5; +} + +/*-------------- + Checkmark +---------------*/ + +.ui.checkbox .box:after, +.ui.checkbox label:after { + position: absolute; + font-size: 14px; + top: 0px; + left: 0px; + width: 17px; + height: 17px; + text-align: center; + opacity: 0; + color: rgba(0, 0, 0, 0.87); + -webkit-transition: border 0.1s ease, opacity 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease; + transition: border 0.1s ease, opacity 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease; + transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease; + transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease; +} + +/*-------------- + Label +---------------*/ + +/* Inside */ + +.ui.checkbox label, +.ui.checkbox + label { + color: rgba(0, 0, 0, 0.87); + -webkit-transition: color 0.1s ease; + transition: color 0.1s ease; +} + +/* Outside */ + +.ui.checkbox + label { + vertical-align: middle; +} + +/******************************* + States +*******************************/ + +/*-------------- + Hover +---------------*/ + +.ui.checkbox .box:hover::before, +.ui.checkbox label:hover::before { + background: #FFFFFF; + border-color: rgba(34, 36, 38, 0.35); +} + +.ui.checkbox label:hover, +.ui.checkbox + label:hover { + color: rgba(0, 0, 0, 0.8); +} + +/*-------------- + Down +---------------*/ + +.ui.checkbox .box:active::before, +.ui.checkbox label:active::before { + background: #F9FAFB; + border-color: rgba(34, 36, 38, 0.35); +} + +.ui.checkbox .box:active::after, +.ui.checkbox label:active::after { + color: rgba(0, 0, 0, 0.95); +} + +.ui.checkbox input:active ~ label { + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Focus +---------------*/ + +.ui.checkbox input:focus ~ .box:before, +.ui.checkbox input:focus ~ label:before { + background: #FFFFFF; + border-color: #96C8DA; +} + +.ui.checkbox input:focus ~ .box:after, +.ui.checkbox input:focus ~ label:after { + color: rgba(0, 0, 0, 0.95); +} + +.ui.checkbox input:focus ~ label { + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Active +---------------*/ + +.ui.checkbox input:checked ~ .box:before, +.ui.checkbox input:checked ~ label:before { + background: #FFFFFF; + border-color: rgba(34, 36, 38, 0.35); +} + +.ui.checkbox input:checked ~ .box:after, +.ui.checkbox input:checked ~ label:after { + opacity: 1; + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Indeterminate +---------------*/ + +.ui.checkbox input:not([type=radio]):indeterminate ~ .box:before, +.ui.checkbox input:not([type=radio]):indeterminate ~ label:before { + background: #FFFFFF; + border-color: rgba(34, 36, 38, 0.35); +} + +.ui.checkbox input:not([type=radio]):indeterminate ~ .box:after, +.ui.checkbox input:not([type=radio]):indeterminate ~ label:after { + opacity: 1; + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Active Focus +---------------*/ + +.ui.checkbox input:not([type=radio]):indeterminate:focus ~ .box:before, +.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:before, +.ui.checkbox input:checked:focus ~ .box:before, +.ui.checkbox input:checked:focus ~ label:before { + background: #FFFFFF; + border-color: #96C8DA; +} + +.ui.checkbox input:not([type=radio]):indeterminate:focus ~ .box:after, +.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:after, +.ui.checkbox input:checked:focus ~ .box:after, +.ui.checkbox input:checked:focus ~ label:after { + color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Read-Only +---------------*/ + +.ui.read-only.checkbox, +.ui.read-only.checkbox label { + cursor: default; +} + +/*-------------- + Disabled +---------------*/ + +.ui.disabled.checkbox .box:after, +.ui.disabled.checkbox label, +.ui.checkbox input[disabled] ~ .box:after, +.ui.checkbox input[disabled] ~ label { + cursor: default !important; + opacity: 0.5; + color: #000000; +} + +/*-------------- + Hidden +---------------*/ + +/* Initialized checkbox moves input below element + to prevent manually triggering */ + +.ui.checkbox input.hidden { + z-index: -1; +} + +/* Selectable Label */ + +.ui.checkbox input.hidden + label { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Radio +---------------*/ + +.ui.radio.checkbox { + min-height: 15px; +} + +.ui.radio.checkbox .box, +.ui.radio.checkbox label { + padding-left: 1.85714em; +} + +/* Box */ + +.ui.radio.checkbox .box:before, +.ui.radio.checkbox label:before { + content: ''; + -webkit-transform: none; + transform: none; + width: 15px; + height: 15px; + border-radius: 500rem; + top: 1px; + left: 0px; +} + +/* Bullet */ + +.ui.radio.checkbox .box:after, +.ui.radio.checkbox label:after { + border: none; + content: '' !important; + width: 15px; + height: 15px; + line-height: 15px; +} + +/* Radio Checkbox */ + +.ui.radio.checkbox .box:after, +.ui.radio.checkbox label:after { + top: 1px; + left: 0px; + width: 15px; + height: 15px; + border-radius: 500rem; + -webkit-transform: scale(0.46666667); + transform: scale(0.46666667); + background-color: rgba(0, 0, 0, 0.87); +} + +/* Focus */ + +.ui.radio.checkbox input:focus ~ .box:before, +.ui.radio.checkbox input:focus ~ label:before { + background-color: #FFFFFF; +} + +.ui.radio.checkbox input:focus ~ .box:after, +.ui.radio.checkbox input:focus ~ label:after { + background-color: rgba(0, 0, 0, 0.95); +} + +/* Indeterminate */ + +.ui.radio.checkbox input:indeterminate ~ .box:after, +.ui.radio.checkbox input:indeterminate ~ label:after { + opacity: 0; +} + +/* Active */ + +.ui.radio.checkbox input:checked ~ .box:before, +.ui.radio.checkbox input:checked ~ label:before { + background-color: #FFFFFF; +} + +.ui.radio.checkbox input:checked ~ .box:after, +.ui.radio.checkbox input:checked ~ label:after { + background-color: rgba(0, 0, 0, 0.95); +} + +/* Active Focus */ + +.ui.radio.checkbox input:focus:checked ~ .box:before, +.ui.radio.checkbox input:focus:checked ~ label:before { + background-color: #FFFFFF; +} + +.ui.radio.checkbox input:focus:checked ~ .box:after, +.ui.radio.checkbox input:focus:checked ~ label:after { + background-color: rgba(0, 0, 0, 0.95); +} + +/*-------------- + Slider +---------------*/ + +.ui.slider.checkbox { + min-height: 1.25rem; +} + +/* Input */ + +.ui.slider.checkbox input { + width: 3.5rem; + height: 1.25rem; +} + +/* Label */ + +.ui.slider.checkbox .box, +.ui.slider.checkbox label { + padding-left: 4.5rem; + line-height: 1rem; + color: rgba(0, 0, 0, 0.4); +} + +/* Line */ + +.ui.slider.checkbox .box:before, +.ui.slider.checkbox label:before { + display: block; + position: absolute; + content: ''; + border: none !important; + left: 0em; + z-index: 1; + top: 0.4rem; + background-color: rgba(0, 0, 0, 0.05); + width: 3.5rem; + height: 0.21428571rem; + -webkit-transform: none; + transform: none; + border-radius: 500rem; + -webkit-transition: background 0.3s ease; + transition: background 0.3s ease; +} + +/* Handle */ + +.ui.slider.checkbox .box:after, +.ui.slider.checkbox label:after { + background: #FFFFFF -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + position: absolute; + content: '' !important; + opacity: 1; + z-index: 2; + border: none; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset; + width: 1.5rem; + height: 1.5rem; + top: -0.25rem; + left: 0em; + -webkit-transform: none; + transform: none; + border-radius: 500rem; + -webkit-transition: left 0.3s ease; + transition: left 0.3s ease; +} + +/* Focus */ + +.ui.slider.checkbox input:focus ~ .box:before, +.ui.slider.checkbox input:focus ~ label:before { + background-color: rgba(0, 0, 0, 0.15); + border: none; +} + +/* Hover */ + +.ui.slider.checkbox .box:hover, +.ui.slider.checkbox label:hover { + color: rgba(0, 0, 0, 0.8); +} + +.ui.slider.checkbox .box:hover::before, +.ui.slider.checkbox label:hover::before { + background: rgba(0, 0, 0, 0.15); +} + +/* Active */ + +.ui.slider.checkbox input:checked ~ .box, +.ui.slider.checkbox input:checked ~ label { + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.slider.checkbox input:checked ~ .box:before, +.ui.slider.checkbox input:checked ~ label:before { + background-color: #545454 !important; +} + +.ui.slider.checkbox input:checked ~ .box:after, +.ui.slider.checkbox input:checked ~ label:after { + left: 2rem; +} + +/* Active Focus */ + +.ui.slider.checkbox input:focus:checked ~ .box, +.ui.slider.checkbox input:focus:checked ~ label { + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.slider.checkbox input:focus:checked ~ .box:before, +.ui.slider.checkbox input:focus:checked ~ label:before { + background-color: #000000 !important; +} + +/*-------------- + Toggle +---------------*/ + +.ui.toggle.checkbox { + min-height: 1.5rem; +} + +/* Input */ + +.ui.toggle.checkbox input { + width: 3.5rem; + height: 1.5rem; +} + +/* Label */ + +.ui.toggle.checkbox .box, +.ui.toggle.checkbox label { + min-height: 1.5rem; + padding-left: 4.5rem; + color: rgba(0, 0, 0, 0.87); +} + +.ui.toggle.checkbox label { + padding-top: 0.15em; +} + +/* Switch */ + +.ui.toggle.checkbox .box:before, +.ui.toggle.checkbox label:before { + display: block; + position: absolute; + content: ''; + z-index: 1; + -webkit-transform: none; + transform: none; + border: none; + top: 0rem; + background: rgba(0, 0, 0, 0.05); + box-shadow: none; + width: 3.5rem; + height: 1.5rem; + border-radius: 500rem; +} + +/* Handle */ + +.ui.toggle.checkbox .box:after, +.ui.toggle.checkbox label:after { + background: #FFFFFF -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05)); + position: absolute; + content: '' !important; + opacity: 1; + z-index: 2; + border: none; + box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset; + width: 1.5rem; + height: 1.5rem; + top: 0rem; + left: 0em; + border-radius: 500rem; + -webkit-transition: background 0.3s ease, left 0.3s ease; + transition: background 0.3s ease, left 0.3s ease; +} + +.ui.toggle.checkbox input ~ .box:after, +.ui.toggle.checkbox input ~ label:after { + left: -0.05rem; + box-shadow: none; +} + +/* Focus */ + +.ui.toggle.checkbox input:focus ~ .box:before, +.ui.toggle.checkbox input:focus ~ label:before { + background-color: rgba(0, 0, 0, 0.15); + border: none; +} + +/* Hover */ + +.ui.toggle.checkbox .box:hover::before, +.ui.toggle.checkbox label:hover::before { + background-color: rgba(0, 0, 0, 0.15); + border: none; +} + +/* Active */ + +.ui.toggle.checkbox input:checked ~ .box, +.ui.toggle.checkbox input:checked ~ label { + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.toggle.checkbox input:checked ~ .box:before, +.ui.toggle.checkbox input:checked ~ label:before { + background-color: #2185D0 !important; +} + +.ui.toggle.checkbox input:checked ~ .box:after, +.ui.toggle.checkbox input:checked ~ label:after { + left: 2.15rem; + box-shadow: none; +} + +/* Active Focus */ + +.ui.toggle.checkbox input:focus:checked ~ .box, +.ui.toggle.checkbox input:focus:checked ~ label { + color: rgba(0, 0, 0, 0.95) !important; +} + +.ui.toggle.checkbox input:focus:checked ~ .box:before, +.ui.toggle.checkbox input:focus:checked ~ label:before { + background-color: #0d71bb !important; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Fitted +---------------*/ + +.ui.fitted.checkbox .box, +.ui.fitted.checkbox label { + padding-left: 0em !important; +} + +.ui.fitted.toggle.checkbox, +.ui.fitted.toggle.checkbox { + width: 3.5rem; +} + +.ui.fitted.slider.checkbox, +.ui.fitted.slider.checkbox { + width: 3.5rem; +} + +/******************************* + Theme Overrides +*******************************/ + +@font-face { + font-family: 'Checkbox'; + src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBD8AAAC8AAAAYGNtYXAYVtCJAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zn4huwUAAAF4AAABYGhlYWQGPe1ZAAAC2AAAADZoaGVhB30DyAAAAxAAAAAkaG10eBBKAEUAAAM0AAAAHGxvY2EAmgESAAADUAAAABBtYXhwAAkALwAAA2AAAAAgbmFtZSC8IugAAAOAAAABknBvc3QAAwAAAAAFFAAAACAAAwMTAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADoAgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6AL//f//AAAAAAAg6AD//f//AAH/4xgEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAEUAUQO7AvgAGgAAARQHAQYjIicBJjU0PwE2MzIfAQE2MzIfARYVA7sQ/hQQFhcQ/uMQEE4QFxcQqAF2EBcXEE4QAnMWEP4UEBABHRAXFhBOEBCoAXcQEE4QFwAAAAABAAABbgMlAkkAFAAAARUUBwYjISInJj0BNDc2MyEyFxYVAyUQEBf9SRcQEBAQFwK3FxAQAhJtFxAQEBAXbRcQEBAQFwAAAAABAAAASQMlA24ALAAAARUUBwYrARUUBwYrASInJj0BIyInJj0BNDc2OwE1NDc2OwEyFxYdATMyFxYVAyUQEBfuEBAXbhYQEO4XEBAQEBfuEBAWbhcQEO4XEBACEm0XEBDuFxAQEBAX7hAQF20XEBDuFxAQEBAX7hAQFwAAAQAAAAIAAHRSzT9fDzz1AAsEAAAAAADRsdR3AAAAANGx1HcAAAAAA7sDbgAAAAgAAgAAAAAAAAABAAADwP/AAAAEAAAAAAADuwABAAAAAAAAAAAAAAAAAAAABwQAAAAAAAAAAAAAAAIAAAAEAABFAyUAAAMlAAAAAAAAAAoAFAAeAE4AcgCwAAEAAAAHAC0AAQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAIAAAAAQAAAAAAAgAHAGkAAQAAAAAAAwAIADkAAQAAAAAABAAIAH4AAQAAAAAABQALABgAAQAAAAAABgAIAFEAAQAAAAAACgAaAJYAAwABBAkAAQAQAAgAAwABBAkAAgAOAHAAAwABBAkAAwAQAEEAAwABBAkABAAQAIYAAwABBAkABQAWACMAAwABBAkABgAQAFkAAwABBAkACgA0ALBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhWZXJzaW9uIDIuMABWAGUAcgBzAGkAbwBuACAAMgAuADBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhDaGVja2JveABDAGgAZQBjAGsAYgBvAHhSZWd1bGFyAFIAZQBnAHUAbABhAHJDaGVja2JveABDAGgAZQBjAGsAYgBvAHhGb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype'); +} + +/* Checkmark */ + +.ui.checkbox label:after, +.ui.checkbox .box:after { + font-family: 'Checkbox'; +} + +/* Checked */ + +.ui.checkbox input:checked ~ .box:after, +.ui.checkbox input:checked ~ label:after { + content: '\e800'; +} + +/* Indeterminate */ + +.ui.checkbox input:indeterminate ~ .box:after, +.ui.checkbox input:indeterminate ~ label:after { + font-size: 12px; + content: '\e801'; +} + +/* UTF Reference +.check:before { content: '\e800'; } +.dash:before { content: '\e801'; } +.plus:before { content: '\e802'; } +*/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Dimmer + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Dimmer +*******************************/ + +.dimmable:not(.body) { + position: relative; +} + +.ui.dimmer { + display: none; + position: absolute; + top: 0em !important; + left: 0em !important; + width: 100%; + height: 100%; + text-align: center; + vertical-align: middle; + background-color: rgba(0, 0, 0, 0.85); + opacity: 0; + line-height: 1; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; + -webkit-transition: background-color 0.5s linear; + transition: background-color 0.5s linear; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + will-change: opacity; + z-index: 1000; +} + +/* Dimmer Content */ + +.ui.dimmer > .content { + width: 100%; + height: 100%; + display: table; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.ui.dimmer > .content > * { + display: table-cell; + vertical-align: middle; + color: #FFFFFF; +} + +/* Loose Coupling */ + +.ui.segment > .ui.dimmer { + border-radius: inherit !important; +} + +/******************************* + States +*******************************/ + +.animating.dimmable:not(body), +.dimmed.dimmable:not(body) { + overflow: hidden; +} + +.dimmed.dimmable > .ui.animating.dimmer, +.dimmed.dimmable > .ui.visible.dimmer, +.ui.active.dimmer { + display: block; + opacity: 1; +} + +.ui.disabled.dimmer { + width: 0 !important; + height: 0 !important; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Page +---------------*/ + +.ui.page.dimmer { + position: fixed; + -webkit-transform-style: ''; + transform-style: ''; + -webkit-perspective: 2000px; + perspective: 2000px; + -webkit-transform-origin: center center; + transform-origin: center center; +} + +body.animating.in.dimmable, +body.dimmed.dimmable { + overflow: hidden; +} + +body.dimmable > .dimmer { + position: fixed; +} + +/*-------------- + Blurring +---------------*/ + +.blurring.dimmable > :not(.dimmer) { + -webkit-filter: blur(0px) grayscale(0); + filter: blur(0px) grayscale(0); + -webkit-transition: 800ms filter ease; + transition: 800ms filter ease; +} + +.blurring.dimmed.dimmable > :not(.dimmer) { + -webkit-filter: blur(5px) grayscale(0.7); + filter: blur(5px) grayscale(0.7); +} + +/* Dimmer Color */ + +.blurring.dimmable > .dimmer { + background-color: rgba(0, 0, 0, 0.6); +} + +.blurring.dimmable > .inverted.dimmer { + background-color: rgba(255, 255, 255, 0.6); +} + +/*-------------- + Aligned +---------------*/ + +.ui.dimmer > .top.aligned.content > * { + vertical-align: top; +} + +.ui.dimmer > .bottom.aligned.content > * { + vertical-align: bottom; +} + +/*-------------- + Inverted +---------------*/ + +.ui.inverted.dimmer { + background-color: rgba(255, 255, 255, 0.85); +} + +.ui.inverted.dimmer > .content > * { + color: #FFFFFF; +} + +/*-------------- + Simple +---------------*/ + +/* Displays without javascript */ + +.ui.simple.dimmer { + display: block; + overflow: hidden; + opacity: 1; + width: 0%; + height: 0%; + z-index: -100; + background-color: rgba(0, 0, 0, 0); +} + +.dimmed.dimmable > .ui.simple.dimmer { + overflow: visible; + opacity: 1; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.85); + z-index: 1; +} + +.ui.simple.inverted.dimmer { + background-color: rgba(255, 255, 255, 0); +} + +.dimmed.dimmable > .ui.simple.inverted.dimmer { + background-color: rgba(255, 255, 255, 0.85); +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Dropdown + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Dropdown +*******************************/ + +.ui.dropdown { + cursor: pointer; + position: relative; + display: inline-block; + outline: none; + text-align: left; + -webkit-transition: box-shadow 0.1s ease, width 0.1s ease; + transition: box-shadow 0.1s ease, width 0.1s ease; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +/******************************* + Content +*******************************/ + +/*-------------- + Menu +---------------*/ + +.ui.dropdown .menu { + cursor: auto; + position: absolute; + display: none; + outline: none; + top: 100%; + min-width: -webkit-max-content; + min-width: -moz-max-content; + min-width: max-content; + margin: 0em; + padding: 0em 0em; + background: #FFFFFF; + font-size: 1em; + text-shadow: none; + text-align: left; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); + border: 1px solid rgba(34, 36, 38, 0.15); + border-radius: 0.28571429rem; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; + z-index: 11; + will-change: transform, opacity; +} + +.ui.dropdown .menu > * { + white-space: nowrap; +} + +/*-------------- + Hidden Input +---------------*/ + +.ui.dropdown > input:not(.search):first-child, +.ui.dropdown > select { + display: none !important; +} + +/*-------------- + Dropdown Icon +---------------*/ + +.ui.dropdown > .dropdown.icon { + position: relative; + width: auto; + font-size: 0.85714286em; + margin: 0em 0em 0em 1em; +} + +.ui.dropdown .menu > .item .dropdown.icon { + width: auto; + float: right; + margin: 0em 0em 0em 1em; +} + +.ui.dropdown .menu > .item .dropdown.icon + .text { + margin-right: 1em; +} + +/*-------------- + Text +---------------*/ + +.ui.dropdown > .text { + display: inline-block; + -webkit-transition: none; + transition: none; +} + +/*-------------- + Menu Item +---------------*/ + +.ui.dropdown .menu > .item { + position: relative; + cursor: pointer; + display: block; + border: none; + height: auto; + text-align: left; + border-top: none; + line-height: 1em; + color: rgba(0, 0, 0, 0.87); + padding: 0.78571429rem 1.14285714rem !important; + font-size: 1rem; + text-transform: none; + font-weight: normal; + box-shadow: none; + -webkit-touch-callout: none; +} + +.ui.dropdown .menu > .item:first-child { + border-top-width: 0px; +} + +/*-------------- + Floated Content +---------------*/ + +.ui.dropdown > .text > [class*="right floated"], +.ui.dropdown .menu .item > [class*="right floated"] { + float: right !important; + margin-right: 0em !important; + margin-left: 1em !important; +} + +.ui.dropdown > .text > [class*="left floated"], +.ui.dropdown .menu .item > [class*="left floated"] { + float: left !important; + margin-left: 0em !important; + margin-right: 1em !important; +} + +.ui.dropdown .menu .item > .icon.floated, +.ui.dropdown .menu .item > .flag.floated, +.ui.dropdown .menu .item > .image.floated, +.ui.dropdown .menu .item > img.floated { + margin-top: 0em; +} + +/*-------------- + Menu Divider +---------------*/ + +.ui.dropdown .menu > .header { + margin: 1rem 0rem 0.75rem; + padding: 0em 1.14285714rem; + color: rgba(0, 0, 0, 0.85); + font-size: 0.78571429em; + font-weight: bold; + text-transform: uppercase; +} + +.ui.dropdown .menu > .divider { + border-top: 1px solid rgba(34, 36, 38, 0.1); + height: 0em; + margin: 0.5em 0em; +} + +.ui.dropdown .menu > .input { + width: auto; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + margin: 1.14285714rem 0.78571429rem; + min-width: 10rem; +} + +.ui.dropdown .menu > .header + .input { + margin-top: 0em; +} + +.ui.dropdown .menu > .input:not(.transparent) input { + padding: 0.5em 1em; +} + +.ui.dropdown .menu > .input:not(.transparent) .button, +.ui.dropdown .menu > .input:not(.transparent) .icon, +.ui.dropdown .menu > .input:not(.transparent) .label { + padding-top: 0.5em; + padding-bottom: 0.5em; +} + +/*----------------- + Item Description +-------------------*/ + +.ui.dropdown > .text > .description, +.ui.dropdown .menu > .item > .description { + float: right; + margin: 0em 0em 0em 1em; + color: rgba(0, 0, 0, 0.4); +} + +/*----------------- + Message +-------------------*/ + +.ui.dropdown .menu > .message { + padding: 0.78571429rem 1.14285714rem; + font-weight: normal; +} + +.ui.dropdown .menu > .message:not(.ui) { + color: rgba(0, 0, 0, 0.4); +} + +/*-------------- + Sub Menu +---------------*/ + +.ui.dropdown .menu .menu { + top: 0% !important; + left: 100% !important; + right: auto !important; + margin: 0em 0em 0em -0.5em !important; + border-radius: 0.28571429rem !important; + z-index: 21 !important; +} + +/* Hide Arrow */ + +.ui.dropdown .menu .menu:after { + display: none; +} + +/*-------------- + Sub Elements +---------------*/ + +/* Icons / Flags / Labels / Image */ + +.ui.dropdown > .text > .icon, +.ui.dropdown > .text > .label, +.ui.dropdown > .text > .flag, +.ui.dropdown > .text > img, +.ui.dropdown > .text > .image { + margin-top: 0em; +} + +.ui.dropdown .menu > .item > .icon, +.ui.dropdown .menu > .item > .label, +.ui.dropdown .menu > .item > .flag, +.ui.dropdown .menu > .item > .image, +.ui.dropdown .menu > .item > img { + margin-top: 0em; +} + +.ui.dropdown > .text > .icon, +.ui.dropdown > .text > .label, +.ui.dropdown > .text > .flag, +.ui.dropdown > .text > img, +.ui.dropdown > .text > .image, +.ui.dropdown .menu > .item > .icon, +.ui.dropdown .menu > .item > .label, +.ui.dropdown .menu > .item > .flag, +.ui.dropdown .menu > .item > .image, +.ui.dropdown .menu > .item > img { + margin-left: 0em; + float: none; + margin-right: 0.78571429rem; +} + +/*-------------- + Image +---------------*/ + +.ui.dropdown > .text > img, +.ui.dropdown > .text > .image, +.ui.dropdown .menu > .item > .image, +.ui.dropdown .menu > .item > img { + display: inline-block; + vertical-align: middle; + width: auto; + max-height: 2em; +} + +/******************************* + Coupling +*******************************/ + +/*-------------- + Menu +---------------*/ + +/* Remove Menu Item Divider */ + +.ui.dropdown .ui.menu > .item:before, +.ui.menu .ui.dropdown .menu > .item:before { + display: none; +} + +/* Prevent Menu Item Border */ + +.ui.menu .ui.dropdown .menu .active.item { + border-left: none; +} + +/* Automatically float dropdown menu right on last menu item */ + +.ui.menu .right.menu .dropdown:last-child .menu, +.ui.menu .right.dropdown.item .menu, +.ui.buttons > .ui.dropdown:last-child .menu { + left: auto; + right: 0em; +} + +/*-------------- + Label +---------------*/ + +/* Dropdown Menu */ + +.ui.label.dropdown .menu { + min-width: 100%; +} + +/*-------------- + Button +---------------*/ + +/* No Margin On Icon Button */ + +.ui.dropdown.icon.button > .dropdown.icon { + margin: 0em; +} + +.ui.button.dropdown .menu { + min-width: 100%; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Selection +---------------*/ + +/* Displays like a select box */ + +.ui.selection.dropdown { + cursor: pointer; + word-wrap: break-word; + line-height: 1em; + white-space: normal; + outline: 0; + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + min-width: 14em; + min-height: 2.71428571em; + background: #FFFFFF; + display: inline-block; + padding: 0.78571429em 2.1em 0.78571429em 1em; + color: rgba(0, 0, 0, 0.87); + box-shadow: none; + border: 1px solid rgba(34, 36, 38, 0.15); + border-radius: 0.28571429rem; + -webkit-transition: box-shadow 0.1s ease, width 0.1s ease; + transition: box-shadow 0.1s ease, width 0.1s ease; +} + +.ui.selection.dropdown.visible, +.ui.selection.dropdown.active { + z-index: 10; +} + +select.ui.dropdown { + height: 38px; + padding: 0.5em; + border: 1px solid rgba(34, 36, 38, 0.15); + visibility: visible; +} + +.ui.selection.dropdown > .search.icon, +.ui.selection.dropdown > .delete.icon, +.ui.selection.dropdown > .dropdown.icon { + cursor: pointer; + position: absolute; + width: auto; + height: auto; + line-height: 1.21428571em; + top: 0.78571429em; + right: 1em; + z-index: 3; + margin: -0.78571429em; + padding: 0.78571429em; + opacity: 0.8; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; +} + +/* Compact */ + +.ui.compact.selection.dropdown { + min-width: 0px; +} + +/* Selection Menu */ + +.ui.selection.dropdown .menu { + overflow-x: hidden; + overflow-y: auto; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-overflow-scrolling: touch; + border-top-width: 0px !important; + width: auto; + outline: none; + margin: 0px -1px; + min-width: calc(100% + 2px ); + width: calc(100% + 2px ); + border-radius: 0em 0em 0.28571429rem 0.28571429rem; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; +} + +.ui.selection.dropdown .menu:after, +.ui.selection.dropdown .menu:before { + display: none; +} + +/*-------------- + Message +---------------*/ + +.ui.selection.dropdown .menu > .message { + padding: 0.78571429rem 1.14285714rem; +} + +@media only screen and (max-width: 767px) { + .ui.selection.dropdown .menu { + max-height: 8.01428571rem; + } +} + +@media only screen and (min-width: 768px) { + .ui.selection.dropdown .menu { + max-height: 10.68571429rem; + } +} + +@media only screen and (min-width: 992px) { + .ui.selection.dropdown .menu { + max-height: 16.02857143rem; + } +} + +@media only screen and (min-width: 1920px) { + .ui.selection.dropdown .menu { + max-height: 21.37142857rem; + } +} + +/* Menu Item */ + +.ui.selection.dropdown .menu > .item { + border-top: 1px solid #FAFAFA; + padding: 0.78571429rem 1.14285714rem !important; + white-space: normal; + word-wrap: normal; +} + +/* User Item */ + +.ui.selection.dropdown .menu > .hidden.addition.item { + display: none; +} + +/* Hover */ + +.ui.selection.dropdown:hover { + border-color: rgba(34, 36, 38, 0.35); + box-shadow: none; +} + +/* Active */ + +.ui.selection.active.dropdown { + border-color: #96C8DA; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); +} + +.ui.selection.active.dropdown .menu { + border-color: #96C8DA; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); +} + +/* Focus */ + +.ui.selection.dropdown:focus { + border-color: #96C8DA; + box-shadow: none; +} + +.ui.selection.dropdown:focus .menu { + border-color: #96C8DA; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); +} + +/* Visible */ + +.ui.selection.visible.dropdown > .text:not(.default) { + font-weight: normal; + color: rgba(0, 0, 0, 0.8); +} + +/* Visible Hover */ + +.ui.selection.active.dropdown:hover { + border-color: #96C8DA; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); +} + +.ui.selection.active.dropdown:hover .menu { + border-color: #96C8DA; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); +} + +/* Dropdown Icon */ + +.ui.active.selection.dropdown > .dropdown.icon, +.ui.visible.selection.dropdown > .dropdown.icon { + opacity: 1; + z-index: 3; +} + +/* Connecting Border */ + +.ui.active.selection.dropdown { + border-bottom-left-radius: 0em !important; + border-bottom-right-radius: 0em !important; +} + +/* Empty Connecting Border */ + +.ui.active.empty.selection.dropdown { + border-radius: 0.28571429rem !important; + box-shadow: none !important; +} + +.ui.active.empty.selection.dropdown .menu { + border: none !important; + box-shadow: none !important; +} + +/*-------------- + Searchable +---------------*/ + +/* Search Selection */ + +.ui.search.dropdown { + min-width: ''; +} + +/* Search Dropdown */ + +.ui.search.dropdown > input.search { + background: none transparent !important; + border: none !important; + box-shadow: none !important; + cursor: text; + top: 0em; + left: 1px; + width: 100%; + outline: none; + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); + padding: inherit; +} + +/* Text Layering */ + +.ui.search.dropdown > input.search { + position: absolute; + z-index: 2; +} + +.ui.search.dropdown > .text { + cursor: text; + position: relative; + left: 1px; + z-index: 3; +} + +/* Search Selection */ + +.ui.search.selection.dropdown > input.search { + line-height: 1.21428571em; + padding: 0.67857143em 2.1em 0.67857143em 1em; +} + +/* Used to size multi select input to character width */ + +.ui.search.selection.dropdown > span.sizer { + line-height: 1.21428571em; + padding: 0.67857143em 2.1em 0.67857143em 1em; + display: none; + white-space: pre; +} + +/* Active/Visible Search */ + +.ui.search.dropdown.active > input.search, +.ui.search.dropdown.visible > input.search { + cursor: auto; +} + +.ui.search.dropdown.active > .text, +.ui.search.dropdown.visible > .text { + pointer-events: none; +} + +/* Filtered Text */ + +.ui.active.search.dropdown input.search:focus + .text .icon, +.ui.active.search.dropdown input.search:focus + .text .flag { + opacity: 0.45; +} + +.ui.active.search.dropdown input.search:focus + .text { + color: rgba(115, 115, 115, 0.87) !important; +} + +/* Search Menu */ + +.ui.search.dropdown .menu { + overflow-x: hidden; + overflow-y: auto; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-overflow-scrolling: touch; +} + +@media only screen and (max-width: 767px) { + .ui.search.dropdown .menu { + max-height: 8.01428571rem; + } +} + +@media only screen and (min-width: 768px) { + .ui.search.dropdown .menu { + max-height: 10.68571429rem; + } +} + +@media only screen and (min-width: 992px) { + .ui.search.dropdown .menu { + max-height: 16.02857143rem; + } +} + +@media only screen and (min-width: 1920px) { + .ui.search.dropdown .menu { + max-height: 21.37142857rem; + } +} + +/*-------------- + Multiple +---------------*/ + +/* Multiple Selection */ + +.ui.multiple.dropdown { + padding: 0.22619048em 2.1em 0.22619048em 0.35714286em; +} + +.ui.multiple.dropdown .menu { + cursor: auto; +} + +/* Multiple Search Selection */ + +.ui.multiple.search.dropdown, +.ui.multiple.search.dropdown > input.search { + cursor: text; +} + +/* Selection Label */ + +.ui.multiple.dropdown > .label { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: inline-block; + vertical-align: top; + white-space: normal; + font-size: 1em; + padding: 0.35714286em 0.78571429em; + margin: 0.14285714rem 0.28571429rem 0.14285714rem 0em; + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset; +} + +/* Dropdown Icon */ + +.ui.multiple.dropdown .dropdown.icon { + margin: ''; + padding: ''; +} + +/* Text */ + +.ui.multiple.dropdown > .text { + position: static; + padding: 0; + max-width: 100%; + margin: 0.45238095em 0em 0.45238095em 0.64285714em; + line-height: 1.21428571em; +} + +.ui.multiple.dropdown > .label ~ input.search { + margin-left: 0.14285714em !important; +} + +.ui.multiple.dropdown > .label ~ .text { + display: none; +} + +/*----------------- + Multiple Search +-----------------*/ + +/* Prompt Text */ + +.ui.multiple.search.dropdown > .text { + display: inline-block; + position: absolute; + top: 0; + left: 0; + padding: inherit; + margin: 0.45238095em 0em 0.45238095em 0.64285714em; + line-height: 1.21428571em; +} + +.ui.multiple.search.dropdown > .label ~ .text { + display: none; +} + +/* Search */ + +.ui.multiple.search.dropdown > input.search { + position: static; + padding: 0; + max-width: 100%; + margin: 0.45238095em 0em 0.45238095em 0.64285714em; + width: 2.2em; + line-height: 1.21428571em; +} + +/*-------------- + Inline +---------------*/ + +.ui.inline.dropdown { + cursor: pointer; + display: inline-block; + color: inherit; +} + +.ui.inline.dropdown .dropdown.icon { + margin: 0em 0.5em 0em 0.21428571em; + vertical-align: baseline; +} + +.ui.inline.dropdown > .text { + font-weight: bold; +} + +.ui.inline.dropdown .menu { + cursor: auto; + margin-top: 0.21428571em; + border-radius: 0.28571429rem; +} + +/******************************* + States +*******************************/ + +/*-------------------- + Active +----------------------*/ + +/* Menu Item Active */ + +.ui.dropdown .menu .active.item { + background: transparent; + font-weight: bold; + color: rgba(0, 0, 0, 0.95); + box-shadow: none; + z-index: 12; +} + +/*-------------------- + Hover +----------------------*/ + +/* Menu Item Hover */ + +.ui.dropdown .menu > .item:hover { + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.95); + z-index: 13; +} + +/*-------------------- + Loading +---------------------*/ + +.ui.loading.dropdown > i.icon { + height: 1em !important; + padding: 1.14285714em 1.07142857em !important; +} + +.ui.loading.dropdown > i.icon:before { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.1); +} + +.ui.loading.dropdown > i.icon:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + box-shadow: 0px 0px 0px 1px transparent; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + -webkit-animation: dropdown-spin 0.6s linear; + animation: dropdown-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 transparent transparent; + border-style: solid; + border-width: 0.2em; +} + +/* Coupling */ + +.ui.loading.dropdown.button > i.icon:before, +.ui.loading.dropdown.button > i.icon:after { + display: none; +} + +@-webkit-keyframes dropdown-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes dropdown-spin { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/*-------------------- + Default Text +----------------------*/ + +.ui.dropdown:not(.button) > .default.text, +.ui.default.dropdown:not(.button) > .text { + color: rgba(191, 191, 191, 0.87); +} + +.ui.dropdown:not(.button) > input:focus + .default.text, +.ui.default.dropdown:not(.button) > input:focus + .text { + color: rgba(115, 115, 115, 0.87); +} + +/*-------------------- + Loading +----------------------*/ + +.ui.loading.dropdown > .text { + -webkit-transition: none; + transition: none; +} + +/* Used To Check Position */ + +.ui.dropdown .loading.menu { + display: block; + visibility: hidden; + z-index: -1; +} + +/*-------------------- + Keyboard Select +----------------------*/ + +/* Selected Item */ + +.ui.dropdown.selected, +.ui.dropdown .menu .selected.item { + background: rgba(0, 0, 0, 0.03); + color: rgba(0, 0, 0, 0.95); +} + +/*-------------------- + Search Filtered +----------------------*/ + +/* Filtered Item */ + +.ui.dropdown > .filtered.text { + visibility: hidden; +} + +.ui.dropdown .filtered.item { + display: none !important; +} + +/*-------------------- + Error +----------------------*/ + +.ui.dropdown.error, +.ui.dropdown.error > .text, +.ui.dropdown.error > .default.text { + color: #9F3A38; +} + +.ui.selection.dropdown.error { + background: #FFF6F6; + border-color: #E0B4B4; +} + +.ui.selection.dropdown.error:hover { + border-color: #E0B4B4; +} + +.ui.dropdown.error > .menu, +.ui.dropdown.error > .menu .menu { + border-color: #E0B4B4; +} + +.ui.dropdown.error > .menu > .item { + color: #9F3A38; +} + +.ui.multiple.selection.error.dropdown > .label { + border-color: #E0B4B4; +} + +/* Item Hover */ + +.ui.dropdown.error > .menu > .item:hover { + background-color: #FFF2F2; +} + +/* Item Active */ + +.ui.dropdown.error > .menu .active.item { + background-color: #FDCFCF; +} + +/*-------------------- + Disabled +----------------------*/ + +/* Disabled */ + +.ui.disabled.dropdown, +.ui.dropdown .menu > .disabled.item { + cursor: default; + pointer-events: none; + opacity: 0.45; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Direction +---------------*/ + +/* Flyout Direction */ + +.ui.dropdown .menu { + left: 0px; +} + +/* Default Side (Right) */ + +.ui.dropdown .right.menu > .menu, +.ui.dropdown .menu .right.menu { + left: 100% !important; + right: auto !important; + border-radius: 0.28571429rem !important; +} + +/* Left Flyout Menu */ + +.ui.dropdown > .left.menu .menu, +.ui.dropdown .menu .left.menu { + left: auto !important; + right: 100% !important; + border-radius: 0.28571429rem !important; +} + +.ui.dropdown .item .left.dropdown.icon, +.ui.dropdown .left.menu .item .dropdown.icon { + width: auto; + float: left; + margin: 0em 0.78571429rem 0em 0em; +} + +.ui.dropdown .item .left.dropdown.icon, +.ui.dropdown .left.menu .item .dropdown.icon { + width: auto; + float: left; + margin: 0em 0.78571429rem 0em 0em; +} + +.ui.dropdown .item .left.dropdown.icon + .text, +.ui.dropdown .left.menu .item .dropdown.icon + .text { + margin-left: 1em; +} + +/*-------------- + Upward +---------------*/ + +/* Upward Main Menu */ + +.ui.upward.dropdown > .menu { + top: auto; + bottom: 100%; + box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.08); + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +/* Upward Sub Menu */ + +.ui.dropdown .upward.menu { + top: auto !important; + bottom: 0 !important; +} + +/* Active Upward */ + +.ui.simple.upward.active.dropdown, +.ui.simple.upward.dropdown:hover { + border-radius: 0.28571429rem 0.28571429rem 0em 0em !important; +} + +.ui.upward.dropdown.button:not(.pointing):not(.floating).active { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +/* Selection */ + +.ui.upward.selection.dropdown .menu { + border-top-width: 1px !important; + border-bottom-width: 0px !important; + box-shadow: 0px -2px 3px 0px rgba(0, 0, 0, 0.08); +} + +.ui.upward.selection.dropdown:hover { + box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.05); +} + +/* Active Upward */ + +.ui.active.upward.selection.dropdown { + border-radius: 0em 0em 0.28571429rem 0.28571429rem !important; +} + +/* Visible Upward */ + +.ui.upward.selection.dropdown.visible { + box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.08); + border-radius: 0em 0em 0.28571429rem 0.28571429rem !important; +} + +/* Visible Hover Upward */ + +.ui.upward.active.selection.dropdown:hover { + box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.05); +} + +.ui.upward.active.selection.dropdown:hover .menu { + box-shadow: 0px -2px 3px 0px rgba(0, 0, 0, 0.08); +} + +/*-------------- + Simple +---------------*/ + +/* Selection Menu */ + +.ui.scrolling.dropdown .menu, +.ui.dropdown .scrolling.menu { + overflow-x: hidden; + overflow-y: auto; +} + +.ui.scrolling.dropdown .menu { + overflow-x: hidden; + overflow-y: auto; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-overflow-scrolling: touch; + min-width: 100% !important; + width: auto !important; +} + +.ui.dropdown .scrolling.menu { + position: static; + overflow-y: auto; + border: none; + box-shadow: none !important; + border-radius: 0 !important; + margin: 0 !important; + min-width: 100% !important; + width: auto !important; + border-top: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.scrolling.dropdown .menu .item.item.item, +.ui.dropdown .scrolling.menu > .item.item.item { + border-top: none; +} + +.ui.scrolling.dropdown .menu .item:first-child, +.ui.dropdown .scrolling.menu .item:first-child { + border-top: none; +} + +.ui.dropdown > .animating.menu .scrolling.menu, +.ui.dropdown > .visible.menu .scrolling.menu { + display: block; +} + +/* Scrollbar in IE */ + +@media all and (-ms-high-contrast: none) { + .ui.scrolling.dropdown .menu, + .ui.dropdown .scrolling.menu { + min-width: calc(100% - 17px ); + } +} + +@media only screen and (max-width: 767px) { + .ui.scrolling.dropdown .menu, + .ui.dropdown .scrolling.menu { + max-height: 10.28571429rem; + } +} + +@media only screen and (min-width: 768px) { + .ui.scrolling.dropdown .menu, + .ui.dropdown .scrolling.menu { + max-height: 15.42857143rem; + } +} + +@media only screen and (min-width: 992px) { + .ui.scrolling.dropdown .menu, + .ui.dropdown .scrolling.menu { + max-height: 20.57142857rem; + } +} + +@media only screen and (min-width: 1920px) { + .ui.scrolling.dropdown .menu, + .ui.dropdown .scrolling.menu { + max-height: 20.57142857rem; + } +} + +/*-------------- + Simple +---------------*/ + +/* Displays without javascript */ + +.ui.simple.dropdown .menu:before, +.ui.simple.dropdown .menu:after { + display: none; +} + +.ui.simple.dropdown .menu { + position: absolute; + display: block; + overflow: hidden; + top: -9999px !important; + opacity: 0; + width: 0; + height: 0; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; +} + +.ui.simple.active.dropdown, +.ui.simple.dropdown:hover { + border-bottom-left-radius: 0em !important; + border-bottom-right-radius: 0em !important; +} + +.ui.simple.active.dropdown > .menu, +.ui.simple.dropdown:hover > .menu { + overflow: visible; + width: auto; + height: auto; + top: 100% !important; + opacity: 1; +} + +.ui.simple.dropdown > .menu > .item:active > .menu, +.ui.simple.dropdown:hover > .menu > .item:hover > .menu { + overflow: visible; + width: auto; + height: auto; + top: 0% !important; + left: 100% !important; + opacity: 1; +} + +.ui.simple.disabled.dropdown:hover .menu { + display: none; + height: 0px; + width: 0px; + overflow: hidden; +} + +/* Visible */ + +.ui.simple.visible.dropdown > .menu { + display: block; +} + +/*-------------- + Fluid +---------------*/ + +.ui.fluid.dropdown { + display: block; + width: 100%; + min-width: 0em; +} + +.ui.fluid.dropdown > .dropdown.icon { + float: right; +} + +/*-------------- + Floating +---------------*/ + +.ui.floating.dropdown .menu { + left: 0; + right: auto; + box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15) !important; + border-radius: 0.28571429rem !important; +} + +.ui.floating.dropdown > .menu { + margin-top: 0.5em !important; + border-radius: 0.28571429rem !important; +} + +/*-------------- + Pointing +---------------*/ + +.ui.pointing.dropdown > .menu { + top: 100%; + margin-top: 0.78571429rem; + border-radius: 0.28571429rem; +} + +.ui.pointing.dropdown > .menu:after { + display: block; + position: absolute; + pointer-events: none; + content: ''; + visibility: visible; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + width: 0.5em; + height: 0.5em; + box-shadow: -1px -1px 0px 1px rgba(34, 36, 38, 0.15); + background: #FFFFFF; + z-index: 2; +} + +.ui.pointing.dropdown > .menu:after { + top: -0.25em; + left: 50%; + margin: 0em 0em 0em -0.25em; +} + +/* Top Left Pointing */ + +.ui.top.left.pointing.dropdown > .menu { + top: 100%; + bottom: auto; + left: 0%; + right: auto; + margin: 1em 0em 0em; +} + +.ui.top.left.pointing.dropdown > .menu { + top: 100%; + bottom: auto; + left: 0%; + right: auto; + margin: 1em 0em 0em; +} + +.ui.top.left.pointing.dropdown > .menu:after { + top: -0.25em; + left: 1em; + right: auto; + margin: 0em; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); +} + +/* Top Right Pointing */ + +.ui.top.right.pointing.dropdown > .menu { + top: 100%; + bottom: auto; + right: 0%; + left: auto; + margin: 1em 0em 0em; +} + +.ui.top.right.pointing.dropdown > .menu:after { + top: -0.25em; + left: auto; + right: 1em; + margin: 0em; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); +} + +/* Left Pointing */ + +.ui.left.pointing.dropdown > .menu { + top: 0%; + left: 100%; + right: auto; + margin: 0em 0em 0em 1em; +} + +.ui.left.pointing.dropdown > .menu:after { + top: 1em; + left: -0.25em; + margin: 0em 0em 0em 0em; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); +} + +/* Right Pointing */ + +.ui.right.pointing.dropdown > .menu { + top: 0%; + left: auto; + right: 100%; + margin: 0em 1em 0em 0em; +} + +.ui.right.pointing.dropdown > .menu:after { + top: 1em; + left: auto; + right: -0.25em; + margin: 0em 0em 0em 0em; + -webkit-transform: rotate(135deg); + transform: rotate(135deg); +} + +/* Bottom Pointing */ + +.ui.bottom.pointing.dropdown > .menu { + top: auto; + bottom: 100%; + left: 0%; + right: auto; + margin: 0em 0em 1em; +} + +.ui.bottom.pointing.dropdown > .menu:after { + top: auto; + bottom: -0.25em; + right: auto; + margin: 0em; + -webkit-transform: rotate(-135deg); + transform: rotate(-135deg); +} + +/* Reverse Sub-Menu Direction */ + +.ui.bottom.pointing.dropdown > .menu .menu { + top: auto !important; + bottom: 0px !important; +} + +/* Bottom Left */ + +.ui.bottom.left.pointing.dropdown > .menu { + left: 0%; + right: auto; +} + +.ui.bottom.left.pointing.dropdown > .menu:after { + left: 1em; + right: auto; +} + +/* Bottom Right */ + +.ui.bottom.right.pointing.dropdown > .menu { + right: 0%; + left: auto; +} + +.ui.bottom.right.pointing.dropdown > .menu:after { + left: auto; + right: 1em; +} + +/* Upward pointing */ + +.ui.upward.pointing.dropdown > .menu, +.ui.upward.top.pointing.dropdown > .menu { + top: auto; + bottom: 100%; + margin: 0em 0em 0.78571429rem; + border-radius: 0.28571429rem; +} + +.ui.upward.pointing.dropdown > .menu:after, +.ui.upward.top.pointing.dropdown > .menu:after { + top: 100%; + bottom: auto; + box-shadow: 1px 1px 0px 1px rgba(34, 36, 38, 0.15); + margin: -0.25em 0em 0em; +} + +/* Right Pointing Upward */ + +.ui.upward.right.pointing.dropdown:not(.top):not(.bottom) > .menu { + top: auto; + bottom: 0; + margin: 0em 1em 0em 0em; +} + +.ui.upward.right.pointing.dropdown:not(.top):not(.bottom) > .menu:after { + top: auto; + bottom: 0; + margin: 0em 0em 1em 0em; + box-shadow: -1px -1px 0px 1px rgba(34, 36, 38, 0.15); +} + +/* Left Pointing Upward */ + +.ui.upward.left.pointing.dropdown:not(.top):not(.bottom) > .menu { + top: auto; + bottom: 0; + margin: 0em 0em 0em 1em; +} + +.ui.upward.left.pointing.dropdown:not(.top):not(.bottom) > .menu:after { + top: auto; + bottom: 0; + margin: 0em 0em 1em 0em; + box-shadow: -1px -1px 0px 1px rgba(34, 36, 38, 0.15); +} + +/******************************* + Theme Overrides +*******************************/ + +/* Dropdown Carets */ + +@font-face { + font-family: 'Dropdown'; + src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggjB5AAAAC8AAAAYGNtYXAPfuIIAAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zjo82LgAAAFwAAABVGhlYWQAQ88bAAACxAAAADZoaGVhAwcB6QAAAvwAAAAkaG10eAS4ABIAAAMgAAAAIGxvY2EBNgDeAAADQAAAABJtYXhwAAoAFgAAA1QAAAAgbmFtZVcZpu4AAAN0AAABRXBvc3QAAwAAAAAEvAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADw2gHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIPDa//3//wAAAAAAIPDX//3//wAB/+MPLQADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAIABJQElABMAABM0NzY3BTYXFhUUDwEGJwYvASY1AAUGBwEACAUGBoAFCAcGgAUBEgcGBQEBAQcECQYHfwYBAQZ/BwYAAQAAAG4BJQESABMAADc0PwE2MzIfARYVFAcGIyEiJyY1AAWABgcIBYAGBgUI/wAHBgWABwaABQWABgcHBgUFBgcAAAABABIASQC3AW4AEwAANzQ/ATYXNhcWHQEUBwYnBi8BJjUSBoAFCAcFBgYFBwgFgAbbBwZ/BwEBBwQJ/wgEBwEBB38GBgAAAAABAAAASQClAW4AEwAANxE0NzYzMh8BFhUUDwEGIyInJjUABQYHCAWABgaABQgHBgVbAQAIBQYGgAUIBwWABgYFBwAAAAEAAAABAADZuaKOXw889QALAgAAAAAA0ABHWAAAAADQAEdYAAAAAAElAW4AAAAIAAIAAAAAAAAAAQAAAeD/4AAAAgAAAAAAASUAAQAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAABAAAAASUAAAElAAAAtwASALcAAAAAAAAACgAUAB4AQgBkAIgAqgAAAAEAAAAIABQAAQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAOAAAAAQAAAAAAAgAOAEcAAQAAAAAAAwAOACQAAQAAAAAABAAOAFUAAQAAAAAABQAWAA4AAQAAAAAABgAHADIAAQAAAAAACgA0AGMAAwABBAkAAQAOAAAAAwABBAkAAgAOAEcAAwABBAkAAwAOACQAAwABBAkABAAOAFUAAwABBAkABQAWAA4AAwABBAkABgAOADkAAwABBAkACgA0AGMAaQBjAG8AbQBvAG8AbgBWAGUAcgBzAGkAbwBuACAAMQAuADAAaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AbgBSAGUAZwB1AGwAYQByAGkAYwBvAG0AbwBvAG4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAAVwAAoAAAAABSgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAAAdkAAAHZLDXE/09TLzIAAALQAAAAYAAAAGAIIweQY21hcAAAAzAAAABMAAAATA9+4ghnYXNwAAADfAAAAAgAAAAIAAAAEGhlYWQAAAOEAAAANgAAADYAQ88baGhlYQAAA7wAAAAkAAAAJAMHAelobXR4AAAD4AAAACAAAAAgBLgAEm1heHAAAAQAAAAABgAAAAYACFAAbmFtZQAABAgAAAFFAAABRVcZpu5wb3N0AAAFUAAAACAAAAAgAAMAAAEABAQAAQEBCGljb21vb24AAQIAAQA6+BwC+BsD+BgEHgoAGVP/i4seCgAZU/+LiwwHi2v4lPh0BR0AAACIDx0AAACNER0AAAAJHQAAAdASAAkBAQgPERMWGyAlKmljb21vb25pY29tb29udTB1MXUyMHVGMEQ3dUYwRDh1RjBEOXVGMERBAAACAYkABgAIAgABAAQABwAKAA0AVgCfAOgBL/yUDvyUDvyUDvuUDvtvi/emFYuQjZCOjo+Pj42Qiwj3lIsFkIuQiY6Hj4iNhouGi4aJh4eHCPsU+xQFiIiGiYaLhouHjYeOCPsU9xQFiI+Jj4uQCA77b4v3FBWLkI2Pjo8I9xT3FAWPjo+NkIuQi5CJjogI9xT7FAWPh42Hi4aLhomHh4eIiIaJhosI+5SLBYaLh42HjoiPiY+LkAgO+92d928Vi5CNkI+OCPcU9xQFjo+QjZCLkIuPiY6Hj4iNhouGCIv7lAWLhomHh4iIh4eJhouGi4aNiI8I+xT3FAWHjomPi5AIDvvdi+YVi/eUBYuQjZCOjo+Pj42Qi5CLkImOhwj3FPsUBY+IjYaLhouGiYeHiAj7FPsUBYiHhomGi4aLh42Hj4iOiY+LkAgO+JQU+JQViwwKAAAAAAMCAAGQAAUAAAFMAWYAAABHAUwBZgAAAPUAGQCEAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA8NoB4P/g/+AB4AAgAAAAAQAAAAAAAAAAAAAAIAAAAAAAAgAAAAMAAAAUAAMAAQAAABQABAA4AAAACgAIAAIAAgABACDw2v/9//8AAAAAACDw1//9//8AAf/jDy0AAwABAAAAAAAAAAAAAAABAAH//wAPAAEAAAABAAA5emozXw889QALAgAAAAAA0ABHWAAAAADQAEdYAAAAAAElAW4AAAAIAAIAAAAAAAAAAQAAAeD/4AAAAgAAAAAAASUAAQAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAABAAAAASUAAAElAAAAtwASALcAAAAAUAAACAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIADgBHAAEAAAAAAAMADgAkAAEAAAAAAAQADgBVAAEAAAAAAAUAFgAOAAEAAAAAAAYABwAyAAEAAAAAAAoANABjAAMAAQQJAAEADgAAAAMAAQQJAAIADgBHAAMAAQQJAAMADgAkAAMAAQQJAAQADgBVAAMAAQQJAAUAFgAOAAMAAQQJAAYADgA5AAMAAQQJAAoANABjAGkAYwBvAG0AbwBvAG4AVgBlAHIAcwBpAG8AbgAgADEALgAwAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG4AUgBlAGcAdQBsAGEAcgBpAGMAbwBtAG8AbwBuAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('woff'); + font-weight: normal; + font-style: normal; +} + +.ui.dropdown > .dropdown.icon { + font-family: 'Dropdown'; + line-height: 1; + height: 1em; + width: 1.23em; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + font-weight: normal; + font-style: normal; + text-align: center; +} + +.ui.dropdown > .dropdown.icon { + width: auto; +} + +.ui.dropdown > .dropdown.icon:before { + content: '\f0d7'; +} + +/* Sub Menu */ + +.ui.dropdown .menu .item .dropdown.icon:before { + content: '\f0da' ; +} + +.ui.dropdown .item .left.dropdown.icon:before, +.ui.dropdown .left.menu .item .dropdown.icon:before { + content: "\f0d9" ; +} + +/* Vertical Menu Dropdown */ + +.ui.vertical.menu .dropdown.item > .dropdown.icon:before { + content: "\f0da" ; +} + +/* Icons for Reference +.dropdown.down.icon { + content: "\f0d7"; +} +.dropdown.up.icon { + content: "\f0d8"; +} +.dropdown.left.icon { + content: "\f0d9"; +} +.dropdown.icon.icon { + content: "\f0da"; +} +*/ + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Video + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Types +*******************************/ + +.ui.embed { + position: relative; + max-width: 100%; + height: 0px; + overflow: hidden; + background: #DCDDDE; + padding-bottom: 56.25%; +} + +/*----------------- + Embedded Content +------------------*/ + +.ui.embed iframe, +.ui.embed embed, +.ui.embed object { + position: absolute; + border: none; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + margin: 0em; + padding: 0em; +} + +/*----------------- + Embed +------------------*/ + +.ui.embed > .embed { + display: none; +} + +/*-------------- + Placeholder +---------------*/ + +.ui.embed > .placeholder { + position: absolute; + cursor: pointer; + top: 0px; + left: 0px; + display: block; + width: 100%; + height: 100%; + background-color: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); +} + +/*-------------- + Icon +---------------*/ + +.ui.embed > .icon { + cursor: pointer; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + z-index: 2; +} + +.ui.embed > .icon:after { + position: absolute; + top: 0%; + left: 0%; + width: 100%; + height: 100%; + z-index: 3; + content: ''; + background: -webkit-radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); + background: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); + opacity: 0.5; + -webkit-transition: opacity 0.5s ease; + transition: opacity 0.5s ease; +} + +.ui.embed > .icon:before { + position: absolute; + top: 50%; + left: 50%; + z-index: 4; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + color: #FFFFFF; + font-size: 6rem; + text-shadow: 0px 2px 10px rgba(34, 36, 38, 0.2); + -webkit-transition: opacity 0.5s ease, color 0.5s ease; + transition: opacity 0.5s ease, color 0.5s ease; + z-index: 10; +} + +/******************************* + States +*******************************/ + +/*-------------- + Hover +---------------*/ + +.ui.embed .icon:hover:after { + background: -webkit-radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); + background: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); + opacity: 1; +} + +.ui.embed .icon:hover:before { + color: #FFFFFF; +} + +/*-------------- + Active +---------------*/ + +.ui.active.embed > .icon, +.ui.active.embed > .placeholder { + display: none; +} + +.ui.active.embed > .embed { + display: block; +} + +/******************************* + Video Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ + +/******************************* + Variations +*******************************/ + +.ui.square.embed { + padding-bottom: 100%; +} + +.ui[class*="4:3"].embed { + padding-bottom: 75%; +} + +.ui[class*="16:9"].embed { + padding-bottom: 56.25%; +} + +.ui[class*="21:9"].embed { + padding-bottom: 42.85714286%; +} +/*! + * # Semantic UI 2.2.10 - Modal + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Modal +*******************************/ + +.ui.modal { + display: none; + position: fixed; + z-index: 1001; + top: 50%; + left: 50%; + text-align: left; + background: #FFFFFF; + border: none; + box-shadow: 1px 3px 3px 0px rgba(0, 0, 0, 0.2), 1px 3px 15px 2px rgba(0, 0, 0, 0.2); + -webkit-transform-origin: 50% 25%; + transform-origin: 50% 25%; + border-radius: 0.28571429rem; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + will-change: top, left, margin, transform, opacity; +} + +.ui.modal > :first-child:not(.icon), +.ui.modal > .icon:first-child + * { + border-top-left-radius: 0.28571429rem; + border-top-right-radius: 0.28571429rem; +} + +.ui.modal > :last-child { + border-bottom-left-radius: 0.28571429rem; + border-bottom-right-radius: 0.28571429rem; +} + +/******************************* + Content +*******************************/ + +/*-------------- + Close +---------------*/ + +.ui.modal > .close { + cursor: pointer; + position: absolute; + top: -2.5rem; + right: -2.5rem; + z-index: 1; + opacity: 0.8; + font-size: 1.25em; + color: #FFFFFF; + width: 2.25rem; + height: 2.25rem; + padding: 0.625rem 0rem 0rem 0rem; +} + +.ui.modal > .close:hover { + opacity: 1; +} + +/*-------------- + Header +---------------*/ + +.ui.modal > .header { + display: block; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + background: #FFFFFF; + margin: 0em; + padding: 1.25rem 1.5rem; + box-shadow: none; + color: rgba(0, 0, 0, 0.85); + border-bottom: 1px solid rgba(34, 36, 38, 0.15); +} + +.ui.modal > .header:not(.ui) { + font-size: 1.42857143rem; + line-height: 1.28571429em; + font-weight: bold; +} + +/*-------------- + Content +---------------*/ + +.ui.modal > .content { + display: block; + width: 100%; + font-size: 1em; + line-height: 1.4; + padding: 1.5rem; + background: #FFFFFF; +} + +.ui.modal > .image.content { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; +} + +/* Image */ + +.ui.modal > .content > .image { + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + width: ''; + -webkit-align-self: top; + -ms-flex-item-align: top; + align-self: top; +} + +.ui.modal > [class*="top aligned"] { + -webkit-align-self: top; + -ms-flex-item-align: top; + align-self: top; +} + +.ui.modal > [class*="middle aligned"] { + -webkit-align-self: middle; + -ms-flex-item-align: middle; + align-self: middle; +} + +.ui.modal > [class*="stretched"] { + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; +} + +/* Description */ + +.ui.modal > .content > .description { + display: block; + -webkit-box-flex: 1; + -webkit-flex: 1 0 auto; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + min-width: 0px; + -webkit-align-self: top; + -ms-flex-item-align: top; + align-self: top; +} + +.ui.modal > .content > .icon + .description, +.ui.modal > .content > .image + .description { + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + min-width: ''; + width: auto; + padding-left: 2em; +} + +/*rtl:ignore*/ + +.ui.modal > .content > .image > i.icon { + margin: 0em; + opacity: 1; + width: auto; + line-height: 1; + font-size: 8rem; +} + +/*-------------- + Actions +---------------*/ + +.ui.modal > .actions { + background: #F9FAFB; + padding: 1rem 1rem; + border-top: 1px solid rgba(34, 36, 38, 0.15); + text-align: right; +} + +.ui.modal .actions > .button { + margin-left: 0.75em; +} + +/*------------------- + Responsive +--------------------*/ + +/* Modal Width */ + +@media only screen and (max-width: 767px) { + .ui.modal { + width: 95%; + margin: 0em 0em 0em -47.5%; + } +} + +@media only screen and (min-width: 768px) { + .ui.modal { + width: 88%; + margin: 0em 0em 0em -44%; + } +} + +@media only screen and (min-width: 992px) { + .ui.modal { + width: 850px; + margin: 0em 0em 0em -425px; + } +} + +@media only screen and (min-width: 1200px) { + .ui.modal { + width: 900px; + margin: 0em 0em 0em -450px; + } +} + +@media only screen and (min-width: 1920px) { + .ui.modal { + width: 950px; + margin: 0em 0em 0em -475px; + } +} + +/* Tablet and Mobile */ + +@media only screen and (max-width: 991px) { + .ui.modal > .header { + padding-right: 2.25rem; + } + + .ui.modal > .close { + top: 1.0535rem; + right: 1rem; + color: rgba(0, 0, 0, 0.87); + } +} + +/* Mobile */ + +@media only screen and (max-width: 767px) { + .ui.modal > .header { + padding: 0.75rem 1rem !important; + padding-right: 2.25rem !important; + } + + .ui.modal > .content { + display: block; + padding: 1rem !important; + } + + .ui.modal > .close { + top: 0.5rem !important; + right: 0.5rem !important; + } + + /*rtl:ignore*/ + + .ui.modal .image.content { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } + + .ui.modal .content > .image { + display: block; + max-width: 100%; + margin: 0em auto !important; + text-align: center; + padding: 0rem 0rem 1rem !important; + } + + .ui.modal > .content > .image > i.icon { + font-size: 5rem; + text-align: center; + } + + /*rtl:ignore*/ + + .ui.modal .content > .description { + display: block; + width: 100% !important; + margin: 0em !important; + padding: 1rem 0rem !important; + box-shadow: none; + } + + /* Let Buttons Stack */ + + .ui.modal > .actions { + padding: 1rem 1rem 0rem !important; + } + + .ui.modal .actions > .buttons, + .ui.modal .actions > .button { + margin-bottom: 1rem; + } +} + +/*-------------- + Coupling +---------------*/ + +.ui.inverted.dimmer > .ui.modal { + box-shadow: 1px 3px 10px 2px rgba(0, 0, 0, 0.2); +} + +/******************************* + Types +*******************************/ + +.ui.basic.modal { + background-color: transparent; + border: none; + border-radius: 0em; + box-shadow: none !important; + color: #FFFFFF; +} + +.ui.basic.modal > .header, +.ui.basic.modal > .content, +.ui.basic.modal > .actions { + background-color: transparent; +} + +.ui.basic.modal > .header { + color: #FFFFFF; +} + +.ui.basic.modal > .close { + top: 1rem; + right: 1.5rem; +} + +.ui.inverted.dimmer > .basic.modal { + color: rgba(0, 0, 0, 0.87); +} + +.ui.inverted.dimmer > .ui.basic.modal > .header { + color: rgba(0, 0, 0, 0.85); +} + +/* Tablet and Mobile */ + +@media only screen and (max-width: 991px) { + .ui.basic.modal > .close { + color: #FFFFFF; + } +} + +/******************************* + States +*******************************/ + +.ui.active.modal { + display: block; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Scrolling +---------------*/ + +/* A modal that cannot fit on the page */ + +.scrolling.dimmable.dimmed { + overflow: hidden; +} + +.scrolling.dimmable.dimmed > .dimmer { + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +.scrolling.dimmable > .dimmer { + position: fixed; +} + +.modals.dimmer .ui.scrolling.modal { + position: static !important; + margin: 3.5rem auto !important; +} + +/* undetached scrolling */ + +.scrolling.undetached.dimmable.dimmed { + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +.scrolling.undetached.dimmable.dimmed > .dimmer { + overflow: hidden; +} + +.scrolling.undetached.dimmable .ui.scrolling.modal { + position: absolute; + left: 50%; + margin-top: 3.5rem !important; +} + +/* Coupling with Sidebar */ + +.undetached.dimmable.dimmed > .pusher { + z-index: auto; +} + +@media only screen and (max-width: 991px) { + .modals.dimmer .ui.scrolling.modal { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } +} + +/*-------------- + Full Screen +---------------*/ + +.ui.fullscreen.modal { + width: 95% !important; + left: 2.5% !important; + margin: 1em auto; +} + +.ui.fullscreen.scrolling.modal { + left: 0em !important; +} + +.ui.fullscreen.modal > .header { + padding-right: 2.25rem; +} + +.ui.fullscreen.modal > .close { + top: 1.0535rem; + right: 1rem; + color: rgba(0, 0, 0, 0.87); +} + +/*-------------- + Size +---------------*/ + +.ui.modal { + font-size: 1rem; +} + +/* Small */ + +.ui.small.modal > .header:not(.ui) { + font-size: 1.3em; +} + +/* Small Modal Width */ + +@media only screen and (max-width: 767px) { + .ui.small.modal { + width: 95%; + margin: 0em 0em 0em -47.5%; + } +} + +@media only screen and (min-width: 768px) { + .ui.small.modal { + width: 70.4%; + margin: 0em 0em 0em -35.2%; + } +} + +@media only screen and (min-width: 992px) { + .ui.small.modal { + width: 680px; + margin: 0em 0em 0em -340px; + } +} + +@media only screen and (min-width: 1200px) { + .ui.small.modal { + width: 720px; + margin: 0em 0em 0em -360px; + } +} + +@media only screen and (min-width: 1920px) { + .ui.small.modal { + width: 760px; + margin: 0em 0em 0em -380px; + } +} + +/* Large Modal Width */ + +.ui.large.modal > .header { + font-size: 1.6em; +} + +@media only screen and (max-width: 767px) { + .ui.large.modal { + width: 95%; + margin: 0em 0em 0em -47.5%; + } +} + +@media only screen and (min-width: 768px) { + .ui.large.modal { + width: 88%; + margin: 0em 0em 0em -44%; + } +} + +@media only screen and (min-width: 992px) { + .ui.large.modal { + width: 1020px; + margin: 0em 0em 0em -510px; + } +} + +@media only screen and (min-width: 1200px) { + .ui.large.modal { + width: 1080px; + margin: 0em 0em 0em -540px; + } +} + +@media only screen and (min-width: 1920px) { + .ui.large.modal { + width: 1140px; + margin: 0em 0em 0em -570px; + } +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Nag + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Nag +*******************************/ + +.ui.nag { + display: none; + opacity: 0.95; + position: relative; + top: 0em; + left: 0px; + z-index: 999; + min-height: 0em; + width: 100%; + margin: 0em; + padding: 0.75em 1em; + background: #555555; + box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.2); + font-size: 1rem; + text-align: center; + color: rgba(0, 0, 0, 0.87); + border-radius: 0em 0em 0.28571429rem 0.28571429rem; + -webkit-transition: 0.2s background ease; + transition: 0.2s background ease; +} + +a.ui.nag { + cursor: pointer; +} + +.ui.nag > .title { + display: inline-block; + margin: 0em 0.5em; + color: #FFFFFF; +} + +.ui.nag > .close.icon { + cursor: pointer; + opacity: 0.4; + position: absolute; + top: 50%; + right: 1em; + font-size: 1em; + margin: -0.5em 0em 0em; + color: #FFFFFF; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; +} + +/******************************* + States +*******************************/ + +/* Hover */ + +.ui.nag:hover { + background: #555555; + opacity: 1; +} + +.ui.nag .close:hover { + opacity: 1; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Static +---------------*/ + +.ui.overlay.nag { + position: absolute; + display: block; +} + +/*-------------- + Fixed +---------------*/ + +.ui.fixed.nag { + position: fixed; +} + +/*-------------- + Bottom +---------------*/ + +.ui.bottom.nags, +.ui.bottom.nag { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; + top: auto; + bottom: 0em; +} + +/*-------------- + White +---------------*/ + +.ui.inverted.nags .nag, +.ui.inverted.nag { + background-color: #F3F4F5; + color: rgba(0, 0, 0, 0.85); +} + +.ui.inverted.nags .nag .close, +.ui.inverted.nags .nag .title, +.ui.inverted.nag .close, +.ui.inverted.nag .title { + color: rgba(0, 0, 0, 0.4); +} + +/******************************* + Groups +*******************************/ + +.ui.nags .nag { + border-radius: 0em !important; +} + +.ui.nags .nag:last-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui.bottom.nags .nag:last-child { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Popup + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Popup +*******************************/ + +.ui.popup { + display: none; + position: absolute; + top: 0px; + right: 0px; + /* Fixes content being squished when inline (moz only) */ + min-width: -webkit-min-content; + min-width: -moz-min-content; + min-width: min-content; + z-index: 1900; + border: 1px solid #D4D4D5; + line-height: 1.4285em; + max-width: 250px; + background: #FFFFFF; + padding: 0.833em 1em; + font-weight: normal; + font-style: normal; + color: rgba(0, 0, 0, 0.87); + border-radius: 0.28571429rem; + box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); +} + +.ui.popup > .header { + padding: 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 1.14285714em; + line-height: 1.2; + font-weight: bold; +} + +.ui.popup > .header + .content { + padding-top: 0.5em; +} + +.ui.popup:before { + position: absolute; + content: ''; + width: 0.71428571em; + height: 0.71428571em; + background: #FFFFFF; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + z-index: 2; + box-shadow: 1px 1px 0px 0px #bababc; +} + +/******************************* + Types +*******************************/ + +/*-------------- + Tooltip +---------------*/ + +/* Content */ + +[data-tooltip] { + position: relative; +} + +/* Arrow */ + +[data-tooltip]:before { + pointer-events: none; + position: absolute; + content: ''; + font-size: 1rem; + width: 0.71428571em; + height: 0.71428571em; + background: #FFFFFF; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + z-index: 2; + box-shadow: 1px 1px 0px 0px #bababc; +} + +/* Popup */ + +[data-tooltip]:after { + pointer-events: none; + content: attr(data-tooltip); + position: absolute; + text-transform: none; + text-align: left; + white-space: nowrap; + font-size: 1rem; + border: 1px solid #D4D4D5; + line-height: 1.4285em; + max-width: none; + background: #FFFFFF; + padding: 0.833em 1em; + font-weight: normal; + font-style: normal; + color: rgba(0, 0, 0, 0.87); + border-radius: 0.28571429rem; + box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); + z-index: 1; +} + +/* Default Position (Top Center) */ + +[data-tooltip]:not([data-position]):before { + top: auto; + right: auto; + bottom: 100%; + left: 50%; + background: #FFFFFF; + margin-left: -0.07142857rem; + margin-bottom: 0.14285714rem; +} + +[data-tooltip]:not([data-position]):after { + left: 50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + bottom: 100%; + margin-bottom: 0.5em; +} + +/* Animation */ + +[data-tooltip]:before, +[data-tooltip]:after { + pointer-events: none; + visibility: hidden; +} + +[data-tooltip]:before { + opacity: 0; + -webkit-transform: rotate(45deg) scale(0) !important; + transform: rotate(45deg) scale(0) !important; + -webkit-transform-origin: center top; + transform-origin: center top; + -webkit-transition: all 0.1s ease; + transition: all 0.1s ease; +} + +[data-tooltip]:after { + opacity: 1; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-transition: all 0.1s ease; + transition: all 0.1s ease; +} + +[data-tooltip]:hover:before, +[data-tooltip]:hover:after { + visibility: visible; + pointer-events: auto; +} + +[data-tooltip]:hover:before { + -webkit-transform: rotate(45deg) scale(1) !important; + transform: rotate(45deg) scale(1) !important; + opacity: 1; +} + +/* Animation Position */ + +[data-tooltip]:after, +[data-tooltip][data-position="top center"]:after, +[data-tooltip][data-position="bottom center"]:after { + -webkit-transform: translateX(-50%) scale(0) !important; + transform: translateX(-50%) scale(0) !important; +} + +[data-tooltip]:hover:after, +[data-tooltip][data-position="bottom center"]:hover:after { + -webkit-transform: translateX(-50%) scale(1) !important; + transform: translateX(-50%) scale(1) !important; +} + +[data-tooltip][data-position="left center"]:after, +[data-tooltip][data-position="right center"]:after { + -webkit-transform: translateY(-50%) scale(0) !important; + transform: translateY(-50%) scale(0) !important; +} + +[data-tooltip][data-position="left center"]:hover:after, +[data-tooltip][data-position="right center"]:hover:after { + -webkit-transform: translateY(-50%) scale(1) !important; + transform: translateY(-50%) scale(1) !important; +} + +[data-tooltip][data-position="top left"]:after, +[data-tooltip][data-position="top right"]:after, +[data-tooltip][data-position="bottom left"]:after, +[data-tooltip][data-position="bottom right"]:after { + -webkit-transform: scale(0) !important; + transform: scale(0) !important; +} + +[data-tooltip][data-position="top left"]:hover:after, +[data-tooltip][data-position="top right"]:hover:after, +[data-tooltip][data-position="bottom left"]:hover:after, +[data-tooltip][data-position="bottom right"]:hover:after { + -webkit-transform: scale(1) !important; + transform: scale(1) !important; +} + +/*-------------- + Inverted +---------------*/ + +/* Arrow */ + +[data-tooltip][data-inverted]:before { + box-shadow: none !important; +} + +/* Arrow Position */ + +[data-tooltip][data-inverted]:before { + background: #1B1C1D; +} + +/* Popup */ + +[data-tooltip][data-inverted]:after { + background: #1B1C1D; + color: #FFFFFF; + border: none; + box-shadow: none; +} + +[data-tooltip][data-inverted]:after .header { + background-color: none; + color: #FFFFFF; +} + +/*-------------- + Position +---------------*/ + +/* Top Center */ + +[data-position="top center"][data-tooltip]:after { + top: auto; + right: auto; + left: 50%; + bottom: 100%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + margin-bottom: 0.5em; +} + +[data-position="top center"][data-tooltip]:before { + top: auto; + right: auto; + bottom: 100%; + left: 50%; + background: #FFFFFF; + margin-left: -0.07142857rem; + margin-bottom: 0.14285714rem; +} + +/* Top Left */ + +[data-position="top left"][data-tooltip]:after { + top: auto; + right: auto; + left: 0; + bottom: 100%; + margin-bottom: 0.5em; +} + +[data-position="top left"][data-tooltip]:before { + top: auto; + right: auto; + bottom: 100%; + left: 1em; + margin-left: -0.07142857rem; + margin-bottom: 0.14285714rem; +} + +/* Top Right */ + +[data-position="top right"][data-tooltip]:after { + top: auto; + left: auto; + right: 0; + bottom: 100%; + margin-bottom: 0.5em; +} + +[data-position="top right"][data-tooltip]:before { + top: auto; + left: auto; + bottom: 100%; + right: 1em; + margin-left: -0.07142857rem; + margin-bottom: 0.14285714rem; +} + +/* Bottom Center */ + +[data-position="bottom center"][data-tooltip]:after { + bottom: auto; + right: auto; + left: 50%; + top: 100%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + margin-top: 0.5em; +} + +[data-position="bottom center"][data-tooltip]:before { + bottom: auto; + right: auto; + top: 100%; + left: 50%; + margin-left: -0.07142857rem; + margin-top: 0.14285714rem; +} + +/* Bottom Left */ + +[data-position="bottom left"][data-tooltip]:after { + left: 0; + top: 100%; + margin-top: 0.5em; +} + +[data-position="bottom left"][data-tooltip]:before { + bottom: auto; + right: auto; + top: 100%; + left: 1em; + margin-left: -0.07142857rem; + margin-top: 0.14285714rem; +} + +/* Bottom Right */ + +[data-position="bottom right"][data-tooltip]:after { + right: 0; + top: 100%; + margin-top: 0.5em; +} + +[data-position="bottom right"][data-tooltip]:before { + bottom: auto; + left: auto; + top: 100%; + right: 1em; + margin-left: -0.14285714rem; + margin-top: 0.07142857rem; +} + +/* Left Center */ + +[data-position="left center"][data-tooltip]:after { + right: 100%; + top: 50%; + margin-right: 0.5em; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} + +[data-position="left center"][data-tooltip]:before { + right: 100%; + top: 50%; + margin-top: -0.14285714rem; + margin-right: -0.07142857rem; +} + +/* Right Center */ + +[data-position="right center"][data-tooltip]:after { + left: 100%; + top: 50%; + margin-left: 0.5em; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} + +[data-position="right center"][data-tooltip]:before { + left: 100%; + top: 50%; + margin-top: -0.07142857rem; + margin-left: 0.14285714rem; +} + +/* Arrow */ + +[data-position~="bottom"][data-tooltip]:before { + background: #FFFFFF; + box-shadow: -1px -1px 0px 0px #bababc; +} + +[data-position="left center"][data-tooltip]:before { + background: #FFFFFF; + box-shadow: 1px -1px 0px 0px #bababc; +} + +[data-position="right center"][data-tooltip]:before { + background: #FFFFFF; + box-shadow: -1px 1px 0px 0px #bababc; +} + +[data-position~="top"][data-tooltip]:before { + background: #FFFFFF; +} + +/* Inverted Arrow Color */ + +[data-inverted][data-position~="bottom"][data-tooltip]:before { + background: #1B1C1D; + box-shadow: -1px -1px 0px 0px #bababc; +} + +[data-inverted][data-position="left center"][data-tooltip]:before { + background: #1B1C1D; + box-shadow: 1px -1px 0px 0px #bababc; +} + +[data-inverted][data-position="right center"][data-tooltip]:before { + background: #1B1C1D; + box-shadow: -1px 1px 0px 0px #bababc; +} + +[data-inverted][data-position~="top"][data-tooltip]:before { + background: #1B1C1D; +} + +[data-position~="bottom"][data-tooltip]:before { + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} + +[data-position~="bottom"][data-tooltip]:after { + -webkit-transform-origin: center top; + transform-origin: center top; +} + +[data-position="left center"][data-tooltip]:before { + -webkit-transform-origin: top center; + transform-origin: top center; +} + +[data-position="left center"][data-tooltip]:after { + -webkit-transform-origin: right center; + transform-origin: right center; +} + +[data-position="right center"][data-tooltip]:before { + -webkit-transform-origin: right center; + transform-origin: right center; +} + +[data-position="right center"][data-tooltip]:after { + -webkit-transform-origin: left center; + transform-origin: left center; +} + +/*-------------- + Spacing +---------------*/ + +.ui.popup { + margin: 0em; +} + +/* Extending from Top */ + +.ui.top.popup { + margin: 0em 0em 0.71428571em; +} + +.ui.top.left.popup { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; +} + +.ui.top.center.popup { + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} + +.ui.top.right.popup { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; +} + +/* Extending from Vertical Center */ + +.ui.left.center.popup { + margin: 0em 0.71428571em 0em 0em; + -webkit-transform-origin: right 50%; + transform-origin: right 50%; +} + +.ui.right.center.popup { + margin: 0em 0em 0em 0.71428571em; + -webkit-transform-origin: left 50%; + transform-origin: left 50%; +} + +/* Extending from Bottom */ + +.ui.bottom.popup { + margin: 0.71428571em 0em 0em; +} + +.ui.bottom.left.popup { + -webkit-transform-origin: left top; + transform-origin: left top; +} + +.ui.bottom.center.popup { + -webkit-transform-origin: center top; + transform-origin: center top; +} + +.ui.bottom.right.popup { + -webkit-transform-origin: right top; + transform-origin: right top; +} + +/*-------------- + Pointer +---------------*/ + +/*--- Below ---*/ + +.ui.bottom.center.popup:before { + margin-left: -0.30714286em; + top: -0.30714286em; + left: 50%; + right: auto; + bottom: auto; + box-shadow: -1px -1px 0px 0px #bababc; +} + +.ui.bottom.left.popup { + margin-left: 0em; +} + +/*rtl:rename*/ + +.ui.bottom.left.popup:before { + top: -0.30714286em; + left: 1em; + right: auto; + bottom: auto; + margin-left: 0em; + box-shadow: -1px -1px 0px 0px #bababc; +} + +.ui.bottom.right.popup { + margin-right: 0em; +} + +/*rtl:rename*/ + +.ui.bottom.right.popup:before { + top: -0.30714286em; + right: 1em; + bottom: auto; + left: auto; + margin-left: 0em; + box-shadow: -1px -1px 0px 0px #bababc; +} + +/*--- Above ---*/ + +.ui.top.center.popup:before { + top: auto; + right: auto; + bottom: -0.30714286em; + left: 50%; + margin-left: -0.30714286em; +} + +.ui.top.left.popup { + margin-left: 0em; +} + +/*rtl:rename*/ + +.ui.top.left.popup:before { + bottom: -0.30714286em; + left: 1em; + top: auto; + right: auto; + margin-left: 0em; +} + +.ui.top.right.popup { + margin-right: 0em; +} + +/*rtl:rename*/ + +.ui.top.right.popup:before { + bottom: -0.30714286em; + right: 1em; + top: auto; + left: auto; + margin-left: 0em; +} + +/*--- Left Center ---*/ + +/*rtl:rename*/ + +.ui.left.center.popup:before { + top: 50%; + right: -0.30714286em; + bottom: auto; + left: auto; + margin-top: -0.30714286em; + box-shadow: 1px -1px 0px 0px #bababc; +} + +/*--- Right Center ---*/ + +/*rtl:rename*/ + +.ui.right.center.popup:before { + top: 50%; + left: -0.30714286em; + bottom: auto; + right: auto; + margin-top: -0.30714286em; + box-shadow: -1px 1px 0px 0px #bababc; +} + +/* Arrow Color By Location */ + +.ui.bottom.popup:before { + background: #FFFFFF; +} + +.ui.right.center.popup:before, +.ui.left.center.popup:before { + background: #FFFFFF; +} + +.ui.top.popup:before { + background: #FFFFFF; +} + +/* Inverted Arrow Color */ + +.ui.inverted.bottom.popup:before { + background: #1B1C1D; +} + +.ui.inverted.right.center.popup:before, +.ui.inverted.left.center.popup:before { + background: #1B1C1D; +} + +.ui.inverted.top.popup:before { + background: #1B1C1D; +} + +/******************************* + Coupling +*******************************/ + +/* Immediate Nested Grid */ + +.ui.popup > .ui.grid:not(.padded) { + width: calc(100% + 1.75rem); + margin: -0.7rem -0.875rem; +} + +/******************************* + States +*******************************/ + +.ui.loading.popup { + display: block; + visibility: hidden; + z-index: -1; +} + +.ui.animating.popup, +.ui.visible.popup { + display: block; +} + +.ui.visible.popup { + -webkit-transform: translateZ(0px); + transform: translateZ(0px); + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Basic +---------------*/ + +.ui.basic.popup:before { + display: none; +} + +/*-------------- + Wide +---------------*/ + +.ui.wide.popup { + max-width: 350px; +} + +.ui[class*="very wide"].popup { + max-width: 550px; +} + +@media only screen and (max-width: 767px) { + .ui.wide.popup, + .ui[class*="very wide"].popup { + max-width: 250px; + } +} + +/*-------------- + Fluid +---------------*/ + +.ui.fluid.popup { + width: 100%; + max-width: none; +} + +/*-------------- + Colors +---------------*/ + +/* Inverted colors */ + +.ui.inverted.popup { + background: #1B1C1D; + color: #FFFFFF; + border: none; + box-shadow: none; +} + +.ui.inverted.popup .header { + background-color: none; + color: #FFFFFF; +} + +.ui.inverted.popup:before { + background-color: #1B1C1D; + box-shadow: none !important; +} + +/*-------------- + Flowing +---------------*/ + +.ui.flowing.popup { + max-width: none; +} + +/*-------------- + Sizes +---------------*/ + +.ui.mini.popup { + font-size: 0.78571429rem; +} + +.ui.tiny.popup { + font-size: 0.85714286rem; +} + +.ui.small.popup { + font-size: 0.92857143rem; +} + +.ui.popup { + font-size: 1rem; +} + +.ui.large.popup { + font-size: 1.14285714rem; +} + +.ui.huge.popup { + font-size: 1.42857143rem; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Progress Bar + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Progress +*******************************/ + +.ui.progress { + position: relative; + display: block; + max-width: 100%; + border: none; + margin: 1em 0em 2.5em; + box-shadow: none; + background: rgba(0, 0, 0, 0.1); + padding: 0em; + border-radius: 0.28571429rem; +} + +.ui.progress:first-child { + margin: 0em 0em 2.5em; +} + +.ui.progress:last-child { + margin: 0em 0em 1.5em; +} + +/******************************* + Content +*******************************/ + +/* Activity Bar */ + +.ui.progress .bar { + display: block; + line-height: 1; + position: relative; + width: 0%; + min-width: 2em; + background: #888888; + border-radius: 0.28571429rem; + -webkit-transition: width 0.1s ease, background-color 0.1s ease; + transition: width 0.1s ease, background-color 0.1s ease; +} + +/* Percent Complete */ + +.ui.progress .bar > .progress { + white-space: nowrap; + position: absolute; + width: auto; + font-size: 0.92857143em; + top: 50%; + right: 0.5em; + left: auto; + bottom: auto; + color: rgba(255, 255, 255, 0.7); + text-shadow: none; + margin-top: -0.5em; + font-weight: bold; + text-align: left; +} + +/* Label */ + +.ui.progress > .label { + position: absolute; + width: 100%; + font-size: 1em; + top: 100%; + right: auto; + left: 0%; + bottom: auto; + color: rgba(0, 0, 0, 0.87); + font-weight: bold; + text-shadow: none; + margin-top: 0.2em; + text-align: center; + -webkit-transition: color 0.4s ease; + transition: color 0.4s ease; +} + +/******************************* + Types +*******************************/ + +/* Indicating */ + +.ui.indicating.progress[data-percent^="1"] .bar, +.ui.indicating.progress[data-percent^="2"] .bar { + background-color: #D95C5C; +} + +.ui.indicating.progress[data-percent^="3"] .bar { + background-color: #EFBC72; +} + +.ui.indicating.progress[data-percent^="4"] .bar, +.ui.indicating.progress[data-percent^="5"] .bar { + background-color: #E6BB48; +} + +.ui.indicating.progress[data-percent^="6"] .bar { + background-color: #DDC928; +} + +.ui.indicating.progress[data-percent^="7"] .bar, +.ui.indicating.progress[data-percent^="8"] .bar { + background-color: #B4D95C; +} + +.ui.indicating.progress[data-percent^="9"] .bar, +.ui.indicating.progress[data-percent^="100"] .bar { + background-color: #66DA81; +} + +/* Indicating Label */ + +.ui.indicating.progress[data-percent^="1"] .label, +.ui.indicating.progress[data-percent^="2"] .label { + color: rgba(0, 0, 0, 0.87); +} + +.ui.indicating.progress[data-percent^="3"] .label { + color: rgba(0, 0, 0, 0.87); +} + +.ui.indicating.progress[data-percent^="4"] .label, +.ui.indicating.progress[data-percent^="5"] .label { + color: rgba(0, 0, 0, 0.87); +} + +.ui.indicating.progress[data-percent^="6"] .label { + color: rgba(0, 0, 0, 0.87); +} + +.ui.indicating.progress[data-percent^="7"] .label, +.ui.indicating.progress[data-percent^="8"] .label { + color: rgba(0, 0, 0, 0.87); +} + +.ui.indicating.progress[data-percent^="9"] .label, +.ui.indicating.progress[data-percent^="100"] .label { + color: rgba(0, 0, 0, 0.87); +} + +/* Single Digits */ + +.ui.indicating.progress[data-percent="1"] .bar, +.ui.indicating.progress[data-percent="2"] .bar, +.ui.indicating.progress[data-percent="3"] .bar, +.ui.indicating.progress[data-percent="4"] .bar, +.ui.indicating.progress[data-percent="5"] .bar, +.ui.indicating.progress[data-percent="6"] .bar, +.ui.indicating.progress[data-percent="7"] .bar, +.ui.indicating.progress[data-percent="8"] .bar, +.ui.indicating.progress[data-percent="9"] .bar { + background-color: #D95C5C; +} + +.ui.indicating.progress[data-percent="1"] .label, +.ui.indicating.progress[data-percent="2"] .label, +.ui.indicating.progress[data-percent="3"] .label, +.ui.indicating.progress[data-percent="4"] .label, +.ui.indicating.progress[data-percent="5"] .label, +.ui.indicating.progress[data-percent="6"] .label, +.ui.indicating.progress[data-percent="7"] .label, +.ui.indicating.progress[data-percent="8"] .label, +.ui.indicating.progress[data-percent="9"] .label { + color: rgba(0, 0, 0, 0.87); +} + +/* Indicating Success */ + +.ui.indicating.progress.success .label { + color: #1A531B; +} + +/******************************* + States +*******************************/ + +/*-------------- + Success +---------------*/ + +.ui.progress.success .bar { + background-color: #21BA45 !important; +} + +.ui.progress.success .bar, +.ui.progress.success .bar::after { + -webkit-animation: none !important; + animation: none !important; +} + +.ui.progress.success > .label { + color: #1A531B; +} + +/*-------------- + Warning +---------------*/ + +.ui.progress.warning .bar { + background-color: #F2C037 !important; +} + +.ui.progress.warning .bar, +.ui.progress.warning .bar::after { + -webkit-animation: none !important; + animation: none !important; +} + +.ui.progress.warning > .label { + color: #794B02; +} + +/*-------------- + Error +---------------*/ + +.ui.progress.error .bar { + background-color: #DB2828 !important; +} + +.ui.progress.error .bar, +.ui.progress.error .bar::after { + -webkit-animation: none !important; + animation: none !important; +} + +.ui.progress.error > .label { + color: #912D2B; +} + +/*-------------- + Active +---------------*/ + +.ui.active.progress .bar { + position: relative; + min-width: 2em; +} + +.ui.active.progress .bar::after { + content: ''; + opacity: 0; + position: absolute; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + background: #FFFFFF; + border-radius: 0.28571429rem; + -webkit-animation: progress-active 2s ease infinite; + animation: progress-active 2s ease infinite; +} + +@-webkit-keyframes progress-active { + 0% { + opacity: 0.3; + width: 0; + } + + 100% { + opacity: 0; + width: 100%; + } +} + +@keyframes progress-active { + 0% { + opacity: 0.3; + width: 0; + } + + 100% { + opacity: 0; + width: 100%; + } +} + +/*-------------- + Disabled +---------------*/ + +.ui.disabled.progress { + opacity: 0.35; +} + +.ui.disabled.progress .bar, +.ui.disabled.progress .bar::after { + -webkit-animation: none !important; + animation: none !important; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Inverted +---------------*/ + +.ui.inverted.progress { + background: rgba(255, 255, 255, 0.08); + border: none; +} + +.ui.inverted.progress .bar { + background: #888888; +} + +.ui.inverted.progress .bar > .progress { + color: #F9FAFB; +} + +.ui.inverted.progress > .label { + color: #FFFFFF; +} + +.ui.inverted.progress.success > .label { + color: #21BA45; +} + +.ui.inverted.progress.warning > .label { + color: #F2C037; +} + +.ui.inverted.progress.error > .label { + color: #DB2828; +} + +/*-------------- + Attached +---------------*/ + +/* bottom attached */ + +.ui.progress.attached { + background: transparent; + position: relative; + border: none; + margin: 0em; +} + +.ui.progress.attached, +.ui.progress.attached .bar { + display: block; + height: 0.2rem; + padding: 0px; + overflow: hidden; + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +.ui.progress.attached .bar { + border-radius: 0em; +} + +/* top attached */ + +.ui.progress.top.attached, +.ui.progress.top.attached .bar { + top: 0px; + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.progress.top.attached .bar { + border-radius: 0em; +} + +/* Coupling */ + +.ui.segment > .ui.attached.progress, +.ui.card > .ui.attached.progress { + position: absolute; + top: auto; + left: 0; + bottom: 100%; + width: 100%; +} + +.ui.segment > .ui.bottom.attached.progress, +.ui.card > .ui.bottom.attached.progress { + top: 100%; + bottom: auto; +} + +/*-------------- + Colors +---------------*/ + +/* Red */ + +.ui.red.progress .bar { + background-color: #DB2828; +} + +.ui.red.inverted.progress .bar { + background-color: #FF695E; +} + +/* Orange */ + +.ui.orange.progress .bar { + background-color: #F2711C; +} + +.ui.orange.inverted.progress .bar { + background-color: #FF851B; +} + +/* Yellow */ + +.ui.yellow.progress .bar { + background-color: #FBBD08; +} + +.ui.yellow.inverted.progress .bar { + background-color: #FFE21F; +} + +/* Olive */ + +.ui.olive.progress .bar { + background-color: #B5CC18; +} + +.ui.olive.inverted.progress .bar { + background-color: #D9E778; +} + +/* Green */ + +.ui.green.progress .bar { + background-color: #21BA45; +} + +.ui.green.inverted.progress .bar { + background-color: #2ECC40; +} + +/* Teal */ + +.ui.teal.progress .bar { + background-color: #00B5AD; +} + +.ui.teal.inverted.progress .bar { + background-color: #6DFFFF; +} + +/* Blue */ + +.ui.blue.progress .bar { + background-color: #2185D0; +} + +.ui.blue.inverted.progress .bar { + background-color: #54C8FF; +} + +/* Violet */ + +.ui.violet.progress .bar { + background-color: #6435C9; +} + +.ui.violet.inverted.progress .bar { + background-color: #A291FB; +} + +/* Purple */ + +.ui.purple.progress .bar { + background-color: #A333C8; +} + +.ui.purple.inverted.progress .bar { + background-color: #DC73FF; +} + +/* Pink */ + +.ui.pink.progress .bar { + background-color: #E03997; +} + +.ui.pink.inverted.progress .bar { + background-color: #FF8EDF; +} + +/* Brown */ + +.ui.brown.progress .bar { + background-color: #A5673F; +} + +.ui.brown.inverted.progress .bar { + background-color: #D67C1C; +} + +/* Grey */ + +.ui.grey.progress .bar { + background-color: #767676; +} + +.ui.grey.inverted.progress .bar { + background-color: #DCDDDE; +} + +/* Black */ + +.ui.black.progress .bar { + background-color: #1B1C1D; +} + +.ui.black.inverted.progress .bar { + background-color: #545454; +} + +/*-------------- + Sizes +---------------*/ + +.ui.tiny.progress { + font-size: 0.85714286rem; +} + +.ui.tiny.progress .bar { + height: 0.5em; +} + +.ui.small.progress { + font-size: 0.92857143rem; +} + +.ui.small.progress .bar { + height: 1em; +} + +.ui.progress { + font-size: 1rem; +} + +.ui.progress .bar { + height: 1.75em; +} + +.ui.large.progress { + font-size: 1.14285714rem; +} + +.ui.large.progress .bar { + height: 2.5em; +} + +.ui.big.progress { + font-size: 1.28571429rem; +} + +.ui.big.progress .bar { + height: 3.5em; +} + +/******************************* + Progress +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Rating + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Rating +*******************************/ + +.ui.rating { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + white-space: nowrap; + vertical-align: baseline; +} + +.ui.rating:last-child { + margin-right: 0em; +} + +/* Icon */ + +.ui.rating .icon { + padding: 0em; + margin: 0em; + text-align: center; + font-weight: normal; + font-style: normal; + -webkit-box-flex: 1; + -webkit-flex: 1 0 auto; + -ms-flex: 1 0 auto; + flex: 1 0 auto; + cursor: pointer; + width: 1.25em; + height: auto; + -webkit-transition: opacity 0.1s ease, background 0.1s ease, text-shadow 0.1s ease, color 0.1s ease; + transition: opacity 0.1s ease, background 0.1s ease, text-shadow 0.1s ease, color 0.1s ease; +} + +/******************************* + Types +*******************************/ + +/*------------------- + Standard +--------------------*/ + +/* Inactive Icon */ + +.ui.rating .icon { + background: transparent; + color: rgba(0, 0, 0, 0.15); +} + +/* Active Icon */ + +.ui.rating .active.icon { + background: transparent; + color: rgba(0, 0, 0, 0.85); +} + +/* Selected Icon */ + +.ui.rating .icon.selected, +.ui.rating .icon.selected.active { + background: transparent; + color: rgba(0, 0, 0, 0.87); +} + +/*------------------- + Star +--------------------*/ + +/* Inactive */ + +.ui.star.rating .icon { + width: 1.25em; + height: auto; + background: transparent; + color: rgba(0, 0, 0, 0.15); + text-shadow: none; +} + +/* Active Star */ + +.ui.star.rating .active.icon { + background: transparent !important; + color: #FFE623 !important; + text-shadow: 0px -1px 0px #DDC507, -1px 0px 0px #DDC507, 0px 1px 0px #DDC507, 1px 0px 0px #DDC507 !important; +} + +/* Selected Star */ + +.ui.star.rating .icon.selected, +.ui.star.rating .icon.selected.active { + background: transparent !important; + color: #FFCC00 !important; + text-shadow: 0px -1px 0px #E6A200, -1px 0px 0px #E6A200, 0px 1px 0px #E6A200, 1px 0px 0px #E6A200 !important; +} + +/*------------------- + Heart +--------------------*/ + +.ui.heart.rating .icon { + width: 1.4em; + height: auto; + background: transparent; + color: rgba(0, 0, 0, 0.15); + text-shadow: none !important; +} + +/* Active Heart */ + +.ui.heart.rating .active.icon { + background: transparent !important; + color: #FF6D75 !important; + text-shadow: 0px -1px 0px #CD0707, -1px 0px 0px #CD0707, 0px 1px 0px #CD0707, 1px 0px 0px #CD0707 !important; +} + +/* Selected Heart */ + +.ui.heart.rating .icon.selected, +.ui.heart.rating .icon.selected.active { + background: transparent !important; + color: #FF3000 !important; + text-shadow: 0px -1px 0px #AA0101, -1px 0px 0px #AA0101, 0px 1px 0px #AA0101, 1px 0px 0px #AA0101 !important; +} + +/******************************* + States +*******************************/ + +/*------------------- + Disabled +--------------------*/ + +/* disabled rating */ + +.ui.disabled.rating .icon { + cursor: default; +} + +/*------------------- + User Interactive +--------------------*/ + +/* Selected Rating */ + +.ui.rating.selected .active.icon { + opacity: 1; +} + +.ui.rating.selected .icon.selected, +.ui.rating .icon.selected { + opacity: 1; +} + +/******************************* + Variations +*******************************/ + +.ui.mini.rating { + font-size: 0.78571429rem; +} + +.ui.tiny.rating { + font-size: 0.85714286rem; +} + +.ui.small.rating { + font-size: 0.92857143rem; +} + +.ui.rating { + font-size: 1rem; +} + +.ui.large.rating { + font-size: 1.14285714rem; +} + +.ui.huge.rating { + font-size: 1.42857143rem; +} + +.ui.massive.rating { + font-size: 2rem; +} + +/******************************* + Theme Overrides +*******************************/ + +@font-face { + font-family: 'Rating'; + src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggjCBsAAAC8AAAAYGNtYXCj2pm8AAABHAAAAKRnYXNwAAAAEAAAAcAAAAAIZ2x5ZlJbXMYAAAHIAAARnGhlYWQBGAe5AAATZAAAADZoaGVhA+IB/QAAE5wAAAAkaG10eCzgAEMAABPAAAAAcGxvY2EwXCxOAAAUMAAAADptYXhwACIAnAAAFGwAAAAgbmFtZfC1n04AABSMAAABPHBvc3QAAwAAAAAVyAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADxZQHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEAJAAAAAgACAABAAAAAEAIOYF8AbwDfAj8C7wbvBw8Irwl/Cc8SPxZf/9//8AAAAAACDmAPAE8AzwI/Au8G7wcPCH8JfwnPEj8WT//f//AAH/4xoEEAYQAQ/sD+IPow+iD4wPgA98DvYOtgADAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAPAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAIAAP/tAgAB0wAKABUAAAEvAQ8BFwc3Fyc3BQc3Jz8BHwEHFycCALFPT7GAHp6eHoD/AHAWW304OH1bFnABGRqgoBp8sFNTsHyyOnxYEnFxElh8OgAAAAACAAD/7QIAAdMACgASAAABLwEPARcHNxcnNwUxER8BBxcnAgCxT0+xgB6enh6A/wA4fVsWcAEZGqCgGnywU1OwfLIBHXESWHw6AAAAAQAA/+0CAAHTAAoAAAEvAQ8BFwc3Fyc3AgCxT0+xgB6enh6AARkaoKAafLBTU7B8AAAAAAEAAAAAAgABwAArAAABFA4CBzEHDgMjIi4CLwEuAzU0PgIzMh4CFz4DMzIeAhUCAAcMEgugBgwMDAYGDAwMBqALEgwHFyg2HhAfGxkKChkbHxAeNigXAS0QHxsZCqAGCwkGBQkLBqAKGRsfEB42KBcHDBILCxIMBxcoNh4AAAAAAgAAAAACAAHAACsAWAAAATQuAiMiDgIHLgMjIg4CFRQeAhcxFx4DMzI+Aj8BPgM1DwEiFCIGMTAmIjQjJy4DNTQ+AjMyHgIfATc+AzMyHgIVFA4CBwIAFyg2HhAfGxkKChkbHxAeNigXBwwSC6AGDAwMBgYMDAwGoAsSDAdbogEBAQEBAaIGCgcEDRceEQkREA4GLy8GDhARCREeFw0EBwoGAS0eNigXBwwSCwsSDAcXKDYeEB8bGQqgBgsJBgUJCwagChkbHxA+ogEBAQGiBg4QEQkRHhcNBAcKBjQ0BgoHBA0XHhEJERAOBgABAAAAAAIAAcAAMQAAARQOAgcxBw4DIyIuAi8BLgM1ND4CMzIeAhcHFwc3Jzc+AzMyHgIVAgAHDBILoAYMDAwGBgwMDAagCxIMBxcoNh4KFRMSCC9wQLBwJwUJCgkFHjYoFwEtEB8bGQqgBgsJBgUJCwagChkbHxAeNigXAwUIBUtAoMBAOwECAQEXKDYeAAABAAAAAAIAAbcAKgAAEzQ3NjMyFxYXFhcWFzY3Njc2NzYzMhcWFRQPAQYjIi8BJicmJyYnJicmNQAkJUARExIQEAsMCgoMCxAQEhMRQCUkQbIGBwcGsgMFBQsKCQkGBwExPyMkBgYLCgkKCgoKCQoLBgYkIz8/QawFBawCBgUNDg4OFRQTAAAAAQAAAA0B2wHSACYAABM0PwI2FzYfAhYVFA8BFxQVFAcGByYvAQcGByYnJjU0PwEnJjUAEI9BBQkIBkCPEAdoGQMDBgUGgIEGBQYDAwEYaAcBIwsCFoEMAQEMgRYCCwYIZJABBQUFAwEBAkVFAgEBAwUFAwOQZAkFAAAAAAIAAAANAdsB0gAkAC4AABM0PwI2FzYfAhYVFA8BFxQVFAcmLwEHBgcmJyY1ND8BJyY1HwEHNxcnNy8BBwAQj0EFCQgGQI8QB2gZDAUGgIEGBQYDAwEYaAc/WBVsaxRXeDY2ASMLAhaBDAEBDIEWAgsGCGSQAQUNAQECRUUCAQEDBQUDA5BkCQURVXg4OHhVEW5uAAABACMAKQHdAXwAGgAANzQ/ATYXNh8BNzYXNh8BFhUUDwEGByYvASY1IwgmCAwLCFS8CAsMCCYICPUIDAsIjgjSCwkmCQEBCVS7CQEBCSYJCg0H9gcBAQePBwwAAAEAHwAfAXMBcwAsAAA3ND8BJyY1ND8BNjMyHwE3NjMyHwEWFRQPARcWFRQPAQYjIi8BBwYjIi8BJjUfCFRUCAgnCAwLCFRUCAwLCCcICFRUCAgnCAsMCFRUCAsMCCcIYgsIVFQIDAsIJwgIVFQICCcICwwIVFQICwwIJwgIVFQICCcIDAAAAAACAAAAJQFJAbcAHwArAAA3NTQ3NjsBNTQ3NjMyFxYdATMyFxYdARQHBiMhIicmNTczNTQnJiMiBwYdAQAICAsKJSY1NCYmCQsICAgIC/7tCwgIW5MWFR4fFRZApQsICDc0JiYmJjQ3CAgLpQsICAgIC8A3HhYVFRYeNwAAAQAAAAcBbgG3ACEAADcRNDc2NzYzITIXFhcWFREUBwYHBiMiLwEHBiMiJyYnJjUABgUKBgYBLAYGCgUGBgUKBQcOCn5+Cg4GBgoFBicBcAoICAMDAwMICAr+kAoICAQCCXl5CQIECAgKAAAAAwAAACUCAAFuABgAMQBKAAA3NDc2NzYzMhcWFxYVFAcGBwYjIicmJyY1MxYXFjMyNzY3JicWFRQHBiMiJyY1NDcGBzcUFxYzMjc2NTQ3NjMyNzY1NCcmIyIHBhUABihDREtLREMoBgYoQ0RLS0RDKAYlJjk5Q0M5OSYrQREmJTU1JSYRQSuEBAQGBgQEEREZBgQEBAQGJBkayQoKQSgoKChBCgoKCkEoJycoQQoKOiMjIyM6RCEeIjUmJSUmNSIeIUQlBgQEBAQGGBIRBAQGBgQEGhojAAAABQAAAAkCAAGJACwAOABRAGgAcAAANzQ3Njc2MzIXNzYzMhcWFxYXFhcWFxYVFDEGBwYPAQYjIicmNTQ3JicmJyY1MxYXNyYnJjU0NwYHNxQXFjMyNzY1NDc2MzI3NjU0JyYjIgcGFRc3Njc2NyYnNxYXFhcWFRQHBgcGBwYjPwEWFRQHBgcABitBQU0ZGhADBQEEBAUFBAUEBQEEHjw8Hg4DBQQiBQ0pIyIZBiUvSxYZDg4RQSuEBAQGBgQEEREZBgQEBAQGJBkaVxU9MzQiIDASGxkZEAYGCxQrODk/LlACFxYlyQsJQycnBRwEAgEDAwIDAwIBAwUCNmxsNhkFFAMFBBUTHh8nCQtKISgSHBsfIh4hRCUGBAQEBAYYEhEEBAYGBAQaGiPJJQUiIjYzISASGhkbCgoKChIXMRsbUZANCyghIA8AAAMAAAAAAbcB2wA5AEoAlAAANzU0NzY7ATY3Njc2NzY3Njc2MzIXFhcWFRQHMzIXFhUUBxYVFAcUFRQHFgcGKwEiJyYnJisBIicmNTcUFxYzMjc2NTQnJiMiBwYVFzMyFxYXFhcWFxYXFhcWOwEyNTQnNjc2NTQnNjU0JyYnNjc2NTQnJisBNDc2NTQnJiMGBwYHBgcGBwYHBgcGBwYHBgcGBwYrARUACwoQTgodEQ4GBAMFBgwLDxgTEwoKDjMdFhYOAgoRARkZKCUbGxsjIQZSEAoLJQUFCAcGBQUGBwgFBUkJBAUFBAQHBwMDBwcCPCUjNwIJBQUFDwMDBAkGBgsLDmUODgoJGwgDAwYFDAYQAQUGAwQGBgYFBgUGBgQJSbcPCwsGJhUPCBERExMMCgkJFBQhGxwWFR4ZFQoKFhMGBh0WKBcXBgcMDAoLDxIHBQYGBQcIBQYGBQgSAQEBAQICAQEDAgEULwgIBQoLCgsJDhQHCQkEAQ0NCg8LCxAdHREcDQ4IEBETEw0GFAEHBwUECAgFBQUFAgO3AAADAAD/2wG3AbcAPABNAJkAADc1NDc2OwEyNzY3NjsBMhcWBxUWFRQVFhUUBxYVFAcGKwEWFRQHBgcGIyInJicmJyYnJicmJyYnIyInJjU3FBcWMzI3NjU0JyYjIgcGFRczMhcWFxYXFhcWFxYXFhcWFxYXFhcWFzI3NjU0JyY1MzI3NjU0JyYjNjc2NTQnNjU0JyYnNjU0JyYrASIHIgcGBwYHBgcGIwYrARUACwoQUgYhJRsbHiAoGRkBEQoCDhYWHTMOCgoTExgPCwoFBgIBBAMFDhEdCk4QCgslBQUIBwYFBQYHCAUFSQkEBgYFBgUGBgYEAwYFARAGDAUGAwMIGwkKDg5lDgsLBgYJBAMDDwUFBQkCDg4ZJSU8AgcHAwMHBwQEBQUECbe3DwsKDAwHBhcWJwIWHQYGExYKChUZHhYVHRoiExQJCgsJDg4MDAwNBg4WJQcLCw+kBwUGBgUHCAUGBgUIpAMCBQYFBQcIBAUHBwITBwwTExERBw0OHBEdHRALCw8KDQ0FCQkHFA4JCwoLCgUICBgMCxUDAgEBAgMBAQG3AAAAAQAAAA0A7gHSABQAABM0PwI2FxEHBgcmJyY1ND8BJyY1ABCPQQUJgQYFBgMDARhoBwEjCwIWgQwB/oNFAgEBAwUFAwOQZAkFAAAAAAIAAAAAAgABtwAqAFkAABM0NzYzMhcWFxYXFhc2NzY3Njc2MzIXFhUUDwEGIyIvASYnJicmJyYnJjUzFB8BNzY1NCcmJyYnJicmIyIHBgcGBwYHBiMiJyYnJicmJyYjIgcGBwYHBgcGFQAkJUARExIQEAsMCgoMCxAQEhMRQCUkQbIGBwcGsgMFBQsKCQkGByU1pqY1BgYJCg4NDg0PDhIRDg8KCgcFCQkFBwoKDw4REg4PDQ4NDgoJBgYBMT8jJAYGCwoJCgoKCgkKCwYGJCM/P0GsBQWsAgYFDQ4ODhUUEzA1oJ82MBcSEgoLBgcCAgcHCwsKCQgHBwgJCgsLBwcCAgcGCwoSEhcAAAACAAAABwFuAbcAIQAoAAA3ETQ3Njc2MyEyFxYXFhURFAcGBwYjIi8BBwYjIicmJyY1PwEfAREhEQAGBQoGBgEsBgYKBQYGBQoFBw4Kfn4KDgYGCgUGJZIZef7cJwFwCggIAwMDAwgICv6QCggIBAIJeXkJAgQICAoIjRl0AWP+nQAAAAABAAAAJQHbAbcAMgAANzU0NzY7ATU0NzYzMhcWHQEUBwYrASInJj0BNCcmIyIHBh0BMzIXFh0BFAcGIyEiJyY1AAgIC8AmJjQ1JiUFBQgSCAUFFhUfHhUWHAsICAgIC/7tCwgIQKULCAg3NSUmJiU1SQgFBgYFCEkeFhUVFh43CAgLpQsICAgICwAAAAIAAQANAdsB0gAiAC0AABM2PwI2MzIfAhYXFg8BFxYHBiMiLwEHBiMiJyY/AScmNx8CLwE/AS8CEwEDDJBABggJBUGODgIDCmcYAgQCCAMIf4IFBgYEAgEZaQgC7hBbEgINSnkILgEBJggCFYILC4IVAggICWWPCgUFA0REAwUFCo9lCQipCTBmEw1HEhFc/u0AAAADAAAAAAHJAbcAFAAlAHkAADc1NDc2OwEyFxYdARQHBisBIicmNTcUFxYzMjc2NTQnJiMiBwYVFzU0NzYzNjc2NzY3Njc2NzY3Njc2NzY3NjMyFxYXFhcWFxYXFhUUFRQHBgcGBxQHBgcGBzMyFxYVFAcWFRYHFgcGBxYHBgcjIicmJyYnJiciJyY1AAUGB1MHBQYGBQdTBwYFJQUFCAcGBQUGBwgFBWQFBQgGDw8OFAkFBAQBAQMCAQIEBAYFBw4KCgcHBQQCAwEBAgMDAgYCAgIBAU8XEBAQBQEOBQUECwMREiYlExYXDAwWJAoHBQY3twcGBQUGB7cIBQUFBQgkBwYFBQYHCAUGBgUIJLcHBQYBEBATGQkFCQgGBQwLBgcICQUGAwMFBAcHBgYICQQEBwsLCwYGCgIDBAMCBBEQFhkSDAoVEhAREAsgFBUBBAUEBAcMAQUFCAAAAAADAAD/2wHJAZIAFAAlAHkAADcUFxYXNxY3Nj0BNCcmBycGBwYdATc0NzY3FhcWFRQHBicGJyY1FzU0NzY3Fjc2NzY3NjcXNhcWBxYXFgcWBxQHFhUUBwYHJxYXFhcWFRYXFhcWFRQVFAcGBwYHBgcGBwYnBicmJyYnJicmJyYnJicmJyYnJiciJyY1AAUGB1MHBQYGBQdTBwYFJQUFCAcGBQUGBwgFBWQGBQcKJBYMDBcWEyUmEhEDCwQFBQ4BBRAQEBdPAQECAgIGAgMDAgEBAwIEBQcHCgoOBwUGBAQCAQIDAQEEBAUJFA4PDwYIBQWlBwYFAQEBBwQJtQkEBwEBAQUGB7eTBwYEAQEEBgcJBAYBAQYECZS4BwYEAgENBwUCBgMBAQEXEyEJEhAREBcIDhAaFhEPAQEFAgQCBQELBQcKDAkIBAUHCgUGBwgDBgIEAQEHBQkIBwUMCwcECgcGCRoREQ8CBgQIAAAAAQAAAAEAAJth57dfDzz1AAsCAAAAAADP/GODAAAAAM/8Y4MAAP/bAgAB2wAAAAgAAgAAAAAAAAABAAAB4P/gAAACAAAAAAACAAABAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAEAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAdwAAAHcAAACAAAjAZMAHwFJAAABbgAAAgAAAAIAAAACAAAAAgAAAAEAAAACAAAAAW4AAAHcAAAB3AABAdwAAAHcAAAAAAAAAAoAFAAeAEoAcACKAMoBQAGIAcwCCgJUAoICxgMEAzoDpgRKBRgF7AYSBpgG2gcgB2oIGAjOAAAAAQAAABwAmgAFAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAwAAAABAAAAAAACAA4AQAABAAAAAAADAAwAIgABAAAAAAAEAAwATgABAAAAAAAFABYADAABAAAAAAAGAAYALgABAAAAAAAKADQAWgADAAEECQABAAwAAAADAAEECQACAA4AQAADAAEECQADAAwAIgADAAEECQAEAAwATgADAAEECQAFABYADAADAAEECQAGAAwANAADAAEECQAKADQAWgByAGEAdABpAG4AZwBWAGUAcgBzAGkAbwBuACAAMQAuADAAcgBhAHQAaQBuAGdyYXRpbmcAcgBhAHQAaQBuAGcAUgBlAGcAdQBsAGEAcgByAGEAdABpAG4AZwBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AABcUAAoAAAAAFswAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAAEuEAABLho6TvIE9TLzIAABPYAAAAYAAAAGAIIwgbY21hcAAAFDgAAACkAAAApKPambxnYXNwAAAU3AAAAAgAAAAIAAAAEGhlYWQAABTkAAAANgAAADYBGAe5aGhlYQAAFRwAAAAkAAAAJAPiAf1obXR4AAAVQAAAAHAAAABwLOAAQ21heHAAABWwAAAABgAAAAYAHFAAbmFtZQAAFbgAAAE8AAABPPC1n05wb3N0AAAW9AAAACAAAAAgAAMAAAEABAQAAQEBB3JhdGluZwABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeLZviU+HQFHQAAAP0PHQAAAQIRHQAAAAkdAAAS2BIAHQEBBw0PERQZHiMoLTI3PEFGS1BVWl9kaW5zeH2Ch4xyYXRpbmdyYXRpbmd1MHUxdTIwdUU2MDB1RTYwMXVFNjAydUU2MDN1RTYwNHVFNjA1dUYwMDR1RjAwNXVGMDA2dUYwMEN1RjAwRHVGMDIzdUYwMkV1RjA2RXVGMDcwdUYwODd1RjA4OHVGMDg5dUYwOEF1RjA5N3VGMDlDdUYxMjN1RjE2NHVGMTY1AAACAYkAGgAcAgABAAQABwAKAA0AVgCWAL0BAgGMAeQCbwLwA4cD5QR0BQMFdgZgB8MJkQtxC7oM2Q1jDggOmRAYEZr8lA78lA78lA77lA74lPetFftFpTz3NDz7NPtFcfcU+xBt+0T3Mt73Mjht90T3FPcQBfuU+0YV+wRRofcQMOP3EZ3D9wXD+wX3EXkwM6H7EPsExQUO+JT3rRX7RaU89zQ8+zT7RXH3FPsQbftE9zLe9zI4bfdE9xT3EAX7lPtGFYuLi/exw/sF9xF5MDOh+xD7BMUFDviU960V+0WlPPc0PPs0+0Vx9xT7EG37RPcy3vcyOG33RPcU9xAFDviU98EVi2B4ZG5wCIuL+zT7NAV7e3t7e4t7i3ube5sI+zT3NAVupniyi7aL3M3N3Iu2i7J4pm6mqLKetovci81JizoIDviU98EVi9xJzTqLYItkeHBucKhknmCLOotJSYs6i2CeZKhwCIuL9zT7NAWbe5t7m4ubi5ubm5sI9zT3NAWopp6yi7YIME0V+zb7NgWKioqKiouKi4qMiowI+zb3NgV6m4Ghi6OLubCwuYuji6GBm3oIule6vwWbnKGVo4u5i7Bmi12Lc4F1ensIDviU98EVi2B4ZG5wCIuL+zT7NAV7e3t7e4t7i3ube5sI+zT3NAVupniyi7aL3M3N3Iuni6WDoX4IXED3BEtL+zT3RPdU+wTLssYFl46YjZiL3IvNSYs6CA6L98UVi7WXrKOio6Otl7aLlouXiZiHl4eWhZaEloSUhZKFk4SShZKEkpKSkZOSkpGUkZaSCJaSlpGXj5iPl42Wi7aLrX+jc6N0l2qLYYthdWBgYAj7RvtABYeIh4mGi4aLh42Hjgj7RvdABYmNiY2Hj4iOhpGDlISUhZWFlIWVhpaHmYaYiZiLmAgOZ4v3txWLkpCPlo0I9yOgzPcWBY6SkI+Ri5CLkIePhAjL+xb3I3YFlomQh4uEi4aJh4aGCCMmpPsjBYuKi4mLiIuHioiJiImIiIqHi4iLh4yHjQj7FM/7FUcFh4mHioiLh4uIjImOiY6KjouPi4yLjYyOCKP3IyPwBYaQiZCLjwgOZ4v3txWLkpCPlo0I9yOgzPcWBY6SkI+Ri5CLkIePhAjL+xb3I3YFlomQh4uEi4aJh4aGCCMmpPsjBYuKi4mLiIuCh4aDi4iLh4yHjQj7FM/7FUcFh4mHioiLh4uIjImOiY6KjouPi4yLjYyOCKP3IyPwBYaQiZCLjwjKeRXjN3b7DfcAxPZSd/cN4t/7DJ1V9wFV+wEFDq73ZhWLk42RkZEIsbIFkZCRjpOLkouSiJCGCN8291D3UAWQkJKOkouTi5GIkYYIsWQFkYaNhIuEi4OJhYWFCPuJ+4kFhYWFiYOLhIuEjYaRCPsi9yIFhZCJkouSCA77AartFYuSjpKQkAjf3zffBYaQiJKLk4uSjpKQkAiysgWRkJGOk4uSi5KIkIYI3zff3wWQkJKOk4uSi5KIkIYIsmQFkIaOhIuEi4OIhIaGCDc33zcFkIaOhIuEi4OIhYaFCGRkBYaGhIiEi4OLhI6GkAg33zc3BYaGhIiEi4OLhY6FkAhksgWGkYiRi5MIDvtLi8sVi/c5BYuSjpKQkJCQko6SiwiVi4vCBYuul6mkpKSkqpiui66LqX6kcqRymG2LaAiLVJSLBZKLkoiQhpCGjoSLhAiL+zkFi4OIhYaGhoWEiYSLCPuniwWEi4SNhpGGkIiRi5MI5vdUFfcni4vCBYufhJx8mn2ZepJ3i3aLeoR9fX18g3qLdwiLVAUO+yaLshWL+AQFi5GNkY+RjpCQj5KNj42PjI+LCPfAiwWPi4+Kj4mRiZCHj4aPhY2Fi4UIi/wEBYuEiYWHhoeGhoeFiIiKhoqHi4GLhI6EkQj7EvcN+xL7DQWEhYOIgouHi4eLh42EjoaPiJCHkImRi5IIDov3XRWLko2Rj5Kltq+vuKW4pbuZvYu9i7t9uHG4ca9npWCPhI2Fi4SLhYmEh4RxYGdoXnAIXnFbflmLWYtbmF6lXqZnrnG2h5KJkouRCLCLFaRkq2yxdLF0tH+4i7iLtJexorGiq6qksm64Z61goZZ3kXaLdItnfm1ycnJybX9oiwhoi22XcqRypH6pi6+LopGglp9gdWdpbl4I9xiwFYuHjIiOiI6IjoqPi4+LjoyOjo2OjY6Lj4ubkJmXl5eWmZGbi4+LjoyOjo2OjY6LjwiLj4mOiY6IjYiNh4tzi3eCenp6eoJ3i3MIDov3XRWLko2Sj5GouK+utqW3pbqYvouci5yJnIgIm6cFjY6NjI+LjIuNi42JjYqOio+JjomOiY6KjomOiY6JjoqNioyKjomMiYuHi4qLiouLCHdnbVVjQ2NDbVV3Zwh9cgWJiIiJiIuJi36SdJiIjYmOi46LjY+UlJlvl3KcdJ90oHeie6WHkYmSi5IIsIsVqlq0Z711CKGzBXqXfpqCnoKdhp6LoIuikaCWn2B1Z2luXgj3GLAVi4eMiI6IjoiOio+Lj4uOjI6OjY6NjouPi5uQmZeXl5aZkZuLj4uOjI6OjY6NjouPCIuPiY6JjoiNiI2Hi3OLd4J6enp6gneLcwji+10VoLAFtI+wmK2hrqKnqKKvdq1wp2uhCJ2rBZ1/nHycepx6mHqWeY+EjYWLhIuEiYWHhIR/gH1+fG9qaXJmeWV5Y4Jhiwi53BXb9yQFjIKMg4uEi3CDc3x1fHV3fHOBCA6L1BWL90sFi5WPlJKSkpKTj5aLCNmLBZKPmJqepJaZlZeVlY+Qj5ONl42WjpeOmI+YkZWTk5OSk46Vi5uLmYiYhZiFlIGSfgiSfo55i3WLeYd5gXgIvosFn4uchJl8mn2Seot3i3qGfIJ9jYSLhYuEi3yIfoR+i4eLh4uHi3eGen99i3CDdnt8CHt8dYNwiwhmiwV5i3mNeY95kHeRc5N1k36Ph4sIOYsFgIuDjoSShJKHlIuVCLCdFYuGjIePiI+Hj4mQi5CLj42Pj46OjY+LkIuQiZCIjoePh42Gi4aLh4mHh4eIioaLhgjUeRWUiwWNi46Lj4qOi4+KjYqOi4+Kj4mQio6KjYqNio+Kj4mQio6KjIqzfquEpIsIrosFr4uemouri5CKkYqQkY6QkI6SjpKNkouSi5KJkoiRlZWQlouYi5CKkImRiZGJj4iOCJGMkI+PlI+UjZKLkouViJODk4SSgo+CiwgmiwWLlpCalJ6UnpCbi5aLnoiYhJSFlH+QeYuGhoeDiYCJf4h/h3+IfoWBg4KHh4SCgH4Ii4qIiYiGh4aIh4mIiIiIh4eGh4aHh4eHiIiHiIeHiIiHiIeKh4mIioiLCIKLi/tLBQ6L90sVi/dLBYuVj5OSk5KSk46WiwjdiwWPi5iPoZOkk6CRnZCdj56Nn4sIq4sFpougg5x8m3yTd4txCIuJBZd8kHuLd4uHi4eLh5J+jn6LfIuEi4SJhZR9kHyLeot3hHp8fH19eoR3iwhYiwWVeI95i3mLdIh6hH6EfoKBfoV+hX2He4uBi4OPg5KFkYaTh5SHlYiTipOKk4qTiJMIiZSIkYiPgZSBl4CaeKR+moSPCD2LBYCLg4+EkoSSh5SLlQiw9zgVi4aMh4+Ij4ePiZCLkIuPjY+Pjo6Nj4uQi5CJkIiOh4+HjYaLhouHiYeHh4iKhouGCNT7OBWUiwWOi46Kj4mPio+IjoiPh4+IjoePiI+Hj4aPho6HjoiNiI6Hj4aOho6Ii4qWfpKDj4YIk4ORgY5+j36OgI1/jYCPg5CGnYuXj5GUkpSOmYuei5aGmoKfgp6GmouWCPCLBZSLlI+SkpOTjpOLlYuSiZKHlIeUho+Fi46PjY+NkY2RjJCLkIuYhpaBlY6RjZKLkgiLkomSiJKIkoaQhY6MkIyRi5CLm4aXgpOBkn6Pe4sIZosFcotrhGN9iouIioaJh4qHiomKiYqIioaKh4mHioiKiYuHioiLh4qIi4mLCIKLi/tLBQ77lIv3txWLkpCPlo0I9yOgzPcWBY6SkI+RiwiL/BL7FUcFh4mHioiLh4uIjImOiY6KjouPi4yLjYyOCKP3IyPwBYaQiZCLjwgOi/fFFYu1l6yjoqOjrZe2i5aLl4mYh5eHloWWhJaElIWShZOEkoWShJKSkpGTkpKRlJGWkgiWkpaRl4+Yj5eNlou2i61/o3OjdJdqi2GLYXVgYGAI+0b7QAWHiIeJhouGi4eNh44I+0b3QAWJjYmNh4+IjoaRg5SElIWVhZSFlYaWh5mGmImYi5gIsIsVi2ucaa9oCPc6+zT3OvczBa+vnK2Lq4ubiZiHl4eXhpSFkoSSg5GCj4KQgo2CjYONgYuBi4KLgIl/hoCGgIWChAiBg4OFhISEhYaFhoaIhoaJhYuFi4aNiJCGkIaRhJGEkoORgZOCkoCRgJB/kICNgosIgYuBi4OJgomCiYKGgoeDhYSEhYSGgod/h3+Jfot7CA77JouyFYv4BAWLkY2Rj5GOkJCPko2PjY+Mj4sI98CLBY+Lj4qPiZGJkIePho+FjYWLhQiL/AQFi4SJhYeGh4aGh4WIiIqGioeLgYuEjoSRCPsS9w37EvsNBYSFg4iCi4eLh4uHjYSOho+IkIeQiZGLkgiwkxX3JvchpHL3DfsIi/f3+7iLi/v3BQ5ni8sVi/c5BYuSjpKQkJCQko6Siwj3VIuLwgWLrpippKSkpKmYrouvi6l+pHKkcpdti2gIi0IFi4aKhoeIh4eHiYaLCHmLBYaLh42Hj4eOipCLkAiL1AWLn4OcfZp9mXqSdot3i3qEfX18fIR6i3cIi1SniwWSi5KIkIaQho6Ei4QIi/s5BYuDiIWGhoaFhImEiwj7p4sFhIuEjYaRhpCIkYuTCA5njPe6FYyQkI6UjQj3I6DM9xYFj5KPj5GLkIuQh4+ECMv7FvcjdgWUiZCIjYaNhoiFhYUIIyak+yMFjIWKhomHiYiIiYaLiIuHjIeNCPsUz/sVRwWHiYeKiIuHi4eNiY6Jj4uQjJEIo/cjI/AFhZGJkY2QCPeB+z0VnILlW3rxiJ6ZmNTS+wydgpxe54v7pwUOZ4vCFYv3SwWLkI2Pjo+Pjo+NkIsI3osFkIuPiY6Ij4eNh4uGCIv7SwWLhomHh4eIh4eKhosIOIsFhouHjIePiI+Jj4uQCLCvFYuGjIePh46IkImQi5CLj42Pjo6PjY+LkIuQiZCIjoePh42Gi4aLhomIh4eIioaLhgjvZxWL90sFi5CNj46Oj4+PjZCLj4ySkJWWlZaVl5SXmJuVl5GRjo6OkI6RjZCNkIyPjI6MkY2TCIySjJGMj4yPjZCOkY6RjpCPjo6Pj42Qi5SLk4qSiZKJkYiPiJCIjoiPho6GjYeMhwiNh4yGjIaMhYuHi4iLiIuHi4eLg4uEiYSJhImFiYeJh4mFh4WLioqJiomJiIqJiokIi4qKiIqJCNqLBZqLmIWWgJaAkH+LfIt6hn2Af46DjYSLhIt9h36Cf4+Bi3+HgImAhYKEhI12hnmAfgh/fXiDcosIZosFfot+jHyOfI5/joOOg41/j32Qc5N8j4SMhouHjYiOh4+Jj4uQCA5ni/c5FYuGjYaOiI+Hj4mQiwjeiwWQi4+Njo+Pjo2Qi5AIi/dKBYuQiZCHjoiPh42Giwg4iwWGi4eJh4eIiImGi4YIi/tKBbD3JhWLkIyPj4+OjpCNkIuQi4+Jj4iOh42Hi4aLhomHiIeHh4eKhouGi4aMiI+Hj4qPi5AI7/snFYv3SwWLkI2Qj46Oj4+NkIuSi5qPo5OZkJePk46TjZeOmo6ajpiMmIsIsIsFpIueg5d9ln6Qeol1koSRgo2Aj4CLgIeAlH+Pfot9i4WJhIiCloCQfIt7i3yFfoGACICAfoZ8iwg8iwWMiIyJi4mMiYyJjYmMiIyKi4mPhI2GjYeNh42GjYOMhIyEi4SLhouHi4iLiYuGioYIioWKhomHioeJh4iGh4eIh4aIh4iFiISJhImDioKLhouHjYiPh4+Ij4iRiJGJkIqPCIqPipGKkomTipGKj4qOiZCJkYiQiJCIjoWSgZZ+nIKXgZaBloGWhJGHi4aLh42HjwiIjomQi48IDviUFPiUFYsMCgAAAAADAgABkAAFAAABTAFmAAAARwFMAWYAAAD1ABkAhAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAEAAAPFlAeD/4P/gAeAAIAAAAAEAAAAAAAAAAAAAACAAAAAAAAIAAAADAAAAFAADAAEAAAAUAAQAkAAAACAAIAAEAAAAAQAg5gXwBvAN8CPwLvBu8HDwivCX8JzxI/Fl//3//wAAAAAAIOYA8ATwDPAj8C7wbvBw8Ifwl/Cc8SPxZP/9//8AAf/jGgQQBhABD+wP4g+jD6IPjA+AD3wO9g62AAMAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAEAAJrVlLJfDzz1AAsCAAAAAADP/GODAAAAAM/8Y4MAAP/bAgAB2wAAAAgAAgAAAAAAAAABAAAB4P/gAAACAAAAAAACAAABAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAEAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAdwAAAHcAAACAAAjAZMAHwFJAAABbgAAAgAAAAIAAAACAAAAAgAAAAEAAAACAAAAAW4AAAHcAAAB3AABAdwAAAHcAAAAAFAAABwAAAAAAA4ArgABAAAAAAABAAwAAAABAAAAAAACAA4AQAABAAAAAAADAAwAIgABAAAAAAAEAAwATgABAAAAAAAFABYADAABAAAAAAAGAAYALgABAAAAAAAKADQAWgADAAEECQABAAwAAAADAAEECQACAA4AQAADAAEECQADAAwAIgADAAEECQAEAAwATgADAAEECQAFABYADAADAAEECQAGAAwANAADAAEECQAKADQAWgByAGEAdABpAG4AZwBWAGUAcgBzAGkAbwBuACAAMQAuADAAcgBhAHQAaQBuAGdyYXRpbmcAcgBhAHQAaQBuAGcAUgBlAGcAdQBsAGEAcgByAGEAdABpAG4AZwBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('woff'); + font-weight: normal; + font-style: normal; +} + +.ui.rating .icon { + font-family: 'Rating'; + line-height: 1; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + font-weight: normal; + font-style: normal; + text-align: center; +} + +/* Empty Star */ + +.ui.rating .icon:before { + content: '\f005'; +} + +/* Active Star */ + +.ui.rating .active.icon:before { + content: '\f005'; +} + +/*------------------- + Star +--------------------*/ + +/* Unfilled Star */ + +.ui.star.rating .icon:before { + content: '\f005'; +} + +/* Active Star */ + +.ui.star.rating .active.icon:before { + content: '\f005'; +} + +/* Partial */ + +.ui.star.rating .partial.icon:before { + content: '\f006'; +} + +.ui.star.rating .partial.icon { + content: '\f005'; +} + +/*------------------- + Heart +--------------------*/ + +/* Empty Heart +.ui.heart.rating .icon:before { + content: '\f08a'; +} +*/ + +.ui.heart.rating .icon:before { + content: '\f004'; +} + +/* Active */ + +.ui.heart.rating .active.icon:before { + content: '\f004'; +} + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Search + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Search +*******************************/ + +.ui.search { + position: relative; +} + +.ui.search > .prompt { + margin: 0em; + outline: none; + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); + text-shadow: none; + font-style: normal; + font-weight: normal; + line-height: 1.21428571em; + padding: 0.67857143em 1em; + font-size: 1em; + background: #FFFFFF; + border: 1px solid rgba(34, 36, 38, 0.15); + color: rgba(0, 0, 0, 0.87); + box-shadow: 0em 0em 0em 0em transparent inset; + -webkit-transition: background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, border-color 0.1s ease; + transition: background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, border-color 0.1s ease; +} + +.ui.search .prompt { + border-radius: 500rem; +} + +/*-------------- + Icon +---------------*/ + +.ui.search .prompt ~ .search.icon { + cursor: pointer; +} + +/*-------------- + Results +---------------*/ + +.ui.search > .results { + display: none; + position: absolute; + top: 100%; + left: 0%; + -webkit-transform-origin: center top; + transform-origin: center top; + white-space: normal; + background: #FFFFFF; + margin-top: 0.5em; + width: 18em; + border-radius: 0.28571429rem; + box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); + border: 1px solid #D4D4D5; + z-index: 998; +} + +.ui.search > .results > :first-child { + border-radius: 0.28571429rem 0.28571429rem 0em 0em; +} + +.ui.search > .results > :last-child { + border-radius: 0em 0em 0.28571429rem 0.28571429rem; +} + +/*-------------- + Result +---------------*/ + +.ui.search > .results .result { + cursor: pointer; + display: block; + overflow: hidden; + font-size: 1em; + padding: 0.85714286em 1.14285714em; + color: rgba(0, 0, 0, 0.87); + line-height: 1.33; + border-bottom: 1px solid rgba(34, 36, 38, 0.1); +} + +.ui.search > .results .result:last-child { + border-bottom: none !important; +} + +/* Image */ + +.ui.search > .results .result .image { + float: right; + overflow: hidden; + background: none; + width: 5em; + height: 3em; + border-radius: 0.25em; +} + +.ui.search > .results .result .image img { + display: block; + width: auto; + height: 100%; +} + +/*-------------- + Info +---------------*/ + +.ui.search > .results .result .image + .content { + margin: 0em 6em 0em 0em; +} + +.ui.search > .results .result .title { + margin: -0.14285714em 0em 0em; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-weight: bold; + font-size: 1em; + color: rgba(0, 0, 0, 0.85); +} + +.ui.search > .results .result .description { + margin-top: 0; + font-size: 0.92857143em; + color: rgba(0, 0, 0, 0.4); +} + +.ui.search > .results .result .price { + float: right; + color: #21BA45; +} + +/*-------------- + Message +---------------*/ + +.ui.search > .results > .message { + padding: 1em 1em; +} + +.ui.search > .results > .message .header { + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 1rem; + font-weight: bold; + color: rgba(0, 0, 0, 0.87); +} + +.ui.search > .results > .message .description { + margin-top: 0.25rem; + font-size: 1em; + color: rgba(0, 0, 0, 0.87); +} + +/* View All Results */ + +.ui.search > .results > .action { + display: block; + border-top: none; + background: #F3F4F5; + padding: 0.92857143em 1em; + color: rgba(0, 0, 0, 0.87); + font-weight: bold; + text-align: center; +} + +/******************************* + States +*******************************/ + +/*-------------------- + Focus +---------------------*/ + +.ui.search > .prompt:focus { + border-color: rgba(34, 36, 38, 0.35); + background: #FFFFFF; + color: rgba(0, 0, 0, 0.95); +} + +/*-------------------- + Loading +---------------------*/ + +.ui.loading.search .input > i.icon:before { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.1); +} + +.ui.loading.search .input > i.icon:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + margin: -0.64285714em 0em 0em -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + -webkit-animation: button-spin 0.6s linear; + animation: button-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 transparent transparent; + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; +} + +/*-------------- + Hover +---------------*/ + +.ui.search > .results .result:hover, +.ui.category.search > .results .category .result:hover { + background: #F9FAFB; +} + +.ui.search .action:hover { + background: #E0E0E0; +} + +/*-------------- + Active +---------------*/ + +.ui.category.search > .results .category.active { + background: #F3F4F5; +} + +.ui.category.search > .results .category.active > .name { + color: rgba(0, 0, 0, 0.87); +} + +.ui.search > .results .result.active, +.ui.category.search > .results .category .result.active { + position: relative; + border-left-color: rgba(34, 36, 38, 0.1); + background: #F3F4F5; + box-shadow: none; +} + +.ui.search > .results .result.active .title { + color: rgba(0, 0, 0, 0.85); +} + +.ui.search > .results .result.active .description { + color: rgba(0, 0, 0, 0.85); +} + +/******************************* + Types +*******************************/ + +/*-------------- + Selection +---------------*/ + +.ui.search.selection .prompt { + border-radius: 0.28571429rem; +} + +/* Remove input */ + +.ui.search.selection > .icon.input > .remove.icon { + pointer-events: none; + position: absolute; + left: auto; + opacity: 0; + color: ''; + top: 0em; + right: 0em; + -webkit-transition: color 0.1s ease, opacity 0.1s ease; + transition: color 0.1s ease, opacity 0.1s ease; +} + +.ui.search.selection > .icon.input > .active.remove.icon { + cursor: pointer; + opacity: 0.8; + pointer-events: auto; +} + +.ui.search.selection > .icon.input:not([class*="left icon"]) > .icon ~ .remove.icon { + right: 1.85714em; +} + +.ui.search.selection > .icon.input > .remove.icon:hover { + opacity: 1; + color: #DB2828; +} + +/*-------------- + Category +---------------*/ + +.ui.category.search .results { + width: 28em; +} + +/* Category */ + +.ui.category.search > .results .category { + background: #F3F4F5; + box-shadow: none; + border-bottom: 1px solid rgba(34, 36, 38, 0.1); + -webkit-transition: background 0.1s ease, border-color 0.1s ease; + transition: background 0.1s ease, border-color 0.1s ease; +} + +/* Last Category */ + +.ui.category.search > .results .category:last-child { + border-bottom: none; +} + +/* First / Last */ + +.ui.category.search > .results .category:first-child .name + .result { + border-radius: 0em 0.28571429rem 0em 0em; +} + +.ui.category.search > .results .category:last-child .result:last-child { + border-radius: 0em 0em 0.28571429rem 0em; +} + +/* Category Result */ + +.ui.category.search > .results .category .result { + background: #FFFFFF; + margin-left: 100px; + border-left: 1px solid rgba(34, 36, 38, 0.15); + border-bottom: 1px solid rgba(34, 36, 38, 0.1); + -webkit-transition: background 0.1s ease, border-color 0.1s ease; + transition: background 0.1s ease, border-color 0.1s ease; + padding: 0.85714286em 1.14285714em; +} + +.ui.category.search > .results .category:last-child .result:last-child { + border-bottom: none; +} + +/* Category Result Name */ + +.ui.category.search > .results .category > .name { + width: 100px; + background: transparent; + font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; + font-size: 1em; + float: 1em; + float: left; + padding: 0.4em 1em; + font-weight: bold; + color: rgba(0, 0, 0, 0.4); +} + +/******************************* + Variations +*******************************/ + +/*------------------- + Left / Right +--------------------*/ + +.ui[class*="left aligned"].search > .results { + right: auto; + left: 0%; +} + +.ui[class*="right aligned"].search > .results { + right: 0%; + left: auto; +} + +/*-------------- + Fluid +---------------*/ + +.ui.fluid.search .results { + width: 100%; +} + +/*-------------- + Sizes +---------------*/ + +.ui.mini.search { + font-size: 0.78571429em; +} + +.ui.small.search { + font-size: 0.92857143em; +} + +.ui.search { + font-size: 1em; +} + +.ui.large.search { + font-size: 1.14285714em; +} + +.ui.big.search { + font-size: 1.28571429em; +} + +.ui.huge.search { + font-size: 1.42857143em; +} + +.ui.massive.search { + font-size: 1.71428571em; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Shape + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Shape +*******************************/ + +.ui.shape { + position: relative; + vertical-align: top; + display: inline-block; + -webkit-perspective: 2000px; + perspective: 2000px; + -webkit-transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; + transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; +} + +.ui.shape .sides { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; +} + +.ui.shape .side { + opacity: 1; + width: 100%; + margin: 0em !important; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} + +.ui.shape .side { + display: none; +} + +.ui.shape .side * { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; +} + +/******************************* + Types +*******************************/ + +.ui.cube.shape .side { + min-width: 15em; + height: 15em; + padding: 2em; + background-color: #E6E6E6; + color: rgba(0, 0, 0, 0.87); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.3); +} + +.ui.cube.shape .side > .content { + width: 100%; + height: 100%; + display: table; + text-align: center; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.ui.cube.shape .side > .content > div { + display: table-cell; + vertical-align: middle; + font-size: 2em; +} + +/******************************* + Variations +*******************************/ + +.ui.text.shape.animating .sides { + position: static; +} + +.ui.text.shape .side { + white-space: nowrap; +} + +.ui.text.shape .side > * { + white-space: normal; +} + +/******************************* + States +*******************************/ + +/*-------------- + Loading +---------------*/ + +.ui.loading.shape { + position: absolute; + top: -9999px; + left: -9999px; +} + +/*-------------- + Animating +---------------*/ + +.ui.shape .animating.side { + position: absolute; + top: 0px; + left: 0px; + display: block; + z-index: 100; +} + +.ui.shape .hidden.side { + opacity: 0.6; +} + +/*-------------- + CSS +---------------*/ + +.ui.shape.animating .sides { + position: absolute; +} + +.ui.shape.animating .sides { + -webkit-transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; + transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; +} + +.ui.shape.animating .side { + -webkit-transition: opacity 0.6s ease-in-out; + transition: opacity 0.6s ease-in-out; +} + +/*-------------- + Active +---------------*/ + +.ui.shape .active.side { + display: block; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Sidebar + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Sidebar +*******************************/ + +/* Sidebar Menu */ + +.ui.sidebar { + position: fixed; + top: 0; + left: 0; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transition: none; + transition: none; + will-change: transform; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + visibility: hidden; + -webkit-overflow-scrolling: touch; + height: 100% !important; + max-height: 100%; + border-radius: 0em !important; + margin: 0em !important; + overflow-y: auto !important; + z-index: 102; +} + +/* GPU Layers for Child Elements */ + +.ui.sidebar > * { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} + +/*-------------- + Direction +---------------*/ + +.ui.left.sidebar { + right: auto; + left: 0px; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); +} + +.ui.right.sidebar { + right: 0px !important; + left: auto !important; + -webkit-transform: translate3d(100%, 0%, 0); + transform: translate3d(100%, 0%, 0); +} + +.ui.top.sidebar, +.ui.bottom.sidebar { + width: 100% !important; + height: auto !important; +} + +.ui.top.sidebar { + top: 0px !important; + bottom: auto !important; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); +} + +.ui.bottom.sidebar { + top: auto !important; + bottom: 0px !important; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); +} + +/*-------------- + Pushable +---------------*/ + +.pushable { + height: 100%; + overflow-x: hidden; + padding: 0em !important; +} + +/* Whole Page */ + +body.pushable { + background: #545454 !important; +} + +/* Page Context */ + +.pushable:not(body) { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} + +.pushable:not(body) > .ui.sidebar, +.pushable:not(body) > .fixed, +.pushable:not(body) > .pusher:after { + position: absolute; +} + +/*-------------- + Fixed +---------------*/ + +.pushable > .fixed { + position: fixed; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; + will-change: transform; + z-index: 101; +} + +/*-------------- + Page +---------------*/ + +.pushable > .pusher { + position: relative; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + overflow: hidden; + min-height: 100%; + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; + z-index: 2; +} + +body.pushable > .pusher { + background: #FFFFFF; +} + +/* Pusher should inherit background from context */ + +.pushable > .pusher { + background: inherit; +} + +/*-------------- + Dimmer +---------------*/ + +.pushable > .pusher:after { + position: fixed; + top: 0px; + right: 0px; + content: ''; + background-color: rgba(0, 0, 0, 0.4); + overflow: hidden; + opacity: 0; + -webkit-transition: opacity 500ms; + transition: opacity 500ms; + will-change: opacity; + z-index: 1000; +} + +/*-------------- + Coupling +---------------*/ + +.ui.sidebar.menu .item { + border-radius: 0em !important; +} + +/******************************* + States +*******************************/ + +/*-------------- + Dimmed +---------------*/ + +.pushable > .pusher.dimmed:after { + width: 100% !important; + height: 100% !important; + opacity: 1 !important; +} + +/*-------------- + Animating +---------------*/ + +.ui.animating.sidebar { + visibility: visible; +} + +/*-------------- + Visible +---------------*/ + +.ui.visible.sidebar { + visibility: visible; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} + +/* Shadow Direction */ + +.ui.left.visible.sidebar, +.ui.right.visible.sidebar { + box-shadow: 0px 0px 20px rgba(34, 36, 38, 0.15); +} + +.ui.top.visible.sidebar, +.ui.bottom.visible.sidebar { + box-shadow: 0px 0px 20px rgba(34, 36, 38, 0.15); +} + +/* Visible On Load */ + +.ui.visible.left.sidebar ~ .fixed, +.ui.visible.left.sidebar ~ .pusher { + -webkit-transform: translate3d(260px, 0, 0); + transform: translate3d(260px, 0, 0); +} + +.ui.visible.right.sidebar ~ .fixed, +.ui.visible.right.sidebar ~ .pusher { + -webkit-transform: translate3d(-260px, 0, 0); + transform: translate3d(-260px, 0, 0); +} + +.ui.visible.top.sidebar ~ .fixed, +.ui.visible.top.sidebar ~ .pusher { + -webkit-transform: translate3d(0, 36px, 0); + transform: translate3d(0, 36px, 0); +} + +.ui.visible.bottom.sidebar ~ .fixed, +.ui.visible.bottom.sidebar ~ .pusher { + -webkit-transform: translate3d(0, -36px, 0); + transform: translate3d(0, -36px, 0); +} + +/* opposite sides visible forces content overlay */ + +.ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .fixed, +.ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher, +.ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .fixed, +.ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} + +/*-------------- + iOS +---------------*/ + +/* + iOS incorrectly sizes document when content + is presented outside of view with 2Dtranslate +*/ + +html.ios { + overflow-x: hidden; + -webkit-overflow-scrolling: touch; +} + +/******************************* + Variations +*******************************/ + +/*-------------- + Width +---------------*/ + +/* Left / Right */ + +.ui.thin.left.sidebar, +.ui.thin.right.sidebar { + width: 150px; +} + +.ui[class*="very thin"].left.sidebar, +.ui[class*="very thin"].right.sidebar { + width: 60px; +} + +.ui.left.sidebar, +.ui.right.sidebar { + width: 260px; +} + +.ui.wide.left.sidebar, +.ui.wide.right.sidebar { + width: 350px; +} + +.ui[class*="very wide"].left.sidebar, +.ui[class*="very wide"].right.sidebar { + width: 475px; +} + +/* Left Visible */ + +.ui.visible.thin.left.sidebar ~ .fixed, +.ui.visible.thin.left.sidebar ~ .pusher { + -webkit-transform: translate3d(150px, 0, 0); + transform: translate3d(150px, 0, 0); +} + +.ui.visible[class*="very thin"].left.sidebar ~ .fixed, +.ui.visible[class*="very thin"].left.sidebar ~ .pusher { + -webkit-transform: translate3d(60px, 0, 0); + transform: translate3d(60px, 0, 0); +} + +.ui.visible.wide.left.sidebar ~ .fixed, +.ui.visible.wide.left.sidebar ~ .pusher { + -webkit-transform: translate3d(350px, 0, 0); + transform: translate3d(350px, 0, 0); +} + +.ui.visible[class*="very wide"].left.sidebar ~ .fixed, +.ui.visible[class*="very wide"].left.sidebar ~ .pusher { + -webkit-transform: translate3d(475px, 0, 0); + transform: translate3d(475px, 0, 0); +} + +/* Right Visible */ + +.ui.visible.thin.right.sidebar ~ .fixed, +.ui.visible.thin.right.sidebar ~ .pusher { + -webkit-transform: translate3d(-150px, 0, 0); + transform: translate3d(-150px, 0, 0); +} + +.ui.visible[class*="very thin"].right.sidebar ~ .fixed, +.ui.visible[class*="very thin"].right.sidebar ~ .pusher { + -webkit-transform: translate3d(-60px, 0, 0); + transform: translate3d(-60px, 0, 0); +} + +.ui.visible.wide.right.sidebar ~ .fixed, +.ui.visible.wide.right.sidebar ~ .pusher { + -webkit-transform: translate3d(-350px, 0, 0); + transform: translate3d(-350px, 0, 0); +} + +.ui.visible[class*="very wide"].right.sidebar ~ .fixed, +.ui.visible[class*="very wide"].right.sidebar ~ .pusher { + -webkit-transform: translate3d(-475px, 0, 0); + transform: translate3d(-475px, 0, 0); +} + +/******************************* + Animations +*******************************/ + +/*-------------- + Overlay +---------------*/ + +/* Set-up */ + +.ui.overlay.sidebar { + z-index: 102; +} + +/* Initial */ + +.ui.left.overlay.sidebar { + -webkit-transform: translate3d(-100%, 0%, 0); + transform: translate3d(-100%, 0%, 0); +} + +.ui.right.overlay.sidebar { + -webkit-transform: translate3d(100%, 0%, 0); + transform: translate3d(100%, 0%, 0); +} + +.ui.top.overlay.sidebar { + -webkit-transform: translate3d(0%, -100%, 0); + transform: translate3d(0%, -100%, 0); +} + +.ui.bottom.overlay.sidebar { + -webkit-transform: translate3d(0%, 100%, 0); + transform: translate3d(0%, 100%, 0); +} + +/* Animation */ + +.animating.ui.overlay.sidebar, +.ui.visible.overlay.sidebar { + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; +} + +/* End - Sidebar */ + +.ui.visible.left.overlay.sidebar { + -webkit-transform: translate3d(0%, 0%, 0); + transform: translate3d(0%, 0%, 0); +} + +.ui.visible.right.overlay.sidebar { + -webkit-transform: translate3d(0%, 0%, 0); + transform: translate3d(0%, 0%, 0); +} + +.ui.visible.top.overlay.sidebar { + -webkit-transform: translate3d(0%, 0%, 0); + transform: translate3d(0%, 0%, 0); +} + +.ui.visible.bottom.overlay.sidebar { + -webkit-transform: translate3d(0%, 0%, 0); + transform: translate3d(0%, 0%, 0); +} + +/* End - Pusher */ + +.ui.visible.overlay.sidebar ~ .fixed, +.ui.visible.overlay.sidebar ~ .pusher { + -webkit-transform: none !important; + transform: none !important; +} + +/*-------------- + Push +---------------*/ + +/* Initial */ + +.ui.push.sidebar { + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; + z-index: 102; +} + +/* Sidebar - Initial */ + +.ui.left.push.sidebar { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); +} + +.ui.right.push.sidebar { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); +} + +.ui.top.push.sidebar { + -webkit-transform: translate3d(0%, -100%, 0); + transform: translate3d(0%, -100%, 0); +} + +.ui.bottom.push.sidebar { + -webkit-transform: translate3d(0%, 100%, 0); + transform: translate3d(0%, 100%, 0); +} + +/* End */ + +.ui.visible.push.sidebar { + -webkit-transform: translate3d(0%, 0, 0); + transform: translate3d(0%, 0, 0); +} + +/*-------------- + Uncover +---------------*/ + +/* Initial */ + +.ui.uncover.sidebar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + z-index: 1; +} + +/* End */ + +.ui.visible.uncover.sidebar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; +} + +/*-------------- + Slide Along +---------------*/ + +/* Initial */ + +.ui.slide.along.sidebar { + z-index: 1; +} + +/* Sidebar - Initial */ + +.ui.left.slide.along.sidebar { + -webkit-transform: translate3d(-50%, 0, 0); + transform: translate3d(-50%, 0, 0); +} + +.ui.right.slide.along.sidebar { + -webkit-transform: translate3d(50%, 0, 0); + transform: translate3d(50%, 0, 0); +} + +.ui.top.slide.along.sidebar { + -webkit-transform: translate3d(0, -50%, 0); + transform: translate3d(0, -50%, 0); +} + +.ui.bottom.slide.along.sidebar { + -webkit-transform: translate3d(0%, 50%, 0); + transform: translate3d(0%, 50%, 0); +} + +/* Animation */ + +.ui.animating.slide.along.sidebar { + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; +} + +/* End */ + +.ui.visible.slide.along.sidebar { + -webkit-transform: translate3d(0%, 0, 0); + transform: translate3d(0%, 0, 0); +} + +/*-------------- + Slide Out +---------------*/ + +/* Initial */ + +.ui.slide.out.sidebar { + z-index: 1; +} + +/* Sidebar - Initial */ + +.ui.left.slide.out.sidebar { + -webkit-transform: translate3d(50%, 0, 0); + transform: translate3d(50%, 0, 0); +} + +.ui.right.slide.out.sidebar { + -webkit-transform: translate3d(-50%, 0, 0); + transform: translate3d(-50%, 0, 0); +} + +.ui.top.slide.out.sidebar { + -webkit-transform: translate3d(0%, 50%, 0); + transform: translate3d(0%, 50%, 0); +} + +.ui.bottom.slide.out.sidebar { + -webkit-transform: translate3d(0%, -50%, 0); + transform: translate3d(0%, -50%, 0); +} + +/* Animation */ + +.ui.animating.slide.out.sidebar { + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; +} + +/* End */ + +.ui.visible.slide.out.sidebar { + -webkit-transform: translate3d(0%, 0, 0); + transform: translate3d(0%, 0, 0); +} + +/*-------------- + Scale Down +---------------*/ + +/* Initial */ + +.ui.scale.down.sidebar { + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; + z-index: 102; +} + +/* Sidebar - Initial */ + +.ui.left.scale.down.sidebar { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); +} + +.ui.right.scale.down.sidebar { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); +} + +.ui.top.scale.down.sidebar { + -webkit-transform: translate3d(0%, -100%, 0); + transform: translate3d(0%, -100%, 0); +} + +.ui.bottom.scale.down.sidebar { + -webkit-transform: translate3d(0%, 100%, 0); + transform: translate3d(0%, 100%, 0); +} + +/* Pusher - Initial */ + +.ui.scale.down.left.sidebar ~ .pusher { + -webkit-transform-origin: 75% 50%; + transform-origin: 75% 50%; +} + +.ui.scale.down.right.sidebar ~ .pusher { + -webkit-transform-origin: 25% 50%; + transform-origin: 25% 50%; +} + +.ui.scale.down.top.sidebar ~ .pusher { + -webkit-transform-origin: 50% 75%; + transform-origin: 50% 75%; +} + +.ui.scale.down.bottom.sidebar ~ .pusher { + -webkit-transform-origin: 50% 25%; + transform-origin: 50% 25%; +} + +/* Animation */ + +.ui.animating.scale.down > .visible.ui.sidebar { + -webkit-transition: -webkit-transform 500ms ease; + transition: -webkit-transform 500ms ease; + transition: transform 500ms ease; + transition: transform 500ms ease, -webkit-transform 500ms ease; +} + +.ui.visible.scale.down.sidebar ~ .pusher, +.ui.animating.scale.down.sidebar ~ .pusher { + display: block !important; + width: 100%; + height: 100%; + overflow: hidden !important; +} + +/* End */ + +.ui.visible.scale.down.sidebar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} + +.ui.visible.scale.down.sidebar ~ .pusher { + -webkit-transform: scale(0.75); + transform: scale(0.75); +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Sticky + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Sticky +*******************************/ + +.ui.sticky { + position: static; + -webkit-transition: none; + transition: none; + z-index: 800; +} + +/******************************* + States +*******************************/ + +/* Bound */ + +.ui.sticky.bound { + position: absolute; + left: auto; + right: auto; +} + +/* Fixed */ + +.ui.sticky.fixed { + position: fixed; + left: auto; + right: auto; +} + +/* Bound/Fixed Position */ + +.ui.sticky.bound.top, +.ui.sticky.fixed.top { + top: 0px; + bottom: auto; +} + +.ui.sticky.bound.bottom, +.ui.sticky.fixed.bottom { + top: auto; + bottom: 0px; +} + +/******************************* + Types +*******************************/ + +.ui.native.sticky { + position: -webkit-sticky; + position: -moz-sticky; + position: -ms-sticky; + position: -o-sticky; + position: sticky; +} + +/******************************* + Theme Overrides +*******************************/ + +/******************************* + Site Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Tab + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + UI Tabs +*******************************/ + +.ui.tab { + display: none; +} + +/******************************* + States +*******************************/ + +/*-------------------- + Active +---------------------*/ + +.ui.tab.active, +.ui.tab.open { + display: block; +} + +/*-------------------- + Loading +---------------------*/ + +.ui.tab.loading { + position: relative; + overflow: hidden; + display: block; + min-height: 250px; +} + +.ui.tab.loading * { + position: relative !important; + left: -10000px !important; +} + +.ui.tab.loading:before, +.ui.tab.loading.segment:before { + position: absolute; + content: ''; + top: 100px; + left: 50%; + margin: -1.25em 0em 0em -1.25em; + width: 2.5em; + height: 2.5em; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.1); +} + +.ui.tab.loading:after, +.ui.tab.loading.segment:after { + position: absolute; + content: ''; + top: 100px; + left: 50%; + margin: -1.25em 0em 0em -1.25em; + width: 2.5em; + height: 2.5em; + -webkit-animation: button-spin 0.6s linear; + animation: button-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #767676 transparent transparent; + border-style: solid; + border-width: 0.2em; + box-shadow: 0px 0px 0px 1px transparent; +} + +/******************************* + Tab Overrides +*******************************/ + +/******************************* + User Overrides +*******************************/ +/*! + * # Semantic UI 2.2.10 - Transition + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +/******************************* + Transitions +*******************************/ + +.transition { + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + -webkit-animation-duration: 300ms; + animation-duration: 300ms; + -webkit-animation-timing-function: ease; + animation-timing-function: ease; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +/******************************* + States +*******************************/ + +/* Animating */ + +.animating.transition { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + visibility: visible !important; +} + +/* Loading */ + +.loading.transition { + position: absolute; + top: -99999px; + left: -99999px; +} + +/* Hidden */ + +.hidden.transition { + display: none; + visibility: hidden; +} + +/* Visible */ + +.visible.transition { + display: block !important; + visibility: visible !important; + /* backface-visibility: @backfaceVisibility; + transform: @use3DAcceleration;*/ +} + +/* Disabled */ + +.disabled.transition { + -webkit-animation-play-state: paused; + animation-play-state: paused; +} + +/******************************* + Variations +*******************************/ + +.looping.transition { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +/******************************* + Transitions +*******************************/ + +/* + Some transitions adapted from Animate CSS + https://github.com/daneden/animate.css + + Additional transitions adapted from Glide + by Nick Pettit - https://github.com/nickpettit/glide +*/ + +/*-------------- + Browse +---------------*/ + +.transition.browse { + -webkit-animation-duration: 500ms; + animation-duration: 500ms; +} + +.transition.browse.in { + -webkit-animation-name: browseIn; + animation-name: browseIn; +} + +.transition.browse.out, +.transition.browse.left.out { + -webkit-animation-name: browseOutLeft; + animation-name: browseOutLeft; +} + +.transition.browse.right.out { + -webkit-animation-name: browseOutRight; + animation-name: browseOutRight; +} + +/* In */ + +@-webkit-keyframes browseIn { + 0% { + -webkit-transform: scale(0.8) translateZ(0px); + transform: scale(0.8) translateZ(0px); + z-index: -1; + } + + 10% { + -webkit-transform: scale(0.8) translateZ(0px); + transform: scale(0.8) translateZ(0px); + z-index: -1; + opacity: 0.7; + } + + 80% { + -webkit-transform: scale(1.05) translateZ(0px); + transform: scale(1.05) translateZ(0px); + opacity: 1; + z-index: 999; + } + + 100% { + -webkit-transform: scale(1) translateZ(0px); + transform: scale(1) translateZ(0px); + z-index: 999; + } +} + +@keyframes browseIn { + 0% { + -webkit-transform: scale(0.8) translateZ(0px); + transform: scale(0.8) translateZ(0px); + z-index: -1; + } + + 10% { + -webkit-transform: scale(0.8) translateZ(0px); + transform: scale(0.8) translateZ(0px); + z-index: -1; + opacity: 0.7; + } + + 80% { + -webkit-transform: scale(1.05) translateZ(0px); + transform: scale(1.05) translateZ(0px); + opacity: 1; + z-index: 999; + } + + 100% { + -webkit-transform: scale(1) translateZ(0px); + transform: scale(1) translateZ(0px); + z-index: 999; + } +} + +/* Out */ + +@-webkit-keyframes browseOutLeft { + 0% { + z-index: 999; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg); + transform: translateX(0%) rotateY(0deg) rotateX(0deg); + } + + 50% { + z-index: -1; + -webkit-transform: translateX(-105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + transform: translateX(-105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + } + + 80% { + opacity: 1; + } + + 100% { + z-index: -1; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + opacity: 0; + } +} + +@keyframes browseOutLeft { + 0% { + z-index: 999; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg); + transform: translateX(0%) rotateY(0deg) rotateX(0deg); + } + + 50% { + z-index: -1; + -webkit-transform: translateX(-105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + transform: translateX(-105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + } + + 80% { + opacity: 1; + } + + 100% { + z-index: -1; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + opacity: 0; + } +} + +@-webkit-keyframes browseOutRight { + 0% { + z-index: 999; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg); + transform: translateX(0%) rotateY(0deg) rotateX(0deg); + } + + 50% { + z-index: 1; + -webkit-transform: translateX(105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + transform: translateX(105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + } + + 80% { + opacity: 1; + } + + 100% { + z-index: 1; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + opacity: 0; + } +} + +@keyframes browseOutRight { + 0% { + z-index: 999; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg); + transform: translateX(0%) rotateY(0deg) rotateX(0deg); + } + + 50% { + z-index: 1; + -webkit-transform: translateX(105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + transform: translateX(105%) rotateY(35deg) rotateX(10deg) translateZ(-10px); + } + + 80% { + opacity: 1; + } + + 100% { + z-index: 1; + -webkit-transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + transform: translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px); + opacity: 0; + } +} + +/*-------------- + Drop +---------------*/ + +.drop.transition { + -webkit-transform-origin: top center; + transform-origin: top center; + -webkit-animation-duration: 400ms; + animation-duration: 400ms; + -webkit-animation-timing-function: cubic-bezier(0.34, 1.61, 0.7, 1); + animation-timing-function: cubic-bezier(0.34, 1.61, 0.7, 1); +} + +.drop.transition.in { + -webkit-animation-name: dropIn; + animation-name: dropIn; +} + +.drop.transition.out { + -webkit-animation-name: dropOut; + animation-name: dropOut; +} + +/* Drop */ + +@-webkit-keyframes dropIn { + 0% { + opacity: 0; + -webkit-transform: scale(0); + transform: scale(0); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes dropIn { + 0% { + opacity: 0; + -webkit-transform: scale(0); + transform: scale(0); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@-webkit-keyframes dropOut { + 0% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(0); + transform: scale(0); + } +} + +@keyframes dropOut { + 0% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(0); + transform: scale(0); + } +} + +/*-------------- + Fade +---------------*/ + +.transition.fade.in { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +.transition[class*="fade up"].in { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +.transition[class*="fade down"].in { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +.transition[class*="fade left"].in { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +.transition[class*="fade right"].in { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +.transition.fade.out { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +.transition[class*="fade up"].out { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +.transition[class*="fade down"].out { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +.transition[class*="fade left"].out { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +.transition[class*="fade right"].out { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +/* In */ + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(10%); + transform: translateY(10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(10%); + transform: translateY(10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } +} + +@-webkit-keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-10%); + transform: translateY(-10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } +} + +@keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-10%); + transform: translateY(-10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } +} + +@-webkit-keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(10%); + transform: translateX(10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(10%); + transform: translateX(10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } +} + +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(-10%); + transform: translateX(-10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(-10%); + transform: translateX(-10%); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } +} + +/* Out */ + +@-webkit-keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@-webkit-keyframes fadeOutUp { + 0% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(5%); + transform: translateY(5%); + } +} + +@keyframes fadeOutUp { + 0% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(5%); + transform: translateY(5%); + } +} + +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-5%); + transform: translateY(-5%); + } +} + +@keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0%); + transform: translateY(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-5%); + transform: translateY(-5%); + } +} + +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(5%); + transform: translateX(5%); + } +} + +@keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(5%); + transform: translateX(5%); + } +} + +@-webkit-keyframes fadeOutRight { + 0% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-5%); + transform: translateX(-5%); + } +} + +@keyframes fadeOutRight { + 0% { + opacity: 1; + -webkit-transform: translateX(0%); + transform: translateX(0%); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-5%); + transform: translateX(-5%); + } +} + +/*-------------- + Flips +---------------*/ + +.flip.transition.in, +.flip.transition.out { + -webkit-animation-duration: 600ms; + animation-duration: 600ms; +} + +.horizontal.flip.transition.in { + -webkit-animation-name: horizontalFlipIn; + animation-name: horizontalFlipIn; +} + +.horizontal.flip.transition.out { + -webkit-animation-name: horizontalFlipOut; + animation-name: horizontalFlipOut; +} + +.vertical.flip.transition.in { + -webkit-animation-name: verticalFlipIn; + animation-name: verticalFlipIn; +} + +.vertical.flip.transition.out { + -webkit-animation-name: verticalFlipOut; + animation-name: verticalFlipOut; +} + +/* In */ + +@-webkit-keyframes horizontalFlipIn { + 0% { + -webkit-transform: perspective(2000px) rotateY(-90deg); + transform: perspective(2000px) rotateY(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform: perspective(2000px) rotateY(0deg); + transform: perspective(2000px) rotateY(0deg); + opacity: 1; + } +} + +@keyframes horizontalFlipIn { + 0% { + -webkit-transform: perspective(2000px) rotateY(-90deg); + transform: perspective(2000px) rotateY(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform: perspective(2000px) rotateY(0deg); + transform: perspective(2000px) rotateY(0deg); + opacity: 1; + } +} + +@-webkit-keyframes verticalFlipIn { + 0% { + -webkit-transform: perspective(2000px) rotateX(-90deg); + transform: perspective(2000px) rotateX(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform: perspective(2000px) rotateX(0deg); + transform: perspective(2000px) rotateX(0deg); + opacity: 1; + } +} + +@keyframes verticalFlipIn { + 0% { + -webkit-transform: perspective(2000px) rotateX(-90deg); + transform: perspective(2000px) rotateX(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform: perspective(2000px) rotateX(0deg); + transform: perspective(2000px) rotateX(0deg); + opacity: 1; + } +} + +/* Out */ + +@-webkit-keyframes horizontalFlipOut { + 0% { + -webkit-transform: perspective(2000px) rotateY(0deg); + transform: perspective(2000px) rotateY(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(2000px) rotateY(90deg); + transform: perspective(2000px) rotateY(90deg); + opacity: 0; + } +} + +@keyframes horizontalFlipOut { + 0% { + -webkit-transform: perspective(2000px) rotateY(0deg); + transform: perspective(2000px) rotateY(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(2000px) rotateY(90deg); + transform: perspective(2000px) rotateY(90deg); + opacity: 0; + } +} + +@-webkit-keyframes verticalFlipOut { + 0% { + -webkit-transform: perspective(2000px) rotateX(0deg); + transform: perspective(2000px) rotateX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(2000px) rotateX(-90deg); + transform: perspective(2000px) rotateX(-90deg); + opacity: 0; + } +} + +@keyframes verticalFlipOut { + 0% { + -webkit-transform: perspective(2000px) rotateX(0deg); + transform: perspective(2000px) rotateX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(2000px) rotateX(-90deg); + transform: perspective(2000px) rotateX(-90deg); + opacity: 0; + } +} + +/*-------------- + Scale +---------------*/ + +.scale.transition.in { + -webkit-animation-name: scaleIn; + animation-name: scaleIn; +} + +.scale.transition.out { + -webkit-animation-name: scaleOut; + animation-name: scaleOut; +} + +@-webkit-keyframes scaleIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.8); + transform: scale(0.8); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes scaleIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.8); + transform: scale(0.8); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +/* Out */ + +@-webkit-keyframes scaleOut { + 0% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(0.9); + transform: scale(0.9); + } +} + +@keyframes scaleOut { + 0% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(0.9); + transform: scale(0.9); + } +} + +/*-------------- + Fly +---------------*/ + +/* Inward */ + +.transition.fly { + -webkit-animation-duration: 0.6s; + animation-duration: 0.6s; + -webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); +} + +.transition.fly.in { + -webkit-animation-name: flyIn; + animation-name: flyIn; +} + +.transition[class*="fly up"].in { + -webkit-animation-name: flyInUp; + animation-name: flyInUp; +} + +.transition[class*="fly down"].in { + -webkit-animation-name: flyInDown; + animation-name: flyInDown; +} + +.transition[class*="fly left"].in { + -webkit-animation-name: flyInLeft; + animation-name: flyInLeft; +} + +.transition[class*="fly right"].in { + -webkit-animation-name: flyInRight; + animation-name: flyInRight; +} + +/* Outward */ + +.transition.fly.out { + -webkit-animation-name: flyOut; + animation-name: flyOut; +} + +.transition[class*="fly up"].out { + -webkit-animation-name: flyOutUp; + animation-name: flyOutUp; +} + +.transition[class*="fly down"].out { + -webkit-animation-name: flyOutDown; + animation-name: flyOutDown; +} + +.transition[class*="fly left"].out { + -webkit-animation-name: flyOutLeft; + animation-name: flyOutLeft; +} + +.transition[class*="fly right"].out { + -webkit-animation-name: flyOutRight; + animation-name: flyOutRight; +} + +/* In */ + +@-webkit-keyframes flyIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + + 100% { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes flyIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + + 100% { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@-webkit-keyframes flyInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 1500px, 0); + transform: translate3d(0, 1500px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes flyInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 1500px, 0); + transform: translate3d(0, 1500px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@-webkit-keyframes flyInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -1500px, 0); + transform: translate3d(0, -1500px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes flyInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -1500px, 0); + transform: translate3d(0, -1500px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes flyInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(1500px, 0, 0); + transform: translate3d(1500px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes flyInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(1500px, 0, 0); + transform: translate3d(1500px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes flyInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(-1500px, 0, 0); + transform: translate3d(-1500px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes flyInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(-1500px, 0, 0); + transform: translate3d(-1500px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +/* Out */ + +@-webkit-keyframes flyOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 50%, 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} + +@keyframes flyOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 50%, 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} + +@-webkit-keyframes flyOutUp { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes flyOutUp { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@-webkit-keyframes flyOutDown { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes flyOutDown { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@-webkit-keyframes flyOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes flyOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@-webkit-keyframes flyOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes flyOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +/*-------------- + Slide +---------------*/ + +.transition.slide.in, +.transition[class*="slide down"].in { + -webkit-animation-name: slideInY; + animation-name: slideInY; + -webkit-transform-origin: top center; + transform-origin: top center; +} + +.transition[class*="slide up"].in { + -webkit-animation-name: slideInY; + animation-name: slideInY; + -webkit-transform-origin: bottom center; + transform-origin: bottom center; +} + +.transition[class*="slide left"].in { + -webkit-animation-name: slideInX; + animation-name: slideInX; + -webkit-transform-origin: center right; + transform-origin: center right; +} + +.transition[class*="slide right"].in { + -webkit-animation-name: slideInX; + animation-name: slideInX; + -webkit-transform-origin: center left; + transform-origin: center left; +} + +.transition.slide.out, +.transition[class*="slide down"].out { + -webkit-animation-name: slideOutY; + animation-name: slideOutY; + -webkit-transform-origin: top center; + transform-origin: top center; +} + +.transition[class*="slide up"].out { + -webkit-animation-name: slideOutY; + animation-name: slideOutY; + -webkit-transform-origin: bottom center; + transform-origin: bottom center; +} + +.transition[class*="slide left"].out { + -webkit-animation-name: slideOutX; + animation-name: slideOutX; + -webkit-transform-origin: center right; + transform-origin: center right; +} + +.transition[class*="slide right"].out { + -webkit-animation-name: slideOutX; + animation-name: slideOutX; + -webkit-transform-origin: center left; + transform-origin: center left; +} + +/* In */ + +@-webkit-keyframes slideInY { + 0% { + opacity: 0; + -webkit-transform: scaleY(0); + transform: scaleY(0); + } + + 100% { + opacity: 1; + -webkit-transform: scaleY(1); + transform: scaleY(1); + } +} + +@keyframes slideInY { + 0% { + opacity: 0; + -webkit-transform: scaleY(0); + transform: scaleY(0); + } + + 100% { + opacity: 1; + -webkit-transform: scaleY(1); + transform: scaleY(1); + } +} + +@-webkit-keyframes slideInX { + 0% { + opacity: 0; + -webkit-transform: scaleX(0); + transform: scaleX(0); + } + + 100% { + opacity: 1; + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} + +@keyframes slideInX { + 0% { + opacity: 0; + -webkit-transform: scaleX(0); + transform: scaleX(0); + } + + 100% { + opacity: 1; + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} + +/* Out */ + +@-webkit-keyframes slideOutY { + 0% { + opacity: 1; + -webkit-transform: scaleY(1); + transform: scaleY(1); + } + + 100% { + opacity: 0; + -webkit-transform: scaleY(0); + transform: scaleY(0); + } +} + +@keyframes slideOutY { + 0% { + opacity: 1; + -webkit-transform: scaleY(1); + transform: scaleY(1); + } + + 100% { + opacity: 0; + -webkit-transform: scaleY(0); + transform: scaleY(0); + } +} + +@-webkit-keyframes slideOutX { + 0% { + opacity: 1; + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + + 100% { + opacity: 0; + -webkit-transform: scaleX(0); + transform: scaleX(0); + } +} + +@keyframes slideOutX { + 0% { + opacity: 1; + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + + 100% { + opacity: 0; + -webkit-transform: scaleX(0); + transform: scaleX(0); + } +} + +/*-------------- + Swing +---------------*/ + +.transition.swing { + -webkit-animation-duration: 800ms; + animation-duration: 800ms; +} + +.transition[class*="swing down"].in { + -webkit-animation-name: swingInX; + animation-name: swingInX; + -webkit-transform-origin: top center; + transform-origin: top center; +} + +.transition[class*="swing up"].in { + -webkit-animation-name: swingInX; + animation-name: swingInX; + -webkit-transform-origin: bottom center; + transform-origin: bottom center; +} + +.transition[class*="swing left"].in { + -webkit-animation-name: swingInY; + animation-name: swingInY; + -webkit-transform-origin: center right; + transform-origin: center right; +} + +.transition[class*="swing right"].in { + -webkit-animation-name: swingInY; + animation-name: swingInY; + -webkit-transform-origin: center left; + transform-origin: center left; +} + +.transition.swing.out, +.transition[class*="swing down"].out { + -webkit-animation-name: swingOutX; + animation-name: swingOutX; + -webkit-transform-origin: top center; + transform-origin: top center; +} + +.transition[class*="swing up"].out { + -webkit-animation-name: swingOutX; + animation-name: swingOutX; + -webkit-transform-origin: bottom center; + transform-origin: bottom center; +} + +.transition[class*="swing left"].out { + -webkit-animation-name: swingOutY; + animation-name: swingOutY; + -webkit-transform-origin: center right; + transform-origin: center right; +} + +.transition[class*="swing right"].out { + -webkit-animation-name: swingOutY; + animation-name: swingOutY; + -webkit-transform-origin: center left; + transform-origin: center left; +} + +/* In */ + +@-webkit-keyframes swingInX { + 0% { + -webkit-transform: perspective(1000px) rotateX(90deg); + transform: perspective(1000px) rotateX(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(1000px) rotateX(-30deg); + transform: perspective(1000px) rotateX(-30deg); + opacity: 1; + } + + 60% { + -webkit-transform: perspective(1000px) rotateX(15deg); + transform: perspective(1000px) rotateX(15deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateX(-7.5deg); + transform: perspective(1000px) rotateX(-7.5deg); + } + + 100% { + -webkit-transform: perspective(1000px) rotateX(0deg); + transform: perspective(1000px) rotateX(0deg); + } +} + +@keyframes swingInX { + 0% { + -webkit-transform: perspective(1000px) rotateX(90deg); + transform: perspective(1000px) rotateX(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(1000px) rotateX(-30deg); + transform: perspective(1000px) rotateX(-30deg); + opacity: 1; + } + + 60% { + -webkit-transform: perspective(1000px) rotateX(15deg); + transform: perspective(1000px) rotateX(15deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateX(-7.5deg); + transform: perspective(1000px) rotateX(-7.5deg); + } + + 100% { + -webkit-transform: perspective(1000px) rotateX(0deg); + transform: perspective(1000px) rotateX(0deg); + } +} + +@-webkit-keyframes swingInY { + 0% { + -webkit-transform: perspective(1000px) rotateY(-90deg); + transform: perspective(1000px) rotateY(-90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(1000px) rotateY(30deg); + transform: perspective(1000px) rotateY(30deg); + opacity: 1; + } + + 60% { + -webkit-transform: perspective(1000px) rotateY(-17.5deg); + transform: perspective(1000px) rotateY(-17.5deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateY(7.5deg); + transform: perspective(1000px) rotateY(7.5deg); + } + + 100% { + -webkit-transform: perspective(1000px) rotateY(0deg); + transform: perspective(1000px) rotateY(0deg); + } +} + +@keyframes swingInY { + 0% { + -webkit-transform: perspective(1000px) rotateY(-90deg); + transform: perspective(1000px) rotateY(-90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(1000px) rotateY(30deg); + transform: perspective(1000px) rotateY(30deg); + opacity: 1; + } + + 60% { + -webkit-transform: perspective(1000px) rotateY(-17.5deg); + transform: perspective(1000px) rotateY(-17.5deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateY(7.5deg); + transform: perspective(1000px) rotateY(7.5deg); + } + + 100% { + -webkit-transform: perspective(1000px) rotateY(0deg); + transform: perspective(1000px) rotateY(0deg); + } +} + +/* Out */ + +@-webkit-keyframes swingOutX { + 0% { + -webkit-transform: perspective(1000px) rotateX(0deg); + transform: perspective(1000px) rotateX(0deg); + } + + 40% { + -webkit-transform: perspective(1000px) rotateX(-7.5deg); + transform: perspective(1000px) rotateX(-7.5deg); + } + + 60% { + -webkit-transform: perspective(1000px) rotateX(17.5deg); + transform: perspective(1000px) rotateX(17.5deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateX(-30deg); + transform: perspective(1000px) rotateX(-30deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(1000px) rotateX(90deg); + transform: perspective(1000px) rotateX(90deg); + opacity: 0; + } +} + +@keyframes swingOutX { + 0% { + -webkit-transform: perspective(1000px) rotateX(0deg); + transform: perspective(1000px) rotateX(0deg); + } + + 40% { + -webkit-transform: perspective(1000px) rotateX(-7.5deg); + transform: perspective(1000px) rotateX(-7.5deg); + } + + 60% { + -webkit-transform: perspective(1000px) rotateX(17.5deg); + transform: perspective(1000px) rotateX(17.5deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateX(-30deg); + transform: perspective(1000px) rotateX(-30deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(1000px) rotateX(90deg); + transform: perspective(1000px) rotateX(90deg); + opacity: 0; + } +} + +@-webkit-keyframes swingOutY { + 0% { + -webkit-transform: perspective(1000px) rotateY(0deg); + transform: perspective(1000px) rotateY(0deg); + } + + 40% { + -webkit-transform: perspective(1000px) rotateY(7.5deg); + transform: perspective(1000px) rotateY(7.5deg); + } + + 60% { + -webkit-transform: perspective(1000px) rotateY(-10deg); + transform: perspective(1000px) rotateY(-10deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateY(30deg); + transform: perspective(1000px) rotateY(30deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(1000px) rotateY(-90deg); + transform: perspective(1000px) rotateY(-90deg); + opacity: 0; + } +} + +@keyframes swingOutY { + 0% { + -webkit-transform: perspective(1000px) rotateY(0deg); + transform: perspective(1000px) rotateY(0deg); + } + + 40% { + -webkit-transform: perspective(1000px) rotateY(7.5deg); + transform: perspective(1000px) rotateY(7.5deg); + } + + 60% { + -webkit-transform: perspective(1000px) rotateY(-10deg); + transform: perspective(1000px) rotateY(-10deg); + } + + 80% { + -webkit-transform: perspective(1000px) rotateY(30deg); + transform: perspective(1000px) rotateY(30deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(1000px) rotateY(-90deg); + transform: perspective(1000px) rotateY(-90deg); + opacity: 0; + } +} + +/******************************* + Static Animations +*******************************/ + +/*-------------- + Emphasis +---------------*/ + +.flash.transition { + -webkit-animation-duration: 750ms; + animation-duration: 750ms; + -webkit-animation-name: flash; + animation-name: flash; +} + +.shake.transition { + -webkit-animation-duration: 750ms; + animation-duration: 750ms; + -webkit-animation-name: shake; + animation-name: shake; +} + +.bounce.transition { + -webkit-animation-duration: 750ms; + animation-duration: 750ms; + -webkit-animation-name: bounce; + animation-name: bounce; +} + +.tada.transition { + -webkit-animation-duration: 750ms; + animation-duration: 750ms; + -webkit-animation-name: tada; + animation-name: tada; +} + +.pulse.transition { + -webkit-animation-duration: 500ms; + animation-duration: 500ms; + -webkit-animation-name: pulse; + animation-name: pulse; +} + +.jiggle.transition { + -webkit-animation-duration: 750ms; + animation-duration: 750ms; + -webkit-animation-name: jiggle; + animation-name: jiggle; +} + +/* Flash */ + +@-webkit-keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +@keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +/* Shake */ + +@-webkit-keyframes shake { + 0%, 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translateX(-10px); + transform: translateX(-10px); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translateX(10px); + transform: translateX(10px); + } +} + +@keyframes shake { + 0%, 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translateX(-10px); + transform: translateX(-10px); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translateX(10px); + transform: translateX(10px); + } +} + +/* Bounce */ + +@-webkit-keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 40% { + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + + 60% { + -webkit-transform: translateY(-15px); + transform: translateY(-15px); + } +} + +@keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 40% { + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + + 60% { + -webkit-transform: translateY(-15px); + transform: translateY(-15px); + } +} + +/* Tada */ + +@-webkit-keyframes tada { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 10%, 20% { + -webkit-transform: scale(0.9) rotate(-3deg); + transform: scale(0.9) rotate(-3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale(1.1) rotate(-3deg); + transform: scale(1.1) rotate(-3deg); + } + + 100% { + -webkit-transform: scale(1) rotate(0); + transform: scale(1) rotate(0); + } +} + +@keyframes tada { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 10%, 20% { + -webkit-transform: scale(0.9) rotate(-3deg); + transform: scale(0.9) rotate(-3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale(1.1) rotate(-3deg); + transform: scale(1.1) rotate(-3deg); + } + + 100% { + -webkit-transform: scale(1) rotate(0); + transform: scale(1) rotate(0); + } +} + +/* Pulse */ + +@-webkit-keyframes pulse { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + + 50% { + -webkit-transform: scale(0.9); + transform: scale(0.9); + opacity: 0.7; + } + + 100% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} + +@keyframes pulse { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + + 50% { + -webkit-transform: scale(0.9); + transform: scale(0.9); + opacity: 0.7; + } + + 100% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} + +/* Rubberband */ + +@-webkit-keyframes jiggle { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes jiggle { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +/******************************* + Site Overrides +*******************************/ diff --git a/front/src/semantic/themes/default/assets/fonts/icons.eot b/front/src/semantic/themes/default/assets/fonts/icons.eot new file mode 100644 index 000000000..e9f60ca95 Binary files /dev/null and b/front/src/semantic/themes/default/assets/fonts/icons.eot differ diff --git a/front/src/semantic/themes/default/assets/fonts/icons.otf b/front/src/semantic/themes/default/assets/fonts/icons.otf new file mode 100644 index 000000000..f7936cc1e Binary files /dev/null and b/front/src/semantic/themes/default/assets/fonts/icons.otf differ diff --git a/front/src/semantic/themes/default/assets/fonts/icons.svg b/front/src/semantic/themes/default/assets/fonts/icons.svg new file mode 100644 index 000000000..855c845e5 --- /dev/null +++ b/front/src/semantic/themes/default/assets/fonts/icons.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/front/src/semantic/themes/default/assets/fonts/icons.ttf b/front/src/semantic/themes/default/assets/fonts/icons.ttf new file mode 100644 index 000000000..35acda2fa Binary files /dev/null and b/front/src/semantic/themes/default/assets/fonts/icons.ttf differ diff --git a/front/src/semantic/themes/default/assets/fonts/icons.woff b/front/src/semantic/themes/default/assets/fonts/icons.woff new file mode 100644 index 000000000..400014a4b Binary files /dev/null and b/front/src/semantic/themes/default/assets/fonts/icons.woff differ diff --git a/front/src/semantic/themes/default/assets/fonts/icons.woff2 b/front/src/semantic/themes/default/assets/fonts/icons.woff2 new file mode 100644 index 000000000..4d13fc604 Binary files /dev/null and b/front/src/semantic/themes/default/assets/fonts/icons.woff2 differ diff --git a/front/src/semantic/themes/default/assets/images/flags.png b/front/src/semantic/themes/default/assets/images/flags.png new file mode 100755 index 000000000..cdd33c3bc Binary files /dev/null and b/front/src/semantic/themes/default/assets/images/flags.png differ diff --git a/front/static/.gitkeep b/front/static/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/front/test/e2e/custom-assertions/elementCount.js b/front/test/e2e/custom-assertions/elementCount.js new file mode 100644 index 000000000..c0d5fe00a --- /dev/null +++ b/front/test/e2e/custom-assertions/elementCount.js @@ -0,0 +1,26 @@ +// A custom Nightwatch assertion. +// the name of the method is the filename. +// can be used in tests like this: +// +// browser.assert.elementCount(selector, count) +// +// for how to write custom assertions see +// http://nightwatchjs.org/guide#writing-custom-assertions +exports.assertion = function (selector, count) { + this.message = 'Testing if element <' + selector + '> has count: ' + count + this.expected = count + this.pass = function (val) { + return val === this.expected + } + this.value = function (res) { + return res.value + } + this.command = function (cb) { + var self = this + return this.api.execute(function (selector) { + return document.querySelectorAll(selector).length + }, [selector], function (res) { + cb.call(self, res) + }) + } +} diff --git a/front/test/e2e/nightwatch.conf.js b/front/test/e2e/nightwatch.conf.js new file mode 100644 index 000000000..f019c0ac4 --- /dev/null +++ b/front/test/e2e/nightwatch.conf.js @@ -0,0 +1,46 @@ +require('babel-register') +var config = require('../../config') + +// http://nightwatchjs.org/gettingstarted#settings-file +module.exports = { + src_folders: ['test/e2e/specs'], + output_folder: 'test/e2e/reports', + custom_assertions_path: ['test/e2e/custom-assertions'], + + selenium: { + start_process: true, + server_path: require('selenium-server').path, + host: '127.0.0.1', + port: 4444, + cli_args: { + 'webdriver.chrome.driver': require('chromedriver').path + } + }, + + test_settings: { + default: { + selenium_port: 4444, + selenium_host: 'localhost', + silent: true, + globals: { + devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + javascriptEnabled: true, + acceptSslCerts: true + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + javascriptEnabled: true, + acceptSslCerts: true + } + } + } +} diff --git a/front/test/e2e/runner.js b/front/test/e2e/runner.js new file mode 100644 index 000000000..85d67d6ba --- /dev/null +++ b/front/test/e2e/runner.js @@ -0,0 +1,33 @@ +// 1. start the dev server using production config +process.env.NODE_ENV = 'testing' +var server = require('../../build/dev-server.js') + +server.ready.then(() => { + // 2. run the nightwatch test suite against it + // to run in additional browsers: + // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" + // 2. add it to the --env flag below + // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` + // For more information on Nightwatch's config file, see + // http://nightwatchjs.org/guide#settings-file + var opts = process.argv.slice(2) + if (opts.indexOf('--config') === -1) { + opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) + } + if (opts.indexOf('--env') === -1) { + opts = opts.concat(['--env', 'chrome']) + } + + var spawn = require('cross-spawn') + var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) + + runner.on('exit', function (code) { + server.close() + process.exit(code) + }) + + runner.on('error', function (err) { + server.close() + throw err + }) +}) diff --git a/front/test/e2e/specs/test.js b/front/test/e2e/specs/test.js new file mode 100644 index 000000000..a7b1bd920 --- /dev/null +++ b/front/test/e2e/specs/test.js @@ -0,0 +1,19 @@ +// For authoring Nightwatch tests, see +// http://nightwatchjs.org/guide#usage + +module.exports = { + 'default e2e tests': function (browser) { + // automatically uses dev Server port from /config.index.js + // default: http://localhost:8080 + // see nightwatch.conf.js + const devServer = browser.globals.devServerURL + + browser + .url(devServer) + .waitForElementVisible('#app', 5000) + .assert.elementPresent('.hello') + .assert.containsText('h1', 'Welcome to Your Vue.js App') + .assert.elementCount('img', 1) + .end() + } +} diff --git a/front/test/unit/.eslintrc b/front/test/unit/.eslintrc new file mode 100644 index 000000000..959a4f4b5 --- /dev/null +++ b/front/test/unit/.eslintrc @@ -0,0 +1,9 @@ +{ + "env": { + "mocha": true + }, + "globals": { + "expect": true, + "sinon": true + } +} diff --git a/front/test/unit/index.js b/front/test/unit/index.js new file mode 100644 index 000000000..c69f33fd8 --- /dev/null +++ b/front/test/unit/index.js @@ -0,0 +1,13 @@ +import Vue from 'vue' + +Vue.config.productionTip = false + +// require all test files (files that ends with .spec.js) +const testsContext = require.context('./specs', true, /\.spec$/) +testsContext.keys().forEach(testsContext) + +// require all src files except main.js for coverage. +// you can also change this to match only the subset of files that +// you want coverage for. +const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) +srcContext.keys().forEach(srcContext) diff --git a/front/test/unit/karma.conf.js b/front/test/unit/karma.conf.js new file mode 100644 index 000000000..8e4951c9e --- /dev/null +++ b/front/test/unit/karma.conf.js @@ -0,0 +1,33 @@ +// This is a karma config file. For more details see +// http://karma-runner.github.io/0.13/config/configuration-file.html +// we are also using it with karma-webpack +// https://github.com/webpack/karma-webpack + +var webpackConfig = require('../../build/webpack.test.conf') + +module.exports = function (config) { + config.set({ + // to run in additional browsers: + // 1. install corresponding karma launcher + // http://karma-runner.github.io/0.13/config/browsers.html + // 2. add it to the `browsers` array below. + browsers: ['PhantomJS'], + frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'], + reporters: ['spec', 'coverage'], + files: ['./index.js'], + preprocessors: { + './index.js': ['webpack', 'sourcemap'] + }, + webpack: webpackConfig, + webpackMiddleware: { + noInfo: true + }, + coverageReporter: { + dir: './coverage', + reporters: [ + { type: 'lcov', subdir: '.' }, + { type: 'text-summary' } + ] + } + }) +} diff --git a/front/test/unit/specs/Hello.spec.js b/front/test/unit/specs/Hello.spec.js new file mode 100644 index 000000000..80140baa9 --- /dev/null +++ b/front/test/unit/specs/Hello.spec.js @@ -0,0 +1,11 @@ +import Vue from 'vue' +import Hello from '@/components/Hello' + +describe('Hello.vue', () => { + it('should render correct contents', () => { + const Constructor = Vue.extend(Hello) + const vm = new Constructor().$mount() + expect(vm.$el.querySelector('.hello h1').textContent) + .to.equal('Welcome to Your Vue.js App') + }) +})