diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..6d4a3893bdf6019ddf4d2b48c16c12c3c9dc3511 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,24 @@ +# Tested target system is Debian Buster + +variables: + POSTGRES_DB: coin + POSTGRES_USER: coin + POSTGRES_PASSWORD: coin + # https://gitlab.com/gitlab-com/support-forum/issues/5199 + POSTGRES_HOST_AUTH_METHOD: trust + + TZ: "Europe/Paris" + DJANGO_SETTINGS_MODULE: coin.settings_gitlab_ci + +before_script: + - echo 'fr_FR.UTF-8 UTF-8' >> /etc/locale.gen + - apt-get update -qq + - apt-get install -qq -y --no-install-recommends libsasl2-dev python-dev libldap2-dev libssl-dev + - pip install -r requirements.txt pytest-django + - pip freeze # debug + +unit_tests_debian_10: + image: python:2.7-buster + services: + - postgres:11.10 + script: py.test diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..1ec550b9927a92613d840d91065f5a2ee3790f82 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM python:2.7-buster + +ENV DEBIAN_FRONTEND noninteractive +ENV TZ="Europe/Paris" +ENV LC_ALL fr_FR.UTF-8 + +RUN apt-get update \ + && apt-get install -y --no-install-recommends libsasl2-dev python-dev libldap2-dev libssl-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /coin +COPY . . +RUN pip install -r requirements.txt + +RUN useradd --uid 10001 --user-group --shell /bin/bash coin +RUN chown coin:coin /coin + +USER coin:coin + +VOLUME ["/coin"] diff --git a/EXTENDING.md b/EXTENDING.md index 77ec0aeb5d31e9a0ec7f8e39c950a9f9bcca8cf8..8e5972b532f515688a8a9890315c3a06e6806ebc 100644 --- a/EXTENDING.md +++ b/EXTENDING.md @@ -188,7 +188,7 @@ Example: {% extends "base.html" %} {% block extra_css %}{% endblock %} - {% block extra_js %}{% endblock %} + {% block extra_js %}{{ block.super }}{% endblock %} Menu items diff --git a/README.md b/README.md index 137221d0d74906bdb6b9de90b661e2e29f55b3f8..f63eacf851dfe4f4a47754a9f156ff18dae958ec 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ The COIN project ================ -`Coin` is Illyse's Information System, designed to manage both members -and Internet accesses, such as through DSL, VPN, wireless… - +COIN is an Information System designed for associative ISPs in the FFDN. ![example of a coin user view : the subscriptions list](doc/_img/user-subscriptions.png) -It is written in Django, and features a generic configuration interface, -which allows to implement custom backends for different technologies. -Currently implemented is a LDAP-based backend for OpenVPN, and a very -simple DSL backend, without any authentication (useful for "white label" -DSL). +It is written in Django, and features : +- a generic configuration interface that correspond to services provided to members +- subscriptions management +- and the corresponding billing / payment handling system -Coin currently only works with python2, because `python-ldap` is (as of -2013) not compatible with python3. +COIN can can be interfaced with the actual infrastructure to fetch the state of +services (e.g. VPS, VPN, ...) and provision them via hooks defined in the +settings. The project page (issue, wiki, etc) is here: @@ -84,84 +82,52 @@ settings: See the end of this README for a reference of available configuration settings. -Database --------- - -At this point, you should setup your database. You have two options. - -### With PostgreSQL (for developpement), recomended - -The official database for coin is postgresql. - -To ease developpement, a postgresql virtual-machine recipe is provided -through [vagrant](https://vagrantup.com). - - -**Note: Vagrant is intended for developpement only and is totaly unsafe for a -production setup**. - -Install requirements: - - sudo apt install virtualbox vagrant - -Then, to boot and configure your dev VM: - - vagrant up - -Default settings target that vagrant+postgreSQL setup, so, you don't have to -change any setting. - - -### With SQLite - -SQLite setup may be simpler, but some features will not be available, namely: +Development +----------- -- automatic allocation of IP subnets (needs proper subnet implementation in - the database) -- sending automated emails to remind of expiring membership fee - (needs aggregation on date fields, see Django doc) +A Dockerfile + docker-compose.yml is provided **for development purposes only**. -To use sqlite instead of PostgreSQL, you have -to [override local settings](#settings) with someting like: +- Install Docker according to Docker's documentation : https://docs.docker.com/engine/install/ (or by running `apt install docker`) +- Validate that docker is running with `sudo systemctl status docker` +- You may need to add your user to the docker group to be able to run docker commands as non-root: -```python -DATABASES = { - # Base de donnée du SI - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'coin.sqlite3', - 'USER': '', # Not needed for SQLite - 'PASSWORD': '', # Not needed for SQLite - 'HOST': '', # Empty for localhost through domain sockets - 'PORT': '', # Empty for default - }, -} +``` +sudo usermod -aG docker $USER +# Then you need to reload your entire session (not just the terminal) for this to propagate... +# or maybe running this command does the trick: newgrp docker ``` -### For both PostgreSQL and SQLite - -The first time, you need to create the database, create a superuser, and -import some base data to play with: - - python manage.py migrate - python manage.py createsuperuser - python manage.py loaddata offers ip_pool # skip this if you don't use PostgreSQL +- Install docker-compose: `sudo pip3 install docker-compose` +- Run `docker-compose up` ... the first time this will download and build a whole bunch of stuff +- You can access your app through http://localhost:8000/ +- Misc tips: -Note that the superuser will be inserted into the LDAP backend exactly in the -same way as all other members, so you should use a real account (not just -admin/admin). +``` +# Launch docker-compose up, but in background +docker-compose up -d -Then, at each code update, you will only need to update dependencies and apply -new migrations: +# Check container logs after startup +docker-compose logs -f coin - pip install -r requirements.txt - python manage.py migrate +# Stop / relaunch the container +docker-compose stop +docker-compose up +# Regen and apply migrations +# (ugly hack: the user coin can't write in the mounted folder ... so gotta run this as root..) +docker-compose exec -u root coin python manage.py makemigrations +docker-compose exec coin python manage.py migrate -At this point, Django should run correctly: +# Enter a shell inside the container +docker-compose exec coin bash +``` - python manage.py runserver +- At some point you will want to initialize the admin and a bunch of dummy data : +``` +docker-compose exec coin python manage.py fill_with_toy_data +docker-compose exec coin python manage.py changepassword admin +``` Running tests ------------- @@ -397,10 +363,12 @@ MEMBERSHIP_FEE_REMINDER_DATES = [ - `MEMBERSHIP_REFERENCE` : Template string to display the label the member should indicates for the bank transfer, default: "ADH-{{ user.pk }}" - `DEFAULT_MEMBERSHIP_FEE` : Default membership fee, if you have a more complex membership fees policy, you could overwrite templates - `PAYMENT_DELAY`: Payment delay in days for issued invoices ( default is 30 days which is the default in french law) +- `MEMBER_TERMS` : You can ask for new user to accept a terms during registration. (example: 'J\'ai lu les statuts de l\'association' ) - `MEMBER_CAN_EDIT_PROFILE`: Allow members to edit their profiles - `HANDLE_BALANCE`: Allows to handle money balances for members (False default) - `INVOICES_INCLUDE_CONFIG_COMMENTS`: Add comment related to a subscription configuration when generating invoices - `MEMBER_CAN_EDIT_VPN_CONF`: Allow members to edit some part of their vpn configuration +- `IP_ALLOCATION_MESSAGE`: Template string that will be used to log IP allocation in the corresponding coin.subnets logging system, defaults to `None` which is disabled logging, full example : `"{ip} to {member.pk} ({member.username} - {member.first_name} {member.last_name}) (for offer {offer}, {ref})"` - `DEBUG` : Enable debug for development **do not use in production** : display stracktraces and enable [django-debug-toolbar](https://django-debug-toolbar.readthedocs.io). - `SITE_TITLE`: the base of site title (displayed in browser window/tab title) @@ -421,18 +389,6 @@ See also [using optional apps](#using-optional-apps). - `{email}`: the mail address of the list - `{short_name}`: the list name -#### vpn - -- `VPN_SECRETS_TRANSMISSION_METHOD` : how are VPN secrets transmited to - subscriber ? Two values are currently supported : - - `gen-password-and-forget` (default, used by Illyse) : generate a - password, push it to LDAP (which holds VPN auth), displays it to user and - forget it. - - `crypto-link` (used by ARN) : credentials are generated by an admin - outside coin, and put on an encrypted burn-after-reading web page, whom - URL is filled-in coin. - - Accounting logs --------------- @@ -453,9 +409,13 @@ LOGGING["handlers"]["coin_accounting"] = { LOGGING["loggers"]["coin.billing"]["handlers"] = [ 'coin_accounting' ] ``` -More information -================ +External account +--------------- -For the rest of the setup (database, LDAP), see https://doc.illyse.net/projects/ils-si/wiki/Mise_en_place_environnement_de_dev + - `VERBOSE_NAME_EXTERNAL_ACCOUNT` : This label is display in the member subscription view (ARN put this to 'Compte sans-nuage') + - `VERBOSE_NAME_PLURAL_EXTERNAL_ACCOUNT` : same for plural + +Deployment +========== For real production deployment, see file `DEPLOYMENT.md`. diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100644 index 6a325f8f098767f339303b03465d9a1361d8907f..0000000000000000000000000000000000000000 --- a/Vagrantfile +++ /dev/null @@ -1,53 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -Vagrant.configure("2") do |config| - - config.vm.box = 'debian/jessie64' - config.vm.host_name = 'postgresql' - - config.vm.provider "virtualbox" do |v| - v.customize ["modifyvm", :id, "--memory", 512] - end - - config.vm.network "forwarded_port", guest: 5432, host: 15432 - - config.vm.provision "shell", privileged: true, inline: <<-SHELL - APP_DB_USER=coin - APP_DB_NAME=coin - APP_DB_PASS=coin - - PG_VERSION=9.4 - PG_CONF="/etc/postgresql/$PG_VERSION/main/postgresql.conf" - PG_HBA="/etc/postgresql/$PG_VERSION/main/pg_hba.conf" - - apt-get -y update - apt-get install -y postgresql - - # Edit postgresql.conf to change listen address to '*': - sed -i "s/#listen_addresses = 'localhost'/listen_addresses = '*'/" "$PG_CONF" - - # Append to pg_hba.conf to add password auth: - echo "host all all all md5" >> "$PG_HBA" - - cat << EOF | su - postgres -c psql - -- Cleanup, if required - DROP DATABASE IF EXISTS $APP_DB_NAME; - DROP USER IF EXISTS $APP_DB_USER; - - -- Create the database user: - CREATE USER $APP_DB_USER WITH PASSWORD '$APP_DB_PASS'; - -- Allow db creation (usefull for unit testing) - ALTER USER $APP_DB_USER CREATEDB; - - -- Create the database: - CREATE DATABASE $APP_DB_NAME WITH OWNER=$APP_DB_USER - LC_COLLATE='en_US.utf8' - LC_CTYPE='en_US.utf8' - ENCODING='UTF8' - TEMPLATE=template0; -EOF - - systemctl restart postgresql - SHELL -end diff --git a/coin/admin.py b/coin/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..2c190dc39cc5356c2064db68502f138e42cce6ce --- /dev/null +++ b/coin/admin.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import apps +from django.contrib import admin + + +def collect_admin_cards(): + """ + Collects menu entries among apps and builds the admin main menu from it + + Collects in apps appconfigs, in two variables : + + AppConfig.admin_menu_entry for defining a full per-app menu entry + AppConfig.admin_menu_addons to add links to a shared menu entry + + Format for those vars can be found in apps.py files + """ + + admin_cards = [ + {"id": "configs", + "icon": "gears", + "title": "Configurations", + "models": [] + }, + + {"id": "infra", + "icon": "database", + "title": "Infra", + "models": [], + }, + ] + + # Menu entries that can receive addons + addons_containers = { + 'configs': admin_cards[0]['models'], + 'infra': admin_cards[1]['models'], + } + + for app_config in apps.get_app_configs(): + menu_entry = getattr(app_config, 'admin_menu_entry', None) + menu_addons = getattr(app_config, 'admin_menu_addons', None) + if menu_entry: + admin_cards.append(menu_entry) + + if menu_addons: + for entry_id, links in menu_addons.items(): + addons_containers[entry_id] += links + + return admin_cards + + +original_index = admin.site.index + +def new_index(request, extra_context=None): + extra_context = extra_context or {} + extra_context["admin_cards"] = collect_admin_cards() + return original_index(request, extra_context) + +admin.site.index = new_index diff --git a/coin/billing/admin.py b/coin/billing/admin.py index 2f9707b54d7217277bbe1332e6eea1ec20413538..3969933843835af3ed6f8e1eac1fe0b6fde6ee85 100644 --- a/coin/billing/admin.py +++ b/coin/billing/admin.py @@ -10,8 +10,11 @@ from django import forms from django.shortcuts import render from coin.filtering_queryset import LimitedAdminInlineMixin -from coin.billing.models import Invoice, InvoiceDetail, Payment, PaymentAllocation -from coin.billing.utils import get_invoice_from_id_or_number +from coin.billing.models import Invoice, InvoiceDetail, Payment, \ + PaymentAllocation, MembershipFee, Donation +from coin.billing.utils import get_bill_from_id_or_number +from coin.members.models import Member +from coin.members.admin import MemberAdmin from django.core.urlresolvers import reverse import autocomplete_light @@ -204,8 +207,8 @@ class InvoiceAdmin(admin.ModelAdmin): # TODO : Add better perm here if request.user.is_superuser: - invoice = get_invoice_from_id_or_number(id) - if invoice.amount() == 0: + invoice = get_bill_from_id_or_number(id) + if invoice.amount == 0: messages.error(request, 'Une facture validée ne peut pas avoir' ' un total de 0€.') else: @@ -223,8 +226,8 @@ class InvoiceAdmin(admin.ModelAdmin): class PaymentAllocationInlineReadOnly(admin.TabularInline): model = PaymentAllocation extra = 0 - fields = ("invoice", "amount") - readonly_fields = ("invoice", "amount") + fields = ("bill", "amount") + readonly_fields = ("bill", "amount") verbose_name = None verbose_name_plural = "Alloué à" @@ -245,8 +248,7 @@ class PaymentAdmin(admin.ModelAdmin): ('amount_already_allocated')) readonly_fields = ('amount_already_allocated',) list_filter = ['payment_mean'] - search_fields = ['member__username', 'member__first_name', - 'member__last_name', 'member__email', 'member__nickname'] + search_fields = ['member__username', 'member__first_name', 'member__last_name', 'member__email', 'member__nickname'] form = autocomplete_light.modelform_factory(Payment, fields='__all__') def get_readonly_fields(self, request, obj=None): @@ -271,7 +273,6 @@ class PaymentAdmin(admin.ModelAdmin): return my_urls + urls - def wizard_import_payment_csv(self, request): template = "admin/billing/payment/wizard_import_payment_csv.html" @@ -289,9 +290,15 @@ class PaymentAdmin(admin.ModelAdmin): 'adminform': form, 'opts': self.model._meta, 'new_payments': new_payments - }) + }) else: add_new_payments(new_payments) + + if "send_reminders" in request.POST: + members_to_remind = Member.objects.filter(balance__lt=0) + for member in members_to_remind: + member.send_reminder_negative_balance(auto=True) + return HttpResponseRedirect('../') else: form = WizardImportPaymentCSV() @@ -301,6 +308,18 @@ class PaymentAdmin(admin.ModelAdmin): 'opts': self.model._meta }) +class MembershipFeeAdmin(admin.ModelAdmin): + list_display = ('member', 'end_date', '_amount') + search_fields = ['member__username', 'member__first_name', 'member__last_name', 'member__email', 'member__nickname'] + list_filter = ['date'] + form = autocomplete_light.modelform_factory(MembershipFee, fields='__all__') + + +class DonationAdmin(admin.ModelAdmin): + list_display = ('member', 'date', '_amount') + form = autocomplete_light.modelform_factory(MembershipFee, fields='__all__') admin.site.register(Invoice, InvoiceAdmin) admin.site.register(Payment, PaymentAdmin) +admin.site.register(MembershipFee, MembershipFeeAdmin) +admin.site.register(Donation, DonationAdmin) diff --git a/coin/billing/app.py b/coin/billing/app.py index c1d0efa0b6f6e11b7dd7e7f77ecbda9a887d2810..13182f3f2848095d1bc300fda1544eb169f27d73 100644 --- a/coin/billing/app.py +++ b/coin/billing/app.py @@ -7,3 +7,15 @@ from django.apps import AppConfig class BillingConfig(AppConfig): name = 'coin.billing' verbose_name = 'Facturation' + + admin_menu_entry = { + "id": "billing", + "icon": "euro", + "title": "Facturation", + "models": [ + ("Cotisations", "billing/membershipfee"), + ("Dons", "billing/donation"), + ("Paiements", "billing/payment"), + ("Factures", "billing/invoice"), + ] + } diff --git a/coin/billing/create_subscriptions_invoices.py b/coin/billing/create_subscriptions_invoices.py index 3add25dccb9d75e2ba6921594f197ae8c2a3c47b..3891489c051d0d74e9b970f40552b57f83f490dd 100644 --- a/coin/billing/create_subscriptions_invoices.py +++ b/coin/billing/create_subscriptions_invoices.py @@ -13,7 +13,7 @@ from coin.members.models import Member from coin.billing.models import Invoice, InvoiceDetail from django.conf import settings -def create_all_members_invoices_for_a_period(date=None): +def create_all_members_invoices_for_a_period(date=None, antidate=False): """ Pour chaque membre ayant au moins un abonnement actif, génère les factures en prenant la date comme premier mois de la période de facturation @@ -27,14 +27,14 @@ def create_all_members_invoices_for_a_period(date=None): invoices = [] for member in members: - invoice = create_member_invoice_for_a_period(member, date) + invoice = create_member_invoice_for_a_period(member, date, antidate) if invoice is not None: invoices.append(invoice) return invoices @transaction.atomic -def create_member_invoice_for_a_period(member, date): +def create_member_invoice_for_a_period(member, date, antidate=False): """ Créé si nécessaire une facture pour un membre en prenant la date passée en paramètre comme premier mois de période. Renvoi la facture générée @@ -157,7 +157,12 @@ def create_member_invoice_for_a_period(member, date): if invoice.details.count() > 0: invoice.save() transaction.savepoint_commit(sid) - invoice.validate() # Valide la facture et génère le PDF + # Valide la facture et génère le PDF + invoice.date_due = None # (reset the due date, will automatically be redefined when validating, to date+PAYMENT_DELAY) + if antidate: + invoice.validate(period_to) + else: + invoice.validate() return invoice else: transaction.savepoint_rollback(sid) diff --git a/coin/billing/management/commands/charge_subscriptions.py b/coin/billing/management/commands/charge_subscriptions.py index e248f65d6f6b8174a81444a1f4fe91ac2f1361e1..a2327d3b82c6ca9eddade6ae1b1eb87eca04537e 100644 --- a/coin/billing/management/commands/charge_subscriptions.py +++ b/coin/billing/management/commands/charge_subscriptions.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- import datetime + +from argparse import RawTextHelpFormatter from django.core.management.base import BaseCommand, CommandError from django.conf import settings @@ -8,13 +10,39 @@ from coin.billing.create_subscriptions_invoices import create_all_members_invoic class Command(BaseCommand): - args = '[date=2011-07-04]' + help = 'Create invoices for members subscriptions for date specified (or today if no date passed)' + def create_parser(self, *args, **kwargs): + parser = super(Command, self).create_parser(*args, **kwargs) + parser.formatter_class = RawTextHelpFormatter + return parser + + def add_arguments(self, parser): + + parser.add_argument( + 'date', + type=str, + help="The date for the period for which to charge subscription (e.g. 2011-07-04)" + ) + + parser.add_argument( + '--antidate', + action='store_true', + dest='antidate', + default=False, + help="'Antidate' invoices, in the sense that invoices won't be validated with today's date but using the date of the end of the service. Meant to be use to charge subscription from a few months in the past..." + ) + + + def handle(self, *args, **options): verbosity = int(options['verbosity']) + antidate = options['antidate'] + date = options["date"] + try: - date = datetime.datetime.strptime(args[0], '%Y-%m-%d').date() + date = datetime.datetime.strptime(date, '%Y-%m-%d').date() except IndexError: date = datetime.date.today() except ValueError: @@ -25,7 +53,7 @@ class Command(BaseCommand): self.stdout.write( 'Create invoices for all members for the date : %s' % date) with respect_language(settings.LANGUAGE_CODE): - invoices = create_all_members_invoices_for_a_period(date) + invoices = create_all_members_invoices_for_a_period(date, antidate) if len(invoices) > 0 or verbosity >= 2: self.stdout.write( diff --git a/coin/billing/migrations/0001_initial.py b/coin/billing/migrations/0001_initial.py index 4a6edc9f29b9ad2e4d3141e71a299a8356afa427..474e66cf510c41eb5850f87ff992aa0660430702 100644 --- a/coin/billing/migrations/0001_initial.py +++ b/coin/billing/migrations/0001_initial.py @@ -23,7 +23,7 @@ class Migration(migrations.Migration): ('status', models.CharField(default='open', max_length=50, verbose_name='statut', choices=[('open', 'A payer'), ('closed', 'Regl\xe9e'), ('trouble', 'Litige')])), ('date', models.DateField(default=datetime.date.today, null=True, verbose_name='date')), ('date_due', models.DateField(default=coin.utils.end_of_month, null=True, verbose_name="date d'\xe9ch\xe9ance de paiement")), - ('pdf', models.FileField(storage=coin.utils.private_files_storage, upload_to=coin.billing.models.invoice_pdf_filename, null=True, verbose_name='PDF', blank=True)), + ('pdf', models.FileField(storage=coin.utils.private_files_storage, upload_to=coin.billing.models.bill_pdf_filename, null=True, verbose_name='PDF', blank=True)), ], options={ 'verbose_name': 'facture', diff --git a/coin/billing/migrations/0010_new_billing_system_data.py b/coin/billing/migrations/0010_new_billing_system_data.py index 485fac6ce4d56cc272c1d25e725b48b3a2d7364c..3e7948869071857502a3746ab426c3c95f451ae8 100755 --- a/coin/billing/migrations/0010_new_billing_system_data.py +++ b/coin/billing/migrations/0010_new_billing_system_data.py @@ -5,12 +5,15 @@ import sys from django.db import migrations -from coin.members.models import Member -from coin.billing.models import Invoice, InvoiceDetail, Payment - def check_current_state(apps, schema_editor): + Member = apps.get_model('members', 'Member') + Invoice = apps.get_model('billing', 'Invoice') + InvoiceDetail = apps.get_model('billing', 'InvoiceDetail') + Payment = apps.get_model('billing', 'Payment') + + for invoice in Invoice.objects.all(): invoice_name = invoice.__unicode__() @@ -30,6 +33,11 @@ def check_current_state(apps, schema_editor): def forwards(apps, schema_editor): + Member = apps.get_model('members', 'Member') + Invoice = apps.get_model('billing', 'Invoice') + InvoiceDetail = apps.get_model('billing', 'InvoiceDetail') + Payment = apps.get_model('billing', 'Payment') + # Create allocation for all payment to their respective invoice for payment in Payment.objects.all(): payment.member = payment.invoice.member diff --git a/coin/billing/migrations/0011_auto_20180414_2250.py b/coin/billing/migrations/0011_auto_20180414_2250.py new file mode 100644 index 0000000000000000000000000000000000000000..a7381942cdf529641558aa44da3f08cb9987fc69 --- /dev/null +++ b/coin/billing/migrations/0011_auto_20180414_2250.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0010_new_billing_system_data'), + ] + + operations = [ + migrations.AlterField( + model_name='payment', + name='amount', + field=models.DecimalField(null=True, verbose_name='montant', max_digits=6, decimal_places=2), + ), + ] diff --git a/coin/billing/migrations/0012_auto_20180415_1502.py b/coin/billing/migrations/0012_auto_20180415_1502.py new file mode 100644 index 0000000000000000000000000000000000000000..3f12f8af75d43335a42c1488fc85ab454f6266d4 --- /dev/null +++ b/coin/billing/migrations/0012_auto_20180415_1502.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import datetime +import coin.billing.models +import django.db.models.deletion +import django.core.files.storage +from django.conf import settings + + +def migrate_invoices_to_bills(apps, schema_editor): + from django.core.management.color import no_style + + Bill = apps.get_model('billing', 'Bill') + Invoice = apps.get_model('billing', 'Invoice') + + for invoice in Invoice.objects.all(): + Bill.objects.create( + id=invoice.id, + member=invoice.member, + status=invoice.status, + date=invoice.date, + pdf=invoice.pdf, + ) + # When specifying id manually, sequence should then be reset, at least with postgresql + # https://django.readthedocs.io/en/stable/ref/databases.html#manually-specifying-values-of-auto-incrementing-primary-keys + # https://stackoverflow.com/a/50275895/1377500 + sequence_sql = schema_editor.connection.ops.sequence_reset_sql( + no_style(), + [Bill], + ) + for sql in sequence_sql: + schema_editor.execute(sql) + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('billing', '0011_auto_20180414_2250'), + ] + + operations = [ + # 1/ Create Bill model + migrations.CreateModel( + name='Bill', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('status', models.CharField(default='open', max_length=50, verbose_name='statut', choices=[('open', '\xc0 payer'), ('closed', 'R\xe9gl\xe9e'), ('trouble', 'Litige')])), + ('date', models.DateField(default=datetime.date.today, help_text='Cette date sera d\xe9finie \xe0 la date de validation dans le document final', null=True, verbose_name='date')), + ('pdf', models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/vagrant/apps/extra/coin2/smedia/'), upload_to=coin.billing.models.bill_pdf_filename, null=True, verbose_name='PDF', blank=True)), + ('member', models.ForeignKey(related_name='bills', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True, verbose_name='membre')), + ], + options={ + 'verbose_name': 'note', + }, + ), + # 2/ Create 1 Bill object per Invoice object, copying status, date and pdf, member + migrations.RunPython(migrate_invoices_to_bills), + # 3/ Create a link between Bill and Invoice + migrations.RenameField( + model_name='invoice', + old_name='id', + new_name='bill_ptr', + ), + migrations.AlterField( + model_name='invoice', + name='bill_ptr', + field=models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, default=1, serialize=False, to='billing.Bill'), + ), + # 4/ Delete duplicate Invoice fields that are present on Bill : status, date, pdf, member + + migrations.RemoveField(model_name='invoice', name='status'), + migrations.RemoveField(model_name='invoice', name='date'), + migrations.RemoveField(model_name='invoice', name='pdf'), + migrations.RemoveField(model_name='invoice', name='member'), + + migrations.AlterField( + model_name='payment', + name='invoice', + field=models.ForeignKey(related_name='payments_old', verbose_name='facture associ\xe9e', blank=True, to='billing.Invoice', null=True), + ), + migrations.AlterField( + model_name='paymentallocation', + name='invoice', + field=models.ForeignKey(related_name='allocations', verbose_name='facture associ\xe9e', to='billing.Bill'), + ), + migrations.CreateModel( + name='Donation', + fields=[ + ('bill_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='billing.Bill')), + ('_amount', models.DecimalField(verbose_name='Montant', max_digits=8, decimal_places=2)), + ], + options={ + 'verbose_name': 'don', + }, + bases=('billing.bill',), + ), + migrations.CreateModel( + name='TempMembershipFee', + fields=[ + ('bill_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='billing.Bill')), + ('_amount', models.DecimalField(default=None, help_text='en \u20ac', verbose_name='montant', max_digits=5, decimal_places=2)), + ('start_date', models.DateField(verbose_name='date de d\xe9but de cotisation')), + ('end_date', models.DateField(help_text='par d\xe9faut, la cotisation dure un an', verbose_name='date de fin de cotisation', blank=True)), + ], + options={ + 'verbose_name': 'cotisation', + }, + bases=('billing.bill',), + ), + migrations.RenameField( + model_name='payment', + old_name='invoice', + new_name='bill', + ), + migrations.AlterField( + model_name='payment', + name='bill', + field=models.ForeignKey(related_name='payments', verbose_name='facture associ\xe9e', blank=True, to='billing.Bill', null=True), + ), + ] diff --git a/coin/billing/migrations/0013_auto_20180415_0413.py b/coin/billing/migrations/0013_auto_20180415_0413.py new file mode 100644 index 0000000000000000000000000000000000000000..2e8a872e9feff24414ff570f1a1e7eb1f2cfb938 --- /dev/null +++ b/coin/billing/migrations/0013_auto_20180415_0413.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + +def fill_empty_fee_payment_date(apps, schema_editor): + """ + If a MembershipFee lacks a payment date, we fill it with the start of the + corresponding membership period, considering all members are very serious + and pay exactly at the due date. + """ + MembershipFee = apps.get_model('members', 'MembershipFee') + for fee in MembershipFee.objects.filter(payment_date=None): + fee.payment_date = fee.start_date + fee.save() + +def forwards(apps, schema_editor): + + Payment = apps.get_model('billing', 'Payment') + MembershipFee = apps.get_model('members', 'MembershipFee') + TempMembershipFee = apps.get_model('billing', 'TempMembershipFee') + PaymentAllocation = apps.get_model('billing', 'PaymentAllocation') + + # Update balance for all members + for fee in MembershipFee.objects.all(): + + temp_fee = TempMembershipFee() + temp_fee._amount = fee.amount + temp_fee.start_date = fee.start_date + temp_fee.end_date = fee.end_date + temp_fee.status = 'closed' + temp_fee.date = temp_fee.start_date + temp_fee.member = fee.member + temp_fee.save() + + payment = Payment() + payment.member = fee.member + payment.payment_mean = fee.payment_method + payment.amount = fee.amount + payment.date = fee.payment_date + payment.label = fee.reference + payment.bill = temp_fee + payment.save() + + allocation = PaymentAllocation() + allocation.invoice = temp_fee + allocation.payment = payment + allocation.amount = fee.amount + allocation.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0012_auto_20180415_1502'), + ] + + operations = [ + migrations.RunPython( + fill_empty_fee_payment_date, + reverse_code=migrations.RunPython.noop, + ), + migrations.RunPython(forwards), + ] diff --git a/coin/billing/migrations/0014_auto_20180415_1814.py b/coin/billing/migrations/0014_auto_20180415_1814.py new file mode 100644 index 0000000000000000000000000000000000000000..4b941d0b46d10a0d49be54bcfaef598b3ec6f14b --- /dev/null +++ b/coin/billing/migrations/0014_auto_20180415_1814.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0013_auto_20180415_0413'), + # After MembershipFee model from members app has been deleted + ('members', '0019_auto_20180415_1814'), + ] + + operations = [ + migrations.RenameModel( + old_name='TempMembershipFee', + new_name='MembershipFee', + ), + ] diff --git a/coin/billing/migrations/0015_remove_payment_invoice.py b/coin/billing/migrations/0015_remove_payment_invoice.py new file mode 100644 index 0000000000000000000000000000000000000000..fe1609d3d025fcf9e3fdf8c012ba3c49760ef387 --- /dev/null +++ b/coin/billing/migrations/0015_remove_payment_invoice.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0014_auto_20180415_1814'), + ] + + operations = [ + # Replaced by a RenameField in 0012_auto_20180415_1502 + # migrations.RemoveField( + # model_name='payment', + # name='invoice', + # ), + ] diff --git a/coin/billing/migrations/0016_auto_20180415_2208.py b/coin/billing/migrations/0016_auto_20180415_2208.py new file mode 100644 index 0000000000000000000000000000000000000000..7f610917b7126b33ea24650189c506f52220f446 --- /dev/null +++ b/coin/billing/migrations/0016_auto_20180415_2208.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0015_remove_payment_invoice'), + ] + + operations = [ + migrations.RenameField( + model_name='paymentallocation', + old_name='invoice', + new_name='bill', + ), + ] diff --git a/coin/billing/migrations/0017_merge.py b/coin/billing/migrations/0017_merge.py new file mode 100644 index 0000000000000000000000000000000000000000..d7ffbcf8fef1491b15beb1458aece40638fb0848 --- /dev/null +++ b/coin/billing/migrations/0017_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0016_auto_20180415_2208'), + ('billing', '0011_auto_20180819_0221'), + ] + + operations = [ + ] diff --git a/coin/billing/migrations/0018_auto_20181118_2001.py b/coin/billing/migrations/0018_auto_20181118_2001.py new file mode 100644 index 0000000000000000000000000000000000000000..d8ff559b50f2fb84cbbf385f7a8b12b14ef9d26b --- /dev/null +++ b/coin/billing/migrations/0018_auto_20181118_2001.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.core.files.storage +import coin.billing.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0017_merge'), + ] + + operations = [ + migrations.AlterField( + model_name='bill', + name='pdf', + field=models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/var/www/adherents.arn-fai.net/smedia/'), upload_to=coin.billing.models.bill_pdf_filename, null=True, verbose_name='PDF', blank=True), + ), + migrations.AlterField( + model_name='invoicedetail', + name='amount', + field=models.DecimalField(verbose_name='montant', max_digits=8, decimal_places=2), + ), + migrations.AlterField( + model_name='membershipfee', + name='_amount', + field=models.DecimalField(default=None, help_text='en \u20ac', verbose_name='montant', max_digits=8, decimal_places=2), + ), + migrations.AlterField( + model_name='payment', + name='amount', + field=models.DecimalField(null=True, verbose_name='montant', max_digits=8, decimal_places=2), + ), + migrations.AlterField( + model_name='payment', + name='payment_mean', + field=models.CharField(default='transfer', max_length=100, null=True, verbose_name='moyen de paiement', choices=[('cash', 'Esp\xe8ces'), ('check', 'Ch\xe8que'), ('transfer', 'Virement'), ('creditnote', 'Avoir'), ('other', 'Autre')]), + ), + migrations.AlterField( + model_name='paymentallocation', + name='amount', + field=models.DecimalField(null=True, verbose_name='montant', max_digits=8, decimal_places=2), + ), + ] diff --git a/coin/billing/migrations/0019_auto_20190623_1256.py b/coin/billing/migrations/0019_auto_20190623_1256.py new file mode 100644 index 0000000000000000000000000000000000000000..5fab37f25490079dd0d887cccc77e94ace632ea4 --- /dev/null +++ b/coin/billing/migrations/0019_auto_20190623_1256.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0018_auto_20181118_2001'), + ] + + operations = [ + migrations.AlterField( + model_name='invoicedetail', + name='label', + field=models.CharField(max_length=255), + ), + ] diff --git a/coin/billing/migrations/0020_auto_20200717_1733.py b/coin/billing/migrations/0020_auto_20200717_1733.py new file mode 100644 index 0000000000000000000000000000000000000000..9bb497aa09afa4f0dec548ad995832ce4e31d8a3 --- /dev/null +++ b/coin/billing/migrations/0020_auto_20200717_1733.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0019_auto_20190623_1256'), + ] + + operations = [ + migrations.AlterField( + model_name='membershipfee', + name='_amount', + field=models.DecimalField(default=15, help_text='en \u20ac', verbose_name='montant', max_digits=8, decimal_places=2), + ), + ] diff --git a/coin/billing/migrations/0021_auto_20201203_1855.py b/coin/billing/migrations/0021_auto_20201203_1855.py new file mode 100644 index 0000000000000000000000000000000000000000..77f4bfc04bbdfda11c545b57bbfcd750d92c2aba --- /dev/null +++ b/coin/billing/migrations/0021_auto_20201203_1855.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.core.files.storage +import coin.members.models +import coin.billing.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0020_auto_20200717_1733'), + ] + + operations = [ + migrations.AlterField( + model_name='membershipfee', + name='_amount', + field=models.DecimalField(default=coin.members.models.default_membership_fee, help_text='en \u20ac', verbose_name='montant', max_digits=8, decimal_places=2), + ), + ] diff --git a/coin/billing/migrations/0022_auto_20201203_1913.py b/coin/billing/migrations/0022_auto_20201203_1913.py new file mode 100644 index 0000000000000000000000000000000000000000..b7d7b2fe2f4285be19d9345853dc381da1a2094c --- /dev/null +++ b/coin/billing/migrations/0022_auto_20201203_1913.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import coin.billing.models +import coin.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0021_auto_20201203_1855'), + ] + + operations = [ + migrations.AlterField( + model_name='bill', + name='pdf', + field=models.FileField(storage=coin.utils.PrivateFileStorage(), upload_to=coin.billing.models.bill_pdf_filename, null=True, verbose_name='PDF', blank=True), + ), + ] diff --git a/coin/billing/migrations/0023_auto_20201203_1932.py b/coin/billing/migrations/0023_auto_20201203_1932.py new file mode 100644 index 0000000000000000000000000000000000000000..3406d610900267ae2569a5c059249dbc0aef7864 --- /dev/null +++ b/coin/billing/migrations/0023_auto_20201203_1932.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('billing', '0022_auto_20201203_1913'), + ] + + operations = [ + migrations.AlterField( + model_name='invoice', + name='bill_ptr', + field=models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='billing.Bill'), + ), + ] diff --git a/coin/billing/models.py b/coin/billing/models.py index 79a6408316ce5954a1670e99f21894f5dab45bc3..210e355c34a19c7d15ed3300ca3982703f292c15 100644 --- a/coin/billing/models.py +++ b/coin/billing/models.py @@ -5,6 +5,7 @@ import datetime import logging import uuid import re +import abc from decimal import Decimal from dateutil.relativedelta import relativedelta @@ -18,7 +19,7 @@ from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from coin.offers.models import OfferSubscription -from coin.members.models import Member +from coin.members.models import Member, default_membership_fee from coin.html2pdf import render_as_pdf from coin.utils import private_files_storage, start_of_month, end_of_month, \ postgresql_regexp, send_templated_email, \ @@ -29,13 +30,144 @@ from coin.isp_database.models import ISPInfo accounting_log = logging.getLogger("coin.billing") -def invoice_pdf_filename(instance, filename): - """Nom et chemin du fichier pdf à stocker pour les factures""" +def bill_pdf_filename(instance, filename): + """Nom et chemin du fichier pdf à stocker""" member_id = instance.member.id if instance.member else 0 - return 'invoices/%d_%s_%s.pdf' % (member_id, - instance.number, - uuid.uuid4()) + number = instance.number if hasattr(instance, "number") else instance.pk + bill_type = instance.type.lower() + return '%ss/%d_%s_%s.pdf' % (bill_type, member_id, number, uuid.uuid4()) +class Bill(models.Model): + + CHILD_CLASS_NAMES = ( + 'Invoice', + 'MembershipFee', + 'Donation', + ) + + BILL_STATUS_CHOICES = ( + ('open', 'À payer'), + ('closed', 'Réglée'), + ('trouble', 'Litige') + ) + + status = models.CharField(max_length=50, choices=BILL_STATUS_CHOICES, + default='open', + verbose_name='statut') + date = models.DateField( + default=datetime.date.today, null=True, verbose_name='date', + help_text='Cette date sera définie à la date de validation dans le document final') + member = models.ForeignKey(Member, null=True, blank=True, default=None, + related_name='bills', + verbose_name='membre', + on_delete=models.SET_NULL) + pdf = models.FileField(storage=private_files_storage, + upload_to=bill_pdf_filename, + null=True, blank=True, + verbose_name='PDF') + + + def as_child(self): + for child_class_name in self.CHILD_CLASS_NAMES: + try: + return self.__getattribute__(child_class_name.lower()) + except eval(child_class_name).DoesNotExist: + pass + return self + + @property + def type(self): + for child_class_name in self.CHILD_CLASS_NAMES: + if hasattr(self, child_class_name.lower()): + return child_class_name + return self.__class__.__name__ + + @property + def amount(self): + """ Return bill amount """ + return self.cast.amount + amount.fget.short_description = 'Montant' + + def amount_paid(self): + """ + Calcul le montant déjà payé à partir des allocations de paiements + """ + return sum([a.amount for a in self.allocations.all()]) + amount_paid.short_description = 'Montant payé' + + def amount_remaining_to_pay(self): + """ + Calcul le montant restant à payer + """ + return self.amount - self.amount_paid() + amount_remaining_to_pay.short_description = 'Reste à payer' + + def has_owner(self, username): + """ + Check if passed username (ex gmajax) is owner of the invoice + """ + return (self.member and self.member.username == username) + + def generate_pdf(self): + """ + Make and store a pdf file for the invoice + """ + context = {"bill": self} + context.update(branding(None)) + pdf_file = render_as_pdf('billing/{bill_type}_pdf.html'.format(bill_type=self.type.lower()), context) + self.pdf.save('%s.pdf' % self.number if hasattr(self, "number") else self.pk, pdf_file) + + def pdf_exists(self): + return (bool(self.pdf) + and private_files_storage.exists(self.pdf.name)) + + def get_absolute_url(self): + return reverse('billing:bill_pdf', args=[self.number]) + + def __unicode__(self): + return '%s - %s - %i€' % (self.member, self.date, self.amount) + + @property + def reference(self): + if hasattr(self, 'membershipfee'): + return 'Cotisation' + elif hasattr(self, 'donation'): + return 'Don' + elif hasattr(self, 'invoice'): + return self.invoice.number + + def log_change(self, created): + if created: + accounting_log.info( + "Creating draft bill DRAFT-{} (Member: {}).".format( + self.pk, self.member)) + else: + if hasattr(self, 'validated') and not self.validated: + accounting_log.info( + "Updating draft bill DRAFT-{} (Member: {}).".format( + self.pk, self.member)) + else: + accounting_log.info( + "Updating bill {} (Member: {}, Total amount: {}, Amount paid: {}).".format( + self.pk, self.member, + self.amount, self.amount_paid())) + + + @property + def cast(bill): + if hasattr(bill, 'membershipfee'): + return bill.membershipfee + elif hasattr(bill, 'donation'): + return bill.donation + elif hasattr(bill, 'invoice'): + return bill.invoice + @staticmethod + def get_member_validated_bills(member): + related_fields = ['membershipfee', 'donation', 'invoice'] + return [i.cast for i in member.bills.order_by("date") if i.cast.validated] + + class Meta: + verbose_name = 'note' @python_2_unicode_compatible class InvoiceNumber: @@ -108,7 +240,7 @@ class InvoiceQuerySet(models.QuerySet): def _get_last_invoice_number(self, date): same_seq_filter = InvoiceNumber.time_sequence_filter(date) return self.filter(**same_seq_filter).with_valid_number().aggregate( - models.Max('number'))['number__max'] + models.Max('number'))["number__max"] def with_valid_number(self): """ Excludes previous numbering schemes or draft invoices @@ -117,13 +249,8 @@ class InvoiceQuerySet(models.QuerySet): InvoiceNumber.RE_INVOICE_NUMBER)) -class Invoice(models.Model): +class Invoice(Bill): - INVOICES_STATUS_CHOICES = ( - ('open', 'À payer'), - ('closed', 'Réglée'), - ('trouble', 'Litige') - ) validated = models.BooleanField(default=False, verbose_name='validée', help_text='Once validated, a PDF is generated' @@ -131,24 +258,10 @@ class Invoice(models.Model): number = models.CharField(max_length=25, unique=True, verbose_name='numéro') - status = models.CharField(max_length=50, choices=INVOICES_STATUS_CHOICES, - default='open', - verbose_name='statut') - date = models.DateField( - default=datetime.date.today, null=True, verbose_name='date', - help_text='Cette date sera définie à la date de validation dans la facture finale') date_due = models.DateField( null=True, blank=True, verbose_name="date d'échéance de paiement", help_text='Le délai de paiement sera fixé à {} jours à la validation si laissé vide'.format(settings.PAYMENT_DELAY)) - member = models.ForeignKey(Member, null=True, blank=True, default=None, - related_name='invoices', - verbose_name='membre', - on_delete=models.SET_NULL) - pdf = models.FileField(storage=private_files_storage, - upload_to=invoice_pdf_filename, - null=True, blank=True, - verbose_name='PDF') date_last_reminder_email = models.DateTimeField(null=True, blank=True, verbose_name="Date du dernier email de relance envoyé") @@ -161,6 +274,7 @@ class Invoice(models.Model): self.number = 'DRAFT-{}'.format(self.pk) self.save() + @property def amount(self): """ Calcul le montant de la facture @@ -170,7 +284,7 @@ class Invoice(models.Model): for detail in self.details.all(): total += detail.total() return total.quantize(Decimal('0.01')) - amount.short_description = 'Montant' + amount.fget.short_description = 'Montant' def amount_before_tax(self): total = Decimal('0.0') @@ -179,42 +293,16 @@ class Invoice(models.Model): return total.quantize(Decimal('0.01')) amount_before_tax.short_description = 'Montant HT' - def amount_paid(self): - """ - Calcul le montant déjà payé à partir des allocations de paiements - """ - return sum([a.amount for a in self.allocations.all()]) - amount_paid.short_description = 'Montant payé' - - def amount_remaining_to_pay(self): - """ - Calcul le montant restant à payer - """ - return self.amount() - self.amount_paid() - amount_remaining_to_pay.short_description = 'Reste à payer' - - def has_owner(self, username): - """ - Check if passed username (ex gmajax) is owner of the invoice - """ - return (self.member and self.member.username == username) - - def generate_pdf(self): - """ - Make and store a pdf file for the invoice - """ - context = {"invoice": self} - context.update(branding(None)) - pdf_file = render_as_pdf('billing/invoice_pdf.html', context) - self.pdf.save('%s.pdf' % self.number, pdf_file) @transaction.atomic - def validate(self): + def validate(self, custom_date=None): """ Switch invoice to validate mode. This set to False the draft field and generate the pdf """ - self.date = datetime.date.today() + + self.date = custom_date or datetime.date.today() + if not self.date_due: self.date_due = self.date + datetime.timedelta(days=settings.PAYMENT_DELAY) old_number = self.number @@ -228,7 +316,7 @@ class Invoice(models.Model): "Draft invoice {} validated as invoice {}. ".format( old_number, self.number) + "(Total amount : {} ; Member : {})".format( - self.amount(), self.member)) + self.amount, self.member)) assert self.pdf_exists() if self.member is not None: update_accounting_for_member(self.member) @@ -239,12 +327,13 @@ class Invoice(models.Model): and bool(self.pdf) and private_files_storage.exists(self.pdf.name)) - def get_absolute_url(self): - return reverse('billing:invoice', args=[self.number]) + @property + def pdf_title(self): + return "Facture N°"+self.number def __unicode__(self): return '#{} {:0.2f}€ {}'.format( - self.number, self.amount(), self.date_due) + self.number, self.amount, self.date_due) def reminder_needed(self): @@ -306,6 +395,18 @@ class Invoice(models.Model): self.save() return True + def log_change(self, created): + + if created: + accounting_log.info("Creating draft invoice %s (Member: %s)." + % ('DRAFT-{}'.format(self.pk), self.member)) + else: + if not self.validated: + accounting_log.info("Updating draft invoice %s (Member: %s)." + % (self.number, self.member)) + else: + accounting_log.info("Updating invoice %s (Member: %s, Total amount: %s, Amount paid: %s)." + % (self.number, self.member, self.amount, self.amount_paid() )) class Meta: verbose_name = 'facture' @@ -314,8 +415,8 @@ class Invoice(models.Model): class InvoiceDetail(models.Model): - label = models.CharField(max_length=100) - amount = models.DecimalField(max_digits=5, decimal_places=2, + label = models.CharField(max_length=255) + amount = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='montant') quantity = models.DecimalField(null=True, verbose_name='quantité', default=1.0, decimal_places=2, max_digits=4) @@ -359,12 +460,97 @@ class InvoiceDetail(models.Model): verbose_name = 'détail de facture' +class Donation(Bill): + _amount = models.DecimalField(max_digits=8, decimal_places=2, + verbose_name='Montant') + + @property + def amount(self): + return self._amount + amount.fget.short_description = 'Montant' + + @property + def validated(self): + return True + + def save(self, *args, **kwargs): + + super(Donation, self).save(*args, **kwargs) + + if not self.pdf_exists(): + self.generate_pdf() + + def clean(self): + + # Only if no amount already allocated... + if self.pk is None and settings.HANDLE_BALANCE and (not self.member or self.member.balance < self.amount): + raise ValidationError("Le solde n'est pas suffisant pour payer ce don. \ + Merci de commencer par enregistrer un paiement pour ce membre.") + + @property + def pdf_title(self): + return "Reçu de don" + + + class Meta: + verbose_name = 'don' + +class MembershipFee(Bill): + _amount = models.DecimalField(null=False, max_digits=8, decimal_places=2, + default=default_membership_fee, + verbose_name='montant', help_text='en €') + start_date = models.DateField( + null=False, + blank=False, + verbose_name='date de début de cotisation') + end_date = models.DateField( + null=False, + blank=True, + verbose_name='date de fin de cotisation', + help_text='par défaut, la cotisation dure un an') + + @property + def amount(self): + return self._amount + amount.fget.short_description = 'Montant' + @property + def validated(self): + return True + + def save(self, *args, **kwargs): + super(MembershipFee, self).save(*args, **kwargs) + + today = datetime.date.today() + if self.start_date <= today and today <= self.end_date: + self.member.status = self.member.MEMBER_STATUS_MEMBER + self.member.save() + + if not self.pdf_exists(): + self.generate_pdf() + + def clean(self): + # Only if no amount already allocated... + if self.pk is None and settings.HANDLE_BALANCE and (not self.member or self.member.balance < self.amount): + raise ValidationError("Le solde n'est pas suffisant pour payer cette cotisation. \ + Merci de commencer par enregistrer un paiement pour ce membre.") + + if self.start_date is not None and self.end_date is None: + self.end_date = self.start_date + datetime.timedelta(364) + + @property + def pdf_title(self): + return "Reçu de cotisation" + + class Meta: + verbose_name = 'cotisation' + class Payment(models.Model): PAYMENT_MEAN_CHOICES = ( ('cash', 'Espèces'), ('check', 'Chèque'), ('transfer', 'Virement'), + ('creditnote', 'Avoir'), ('other', 'Autre') ) @@ -377,10 +563,10 @@ class Payment(models.Model): default='transfer', choices=PAYMENT_MEAN_CHOICES, verbose_name='moyen de paiement') - amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, + amount = models.DecimalField(max_digits=8, decimal_places=2, null=True, verbose_name='montant') date = models.DateField(default=datetime.date.today) - invoice = models.ForeignKey(Invoice, verbose_name='facture associée', null=True, + bill = models.ForeignKey(Bill, verbose_name='facture associée', null=True, blank=True, related_name='payments') label = models.CharField(max_length=500, @@ -393,9 +579,9 @@ class Payment(models.Model): if self.amount_already_allocated() == 0: # If there's a linked invoice and no member defined - if self.invoice and not self.member: + if self.bill and not self.member: # Automatically set member to invoice's member - self.member = self.invoice.member + self.member = self.bill.member super(Payment, self).save(*args, **kwargs) @@ -407,7 +593,7 @@ class Payment(models.Model): # If there's a linked invoice and this payment would pay more than # the remaining amount needed to pay the invoice... - if self.invoice and self.amount > self.invoice.amount_remaining_to_pay(): + if self.bill and self.amount > self.bill.amount_remaining_to_pay(): raise ValidationError("This payment would pay more than the invoice's remaining to pay") def amount_already_allocated(self): @@ -417,13 +603,13 @@ class Payment(models.Model): return self.amount - self.amount_already_allocated() @transaction.atomic - def allocate_to_invoice(self, invoice): + def allocate_to_bill(self, bill): # FIXME - Add asserts about remaining amount > 0, unpaid amount > 0, # ... amount_can_pay = self.amount_not_allocated() - amount_to_pay = invoice.amount_remaining_to_pay() + amount_to_pay = bill.amount_remaining_to_pay() amount_to_allocate = min(amount_can_pay, amount_to_pay) if amount_to_allocate <= 0: @@ -433,21 +619,21 @@ class Payment(models.Model): return accounting_log.info( - "Allocating {} from payment {} to invoice {}".format( - amount_to_allocate, self.date, invoice.number)) + "Allocating {} from payment {} to bill {} {}".format( + amount_to_allocate, self.date, bill.reference, bill.pk)) - PaymentAllocation.objects.create(invoice=invoice, + PaymentAllocation.objects.create(bill=bill, payment=self, amount=amount_to_allocate) # Close invoice if relevant - if (invoice.amount_remaining_to_pay() <= 0) and (invoice.status == "open"): + if (bill.amount_remaining_to_pay() <= 0) and (bill.status == "open"): accounting_log.info( - "Invoice {} has been paid and is now closed".format( - invoice.number)) - invoice.status = "closed" + "Bill {} {} has been paid and is now closed".format( + bill.reference, bill.pk)) + bill.status = "closed" - invoice.save() + bill.save() self.save() def __unicode__(self): @@ -468,31 +654,31 @@ class Payment(models.Model): # There can be for example an allocation of 3.14€ from P to I. class PaymentAllocation(models.Model): - invoice = models.ForeignKey(Invoice, verbose_name='facture associée', + bill = models.ForeignKey(Bill, verbose_name='facture associée', null=False, blank=False, related_name='allocations') payment = models.ForeignKey(Payment, verbose_name='facture associée', null=False, blank=False, related_name='allocations') - amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, + amount = models.DecimalField(max_digits=8, decimal_places=2, null=True, verbose_name='montant') -def get_active_payment_and_invoices(member): +def get_active_payment_and_bills(member): # Fetch relevant and active payments / invoices # and sort then by chronological order : olders first, newers last. - this_member_invoices = [i for i in member.invoices.filter(validated=True).order_by("date")] + this_member_bills = Bill.get_member_validated_bills(member) this_member_payments = [p for p in member.payments.order_by("date")] # TODO / FIXME ^^^ maybe also consider only 'opened' invoices (i.e. not # conflict / trouble invoices) active_payments = [p for p in this_member_payments if p.amount_not_allocated() > 0] - active_invoices = [p for p in this_member_invoices if p.amount_remaining_to_pay() > 0] + active_bills = [p for p in this_member_bills if p.amount_remaining_to_pay() > 0] - return active_payments, active_invoices + return active_payments, active_bills def update_accounting_for_member(member): @@ -507,12 +693,12 @@ def update_accounting_for_member(member): accounting_log.info( "Member {} current balance is {} ...".format(member, member.balance)) - reconcile_invoices_and_payments(member) + reconcile_bills_and_payments(member) - this_member_invoices = [i for i in member.invoices.filter(validated=True).order_by("date")] + this_member_bills = Bill.get_member_validated_bills(member) this_member_payments = [p for p in member.payments.order_by("date")] - member.balance = compute_balance(this_member_invoices, + member.balance = compute_balance(this_member_bills, this_member_payments) member.save() @@ -520,22 +706,22 @@ def update_accounting_for_member(member): member, member.balance)) -def reconcile_invoices_and_payments(member): +def reconcile_bills_and_payments(member): """ Rapproche des factures et des paiements qui sont actifs (paiement non alloué ou factures non entièrement payées) automatiquement. """ - active_payments, active_invoices = get_active_payment_and_invoices(member) + active_payments, active_bills = get_active_payment_and_bills(member) if active_payments == []: accounting_log.info( "(No active payment for {}.".format(member) - + " No invoice/payment reconciliation needed.).") + + " No bill/payment reconciliation needed.).") return - elif active_invoices == []: + elif active_bills == []: accounting_log.info( - "(No active invoice for {}. No invoice/payment ".format(member) + + "(No active bill for {}. No bill/payment ".format(member) + "reconciliation needed.).") return @@ -543,32 +729,32 @@ def reconcile_invoices_and_payments(member): "Initiating reconciliation between invoice and payments for {}".format( member)) - while active_payments != [] and active_invoices != []: + while active_payments != [] and active_bills != []: - # Only consider the oldest active payment and the oldest active invoice + # Only consider the oldest active payment and the oldest active bill p = active_payments[0] - # If this payment is to be allocated for a specific invoice... - if p.invoice: + # If this payment is to be allocated for a specific bill... + if p.bill: # Assert that the invoice is still 'active' - assert p.invoice in active_invoices - i = p.invoice + assert p.bill.pk in [b.pk for b in active_bills] + i = p.bill accounting_log.info( - "Payment is to be allocated specifically to invoice {}".format( - i.number)) + "Payment is to be allocated specifically to bill {}".format( + i.pk)) else: - i = active_invoices[0] + i = active_bills[0] # TODO : should add an assert that the ammount not allocated / remaining to - # pay is lower before and after calling the allocate_to_invoice + # pay is lower before and after calling the allocate_to_bill - p.allocate_to_invoice(i) + p.allocate_to_bill(i) - active_payments, active_invoices = get_active_payment_and_invoices(member) + active_payments, active_bills = get_active_payment_and_bills(member) if active_payments == []: accounting_log.info("No more active payment. Nothing to reconcile anymore.") - elif active_invoices == []: + elif active_bills == []: accounting_log.info("No more active invoice. Nothing to reconcile anymore.") return @@ -585,7 +771,7 @@ def compute_balance(invoices, payments): return s -@receiver(post_save, sender=Payment) +@receiver(post_save, sender=Payment, dispatch_uid='payment_payment_changed') @disable_for_loaddata def payment_changed(sender, instance, created, **kwargs): @@ -605,8 +791,8 @@ def payment_changed(sender, instance, created, **kwargs): and (instance.member is not None): # Not using the auto-accounting module ... and apparently the user did chose explicitly to which invoice - if not settings.HANDLE_BALANCE and instance.invoice: - instance.allocate_to_invoice(instance.invoice) + if not settings.HANDLE_BALANCE and instance.bill: + instance.allocate_to_bill(instance.bill) # Otherwise, if we know to which member to use this payment for, we trigger an update of its accounting elif instance.member is not None: @@ -614,38 +800,37 @@ def payment_changed(sender, instance, created, **kwargs): -@receiver(post_save, sender=Invoice) +@receiver(post_save, sender=Bill, dispatch_uid='bill_changed') @disable_for_loaddata -def invoice_changed(sender, instance, created, **kwargs): +def bill_changed(sender, instance, created, **kwargs): - if created: - accounting_log.info( - "Creating draft invoice DRAFT-{} (Member: {}).".format( - instance.pk, instance.member)) - else: - if not instance.validated: - accounting_log.info( - "Updating draft invoice DRAFT-{} (Member: {}).".format( - instance.number, instance.member)) - else: - accounting_log.info( - "Updating invoice {} (Member: {}, Total amount: {}, Amount paid: {}).".format( - instance.number, instance.member, - instance.amount(), instance.amount_paid())) + instance.log_change(created) + +@receiver(post_save, sender=MembershipFee, dispatch_uid='membershipfee_changed') +@disable_for_loaddata +def membershipfee_changed(sender, instance, created, **kwargs): + if created and instance.member is not None: + update_accounting_for_member(instance.member) -@receiver(post_delete, sender=PaymentAllocation) +@receiver(post_save, sender=Donation, dispatch_uid='donation_changed') +@disable_for_loaddata +def donation_changed(sender, instance, created, **kwargs): + if created and instance.member is not None: + update_accounting_for_member(instance.member) + +@receiver(post_delete, sender=PaymentAllocation, dispatch_uid='paymentallocation_deleted') def paymentallocation_deleted(sender, instance, **kwargs): - invoice = instance.invoice + bill = instance.bill # Reopen invoice if relevant - if (invoice.amount_remaining_to_pay() > 0) and (invoice.status == "closed"): - accounting_log.info("Reopening invoice {} ...".format(invoice.number)) - invoice.status = "open" - invoice.save() + if (bill.amount_remaining_to_pay() > 0) and (bill.status == "closed"): + accounting_log.info("Reopening bill {} ...".format(bill.number)) + bill.status = "open" + bill.save() -@receiver(post_delete, sender=Payment) +@receiver(post_delete, sender=Payment, dispatch_uid='payment_deleted') def payment_deleted(sender, instance, **kwargs): accounting_log.info( @@ -657,11 +842,9 @@ def payment_deleted(sender, instance, **kwargs): if member is None: return - this_member_invoices = [i for i in member.invoices.filter(validated=True).order_by("date")] + this_member_bills = Bill.get_member_validated_bills(member) this_member_payments = [p for p in member.payments.order_by("date")] - member.balance = compute_balance(this_member_invoices, + member.balance = compute_balance(this_member_bills, this_member_payments) member.save() - - diff --git a/coin/billing/templates/admin/billing/invoice/change_form.html b/coin/billing/templates/admin/billing/invoice/change_form.html index 281786eaec0ae1aff590c08b30a3b71bfedd7fa5..b5b1b093a9dc1afcc688efaef2bf246844e1bbae 100644 --- a/coin/billing/templates/admin/billing/invoice/change_form.html +++ b/coin/billing/templates/admin/billing/invoice/change_form.html @@ -1,10 +1,9 @@ {% extends "admin/change_form.html" %} -{% load url from future %} {% block object-tools-items %} {% if not original.validated %}
  • Valider la facture
  • {% elif original.validated %} -
  • Télécharger le PDF
  • +
  • Télécharger le PDF
  • {% endif %} {{ block.super }} {% endblock %} diff --git a/coin/billing/templates/admin/billing/payment/change_list.html b/coin/billing/templates/admin/billing/payment/change_list.html index eb0c919f3c9f739833b03d719800d570a01f1171..a984fde669bbdeb91e1c460f39ed0105abee92b4 100644 --- a/coin/billing/templates/admin/billing/payment/change_list.html +++ b/coin/billing/templates/admin/billing/payment/change_list.html @@ -1,5 +1,6 @@ {% extends "admin/change_list.html" %} {% block object-tools-items %} -
  • Importer des paiements
  • +
  • Importer des paiements depuis un .csv
  • +
  • Ajouter un paiement manuellement
  • {% endblock %} diff --git a/coin/billing/templates/admin/billing/payment/wizard_import_payment_csv.html b/coin/billing/templates/admin/billing/payment/wizard_import_payment_csv.html index 788d4e254d7f1cab0a97fb99dccd02504c7428bf..4e23bae6706f83c41e8f163617fb909988abe46f 100644 --- a/coin/billing/templates/admin/billing/payment/wizard_import_payment_csv.html +++ b/coin/billing/templates/admin/billing/payment/wizard_import_payment_csv.html @@ -14,19 +14,23 @@
    {% csrf_token %} -
    +
    {{ adminform.as_p }} {% if not new_payments %} {% else %} - -

    - Les paiements suivants seront importés. Passez en revue les membres matchés avant de cliquer sur 'Import' ! -

    - N.B. : Il faut resélectionner le fichier (désolé~). + Les paiements suivants seront importés. Passez en revue les membres matchés avant de cliquer sur 'Import' ! +
    + N.B. : Il faut resélectionner le fichier (désolé~).

    + +
    + + +
    +
    diff --git a/coin/billing/templates/billing/bill_pdf.html b/coin/billing/templates/billing/bill_pdf.html new file mode 100644 index 0000000000000000000000000000000000000000..6e1cf33ea5423543f59502764cabcb2aa8d435ed --- /dev/null +++ b/coin/billing/templates/billing/bill_pdf.html @@ -0,0 +1,175 @@ +{% load static isptags %} + + + {{ bill.pdf_title }} + + + + + + {% block header %} +
    + +

    {{ bill.pdf_title }}

    +

    Le {{ bill.date }}

    +
    + {% endblock %} + + {% block coordinates %} +
    Date
    + + + + +
    +

    + {% multiline_isp_addr branding %} +

    +

    + {{ branding.email }}
    + {{ branding.website }}
    + {{ branding.phone_number }} +

    +
    +

    + À l'intention de :
    + {% with member=bill.member %} + {{ member.last_name }} {{ member.first_name }}
    + {% if member.organization_name != "" %}{{ member.organization_name }}
    {% endif %} + {% if member.address %}{{member.address}}
    {% endif %} + {% if member.postal_code and member.city %} + {{ member.postal_code }} {{ member.city }} + {% endif %} + {% endwith %} +

    +
    + {% endblock %} + + {% block content %} + {% endblock %} + + {% block footer %} +
    + +

    /

    +

    {{ branding.shortname|upper }}, association loi de 1901 à but non lucratif - SIRET : {{ branding.registeredoffice.siret }}

    +
    + {% endblock %} + + + diff --git a/coin/billing/templates/billing/donation_pdf.html b/coin/billing/templates/billing/donation_pdf.html new file mode 100644 index 0000000000000000000000000000000000000000..47c73b196b67e46e51ce375d89611ae8a0de8696 --- /dev/null +++ b/coin/billing/templates/billing/donation_pdf.html @@ -0,0 +1,19 @@ +{% extends "billing/bill_pdf.html" %} + +{% block content %} +
    +
    +
    + +

    + En date du {{ bill.date }}, l'association {{ branding.shortname|upper }} certifie avoir reçu un don d'un montant de {{ bill.amount }}€ de la part de {{ bill.member.first_name }} {{ bill.member.last_name }}. +

    + +
    +
    +
    + +

    + N.B. : ce reçu n'a pas valeur de reçu fiscal et ne peut pas être utilisé pour prétendre à une réduction d'impôts. +

    +{% endblock %} diff --git a/coin/billing/templates/billing/invoice.html b/coin/billing/templates/billing/invoice.html deleted file mode 100644 index 365bba35a7367eb46e102b861714f51d5bf08d63..0000000000000000000000000000000000000000 --- a/coin/billing/templates/billing/invoice.html +++ /dev/null @@ -1,79 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Facture N°{{ invoice.number }} - {{ block.super }}{% endblock %} - -{% block content %} -
    -
    -

    Facture N°{{ invoice.number }}

    -

    Émise le {{ invoice.date }}

    -
    -
    - {% if invoice.validated %} Télécharger en PDF{% endif %} -
    -
    - - - - - - - - - - - - {% for detail in invoice.details.all %} - - - - - - - {% endfor %} - - - - - -
    QuantitéPUTotal TTC
    {{ detail.label }} - {% if detail.period_from and detail.period_to %}
    Pour la période du {{ detail.period_from }} au {{ detail.period_to }}{% endif %}
    {{ detail.quantity }}{{ detail.amount }}€{{ detail.total }}€
    Total TTC{{ invoice.amount }}€
    - -

    - Facture à payer avant le {{ invoice.date_due }}. -

    - -

    Règlement

    - -{% if invoice.payments.exists %} - - - - - - - - - - {% for payment in invoice.payments.all %} - - - - - - {% endfor %} - - - - - -
    Type de paiementDateMontant
    {{ payment.get_payment_mean_display }}{{ payment.date }}-{{ payment.amount }}€
    Reste à payer{{ invoice.amount_remaining_to_pay }}€
    -{% endif %} - -{% if invoice.amount_remaining_to_pay > 0 %} -
    - {% include "billing/payment_howto.html" %} -
    -{% endif %} - -{% endblock %} diff --git a/coin/billing/templates/billing/invoice_pdf.html b/coin/billing/templates/billing/invoice_pdf.html index 9dac062ed5faad0aa18e6cd8e858a09f29eeba46..bf4ede66801e3d4fbdc5ed418860aee6bed0bbe7 100644 --- a/coin/billing/templates/billing/invoice_pdf.html +++ b/coin/billing/templates/billing/invoice_pdf.html @@ -1,162 +1,7 @@ -{% load static isptags %} - - - Facture N°{{ invoice.number }} +{% extends "billing/bill_pdf.html" %} - - - - -
    - -

    Facture N°{{ invoice.number }}

    -

    Le {{ invoice.date }}

    -
    - - - - - - -
    -

    - {% multiline_isp_addr branding %} -

    -

    - {{ branding.email }}
    - {{ branding.website }}
    - {{ branding.phone_number }} -

    -
    -

    - Facturé à :
    - {% with member=invoice.member %} - {{ member.last_name }} {{ member.first_name }}
    - {% if member.organization_name != "" %}{{ member.organization_name }}
    {% endif %} - {% if member.address %}{{member.address}}
    {% endif %} - {% if member.postal_code and member.city %} - {{ member.postal_code }} {{ member.city }} - {% endif %} - {% endwith %} -

    -
    - - +{% block content %} +
    @@ -167,7 +12,7 @@ - {% for detail in invoice.details.all %} + {% for detail in bill.details.all %} {% endfor %} - + - + - + - -

    @@ -189,35 +34,27 @@

    {{ detail.total }}€
    Total HT{{ invoice.amount_before_tax }}€{{ bill.amount_before_tax }}€
    Total TTC{{ invoice.amount }}€{{ bill.amount }}€
    -

    - TVA non applicable - article 293 B du CGI -

    -

    - Facture à payer avant le {{ invoice.date_due }}. -

    - -
    - {% include "billing/payment_howto.html" %} -
    - -
    - -

    /

    -

    {{ branding.shortname|upper }}, association loi de 1901 à but non lucratif - SIRET : {{ branding.registeredoffice.siret }}

    -
    - - + +

    +TVA non applicable - article 293 B du CGI +

    +

    +Facture à payer avant le {{ bill.date_due }}. +

    + +
    +{% include "billing/payment_howto.html" %} +
    +{% endblock %} diff --git a/coin/billing/templates/billing/membershipfee_pdf.html b/coin/billing/templates/billing/membershipfee_pdf.html new file mode 100644 index 0000000000000000000000000000000000000000..acb70b7ae8b9d5d4a81efcb1c6c6779fc796f590 --- /dev/null +++ b/coin/billing/templates/billing/membershipfee_pdf.html @@ -0,0 +1,11 @@ +{% extends "billing/bill_pdf.html" %} + +{% block content %} +
    +
    +
    + +

    + En date du {{ bill.date }}, l'association {{ branding.shortname|upper }} certifie avoir reçu et accepté une cotisation d'un montant de {{ bill.amount }}€ de la part de {{ bill.member.first_name }} {{ bill.member.last_name }}. Cette cotisation lui confère le statut de membre pour la période du {{ bill.start_date }} au {{ bill.end_date }}. +

    +{% endblock %} diff --git a/coin/billing/templates/billing/payment_howto.html b/coin/billing/templates/billing/payment_howto.html index e66ddf47239d25b7a8d9f4008db506674a0bb282..5f6f97207dbf82cfa02a3ded84e1427b1ab4f95f 100644 --- a/coin/billing/templates/billing/payment_howto.html +++ b/coin/billing/templates/billing/payment_howto.html @@ -1,31 +1,54 @@ {% load isptags %} -

    - Merci de préférer si possible le paiement par virement -

    -

    - Virement
    - Titulaire du compte : {% firstof branding.shortname branding.name %}
    - IBAN : {{ branding.bankinfo.iban|pretty_iban }}
    - - {% if branding.bankinfo.bic %} - BIC : {{ branding.bankinfo.bic }}
    - {% endif %} - {% if invoice %} - Merci de faire figurer la référence suivante sur votre virement : {{ invoice.number }} - {% endif %} -

    -

    - Chèque
    - {% with address=branding.registeredoffice %} - Paiement par chèque à l'ordre de "{{ branding.bankinfo.check_order }}" envoyé à l'adresse :
    - {% firstof branding.shortname branding.name %}
    - {% if address.extended_address %} - {{ address.extended_address }}
    - {% endif %} - {% if address.street_address %} - {{ address.street_address }}
    - {% endif %} - {{ address.postal_code }} {{ address.locality }} - {% endwith %} -

    +
    +
    +
    +
    +

    Coordonnées bancaires

    +
    +

    + Merci de privilégier les paiements par virement bancaire
    +
    + Titulaire du compte : {% firstof branding.shortname branding.name %}
    + IBAN : {{ branding.bankinfo.iban|pretty_iban }}
    + {% if branding.bankinfo.bic %} + BIC : {{ branding.bankinfo.bic }}
    + {% endif %} + +
    + + {% if bill %} + Prière de faire figurer l'une de vos reference adherent sur vos virement :
    + {% with member=bill.member %} + ID {{ member.pk }} et/ou {{ member.username }}
    + {% endwith %} + {% endif %} + + {% if member %} + Prière de faire figurer l'une de vos reference adherent sur vos virement :
    + ID {{ member.pk }} et/ou {{ member.username }}
    + {% endif %} +

    + +

    + Chèque
    + {% with address=branding.registeredoffice %} + Paiement par chèque à l'ordre de "{{ branding.bankinfo.check_order }}" envoyé à l'adresse :
    + {% firstof branding.shortname branding.name %}
    + {% if address.extended_address %} + {{ address.extended_address }}
    + {% endif %} + {% if address.street_address %} + {{ address.street_address }}
    + {% endif %} + {{ address.postal_code }} {{ address.locality }} + {% endwith %} +

    + + +
    +
    +
    +
    +
    + diff --git a/coin/billing/tests.py b/coin/billing/tests.py index 42dc8f55ada91c9216910f2fe697e35ecc4b7f80..6f7c314e7d3898cada3fbf9316b2fc4bfce51231 100644 --- a/coin/billing/tests.py +++ b/coin/billing/tests.py @@ -1,15 +1,20 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import datetime +from datetime import date +from dateutil.relativedelta import relativedelta from decimal import Decimal +from cStringIO import StringIO +from django.core import mail, management from django.conf import settings from django.test import TestCase, Client, override_settings +from django.core.exceptions import ValidationError from freezegun import freeze_time + from coin.members.tests import MemberTestsUtils from coin.members.models import Member, LdapUser -from coin.billing.models import Invoice, InvoiceQuerySet, InvoiceDetail, Payment +from coin.billing.models import Invoice, InvoiceQuerySet, InvoiceDetail, Payment, MembershipFee from coin.offers.models import Offer, OfferSubscription from coin.billing.create_subscriptions_invoices import create_member_invoice_for_a_period from coin.billing.create_subscriptions_invoices import create_all_members_invoices_for_a_period @@ -30,7 +35,7 @@ class BillingInvoiceCreationTests(TestCase): self.member.save() # Créé un abonnement self.subscription = OfferSubscription( - subscription_date=datetime.date(2014, 1, 10), + subscription_date=date(2014, 1, 10), member=self.member, offer=self.offer) self.subscription.save() @@ -47,7 +52,7 @@ class BillingInvoiceCreationTests(TestCase): """ # Demande la création de la première facture invoice = create_member_invoice_for_a_period( - self.member, datetime.date(2014, 1, 1)) + self.member, date(2014, 1, 1)) # La facture doit avoir les frais de mise en service # Pour tester cela on tri par montant d'item décroissant. # Comme dans l'offre créé, les initial_fees sont plus élevées que @@ -61,7 +66,7 @@ class BillingInvoiceCreationTests(TestCase): """ # Créé la facture pour le mois de janvier invoice = create_member_invoice_for_a_period( - self.member, datetime.date(2014, 1, 1)) + self.member, date(2014, 1, 1)) # Comme l'abonnement a été souscris le 10/01 et que la période de # facturation est de 3 mois, alors le prorata doit être : # janvier : 22j (31-9) @@ -87,22 +92,22 @@ class BillingInvoiceCreationTests(TestCase): invoice.details.create(label=self.offer.name, amount=self.offer.period_fees, offersubscription=self.subscription, - period_from=datetime.date(2014, 1, 1), - period_to=datetime.date(2014, 3, 31)) + period_from=date(2014, 1, 1), + period_to=date(2014, 3, 31)) # Créé une facturation pour cet abonnement pour une seconde période # de juin à aout invoice.details.create(label=self.offer.name, amount=self.offer.period_fees, offersubscription=self.subscription, - period_from=datetime.date(2014, 6, 1), - period_to=datetime.date(2014, 8, 31)) + period_from=date(2014, 6, 1), + period_to=date(2014, 8, 31)) # Demande la génération d'une facture pour février # Elle doit renvoyer None car l'offre est déjà facturée de # janvier à mars invoice_test_1 = create_member_invoice_for_a_period( - self.member, datetime.date(2014, 2, 1)) + self.member, date(2014, 2, 1)) self.assertEqual(invoice_test_1, None) # Demande la création d'une facture pour avril @@ -110,11 +115,11 @@ class BillingInvoiceCreationTests(TestCase): # que de 2 mois, d'avril à mai car il y a déjà une facture pour # la période de juin à aout invoice_test_2 = create_member_invoice_for_a_period( - self.member, datetime.date(2014, 4, 1)) + self.member, date(2014, 4, 1)) self.assertEqual(invoice_test_2.details.first().period_from, - datetime.date(2014, 4, 1)) + date(2014, 4, 1)) self.assertEqual(invoice_test_2.details.first().period_to, - datetime.date(2014, 5, 31)) + date(2014, 5, 31)) def test_invoice_amount(self): invoice = Invoice(member=self.member) @@ -123,18 +128,18 @@ class BillingInvoiceCreationTests(TestCase): invoice.details.create(label=self.offer.name, amount=100, offersubscription=self.subscription, - period_from=datetime.date(2014, 1, 1), - period_to=datetime.date(2014, 3, 31), + period_from=date(2014, 1, 1), + period_to=date(2014, 3, 31), tax=0) invoice.details.create(label=self.offer.name, amount=10, offersubscription=self.subscription, - period_from=datetime.date(2014, 6, 1), - period_to=datetime.date(2014, 8, 31), + period_from=date(2014, 6, 1), + period_to=date(2014, 8, 31), tax=10) - self.assertEqual(invoice.amount(), 111) + self.assertEqual(invoice.amount, 111) def test_invoice_partial_payment(self): invoice = Invoice(member=self.member) @@ -143,15 +148,15 @@ class BillingInvoiceCreationTests(TestCase): invoice.details.create(label=self.offer.name, amount=100, offersubscription=self.subscription, - period_from=datetime.date(2014, 1, 1), - period_to=datetime.date(2014, 3, 31), + period_from=date(2014, 1, 1), + period_to=date(2014, 3, 31), tax=0) invoice.validate() invoice.save() self.assertEqual(invoice.status, 'open') p1 = Payment.objects.create(member=self.member, - invoice=invoice, + bill=invoice, payment_mean='cash', amount=10) p1.save() @@ -160,7 +165,7 @@ class BillingInvoiceCreationTests(TestCase): self.assertEqual(invoice.status, 'open') p2 = Payment.objects.create(member=self.member, - invoice=invoice, + bill=invoice, payment_mean='cash', amount=90) p2.save() @@ -175,15 +180,15 @@ class BillingInvoiceCreationTests(TestCase): invoice.details.create(label=self.offer.name, amount=100, offersubscription=self.subscription, - period_from=datetime.date(2014, 1, 1), - period_to=datetime.date(2014, 3, 31), + period_from=date(2014, 1, 1), + period_to=date(2014, 3, 31), tax=0) invoice.details.create(label=self.offer.name, amount=10, offersubscription=self.subscription, - period_from=datetime.date(2014, 6, 1), - period_to=datetime.date(2014, 8, 31), + period_from=date(2014, 6, 1), + period_to=date(2014, 8, 31), tax=10) self.assertEqual(invoice.amount_before_tax(), 110) @@ -196,8 +201,8 @@ class BillingInvoiceCreationTests(TestCase): amount=100, quantity=0.5, offersubscription=None, - period_from=datetime.date(2014, 1, 1), - period_to=datetime.date(2014, 3, 31), + period_from=date(2014, 1, 1), + period_to=date(2014, 3, 31), tax=0) self.assertEqual(invoice.amount_before_tax(), 50) @@ -211,14 +216,14 @@ class BillingInvoiceCreationTests(TestCase): offer.save() # Créé un abonnement self.subscription = OfferSubscription( - subscription_date=datetime.date(2014, 1, 10), + subscription_date=date(2014, 1, 10), member=self.member, offer=offer) self.subscription.save() # Demande la création de la première facture invoice = create_member_invoice_for_a_period( - self.member, datetime.date(2014, 1, 1)) + self.member, date(2014, 1, 1)) # Vérifie qu'il n'y a pas l'offre dans la facture, si c'est le cas génère une exception if invoice: @@ -250,7 +255,7 @@ class BillingTests(TestCase): client = Client() client.login(username=username, password='1234') # Tente de télécharger la facture - response = client.get('/billing/invoice/%i/pdf' % invoice.id) + response = client.get('/billing/bill/%i/pdf' % invoice.id) # Vérifie return code 200 et contient chaine %PDF-1. self.assertContains(response, b'%PDF-1.', status_code=200, html=False) member.delete() @@ -291,7 +296,7 @@ class BillingTests(TestCase): # Vérifie que A a reçu retour OK 200 self.assertEqual(response.status_code, 200) # Tente de télécharger la facture pdf de A en tant que A - response = client.get('/billing/invoice/%i/pdf' % invoice_a.id) + response = client.get('/billing/bill/%i/pdf' % invoice_a.id) # Vérifie que A a reçu retour OK 200 self.assertEqual(response.status_code, 200) @@ -303,7 +308,7 @@ class BillingTests(TestCase): # Vérifie que B a reçu retour Forbissen 403 self.assertEqual(response.status_code, 403) # Tente de télécharger la facture pdf de A en tant que B - response = client.get('/billing/invoice/%i/pdf' % invoice_a.id) + response = client.get('/billing/bill/%i/pdf' % invoice_a.id) # Vérifie que B a reçu retour Forbidden 403 self.assertEqual(response.status_code, 403) @@ -314,7 +319,7 @@ class BillingTests(TestCase): class InvoiceQuerySetTests(TestCase): def test_get_first_invoice_number_ever(self): self.assertEqual( - Invoice.objects.get_next_invoice_number(datetime.date(2016,1,1)), + Invoice.objects.get_next_invoice_number(date(2016,1,1)), '2016-01-000001') @freeze_time('2016-01-01') @@ -324,7 +329,7 @@ class InvoiceQuerySetTests(TestCase): # … Does not affect the numbering of following month. self.assertEqual( - Invoice.objects.get_next_invoice_number(datetime.date(2016,2,15)), + Invoice.objects.get_next_invoice_number(date(2016,2,15)), '2016-02-000001') @freeze_time('2016-01-01') @@ -336,31 +341,31 @@ class InvoiceQuerySetTests(TestCase): @freeze_time('2016-01-01') def test_get_second_of_month_invoice_number(self): - first_bill = Invoice.objects.create(date=datetime.date(2016,1,1)) + first_bill = Invoice.objects.create(date=date(2016,1,1)) first_bill.validate() self.assertEqual( - Invoice.objects.get_next_invoice_number(datetime.date(2016,1,1)), + Invoice.objects.get_next_invoice_number(date(2016,1,1)), '2016-01-000002') def test_get_right_year_invoice_number(self): with freeze_time('2016-01-01'): - Invoice.objects.create(date=datetime.date(2016, 1, 1)).validate() + Invoice.objects.create(date=date(2016, 1, 1)).validate() with freeze_time('2017-01-01'): - Invoice.objects.create(date=datetime.date(2017, 1, 1)).validate() + Invoice.objects.create(date=date(2017, 1, 1)).validate() with freeze_time('2018-01-01'): - Invoice.objects.create(date=datetime.date(2018, 1, 1)).validate() + Invoice.objects.create(date=date(2018, 1, 1)).validate() self.assertEqual( - Invoice.objects.get_next_invoice_number(datetime.date(2017, 1, 1)), + Invoice.objects.get_next_invoice_number(date(2017, 1, 1)), '2017-01-000002') def test_bill_date_is_validation_date(self): - bill = Invoice.objects.create(date=datetime.date(2016,1,1)) - self.assertEqual(bill.date, datetime.date(2016,1,1)) + bill = Invoice.objects.create(date=date(2016,1,1)) + self.assertEqual(bill.date, date(2016,1,1)) with freeze_time('2017-01-01'): bill.validate() - self.assertEqual(bill.date, datetime.date(2017, 1, 1)) + self.assertEqual(bill.date, date(2017, 1, 1)) self.assertEqual(bill.number, '2017-01-000001') @@ -400,3 +405,81 @@ class PaymentInvoiceAutoReconciliationTests(TestCase): johndoe.delete() +class MembershipFeeTests(TestCase): + def test_mandatory_start_date(self): + member = Member(first_name='foo', last_name='foo', password='foo', email='foo') + member.save() + + # If there is no start_date clean_fields() should raise an + # error but not clean(). + membershipfee = MembershipFee(member=member) + self.assertRaises(ValidationError, membershipfee.clean_fields) + self.assertIsNone(membershipfee.clean()) + + # If there is a start_date, everything is fine. + membershipfee = MembershipFee(member=member, start_date=date.today()) + self.assertIsNone(membershipfee.clean_fields()) + self.assertIsNone(membershipfee.clean()) + + member.delete() + + def test_member_end_date_of_memberhip(self): + """ + Test que end_date_of_membership d'un membre envoi bien la date de fin d'adhésion + """ + # Créer un membre + first_name = 'Tin' + last_name = 'Tin' + username = MemberTestsUtils.get_random_username() + member = Member(first_name=first_name, + last_name=last_name, username=username) + member.save() + + start_date = date.today() + end_date = start_date + relativedelta(years=+1) + + # Créé une cotisation + membershipfee = MembershipFee(member=member, amount=20, + start_date=start_date, + end_date=end_date) + membershipfee.save() + + self.assertEqual(member.end_date_of_membership(), end_date) + + def test_member_is_paid_up(self): + """ + Test l'état "a jour de cotisation" d'un adhérent. + """ + # Créé un membre + first_name = 'Capitain' + last_name = 'Haddock' + username = MemberTestsUtils.get_random_username() + member = Member(first_name=first_name, + last_name=last_name, username=username) + member.save() + + start_date = date.today() + end_date = start_date + relativedelta(years=+1) + + # Test qu'un membre sans cotisation n'est pas à jour + self.assertEqual(member.is_paid_up(), False) + + # Créé une cotisation passée + membershipfee = MembershipFee(member=member, amount=20, + start_date=date.today() + + relativedelta(years=-1), + end_date=date.today() + relativedelta(days=-10)) + membershipfee.save() + # La cotisation s'étant terminée il y a 10 jours, il ne devrait pas + # être à jour de cotistion + self.assertEqual(member.is_paid_up(), False) + + # Créé une cotisation actuelle + membershipfee = MembershipFee(member=member, amount=20, + start_date=date.today() + + relativedelta(days=-10), + end_date=date.today() + relativedelta(days=+10)) + membershipfee.save() + # La cotisation se terminant dans 10 jour, il devrait être à jour + # de cotisation + self.assertEqual(member.is_paid_up(), True) diff --git a/coin/billing/urls.py b/coin/billing/urls.py index cf32e5e0014da8cf34458f29ecc4454e90157348..9444397a3a06fadab1de77b73d41d3090e54e9a3 100644 --- a/coin/billing/urls.py +++ b/coin/billing/urls.py @@ -1,13 +1,11 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.conf.urls import patterns, url +from django.conf.urls import url from django.views.generic import DetailView from coin.billing import views -urlpatterns = patterns( - '', - url(r'^invoice/(?P.+)/pdf$', views.invoice_pdf, name="invoice_pdf"), - url(r'^invoice/(?P.+)$', views.invoice, name="invoice"), - # url(r'^invoice/(?P.+)/validate$', views.invoice_validate, name="invoice_validate"), -) +urlpatterns = [ + #'', + url(r'^bill/(?P.+)/pdf$', views.bill_pdf, name="bill_pdf"), +] diff --git a/coin/billing/utils.py b/coin/billing/utils.py index 86664f932e155763116cbc1df3397f278843ad6e..902dd0c6fb33843b90685b2c55606342576d8158 100644 --- a/coin/billing/utils.py +++ b/coin/billing/utils.py @@ -4,23 +4,24 @@ from __future__ import unicode_literals from django.shortcuts import render, get_object_or_404 from django.core.exceptions import PermissionDenied -from coin.billing.models import Invoice +from coin.billing.models import Bill, Invoice -def get_invoice_from_id_or_number(id): +def get_bill_from_id_or_number(id): """ - Return an invoice using id as invoice id or failing as invoice number + Return an bill using id as bill id (or failing as invoice number) """ + try: - return Invoice.objects.get(pk=id) + return Bill.objects.get(pk=id).as_child() except: return get_object_or_404(Invoice, number=id) -def assert_user_can_view_the_invoice(request, invoice): +def assert_user_can_view_the_bill(request, bill): """ - Raise PermissionDenied if logged user can't access given invoice + Raise PermissionDenied if logged user can't access given bill """ - if not invoice.has_owner(request.user.username)\ + if not bill.has_owner(request.user.username)\ and not request.user.is_superuser: - raise PermissionDenied \ No newline at end of file + raise PermissionDenied diff --git a/coin/billing/views.py b/coin/billing/views.py index 0af6ae20156a0a1cf8b51959fd71ba1b7791b199..036ade797c689da115079296e7fad162b6dd3726 100644 --- a/coin/billing/views.py +++ b/coin/billing/views.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse from django.template import RequestContext from django.shortcuts import render from django.contrib import messages @@ -11,33 +11,24 @@ from sendfile import sendfile from coin.billing.models import Invoice from coin.members.models import Member from coin.html2pdf import render_as_pdf -from coin.billing.utils import get_invoice_from_id_or_number, assert_user_can_view_the_invoice +from coin.billing.create_subscriptions_invoices import create_all_members_invoices_for_a_period +from coin.billing.utils import get_bill_from_id_or_number, assert_user_can_view_the_bill -def invoice_pdf(request, id): - """ - Renvoi une facture générée en format pdf - id peut être soit la pk d'une facture, soit le numero de facture - """ - invoice = get_invoice_from_id_or_number(id) - - assert_user_can_view_the_invoice(request, invoice) - pdf_filename = 'Facture_%s.pdf' % invoice.number - - return sendfile(request, invoice.pdf.path, - attachment=True, attachment_filename=pdf_filename) - - -def invoice(request, id): +def bill_pdf(request, id): """ - Affiche une facture et son détail - id peut être soit la pk d'une facture, soit le numero de facture + Renvoi une note générée en format pdf + id peut être soit la pk d'une note, soit le numero d'une facture """ - invoice = get_invoice_from_id_or_number(id) + bill = get_bill_from_id_or_number(id) - assert_user_can_view_the_invoice(request, invoice) + assert_user_can_view_the_bill(request, bill) - return render(request, 'billing/invoice.html', {"invoice": invoice}) + human_type = bill.__class__._meta.verbose_name + id_for_filename = bill.number if bill.type == "Invoice" else bill.pk - return response + pdf_filename = '%s_%s.pdf' % (human_type, id_for_filename) + + return sendfile(request, bill.pdf.path, + attachment=True, attachment_filename=pdf_filename) diff --git a/coin/configuration/admin.py b/coin/configuration/admin.py index 905ab6b5f37530b2bd245cf96ceb8163b95cbfcc..e0dd1e2654ece15edd5c84119e98ad334daaa071 100644 --- a/coin/configuration/admin.py +++ b/coin/configuration/admin.py @@ -1,11 +1,15 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.contrib import admin +from django.shortcuts import get_object_or_404 +from django.contrib import admin, messages +from django.http import HttpResponseRedirect +from django.conf.urls import url +from django.core.urlresolvers import reverse from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin from coin.resources.models import IPSubnet -from coin.configuration.models import Configuration +from coin.configuration.models import Configuration, IPConfiguration from coin.configuration.forms import ConfigurationForm """ @@ -14,15 +18,17 @@ ConfigurationAdminFormMixin. This make use of ConfigurationForm form that filter offersubscription select input to avoid selecting wrong subscription. """ + class IPSubnetInline(admin.TabularInline): model = IPSubnet extra = 0 + fields = ["inet", "ip_pool"] class ParentConfigurationAdmin(PolymorphicParentModelAdmin): base_model = Configuration polymorphic_list = True - list_display = ('model_name','configuration_type_name', 'offersubscription', 'offer_subscription_member') + list_display = ('model_name', 'configuration_type_name', 'offersubscription', 'offer_subscription_member') def offer_subscription_member(self, config): return config.offersubscription.member @@ -34,7 +40,8 @@ class ParentConfigurationAdmin(PolymorphicParentModelAdmin): ex :((VPNConfiguration, VPNConfigurationAdmin), (ADSLConfiguration, ADSLConfigurationAdmin)) """ - return (tuple((x.base_model, x) for x in PolymorphicChildModelAdmin.__subclasses__())) + + return tuple((x.base_model, x) for x in ChildConfigurationAdmin.__subclasses__()) def get_urls(self): """ @@ -53,10 +60,152 @@ class ParentConfigurationAdmin(PolymorphicParentModelAdmin): return urls -class ConfigurationAdminFormMixin(object): +class ChildConfigurationAdmin(PolymorphicChildModelAdmin): + base_form = ConfigurationForm - # For each child (admin object for configurations), this will display - # an inline form to assign IP addresses. - inlines = (IPSubnetInline, ) + + change_form_template = "admin/configuration/configuration/change_form.html" + + specific_fields = [] + + def get_inlines(self, request, obj=None): + + if isinstance(obj, IPConfiguration): + return tuple(IPSubnetInline, ) + else: + return tuple() + + def get_fieldsets(self, request, obj=None): + fields = [('', {'fields': ['offersubscription', + 'comment', + 'provisioned', + 'status']})] + + if self.specific_fields: + fields.append(["Configuration spécifique", + {"fields": tuple(self.specific_fields)}]) + + if hasattr(obj, "provisioning_infos") and obj.provisioning_infos: + fields.append(["Informations pour le provisionnement", + {"fields": tuple(obj.provisioning_infos)}]) + + if hasattr(obj, "ipv4_endpoint") and hasattr(obj, "ipv6_endpoint"): + fields.append(["Adresses IP (endpoints)", + {"fields": tuple(["ipv4_endpoint", "ipv6_endpoint"])}]) + + return fields + + def get_readonly_fields(self, request, obj=None): + + readonly_fields = [] + if self.base_model.provision_is_managed_via_hook(): + readonly_fields.append("provisioned") + + if self.base_model.state_is_managed_via_hook(): + readonly_fields.append("status") + + # If this config is provisioned, we shouldn't change the subscription or the provisioning infos + if obj and obj.provisioned != "no": + readonly_fields.append("offersubscription") + if hasattr(obj, "provisioning_infos") and obj.provisioning_infos: + readonly_fields.extend(obj.provisioning_infos) + + return readonly_fields + + def get_urls(self): + """ + Custom admin urls + """ + urls = super(ChildConfigurationAdmin, self).get_urls() + return urls + [ + url(r'^provision/(?P.+)$', + self.admin_site.admin_view(self.provision_view), + name='configuration_provision'), + url(r'^deprovision/(?P.+)$', + self.admin_site.admin_view(self.deprovision_view), + name='configuration_deprovision'), + ] + + def provision_view(self, request, id): + # TODO : Add better perm here + if request.user.is_superuser: + conf = get_object_or_404(Configuration, pk=id) + conf.provision() + #try: + # conf.provision() + #except Exception as e: + # messages.error(request, "Le provisionnement a échoué : %s" % e) + #else: + # messages.success(request, "Le provisionnement a été déclenché") + else: + messages.error(request, + "Vous n'avez pas l'autorisation de provisionner / déprovisionner des configurations.") + + return HttpResponseRedirect(reverse('admin:configuration_configuration_change', + args=(id,))) + + def deprovision_view(self, request, id): + # TODO : Add better perm here + if request.user.is_superuser: + conf = get_object_or_404(Configuration, pk=id) + try: + conf.deprovision() + except Exception as e: + messages.error(request, "Le déprovisionnement a échoué : %s" % e) + else: + messages.success(request, "Le déprovisionnement a été déclenché") + else: + messages.error(request, + "Vous n'avez pas l'autorisation de provisionner / déprovisionner des configurations.") + + return HttpResponseRedirect(reverse('admin:configuration_configuration_change', + args=(id,))) + +class ChildConfigurationAdminInline(admin.StackedInline): + + specific_fields = [] + + def get_fieldsets(self, request, obj=None): + + fields = [('', {'fields': ['comment', + 'provisioned', + 'status']})] + + conf = obj.configuration + + if self.specific_fields: + fields.append(["Configuration spécifique", + {"fields": tuple(self.specific_fields)}]) + + if hasattr(conf, "provisioning_infos") and conf.provisioning_infos: + fields.append(["Informations pour le provisionnement", + {"fields": conf.provisioning_infos}]) + + if hasattr(conf, "ipv4_endpoint") and hasattr(conf, "ipv6_endpoint"): + fields.append(["Adresses IP (endpoints)", + {"fields": ["ipv4_endpoint", "ipv6_endpoint"]}]) + + return fields + + def get_readonly_fields(self, request, obj=None): + + readonly_fields = [] + if self.model.provision_is_managed_via_hook(): + readonly_fields.append("provisioned") + + if self.model.state_is_managed_via_hook(): + readonly_fields.append("status") + + conf = obj.configuration + + # If this config is provisioned, we shouldn't change the subscription or the provisioning infos + if conf and conf.provisioned != "no": + readonly_fields.append("offersubscription") + if hasattr(conf, "provisioning_infos") and conf.provisioning_infos: + readonly_fields.extend(conf.provisioning_infos) + + return readonly_fields + + admin.site.register(Configuration, ParentConfigurationAdmin) diff --git a/coin/configuration/forms.py b/coin/configuration/forms.py index c6b59fa1ef5a54d7c92bcfc68ddd8181d90b8de9..8c6e02ff24493f14c408e96d178f5bcaab36add1 100644 --- a/coin/configuration/forms.py +++ b/coin/configuration/forms.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.forms import ModelForm, ValidationError from django.db.models import Q from django import forms @@ -9,7 +8,7 @@ from coin.offers.models import OfferSubscription from coin.configuration.models import Configuration -class ConfigurationForm(ModelForm): +class ConfigurationForm(forms.ModelForm): class Meta: model = Configuration widgets = { @@ -24,11 +23,12 @@ class ConfigurationForm(ModelForm): and that haven't already a configuration associated with """ super(ConfigurationForm, self).__init__(*args, **kwargs) - if self.instance: + if self.instance and not hasattr(self.instance, "offersubscription"): queryset = OfferSubscription.objects.filter( Q(offer__configuration_type=self.instance.model_name) & ( Q(configuration=None) | Q(configuration=self.instance.pk))) - self.fields['offersubscription'].queryset = queryset + if 'offersubscription' in self.fields: + self.fields['offersubscription'].queryset = queryset def clean_offersubscription(self): """ @@ -37,6 +37,6 @@ class ConfigurationForm(ModelForm): """ offersubscription = self.cleaned_data['offersubscription'] if offersubscription.offer.configuration_type != self.instance.model_name(): - raise ValidationError('Administrative subscription must refer an offer having a "{}" configuration type.'.format(self.instance.model_name())) + raise forms.ValidationError('Administrative subscription must refer an offer having a "{}" configuration type.'.format(self.instance.model_name())) return offersubscription diff --git a/coin/configuration/management/__init__.py b/coin/configuration/management/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/coin/configuration/management/commands/__init__.py b/coin/configuration/management/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/coin/configuration/management/commands/fill_with_toy_data.py b/coin/configuration/management/commands/fill_with_toy_data.py new file mode 100644 index 0000000000000000000000000000000000000000..9db04c3f055b2ae6c6b87401ca590b1566e8c057 --- /dev/null +++ b/coin/configuration/management/commands/fill_with_toy_data.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from argparse import RawTextHelpFormatter +from django.core.management.base import BaseCommand, CommandError +from django.contrib.auth.hashers import make_password + +from coin.resources.models import IPPool +from coin.offers.models import Offer, OfferSubscription, OfferIPPool +from coin.configuration.models import Configuration +from coin.members.models import Member + +################################################################################ + + +class Command(BaseCommand): + + help = __doc__ + + def create_parser(self, *args, **kwargs): + parser = super(Command, self).create_parser(*args, **kwargs) + parser.formatter_class = RawTextHelpFormatter + return parser + + def handle(self, *args, **options): + + Member.objects.all().delete() + IPPool.objects.all().delete() + Offer.objects.all().delete() + OfferIPPool.objects.all().delete() + + admin = Member.objects.create_superuser(username="admin", first_name="Syssa", last_name="Mine", email="admin@yolo.test", password="Yunohost") + member1 = Member.objects.create(username="sasha", first_name="Sasha", last_name="Yolo", email="sasha@yolo.test") + member2 = Member.objects.create(username="camille", first_name="Camille", last_name="Yolo", email="camille@yolo.test") + admin.save() + member1.save() + member2.save() + + pool1 = IPPool.objects.create(name="Pool d'IP pour VPS", default_subnetsize=32, inet="10.20.0.0/24") + pool2 = IPPool.objects.create(name="Pool d'IP pour VPN", default_subnetsize=32, inet="10.30.0.0/24") + pool1.save() + pool2.save() + + vps_de_test = Offer.objects.create(name="VPS de test", reference="vps-test", configuration_type="VPS", period_fees=0, initial_fees=0, non_billable=True) + vps_small = Offer.objects.create(name="VPS 1core 1G", reference="vps-1core-1G", configuration_type="VPS", period_fees=8, initial_fees=0, non_billable=False) + vps_big = Offer.objects.create(name="VPS 2core 2G", reference="vps-2core-2G", configuration_type="VPS", period_fees=15, initial_fees=0, non_billable=False) + vps_de_test.save() + vps_small.save() + vps_big.save() + OfferIPPool.objects.create(ip_pool=pool1, to_assign=True, offer=vps_de_test).save() + OfferIPPool.objects.create(ip_pool=pool1, to_assign=True, offer=vps_small).save() + OfferIPPool.objects.create(ip_pool=pool1, to_assign=True, offer=vps_big).save() + + vpn_de_test = Offer.objects.create(name="VPN de test", reference="vpn-test", configuration_type="VPN", period_fees=0, initial_fees=0, non_billable=True) + vpn_standard = Offer.objects.create(name="VPN standard", reference="vpn-standard", configuration_type="VPN", period_fees=4, initial_fees=0, non_billable=False) + vpn_de_test.save() + vpn_standard.save() + OfferIPPool.objects.create(ip_pool=pool2, to_assign=True, offer=vpn_de_test).save() + OfferIPPool.objects.create(ip_pool=pool2, to_assign=True, offer=vpn_standard).save() diff --git a/coin/configuration/management/commands/update_configuration_states.py b/coin/configuration/management/commands/update_configuration_states.py new file mode 100644 index 0000000000000000000000000000000000000000..e57ccdb7924b8be1de931b6e340470802ad048c5 --- /dev/null +++ b/coin/configuration/management/commands/update_configuration_states.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +""" +Fetch all states for configuration of a given type (e.g. VPS, ...) using the +FETCH_STATES hook define for this conf type using settings.HOOKS. + +This command is meant to be called regularly from a cron job like : + + */10 * * * * root manage.py update_configuration_states VPS + + +The {conf_list} is a python list containing dicts like : + [ {"id": 4, "offer_name": "VPS-de-test", "offer_ref": "vps-test", "username": "sam" }, + {"id": 6, "offer_name": "VPS-de-test", "offer_ref": "vps-test", "username": "saeed" }, + {"id": 7, "offer_name": "VPS-2G-500", "offer_ref": "vps-2g", "username": "sasha" } + ] + +The {conf_list_csv} contains the same kind of information, but in the form of a CSV +which is expected to be easier to interface with for bash hooks. + + 4;VPS-de-test;vps-test;sam + 6;VPS-de-test;vps-test;seed + 7;VPS-2G-500;vps-2g;sasha + +The hook is expected to return the following kind of output (loaded from json or yaml or ...) + + [{"id":4, "provisioned": "disabled", "status": "down", "status_color": "red"}, + {"id":6, "provisioned": "yes", "status": "running", "status_color": "green"}, + {"id":7, "provisioned": "ongoing", "status": "booting", "status_color": "orange"} + ] +""" + +from __future__ import unicode_literals + +from argparse import RawTextHelpFormatter +from django.core.management.base import BaseCommand, CommandError + +from coin.configuration.models import Configuration +from coin.utils import get_descendant_classes + +################################################################################ + + +class Command(BaseCommand): + + help = __doc__ + + def create_parser(self, *args, **kwargs): + parser = super(Command, self).create_parser(*args, **kwargs) + parser.formatter_class = RawTextHelpFormatter + return parser + + def add_arguments(self, parser): + + parser.add_argument( + 'conf_type', + type=str, + help="Something like VPS, VPN, Housing, ..." + ) + + def handle(self, *args, **options): + + if not options["conf_type"] != "": + raise CommandError("You must provide a configuration type") + + conf_classes = {c.url_namespace: c for c in get_descendant_classes(Configuration)} + if options["conf_type"] not in conf_classes: + raise CommandError("Unknown conf type %s ... known conf types are : %s" % (options["conf_type"], ', '.join(conf_classes.keys()))) + + conf_classes[options["conf_type"]].fetch_and_update_all_states() diff --git a/coin/configuration/migrations/0005_auto_20200717_1733.py b/coin/configuration/migrations/0005_auto_20200717_1733.py new file mode 100644 index 0000000000000000000000000000000000000000..73aec1675b28dd4fb274cbf6d8b229ea83eeeff6 --- /dev/null +++ b/coin/configuration/migrations/0005_auto_20200717_1733.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('configuration', '0004_auto_20161015_1837'), + ] + + operations = [ + migrations.AddField( + model_name='configuration', + name='last_status_update', + field=models.DateTimeField(null=True, verbose_name="derni\xe8re mise \xe0 jour de l'\xe9tat", blank=True), + ), + migrations.AddField( + model_name='configuration', + name='provisioned', + field=models.CharField(default='no', max_length=16, verbose_name='provisionn\xe9', choices=[('no', 'Non'), ('ongoing', 'En cours'), ('yes', 'Oui'), ('disabled', 'D\xe9sactiv\xe9 temporairement')]), + ), + migrations.AddField( + model_name='configuration', + name='status', + field=models.CharField(default='N/A', max_length=32, verbose_name='status'), + ), + migrations.AddField( + model_name='configuration', + name='status_color', + field=models.CharField(default='grey', max_length=16, blank=True, choices=[('green', 'green'), ('orange', 'orange'), ('red', 'red'), ('grey', 'grey')]), + ), + ] diff --git a/coin/configuration/migrations/0006_auto_20201030_1745.py b/coin/configuration/migrations/0006_auto_20201030_1745.py new file mode 100644 index 0000000000000000000000000000000000000000..d3dc36f36aa5284dbe3a861f237693d99f90dfb5 --- /dev/null +++ b/coin/configuration/migrations/0006_auto_20201030_1745.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('configuration', '0005_auto_20200717_1733'), + ] + + operations = [ + migrations.AlterField( + model_name='configuration', + name='comment', + field=models.CharField(help_text="Ce texte s'affiche dans l'interface de l'abonn\xe9\u22c5e", max_length=512, verbose_name='commentaire', blank=True), + ), + ] diff --git a/coin/configuration/models.py b/coin/configuration/models.py index 8f54268ede1d8d9fef253ccb9f7f66f4ab5bf761..55b114e42c867c81daeaeddf978a740f371ffb78 100644 --- a/coin/configuration/models.py +++ b/coin/configuration/models.py @@ -1,5 +1,13 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import datetime +import csv +# In Python3, StringIO will just become io +import StringIO as io + +import logging + +from netfields import InetAddressField, NetManager from django.db import models from polymorphic import PolymorphicModel @@ -7,8 +15,14 @@ from coin.offers.models import OfferSubscription from django.db.models.signals import post_save, post_delete from django.core.exceptions import ObjectDoesNotExist from django.dispatch import receiver +from django.conf import settings +from django.utils.safestring import mark_safe +from django.core.exceptions import ValidationError +from coin.utils import get_descendant_classes +from coin.hooks import HookManager from coin.resources.models import IPSubnet +from coin import validation """ Implementation note : Configuration is a PolymorphicModel. @@ -17,7 +31,7 @@ technical informations of a subscription. To add a new configuration backend, you have to create a new app with a model which inherit from Configuration. -Your model can implement Meta verbose_name to have human readable name and a +Your model can implement Meta verbose_name to have human readable name and a url_namespace variable to specify the url namespace used by this model. """ @@ -27,7 +41,35 @@ class Configuration(PolymorphicModel): related_name='configuration', verbose_name='abonnement') comment = models.CharField(blank=True, max_length=512, - verbose_name="commentaire") + verbose_name="commentaire", + help_text="Ce texte s'affiche dans l'interface de l'abonné⋅e") + + # Is this service configured / served on the actual infrastructure ? + # This can be 'no', 'yes', 'ongoing' (e.g. machine being configured) or 'temporary disabled' + provisioned_choices = [("no", "Non"), ("ongoing", "En cours"), ("yes", "Oui"), ("disabled", "Désactivé temporairement")] + provisioned = models.CharField(default="no", max_length=16, choices=provisioned_choices, blank=False, null=False, verbose_name='provisionné') + + # Subclasses can fill this list with stuff like "operating_system" + # or "ssh_key" or "password" or whichever field is related to provisionning + provisioning_infos = [] + + # Is this service actually running and usable ? + # E.g. a VPS can be provisionned but be powered down + # The value is free, to be set manually by the admin, or (if state hook is enabled) via a hook. + # The status_color can be used to signify if status is good / bad / other... + status = models.CharField(default="N/A", blank=False, null=False, max_length=32, verbose_name="status") + status_color_choices = ["green", "orange", "red", "grey"] + status_color = models.CharField(default="grey", max_length=16, choices=[(c, c) for c in status_color_choices], blank=True, null=False) + last_status_update = models.DateTimeField(null=True, blank=True, + verbose_name="dernière mise à jour de l'état") + + @classmethod + def provision_is_managed_via_hook(self): + return HookManager.is_defined(self.url_namespace, "PROVISION") + + @classmethod + def state_is_managed_via_hook(self): + return HookManager.is_defined(self.url_namespace, "FETCH_ALL_STATES") @staticmethod def get_configurations_choices_list(): @@ -35,15 +77,147 @@ class Configuration(PolymorphicModel): Génère automatiquement la liste de choix possibles de configurations en fonction des classes enfants de Configuration """ - return tuple((x().__class__.__name__,x()._meta.verbose_name) - for x in Configuration.__subclasses__()) - + return tuple([(c.__name__, c._meta.verbose_name) for c in get_descendant_classes(Configuration)]) + + def convert_to_dict_for_hook(self): + # FIXME : check assertions here + return {"id": self.pk, + "offer_name": self.offersubscription.offer.name.encode('utf-8'), + "offer_ref": self.offersubscription.offer.reference.encode('utf-8'), + "username": self.offersubscription.member.username.encode('utf-8'), + } + + def provision(self): + assert self.provisioned == "no", "Cette configuration est déjà provisionnée" + success, out, err = HookManager.run(self.configuration_type_name(), "PROVISION", **(self.convert_to_dict_for_hook())) + if not success: + raise Exception("Le provisionnement a échoué : %s" % err) + # If state is managed via hooks, this info will be updated via the hook. + # So for now we just set it to 'ongoing' so that the button 'provision' is not showed while we wait for the state to be updated + if self.state_is_managed_via_hook(): + self.provisioned = "ongoing" + # Otherwise, just flag this as provisioned because no hook will update this info + else: + self.provisioned = "yes" + self.save() + + def deprovision(self): + assert self.provisioned == "yes", "Cette configuration n'est pas provisionnée" + success, out, err = HookManager.run(self.configuration_type_name(), "DEPROVISION", **(self.convert_to_dict_for_hook())) + if not success: + raise Exception("Le déprovisionnement a échoué : %s" % err) + self.provisioned = "no" + self.save() + + def update_state(self, provisioned=None, status=None, status_color=None, **kwargs): + if provisioned is not None: + provisioned = 'yes' if provisioned is True else provisioned + provisioned = 'no' if provisioned is False else provisioned + self.provisioned = provisioned + if status is not None: + self.status = status + if status_color is not None: + self.status_color = status_color + for key, value in kwargs.iteritems(): + if value is not None: + setattr(self, key, value) + if any([info is not None for info in [provisioned, status, status_color]]): + self.last_status_update = datetime.datetime.now() + self.save() + + @classmethod + def fetch_and_update_all_states(self): + """ + Fetch all states for configuration of a given type (e.g. VPS, ...) using the + FETCH_ALL_STATES hook define for this conf type using settings.HOOKS. + + The {conf_list} is a python list containing dicts like : + [ {"id": 4, "offer_name": "VPS-de-test", "offer_ref": "vps-test", "username": "sam" }, + {"id": 6, "offer_name": "VPS-de-test", "offer_ref": "vps-test", "username": "saeed" }, + {"id": 7, "offer_name": "VPS-2G-500", "offer_ref": "vps-2g", "username": "sasha" } + ] + + The {conf_list_csv} contains the same kind of information, but in the form of a CSV + which is expected to be easier to interface with for bash hooks. + + 4;VPS-de-test;vps-test;sam + 6;VPS-de-test;vps-test;seed + 7;VPS-2G-500;vps-2g;sasha + + The hook is expected to return the following kind of output (loaded from json or yaml or ...) + + [{"id":4, "provisioned": "disabled", "status": "down", "status_color": "red"}, + {"id":6, "provisioned": "yes", "status": "running", "status_color": "green"}, + {"id":7, "provisioned": "ongoing", "status": "booting", "status_color": "orange"} + ] + """ + assert self.state_is_managed_via_hook(), "There is no hook defined for %s" % self.url_namespace + confs_to_update = self.objects.all() + + conf_list = [c.convert_to_dict_for_hook() for c in confs_to_update] + conf_list_csv = io.StringIO() + info_keys = conf_list[0].keys() + writer = csv.writer(conf_list_csv, delimiter=str(';'), quotechar=str('"'), quoting=csv.QUOTE_MINIMAL) + writer.writerow([key for key in info_keys]) + for c in conf_list: + row = [] + for info in info_keys: + try: + c[info] = c[info].encode('utf8') + except: + pass + row.append(c[info]) + writer.writerow(row) + conf_list_csv = conf_list_csv.getvalue() + success, out, err = HookManager.run(self.url_namespace, "FETCH_ALL_STATES", conf_list=conf_list, conf_list_csv=conf_list_csv) + + if not success: + raise Exception("Some errors happened during the execution of FETCH_ALL_STATES for %s : %s" % (self.url_namespace, err)) + + assert isinstance(out, list), "Was expecting to get a list as output of FETCH_ALL_STATES" + for state_infos in out: + assert isinstance(state_infos, dict) and "id" in state_infos, "Was expecting to get a list of dict as output of FETCH_ALL_STATES with at least 'id' in it" + conf_to_update = Configuration.objects.get(pk=state_infos.pop("id")) + conf_to_update.update_state(**state_infos) + + def get_state_display(self): + + if self.provisioned == "yes": + text = self.status + color = self.status_color + elif self.provisioned == "ongoing": + text = "Pas encore provisionné" + color = "orange" + elif self.provisioned == "disabled": + text = "Désactivé" + color = "red" + else: + text = "Pas encore provisionné" + color = "grey" + + return (text, color) + + def get_state_text_display(self): + + return self.get_state_display()[0] + + def get_state_icon_display(self): + + text, color = self.get_state_display() + text = "Status: %s\nDernière mise à jour: %s" % (text, str(self.last_status_update)) + + return mark_safe(''.format(color=color, text=text)) + get_state_icon_display.short_description = 'État' + + def __str__(self): + return str(self.offersubscription) + def model_name(self): return self.__class__.__name__ model_name.short_description = 'Nom du modèle' def configuration_type_name(self): - return self._meta.verbose_name + return self.url_namespace configuration_type_name.short_description = 'Type' def get_absolute_url(self): @@ -52,7 +226,7 @@ class Configuration(PolymorphicModel): Une url doit être nommée "details" """ from django.core.urlresolvers import reverse - return reverse('%s:details' % self.get_url_namespace(), + return reverse('%s:details' % self.get_url_namespace(), args=[str(self.id)]) def get_url_namespace(self): @@ -66,12 +240,180 @@ class Configuration(PolymorphicModel): else: return self.model_name().lower() + # + # Standard hook to fetch states + # + + def _has_hook_state(self): + return HookManager.is_defined(self.configuration_type_name(), "GET_STATE") + + def _get_state(self, key=None): + if self._has_hook_state(): + # FIXME : gotta see what info to feed exactly + state = HookManager.run(self.configuration_type_name(), "GET_STATE", self) + if key is None: + return state + else: + value = state.get(key, None) + return value if value else "N/A" + else: + return "Inconnu (pas de hook provisionné)" + + def is_provisioned(self): + return self._get_state("provisioned") + is_provisioned.short_description = 'Provisionné' + + def state_display(self): + return self._get_state("display") + state_display.short_description = 'État' + + # + # Standard hook to provision + # + + def _has_hook_provision(self): + return HookManager.is_defined(self.configuration_type_name(), "PROVISION") + + + def bulk_related_objects(self, objs, *args, **kwargs): + # Fix delete screen. Workaround for https://github.com/chrisglass/django_polymorphic/issues/34 + return super(Configuration, self).bulk_related_objects(objs, *args, **kwargs).non_polymorphic() + class Meta: verbose_name = 'configuration' +class IPConfiguration(Configuration): + ipv4_endpoint = InetAddressField(validators=[validation.validate_v4], + verbose_name="IPv4", blank=True, null=True, + help_text="Adresse IPv4 utilisée comme endpoint") + ipv6_endpoint = InetAddressField(validators=[validation.validate_v6], + verbose_name="IPv6", blank=True, null=True, + help_text="Adresse IPv6 utilisée comme endpoint") + objects = NetManager() + + # This method is part of the general configuration interface. + def subnet_event(self): + self.check_endpoints(delete=True) + # We potentially changed the endpoints, so we need to save. Also, + # saving will update the subnets in the LDAP backend. + self.full_clean() + self.save() + + def get_subnets(self, version): + subnets = self.ip_subnet.all() + return [subnet for subnet in subnets if subnet.inet.version == version] + + def generate_endpoints(self, v4=True, v6=True): + """Generate IP endpoints in one of the attributed IP subnets. If there is + no available subnet for a given address family, then no endpoint + is generated for this address family. If there already is an + endpoint, do nothing. + + Returns True if an endpoint was generated. + """ + offer = self.offersubscription.offer + # Note: lorsqu'un pool d'IP est rempli, le FAI va devoir changer les + # pools d'IP associé à l'offre, du coup il se peut que d'anciens VPS + # aient des subnets qui ne sont plus référencés dans les pools d'IPs + # configurés pour une offre. Il faut donc avoir ça en tête. + # Du coup, on retire de l'affectation automatique les sous-réseaux + # qui sont explicitement indiquer comme ne servant pas pour le + # endpoints (case "utiliser pour les ips d'endpoints") + subnets = set([s for s in self.ip_subnet.all()]) + subnets -= set([s for s in self.ip_subnet.filter( + ip_pool__offer_ip_pools__to_assign=False, + ip_pool__offer_ip_pools__offer=offer)]) + updated = False + if v4 and self.ipv4_endpoint is None: + subnets_v4 = [s for s in subnets if s.inet.version == 4] + if len(subnets_v4) > 0: + self.ipv4_endpoint = subnets_v4[0].inet.ip + updated = True + if v6 and self.ipv6_endpoint is None: + subnets_v6 = [s for s in subnets if s.inet.version == 6] + if len(subnets_v6) > 0: + # With v6, we choose the second host of the subnet (cafe::1) + inet = subnets_v6[0].inet + if inet.prefixlen != 128: + gen = inet.iter_hosts() + gen.next() + self.ipv6_endpoint = gen.next() + else: + self.ipv6_endpoint = inet.ip + updated = True + return updated + + def check_endpoints(self, delete=False): + """Check that the IP endpoints are included in one of the attributed IP + subnets. + + If [delete] is True, then simply delete the faulty endpoints + instead of raising an exception. + """ + error = "L'IP {} n'est pas dans un réseau attribué." + subnets = self.ip_subnet.all() + is_faulty = lambda endpoint: endpoint and not any([endpoint in subnet.inet for subnet in subnets]) + if is_faulty(self.ipv4_endpoint): + if delete: + self.ipv4_endpoint = None + else: + raise ValidationError(error.format(self.ipv4_endpoint)) + if is_faulty(self.ipv6_endpoint): + if delete: + self.ipv6_endpoint = None + else: + raise ValidationError(error.format(self.ipv6_endpoint)) + + def fill_empty_fields(self): + if not self.ip_subnet.all(): + for offer_ip_pool in self.offersubscription.offer.offer_ip_pools.order_by('-to_assign'): + IPSubnet.objects.create( + configuration=self, + ip_pool=offer_ip_pool.ip_pool) + # If IP endpoints are not specified, + # generate them automatically. + if self.ipv4_endpoint is None or self.ipv6_endpoint is None: + self.generate_endpoints() + super(IPConfiguration, self).save() + + def save(self, **kwargs): + config = super(IPConfiguration, self).save(**kwargs) + self.fill_empty_fields() + return config + + def clean(self): + self.check_endpoints() + + def convert_to_dict_for_hook(self): + d = super(IPConfiguration, self).convert_to_dict_for_hook() + if self.ipv4_endpoint: + d["ipv4"] = str(self.ipv4_endpoint) + if self.ipv6_endpoint: + d["ipv6"] = str(self.ipv6_endpoint) + prefix = [str(subnet) for subnet in self.get_subnets(6) if self.ipv6_endpoint not in subnet.inet] + prefix = ','.join(prefix) + if prefix != '': + d['prefix'] = prefix + + return d + + class Meta: + abstract = True + + @receiver(post_save, sender=IPSubnet) +def subnet_event_save(sender, **kwargs): + kwargs["signal_type"] = "save" + subnet_event(sender, **kwargs) + + @receiver(post_delete, sender=IPSubnet) +def subnet_event_delete(sender, **kwargs): + kwargs["signal_type"] = "delete" + subnet_event(sender, **kwargs) + +subnet_log = logging.getLogger("coin.subnets") def subnet_event(sender, **kwargs): """Fires when a subnet is created, modified or deleted. We tell the configuration backend to do whatever it needs to do with it. @@ -101,9 +443,29 @@ def subnet_event(sender, **kwargs): """ subnet = kwargs['instance'] + if not settings.IP_ALLOCATION_MESSAGE: + return try: config = subnet.configuration if hasattr(config, 'subnet_event'): config.subnet_event() - except ObjectDoesNotExist: - pass + + offer = config.offersubscription.offer.name + ref = config.offersubscription.get_subscription_reference() + member = config.offersubscription.member + ip = subnet.inet + + if kwargs['signal_type'] == "save": + msg = "[Allocating IP] " + settings.IP_ALLOCATION_MESSAGE + elif kwargs['signal_type'] == "delete": + msg = "[Deallocating IP] " + settings.IP_ALLOCATION_MESSAGE + else: + # Does not happens + msg = "" + + subnet_log.info(msg.format(ip=ip, member=member, offer=offer, ref=ref)) + except ObjectDoesNotExist as e: + subnet_log.info("No subnet allocated") + subnet_log.info(str(e)) + + diff --git a/coin/configuration/templates/admin/configuration/configuration/change_form.html b/coin/configuration/templates/admin/configuration/configuration/change_form.html new file mode 100644 index 0000000000000000000000000000000000000000..58b5d8f3d9c3f3505612771d1a383d5ddaa4afbd --- /dev/null +++ b/coin/configuration/templates/admin/configuration/configuration/change_form.html @@ -0,0 +1,12 @@ +{% extends "admin/change_form.html" %} +{% load configuration %} +{% block object-tools-items %} +{% if original|provision_is_managed_via_hook %} + {% if original.provisioned == "no" %} +
  • Provisionner
  • + {% elif original.provisioned == "yes" %} +
  • Déprovisionner
  • + {% endif %} +{% endif %} +{{ block.super }} +{% endblock %} diff --git a/coin/configuration/templatetags/__init__.py b/coin/configuration/templatetags/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/coin/configuration/templatetags/configuration.py b/coin/configuration/templatetags/configuration.py new file mode 100644 index 0000000000000000000000000000000000000000..a2d1805dbe96d8f146c2010e04b384a6ed87794c --- /dev/null +++ b/coin/configuration/templatetags/configuration.py @@ -0,0 +1,15 @@ +from django.template import Library + +register = Library() + +@register.filter +def provision_is_managed_via_hook(self): + return self.provision_is_managed_via_hook() + +@register.filter +def state_is_managed_via_hook(self): + return self.state_is_managed_via_hook() + +@register.filter +def state_icon_display(self): + return self.get_state_icon_display() diff --git a/coin/hooks.py b/coin/hooks.py new file mode 100644 index 0000000000000000000000000000000000000000..806a4d224779e57307b1855be8996272e5696090 --- /dev/null +++ b/coin/hooks.py @@ -0,0 +1,152 @@ +import json +import yaml +import logging +import shlex +import subprocess +from importlib import import_module +from pipes import quote + +from django.conf import settings + +logger = logging.getLogger(__name__) + + +""" +Hooks are defined in the settings with a syntax like : + +settings.HOOKS = {"foo": {"CREATE_FILE": {"type": "bash", + "command": "touch {dir}/{file}"}, + "CREATE_REMOTE_FILE": {"type": "bash", + "remote": "user@foo.com", + "command": "touch {dir}/{file}"}, + "UPDATE_FILE": {"type": "bash", + "command": "tee {dir}/{file}", + "stdin": "{content}"}, + "LOAD_FILE": {"type": "bash", + "command": "cat {dir}/{file}", + "parse_output": "yaml"}, + "PROVISION": {"type": "bash", + "remote": "user@machine", + "command": "provision_foo.sh --name {name} --ipv4 {ipv4}", + "stdin": "{password}"} + }, + "bar": {"PROVISION": {"type": "python", + "module": "bar", + "function": "provision"}, + "GET_STATE": {"type": "python", + "module": "bar", + "function": "state"} + } + } +""" + + +class HookManager(): + + @staticmethod + def is_defined(module, name): + """ + Returns true or false if the given hook name has been defined in + settings (and is not empty string) + """ + return hasattr(settings, "HOOKS") and settings.HOOKS.get(module, {}).get(name, {}) + + @staticmethod + def run(module, name, **kwargs): + + # The arg stdin can be provided and defines what will be fed on the + # standard input of the command + # In particular, in can / should be used to transmit password in a more + # secure way compared to using regular arguments which can be sniffed + # through ps -ef by other users on the system. + + if not HookManager.is_defined(module, name): + raise Exception("No hook been defined for module %s, hook %s" % (module, name)) + + logger.debug("Running hook %s for module %s with args %s" % (name, module, kwargs)) + + hook = settings.HOOKS[module][name] + if hook["type"] == "bash": + (success, stdout, stderr) = HookManager._run_bash(hook, **kwargs) + elif hook["type"] == "python": + (success, stdout, stderr) = HookManager._run_python(hook, **kwargs) + return (success, stdout, stderr) + + @staticmethod + def _format_hook_bash(hook, **kwargs): + + command = hook["command"] + + # N.B. : here we split() the string to have separate piece. + # So for example + # foo --bar "zblerg {bar}" + # becomes something like + # ["foo", "--bar", "zblerg {bar}"] + # and then format each piece independently. + # + # This is meant to avoid obvious injections. Though if you're using + # a hook, you should try to validate the format of the args before + # calling this (e.g. check that a variable domain provided by the + # user really looks like a domain) + + to_run = [e.format(**kwargs) for e in shlex.split(command)] + + if "remote" in hook: + user_at_machine = hook["remote"] + remote_command = [quote(e) for e in to_run] + remote_command = " ".join(remote_command) + to_run = ["ssh", user_at_machine, remote_command] + + return to_run + + @staticmethod + def _run_bash(hook, **kwargs): + + # Format command with provided infos + to_run = HookManager._format_hook_bash(hook, **kwargs) + + if "stdin" in hook: + stdin = hook["stdin"].encode('utf-8').format(**kwargs) + else: + stdin = None + + logger.debug("Will run hook command : %s" % to_run) + + p = subprocess.Popen( + to_run, + stdin=subprocess.PIPE if stdin else None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + stdout, stderr = p.communicate(stdin) + success = p.returncode == 0 + + if "parse_output" in hook: + parse_format = hook["parse_output"] + if parse_format == "json": + try: + stdout = json.loads(stdout) + except Exception as e: + raise Exception("Failed to load stdout as json.\nStdout:\n%sStderr:\n%s\nError parsing stdout:%s" % (stdout, stderr, e)) + elif parse_format == "yaml": + try: + stdout = yaml.safe_load(stdout) + except Exception as e: + raise Exception("Failed to load stdout as yaml. Raw content:\n%s\nError:%s" % (stdout, e)) + else: + raise Exception("Unsupported parse_format %s" % parse_format) + + return (success, stdout, stderr) + + @staticmethod + def _run_python(hook, **kwargs): + try: + module = import_module("custom_hooks." + hook["module"]) + except Exception as e: + raise Exception("Could not load python hook %s : %s" % (hook["module"], e)) + + try: + output = getattr(module, hook["function"])(**kwargs) + return (True, output, None) + except Exception as e: + return (False, None, str(e)) diff --git a/coin/html2pdf.py b/coin/html2pdf.py index 0a31cb0a40087f534bfdc2de7d806b392a34cad1..31714b519fcce29fc037e0e4980fa686921563a2 100644 --- a/coin/html2pdf.py +++ b/coin/html2pdf.py @@ -6,7 +6,7 @@ import re from tempfile import NamedTemporaryFile from django.conf import settings -from django.template import loader, Context +from django.template import loader from django.core.files import File from weasyprint import HTML @@ -53,7 +53,7 @@ def render_as_pdf(template, context): """ template = loader.get_template(template) - html = template.render(Context(context)) + html = template.render(context) file = NamedTemporaryFile() pisaStatus = HTML(string=html).write_pdf(file) diff --git a/coin/isp_database/admin.py b/coin/isp_database/admin.py index 5b8e040af91e1b2d34e7639663ae7e2f650c353d..0305598a10f7ae7acbae4211c600add4f3ffeaea 100644 --- a/coin/isp_database/admin.py +++ b/coin/isp_database/admin.py @@ -2,13 +2,13 @@ from __future__ import unicode_literals from django.contrib import admin -from django.forms import ModelForm +from django import forms from localflavor.fr.forms import FRPhoneNumberField from coin.isp_database.models import ISPInfo, RegisteredOffice, OtherWebsite, ChatRoom, CoveredArea, BankInfo -class ISPAdminForm(ModelForm): +class ISPAdminForm(forms.ModelForm): class Meta: model = ISPInfo diff --git a/coin/isp_database/app.py b/coin/isp_database/app.py index 9e0272c54427be72bc138b85c9fd62b16019bc4e..2a25470040891ea154651b44a6ee7f9125f08c0b 100644 --- a/coin/isp_database/app.py +++ b/coin/isp_database/app.py @@ -7,3 +7,12 @@ from django.apps import AppConfig class ISPdatabaseConfig(AppConfig): name = 'coin.isp_database' verbose_name = 'Identité du FAI' + + admin_menu_entry = { + "id": "meta", + "icon": "institution", + "title": "Meta", + "models": [ + ("Infos du FAI", "isp_database/ispinfo"), + ] + } diff --git a/coin/members/admin.py b/coin/members/admin.py index 4812487db399bace3b018fac5705ca9404d43884..9a8b9e8ac8cbed54b2110b25afa6d41eada7d30e 100644 --- a/coin/members/admin.py +++ b/coin/members/admin.py @@ -16,23 +16,16 @@ from django.core.urlresolvers import reverse from django.utils.safestring import mark_safe from coin.members.models import ( - Member, CryptoKey, LdapUser, MembershipFee, Offer, OfferSubscription, RowLevelPermission) + Member, CryptoKey, LdapUser, Offer, OfferSubscription, RowLevelPermission) from coin.members.forms import AdminMemberChangeForm, MemberCreationForm from coin.utils import delete_selected - +from coin.billing.models import MembershipFee class CryptoKeyInline(admin.StackedInline): model = CryptoKey extra = 0 -class MembershipFeeInline(admin.TabularInline): - model = MembershipFee - extra = 0 - fields = ('start_date', 'end_date', 'amount', 'payment_method', - 'reference', 'payment_date') - - class OfferSubscriptionInline(admin.TabularInline): model = OfferSubscription extra = 0 @@ -97,16 +90,16 @@ class DataRetentionFilter(SimpleListFilter): def queryset(self, request, queryset): if self.value() == 'pending_deletion': - return queryset.could_be_deleted() + return queryset.filter(id__in=[i.id for i in queryset.all() if i.could_be_deleted()]) class MembershipFeeFilter(SimpleListFilter): # Human-readable title which will be displayed in the # right admin sidebar just above the filter options. - title = 'Cotisations' + title = 'cotisations' # Parameter for the filter that will be used in the URL query. - parameter_name = 'fee' + parameter_name = 'fee_billing' def lookups(self, request, model_admin): return ( @@ -116,10 +109,14 @@ class MembershipFeeFilter(SimpleListFilter): def queryset(self, request, queryset): if self.value() == 'paidup': - return queryset.paidup_fee() + return queryset.filter(id__in=[i.id for i in queryset.all() if i.is_paid_up()]) if self.value() == 'late': - return queryset.no_fee_or_late() + return queryset.filter(id__in=[i.id for i in queryset.all() if not i.is_paid_up()]) +class MembershipFeeInline(admin.TabularInline): + model = MembershipFee + extra = 0 + fields = ('start_date', 'end_date', '_amount') class MemberAdmin(UserAdmin): SERVICE_NO_FEE_MSG = ( @@ -232,7 +229,7 @@ class MemberAdmin(UserAdmin): save_on_top = True - inlines = [CryptoKeyInline, MembershipFeeInline, OfferSubscriptionInline] + inlines = [CryptoKeyInline, OfferSubscriptionInline, MembershipFeeInline] def add_member_warnings(self, request, member): has_active_subscriptions = member.get_active_subscriptions().exists() diff --git a/coin/members/app.py b/coin/members/app.py index c007331fd38cb91c8fdba41f4e8f988d41678ac6..ecd61dc73ae40c564b6cce9f362a5ee7ef51ab0c 100644 --- a/coin/members/app.py +++ b/coin/members/app.py @@ -6,3 +6,13 @@ from django.apps import AppConfig class MembersConfig(AppConfig): name = 'coin.members' verbose_name = 'Membres' + admin_menu_entry = { + "id": "members", + "icon": "users", + "title": "Membres", + "models": [ + ("Membres", "members/member"), + ("Groupes", "auth/group"), + ("Permissions", "members/rowlevelpermission"), + ] + } diff --git a/coin/members/forms.py b/coin/members/forms.py index 8001853157332c36259727ac1e51295623956ba5..d8a2baa493183a807145cafb31367319ab1e63a7 100644 --- a/coin/members/forms.py +++ b/coin/members/forms.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals from django import forms -from django.contrib.auth.forms import PasswordResetForm, ReadOnlyPasswordHashField +from django.contrib.auth.forms import PasswordResetForm, ReadOnlyPasswordHashField, PasswordChangeForm, SetPasswordForm +from django.conf import settings from django.forms.utils import ErrorList from django.forms.forms import BoundField @@ -10,12 +11,24 @@ from coin.members.models import Member from registration.forms import RegistrationForm +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout, Div +from crispy_forms.bootstrap import StrictButton + class MemberRegistrationForm(RegistrationForm): + # Protect against robot - trap = forms.CharField(required=False, label='Trap', - widget=forms.TextInput(attrs={'style' : 'display:none'}), - help_text="Si vous êtes humain ignorez ce champ") + trap = forms.CharField(label='Trap', + required=False, + widget=forms.TextInput(attrs={'style' : 'display:none'}), + help_text="Si vous êtes humain ignorez ce champ") + + ack_status = forms.BooleanField(label=str(settings.MEMBER_TERMS), + widget=forms.CheckboxInput(attrs={ + 'style' : '' if settings.MEMBER_TERMS else 'display:none' + }), + required=bool(settings.MEMBER_TERMS)) def __init__(self, *args, **kwargs): super(MemberRegistrationForm, self).__init__(*args, **kwargs) @@ -23,6 +36,7 @@ class MemberRegistrationForm(RegistrationForm): for fieldname in ['email', 'organization_name', 'password2']: self.fields[fieldname].help_text = None + def is_valid(self): valid = super(MemberRegistrationForm,self).is_valid() avoid_trap = not self.data['trap'] @@ -31,17 +45,23 @@ class MemberRegistrationForm(RegistrationForm): else: return False - def as_p(self): - """" - We rewrite the as_p method to apply a style on the

    tag related to - trap field. Indeed, it seeems there is no cleaner way to do it. - """ - def css_classes(self, extra_classes=None): - return 'captcha' + @property + def helper(self): + helper = FormHelper() + + helper.form_class = 'form-horizontal' + helper.label_class = 'col-4' + helper.field_class = 'col-8' + helper.layout = Layout( + *(self.fields.keys() + [ + Div( + StrictButton(' Créer mon compte', css_class="btn-success", type="submit"), + css_class="text-center" + ) + ]) + ) - func_type = type(BoundField.css_classes) - self['trap'].css_classes = func_type(css_classes, self, BoundField) - return super(MemberRegistrationForm, self).as_p() + return helper class Meta: model = Member @@ -94,6 +114,22 @@ class AbstractMemberChangeForm(forms.ModelForm): if f is not None: f.queryset = f.queryset.select_related('content_type') + if not settings.MEMBER_CAN_EDIT_PROFILE: + for _, field in self.fields.items(): + # In recent Django versions, setting field.disabled should be enough for + # both visual and processing disable + field.disabled = True + field.widget.attrs['readonly'] = True + + def save(self, *args, **kwargs): + if settings.MEMBER_CAN_EDIT_PROFILE: + return super(AbstractMemberChangeForm, self).save(*args, **kwargs) + else: + # skip form saving. In recent Django versions, this save() + # override should no longer be required. + return self.instance + + def clean_password(self): # Regardless of what the user provides, return the initial value. # This is done here, rather than on the field, because the @@ -104,6 +140,27 @@ class AbstractMemberChangeForm(forms.ModelForm): # idem clean_password return self.initial["username"] + @property + def helper(self): + helper = FormHelper() + + helper.form_class = 'form-horizontal' + helper.label_class = 'col-4' + helper.field_class = 'col-8' + helper.layout = Layout( + *(self.fields.keys() + [ + Div( + StrictButton(' Modifier', css_class="btn-primary", type="submit"), + css_class="text-center" + ) + ]) + ) + + return helper + + def save_m2m(self): + pass + class AdminMemberChangeForm(AbstractMemberChangeForm): password = ReadOnlyPasswordHashField() @@ -154,3 +211,42 @@ class OrganizationMemberChangeForm(AbstractMemberChangeForm): class MemberPasswordResetForm(PasswordResetForm): pass +def helper_password_reset(self): + helper = FormHelper() + + + helper.field_template = 'bootstrap4/layout/inline_field.html' + + helper.layout = Layout( + *(self.fields.keys() + [ + Div( + StrictButton('Réinitialiser mon mot de passe', css_class="btn-primary mt-2", type="submit"), + css_class="text-center" + ) + ]) + ) + + return helper + +PasswordResetForm.helper = property(helper_password_reset) + +def helper_password_change(self): + helper = FormHelper() + + #helper.form_class = 'form-horizontal' + #helper.label_class = 'col-4' + #helper.field_class = 'col-8' + helper.layout = Layout( + *(self.fields.keys() + [ + Div( + StrictButton('Changer mon mot mot de passe', css_class="btn-primary", type="submit"), + css_class="text-center" + ) + ]) + ) + + return helper + +PasswordChangeForm.helper = property(helper_password_change) +SetPasswordForm.helper = property(helper_password_change) + diff --git a/coin/members/management/commands/call_for_membership_fees.py b/coin/members/management/commands/call_for_membership_fees.py index 34ffdf2db6b43079bbd8853a037539b1dc1532f1..71608275a82aab59bbf0ae54bf621c8236688829 100644 --- a/coin/members/management/commands/call_for_membership_fees.py +++ b/coin/members/management/commands/call_for_membership_fees.py @@ -8,8 +8,7 @@ from django.db.models import Max from django.conf import settings from coin.utils import respect_language -from coin.members.models import Member, MembershipFee - +from coin.members.models import Member class Command(BaseCommand): args = '[date=2011-07-04]' @@ -41,9 +40,10 @@ class Command(BaseCommand): dates=[str(d) for d in end_dates])) members = Member.objects.filter(status='member')\ - .annotate(end=Max('membership_fees__end_date'))\ - .filter(end__in=end_dates)\ .filter(send_membership_fees_email=True) + + members = [member for member in members if member.end_date_of_membership() in end_dates] + if verbosity >= 2: self.stdout.write( "Got {number} members.".format(number=members.count())) diff --git a/coin/members/management/commands/create_membership_fees.py b/coin/members/management/commands/create_membership_fees.py new file mode 100644 index 0000000000000000000000000000000000000000..bafe2a2d1a5929325b9136d620a1e6e4fdf2a666 --- /dev/null +++ b/coin/members/management/commands/create_membership_fees.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import datetime +from dateutil.relativedelta import relativedelta +from django.core.management.base import BaseCommand, CommandError +from django.db.models import Q +from django.conf import settings + +from coin.utils import respect_language +from coin.members.models import Member +from coin.billing.models import MembershipFee, Payment + +class Command(BaseCommand): + args = '[date=2011-07-04]' + help = """Create membership fees if a member has an active service + """ + + def handle(self, *args, **options): + + # Member with a service + self.stdout.write("Member with a service") + members = Member.objects.exclude(status='not_member').exclude(offersubscription=None).filter(offersubscription__resign_date=None).distinct('username') + + membership_fees = MembershipFee.objects.order_by('member__username', '-end_date').distinct('member__username').filter(member__in=members) + + for member in members: + membership_fee = membership_fees.filter(member=member) + start_date = member.offersubscription_set.order_by('subscription_date')[0].subscription_date + if membership_fee and start_date < membership_fee[0].end_date: + start_date = membership_fee[0].end_date + + while start_date <= datetime.date.today(): + self.stdout.write("Create MembershipFee for {username} {date}".format(username=member.username,date=start_date)) + end_date = start_date + relativedelta(years=1) + fee = MembershipFee(member=member, _amount=settings.DEFAULT_MEMBERSHIP_FEE, + start_date=start_date, + end_date=start_date + relativedelta(years=1)) + fee.save() + start_date = end_date + member.status='member' + member.save() + + + # Member whithout services + self.stdout.write("\n\nMember without a service") + members = Member.objects.exclude(status='not_member').filter(offersubscription=None, balance__gte=settings.DEFAULT_MEMBERSHIP_FEE).distinct('username') + for member in members: + membership_fee = membership_fees.filter(member=member) + start_date = None + past_year = datetime.date.today() + relativedelta(years=-1) + if not (membership_fee and membership_fee[0].end_date > datetime.date.today()): + continue + if membership_fee and past_year < membership_fee[0].end_date: + start_date = membership_fee[0].end_date + + last_payment = Payment.objects.filter(member=member, amount__gte=settings.DEFAULT_MEMBERSHIP_FEE, date__gte=past_year).order_by('-date') + if last_payment: + start_date = last_payment[0].date + + + if start_date: + self.stdout.write("Create MembershipFee for {username} {date}".format(username=member.username,date=start_date)) + fee = MembershipFee(member=member, _amount=settings.DEFAULT_MEMBERSHIP_FEE, + start_date=start_date, + end_date=start_date + relativedelta(years=1)) + fee.save() + member.status='member' + member.save() + + diff --git a/coin/members/migrations/0018_auto_20180414_2250.py b/coin/members/migrations/0018_auto_20180414_2250.py new file mode 100644 index 0000000000000000000000000000000000000000..ba9817108f8abe4b3ee88a6063dcf2827a2d1889 --- /dev/null +++ b/coin/members/migrations/0018_auto_20180414_2250.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import coin.members.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0017_merge'), + ] + + operations = [ + # Duplicate of 0018_auto_20180819_0211 + # migrations.AlterModelOptions( + # name='rowlevelpermission', + # options={'verbose_name': 'permission fine', 'verbose_name_plural': 'permissions fines'}, + # ), + migrations.AlterModelManagers( + name='member', + managers=[ + ('objects', coin.members.models.MemberManager()), + ], + ), + # Duplicate of 0019_auto_20190825_2329 + # migrations.AlterField( + # model_name='member', + # name='balance', + # field=models.DecimalField(default=0, verbose_name='account balance', max_digits=6, decimal_places=2), + # ), + ] diff --git a/coin/members/migrations/0019_auto_20180415_1814.py b/coin/members/migrations/0019_auto_20180415_1814.py new file mode 100644 index 0000000000000000000000000000000000000000..ce80c07a2535cddcfd2dd1542ff5c6b28b349c40 --- /dev/null +++ b/coin/members/migrations/0019_auto_20180415_1814.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0018_auto_20180414_2250'), + # Migration of MembershipFee from members app to billing app: + ('billing', '0013_auto_20180415_0413'), + ] + + operations = [ + migrations.RemoveField( + model_name='membershipfee', + name='member', + ), + migrations.DeleteModel( + name='MembershipFee', + ), + ] diff --git a/coin/members/migrations/0019_auto_20190825_2329.py b/coin/members/migrations/0019_auto_20190825_2329.py new file mode 100644 index 0000000000000000000000000000000000000000..70bf3265eece262014114cd159d8e9d6723ed212 --- /dev/null +++ b/coin/members/migrations/0019_auto_20190825_2329.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0018_auto_20180819_0211'), + ] + + operations = [ + migrations.AlterField( + model_name='member', + name='balance', + field=models.DecimalField(default=0, verbose_name='solde', max_digits=6, decimal_places=2), + ), + ] diff --git a/coin/members/migrations/0020_merge.py b/coin/members/migrations/0020_merge.py new file mode 100644 index 0000000000000000000000000000000000000000..cbbef91ad295851fc361006dffdeee768257f771 --- /dev/null +++ b/coin/members/migrations/0020_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0019_auto_20180415_1814'), + ('members', '0018_auto_20180819_0211'), + ] + + operations = [ + ] diff --git a/coin/members/migrations/0021_auto_20181118_2001.py b/coin/members/migrations/0021_auto_20181118_2001.py new file mode 100644 index 0000000000000000000000000000000000000000..d0be2f79ae600a34a57cc07c9f2df83831708a42 --- /dev/null +++ b/coin/members/migrations/0021_auto_20181118_2001.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0020_merge'), + ] + + operations = [ + migrations.CreateModel( + name='MembershipFee', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('amount', models.DecimalField(default=20, help_text='en \u20ac', verbose_name='montant', max_digits=5, decimal_places=2)), + ('start_date', models.DateField(verbose_name='date de d\xe9but de cotisation')), + ('end_date', models.DateField(help_text='par d\xe9faut, la cotisation dure un an', verbose_name='date de fin de cotisation', blank=True)), + ('payment_method', models.CharField(blank=True, max_length=100, null=True, verbose_name='moyen de paiement', choices=[('cash', 'Esp\xe8ces'), ('check', 'Ch\xe8que'), ('transfer', 'Virement'), ('other', 'Autre')])), + ('reference', models.CharField(help_text='num\xe9ro de ch\xe8que, r\xe9f\xe9rence de virement, commentaire...', max_length=125, null=True, verbose_name='r\xe9f\xe9rence du paiement', blank=True)), + ('payment_date', models.DateField(null=True, verbose_name='date du paiement', blank=True)), + ], + options={ + 'verbose_name': 'cotisation', + }, + ), + # Duplicate of 0019_auto_20190825_2329 + # migrations.AlterField( + # model_name='member', + # name='balance', + # field=models.DecimalField(default=0, verbose_name='solde', max_digits=6, decimal_places=2), + # ), + migrations.AddField( + model_name='membershipfee', + name='member', + field=models.ForeignKey(related_name='membership_fees', verbose_name='membre', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/coin/members/migrations/0022_auto_20190623_1256.py b/coin/members/migrations/0022_auto_20190623_1256.py new file mode 100644 index 0000000000000000000000000000000000000000..9e96d531ecedd0bf6e33fe288da9c99335d82dee --- /dev/null +++ b/coin/members/migrations/0022_auto_20190623_1256.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0021_auto_20181118_2001'), + ] + + operations = [ + migrations.AlterField( + model_name='membershipfee', + name='amount', + field=models.DecimalField(default=15, help_text='en \u20ac', verbose_name='montant', max_digits=5, decimal_places=2), + ), + ] diff --git a/coin/members/migrations/0023_merge.py b/coin/members/migrations/0023_merge.py new file mode 100644 index 0000000000000000000000000000000000000000..55856aa138e0794b4d3370240f8549addd785c41 --- /dev/null +++ b/coin/members/migrations/0023_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0019_auto_20190825_2329'), + ('members', '0022_auto_20190623_1256'), + ] + + operations = [ + ] diff --git a/coin/members/migrations/0024_auto_20201203_1852.py b/coin/members/migrations/0024_auto_20201203_1852.py new file mode 100644 index 0000000000000000000000000000000000000000..ea41f7b968006f4a4429e75b1681d298d1017ee6 --- /dev/null +++ b/coin/members/migrations/0024_auto_20201203_1852.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import coin.members.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0023_merge'), + ] + + operations = [ + migrations.AlterField( + model_name='membershipfee', + name='amount', + field=models.DecimalField(default=coin.members.models.default_membership_fee, help_text='en \u20ac', verbose_name='montant', max_digits=5, decimal_places=2), + ), + ] diff --git a/coin/members/migrations/0025_auto_20220219_1749.py b/coin/members/migrations/0025_auto_20220219_1749.py new file mode 100644 index 0000000000000000000000000000000000000000..f667faa6b36989d5fcc7a98a915351a5519d01ec --- /dev/null +++ b/coin/members/migrations/0025_auto_20220219_1749.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.contrib.auth.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0024_auto_20201203_1852'), + ] + + operations = [ + migrations.RemoveField( + model_name='membershipfee', + name='member', + ), + migrations.AlterModelManagers( + name='member', + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.DeleteModel( + name='MembershipFee', + ), + ] diff --git a/coin/members/models.py b/coin/members/models.py index d35e8b911754e67f420c00c786e04639f40b3312..3edfabb43d72abd7e882b7140c26542b3f3aefab 100644 --- a/coin/members/models.py +++ b/coin/members/models.py @@ -24,31 +24,6 @@ from coin.offers.models import Offer, OfferSubscription from coin.mixins import CoinLdapSyncMixin from coin import utils - -class MemberQuerySet(models.QuerySet): - paidup_q = Q( - # we have at least one fee - membership_fees__isnull=False, - # and it is still running - membership_fees__end_date__gte=datetime.date.today) - - def paidup_fee(self): - return self.filter(self.paidup_q) - - def no_fee_or_late(self): - return self.exclude(self.paidup_q) - - def could_be_deleted(self): - return self.exclude( - # we have at least one subscription - Q(offersubscription__isnull=False), - # still running or resigned less than one year ago - Q(offersubscription__resign_date__isnull=True) - | - Q(offersubscription__resign_date__gte=utils.one_year_ago()) - ).exclude(self.paidup_q) - - class MemberManager(UserManager): use_in_migrations = False @@ -137,14 +112,13 @@ class Member(CoinLdapSyncMixin, AbstractUser): date_last_call_for_membership_fees_email = models.DateTimeField(null=True, blank=True, verbose_name="Date du dernier email de relance de cotisation envoyé") + send_membership_fees_email = models.BooleanField( default=True, verbose_name='relance de cotisation', help_text='Précise si l\'utilisateur doit recevoir des mails de relance pour la cotisation. Certains membres n\'ont pas à recevoir de relance (prélèvement automatique, membres d\'honneurs, etc.)') - balance = models.DecimalField(max_digits=5, decimal_places=2, default=0, + balance = models.DecimalField(max_digits=6, decimal_places=2, default=0, verbose_name='solde') - objects = MemberManager.from_queryset(MemberQuerySet)() - # Following fields are managed by the parent class AbstractUser : # username, first_name, last_name, email # However we hack the model to force theses fields to be required. (see @@ -181,8 +155,11 @@ class Member(CoinLdapSyncMixin, AbstractUser): # Renvoie la date de fin de la dernière cotisation du membre def end_date_of_membership(self): - aggregate = self.membership_fees.aggregate(end=Max('end_date')) + # Avoid import loop + from coin.billing.models import MembershipFee + aggregate = MembershipFee.objects.filter(member=self).aggregate(end=Max('end_date')) return aggregate['end'] + end_date_of_membership.short_description = "Date de fin d'adhésion" def is_paid_up(self, date=None): @@ -196,6 +173,12 @@ class Member(CoinLdapSyncMixin, AbstractUser): return False return (end_date >= date) + def could_be_deleted(self): + + end_date = self.end_date_of_membership() + + return (end_date is None or end_date <= datetime.date.today()) and not (self.get_active_subscriptions() or self.get_recent_inactive_subscriptions()) + def set_password(self, new_password, *args, **kwargs): """ Définit le mot de passe a sauvegarder en base et dans le LDAP @@ -387,6 +370,37 @@ class Member(CoinLdapSyncMixin, AbstractUser): return False + def send_reminder_negative_balance(self, auto=False): + + # We only send these reminders if (strictly) more than 14€ is due + if self.balance >= -14: + return + + from coin.isp_database.models import ISPInfo + isp_info = ISPInfo.objects.first() + kwargs = {} + # Il peut ne pas y avir d'ISPInfo, ou bien pas d'administrative_email + if isp_info and isp_info.administrative_email: + kwargs['from_email'] = isp_info.administrative_email + + url_to_billing_screen = reverse('members:invoices') + + # Not sure what's the proper way to build an absolute url :/ + if settings.ALLOWED_HOSTS: + url_to_billing_screen = "https://" + settings.ALLOWED_HOSTS[0] + url_to_billing_screen + + # Si le dernier courriel de relance a été envoyé il y a moins de trois + # semaines, n'envoi pas un nouveau courriel + utils.send_templated_email( + to=self.email, + subject_template='members/emails/reminder_negative_balance_subject.txt', + body_template='members/emails/reminder_negative_balance.html', + context={'member': self, + 'url_to_billing_screen': url_to_billing_screen, + 'branding': isp_info, + 'auto_sent': auto}, + **kwargs) + class Meta: verbose_name = 'membre' @@ -474,57 +488,8 @@ class CryptoKey(CoinLdapSyncMixin, models.Model): verbose_name = 'clé' -class MembershipFee(models.Model): - PAYMENT_METHOD_CHOICES = ( - ('cash', 'Espèces'), - ('check', 'Chèque'), - ('transfer', 'Virement'), - ('other', 'Autre') - ) - - member = models.ForeignKey('Member', related_name='membership_fees', - verbose_name='membre') - amount = models.DecimalField(null=False, max_digits=5, decimal_places=2, - default=settings.DEFAULT_MEMBERSHIP_FEE, - verbose_name='montant', help_text='en €') - start_date = models.DateField( - null=False, - blank=False, - verbose_name='date de début de cotisation') - end_date = models.DateField( - null=False, - blank=True, - verbose_name='date de fin de cotisation', - help_text='par défaut, la cotisation dure un an') - - payment_method = models.CharField(max_length=100, null=True, blank=True, - choices=PAYMENT_METHOD_CHOICES, - verbose_name='moyen de paiement') - reference = models.CharField(max_length=125, null=True, blank=True, - verbose_name='référence du paiement', - help_text='numéro de chèque, ' - 'référence de virement, commentaire...') - payment_date = models.DateField(null=True, blank=True, - verbose_name='date du paiement') - - def clean(self): - if self.start_date is not None and self.end_date is None: - self.end_date = self.start_date + datetime.timedelta(364) - - def save(self, *args, **kwargs): - ret = super(MembershipFee, self).save(*args, **kwargs) - today = datetime.date.today() - if self.start_date <= today and today <= self.end_date: - self.member.status = self.member.MEMBER_STATUS_MEMBER - self.member.save() - return ret - - def __unicode__(self): - return '%s - %s - %i€' % (self.member, self.start_date, self.amount) - - class Meta: - verbose_name = 'cotisation' - +def default_membership_fee(): + return settings.DEFAULT_MEMBERSHIP_FEE class LdapUser(ldapdb.models.Model): # "ou=users,ou=unix,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" diff --git a/coin/members/templates/admin/members/member/change_form.html b/coin/members/templates/admin/members/member/change_form.html index 60bdb803a538cb142a4b140b1f22945a773e8b87..6fd2ce3335ad44bf78aed19e2e577f45f8582fd4 100644 --- a/coin/members/templates/admin/members/member/change_form.html +++ b/coin/members/templates/admin/members/member/change_form.html @@ -1,5 +1,4 @@ {% extends "admin/change_form.html" %} -{% load url from future %} {% block object-tools-items %}

  • Envoyer le courriel de bienvenue
  • {% if request.user.is_superuser %} diff --git a/coin/members/templates/members/contact.html b/coin/members/templates/members/contact.html index b203d3968bb44427d30d80e0ea926ac3d32ad751..0b6b048c9c46bcb9f9cb42b32845646cfc056e0d 100644 --- a/coin/members/templates/members/contact.html +++ b/coin/members/templates/members/contact.html @@ -3,36 +3,41 @@ {% block content %}
    -
    -

    Contact / Support

    -
    -

    Courriel

    -

    - {{ branding.email }} (questions générales)
    - {% if branding.administrative_email %} - {{ branding.administrative_email }} (questions administratives)
    - {% endif %} - {% if branding.support_email %} - {{ branding.support_email }} (support technique) - {% endif %} -

    -
    +
    +

    Contact / Support

    + +

    Par courriel

    +

    + Questions générales : {{ branding.email }} +
    + {% if branding.administrative_email %} + Questions administratives : {{ branding.administrative_email }} +
    + {% endif %} + {% if branding.support_email %} + Support technique : {{ branding.support_email }} + {% endif %} +

    + {% if branding.lists_url %} -
    -

    Listes de discussion

    -

    Gérer ses abonnements aux listes de discussion et diffusion : {{ branding.lists_url }}

    -
    +

    Listes de discussion

    +

    + Gérer ses abonnements aux listes de discussion et diffusion : {{ branding.lists_url }} +

    {% endif %} + {% if branding.main_chat_verbose %} - +

    IRC

    +

    + {{ branding.main_chat_verbose }} +

    {% endif %} + {% if branding.phone_number %} -
    -

    Téléphone

    -

    {{ branding.phone_number }}

    +

    Téléphone

    +

    + {{ branding.phone_number }} +

    {% endif %}
    diff --git a/coin/members/templates/members/detail.html b/coin/members/templates/members/detail.html index 83ae3fb58f0fb2e897472767884b52c5c1ccaf3c..39241bfc0f1e6475af48e1d34bea3e6621b1f2f2 100644 --- a/coin/members/templates/members/detail.html +++ b/coin/members/templates/members/detail.html @@ -1,124 +1,53 @@ {% extends "base.html" %} +{% load crispy_forms_tags %} + {% block title %}Mes informations - {{ block.super }}{% endblock %} {% block content %} +
    -
    -

    Mes informations personnelles

    -
    -
    -
    -
    -
    -

    Mes coordonnées

    - - {% if user.type == 'natural_person' %} - {% if user.first_name %} - - - - - {% endif %} - {% if user.last_name %} - - - - - {% endif %} - {% if user.nickname %} - - - - - {% endif %} - {% else %} - - - - - {% endif %} - {% if user.address %} - - - - - {% endif %} +
    +

    Mon adhésion

    +
    - {% if user.email %} - - - - - {% endif %} +
    +

    Ma cotisation + {% if user.is_paid_up %} + à jour ! + {% if user.end_date_of_membership %} + (valide jusqu'au {{ user.end_date_of_membership }}) + {% endif %} + {% else %} + n'est pas à jour ! + {% endif %} +

    - {% if user.home_phone_number %} -
    - - - - {% endif %} +
    + Nous importons les comptes tous les 1 à 2 mois. Il n'est pas nécessaire de nous contacter si votre adhésion n'est pas validée malgré un paiement de moins de 2 mois. +
    - {% if user.mobile_phone_number %} - - - - - {% endif %} -
    Prénom{{user.first_name}}
    Nom{{user.last_name}}
    Pseudo{{ user.nickname }}
    Nom de la structure{{ user.organization_name }}
    Adresse{{user.address}}
    {{user.postal_code}} {{user.city}}
    Téléphone fixe{{user.home_phone_number}}
    Téléphone mobile{{user.mobile_phone_number}}
    + {% if membership_info_url %} + + {% endif %}
    -
    -
    -

    Membre de {{ branding.shortname|capfirst }}

    -

    Ma cotisation est : - {% if user.is_paid_up %} - à jour ! - {% else %} - non à jour ! - {% endif %} -

    -

    - {% if user.end_date_of_membership %} - Date de fin de cotisation : {{ user.end_date_of_membership }} - {% else %} - Je n'ai encore jamais cotisé. - {% endif %} -

    +
    +

    Mes informations personnelles

    +
    - {% if membership_info_url %} - - Renouveler ma cotisation - - {% endif %} -
    +
    +
    +
    + {% crispy form %} +
    +
    -
    -
    - {% if form %} - - {% csrf_token %} -
    - {{ form.as_p }} -
    - - - {% else %} -

    - Pour modifier vos informations personnelles et vos coordonnées, veuillez en faire la demande - {% if branding.administrative_email %} - par email à {{ branding.administrative_email }}. - {% else %} - à l'association. - {% endif%} -

    - {% endif %} -
    -
    {% endblock %} diff --git a/coin/members/templates/members/emails/new_member_email.html b/coin/members/templates/members/emails/new_member_email.html index e5d2eec0079be28bfa9f4ea455d815ae0270de8b..6653c0f02add5c15a2e23b92c7ece0d1b8ce823c 100644 --- a/coin/members/templates/members/emails/new_member_email.html +++ b/coin/members/templates/members/emails/new_member_email.html @@ -1,9 +1,10 @@ -Bonjour,
    +{% extends "emails/staff_email_base.html" %} + +{% block content %}

    {{ member }} s'est enregistré⋅e sur l'espace adhérent (COIN).

    Lien d'édition: {{ edit_link }}

    -Bisou, -Votre canard dévoué +{% endblock %} diff --git a/coin/members/templates/members/emails/new_member_subject.txt b/coin/members/templates/members/emails/new_member_subject.txt new file mode 100644 index 0000000000000000000000000000000000000000..a40bc7b8e227f2a25795bb20b7fa0ae31c80b370 --- /dev/null +++ b/coin/members/templates/members/emails/new_member_subject.txt @@ -0,0 +1 @@ +[COIN] Nouveau compte créé diff --git a/coin/members/templates/members/emails/reminder_negative_balance.html b/coin/members/templates/members/emails/reminder_negative_balance.html new file mode 100644 index 0000000000000000000000000000000000000000..cbbf01c6ca8b6de59c8d4185e1df75ab7321095a --- /dev/null +++ b/coin/members/templates/members/emails/reminder_negative_balance.html @@ -0,0 +1,17 @@ +

    Bonjour {{ member }},

    + +

    +Ce message est un petit rappel qu'il y a des notes en attente de paiement. +Tu peux voir le détail sur ton espace adhérent : +{{ url_to_billing_screen }} +

    + +

    +N'hésite pas à nous contacter en cas de soucis ! +

    + +

    L'équipe de l'association {{ branding.shortname|capfirst }}

    + +{% if auto_sent %} +

    (Ceci est un message automatique)

    +{% endif %} diff --git a/coin/members/templates/members/emails/reminder_negative_balance_subject.txt b/coin/members/templates/members/emails/reminder_negative_balance_subject.txt new file mode 100644 index 0000000000000000000000000000000000000000..d8e54a02f6d7d1e0d042c0670497cad0cbfba0db --- /dev/null +++ b/coin/members/templates/members/emails/reminder_negative_balance_subject.txt @@ -0,0 +1 @@ +Notes en attente de paiements pour {{ branding.shortname|capfirst }} diff --git a/coin/members/templates/members/index.html b/coin/members/templates/members/index.html index 715193bf66f2b0824799ea1bd651f3f88ce7640f..f6f7eedd33090842cd8fc1eda0e9271add83a606 100644 --- a/coin/members/templates/members/index.html +++ b/coin/members/templates/members/index.html @@ -3,42 +3,51 @@ {% block title %}Tableau de bord - {{ block.super }}{% endblock %} {% block content %} +
    -
    -

    Tableau de bord

    + +
    +

    Tableau de bord

    -
    -
    + {% if has_isp_feed %} -
    -
    -

    News {{ branding.shortname|capfirst }}

    -
    -

    - - Chargement en cours -

    -
    +
    +
    +
    +

    News {{ branding.shortname|capfirst }}

    +
    +

    + + Chargement en cours +

    +
    +
    {% endif %} -
    -
    -

    News de la FFDN

    -
    + + + +
    +
    +
    +

    News de la FFDN

    +

    Chargement en cours

    +
    + +
    {% endblock %} - {% block extra_js %} {{ block.super }} - {% endblock %} diff --git a/coin/members/templates/members/subscriptions.html b/coin/members/templates/members/subscriptions.html index aedfd1e24f9da3ab4f27593113662d76ce8e3a5c..c920dce8ad671f51ff0255bfd067480289d4e647 100644 --- a/coin/members/templates/members/subscriptions.html +++ b/coin/members/templates/members/subscriptions.html @@ -1,53 +1,64 @@ {% extends "base.html" %} +{% load configuration %} {% block title %}Mes abonnements - {{ block.super }}{% endblock %} {% block content %} -

    Mes abonnements

    - - - - - - - - - - - - - - {% for subscription in subscriptions %} - - - - - - - - - - {% endfor %} - {% for subscription in old_subscriptions %} - - - - - - - - - {% endfor %} - -
    TypeOffreDate de souscriptionDate de résiliationCommentaireConfiguration
    {{ subscription.offer.get_configuration_type_display }}{{ subscription.offer.name }}{{ subscription.subscription_date }}{{ subscription.resign_date|default_if_none:"" }}{{ subscription.configuration.comment }}{% if subscription.configuration and subscription.configuration.url_namespace %} Configuration{% endif %}
    {{ subscription.offer.get_configuration_type_display }}{{ subscription.offer.name }}{{ subscription.subscription_date }}{{ subscription.resign_date|default_if_none:"" }}{{ subscription.configuration.comment }}
    - +
    + +
    +

    Mes abonnements

    +
    + +
    + {% for subscription in subscriptions %} + {% include "members/partials/subscription_item.html" %} + {% empty %} + Aucun abonnement ... pour le moment ! + {% endfor %} + {% if can_request_subscription %} + + {% endif %} +
    + + +{% if pending_subscriptions %} + +
    +

    Mes demandes d'abonnement en attente

    +
    + +
    + {% for subscription in pending_subscriptions %} + + +
    +

    + {{ subscription.offer.name }} + demandé le {{ subscription.request_date|date:"j F Y" }} +

    +
    +
    + {% endfor %} +
    + +{% endif %} + +{% if old_subscriptions %} + +
    +

    Abonnements résiliés

    +
    +
    + {% for subscription in old_subscriptions %} + {% include "members/partials/subscription_item.html" %} + {% endfor %} +
    + +{% endif %} + +
    {% endblock %} diff --git a/coin/members/tests.py b/coin/members/tests.py index 79ce4f0c68ca9cf3ce55d5943d959850dd29efce..52d71af739c4b3efa0e142b3871a1fa738f30f55 100644 --- a/coin/members/tests.py +++ b/coin/members/tests.py @@ -17,7 +17,8 @@ from django.test import TestCase, Client from django.core import mail, management from django.core.exceptions import ValidationError -from coin.members.models import Member, MembershipFee, LdapUser +from coin.members.models import Member, LdapUser +from coin.billing.models import MembershipFee from coin.offers.models import OfferSubscription, Offer from coin.validation import chatroom_url_validator @@ -300,78 +301,16 @@ class MemberTests(TestCase): member.delete() - def test_member_end_date_of_memberhip(self): - """ - Test que end_date_of_membership d'un membre envoi bien la date de fin d'adhésion - """ - # Créer un membre - first_name = 'Tin' - last_name = 'Tin' - username = MemberTestsUtils.get_random_username() - member = Member(first_name=first_name, - last_name=last_name, username=username) - member.save() - - start_date = date.today() - end_date = start_date + relativedelta(years=+1) - - # Créé une cotisation - membershipfee = MembershipFee(member=member, amount=20, - start_date=start_date, - end_date=end_date) - membershipfee.save() - - self.assertEqual(member.end_date_of_membership(), end_date) - - def test_member_is_paid_up(self): - """ - Test l'état "a jour de cotisation" d'un adhérent. - """ - # Créé un membre - first_name = 'Capitain' - last_name = 'Haddock' - username = MemberTestsUtils.get_random_username() - member = Member(first_name=first_name, - last_name=last_name, username=username) - member.save() - - start_date = date.today() - end_date = start_date + relativedelta(years=+1) - - # Test qu'un membre sans cotisation n'est pas à jour - self.assertEqual(member.is_paid_up(), False) - - # Créé une cotisation passée - membershipfee = MembershipFee(member=member, amount=20, - start_date=date.today() + - relativedelta(years=-1), - end_date=date.today() + relativedelta(days=-10)) - membershipfee.save() - # La cotisation s'étant terminée il y a 10 jours, il ne devrait pas - # être à jour de cotistion - self.assertEqual(member.is_paid_up(), False) - - # Créé une cotisation actuelle - membershipfee = MembershipFee(member=member, amount=20, - start_date=date.today() + - relativedelta(days=-10), - end_date=date.today() + relativedelta(days=+10)) - membershipfee.save() - # La cotisation se terminant dans 10 jour, il devrait être à jour - # de cotisation - self.assertEqual(member.is_paid_up(), True) - @freeze_time('2016-01-01') def test_adding_running_fee_set_membership_status(self): member = Member.objects.create( first_name='a', last_name='b', username='c', status=Member.MEMBER_STATUS_PENDING) - # Créé une cotisation passée - MembershipFee.objects.create( - member=member, amount=20, - start_date=date(2015, 12, 12), - end_date=date(2016, 12, 12)) + membershipfee = MembershipFee(member=member, amount=20, + start_date=date(2015, 12, 12), + end_date=date(2016, 12, 12)) + membershipfee.save() member = Member.objects.get(pk=member.pk) self.assertEqual(member.status, member.MEMBER_STATUS_MEMBER) @@ -391,7 +330,6 @@ class MemberTests(TestCase): member.save() - class MemberAdminTests(TestCase): def setUp(self): @@ -449,13 +387,6 @@ class MemberTestCallForMembershipCommand(TestCase): self.member.delete() MembershipFee.objects.all().delete() - def create_membership_fee(self, end_date): - # Créé une cotisation passée se terminant dans un mois - membershipfee = MembershipFee(member=self.member, amount=20, - start_date=end_date + relativedelta(years=-1), - end_date=end_date) - membershipfee.save() - def create_membership_fee(self, end_date): # Créé une cotisation se terminant à la date indiquée membershipfee = MembershipFee(member=self.member, amount=20, @@ -542,7 +473,7 @@ class MemberManagerTest(TestCase): @freeze_time('2016-10-01') def test_could_be_deleted(self): - deletion_set = set(Member.objects.could_be_deleted()) + deletion_set = set([m for m in Member.objects.all() if m.could_be_deleted()]) # late on fee (-> delete) self.assertIn(self.cd, deletion_set) @@ -572,23 +503,3 @@ class TestValidators(TestCase): chatroom_url_validator('irc://irc.example.com/#chan') with self.assertRaises(ValidationError): chatroom_url_validator('http://#faimaison@irc.geeknode.org') - - -class MembershipFeeTests(TestCase): - def test_mandatory_start_date(self): - member = Member(first_name='foo', last_name='foo', password='foo', email='foo') - member.save() - - # If there is no start_date clean_fields() should raise an - # error but not clean(). - membershipfee = MembershipFee(member=member, amount=15) - self.assertRaises(ValidationError, membershipfee.clean_fields) - self.assertIsNone(membershipfee.clean()) - - # If there is a start_date, everything is fine. - membershipfee = MembershipFee(member=member, amount=15, - start_date=date.today()) - self.assertIsNone(membershipfee.clean_fields()) - self.assertIsNone(membershipfee.clean()) - - member.delete() diff --git a/coin/members/urls.py b/coin/members/urls.py index 33a1b5bffd5c9bbf761e62f2a54ba34f85ec9608..edb9adcb51e8eb0d00f1ae6db47db5317933f220 100644 --- a/coin/members/urls.py +++ b/coin/members/urls.py @@ -1,15 +1,16 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.conf.urls import patterns, url -from coin.members import forms -from coin.members import views +from django.conf.urls import url +from coin.members import forms, views from django.views.generic.base import TemplateView from . import registration_views as views_r from coin import settings from registration.signals import user_activated from django.contrib.auth import login +from coin.offers.views import offersubscriptionrequest_step1, offersubscriptionrequest_step2, offersubscriptionrequest_step3 +import django.contrib.auth.views def login_on_activation(sender, user, request, **kwargs): """Logs in the user after activation""" @@ -19,39 +20,39 @@ def login_on_activation(sender, user, request, **kwargs): # Registers the function with the django-registration user_activated signal user_activated.connect(login_on_activation) -urlpatterns = patterns( - '', +urlpatterns = [ + #'', url(r'^$', views.index, name='index'), - url(r'^login/$', 'django.contrib.auth.views.login', + url(r'^login/$', django.contrib.auth.views.login, {'template_name': 'members/registration/login.html', 'extra_context': {'settings': settings} }, name='login'), - url(r'^logout/$', 'django.contrib.auth.views.logout_then_login', + url(r'^logout/$', django.contrib.auth.views.logout_then_login, name='logout'), - url(r'^password_change/$', 'django.contrib.auth.views.password_change', + url(r'^password_change/$', django.contrib.auth.views.password_change, {'post_change_redirect': 'members:password_change_done', 'template_name': 'members/registration/password_change_form.html'}, name='password_change'), - url(r'^password_change_done/$', 'django.contrib.auth.views.password_change_done', + url(r'^password_change_done/$', django.contrib.auth.views.password_change_done, {'template_name': 'members/registration/password_change_done.html'}, name='password_change_done'), - url(r'^password_reset/$', 'django.contrib.auth.views.password_reset', + url(r'^password_reset/$', django.contrib.auth.views.password_reset, {'post_reset_redirect': 'members:password_reset_done', 'template_name': 'members/registration/password_reset_form.html', 'email_template_name': 'members/registration/password_reset_email.html', 'subject_template_name': 'members/registration/password_reset_subject.txt'}, name='password_reset'), - url(r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', + url(r'^password_reset/done/$', django.contrib.auth.views.password_reset_done, {'template_name': 'members/registration/password_reset_done.html', 'current_app': 'members'}, name='password_reset_done'), - url(r'^password_reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', 'django.contrib.auth.views.password_reset_confirm', + url(r'^password_reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', django.contrib.auth.views.password_reset_confirm, {'post_reset_redirect': 'members:password_reset_complete', 'template_name': 'members/registration/password_reset_confirm.html'}, name='password_reset_confirm'), - url(r'^password_reset/complete/$', 'django.contrib.auth.views.password_reset_complete', + url(r'^password_reset/complete/$', django.contrib.auth.views.password_reset_complete, {'template_name': 'members/registration/password_reset_complete.html'}, name='password_reset_complete'), @@ -89,7 +90,10 @@ urlpatterns = patterns( url(r'^subscriptions/', views.subscriptions, name='subscriptions'), # url(r'^subscription/(?P\d+)', views.subscriptions, name = 'subscription'), + url(r'^request_subscriptions/step1$', offersubscriptionrequest_step1, name="subscriptionrequest_step1"), + url(r'^request_subscriptions/step2/(?P.+)$', offersubscriptionrequest_step2, name="subscriptionrequest_step2"), + url(r'^request_subscriptions/step3', offersubscriptionrequest_step3, name="subscriptionrequest_step3"), url(r'^invoices/', views.invoices, name='invoices'), url(r'^contact/', views.contact, name='contact'), -) +] diff --git a/coin/members/views.py b/coin/members/views.py index 154964cc41d39a669fd72a35bee24075d5d8f786..a8590daa53876ab1baf50479f72919df466cb070 100644 --- a/coin/members/views.py +++ b/coin/members/views.py @@ -2,65 +2,72 @@ from __future__ import unicode_literals from django.template import RequestContext -from django.shortcuts import render +from django.shortcuts import redirect, render from django.contrib.auth.decorators import login_required from django.conf import settings from forms import PersonMemberChangeForm, OrganizationMemberChangeForm +from coin.billing.models import Bill + +from coin.offers.models import Offer, OfferSubscriptionRequest @login_required def index(request): has_isp_feed = 'isp' in [k for k, _, _ in settings.FEEDS] - return render(request, 'members/index.html', + return render(request, + 'members/index.html', {'has_isp_feed': has_isp_feed}) @login_required def detail(request): - membership_info_url = settings.MEMBER_MEMBERSHIP_INFO_URL - context={ - 'membership_info_url': membership_info_url, - } - - if settings.MEMBER_CAN_EDIT_PROFILE: - if request.user.type == "natural_person": - form_cls = PersonMemberChangeForm - else: - form_cls = OrganizationMemberChangeForm + if request.user.type == "natural_person": + form_cls = PersonMemberChangeForm + else: + form_cls = OrganizationMemberChangeForm - if request.method == "POST": - form = form_cls(data = request.POST, instance = request.user) - if form.is_valid(): - form.save() - else: - form = form_cls(instance = request.user) + if request.method == "POST": + form = form_cls(data = request.POST, instance = request.user) + if form.is_valid(): + form.save() + return redirect(request.path) + else: + form = form_cls(instance = request.user) - context['form'] = form - - return render(request, 'members/detail.html', context) + return render(request, + 'members/detail.html', + {'membership_info_url': settings.MEMBER_MEMBERSHIP_INFO_URL, + 'form': form}) @login_required def subscriptions(request): subscriptions = request.user.get_active_subscriptions() old_subscriptions = request.user.get_inactive_subscriptions() + pending_subscriptions = OfferSubscriptionRequest.objects.filter(member=request.user, state="pending") - return render(request, 'members/subscriptions.html', - {'subscriptions': subscriptions, - 'old_subscriptions': old_subscriptions}) + return render(request, + 'members/subscriptions.html', + {'can_request_subscription': Offer.objects.filter(requestable=True).exists(), + 'subscriptions': subscriptions, + 'old_subscriptions': old_subscriptions, + 'pending_subscriptions': pending_subscriptions}) @login_required def invoices(request): balance = request.user.balance - invoices = request.user.invoices.filter(validated=True).order_by('-date') + invoices = Bill.get_member_validated_bills(request.user) + invoices.reverse() payments = request.user.payments.filter().order_by('-date') - return render(request, 'members/invoices.html', - {'balance' : balance, - 'handle_balance' : settings.HANDLE_BALANCE, - 'invoices': invoices, - 'payments': payments}) + return render(request, + 'members/invoices.html', + {'balance' : balance, + 'handle_balance' : settings.HANDLE_BALANCE, + 'invoices': invoices, + 'payments': payments, + 'member': request.user}) @login_required @@ -70,11 +77,9 @@ def contact(request): @login_required def activation_completed(request): - label_template = settings.MEMBERSHIP_REFERENCE.format(user=request.user) - context = { - 'bank_transfer_label': label_template, - 'dues': settings.DEFAULT_MEMBERSHIP_FEE - } - - return render(request, 'members/registration/activation_complete.html', - context) + + return render(request, + 'members/registration/activation_complete.html', + {'member': request.user, + 'dues': settings.DEFAULT_MEMBERSHIP_FEE + }) diff --git a/coin/offers/admin.py b/coin/offers/admin.py index 461b1aea84a3cc8696c47e9cbe9d64f16d90fbd2..9ddcfe8de2682fb2fc65b4d733138242552bf593 100644 --- a/coin/offers/admin.py +++ b/coin/offers/admin.py @@ -1,27 +1,39 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.contrib import admin +import autocomplete_light + +from django.contrib import admin, messages from django.db.models import Q -from polymorphic.admin import PolymorphicChildModelAdmin +from django.conf.urls import url +from django.shortcuts import get_object_or_404 +from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from django.utils.safestring import mark_safe +from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin from coin.members.models import Member -from coin.offers.models import Offer, OfferSubscription +from coin.offers.models import Offer, OfferIPPool, OfferSubscription, OfferSubscriptionRequest from coin.offers.offersubscription_filter import\ OfferSubscriptionTerminationFilter,\ OfferSubscriptionCommitmentFilter from coin.offers.forms import OfferAdminForm -import autocomplete_light +from coin.configuration.admin import ChildConfigurationAdmin +from coin.configuration.models import Configuration +from coin.resources.models import IPSubnet + +class OfferIPPoolAdmin(admin.TabularInline): + model = OfferIPPool + extra = 1 class OfferAdmin(admin.ModelAdmin): - list_display = ('get_configuration_type_display', 'name', 'reference', 'billing_period', 'period_fees', + list_display = ('name', 'get_configuration_type_display', 'reference', 'billing_period', 'period_fees', 'initial_fees') - list_display_links = ('name',) list_filter = ('configuration_type',) search_fields = ['name'] form = OfferAdminForm - + inlines = (OfferIPPoolAdmin,) # def get_readonly_fields(self, request, obj=None): # if obj: # return ['backend',] @@ -32,13 +44,13 @@ class OfferAdmin(admin.ModelAdmin): class OfferSubscriptionAdmin(admin.ModelAdmin): list_display = ('get_subscription_reference', 'member', 'offer', 'subscription_date', 'commitment', 'resign_date') - list_display_links = ('member','offer') + list_display_links = ('get_subscription_reference',) list_filter = ( OfferSubscriptionTerminationFilter, OfferSubscriptionCommitmentFilter, 'offer', 'member') search_fields = ['member__first_name', 'member__last_name', 'member__email', 'member__nickname'] - + fields = ( 'member', 'offer', @@ -77,10 +89,133 @@ class OfferSubscriptionAdmin(admin.ModelAdmin): correspondant à l'offre choisie """ if obj is not None: - for item in PolymorphicChildModelAdmin.__subclasses__(): + for item in ChildConfigurationAdmin.__subclasses__(): if (item.base_model.__name__ == obj.offer.configuration_type): return [item.inline(self.model, self.admin_site)] return [] + def save_model(self, request, obj, form, change): + super(OfferSubscriptionAdmin, self).save_model(request, obj, form, change) + + # On auto-complète le modèle que si on n'est pas en train de créer un + # abonnement via une configuration + if request.GET.get('_popup', 0): + return + + obj.create_config_if_it_does_not_exists_yet() + + +class ParentOfferSubscriptionRequestAdmin(PolymorphicParentModelAdmin): + + base_model = OfferSubscriptionRequest + + list_display = ('__unicode__', 'enhanced_state', 'request_date') + + list_display_links = ('__unicode__',) + + list_filter = ("state",) + + polymorphic_list = True + + def get_child_models(self): + """ + Renvoi la liste des modèles enfants de ChildOfferSubscriptionRequestAdmin + ex :((VPNSubscriptionRequest, VPNSubscriptionRequestAdmin), + (AccountSubscriptionRequest, AccountSubscriptionRequestAdmin)) + """ + return tuple((x.base_model, x) for x in ChildOfferSubscriptionRequestAdmin.__subclasses__()) + + def enhanced_state(self, obj): + + if obj.state == "pending": + icon = ' ' + color = "goldenrod" + elif obj.state == "accepted": + icon = ' ' + color = "green" + elif obj.state == "refused": + icon = ' ' + color = "crimson" + else: + # Should not happen + icon = "" + + return mark_safe("{icon} {state}".format(color=color, icon=icon, state=obj.get_state_display())) + + enhanced_state.short_description = "Status" + + def get_urls(self): + """ + Custom admin urls + """ + urls = super(ParentOfferSubscriptionRequestAdmin, self).get_urls() + my_urls = [ + url(r'^process/(?P.+)/(?P[a-z_]+)$', + self.admin_site.admin_view(self.view_process), + name='offersubscriptionrequest_process') + ] + return my_urls + urls + + def view_process(self, request, id, whatdo): + + if not request.user.is_superuser: + messages.error( + request, 'Vous n\'avez pas l\'autorisation de gérer les demandes de service.') + elif whatdo not in ["accept", "refuse"]: + messages.error(request, "This is not a valid process action") + else: + offersubscriptionrequest = get_object_or_404(OfferSubscriptionRequest, pk=id) + + if offersubscriptionrequest.state != u"pending": + messages.error(request, "Cette demande a déjà été acceptée ou refusée.") + else: + try: + if whatdo == "accept": + offersubscriptionrequest.accept() + elif whatdo == "refuse": + offersubscriptionrequest.refuse() + except Exception as e: + messages.error(request, "Erreur en tentant de processer l'action %s pour %s : %s" % (whatdo, offersubscriptionrequest, str(e))) + + return HttpResponseRedirect(reverse('admin:offers_offersubscriptionrequest_change', + args=(id,))) + + +class ChildOfferSubscriptionRequestAdmin(PolymorphicChildModelAdmin): + + change_form_template = "admin/offersubscriptionrequest/change_form.html" + + def get_fieldsets(self, request, obj=None): + return [ + ('', {'fields': ( + 'member', + 'offer', + ('state', 'request_date', 'resolution_date'), + 'member_comments', + 'admin_comments')}), + ('Abonnement créé', { + 'fields': ('offersubscription',), + 'description': 'Un abonnement sera automatiquement créé une fois la demande validée'}) + ] + + def get_readonly_fields(self, request, obj=None): + readonly = ["state", "request_date", "resolution_date", "offersubscription"] + if obj: + readonly += ["member_comments"] + if obj.state != "pending": + readonly += ["member", "offer"] + return readonly + + # + # This allows to only display VPS-related *requestable* offers + # when creating a VPSSubscriptionRequests (for example) + # + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "offer": + kwargs["queryset"] = OfferSubscriptionRequest.requestable_offers(offer_type=self.base_model.offer_type) + return super(ChildOfferSubscriptionRequestAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) + + admin.site.register(Offer, OfferAdmin) admin.site.register(OfferSubscription, OfferSubscriptionAdmin) +admin.site.register(OfferSubscriptionRequest, ParentOfferSubscriptionRequestAdmin) diff --git a/coin/offers/app.py b/coin/offers/app.py index 85c9d1e5a962d9b2d6f81ae5bb39a3c54e11df85..abb4fe3a0e2e241a502da4d698bead123c74d147 100644 --- a/coin/offers/app.py +++ b/coin/offers/app.py @@ -7,3 +7,13 @@ from django.apps import AppConfig class OffersConfig(AppConfig): name = 'coin.offers' verbose_name = 'Offres et Abonnements' + admin_menu_entry = { + "id": "services", + "icon": "shopping-cart", + "title": "Services", + "models": [ + ("Offres", "offers/offer"), + ("Demandes", "offers/offersubscriptionrequest"), + ("Abonnements", "offers/offersubscription"), + ] + } diff --git a/coin/offers/forms.py b/coin/offers/forms.py index 8b545ea157c7465fb8edb88cb254e947f219d9ac..4f41d0e81ee6e4c8da56b11d6b565418eb17af18 100644 --- a/coin/offers/forms.py +++ b/coin/offers/forms.py @@ -1,14 +1,113 @@ # -*- coding: utf-8 -*- -from django.forms import ModelForm +from django import forms from django.forms.widgets import Select -from coin.offers.models import Offer +from django.core.urlresolvers import reverse +from django.conf import settings + +from coin.offers.models import Offer, OfferSubscriptionRequest from coin.configuration.models import Configuration +from coin.utils import send_templated_email + +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout, Div +from crispy_forms.bootstrap import StrictButton + +class ConfigurationTypeSelect(forms.Select): + def render(self, *args, **kwargs): + # We do this so that get_configurations_choices_list is called during + # runtime once we're sure all Configuration subclasses are loaded... + self.choices = [('', '---------'),] + list(Configuration.get_configurations_choices_list()) + return super(ConfigurationTypeSelect, self).render(*args, **kwargs) -class OfferAdminForm(ModelForm): +class OfferAdminForm(forms.ModelForm): class Meta: model = Offer widgets = { - 'configuration_type': Select(choices=(('','---------'),) + Configuration.get_configurations_choices_list()) + 'configuration_type': ConfigurationTypeSelect() } - exclude = ('', ) \ No newline at end of file + exclude = ('', ) + +class OfferSubscriptionRequestStep1Form(forms.Form): + + offer_type = forms.ChoiceField(label="Type d'abonnement", widget=forms.RadioSelect, required=True) + + def __init__(self, *args, **kwargs): + super(OfferSubscriptionRequestStep1Form, self).__init__(*args, **kwargs) + self.fields['offer_type'].choices = tuple((type, type) for type in OfferSubscriptionRequest.requestable_offertypes()) + + @property + def helper(self): + helper = FormHelper() + + helper.layout = Layout( + *(self.fields.keys() + [ + Div( + StrictButton('Continuer', css_class="btn-primary", type="submit"), + css_class="text-center" + ) + ]) + ) + + return helper + +class OfferSubscriptionRequestStep2Form(forms.Form): + + offer = forms.ModelChoiceField(queryset=None, label="Offre", required=True) + member_comments = forms.CharField(label="Commentaires pour l'équipe de bénévole", max_length=1000, widget=forms.Textarea(attrs={'style': 'height: 10em;'}), required=False) + agree_tos = forms.BooleanField(label="Vous acceptez les conditions d'abonnement et d'utilisation de cette offre", required=True) + + def __init__(self, *args, **kwargs): + super(OfferSubscriptionRequestStep2Form, self).__init__(*args, **kwargs) + + # Put the comment + agree tos checkbox at the end of the form + member_comments = self.fields.pop("member_comments") + agree_tos = self.fields.pop("agree_tos") + self.fields["member_comments"] = member_comments + self.fields["agree_tos"] = agree_tos + + def set_offer_choices(self, offer_type): + self.offer_type = offer_type + self.fields['offer'].queryset = OfferSubscriptionRequest.requestable_offers(offer_type=offer_type) + + def create_offersubscriptionrequest(self, request): + + request_class = self.cleaned_data["offer"].subscriptionrequest_class + subscription_request = request_class.objects.create(offer=self.cleaned_data["offer"], + member=request.user, + member_comments=self.cleaned_data["member_comments"]) + subscription_request.save() + + if settings.REQUESTS_NOTIFICATION_EMAILS: + + relative_link = reverse('admin:offers_offersubscriptionrequest_change', args=[subscription_request.id]) + admin_link = request.build_absolute_uri(relative_link) + + send_templated_email( + to=settings.REQUESTS_NOTIFICATION_EMAILS, + subject_template='offers/emails/subscription_request_new_subject.txt', + body_template='offers/emails/subscription_request_new.txt', + context={'request': subscription_request, 'admin_link': admin_link}, + ) + + return subscription_request + + @property + def helper(self): + helper = FormHelper() + + helper.form_action = reverse('members:subscriptionrequest_step2', args=[self.offer_type]) + + helper.form_class = 'form-horizontal' + helper.label_class = 'col-4' + helper.field_class = 'col-8' + helper.layout = Layout( + *(self.fields.keys() + [ + Div( + StrictButton(' Envoyer la demande', css_class="btn-success", type="submit"), + css_class="text-center" + ) + ]) + ) + + return helper diff --git a/coin/offers/migrations/0008_auto_20170818_1507.py b/coin/offers/migrations/0008_auto_20170818_1507.py new file mode 100644 index 0000000000000000000000000000000000000000..0f5e4cb7083595374333d5ef9285f0f93f61cc27 --- /dev/null +++ b/coin/offers/migrations/0008_auto_20170818_1507.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resources', '0003_auto_20150203_1043'), + ('offers', '0007_offersubscription_comments'), + ] + + operations = [ + migrations.CreateModel( + name='OfferIPPool', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('priority', models.IntegerField()), + ('ippool', models.ForeignKey(to='resources.IPPool')), + ('offer', models.ForeignKey(to='offers.Offer')), + ], + options={ + 'ordering': ['priority'], + }, + ), + migrations.AddField( + model_name='offer', + name='ippools', + field=models.ManyToManyField(to='resources.IPPool', through='offers.OfferIPPool'), + ), + ] diff --git a/coin/offers/migrations/0009_auto_20170818_1529.py b/coin/offers/migrations/0009_auto_20170818_1529.py new file mode 100644 index 0000000000000000000000000000000000000000..d22258e1aa56a919e7a0a066f691baac07fcc022 --- /dev/null +++ b/coin/offers/migrations/0009_auto_20170818_1529.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('offers', '0008_auto_20170818_1507'), + ] + + operations = [ + migrations.AlterModelOptions( + name='offerippool', + options={'ordering': ['to_assign'], 'verbose_name': "pool d'IP", 'verbose_name_plural': "pools d'IP"}, + ), + migrations.RemoveField( + model_name='offerippool', + name='priority', + ), + migrations.AddField( + model_name='offerippool', + name='to_assign', + field=models.BooleanField(default=False, verbose_name='assignation par d\xe9faut'), + ), + migrations.AlterField( + model_name='offerippool', + name='ippool', + field=models.ForeignKey(verbose_name="pool d'IP", to='resources.IPPool'), + ), + migrations.AlterField( + model_name='offerippool', + name='offer', + field=models.ForeignKey(verbose_name='offre', to='offers.Offer'), + ), + ] diff --git a/coin/offers/migrations/0010_auto_20170818_1835.py b/coin/offers/migrations/0010_auto_20170818_1835.py new file mode 100644 index 0000000000000000000000000000000000000000..4bbea48642733e8d101a3dd3dccf61bc5fc32e4c --- /dev/null +++ b/coin/offers/migrations/0010_auto_20170818_1835.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('offers', '0009_auto_20170818_1529'), + ] + + operations = [ + migrations.AlterModelOptions( + name='offerippool', + options={'ordering': ['-to_assign'], 'verbose_name': "pool d'IP", 'verbose_name_plural': "pools d'IP"}, + ), + migrations.RenameField( + model_name='offer', + old_name='ippools', + new_name='ip_pools', + ), + migrations.RenameField( + model_name='offerippool', + old_name='ippool', + new_name='ip_pool', + ), + ] diff --git a/coin/offers/migrations/0011_auto_20200717_1733.py b/coin/offers/migrations/0011_auto_20200717_1733.py new file mode 100644 index 0000000000000000000000000000000000000000..94e0297cbd196a6c7849ab5fc2deba6f61ae15e5 --- /dev/null +++ b/coin/offers/migrations/0011_auto_20200717_1733.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import datetime +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('offers', '0010_auto_20170818_1835'), + ] + + operations = [ + migrations.CreateModel( + name='Request', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('state', models.CharField(default='pending', max_length=14, verbose_name='status', choices=[('pending', 'En attente'), ('accepted', 'Accept\xe9'), ('refused', 'Refus\xe9')])), + ('request_date', models.DateTimeField(default=datetime.datetime.now, verbose_name='date de la demande')), + ('resolution_date', models.DateTimeField(null=True, verbose_name='date de r\xe9solution', blank=True)), + ('member_comments', models.TextField(help_text='Commentaires libres', verbose_name='commentaires du membre', blank=True)), + ('admin_comments', models.TextField(help_text="Commentaires de l'\xe9quipe b\xe9n\xe9vole", verbose_name="commentaires de l'\xe9quipe b\xe9n\xe9vole", blank=True)), + ], + options={ + 'verbose_name': 'demande', + }, + ), + migrations.AddField( + model_name='offer', + name='infos', + field=models.TextField(help_text='Informations compl\xe9mentaires pour les membres, affich\xe9es dans leur espace', verbose_name='infos compl\xe9mentaires', blank=True), + ), + migrations.AddField( + model_name='offer', + name='requestable', + field=models.BooleanField(default=False, verbose_name='Permettre aux membres de cr\xe9er des demandes pour cette offre depuis leur espace'), + ), + migrations.AlterField( + model_name='offer', + name='ip_pools', + field=models.ManyToManyField(related_name='offers', through='offers.OfferIPPool', to='resources.IPPool'), + ), + migrations.AlterField( + model_name='offerippool', + name='ip_pool', + field=models.ForeignKey(related_name='offer_ip_pools', verbose_name="pool d'IP", to='resources.IPPool'), + ), + migrations.AlterField( + model_name='offerippool', + name='offer', + field=models.ForeignKey(related_name='offer_ip_pools', verbose_name='offre', to='offers.Offer'), + ), + migrations.AlterField( + model_name='offerippool', + name='to_assign', + field=models.BooleanField(default=False, help_text="Si vous cocher cette case, COIN utilisera ce pool d'IP afin de d\xe9finir l'IP d'endpoint", verbose_name="utiliser pour les IP d'endpoints"), + ), + migrations.CreateModel( + name='OfferSubscriptionRequest', + fields=[ + ('request_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='offers.Request')), + ('offer', models.ForeignKey(verbose_name='offre', to='offers.Offer')), + ('offersubscription', models.OneToOneField(related_name='subscriptionrequest', null=True, blank=True, to='offers.OfferSubscription', verbose_name='abonnement cr\xe9\xe9')), + ], + options={ + 'verbose_name': 'demande de souscription', + 'verbose_name_plural': 'demandes de souscription', + }, + bases=('offers.request',), + ), + migrations.AddField( + model_name='request', + name='member', + field=models.ForeignKey(verbose_name='membre', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='request', + name='polymorphic_ctype', + field=models.ForeignKey(related_name='polymorphic_offers.request_set+', editable=False, to='contenttypes.ContentType', null=True), + ), + ] diff --git a/coin/offers/models.py b/coin/offers/models.py index 0a01a9d1e751828a4fe37a7696c46140aa4dc3ef..404a4befb83cc280877ea51fd354ee26f206071a 100644 --- a/coin/offers/models.py +++ b/coin/offers/models.py @@ -3,12 +3,17 @@ from __future__ import unicode_literals import datetime +from polymorphic import PolymorphicModel + from django.conf import settings from django.db import models from django.db.models import Count, Q from django.core.validators import MinValueValidator from django.contrib.contenttypes.models import ContentType +from coin.utils import get_descendant_classes, send_templated_email +from coin.resources.models import IPPool + class OfferManager(models.Manager): def manageable_by(self, user): @@ -59,19 +64,66 @@ class Offer(models.Model): non_billable = models.BooleanField(default=False, verbose_name='n\'est pas facturable', help_text='L\'offre ne sera pas facturée par la commande charge_members') + requestable = models.BooleanField(default=False, + verbose_name='Permettre aux membres de créer des demandes pour cette offre depuis leur espace') + + infos = models.TextField(blank=True, + verbose_name='infos complémentaires', + help_text="Informations complémentaires pour les membres, affichées dans leur espace") + + ip_pools = models.ManyToManyField(IPPool, related_name='offers', through='OfferIPPool') objects = OfferManager() def get_configuration_type_display(self): + return Offer._get_offer_type(self.configuration_type) + get_configuration_type_display.short_description = 'type de configuration' + + @staticmethod + def _get_offer_type(configuration_type): """ - Renvoi le nom affichable du type de configuration + This translates for example "VPNConfiguration" into "VPN" ... """ from coin.configuration.models import Configuration - for item in Configuration.get_configurations_choices_list(): - if item and self.configuration_type in item: - return item[1] - return self.configuration_type - get_configuration_type_display.short_description = 'type de configuration' + for subconfig_class in get_descendant_classes(Configuration): + if subconfig_class.__name__ == configuration_type: + return subconfig_class._meta.verbose_name + return configuration_type + + @staticmethod + def _get_configuration_type(offer_type): + """ + This translates for example "VPN" into "VPNConfiguration" ... + """ + from coin.configuration.models import Configuration + for subconfig_class in get_descendant_classes(Configuration): + if subconfig_class._meta.verbose_name == offer_type: + return subconfig_class.__name__ + return offer_type + + @property + def configuration_class(self): + """ + This translate an offer into its corresponding configuration class (e.g. VPNConfiguration) + """ + from coin.configuration.models import Configuration + for subconfig_class in get_descendant_classes(Configuration): + if subconfig_class.__name__ == self.configuration_type: + return subconfig_class + return None + + + @property + def subscriptionrequest_class(self): + """ + This translate an offer into its corresponding subscription request class (e.g. VPNSubscriptionRequest) + """ + conf_class = self.configuration_class + for subconfig_class in get_descendant_classes(OfferSubscriptionRequest): + if subconfig_class.configuration_class == conf_class: + return subconfig_class + return None + def display_price(self): """Displays the price of an offer in a human-readable manner @@ -97,6 +149,25 @@ class Offer(models.Model): verbose_name = 'offre' +class OfferIPPool(models.Model): + offer = models.ForeignKey(Offer, + verbose_name='offre', related_name='offer_ip_pools') + ip_pool = models.ForeignKey(IPPool, + verbose_name='pool d\'IP', related_name='offer_ip_pools') + to_assign = models.BooleanField(default=False, + verbose_name='utiliser pour les IP d\'endpoints', + help_text='Si vous cocher cette case, COIN utilisera ce pool d\'IP' + ' afin de définir l\'IP d\'endpoint') + def __unicode__(self): + return '{ip_pool} - {offer}'.format(ip_pool=self.ip_pool, + offer=self.offer) + + class Meta: + verbose_name = 'pool d\'IP' + verbose_name_plural = "pools d'IP" + ordering = ['-to_assign'] + + class OfferSubscriptionQuerySet(models.QuerySet): def running(self, at_date=None): """ Only the running contracts at a given date. @@ -155,10 +226,25 @@ class OfferSubscription(models.Model): return settings.SUBSCRIPTION_REFERENCE.format(subscription=self) get_subscription_reference.short_description = 'Référence' + def create_config_if_it_does_not_exists_yet(self): + if not hasattr(self, 'configuration'): + config_class = self.offer.configuration_class + if config_class is not None: + config = config_class.objects.create(offersubscription=self) + config.offersubscription = self + config.save() + return True + + return False + def __unicode__(self): return '%s - %s - %s' % (self.member, self.offer.name, self.subscription_date) + def bulk_related_objects(self, objs, *args, **kwargs): + # Fix delete screen. Workaround for https://github.com/chrisglass/django_polymorphic/issues/34 + return super(OfferSubscription, self).bulk_related_objects(objs, *args, **kwargs).non_polymorphic() + class Meta: verbose_name = 'abonnement' @@ -167,3 +253,124 @@ def count_active_subscriptions(): today = datetime.date.today() query = Q(subscription_date__lte=today) & (Q(resign_date__isnull=True) | Q(resign_date__gte=today)) return OfferSubscription.objects.filter(query).count() + + +class Request(PolymorphicModel): + """ + Corresponds to request made by a member, for instance a request to create a + new VPN subscription, of a request to reinstall a VPS + """ + + member = models.ForeignKey('members.Member', verbose_name='membre') + + state = models.CharField(max_length=14, + choices=[('pending', 'En attente'), + ('accepted', 'Accepté'), + ('refused', 'Refusé')], + default="pending", + verbose_name="status") + + request_date = models.DateTimeField(null=False, + blank=False, + default=datetime.datetime.now, + verbose_name="date de la demande") + + resolution_date = models.DateTimeField(null=True, + blank=True, + verbose_name='date de résolution') + + member_comments = models.TextField(blank=True, + verbose_name='commentaires du membre', + help_text="Commentaires libres") + + admin_comments = models.TextField(blank=True, + verbose_name='commentaires de l\'équipe bénévole', + help_text="Commentaires de l\'équipe bénévole") + + def accept(self): + self.state = "accepted" + self.resolution_date = datetime.datetime.now() + self.save() + + def refuse(self): + self.state = "refused" + self.resolution_date = datetime.datetime.now() + self.save() + + def __unicode__(self): + return 'Demande de %s' % self.member + + def bulk_related_objects(self, objs, *args, **kwargs): + # Fix delete screen. Workaround for https://github.com/chrisglass/django_polymorphic/issues/34 + return super(OfferSubscription, self).bulk_related_objects(objs, *args, **kwargs).non_polymorphic() + + class Meta: + verbose_name = 'demande' + + +class OfferSubscriptionRequest(Request): + + offer = models.ForeignKey('Offer', verbose_name='offre') + + offersubscription = models.OneToOneField(OfferSubscription, + blank=True, null=True, + related_name='subscriptionrequest', + verbose_name='abonnement créé') + + offer_type = None + + def accept(self): + + self.offersubscription = OfferSubscription.objects.create(offer=self.offer, + member=self.member, + comments=self.admin_comments) + self.offersubscription.save() + + super(OfferSubscriptionRequest, self).accept() + + self.offersubscription.create_config_if_it_does_not_exists_yet() + + # If there are some provisioning_infos to transmit to the created configuration + config = self.offersubscription.configuration + for info in config.provisioning_infos: + setattr(config, info, getattr(self, info)) + config.save() + + send_templated_email( + to=self.member.email, + subject_template='offers/emails/subscription_request_accepted_subject.txt', + body_template='offers/emails/subscription_request_accepted.txt', + context={ 'request': self }) + + def refuse(self): + + super(OfferSubscriptionRequest, self).refuse() + + send_templated_email( + to=self.member.email, + subject_template='offers/emails/subscription_request_refused_subject.txt', + body_template='offers/emails/subscription_request_refused.txt', + context={ 'request': self }) + + @property + def configuration_type(self): + return Offer._get_configuration_type(self.offer_type) + + @staticmethod + def requestable_offers(offer_type=None): + + if offer_type is None: + return Offer.objects.filter(requestable=True) + else: + return Offer.objects.filter(configuration_type=Offer._get_configuration_type(offer_type), requestable=True) + + @staticmethod + def requestable_offertypes(): + return sorted({Offer._get_offer_type(o.configuration_type) for o in Offer.objects.filter(requestable=True)}) + + def __unicode__(self): + return 'Demande de %s pour un %s' % (self.member, self.offer.name) + + class Meta: + verbose_name = 'demande de souscription' + verbose_name_plural = 'demandes de souscription' diff --git a/coin/offers/templates/admin/offersubscriptionrequest/change_form.html b/coin/offers/templates/admin/offersubscriptionrequest/change_form.html new file mode 100644 index 0000000000000000000000000000000000000000..1dab025a107d916bd69bf2cc40a8548234c6d22c --- /dev/null +++ b/coin/offers/templates/admin/offersubscriptionrequest/change_form.html @@ -0,0 +1,12 @@ +{% extends "admin/change_form.html" %} +{% load configuration %} +{% block object-tools-items %} + {% if original.state == "pending" %} +
  • Accepter
  • + {% if original.offer.configuration_class|provision_is_managed_via_hook %} +
  • Accepter et provisionner
  • + {% endif %} +
  • Refuser
  • + {% endif %} + {{ block.super }} +{% endblock %} diff --git a/coin/offers/templates/members/offersubscriptionrequest/form.html b/coin/offers/templates/members/offersubscriptionrequest/form.html new file mode 100644 index 0000000000000000000000000000000000000000..3b3aa761be525dec2fb7da23a7e8ca35db02c46b --- /dev/null +++ b/coin/offers/templates/members/offersubscriptionrequest/form.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} + +{% load crispy_forms_tags %} + +{% block title %}Demande de nouvel abonnement{% endblock %} + +{% block content %} +
    +

    Demande de nouvel abonnement

    + + {% if form %} +
    + {% crispy form %} +
    + {% elif success %} +
    +

    + Votre demande a bien été transmise à l'équipe de bénévoles ! +

    +

    + En attendant sa validation, vous pouvez vous préparer à mettre en place un virement automatique grâce aux coordonnées bancaires décrites dans "Factures et paiements" +

    + D'accord ! +
    + {% endif %} +
    + +{% endblock %} diff --git a/coin/offers/templates/offers/emails/subscription_request_accepted.html b/coin/offers/templates/offers/emails/subscription_request_accepted.html new file mode 100644 index 0000000000000000000000000000000000000000..8e862ba019759e006bf0fde760894f5fc1755193 --- /dev/null +++ b/coin/offers/templates/offers/emails/subscription_request_accepted.html @@ -0,0 +1,16 @@ +

    +Un bénévole viens de valider votre demande pour un {{ request.offer.name }}. +

    + +{% if request.admin_comments %} +

    +Commentaires de l'équipe bénévole : +

    +

    +{{ request.admin_comments }} +

    +{% endif %} + +

    +Vous pouvez consulter votre espace adhérent pour plus d'informations sur l'état et la configuration de votre service. +

    diff --git a/coin/offers/templates/offers/emails/subscription_request_accepted_subject.txt b/coin/offers/templates/offers/emails/subscription_request_accepted_subject.txt new file mode 100644 index 0000000000000000000000000000000000000000..326812d8767711ac4679f1a5d006c43729a97d41 --- /dev/null +++ b/coin/offers/templates/offers/emails/subscription_request_accepted_subject.txt @@ -0,0 +1 @@ +Votre demande pour un {{ request.offer.name }} a été accepté ! diff --git a/coin/offers/templates/offers/emails/subscription_request_new.html b/coin/offers/templates/offers/emails/subscription_request_new.html new file mode 100644 index 0000000000000000000000000000000000000000..3b195c93a64d7fc11fcd375673dee32d59f33bab --- /dev/null +++ b/coin/offers/templates/offers/emails/subscription_request_new.html @@ -0,0 +1,11 @@ +{% extends "emails/staff_email_base.html" %} + +{% block content %} +

    +{{ request.member }} vient de faire une demande pour un {{ request.offer.name }} +

    + +

    +Lien pour gérer la requête: {{ admin_link }} +

    +{% endblock %} diff --git a/coin/offers/templates/offers/emails/subscription_request_new_subject.txt b/coin/offers/templates/offers/emails/subscription_request_new_subject.txt new file mode 100644 index 0000000000000000000000000000000000000000..70f48a956486f7d3e321f91f1c12c3823ff0d27d --- /dev/null +++ b/coin/offers/templates/offers/emails/subscription_request_new_subject.txt @@ -0,0 +1 @@ +Nouvelle demande de {{ request.member }} pour un {{ request.offer.name }} diff --git a/coin/offers/templates/offers/emails/subscription_request_refused.html b/coin/offers/templates/offers/emails/subscription_request_refused.html new file mode 100644 index 0000000000000000000000000000000000000000..fd71b0da6c63cb71a62b3d424cd9503bea8fc01d --- /dev/null +++ b/coin/offers/templates/offers/emails/subscription_request_refused.html @@ -0,0 +1,11 @@ +

    +Votre demande pour un {{ request.offer.name }} a été refusée. +

    + +

    +Commentaires de l'équipe bénévole : +

    + +

    +{{ request.admin_comments }} +

    diff --git a/coin/offers/templates/offers/emails/subscription_request_refused_subject.txt b/coin/offers/templates/offers/emails/subscription_request_refused_subject.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b22b1850d0d4249f8aabb05ce5591b3c9195ded --- /dev/null +++ b/coin/offers/templates/offers/emails/subscription_request_refused_subject.txt @@ -0,0 +1 @@ +Votre demande pour un {{ request.offer.name }} a été refusée. diff --git a/coin/offers/urls.py b/coin/offers/urls.py index 129584f1bfd23a972edb26c91229a64884afa47f..3dd3c13bace089b4a545c0eed07816c70fb85d8f 100644 --- a/coin/offers/urls.py +++ b/coin/offers/urls.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.conf.urls import patterns, url +from django.conf.urls import url from coin.offers.views import ConfigurationRedirectView, subscription_count_json -urlpatterns = patterns( - '', +urlpatterns = [ + #'', # Redirect to the appropriate configuration backend. url(r'^configuration/(?P.+)$', ConfigurationRedirectView.as_view(), name="configuration-redirect"), url(r'^api/v1/count$', subscription_count_json), -) +] diff --git a/coin/offers/views.py b/coin/offers/views.py index d2e825a7196c7d55910ec157ac3a2d91a6c3922c..9345303f471a3423b3aae6374d2584361390b61a 100644 --- a/coin/offers/views.py +++ b/coin/offers/views.py @@ -6,12 +6,13 @@ import json from django.db.models import Q, Count from django.views.generic.base import RedirectView -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, render from django.core.urlresolvers import reverse -from django.http import JsonResponse, HttpResponseServerError -# from django.views.decorators.cache import cache_control +from django.http import JsonResponse, HttpResponseServerError, HttpResponseRedirect +from django.contrib.auth.decorators import login_required -from coin.offers.models import Offer, OfferSubscription +from coin.offers.models import Offer, OfferSubscription, OfferSubscriptionRequest +from coin.offers.forms import OfferSubscriptionRequestStep1Form, OfferSubscriptionRequestStep2Form class ConfigurationRedirectView(RedirectView): """Redirects to the appropriate view for the configuration backend of the @@ -50,4 +51,43 @@ def subscription_count_json(request): }) # Return JSON - return JsonResponse(output, safe=False) \ No newline at end of file + return JsonResponse(output, safe=False) + + +@login_required +def offersubscriptionrequest_step1(request): + if request.method == 'POST': + form = OfferSubscriptionRequestStep1Form(request.POST) + if form.is_valid(): + return HttpResponseRedirect(reverse('members:subscriptionrequest_step2', args=[request.POST["offer_type"]])) + else: + form = OfferSubscriptionRequestStep1Form() + + return render(request, 'members/offersubscriptionrequest/form.html', {'form': form}) + + +@login_required +def offersubscriptionrequest_step2(request, offer_type): + if offer_type not in OfferSubscriptionRequest.requestable_offertypes(): + return HttpResponseServerError("Ce type d'offre n'est pas correct.") + + # Try to get the form class specific to this offer type. + # If we do not find such a class, fallback to the regular "OfferSubscriptionRequestStep2Form" + FormsPerOfferType = {x.offer_type:x for x in OfferSubscriptionRequestStep2Form.__subclasses__()} + FormForThisOfferType = FormsPerOfferType.get(offer_type, OfferSubscriptionRequestStep2Form) + + if request.method == 'POST': + form = FormForThisOfferType(request.POST) + form.set_offer_choices(offer_type) + if form.is_valid(): + form.create_offersubscriptionrequest(request) + return HttpResponseRedirect(reverse('members:subscriptionrequest_step3')) + else: + form = FormForThisOfferType() + form.set_offer_choices(offer_type) + + return render(request, 'members/offersubscriptionrequest/form.html', {'form': form}) + +@login_required +def offersubscriptionrequest_step3(request): + return render(request, 'members/offersubscriptionrequest/form.html', {'success': True}) diff --git a/coin/resources/__init__.py b/coin/resources/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7a965971938269222f95f563f0f6bb90e59fccb3 100644 --- a/coin/resources/__init__.py +++ b/coin/resources/__init__.py @@ -0,0 +1 @@ +default_app_config = 'coin.resources.app.ResourcesConfig' diff --git a/coin/resources/admin.py b/coin/resources/admin.py index 8db23dc5d8b794ce833b02ffea6558be7c4a2b48..743758b28d56acc14003d9ae81ea300983cc06b2 100644 --- a/coin/resources/admin.py +++ b/coin/resources/admin.py @@ -4,17 +4,32 @@ from __future__ import unicode_literals from django.contrib import admin from coin.resources.models import IPPool, IPSubnet +from coin.offers.models import OfferIPPool + + +class OfferIPPoolAdmin(admin.TabularInline): + model = OfferIPPool + extra = 1 + verbose_name_plural = "Offres utilisant ce pool d'IP" + verbose_name = "Offre utilisant ce pool d'IP" + class IPPoolAdmin(admin.ModelAdmin): - list_display = ('name', 'inet', 'default_subnetsize') + list_display = ('name', 'inet', 'default_subnetsize', 'linked_offers') ordering = ('inet',) + inlines = [OfferIPPoolAdmin] + + def linked_offers(self, obj): + offers = (i.name for i in obj.offers.all()) + return '{}'.format(', '.join(offers) or 'aucune') + linked_offers.short_description = 'Offres liées' # TODO: don't display "Delegate reverse DNS" checkbox and Nameservers when # creating/editing the object in the admin (since it is a purely # user-specific parameter) class IPSubnetAdmin(admin.ModelAdmin): - list_display = ('inet', 'ip_pool', 'configuration') + list_display = ('inet', 'ip_pool', 'configuration', 'comment') list_filter = ('ip_pool',) search_fields = ('inet',) ordering = ('inet',) diff --git a/coin/resources/app.py b/coin/resources/app.py new file mode 100644 index 0000000000000000000000000000000000000000..63c9db35285ba7d1c564659a18b5dae7117de763 --- /dev/null +++ b/coin/resources/app.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class ResourcesConfig(AppConfig): + name = 'coin.resources' + verbose_name = "IPAM / Ressources" + + admin_menu_addons = { + 'infra': [ + ("Pool d'IP", "resources/ippool"), + ("Subnets", "resources/ipsubnet"), + ] + } diff --git a/coin/resources/migrations/0004_auto_20190826_0011.py b/coin/resources/migrations/0004_auto_20190826_0011.py new file mode 100644 index 0000000000000000000000000000000000000000..aa6f6b33bb5ec7e3cc9f8f218157de6d9198be3b --- /dev/null +++ b/coin/resources/migrations/0004_auto_20190826_0011.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resources', '0003_auto_20150203_1043'), + ] + + operations = [ + migrations.AddField( + model_name='ipsubnet', + name='comment', + field=models.CharField(default='', help_text='Commentaire', max_length=255, verbose_name='commentaire', blank=True), + ), + migrations.AlterField( + model_name='ipsubnet', + name='configuration', + field=models.ForeignKey(related_name='ip_subnet', verbose_name='configuration', blank=True, to='configuration.Configuration', null=True), + ), + ] diff --git a/coin/resources/migrations/0005_auto_20200717_1733.py b/coin/resources/migrations/0005_auto_20200717_1733.py new file mode 100644 index 0000000000000000000000000000000000000000..c733c033cc784f660c5de2c6dc8c622613cb8dc3 --- /dev/null +++ b/coin/resources/migrations/0005_auto_20200717_1733.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resources', '0004_auto_20190826_0011'), + ] + + operations = [ + migrations.AlterField( + model_name='ipsubnet', + name='comment', + field=models.CharField(help_text="peut servir par exemple \xe0 indiquer que cette IP est r\xe9serv\xe9e \xe0 un \xe9l\xe9ment d'infra", max_length=255, verbose_name='commentaire', blank=True), + ), + ] diff --git a/coin/resources/models.py b/coin/resources/models.py index 69211d7e157d980c7e93a56bd1152e634c5bca05..8953e89295ea020567050fa180ac8acdfece77c0 100644 --- a/coin/resources/models.py +++ b/coin/resources/models.py @@ -5,7 +5,7 @@ from django.db import models from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator from netfields import CidrAddressField, NetManager -from netaddr import IPSet +from netaddr import IPSet, IPNetwork, IPAddress class IPPool(models.Model): @@ -50,8 +50,13 @@ class IPSubnet(models.Model): objects = NetManager() ip_pool = models.ForeignKey(IPPool, verbose_name="pool d'IP") configuration = models.ForeignKey('configuration.Configuration', + on_delete=models.CASCADE, + blank=True, null=True, related_name='ip_subnet', verbose_name='configuration') + comment = models.CharField(max_length=255, blank=True, + verbose_name='commentaire', + help_text="peut servir par exemple à indiquer que cette IP est réservée à un élément d'infra") delegate_reverse_dns = models.BooleanField(default=False, verbose_name='déléguer le reverse DNS', help_text='Déléguer la résolution DNS inverse de ce sous-réseau à un ou plusieurs serveurs de noms') @@ -65,6 +70,13 @@ class IPSubnet(models.Model): pool = IPSet([self.ip_pool.inet]) used = IPSet((s.inet for s in self.ip_pool.ipsubnet_set.all())) free = pool.difference(used) + free = free.difference(IPSet([ + IPNetwork('89.234.141.0/31'), + IPAddress('2a00:5881:8100:0100::0'), + IPAddress('2a00:5881:8100:0100::1'), + IPNetwork('2a00:5881:8118:0000::/56'), + IPNetwork('2a00:5881:8118:0100::/56'), + ])) # Generator for efficiency (we don't build the whole list) available = (p for p in free.iter_cidrs() if p.prefixlen <= self.ip_pool.default_subnetsize) # TODO: for IPv4, get rid of the network and broadcast @@ -111,6 +123,11 @@ class IPSubnet(models.Model): self.validate_inclusion() self.validate_reverse_dns() + def save(self, **kwargs): + if not self.inet: + self.allocate() + return super(IPSubnet, self).save(**kwargs) + def __unicode__(self): return str(self.inet) diff --git a/coin/resources/templatetags/subnets.py b/coin/resources/templatetags/subnets.py index 689889ddbcbb1df0a2aad3b1953c0bff745beace..cfb6e6c3852a2d8e84c8d4bcde86aef481acb4ed 100644 --- a/coin/resources/templatetags/subnets.py +++ b/coin/resources/templatetags/subnets.py @@ -11,12 +11,13 @@ register = template.Library() def prettify(subnet): """Prettify an IPv4 subnet by remove the subnet length when it is equal to /32 """ - # Support IPSubnet objects, who have a IPNetwork as attribute if hasattr(subnet, "inet") and isinstance(subnet.inet, IPNetwork): subnet = subnet.inet if isinstance(subnet, IPNetwork): if subnet.version == 4 and subnet.prefixlen == 32: return str(subnet.ip) + elif subnet.version == 6 and subnet.prefixlen == 128: + return str(subnet.ip) else: return str(subnet) return subnet diff --git a/coin/settings.py b/coin/settings.py index 0125402207e14c1bd023af6b01fd2395eb136126..43f4fd7d1dadb86faa006fcd515438b54ef2c2eb 100644 --- a/coin/settings.py +++ b/coin/settings.py @@ -10,3 +10,12 @@ except ImportError: TEMPLATE_DIRS = EXTRA_TEMPLATE_DIRS + TEMPLATE_DIRS INSTALLED_APPS = INSTALLED_APPS + EXTRA_INSTALLED_APPS + +TEMPLATES = { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': TEMPLATE_DIRS, + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': TEMPLATE_CONTEXT_PROCESSORS + }, +} diff --git a/coin/settings_base.py b/coin/settings_base.py index 7975185341705e9d37a8b27c45b8425632f887d0..39bebd87ee4155202fa5b5492437b84867a9e9ed 100644 --- a/coin/settings_base.py +++ b/coin/settings_base.py @@ -18,6 +18,7 @@ ADMINS = ( # Email on which to send emails SUBSCRIPTIONS_NOTIFICATION_EMAILS = [] +REQUESTS_NOTIFICATION_EMAILS = [] MANAGERS = ADMINS @@ -113,13 +114,6 @@ SENDFILE_BACKEND = 'sendfile.backends.development' # Make this unique, and don't share it with anybody. SECRET_KEY = '!qy_)gao6q)57#mz1s-d$5^+dp1nt=lk1d19&9bb3co37vn)!3' -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - #'django.template.loaders.eggs.Loader', -) - MIDDLEWARE_CLASSES = ( 'debug_toolbar.middleware.DebugToolbarMiddleware', 'django.middleware.common.CommonMiddleware', @@ -171,7 +165,7 @@ INSTALLED_APPS = ( 'compat', 'hijack', 'django_extensions', - + 'crispy_forms', 'coin', 'coin.members', 'coin.offers', @@ -182,6 +176,8 @@ INSTALLED_APPS = ( 'coin.isp_database', ) +CRISPY_TEMPLATE_PACK = 'bootstrap4' + EXTRA_INSTALLED_APPS = tuple() # A sample logging configuration. The only tangible logging @@ -222,18 +218,22 @@ LOGGING = { "coin.billing": { 'handlers': ['console'], 'level': 'INFO', + }, + "coin.subnets": { + 'handlers': ['console'], + 'level': 'INFO', } } } TEMPLATE_CONTEXT_PROCESSORS = ( "django.contrib.auth.context_processors.auth", - "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "django.core.context_processors.static", - "django.core.context_processors.tz", - "django.core.context_processors.request", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.template.context_processors.request", "coin.isp_database.context_processors.branding", "coin.context_processors.installed_apps", "django.contrib.messages.context_processors.messages") @@ -281,6 +281,9 @@ DEFAULT_MEMBERSHIP_FEE = 20 # membership fee MEMBER_MEMBERSHIP_INFO_URL = '' +# Statutes / Terms validation +#MEMBER_TERMS = 'J\'ai lu les statuts de l\'association' +MEMBER_TERMS = False # When should we remind a member about its membership ? List of deltas from # the anniversary date, can be a combination of positive (after anniversary) @@ -326,9 +329,6 @@ MEMBER_CAN_EDIT_VPS_CONF = True # Allow user to edit their VPN Info MEMBER_CAN_EDIT_VPN_CONF = True -# vpn app settings : how do we transmit the VPN secrets to subscriber ? -VPN_SECRETS_TRANSMISSION_METHOD = 'gen-password-and-forget' - # Account registration # Allow visitor to join the association by register on COIN REGISTRATION_OPEN = False @@ -345,6 +345,16 @@ HANDLE_BALANCE = False # Add subscription comments in invoice items INVOICES_INCLUDE_CONFIG_COMMENTS = True +# String template used for the IP allocation log (c.f. coin.subnet loggers +# This will get prefixed by [Allocating IP] or [Desallocating IP] +IP_ALLOCATION_MESSAGE = None + ## maillist module # Command that push mailling-list subscribers to the lists server MAILLIST_SYNC_COMMAND = '' + +# External account +# This label appears in member account if user can ask for a subscription +# on an external account +VERBOSE_NAME_EXTERNAL_ACCOUNT = 'Compte externe' +VERBOSE_NAME_PLURAL_EXTERNAL_ACCOUNT = 'Comptes externes' diff --git a/coin/settings_dev.py b/coin/settings_dev.py new file mode 100644 index 0000000000000000000000000000000000000000..78ffbac1264c531c107896f03ca9747ca60f2bd2 --- /dev/null +++ b/coin/settings_dev.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +from settings_base import * + +DATABASES = { + # Database hosted on vagant test box + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'coin', + 'USER': 'coin', + 'PASSWORD': 'kouaingkouaing', + 'HOST': 'db', + 'PORT': '5432', + }, +} + + +EXTRA_INSTALLED_APPS = ( + 'hardware_provisioning', + 'maillists', + 'vpn', + 'vps', + 'housing', +) + +# Surcharge les paramètres en utilisant le fichier settings_local.py +try: + from settings_local import * +except ImportError: + pass + +TEMPLATE_DIRS = EXTRA_TEMPLATE_DIRS + TEMPLATE_DIRS +INSTALLED_APPS = INSTALLED_APPS + EXTRA_INSTALLED_APPS diff --git a/coin/settings_gitlab_ci.py b/coin/settings_gitlab_ci.py new file mode 100644 index 0000000000000000000000000000000000000000..a2d13b9043e4ffba5b0e8682d762a77a5363271d --- /dev/null +++ b/coin/settings_gitlab_ci.py @@ -0,0 +1,16 @@ +""" +Configuration coin pour la CI +""" +from coin.settings_test import * + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'coin', + 'USER': 'coin', + 'PASSWORD': 'coin', + 'HOST': 'postgres', # Empty for localhost through domain sockets + 'PORT': '5432', # Empty for default + 'ATOMIC_REQUESTS': True, + } +} diff --git a/coin/static/css/admin-local.css b/coin/static/css/admin-local.css index 691e94077f9a4b581637b0a9f4764997c51f1314..b65c674991ea2d6dedb5e107a3dc359195a66cf3 100644 --- a/coin/static/css/admin-local.css +++ b/coin/static/css/admin-local.css @@ -17,3 +17,49 @@ form .inline-group .inline-related h3 .inline_label { /* TabularStacked .inline-related.dynamic-maillinglistsubscription_set .related-widget-wrapper-link.add-related { display: none; } + +/* Cards in admin index */ + +.dashboard #content { + width: auto; +} + +.app-card { + width: 31%; + border: 1px solid lightgray; + border-radius: 3px; + height: 15em; + display: inline-grid; + margin: 3px; + font-weight: bold; + position: relative; + text-align: center; +} + +.app-card h3 { + font-size: 1.9em; + margin: 0; + margin-top: 0.4em; + font-weight: normal; +} + +.app-card h3 .fa { + display: block; + font-size: 2em; +} + +.app-card ul { + position: absolute; + bottom: 0; + left: 0; + padding: 0; + margin: 0; + width: 100%; +} + +.app-card ul li { + line-height: 1.4em; + font-size: 1.2em; + list-style-type: none; + border-top: 1px solid #eee; +} diff --git a/coin/static/css/bootstrap.min.css b/coin/static/css/bootstrap.min.css new file mode 100644 index 0000000000000000000000000000000000000000..92e3fe871295c44f8fa58ddc7ac242463f13e6bd --- /dev/null +++ b/coin/static/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip{display:block}.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip,.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip{display:block}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip{display:block}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip{display:block}.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip,.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip{display:block}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:calc(1rem + .4rem);padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion>.card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion>.card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.accordion>.card .card-header{margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-sm .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-md .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-lg .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-xl .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush .list-group-item:last-child{margin-bottom:-1px}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{margin-bottom:0;border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #dee2e6;border-bottom-right-radius:.3rem;border-bottom-left-radius:.3rem}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:0s .6s opacity}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/coin/static/css/foundation.css b/coin/static/css/foundation.css deleted file mode 100644 index 87b694ce4224e26a82376d71f33c1ae93367c36d..0000000000000000000000000000000000000000 --- a/coin/static/css/foundation.css +++ /dev/null @@ -1,5006 +0,0 @@ -meta.foundation-version { - font-family: "/5.1.0/"; } - -meta.foundation-mq-small { - font-family: "/only screen and (max-width: 40em)/"; - width: 0em; } - -meta.foundation-mq-medium { - font-family: "/only screen and (min-width:40.063em)/"; - width: 40.063em; } - -meta.foundation-mq-large { - font-family: "/only screen and (min-width:64.063em)/"; - width: 64.063em; } - -meta.foundation-mq-xlarge { - font-family: "/only screen and (min-width:90.063em)/"; - width: 90.063em; } - -meta.foundation-mq-xxlarge { - font-family: "/only screen and (min-width:120.063em)/"; - width: 120.063em; } - -meta.foundation-data-attribute-namespace { - font-family: false; } - -html, body { - height: 100%; } - -*, -*:before, -*:after { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; } - -html, -body { - font-size: 100%; } - -body { - background: white; - color: #222222; - padding: 0; - margin: 0; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-weight: normal; - font-style: normal; - line-height: 1; - position: relative; - cursor: default; } - -a:hover { - cursor: pointer; } - -img, -object, -embed { - max-width: 100%; - height: auto; } - -object, -embed { - height: 100%; } - -img { - -ms-interpolation-mode: bicubic; } - -#map_canvas img, -#map_canvas embed, -#map_canvas object, -.map_canvas img, -.map_canvas embed, -.map_canvas object { - max-width: none !important; } - -.left { - float: left !important; } - -.right { - float: right !important; } - -.clearfix { - *zoom: 1; } - .clearfix:before, .clearfix:after { - content: " "; - display: table; } - .clearfix:after { - clear: both; } - -.hide { - display: none; } - -.antialiased { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; } - -img { - display: inline-block; - vertical-align: middle; } - -textarea { - height: auto; - min-height: 50px; } - -select { - width: 100%; } - -.row { - width: 100%; - margin-left: auto; - margin-right: auto; - margin-top: 0; - margin-bottom: 0; - max-width: 62.5em; - *zoom: 1; } - .row:before, .row:after { - content: " "; - display: table; } - .row:after { - clear: both; } - .row.collapse > .column, - .row.collapse > .columns { - padding-left: 0; - padding-right: 0; - float: left; } - .row.collapse .row { - margin-left: 0; - margin-right: 0; } - .row .row { - width: auto; - margin-left: -0.9375em; - margin-right: -0.9375em; - margin-top: 0; - margin-bottom: 0; - max-width: none; - *zoom: 1; } - .row .row:before, .row .row:after { - content: " "; - display: table; } - .row .row:after { - clear: both; } - .row .row.collapse { - width: auto; - margin: 0; - max-width: none; - *zoom: 1; } - .row .row.collapse:before, .row .row.collapse:after { - content: " "; - display: table; } - .row .row.collapse:after { - clear: both; } - -.column, -.columns { - padding-left: 0.9375em; - padding-right: 0.9375em; - width: 100%; - float: left; } - -@media only screen { - .column.small-centered, - .columns.small-centered { - margin-left: auto; - margin-right: auto; - float: none; } - - .column.small-uncentered, - .columns.small-uncentered { - margin-left: 0; - margin-right: 0; - float: left; } - - .column.small-uncentered.opposite, - .columns.small-uncentered.opposite { - float: right; } - - .small-push-0 { - left: 0%; - right: auto; } - - .small-pull-0 { - right: 0%; - left: auto; } - - .small-push-1 { - left: 8.33333%; - right: auto; } - - .small-pull-1 { - right: 8.33333%; - left: auto; } - - .small-push-2 { - left: 16.66667%; - right: auto; } - - .small-pull-2 { - right: 16.66667%; - left: auto; } - - .small-push-3 { - left: 25%; - right: auto; } - - .small-pull-3 { - right: 25%; - left: auto; } - - .small-push-4 { - left: 33.33333%; - right: auto; } - - .small-pull-4 { - right: 33.33333%; - left: auto; } - - .small-push-5 { - left: 41.66667%; - right: auto; } - - .small-pull-5 { - right: 41.66667%; - left: auto; } - - .small-push-6 { - left: 50%; - right: auto; } - - .small-pull-6 { - right: 50%; - left: auto; } - - .small-push-7 { - left: 58.33333%; - right: auto; } - - .small-pull-7 { - right: 58.33333%; - left: auto; } - - .small-push-8 { - left: 66.66667%; - right: auto; } - - .small-pull-8 { - right: 66.66667%; - left: auto; } - - .small-push-9 { - left: 75%; - right: auto; } - - .small-pull-9 { - right: 75%; - left: auto; } - - .small-push-10 { - left: 83.33333%; - right: auto; } - - .small-pull-10 { - right: 83.33333%; - left: auto; } - - .small-push-11 { - left: 91.66667%; - right: auto; } - - .small-pull-11 { - right: 91.66667%; - left: auto; } - - .column, - .columns { - position: relative; - padding-left: 0.9375em; - padding-right: 0.9375em; - float: left; } - - .small-1 { - width: 8.33333%; } - - .small-2 { - width: 16.66667%; } - - .small-3 { - width: 25%; } - - .small-4 { - width: 33.33333%; } - - .small-5 { - width: 41.66667%; } - - .small-6 { - width: 50%; } - - .small-7 { - width: 58.33333%; } - - .small-8 { - width: 66.66667%; } - - .small-9 { - width: 75%; } - - .small-10 { - width: 83.33333%; } - - .small-11 { - width: 91.66667%; } - - .small-12 { - width: 100%; } - - [class*="column"] + [class*="column"]:last-child { - float: right; } - - [class*="column"] + [class*="column"].end { - float: left; } - - .small-offset-0 { - margin-left: 0% !important; } - - .small-offset-1 { - margin-left: 8.33333% !important; } - - .small-offset-2 { - margin-left: 16.66667% !important; } - - .small-offset-3 { - margin-left: 25% !important; } - - .small-offset-4 { - margin-left: 33.33333% !important; } - - .small-offset-5 { - margin-left: 41.66667% !important; } - - .small-offset-6 { - margin-left: 50% !important; } - - .small-offset-7 { - margin-left: 58.33333% !important; } - - .small-offset-8 { - margin-left: 66.66667% !important; } - - .small-offset-9 { - margin-left: 75% !important; } - - .small-offset-10 { - margin-left: 83.33333% !important; } - - .small-offset-11 { - margin-left: 91.66667% !important; } - - .small-reset-order, - .small-reset-order { - margin-left: 0; - margin-right: 0; - left: auto; - right: auto; - float: left; } } -@media only screen and (min-width: 40.063em) { - .column.medium-centered, - .columns.medium-centered { - margin-left: auto; - margin-right: auto; - float: none; } - - .column.medium-uncentered, - .columns.medium-uncentered { - margin-left: 0; - margin-right: 0; - float: left; } - - .column.medium-uncentered.opposite, - .columns.medium-uncentered.opposite { - float: right; } - - .medium-push-0 { - left: 0%; - right: auto; } - - .medium-pull-0 { - right: 0%; - left: auto; } - - .medium-push-1 { - left: 8.33333%; - right: auto; } - - .medium-pull-1 { - right: 8.33333%; - left: auto; } - - .medium-push-2 { - left: 16.66667%; - right: auto; } - - .medium-pull-2 { - right: 16.66667%; - left: auto; } - - .medium-push-3 { - left: 25%; - right: auto; } - - .medium-pull-3 { - right: 25%; - left: auto; } - - .medium-push-4 { - left: 33.33333%; - right: auto; } - - .medium-pull-4 { - right: 33.33333%; - left: auto; } - - .medium-push-5 { - left: 41.66667%; - right: auto; } - - .medium-pull-5 { - right: 41.66667%; - left: auto; } - - .medium-push-6 { - left: 50%; - right: auto; } - - .medium-pull-6 { - right: 50%; - left: auto; } - - .medium-push-7 { - left: 58.33333%; - right: auto; } - - .medium-pull-7 { - right: 58.33333%; - left: auto; } - - .medium-push-8 { - left: 66.66667%; - right: auto; } - - .medium-pull-8 { - right: 66.66667%; - left: auto; } - - .medium-push-9 { - left: 75%; - right: auto; } - - .medium-pull-9 { - right: 75%; - left: auto; } - - .medium-push-10 { - left: 83.33333%; - right: auto; } - - .medium-pull-10 { - right: 83.33333%; - left: auto; } - - .medium-push-11 { - left: 91.66667%; - right: auto; } - - .medium-pull-11 { - right: 91.66667%; - left: auto; } - - .column, - .columns { - position: relative; - padding-left: 0.9375em; - padding-right: 0.9375em; - float: left; } - - .medium-1 { - width: 8.33333%; } - - .medium-2 { - width: 16.66667%; } - - .medium-3 { - width: 25%; } - - .medium-4 { - width: 33.33333%; } - - .medium-5 { - width: 41.66667%; } - - .medium-6 { - width: 50%; } - - .medium-7 { - width: 58.33333%; } - - .medium-8 { - width: 66.66667%; } - - .medium-9 { - width: 75%; } - - .medium-10 { - width: 83.33333%; } - - .medium-11 { - width: 91.66667%; } - - .medium-12 { - width: 100%; } - - [class*="column"] + [class*="column"]:last-child { - float: right; } - - [class*="column"] + [class*="column"].end { - float: left; } - - .medium-offset-0 { - margin-left: 0% !important; } - - .medium-offset-1 { - margin-left: 8.33333% !important; } - - .medium-offset-2 { - margin-left: 16.66667% !important; } - - .medium-offset-3 { - margin-left: 25% !important; } - - .medium-offset-4 { - margin-left: 33.33333% !important; } - - .medium-offset-5 { - margin-left: 41.66667% !important; } - - .medium-offset-6 { - margin-left: 50% !important; } - - .medium-offset-7 { - margin-left: 58.33333% !important; } - - .medium-offset-8 { - margin-left: 66.66667% !important; } - - .medium-offset-9 { - margin-left: 75% !important; } - - .medium-offset-10 { - margin-left: 83.33333% !important; } - - .medium-offset-11 { - margin-left: 91.66667% !important; } - - .medium-reset-order, - .medium-reset-order { - margin-left: 0; - margin-right: 0; - left: auto; - right: auto; - float: left; } - - .push-0 { - left: 0%; - right: auto; } - - .pull-0 { - right: 0%; - left: auto; } - - .push-1 { - left: 8.33333%; - right: auto; } - - .pull-1 { - right: 8.33333%; - left: auto; } - - .push-2 { - left: 16.66667%; - right: auto; } - - .pull-2 { - right: 16.66667%; - left: auto; } - - .push-3 { - left: 25%; - right: auto; } - - .pull-3 { - right: 25%; - left: auto; } - - .push-4 { - left: 33.33333%; - right: auto; } - - .pull-4 { - right: 33.33333%; - left: auto; } - - .push-5 { - left: 41.66667%; - right: auto; } - - .pull-5 { - right: 41.66667%; - left: auto; } - - .push-6 { - left: 50%; - right: auto; } - - .pull-6 { - right: 50%; - left: auto; } - - .push-7 { - left: 58.33333%; - right: auto; } - - .pull-7 { - right: 58.33333%; - left: auto; } - - .push-8 { - left: 66.66667%; - right: auto; } - - .pull-8 { - right: 66.66667%; - left: auto; } - - .push-9 { - left: 75%; - right: auto; } - - .pull-9 { - right: 75%; - left: auto; } - - .push-10 { - left: 83.33333%; - right: auto; } - - .pull-10 { - right: 83.33333%; - left: auto; } - - .push-11 { - left: 91.66667%; - right: auto; } - - .pull-11 { - right: 91.66667%; - left: auto; } } -@media only screen and (min-width: 64.063em) { - .column.large-centered, - .columns.large-centered { - margin-left: auto; - margin-right: auto; - float: none; } - - .column.large-uncentered, - .columns.large-uncentered { - margin-left: 0; - margin-right: 0; - float: left; } - - .column.large-uncentered.opposite, - .columns.large-uncentered.opposite { - float: right; } - - .large-push-0 { - left: 0%; - right: auto; } - - .large-pull-0 { - right: 0%; - left: auto; } - - .large-push-1 { - left: 8.33333%; - right: auto; } - - .large-pull-1 { - right: 8.33333%; - left: auto; } - - .large-push-2 { - left: 16.66667%; - right: auto; } - - .large-pull-2 { - right: 16.66667%; - left: auto; } - - .large-push-3 { - left: 25%; - right: auto; } - - .large-pull-3 { - right: 25%; - left: auto; } - - .large-push-4 { - left: 33.33333%; - right: auto; } - - .large-pull-4 { - right: 33.33333%; - left: auto; } - - .large-push-5 { - left: 41.66667%; - right: auto; } - - .large-pull-5 { - right: 41.66667%; - left: auto; } - - .large-push-6 { - left: 50%; - right: auto; } - - .large-pull-6 { - right: 50%; - left: auto; } - - .large-push-7 { - left: 58.33333%; - right: auto; } - - .large-pull-7 { - right: 58.33333%; - left: auto; } - - .large-push-8 { - left: 66.66667%; - right: auto; } - - .large-pull-8 { - right: 66.66667%; - left: auto; } - - .large-push-9 { - left: 75%; - right: auto; } - - .large-pull-9 { - right: 75%; - left: auto; } - - .large-push-10 { - left: 83.33333%; - right: auto; } - - .large-pull-10 { - right: 83.33333%; - left: auto; } - - .large-push-11 { - left: 91.66667%; - right: auto; } - - .large-pull-11 { - right: 91.66667%; - left: auto; } - - .column, - .columns { - position: relative; - padding-left: 0.9375em; - padding-right: 0.9375em; - float: left; } - - .large-1 { - width: 8.33333%; } - - .large-2 { - width: 16.66667%; } - - .large-3 { - width: 25%; } - - .large-4 { - width: 33.33333%; } - - .large-5 { - width: 41.66667%; } - - .large-6 { - width: 50%; } - - .large-7 { - width: 58.33333%; } - - .large-8 { - width: 66.66667%; } - - .large-9 { - width: 75%; } - - .large-10 { - width: 83.33333%; } - - .large-11 { - width: 91.66667%; } - - .large-12 { - width: 100%; } - - [class*="column"] + [class*="column"]:last-child { - float: right; } - - [class*="column"] + [class*="column"].end { - float: left; } - - .large-offset-0 { - margin-left: 0% !important; } - - .large-offset-1 { - margin-left: 8.33333% !important; } - - .large-offset-2 { - margin-left: 16.66667% !important; } - - .large-offset-3 { - margin-left: 25% !important; } - - .large-offset-4 { - margin-left: 33.33333% !important; } - - .large-offset-5 { - margin-left: 41.66667% !important; } - - .large-offset-6 { - margin-left: 50% !important; } - - .large-offset-7 { - margin-left: 58.33333% !important; } - - .large-offset-8 { - margin-left: 66.66667% !important; } - - .large-offset-9 { - margin-left: 75% !important; } - - .large-offset-10 { - margin-left: 83.33333% !important; } - - .large-offset-11 { - margin-left: 91.66667% !important; } - - .large-reset-order, - .large-reset-order { - margin-left: 0; - margin-right: 0; - left: auto; - right: auto; - float: left; } - - .push-0 { - left: 0%; - right: auto; } - - .pull-0 { - right: 0%; - left: auto; } - - .push-1 { - left: 8.33333%; - right: auto; } - - .pull-1 { - right: 8.33333%; - left: auto; } - - .push-2 { - left: 16.66667%; - right: auto; } - - .pull-2 { - right: 16.66667%; - left: auto; } - - .push-3 { - left: 25%; - right: auto; } - - .pull-3 { - right: 25%; - left: auto; } - - .push-4 { - left: 33.33333%; - right: auto; } - - .pull-4 { - right: 33.33333%; - left: auto; } - - .push-5 { - left: 41.66667%; - right: auto; } - - .pull-5 { - right: 41.66667%; - left: auto; } - - .push-6 { - left: 50%; - right: auto; } - - .pull-6 { - right: 50%; - left: auto; } - - .push-7 { - left: 58.33333%; - right: auto; } - - .pull-7 { - right: 58.33333%; - left: auto; } - - .push-8 { - left: 66.66667%; - right: auto; } - - .pull-8 { - right: 66.66667%; - left: auto; } - - .push-9 { - left: 75%; - right: auto; } - - .pull-9 { - right: 75%; - left: auto; } - - .push-10 { - left: 83.33333%; - right: auto; } - - .pull-10 { - right: 83.33333%; - left: auto; } - - .push-11 { - left: 91.66667%; - right: auto; } - - .pull-11 { - right: 91.66667%; - left: auto; } } -meta.foundation-mq-topbar { - font-family: "/only screen and (min-width:40.063em)/"; - width: 58.75em; } - -/* Wrapped around .top-bar to contain to grid width */ -.contain-to-grid { - width: 100%; - background: #333333; } - .contain-to-grid .top-bar { - margin-bottom: 0; } - -.fixed { - width: 100%; - left: 0; - position: fixed; - top: 0; - z-index: 99; } - .fixed.expanded:not(.top-bar) { - overflow-y: auto; - height: auto; - width: 100%; - max-height: 100%; } - .fixed.expanded:not(.top-bar) .title-area { - position: fixed; - width: 100%; - z-index: 99; } - .fixed.expanded:not(.top-bar) .top-bar-section { - z-index: 98; - margin-top: 45px; } - -.top-bar { - overflow: hidden; - height: 45px; - line-height: 45px; - position: relative; - background: #333333; - margin-bottom: 0; } - .top-bar ul { - margin-bottom: 0; - list-style: none; } - .top-bar .row { - max-width: none; } - .top-bar form, - .top-bar input { - margin-bottom: 0; } - .top-bar input { - height: auto; - padding-top: .35rem; - padding-bottom: .35rem; - font-size: 0.75rem; } - .top-bar .button { - padding-top: .45rem; - padding-bottom: .35rem; - margin-bottom: 0; - font-size: 0.75rem; } - .top-bar .title-area { - position: relative; - margin: 0; } - .top-bar .name { - height: 45px; - margin: 0; - font-size: 16px; } - .top-bar .name h1 { - line-height: 45px; - font-size: 1.0625rem; - margin: 0; } - .top-bar .name h1 a { - font-weight: normal; - color: white; - width: 50%; - display: block; - padding: 0 15px; } - .top-bar .toggle-topbar { - position: absolute; - right: 0; - top: 0; } - .top-bar .toggle-topbar a { - color: white; - text-transform: uppercase; - font-size: 0.8125rem; - font-weight: bold; - position: relative; - display: block; - padding: 0 15px; - height: 45px; - line-height: 45px; } - .top-bar .toggle-topbar.menu-icon { - right: 15px; - top: 50%; - margin-top: -16px; - padding-left: 40px; } - .top-bar .toggle-topbar.menu-icon a { - height: 34px; - line-height: 33px; - padding: 0; - padding-right: 25px; - color: white; - position: relative; } - .top-bar .toggle-topbar.menu-icon a::after { - content: ""; - position: absolute; - right: 0; - display: block; - width: 16px; - top: 0; - height: 0; - -webkit-box-shadow: 0 10px 0 1px white, 0 16px 0 1px white, 0 22px 0 1px white; - box-shadow: 0 10px 0 1px white, 0 16px 0 1px white, 0 22px 0 1px white; } - .top-bar.expanded { - height: auto; - background: transparent; } - .top-bar.expanded .title-area { - background: #333333; } - .top-bar.expanded .toggle-topbar a { - color: #888888; } - .top-bar.expanded .toggle-topbar a span { - -webkit-box-shadow: 0 10px 0 1px #888888, 0 16px 0 1px #888888, 0 22px 0 1px #888888; - box-shadow: 0 10px 0 1px #888888, 0 16px 0 1px #888888, 0 22px 0 1px #888888; } - -.top-bar-section { - left: 0; - position: relative; - width: auto; - -webkit-transition: left 300ms ease-out; - -moz-transition: left 300ms ease-out; - transition: left 300ms ease-out; } - .top-bar-section ul { - width: 100%; - height: auto; - display: block; - background: #333333; - font-size: 16px; - margin: 0; } - .top-bar-section .divider, - .top-bar-section [role="separator"] { - border-top: solid 1px #1a1a1a; - clear: both; - height: 1px; - width: 100%; } - .top-bar-section ul li > a { - display: block; - width: 100%; - color: white; - padding: 12px 0 12px 0; - padding-left: 15px; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-size: 0.8125rem; - font-weight: normal; - background: #333333; } - .top-bar-section ul li > a.button { - background: #0086a9; - font-size: 0.8125rem; - padding-right: 15px; - padding-left: 15px; } - .top-bar-section ul li > a.button:hover { - background: #00627b; } - .top-bar-section ul li > a.button.secondary { - background: #ff6600; } - .top-bar-section ul li > a.button.secondary:hover { - background: #e35b00; } - .top-bar-section ul li > a.button.success { - background: #20ba44; } - .top-bar-section ul li > a.button.success:hover { - background: #199336; } - .top-bar-section ul li > a.button.alert { - background: #c60f13; } - .top-bar-section ul li > a.button.alert:hover { - background: #a20c10; } - .top-bar-section ul li:hover > a { - background: #272727; - color: white; } - .top-bar-section ul li.active > a { - background: #0086a9; - color: white; } - .top-bar-section ul li.active > a:hover { - background: #007391; - color: white; } - .top-bar-section .has-form { - padding: 15px; } - .top-bar-section .has-dropdown { - position: relative; } - .top-bar-section .has-dropdown > a:after { - content: ""; - display: block; - width: 0; - height: 0; - border: inset 5px; - border-color: transparent transparent transparent rgba(255, 255, 255, 0.4); - border-left-style: solid; - margin-right: 15px; - margin-top: -4.5px; - position: absolute; - top: 50%; - right: 0; } - .top-bar-section .has-dropdown.moved { - position: static; } - .top-bar-section .has-dropdown.moved > .dropdown { - display: block; } - .top-bar-section .dropdown { - position: absolute; - left: 100%; - top: 0; - display: none; - z-index: 99; } - .top-bar-section .dropdown li { - width: 100%; - height: auto; } - .top-bar-section .dropdown li a { - font-weight: normal; - padding: 8px 15px; } - .top-bar-section .dropdown li a.parent-link { - font-weight: normal; } - .top-bar-section .dropdown li.title h5 { - margin-bottom: 0; } - .top-bar-section .dropdown li.title h5 a { - color: white; - line-height: 22.5px; - display: block; } - .top-bar-section .dropdown li.has-form { - padding: 8px 15px; } - .top-bar-section .dropdown li .button { - top: auto; } - .top-bar-section .dropdown label { - padding: 8px 15px 2px; - margin-bottom: 0; - text-transform: uppercase; - color: #777777; - font-weight: bold; - font-size: 0.625rem; } - -.js-generated { - display: block; } - -@media only screen and (min-width: 40.063em) { - .top-bar { - background: #333333; - *zoom: 1; - overflow: visible; } - .top-bar:before, .top-bar:after { - content: " "; - display: table; } - .top-bar:after { - clear: both; } - .top-bar .toggle-topbar { - display: none; } - .top-bar .title-area { - float: left; } - .top-bar .name h1 a { - width: auto; } - .top-bar input, - .top-bar .button { - font-size: 0.875rem; - position: relative; - top: 7px; } - .top-bar.expanded { - background: #333333; } - - .contain-to-grid .top-bar { - max-width: 62.5em; - margin: 0 auto; - margin-bottom: 0; } - - .top-bar-section { - -webkit-transition: none 0 0; - -moz-transition: none 0 0; - transition: none 0 0; - left: 0 !important; } - .top-bar-section ul { - width: auto; - height: auto !important; - display: inline; } - .top-bar-section ul li { - float: left; } - .top-bar-section ul li .js-generated { - display: none; } - .top-bar-section li.hover > a:not(.button) { - background: #272727; - color: white; } - .top-bar-section li:not(.has-form) a:not(.button) { - padding: 0 15px; - line-height: 45px; - background: #333333; } - .top-bar-section li:not(.has-form) a:not(.button):hover { - background: #272727; } - .top-bar-section li.active:not(.has-form) a:not(.button) { - padding: 0 15px; - line-height: 45px; - color: white; - background: #0086a9; } - .top-bar-section li.active:not(.has-form) a:not(.button):hover { - background: #007391; } - .top-bar-section .has-dropdown > a { - padding-right: 35px !important; } - .top-bar-section .has-dropdown > a:after { - content: ""; - display: block; - width: 0; - height: 0; - border: inset 5px; - border-color: rgba(255, 255, 255, 0.4) transparent transparent transparent; - border-top-style: solid; - margin-top: -2.5px; - top: 22.5px; } - .top-bar-section .has-dropdown.moved { - position: relative; } - .top-bar-section .has-dropdown.moved > .dropdown { - display: none; } - .top-bar-section .has-dropdown.hover > .dropdown, .top-bar-section .has-dropdown.not-click:hover > .dropdown { - display: block; } - .top-bar-section .has-dropdown .dropdown li.has-dropdown > a:after { - border: none; - content: "\00bb"; - top: 1rem; - margin-top: -2px; - right: 5px; - line-height: 1.2; } - .top-bar-section .dropdown { - left: 0; - top: auto; - background: transparent; - min-width: 100%; } - .top-bar-section .dropdown li a { - color: white; - line-height: 1; - white-space: nowrap; - padding: 12px 15px; - background: #333333; } - .top-bar-section .dropdown li label { - white-space: nowrap; - background: #333333; } - .top-bar-section .dropdown li .dropdown { - left: 100%; - top: 0; } - .top-bar-section > ul > .divider, .top-bar-section > ul > [role="separator"] { - border-bottom: none; - border-top: none; - border-right: solid 1px #4e4e4e; - clear: none; - height: 45px; - width: 0; } - .top-bar-section .has-form { - background: #333333; - padding: 0 15px; - height: 45px; } - .top-bar-section .right li .dropdown { - left: auto; - right: 0; } - .top-bar-section .right li .dropdown li .dropdown { - right: 100%; } - .top-bar-section .left li .dropdown { - right: auto; - left: 0; } - .top-bar-section .left li .dropdown li .dropdown { - left: 100%; } - - .no-js .top-bar-section ul li:hover > a { - background: #272727; - color: white; } - .no-js .top-bar-section ul li:active > a { - background: #0086a9; - color: white; } - .no-js .top-bar-section .has-dropdown:hover > .dropdown { - display: block; } } -.breadcrumbs { - display: block; - padding: 0.5625rem 0.875rem 0.5625rem; - overflow: hidden; - margin-left: 0; - list-style: none; - border-style: solid; - border-width: 1px; - background-color: #ffba8c; - border-color: #ffa265; - -webkit-border-radius: 3px; - border-radius: 3px; } - .breadcrumbs > * { - margin: 0; - float: left; - font-size: 0.6875rem; - text-transform: uppercase; } - .breadcrumbs > *:hover a, .breadcrumbs > *:focus a { - text-decoration: underline; } - .breadcrumbs > * a, - .breadcrumbs > * span { - text-transform: uppercase; - color: #0086a9; } - .breadcrumbs > *.current { - cursor: default; - color: #333333; } - .breadcrumbs > *.current a { - cursor: default; - color: #333333; } - .breadcrumbs > *.current:hover, .breadcrumbs > *.current:hover a, .breadcrumbs > *.current:focus, .breadcrumbs > *.current:focus a { - text-decoration: none; } - .breadcrumbs > *.unavailable { - color: #999999; } - .breadcrumbs > *.unavailable a { - color: #999999; } - .breadcrumbs > *.unavailable:hover, .breadcrumbs > *.unavailable:hover a, .breadcrumbs > *.unavailable:focus, - .breadcrumbs > *.unavailable a:focus { - text-decoration: none; - color: #999999; - cursor: default; } - .breadcrumbs > *:before { - content: "/"; - color: #aaaaaa; - margin: 0 0.75rem; - position: relative; - top: 1px; } - .breadcrumbs > *:first-child:before { - content: " "; - margin: 0; } - -.alert-box { - border-style: solid; - border-width: 1px; - display: block; - font-weight: normal; - margin-bottom: 1.25rem; - position: relative; - padding: 0.875rem 1.5rem 0.875rem 0.875rem; - font-size: 0.8125rem; - background-color: #0086a9; - border-color: #007391; - color: white; } - .alert-box .close { - font-size: 1.375rem; - padding: 9px 6px 4px; - line-height: 0; - position: absolute; - top: 50%; - margin-top: -0.6875rem; - right: 0.25rem; - color: #333333; - opacity: 0.3; } - .alert-box .close:hover, .alert-box .close:focus { - opacity: 0.5; } - .alert-box.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - .alert-box.round { - -webkit-border-radius: 1000px; - border-radius: 1000px; } - .alert-box.success { - background-color: #20ba44; - border-color: #1ca03a; - color: white; } - .alert-box.alert { - background-color: #c60f13; - border-color: #aa0d10; - color: white; } - .alert-box.secondary { - background-color: #ff6600; - border-color: #db5800; - color: white; } - .alert-box.warning { - background-color: #f08a24; - border-color: #de770f; - color: white; } - .alert-box.info { - background-color: #a0d3e8; - border-color: #74bfdd; - color: #572300; } - -.inline-list { - margin: 0 auto 1.0625rem auto; - margin-left: -1.375rem; - margin-right: 0; - padding: 0; - list-style: none; - overflow: hidden; } - .inline-list > li { - list-style: none; - float: left; - margin-left: 1.375rem; - display: block; } - .inline-list > li > * { - display: block; } - -button, .button { - border-style: solid; - border-width: 0px; - cursor: pointer; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-weight: normal; - line-height: normal; - margin: 0 0 1.25rem; - position: relative; - text-decoration: none; - text-align: center; - display: inline-block; - padding-top: 1rem; - padding-right: 2rem; - padding-bottom: 1.0625rem; - padding-left: 2rem; - font-size: 1rem; - /* @else { font-size: $padding - rem-calc(2); } */ - background-color: #0086a9; - border-color: #006b87; - color: white; - -webkit-transition: background-color 300ms ease-out; - -moz-transition: background-color 300ms ease-out; - transition: background-color 300ms ease-out; - padding-top: 1.0625rem; - padding-bottom: 1rem; - -webkit-appearance: none; - border: none; - font-weight: normal !important; } - button:hover, button:focus, .button:hover, .button:focus { - background-color: #006b87; } - button:hover, button:focus, .button:hover, .button:focus { - color: white; } - button.secondary, .button.secondary { - background-color: #ff6600; - border-color: #cc5200; - color: white; } - button.secondary:hover, button.secondary:focus, .button.secondary:hover, .button.secondary:focus { - background-color: #cc5200; } - button.secondary:hover, button.secondary:focus, .button.secondary:hover, .button.secondary:focus { - color: white; } - button.success, .button.success { - background-color: #20ba44; - border-color: #1a9536; - color: white; } - button.success:hover, button.success:focus, .button.success:hover, .button.success:focus { - background-color: #1a9536; } - button.success:hover, button.success:focus, .button.success:hover, .button.success:focus { - color: white; } - button.alert, .button.alert { - background-color: #c60f13; - border-color: #9e0c0f; - color: white; } - button.alert:hover, button.alert:focus, .button.alert:hover, .button.alert:focus { - background-color: #9e0c0f; } - button.alert:hover, button.alert:focus, .button.alert:hover, .button.alert:focus { - color: white; } - button.large, .button.large { - padding-top: 1.125rem; - padding-right: 2.25rem; - padding-bottom: 1.1875rem; - padding-left: 2.25rem; - font-size: 1.25rem; - /* @else { font-size: $padding - rem-calc(2); } */ } - button.small, .button.small { - padding-top: 0.875rem; - padding-right: 1.75rem; - padding-bottom: 0.9375rem; - padding-left: 1.75rem; - font-size: 0.8125rem; - /* @else { font-size: $padding - rem-calc(2); } */ } - button.tiny, .button.tiny { - padding-top: 0.625rem; - padding-right: 1.25rem; - padding-bottom: 0.6875rem; - padding-left: 1.25rem; - font-size: 0.6875rem; - /* @else { font-size: $padding - rem-calc(2); } */ } - button.expand, .button.expand { - padding-right: 0; - padding-left: 0; - width: 100%; } - button.left-align, .button.left-align { - text-align: left; - text-indent: 0.75rem; } - button.right-align, .button.right-align { - text-align: right; - padding-right: 0.75rem; } - button.radius, .button.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - button.round, .button.round { - -webkit-border-radius: 1000px; - border-radius: 1000px; } - button.disabled, button[disabled], .button.disabled, .button[disabled] { - background-color: #0086a9; - border-color: #006b87; - color: white; - cursor: default; - opacity: 0.7; - -webkit-box-shadow: none; - box-shadow: none; } - button.disabled:hover, button.disabled:focus, button[disabled]:hover, button[disabled]:focus, .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus { - background-color: #006b87; } - button.disabled:hover, button.disabled:focus, button[disabled]:hover, button[disabled]:focus, .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus { - color: white; } - button.disabled:hover, button.disabled:focus, button[disabled]:hover, button[disabled]:focus, .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus { - background-color: #0086a9; } - button.disabled.secondary, button[disabled].secondary, .button.disabled.secondary, .button[disabled].secondary { - background-color: #ff6600; - border-color: #cc5200; - color: white; - cursor: default; - opacity: 0.7; - -webkit-box-shadow: none; - box-shadow: none; } - button.disabled.secondary:hover, button.disabled.secondary:focus, button[disabled].secondary:hover, button[disabled].secondary:focus, .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus { - background-color: #cc5200; } - button.disabled.secondary:hover, button.disabled.secondary:focus, button[disabled].secondary:hover, button[disabled].secondary:focus, .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus { - color: white; } - button.disabled.secondary:hover, button.disabled.secondary:focus, button[disabled].secondary:hover, button[disabled].secondary:focus, .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus { - background-color: #ff6600; } - button.disabled.success, button[disabled].success, .button.disabled.success, .button[disabled].success { - background-color: #20ba44; - border-color: #1a9536; - color: white; - cursor: default; - opacity: 0.7; - -webkit-box-shadow: none; - box-shadow: none; } - button.disabled.success:hover, button.disabled.success:focus, button[disabled].success:hover, button[disabled].success:focus, .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus { - background-color: #1a9536; } - button.disabled.success:hover, button.disabled.success:focus, button[disabled].success:hover, button[disabled].success:focus, .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus { - color: white; } - button.disabled.success:hover, button.disabled.success:focus, button[disabled].success:hover, button[disabled].success:focus, .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus { - background-color: #20ba44; } - button.disabled.alert, button[disabled].alert, .button.disabled.alert, .button[disabled].alert { - background-color: #c60f13; - border-color: #9e0c0f; - color: white; - cursor: default; - opacity: 0.7; - -webkit-box-shadow: none; - box-shadow: none; } - button.disabled.alert:hover, button.disabled.alert:focus, button[disabled].alert:hover, button[disabled].alert:focus, .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus { - background-color: #9e0c0f; } - button.disabled.alert:hover, button.disabled.alert:focus, button[disabled].alert:hover, button[disabled].alert:focus, .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus { - color: white; } - button.disabled.alert:hover, button.disabled.alert:focus, button[disabled].alert:hover, button[disabled].alert:focus, .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus { - background-color: #c60f13; } - -@media only screen and (min-width: 40.063em) { - button, .button { - display: inline-block; } } -.button-group { - list-style: none; - margin: 0; - left: 0; - *zoom: 1; } - .button-group:before, .button-group:after { - content: " "; - display: table; } - .button-group:after { - clear: both; } - .button-group li { - margin: 0; - float: left; } - .button-group li > button, .button-group li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group li:first-child button, .button-group li:first-child .button { - border-left: 0; } - .button-group li:first-child { - margin-left: 0; } - .button-group.radius > * > button, .button-group.radius > * .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.radius > *:first-child button, .button-group.radius > *:first-child .button { - border-left: 0; } - .button-group.radius > *:first-child, .button-group.radius > *:first-child > a, .button-group.radius > *:first-child > button, .button-group.radius > *:first-child > .button { - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; - -webkit-border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; } - .button-group.radius > *:last-child, .button-group.radius > *:last-child > a, .button-group.radius > *:last-child > button, .button-group.radius > *:last-child > .button { - -moz-border-radius-bottomright: 3px; - -moz-border-radius-topright: 3px; - -webkit-border-bottom-right-radius: 3px; - -webkit-border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; } - .button-group.round > * > button, .button-group.round > * .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.round > *:first-child button, .button-group.round > *:first-child .button { - border-left: 0; } - .button-group.round > *:first-child, .button-group.round > *:first-child > a, .button-group.round > *:first-child > button, .button-group.round > *:first-child > .button { - -moz-border-radius-bottomleft: 1000px; - -moz-border-radius-topleft: 1000px; - -webkit-border-bottom-left-radius: 1000px; - -webkit-border-top-left-radius: 1000px; - border-bottom-left-radius: 1000px; - border-top-left-radius: 1000px; } - .button-group.round > *:last-child, .button-group.round > *:last-child > a, .button-group.round > *:last-child > button, .button-group.round > *:last-child > .button { - -moz-border-radius-bottomright: 1000px; - -moz-border-radius-topright: 1000px; - -webkit-border-bottom-right-radius: 1000px; - -webkit-border-top-right-radius: 1000px; - border-bottom-right-radius: 1000px; - border-top-right-radius: 1000px; } - .button-group.even-2 li { - width: 50%; } - .button-group.even-2 li > button, .button-group.even-2 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-2 li:first-child button, .button-group.even-2 li:first-child .button { - border-left: 0; } - .button-group.even-2 li button, .button-group.even-2 li .button { - width: 100%; } - .button-group.even-3 li { - width: 33.33333%; } - .button-group.even-3 li > button, .button-group.even-3 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-3 li:first-child button, .button-group.even-3 li:first-child .button { - border-left: 0; } - .button-group.even-3 li button, .button-group.even-3 li .button { - width: 100%; } - .button-group.even-4 li { - width: 25%; } - .button-group.even-4 li > button, .button-group.even-4 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-4 li:first-child button, .button-group.even-4 li:first-child .button { - border-left: 0; } - .button-group.even-4 li button, .button-group.even-4 li .button { - width: 100%; } - .button-group.even-5 li { - width: 20%; } - .button-group.even-5 li > button, .button-group.even-5 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-5 li:first-child button, .button-group.even-5 li:first-child .button { - border-left: 0; } - .button-group.even-5 li button, .button-group.even-5 li .button { - width: 100%; } - .button-group.even-6 li { - width: 16.66667%; } - .button-group.even-6 li > button, .button-group.even-6 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-6 li:first-child button, .button-group.even-6 li:first-child .button { - border-left: 0; } - .button-group.even-6 li button, .button-group.even-6 li .button { - width: 100%; } - .button-group.even-7 li { - width: 14.28571%; } - .button-group.even-7 li > button, .button-group.even-7 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-7 li:first-child button, .button-group.even-7 li:first-child .button { - border-left: 0; } - .button-group.even-7 li button, .button-group.even-7 li .button { - width: 100%; } - .button-group.even-8 li { - width: 12.5%; } - .button-group.even-8 li > button, .button-group.even-8 li .button { - border-left: 1px solid; - border-color: rgba(255, 255, 255, 0.5); } - .button-group.even-8 li:first-child button, .button-group.even-8 li:first-child .button { - border-left: 0; } - .button-group.even-8 li button, .button-group.even-8 li .button { - width: 100%; } - -.button-bar { - *zoom: 1; } - .button-bar:before, .button-bar:after { - content: " "; - display: table; } - .button-bar:after { - clear: both; } - .button-bar .button-group { - float: left; - margin-right: 0.625rem; } - .button-bar .button-group div { - overflow: hidden; } - -/* Panels */ -.panel { - border-style: solid; - border-width: 1px; - border-color: #d8d8d8; - margin-bottom: 1.25rem; - padding: 1.25rem; - background: #f2f2f2; } - .panel > :first-child { - margin-top: 0; } - .panel > :last-child { - margin-bottom: 0; } - .panel h1, .panel h2, .panel h3, .panel h4, .panel h5, .panel h6, .panel p { - color: #333333; } - .panel h1, .panel h2, .panel h3, .panel h4, .panel h5, .panel h6 { - line-height: 1; - margin-bottom: 0.625rem; } - .panel h1.subheader, .panel h2.subheader, .panel h3.subheader, .panel h4.subheader, .panel h5.subheader, .panel h6.subheader { - line-height: 1.4; } - .panel.callout { - border-style: solid; - border-width: 1px; - border-color: #b5f0ff; - margin-bottom: 1.25rem; - padding: 1.25rem; - background: #ebfbff; } - .panel.callout > :first-child { - margin-top: 0; } - .panel.callout > :last-child { - margin-bottom: 0; } - .panel.callout h1, .panel.callout h2, .panel.callout h3, .panel.callout h4, .panel.callout h5, .panel.callout h6, .panel.callout p { - color: #333333; } - .panel.callout h1, .panel.callout h2, .panel.callout h3, .panel.callout h4, .panel.callout h5, .panel.callout h6 { - line-height: 1; - margin-bottom: 0.625rem; } - .panel.callout h1.subheader, .panel.callout h2.subheader, .panel.callout h3.subheader, .panel.callout h4.subheader, .panel.callout h5.subheader, .panel.callout h6.subheader { - line-height: 1.4; } - .panel.callout a { - color: #0086a9; } - .panel.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - -.dropdown.button, button.dropdown { - position: relative; - padding-right: 3.5625rem; } - .dropdown.button:before, button.dropdown:before { - position: absolute; - content: ""; - width: 0; - height: 0; - display: block; - border-style: solid; - border-color: white transparent transparent transparent; - top: 50%; } - .dropdown.button:before, button.dropdown:before { - border-width: 0.375rem; - right: 1.40625rem; - margin-top: -0.15625rem; } - .dropdown.button:before, button.dropdown:before { - border-color: white transparent transparent transparent; } - .dropdown.button.tiny, button.dropdown.tiny { - padding-right: 2.625rem; } - .dropdown.button.tiny:before, button.dropdown.tiny:before { - border-width: 0.375rem; - right: 1.125rem; - margin-top: -0.125rem; } - .dropdown.button.tiny:before, button.dropdown.tiny:before { - border-color: white transparent transparent transparent; } - .dropdown.button.small, button.dropdown.small { - padding-right: 3.0625rem; } - .dropdown.button.small:before, button.dropdown.small:before { - border-width: 0.4375rem; - right: 1.3125rem; - margin-top: -0.15625rem; } - .dropdown.button.small:before, button.dropdown.small:before { - border-color: white transparent transparent transparent; } - .dropdown.button.large, button.dropdown.large { - padding-right: 3.625rem; } - .dropdown.button.large:before, button.dropdown.large:before { - border-width: 0.3125rem; - right: 1.71875rem; - margin-top: -0.15625rem; } - .dropdown.button.large:before, button.dropdown.large:before { - border-color: white transparent transparent transparent; } - .dropdown.button.secondary:before, button.dropdown.secondary:before { - border-color: #333333 transparent transparent transparent; } - -/* Image Thumbnails */ -.th { - line-height: 0; - display: inline-block; - border: solid 4px white; - max-width: 100%; - -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); - -webkit-transition: all 200ms ease-out; - -moz-transition: all 200ms ease-out; - transition: all 200ms ease-out; } - .th:hover, .th:focus { - -webkit-box-shadow: 0 0 6px 1px rgba(0, 134, 169, 0.5); - box-shadow: 0 0 6px 1px rgba(0, 134, 169, 0.5); } - .th.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - -/* Pricing Tables */ -.pricing-table { - border: solid 1px #dddddd; - margin-left: 0; - margin-bottom: 1.25rem; } - .pricing-table * { - list-style: none; - line-height: 1; } - .pricing-table .title { - background-color: #333333; - padding: 0.9375rem 1.25rem; - text-align: center; - color: #eeeeee; - font-weight: normal; - font-size: 1rem; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - .pricing-table .price { - background-color: #f6f6f6; - padding: 0.9375rem 1.25rem; - text-align: center; - color: #333333; - font-weight: normal; - font-size: 2rem; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - .pricing-table .description { - background-color: white; - padding: 0.9375rem; - text-align: center; - color: #777777; - font-size: 0.75rem; - font-weight: normal; - line-height: 1.4; - border-bottom: dotted 1px #dddddd; } - .pricing-table .bullet-item { - background-color: white; - padding: 0.9375rem; - text-align: center; - color: #333333; - font-size: 0.875rem; - font-weight: normal; - border-bottom: dotted 1px #dddddd; } - .pricing-table .cta-button { - background-color: white; - text-align: center; - padding: 1.25rem 1.25rem 0; } - -@-webkit-keyframes rotate { - from { - -webkit-transform: rotate(0deg); } - - to { - -webkit-transform: rotate(360deg); } } - -@-moz-keyframes rotate { - from { - -moz-transform: rotate(0deg); } - - to { - -moz-transform: rotate(360deg); } } - -@-o-keyframes rotate { - from { - -o-transform: rotate(0deg); } - - to { - -o-transform: rotate(360deg); } } - -@keyframes rotate { - from { - transform: rotate(0deg); } - - to { - transform: rotate(360deg); } } - -/* Orbit Graceful Loading */ -.slideshow-wrapper { - position: relative; } - .slideshow-wrapper ul { - list-style-type: none; - margin: 0; } - .slideshow-wrapper ul li, - .slideshow-wrapper ul li .orbit-caption { - display: none; } - .slideshow-wrapper ul li:first-child { - display: block; } - .slideshow-wrapper .orbit-container { - background-color: transparent; } - .slideshow-wrapper .orbit-container li { - display: block; } - .slideshow-wrapper .orbit-container li .orbit-caption { - display: block; } - -.preloader { - display: block; - width: 40px; - height: 40px; - position: absolute; - top: 50%; - left: 50%; - margin-top: -20px; - margin-left: -20px; - border: solid 3px; - border-color: #555555 white; - -webkit-border-radius: 1000px; - border-radius: 1000px; - -webkit-animation-name: rotate; - -webkit-animation-duration: 1.5s; - -webkit-animation-iteration-count: infinite; - -webkit-animation-timing-function: linear; - -moz-animation-name: rotate; - -moz-animation-duration: 1.5s; - -moz-animation-iteration-count: infinite; - -moz-animation-timing-function: linear; - -o-animation-name: rotate; - -o-animation-duration: 1.5s; - -o-animation-iteration-count: infinite; - -o-animation-timing-function: linear; - animation-name: rotate; - animation-duration: 1.5s; - animation-iteration-count: infinite; - animation-timing-function: linear; } - -.orbit-container { - overflow: hidden; - width: 100%; - position: relative; - background: none; } - .orbit-container .orbit-slides-container { - list-style: none; - margin: 0; - padding: 0; - position: relative; - -webkit-transform: translateZ(0); } - .orbit-container .orbit-slides-container img { - display: block; - max-width: 100%; } - .orbit-container .orbit-slides-container > * { - position: absolute; - top: 0; - width: 100%; - margin-left: 100%; } - .orbit-container .orbit-slides-container > *:first-child { - margin-left: 0%; } - .orbit-container .orbit-slides-container > * .orbit-caption { - position: absolute; - bottom: 0; - background-color: rgba(51, 51, 51, 0.8); - color: white; - width: 100%; - padding: 0.625rem 0.875rem; - font-size: 0.875rem; } - .orbit-container .orbit-slide-number { - position: absolute; - top: 10px; - left: 10px; - font-size: 12px; - color: white; - background: rgba(0, 0, 0, 0); - z-index: 10; } - .orbit-container .orbit-slide-number span { - font-weight: 700; - padding: 0.3125rem; } - .orbit-container .orbit-timer { - position: absolute; - top: 12px; - right: 10px; - height: 6px; - width: 100px; - z-index: 10; } - .orbit-container .orbit-timer .orbit-progress { - height: 3px; - background-color: rgba(255, 255, 255, 0.3); - display: block; - width: 0%; - position: relative; - right: 20px; - top: 5px; } - .orbit-container .orbit-timer > span { - display: none; - position: absolute; - top: 0px; - right: 0; - width: 11px; - height: 14px; - border: solid 4px white; - border-top: none; - border-bottom: none; } - .orbit-container .orbit-timer.paused > span { - right: -4px; - top: 0px; - width: 11px; - height: 14px; - border: inset 8px; - border-right-style: solid; - border-color: transparent transparent transparent white; } - .orbit-container .orbit-timer.paused > span.dark { - border-color: transparent transparent transparent #333333; } - .orbit-container:hover .orbit-timer > span { - display: block; } - .orbit-container .orbit-prev, - .orbit-container .orbit-next { - position: absolute; - top: 45%; - margin-top: -25px; - width: 36px; - height: 60px; - line-height: 50px; - color: white; - background-color: none; - text-indent: -9999px !important; - z-index: 10; } - .orbit-container .orbit-prev:hover, - .orbit-container .orbit-next:hover { - background-color: rgba(0, 0, 0, 0.3); } - .orbit-container .orbit-prev > span, - .orbit-container .orbit-next > span { - position: absolute; - top: 50%; - margin-top: -10px; - display: block; - width: 0; - height: 0; - border: inset 10px; } - .orbit-container .orbit-prev { - left: 0; } - .orbit-container .orbit-prev > span { - border-right-style: solid; - border-color: transparent; - border-right-color: white; } - .orbit-container .orbit-prev:hover > span { - border-right-color: white; } - .orbit-container .orbit-next { - right: 0; } - .orbit-container .orbit-next > span { - border-color: transparent; - border-left-style: solid; - border-left-color: white; - left: 50%; - margin-left: -4px; } - .orbit-container .orbit-next:hover > span { - border-left-color: white; } - -.orbit-bullets-container { - text-align: center; } - -.orbit-bullets { - margin: 0 auto 30px auto; - overflow: hidden; - position: relative; - top: 10px; - float: none; - text-align: center; - display: block; } - .orbit-bullets li { - display: inline-block; - width: 0.5625rem; - height: 0.5625rem; - background: #cccccc; - float: none; - margin-right: 6px; - -webkit-border-radius: 1000px; - border-radius: 1000px; } - .orbit-bullets li.active { - background: #999999; } - .orbit-bullets li:last-child { - margin-right: 0; } - -.touch .orbit-container .orbit-prev, -.touch .orbit-container .orbit-next { - display: none; } -.touch .orbit-bullets { - display: none; } - -@media only screen and (min-width: 40.063em) { - .touch .orbit-container .orbit-prev, - .touch .orbit-container .orbit-next { - display: inherit; } - .touch .orbit-bullets { - display: block; } } -@media only screen and (max-width: 40em) { - .orbit-stack-on-small .orbit-slides-container { - height: auto !important; } - .orbit-stack-on-small .orbit-slides-container > * { - position: relative; - margin-left: 0% !important; } - .orbit-stack-on-small .orbit-timer, - .orbit-stack-on-small .orbit-next, - .orbit-stack-on-small .orbit-prev, - .orbit-stack-on-small .orbit-bullets { - display: none; } } -[data-magellan-expedition] { - background: white; - z-index: 50; - min-width: 100%; - padding: 10px; } - [data-magellan-expedition] .sub-nav { - margin-bottom: 0; } - [data-magellan-expedition] .sub-nav dd { - margin-bottom: 0; } - [data-magellan-expedition] .sub-nav a { - line-height: 1.8em; } - -.tabs { - *zoom: 1; - margin-bottom: 0 !important; } - .tabs:before, .tabs:after { - content: " "; - display: table; } - .tabs:after { - clear: both; } - .tabs dd { - position: relative; - margin-bottom: 0 !important; - top: 1px; - float: left; } - .tabs dd > a { - display: block; - background: #efefef; - color: #222222; - padding-top: 1rem; - padding-right: 2rem; - padding-bottom: 1.0625rem; - padding-left: 2rem; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-size: 1rem; } - .tabs dd > a:hover { - background: #e1e1e1; } - .tabs dd.active a { - background: white; } - .tabs.radius dd:first-child a { - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; - -webkit-border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; } - .tabs.radius dd:last-child a { - -moz-border-radius-bottomright: 3px; - -moz-border-radius-topright: 3px; - -webkit-border-bottom-right-radius: 3px; - -webkit-border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; } - .tabs.vertical dd { - position: inherit; - float: none; - display: block; - top: auto; } - -.tabs-content { - *zoom: 1; - margin-bottom: 1.5rem; - width: 100%; } - .tabs-content:before, .tabs-content:after { - content: " "; - display: table; } - .tabs-content:after { - clear: both; } - .tabs-content > .content { - display: none; - float: left; - padding: 0.9375em 0; - width: 100%; } - .tabs-content > .content.active { - display: block; } - .tabs-content > .content.contained { - padding: 0.9375em; } - .tabs-content.vertical { - display: block; } - .tabs-content.vertical > .content { - padding: 0 0.9375em; } - -@media only screen and (min-width: 40.063em) { - .tabs.vertical { - width: 20%; - float: left; - margin-bottom: 1.25rem; } - - .tabs-content.vertical { - width: 80%; - float: left; - margin-left: -1px; } } -.side-nav { - display: block; - margin: 0; - padding: 0.875rem 0; - list-style-type: none; - list-style-position: inside; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - .side-nav li { - margin: 0 0 0.4375rem 0; - font-size: 0.875rem; } - .side-nav li a:not(.button) { - display: block; - color: #0086a9; } - .side-nav li a:not(.button):hover, .side-nav li a:not(.button):focus { - color: #10ceff; } - .side-nav li.active > a:first-child:not(.button) { - color: #10ceff; - font-weight: normal; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - .side-nav li.divider { - border-top: 1px solid; - height: 0; - padding: 0; - list-style: none; - border-top-color: white; } - -.accordion { - *zoom: 1; - margin-bottom: 0; } - .accordion:before, .accordion:after { - content: " "; - display: table; } - .accordion:after { - clear: both; } - .accordion dd { - display: block; - margin-bottom: 0 !important; } - .accordion dd.active a { - background: #e8e8e8; } - .accordion dd > a { - background: #efefef; - color: #222222; - padding: 1rem; - display: block; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-size: 1rem; } - .accordion dd > a:hover { - background: #e3e3e3; } - .accordion .content { - display: none; - padding: 0.9375em; } - .accordion .content.active { - display: block; - background: white; } - -.text-left { - text-align: left !important; } - -.text-right { - text-align: right !important; } - -.text-center { - text-align: center !important; } - -.text-justify { - text-align: justify !important; } - -@media only screen and (max-width: 40em) { - .small-only-text-left { - text-align: left !important; } - - .small-only-text-right { - text-align: right !important; } - - .small-only-text-center { - text-align: center !important; } - - .small-only-text-justify { - text-align: justify !important; } } -@media only screen { - .small-text-left { - text-align: left !important; } - - .small-text-right { - text-align: right !important; } - - .small-text-center { - text-align: center !important; } - - .small-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 40.063em) and (max-width: 64em) { - .medium-only-text-left { - text-align: left !important; } - - .medium-only-text-right { - text-align: right !important; } - - .medium-only-text-center { - text-align: center !important; } - - .medium-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 40.063em) { - .medium-text-left { - text-align: left !important; } - - .medium-text-right { - text-align: right !important; } - - .medium-text-center { - text-align: center !important; } - - .medium-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 64.063em) and (max-width: 90em) { - .large-only-text-left { - text-align: left !important; } - - .large-only-text-right { - text-align: right !important; } - - .large-only-text-center { - text-align: center !important; } - - .large-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 64.063em) { - .large-text-left { - text-align: left !important; } - - .large-text-right { - text-align: right !important; } - - .large-text-center { - text-align: center !important; } - - .large-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 90.063em) and (max-width: 120em) { - .xlarge-only-text-left { - text-align: left !important; } - - .xlarge-only-text-right { - text-align: right !important; } - - .xlarge-only-text-center { - text-align: center !important; } - - .xlarge-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 90.063em) { - .xlarge-text-left { - text-align: left !important; } - - .xlarge-text-right { - text-align: right !important; } - - .xlarge-text-center { - text-align: center !important; } - - .xlarge-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 120.063em) and (max-width: 99999999em) { - .xxlarge-only-text-left { - text-align: left !important; } - - .xxlarge-only-text-right { - text-align: right !important; } - - .xxlarge-only-text-center { - text-align: center !important; } - - .xxlarge-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 120.063em) { - .xxlarge-text-left { - text-align: left !important; } - - .xxlarge-text-right { - text-align: right !important; } - - .xxlarge-text-center { - text-align: center !important; } - - .xxlarge-text-justify { - text-align: justify !important; } } -/* Typography resets */ -div, -dl, -dt, -dd, -ul, -ol, -li, -h1, -h2, -h3, -h4, -h5, -h6, -pre, -form, -p, -blockquote, -th, -td { - margin: 0; - padding: 0; } - -/* Default Link Styles */ -a { - color: #0086a9; - text-decoration: none; - line-height: inherit; } - a:hover, a:focus { - color: #007391; } - a img { - border: none; } - -/* Default paragraph styles */ -p { - font-family: inherit; - font-weight: normal; - font-size: 1rem; - line-height: 1.6; - margin-bottom: 1.25rem; - text-rendering: optimizeLegibility; } - p.lead { - font-size: 1.21875rem; - line-height: 1.6; } - p aside { - font-size: 0.875rem; - line-height: 1.35; - font-style: italic; } - -/* Default header styles */ -h1, h2, h3, h4, h5, h6 { - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-weight: normal; - font-style: normal; - color: #222222; - text-rendering: optimizeLegibility; - margin-top: 0.2rem; - margin-bottom: 0.5rem; - line-height: 1.4; } - h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { - font-size: 60%; - color: #6f6f6f; - line-height: 0; } - -h1 { - font-size: 2.125rem; } - -h2 { - font-size: 1.6875rem; } - -h3 { - font-size: 1.375rem; } - -h4 { - font-size: 1.125rem; } - -h5 { - font-size: 1.125rem; } - -h6 { - font-size: 1rem; } - -.subheader { - line-height: 1.4; - color: #6f6f6f; - font-weight: normal; - margin-top: 0.2rem; - margin-bottom: 0.5rem; } - -hr { - border: solid #dddddd; - border-width: 1px 0 0; - clear: both; - margin: 1.25rem 0 1.1875rem; - height: 0; } - -/* Helpful Typography Defaults */ -em, -i { - font-style: italic; - line-height: inherit; } - -strong, -b { - font-weight: bold; - line-height: inherit; } - -small { - font-size: 60%; - line-height: inherit; } - -code { - font-family: Consolas, "Liberation Mono", Courier, monospace; - font-weight: bold; - color: #910b0e; } - -/* Lists */ -ul, -ol, -dl { - font-size: 1rem; - line-height: 1.6; - margin-bottom: 1.25rem; - list-style-position: outside; - font-family: inherit; } - -ul { - margin-left: 1.1rem; } - ul.no-bullet { - margin-left: 0; } - ul.no-bullet li ul, - ul.no-bullet li ol { - margin-left: 1.25rem; - margin-bottom: 0; - list-style: none; } - -/* Unordered Lists */ -ul li ul, -ul li ol { - margin-left: 1.25rem; - margin-bottom: 0; } -ul.square li ul, ul.circle li ul, ul.disc li ul { - list-style: inherit; } -ul.square { - list-style-type: square; - margin-left: 1.1rem; } -ul.circle { - list-style-type: circle; - margin-left: 1.1rem; } -ul.disc { - list-style-type: disc; - margin-left: 1.1rem; } -ul.no-bullet { - list-style: none; } - -/* Ordered Lists */ -ol { - margin-left: 1.4rem; } - ol li ul, - ol li ol { - margin-left: 1.25rem; - margin-bottom: 0; } - -/* Definition Lists */ -dl dt { - margin-bottom: 0.3rem; - font-weight: bold; } -dl dd { - margin-bottom: 0.75rem; } - -/* Abbreviations */ -abbr, -acronym { - text-transform: uppercase; - font-size: 90%; - color: #222222; - border-bottom: 1px dotted #dddddd; - cursor: help; } - -abbr { - text-transform: none; } - -/* Blockquotes */ -blockquote { - margin: 0 0 1.25rem; - padding: 0.5625rem 1.25rem 0 1.1875rem; - border-left: 1px solid #dddddd; } - blockquote cite { - display: block; - font-size: 0.8125rem; - color: #555555; } - blockquote cite:before { - content: "\2014 \0020"; } - blockquote cite a, - blockquote cite a:visited { - color: #555555; } - -blockquote, -blockquote p { - line-height: 1.6; - color: #6f6f6f; } - -/* Microformats */ -.vcard { - display: inline-block; - margin: 0 0 1.25rem 0; - border: 1px solid #dddddd; - padding: 0.625rem 0.75rem; } - .vcard li { - margin: 0; - display: block; } - .vcard .fn { - font-weight: bold; - font-size: 0.9375rem; } - -.vevent .summary { - font-weight: bold; } -.vevent abbr { - cursor: default; - text-decoration: none; - font-weight: bold; - border: none; - padding: 0 0.0625rem; } - -@media only screen and (min-width: 40.063em) { - h1, h2, h3, h4, h5, h6 { - line-height: 1.4; } - - h1 { - font-size: 2.75rem; } - - h2 { - font-size: 2.3125rem; } - - h3 { - font-size: 1.6875rem; } - - h4 { - font-size: 1.4375rem; } } -/* - * Print styles. - * - * Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/ - * Credit to Paul Irish and HTML5 Boilerplate (html5boilerplate.com) -*/ -.print-only { - display: none !important; } - -@media print { - * { - background: transparent !important; - color: black !important; - /* Black prints faster: h5bp.com/s */ - box-shadow: none !important; - text-shadow: none !important; } - - a, - a:visited { - text-decoration: underline; } - - a[href]:after { - content: " (" attr(href) ")"; } - - abbr[title]:after { - content: " (" attr(title) ")"; } - - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; } - - pre, - blockquote { - border: 1px solid #999999; - page-break-inside: avoid; } - - thead { - display: table-header-group; - /* h5bp.com/t */ } - - tr, - img { - page-break-inside: avoid; } - - img { - max-width: 100% !important; } - - @page { - margin: 0.5cm; } - - p, - h2, - h3 { - orphans: 3; - widows: 3; } - - h2, - h3 { - page-break-after: avoid; } - - .hide-on-print { - display: none !important; } - - .print-only { - display: block !important; } - - .hide-for-print { - display: none !important; } - - .show-for-print { - display: inherit !important; } } -.split.button { - position: relative; - padding-right: 5.0625rem; } - .split.button span { - display: block; - height: 100%; - position: absolute; - right: 0; - top: 0; - border-left: solid 1px; } - .split.button span:before { - position: absolute; - content: ""; - width: 0; - height: 0; - display: block; - border-style: inset; - top: 50%; - left: 50%; } - .split.button span:active { - background-color: rgba(0, 0, 0, 0.1); } - .split.button span { - border-left-color: rgba(255, 255, 255, 0.5); } - .split.button span { - width: 3.09375rem; } - .split.button span:before { - border-top-style: solid; - border-width: 0.375rem; - top: 48%; - margin-left: -0.375rem; } - .split.button span:before { - border-color: white transparent transparent transparent; } - .split.button.secondary span { - border-left-color: rgba(255, 255, 255, 0.5); } - .split.button.secondary span:before { - border-color: white transparent transparent transparent; } - .split.button.alert span { - border-left-color: rgba(255, 255, 255, 0.5); } - .split.button.success span { - border-left-color: rgba(255, 255, 255, 0.5); } - .split.button.tiny { - padding-right: 3.75rem; } - .split.button.tiny span { - width: 2.25rem; } - .split.button.tiny span:before { - border-top-style: solid; - border-width: 0.375rem; - top: 48%; - margin-left: -0.375rem; } - .split.button.small { - padding-right: 4.375rem; } - .split.button.small span { - width: 2.625rem; } - .split.button.small span:before { - border-top-style: solid; - border-width: 0.4375rem; - top: 48%; - margin-left: -0.375rem; } - .split.button.large { - padding-right: 5.5rem; } - .split.button.large span { - width: 3.4375rem; } - .split.button.large span:before { - border-top-style: solid; - border-width: 0.3125rem; - top: 48%; - margin-left: -0.375rem; } - .split.button.expand { - padding-left: 2rem; } - .split.button.secondary span:before { - border-color: #333333 transparent transparent transparent; } - .split.button.radius span { - -moz-border-radius-bottomright: 3px; - -moz-border-radius-topright: 3px; - -webkit-border-bottom-right-radius: 3px; - -webkit-border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; } - .split.button.round span { - -moz-border-radius-bottomright: 1000px; - -moz-border-radius-topright: 1000px; - -webkit-border-bottom-right-radius: 1000px; - -webkit-border-top-right-radius: 1000px; - border-bottom-right-radius: 1000px; - border-top-right-radius: 1000px; } - -.reveal-modal-bg { - position: fixed; - height: 100%; - width: 100%; - background: black; - background: rgba(0, 0, 0, 0.45); - z-index: 98; - display: none; - top: 0; - left: 0; } - -dialog, .reveal-modal { - visibility: hidden; - display: none; - position: absolute; - left: 50%; - z-index: 99; - height: auto; - margin-left: -40%; - width: 80%; - background-color: white; - padding: 1.25rem; - border: solid 1px #666666; - -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); - top: 6.25rem; } - dialog .column, - dialog .columns, .reveal-modal .column, - .reveal-modal .columns { - min-width: 0; } - dialog > :first-child, .reveal-modal > :first-child { - margin-top: 0; } - dialog > :last-child, .reveal-modal > :last-child { - margin-bottom: 0; } - dialog .close-reveal-modal, .reveal-modal .close-reveal-modal { - font-size: 1.375rem; - line-height: 1; - position: absolute; - top: 0.5rem; - right: 0.6875rem; - color: #aaaaaa; - font-weight: bold; - cursor: pointer; } - -dialog[open] { - display: block; - visibility: visible; } - -@media only screen and (min-width: 40.063em) { - dialog, .reveal-modal { - padding: 1.875rem; - top: 6.25rem; } - dialog.tiny, .reveal-modal.tiny { - margin-left: -15%; - width: 30%; } - dialog.small, .reveal-modal.small { - margin-left: -20%; - width: 40%; } - dialog.medium, .reveal-modal.medium { - margin-left: -30%; - width: 60%; } - dialog.large, .reveal-modal.large { - margin-left: -35%; - width: 70%; } - dialog.xlarge, .reveal-modal.xlarge { - margin-left: -47.5%; - width: 95%; } } -@media print { - dialog, .reveal-modal { - background: white !important; } } -/* Tooltips */ -.has-tip { - border-bottom: dotted 1px #cccccc; - cursor: help; - font-weight: bold; - color: #333333; } - .has-tip:hover, .has-tip:focus { - border-bottom: dotted 1px #003c4c; - color: #0086a9; } - .has-tip.tip-left, .has-tip.tip-right { - float: none !important; } - -.tooltip { - display: none; - position: absolute; - z-index: 999; - font-weight: normal; - font-size: 0.875rem; - line-height: 1.3; - padding: 0.75rem; - max-width: 85%; - left: 50%; - width: 100%; - color: white; - background: #333333; } - .tooltip > .nub { - display: block; - left: 5px; - position: absolute; - width: 0; - height: 0; - border: solid 5px; - border-color: transparent transparent #333333 transparent; - top: -10px; } - .tooltip.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - .tooltip.round { - -webkit-border-radius: 1000px; - border-radius: 1000px; } - .tooltip.round > .nub { - left: 2rem; } - .tooltip.opened { - color: #0086a9 !important; - border-bottom: dotted 1px #003c4c !important; } - -.tap-to-close { - display: block; - font-size: 0.625rem; - color: #777777; - font-weight: normal; } - -@media only screen and (min-width: 40.063em) { - .tooltip > .nub { - border-color: transparent transparent #333333 transparent; - top: -10px; } - .tooltip.tip-top > .nub { - border-color: #333333 transparent transparent transparent; - top: auto; - bottom: -10px; } - .tooltip.tip-left, .tooltip.tip-right { - float: none !important; } - .tooltip.tip-left > .nub { - border-color: transparent transparent transparent #333333; - right: -10px; - left: auto; - top: 50%; - margin-top: -5px; } - .tooltip.tip-right > .nub { - border-color: transparent #333333 transparent transparent; - right: auto; - left: -10px; - top: 50%; - margin-top: -5px; } } -/* Clearing Styles */ -.clearing-thumbs, [data-clearing] { - *zoom: 1; - margin-bottom: 0; - margin-left: 0; - list-style: none; } - .clearing-thumbs:before, .clearing-thumbs:after, [data-clearing]:before, [data-clearing]:after { - content: " "; - display: table; } - .clearing-thumbs:after, [data-clearing]:after { - clear: both; } - .clearing-thumbs li, [data-clearing] li { - float: left; - margin-right: 10px; } - .clearing-thumbs[class*="block-grid-"] li, [data-clearing][class*="block-grid-"] li { - margin-right: 0; } - -.clearing-blackout { - background: #333333; - position: fixed; - width: 100%; - height: 100%; - top: 0; - left: 0; - z-index: 998; } - .clearing-blackout .clearing-close { - display: block; } - -.clearing-container { - position: relative; - z-index: 998; - height: 100%; - overflow: hidden; - margin: 0; } - -.clearing-touch-label { - position: absolute; - top: 50%; - left: 50%; - color: #aaa; - font-size: 0.6em; } - -.visible-img { - height: 95%; - position: relative; } - .visible-img img { - position: absolute; - left: 50%; - top: 50%; - margin-left: -50%; - max-height: 100%; - max-width: 100%; } - -.clearing-caption { - color: #cccccc; - font-size: 0.875em; - line-height: 1.3; - margin-bottom: 0; - text-align: center; - bottom: 0; - background: #333333; - width: 100%; - padding: 10px 30px 20px; - position: absolute; - left: 0; } - -.clearing-close { - z-index: 999; - padding-left: 20px; - padding-top: 10px; - font-size: 30px; - line-height: 1; - color: #cccccc; - display: none; } - .clearing-close:hover, .clearing-close:focus { - color: #ccc; } - -.clearing-assembled .clearing-container { - height: 100%; } - .clearing-assembled .clearing-container .carousel > ul { - display: none; } - -.clearing-feature li { - display: none; } - .clearing-feature li.clearing-featured-img { - display: block; } - -@media only screen and (min-width: 40.063em) { - .clearing-main-prev, - .clearing-main-next { - position: absolute; - height: 100%; - width: 40px; - top: 0; } - .clearing-main-prev > span, - .clearing-main-next > span { - position: absolute; - top: 50%; - display: block; - width: 0; - height: 0; - border: solid 12px; } - .clearing-main-prev > span:hover, - .clearing-main-next > span:hover { - opacity: 0.8; } - - .clearing-main-prev { - left: 0; } - .clearing-main-prev > span { - left: 5px; - border-color: transparent; - border-right-color: #cccccc; } - - .clearing-main-next { - right: 0; } - .clearing-main-next > span { - border-color: transparent; - border-left-color: #cccccc; } - - .clearing-main-prev.disabled, - .clearing-main-next.disabled { - opacity: 0.3; } - - .clearing-assembled .clearing-container .carousel { - background: rgba(51, 51, 51, 0.8); - height: 120px; - margin-top: 10px; - text-align: center; } - .clearing-assembled .clearing-container .carousel > ul { - display: inline-block; - z-index: 999; - height: 100%; - position: relative; - float: none; } - .clearing-assembled .clearing-container .carousel > ul li { - display: block; - width: 120px; - min-height: inherit; - float: left; - overflow: hidden; - margin-right: 0; - padding: 0; - position: relative; - cursor: pointer; - opacity: 0.4; } - .clearing-assembled .clearing-container .carousel > ul li.fix-height img { - height: 100%; - max-width: none; } - .clearing-assembled .clearing-container .carousel > ul li a.th { - border: none; - -webkit-box-shadow: none; - box-shadow: none; - display: block; } - .clearing-assembled .clearing-container .carousel > ul li img { - cursor: pointer !important; - width: 100% !important; } - .clearing-assembled .clearing-container .carousel > ul li.visible { - opacity: 1; } - .clearing-assembled .clearing-container .carousel > ul li:hover { - opacity: 0.8; } - .clearing-assembled .clearing-container .visible-img { - background: #333333; - overflow: hidden; - height: 85%; } - - .clearing-close { - position: absolute; - top: 10px; - right: 20px; - padding-left: 0; - padding-top: 0; } } -/* Progress Bar */ -.progress { - background-color: #f6f6f6; - height: 1.5625rem; - border: 1px solid white; - padding: 0.125rem; - margin-bottom: 0.625rem; } - .progress .meter { - background: #0086a9; - height: 100%; - display: block; } - .progress.secondary .meter { - background: #ff6600; - height: 100%; - display: block; } - .progress.success .meter { - background: #20ba44; - height: 100%; - display: block; } - .progress.alert .meter { - background: #c60f13; - height: 100%; - display: block; } - .progress.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - .progress.radius .meter { - -webkit-border-radius: 2px; - border-radius: 2px; } - .progress.round { - -webkit-border-radius: 1000px; - border-radius: 1000px; } - .progress.round .meter { - -webkit-border-radius: 999px; - border-radius: 999px; } - -.sub-nav { - display: block; - width: auto; - overflow: hidden; - margin: -0.25rem 0 1.125rem; - padding-top: 0.25rem; - margin-right: 0; - margin-left: -0.75rem; } - .sub-nav dt { - text-transform: uppercase; } - .sub-nav dt, - .sub-nav dd, - .sub-nav li { - float: left; - display: inline; - margin-left: 1rem; - margin-bottom: 0.625rem; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-weight: normal; - font-size: 0.875rem; - color: #999999; } - .sub-nav dt a, - .sub-nav dd a, - .sub-nav li a { - text-decoration: none; - color: #999999; - padding: 0.1875rem 1rem; } - .sub-nav dt a:hover, - .sub-nav dd a:hover, - .sub-nav li a:hover { - color: #737373; } - .sub-nav dt.active a, - .sub-nav dd.active a, - .sub-nav li.active a { - -webkit-border-radius: 3px; - border-radius: 3px; - font-weight: normal; - background: #0086a9; - padding: 0.1875rem 1rem; - cursor: default; - color: white; } - .sub-nav dt.active a:hover, - .sub-nav dd.active a:hover, - .sub-nav li.active a:hover { - background: #007391; } - -/* Foundation Joyride */ -.joyride-list { - display: none; } - -/* Default styles for the container */ -.joyride-tip-guide { - display: none; - position: absolute; - background: #333333; - color: white; - z-index: 101; - top: 0; - left: 2.5%; - font-family: inherit; - font-weight: normal; - width: 95%; } - -.lt-ie9 .joyride-tip-guide { - max-width: 800px; - left: 50%; - margin-left: -400px; } - -.joyride-content-wrapper { - width: 100%; - padding: 1.125rem 1.25rem 1.5rem; } - .joyride-content-wrapper .button { - margin-bottom: 0 !important; } - -/* Add a little css triangle pip, older browser just miss out on the fanciness of it */ -.joyride-tip-guide .joyride-nub { - display: block; - position: absolute; - left: 22px; - width: 0; - height: 0; - border: 10px solid #333333; } - .joyride-tip-guide .joyride-nub.top { - border-top-style: solid; - border-color: #333333; - border-top-color: transparent !important; - border-left-color: transparent !important; - border-right-color: transparent !important; - top: -20px; } - .joyride-tip-guide .joyride-nub.bottom { - border-bottom-style: solid; - border-color: #333333 !important; - border-bottom-color: transparent !important; - border-left-color: transparent !important; - border-right-color: transparent !important; - bottom: -20px; } - .joyride-tip-guide .joyride-nub.right { - right: -20px; } - .joyride-tip-guide .joyride-nub.left { - left: -20px; } - -/* Typography */ -.joyride-tip-guide h1, -.joyride-tip-guide h2, -.joyride-tip-guide h3, -.joyride-tip-guide h4, -.joyride-tip-guide h5, -.joyride-tip-guide h6 { - line-height: 1.25; - margin: 0; - font-weight: bold; - color: white; } - -.joyride-tip-guide p { - margin: 0 0 1.125rem 0; - font-size: 0.875rem; - line-height: 1.3; } - -.joyride-timer-indicator-wrap { - width: 50px; - height: 3px; - border: solid 1px #555555; - position: absolute; - right: 1.0625rem; - bottom: 1rem; } - -.joyride-timer-indicator { - display: block; - width: 0; - height: inherit; - background: #666666; } - -.joyride-close-tip { - position: absolute; - right: 12px; - top: 10px; - color: #777777 !important; - text-decoration: none; - font-size: 24px; - font-weight: normal; - line-height: 0.5 !important; } - .joyride-close-tip:hover, .joyride-close-tip:focus { - color: #eeeeee !important; } - -.joyride-modal-bg { - position: fixed; - height: 100%; - width: 100%; - background: transparent; - background: rgba(0, 0, 0, 0.5); - z-index: 100; - display: none; - top: 0; - left: 0; - cursor: pointer; } - -.joyride-expose-wrapper { - background-color: #ffffff; - position: absolute; - border-radius: 3px; - z-index: 102; - -moz-box-shadow: 0 0 30px white; - -webkit-box-shadow: 0 0 15px white; - box-shadow: 0 0 15px white; } - -.joyride-expose-cover { - background: transparent; - border-radius: 3px; - position: absolute; - z-index: 9999; - top: 0; - left: 0; } - -/* Styles for screens that are at least 768px; */ -@media only screen and (min-width: 40.063em) { - .joyride-tip-guide { - width: 300px; - left: inherit; } - .joyride-tip-guide .joyride-nub.bottom { - border-color: #333333 !important; - border-bottom-color: transparent !important; - border-left-color: transparent !important; - border-right-color: transparent !important; - bottom: -20px; } - .joyride-tip-guide .joyride-nub.right { - border-color: #333333 !important; - border-top-color: transparent !important; - border-right-color: transparent !important; - border-bottom-color: transparent !important; - top: 22px; - left: auto; - right: -20px; } - .joyride-tip-guide .joyride-nub.left { - border-color: #333333 !important; - border-top-color: transparent !important; - border-left-color: transparent !important; - border-bottom-color: transparent !important; - top: 22px; - left: -20px; - right: auto; } } -.label { - font-weight: normal; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - text-align: center; - text-decoration: none; - line-height: 1; - white-space: nowrap; - display: inline-block; - position: relative; - margin-bottom: inherit; - padding: 0.25rem 0.5rem 0.375rem; - font-size: 0.6875rem; - background-color: #0086a9; - color: white; } - .label.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - .label.round { - -webkit-border-radius: 1000px; - border-radius: 1000px; } - .label.alert { - background-color: #c60f13; - color: white; } - .label.success { - background-color: #20ba44; - color: white; } - .label.secondary { - background-color: #ff6600; - color: white; } - -.text-left { - text-align: left !important; } - -.text-right { - text-align: right !important; } - -.text-center { - text-align: center !important; } - -.text-justify { - text-align: justify !important; } - -@media only screen and (max-width: 40em) { - .small-only-text-left { - text-align: left !important; } - - .small-only-text-right { - text-align: right !important; } - - .small-only-text-center { - text-align: center !important; } - - .small-only-text-justify { - text-align: justify !important; } } -@media only screen { - .small-text-left { - text-align: left !important; } - - .small-text-right { - text-align: right !important; } - - .small-text-center { - text-align: center !important; } - - .small-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 40.063em) and (max-width: 64em) { - .medium-only-text-left { - text-align: left !important; } - - .medium-only-text-right { - text-align: right !important; } - - .medium-only-text-center { - text-align: center !important; } - - .medium-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 40.063em) { - .medium-text-left { - text-align: left !important; } - - .medium-text-right { - text-align: right !important; } - - .medium-text-center { - text-align: center !important; } - - .medium-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 64.063em) and (max-width: 90em) { - .large-only-text-left { - text-align: left !important; } - - .large-only-text-right { - text-align: right !important; } - - .large-only-text-center { - text-align: center !important; } - - .large-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 64.063em) { - .large-text-left { - text-align: left !important; } - - .large-text-right { - text-align: right !important; } - - .large-text-center { - text-align: center !important; } - - .large-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 90.063em) and (max-width: 120em) { - .xlarge-only-text-left { - text-align: left !important; } - - .xlarge-only-text-right { - text-align: right !important; } - - .xlarge-only-text-center { - text-align: center !important; } - - .xlarge-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 90.063em) { - .xlarge-text-left { - text-align: left !important; } - - .xlarge-text-right { - text-align: right !important; } - - .xlarge-text-center { - text-align: center !important; } - - .xlarge-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 120.063em) and (max-width: 99999999em) { - .xxlarge-only-text-left { - text-align: left !important; } - - .xxlarge-only-text-right { - text-align: right !important; } - - .xxlarge-only-text-center { - text-align: center !important; } - - .xxlarge-only-text-justify { - text-align: justify !important; } } -@media only screen and (min-width: 120.063em) { - .xxlarge-text-left { - text-align: left !important; } - - .xxlarge-text-right { - text-align: right !important; } - - .xxlarge-text-center { - text-align: center !important; } - - .xxlarge-text-justify { - text-align: justify !important; } } -.off-canvas-wrap { - -webkit-backface-visibility: hidden; - position: relative; - width: 100%; - overflow-x: hidden; } - .off-canvas-wrap.move-right, .off-canvas-wrap.move-left { - height: 100%; } - -.inner-wrap { - -webkit-backface-visibility: hidden; - position: relative; - width: 100%; - *zoom: 1; - -webkit-transition: -webkit-transform 500ms ease; - -moz-transition: -moz-transform 500ms ease; - -ms-transition: -ms-transform 500ms ease; - -o-transition: -o-transform 500ms ease; - transition: transform 500ms ease; } - .inner-wrap:before, .inner-wrap:after { - content: " "; - display: table; } - .inner-wrap:after { - clear: both; } - -nav.tab-bar { - -webkit-backface-visibility: hidden; - background: #333333; - color: white; - height: 2.8125rem; - line-height: 2.8125rem; - position: relative; } - nav.tab-bar h1, nav.tab-bar h2, nav.tab-bar h3, nav.tab-bar h4, nav.tab-bar h5, nav.tab-bar h6 { - color: white; - font-weight: bold; - line-height: 2.8125rem; - margin: 0; } - nav.tab-bar h1, nav.tab-bar h2, nav.tab-bar h3, nav.tab-bar h4 { - font-size: 1.125rem; } - -section.left-small { - width: 2.8125rem; - height: 2.8125rem; - position: absolute; - top: 0; - border-right: solid 1px #1a1a1a; - box-shadow: 1px 0 0 #4e4e4e; - left: 0; } - -section.right-small { - width: 2.8125rem; - height: 2.8125rem; - position: absolute; - top: 0; - border-left: solid 1px #4e4e4e; - box-shadow: -1px 0 0 #1a1a1a; - right: 0; } - -section.tab-bar-section { - padding: 0 0.625rem; - position: absolute; - text-align: center; - height: 2.8125rem; - top: 0; } - @media only screen and (min-width: 40.063em) { - section.tab-bar-section { - text-align: left; } } - section.tab-bar-section.left { - left: 0; - right: 2.8125rem; } - section.tab-bar-section.right { - left: 2.8125rem; - right: 0; } - section.tab-bar-section.middle { - left: 2.8125rem; - right: 2.8125rem; } - -a.menu-icon { - text-indent: 2.1875rem; - width: 2.8125rem; - height: 2.8125rem; - display: block; - line-height: 2.0625rem; - padding: 0; - color: white; - position: relative; } - a.menu-icon span { - position: absolute; - display: block; - width: 1rem; - height: 0; - left: 0.8125rem; - top: 0.3125rem; - -webkit-box-shadow: 1px 10px 1px 1px white, 1px 16px 1px 1px white, 1px 22px 1px 1px white; - box-shadow: 0 10px 0 1px white, 0 16px 0 1px white, 0 22px 0 1px white; } - a.menu-icon:hover span { - -webkit-box-shadow: 1px 10px 1px 1px #b3b3b3, 1px 16px 1px 1px #b3b3b3, 1px 22px 1px 1px #b3b3b3; - box-shadow: 0 10px 0 1px #b3b3b3, 0 16px 0 1px #b3b3b3, 0 22px 0 1px #b3b3b3; } - -.left-off-canvas-menu { - -webkit-backface-visibility: hidden; - width: 250px; - top: 0; - bottom: 0; - position: absolute; - overflow-y: auto; - background: #333333; - z-index: 1001; - box-sizing: content-box; - -webkit-transform: translate3d(-100%, 0, 0); - -moz-transform: translate3d(-100%, 0, 0); - -ms-transform: translate3d(-100%, 0, 0); - -o-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - left: 0; } - .left-off-canvas-menu * { - -webkit-backface-visibility: hidden; } - -.right-off-canvas-menu { - -webkit-backface-visibility: hidden; - width: 250px; - top: 0; - bottom: 0; - position: absolute; - overflow-y: auto; - background: #333333; - z-index: 1001; - box-sizing: content-box; - -webkit-transform: translate3d(100%, 0, 0); - -moz-transform: translate3d(100%, 0, 0); - -ms-transform: translate3d(100%, 0, 0); - -o-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - right: 0; } - -ul.off-canvas-list { - list-style-type: none; - padding: 0; - margin: 0; } - ul.off-canvas-list li label { - padding: 0.3rem 0.9375rem; - color: #999999; - text-transform: uppercase; - font-weight: bold; - background: #444444; - border-top: 1px solid #5e5e5e; - border-bottom: none; - margin: 0; } - ul.off-canvas-list li a { - display: block; - padding: 0.66667rem; - color: rgba(255, 255, 255, 0.7); - border-bottom: 1px solid #262626; } - -.move-right > .inner-wrap { - -webkit-transform: translate3d(250px, 0, 0); - -moz-transform: translate3d(250px, 0, 0); - -ms-transform: translate3d(250px, 0, 0); - -o-transform: translate3d(250px, 0, 0); - transform: translate3d(250px, 0, 0); } -.move-right a.exit-off-canvas { - -webkit-backface-visibility: hidden; - transition: background 300ms ease; - cursor: pointer; - box-shadow: -4px 0 4px rgba(0, 0, 0, 0.5), 4px 0 4px rgba(0, 0, 0, 0.5); - display: block; - position: absolute; - background: rgba(255, 255, 255, 0.2); - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1002; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - @media only screen and (min-width: 40.063em) { - .move-right a.exit-off-canvas:hover { - background: rgba(255, 255, 255, 0.05); } } - -.move-left > .inner-wrap { - -webkit-transform: translate3d(-250px, 0, 0); - -moz-transform: translate3d(-250px, 0, 0); - -ms-transform: translate3d(-250px, 0, 0); - -o-transform: translate3d(-250px, 0, 0); - transform: translate3d(-250px, 0, 0); } -.move-left a.exit-off-canvas { - -webkit-backface-visibility: hidden; - transition: background 300ms ease; - cursor: pointer; - box-shadow: -4px 0 4px rgba(0, 0, 0, 0.5), 4px 0 4px rgba(0, 0, 0, 0.5); - display: block; - position: absolute; - background: rgba(255, 255, 255, 0.2); - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1002; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - @media only screen and (min-width: 40.063em) { - .move-left a.exit-off-canvas:hover { - background: rgba(255, 255, 255, 0.05); } } - -.csstransforms.no-csstransforms3d .left-off-canvas-menu { - -webkit-transform: translate(-100%, 0); - -moz-transform: translate(-100%, 0); - -ms-transform: translate(-100%, 0); - -o-transform: translate(-100%, 0); - transform: translate(-100%, 0); } -.csstransforms.no-csstransforms3d .right-off-canvas-menu { - -webkit-transform: translate(100%, 0); - -moz-transform: translate(100%, 0); - -ms-transform: translate(100%, 0); - -o-transform: translate(100%, 0); - transform: translate(100%, 0); } -.csstransforms.no-csstransforms3d .move-left > .inner-wrap { - -webkit-transform: translate(-250px, 0); - -moz-transform: translate(-250px, 0); - -ms-transform: translate(-250px, 0); - -o-transform: translate(-250px, 0); - transform: translate(-250px, 0); } -.csstransforms.no-csstransforms3d .move-right > .inner-wrap { - -webkit-transform: translate(250px, 0); - -moz-transform: translate(250px, 0); - -ms-transform: translate(250px, 0); - -o-transform: translate(250px, 0); - transform: translate(250px, 0); } - -.no-csstransforms .left-off-canvas-menu { - left: -250px; } -.no-csstransforms .right-off-canvas-menu { - right: -250px; } -.no-csstransforms .move-left > .inner-wrap { - right: 250px; } -.no-csstransforms .move-right > .inner-wrap { - left: 250px; } - -@media only screen and (max-width: 40em) { - .f-dropdown { - max-width: 100%; - left: 0; } } -/* Foundation Dropdowns */ -.f-dropdown { - position: absolute; - left: -9999px; - list-style: none; - margin-left: 0; - width: 100%; - max-height: none; - height: auto; - background: white; - border: solid 1px #cccccc; - font-size: 16px; - z-index: 99; - margin-top: 2px; - max-width: 200px; } - .f-dropdown > *:first-child { - margin-top: 0; } - .f-dropdown > *:last-child { - margin-bottom: 0; } - .f-dropdown:before { - content: ""; - display: block; - width: 0; - height: 0; - border: inset 6px; - border-color: transparent transparent white transparent; - border-bottom-style: solid; - position: absolute; - top: -12px; - left: 10px; - z-index: 99; } - .f-dropdown:after { - content: ""; - display: block; - width: 0; - height: 0; - border: inset 7px; - border-color: transparent transparent #cccccc transparent; - border-bottom-style: solid; - position: absolute; - top: -14px; - left: 9px; - z-index: 98; } - .f-dropdown.right:before { - left: auto; - right: 10px; } - .f-dropdown.right:after { - left: auto; - right: 9px; } - .f-dropdown li { - font-size: 0.875rem; - cursor: pointer; - line-height: 1.125rem; - margin: 0; } - .f-dropdown li:hover, .f-dropdown li:focus { - background: #eeeeee; } - .f-dropdown li a { - display: block; - padding: 0.5rem; - color: #555555; } - .f-dropdown.content { - position: absolute; - left: -9999px; - list-style: none; - margin-left: 0; - padding: 1.25rem; - width: 100%; - height: auto; - max-height: none; - background: white; - border: solid 1px #cccccc; - font-size: 16px; - z-index: 99; - max-width: 200px; } - .f-dropdown.content > *:first-child { - margin-top: 0; } - .f-dropdown.content > *:last-child { - margin-bottom: 0; } - .f-dropdown.tiny { - max-width: 200px; } - .f-dropdown.small { - max-width: 300px; } - .f-dropdown.medium { - max-width: 500px; } - .f-dropdown.large { - max-width: 800px; } - -table { - background: white; - margin-bottom: 1.25rem; - border: solid 1px #dddddd; } - table thead, - table tfoot { - background: whitesmoke; } - table thead tr th, - table thead tr td, - table tfoot tr th, - table tfoot tr td { - padding: 0.5rem 0.625rem 0.625rem; - font-size: 0.875rem; - font-weight: bold; - color: #222222; - text-align: left; } - table tr th, - table tr td { - padding: 0.5625rem 0.625rem; - font-size: 0.875rem; - color: #222222; } - table tr.even, table tr.alt, table tr:nth-of-type(even) { - background: #f9f9f9; } - table thead tr th, - table tfoot tr th, - table tbody tr td, - table tr td, - table tfoot tr td { - display: table-cell; - line-height: 1.125rem; } - -/* Standard Forms */ -form { - margin: 0 0 1rem; } - -/* Using forms within rows, we need to set some defaults */ -form .row .row { - margin: 0 -0.5rem; } - form .row .row .column, - form .row .row .columns { - padding: 0 0.5rem; } - form .row .row.collapse { - margin: 0; } - form .row .row.collapse .column, - form .row .row.collapse .columns { - padding: 0; } - form .row .row.collapse input { - -moz-border-radius-bottomright: 0; - -moz-border-radius-topright: 0; - -webkit-border-bottom-right-radius: 0; - -webkit-border-top-right-radius: 0; } -form .row input.column, -form .row input.columns, -form .row textarea.column, -form .row textarea.columns { - padding-left: 0.5rem; } - -/* Label Styles */ -label { - font-size: 0.875rem; - color: #4d4d4d; - cursor: pointer; - display: block; - font-weight: normal; - line-height: 1.5; - margin-bottom: 0; - /* Styles for required inputs */ } - label.right { - float: none; - text-align: right; } - label.inline { - margin: 0 0 1rem 0; - padding: 0.625rem 0; } - label small { - text-transform: capitalize; - color: #676767; } - -select { - -webkit-appearance: none !important; - background: #fafafa url("data:image/svg+xml;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iM3B4IiB2aWV3Qm94PSIwIDAgNiAzIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2IDMiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIHBvaW50cz0iNS45OTIsMCAyLjk5MiwzIC0wLjAwOCwwICIvPjwvc3ZnPg==") no-repeat; - background-position-x: 97%; - background-position-y: center; - border: 1px solid #cccccc; - padding: 0.5rem; - font-size: 0.875rem; - -webkit-border-radius: 0; - border-radius: 0; } - select.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - select:hover { - background: #f3f3f3 url("data:image/svg+xml;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iM3B4IiB2aWV3Qm94PSIwIDAgNiAzIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2IDMiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIHBvaW50cz0iNS45OTIsMCAyLjk5MiwzIC0wLjAwOCwwICIvPjwvc3ZnPg==") no-repeat; - background-position-x: 97%; - background-position-y: center; - border-color: #999999; } - -select::-ms-expand { - display: none; } - -@-moz-document url-prefix() { - select { - background: #fafafa; } - - select:hover { - background: #f3f3f3; } } - -/* Attach elements to the beginning or end of an input */ -.prefix, -.postfix { - display: block; - position: relative; - z-index: 2; - text-align: center; - width: 100%; - padding-top: 0; - padding-bottom: 0; - border-style: solid; - border-width: 1px; - overflow: hidden; - font-size: 0.875rem; - height: 2.3125rem; - line-height: 2.3125rem; } - -/* Adjust padding, alignment and radius if pre/post element is a button */ -.postfix.button { - padding-left: 0; - padding-right: 0; - padding-top: 0; - padding-bottom: 0; - text-align: center; - line-height: 2.125rem; - border: none; } - -.prefix.button { - padding-left: 0; - padding-right: 0; - padding-top: 0; - padding-bottom: 0; - text-align: center; - line-height: 2.125rem; - border: none; } - -.prefix.button.radius { - -webkit-border-radius: 0; - border-radius: 0; - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; - -webkit-border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; } - -.postfix.button.radius { - -webkit-border-radius: 0; - border-radius: 0; - -moz-border-radius-bottomright: 3px; - -moz-border-radius-topright: 3px; - -webkit-border-bottom-right-radius: 3px; - -webkit-border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; } - -.prefix.button.round { - -webkit-border-radius: 0; - border-radius: 0; - -moz-border-radius-bottomleft: 1000px; - -moz-border-radius-topleft: 1000px; - -webkit-border-bottom-left-radius: 1000px; - -webkit-border-top-left-radius: 1000px; - border-bottom-left-radius: 1000px; - border-top-left-radius: 1000px; } - -.postfix.button.round { - -webkit-border-radius: 0; - border-radius: 0; - -moz-border-radius-bottomright: 1000px; - -moz-border-radius-topright: 1000px; - -webkit-border-bottom-right-radius: 1000px; - -webkit-border-top-right-radius: 1000px; - border-bottom-right-radius: 1000px; - border-top-right-radius: 1000px; } - -/* Separate prefix and postfix styles when on span or label so buttons keep their own */ -span.prefix, label.prefix { - background: #f2f2f2; - border-right: none; - color: #333333; - border-color: #cccccc; } - span.prefix.radius, label.prefix.radius { - -webkit-border-radius: 0; - border-radius: 0; - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; - -webkit-border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; } - -span.postfix, label.postfix { - background: #f2f2f2; - border-left: none; - color: #333333; - border-color: #cccccc; } - span.postfix.radius, label.postfix.radius { - -webkit-border-radius: 0; - border-radius: 0; - -moz-border-radius-bottomright: 3px; - -moz-border-radius-topright: 3px; - -webkit-border-bottom-right-radius: 3px; - -webkit-border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; } - -/* We use this to get basic styling on all basic form elements */ -input[type="text"], -input[type="password"], -input[type="date"], -input[type="datetime"], -input[type="datetime-local"], -input[type="month"], -input[type="week"], -input[type="email"], -input[type="number"], -input[type="search"], -input[type="tel"], -input[type="time"], -input[type="url"], -textarea { - -webkit-appearance: none; - background-color: white; - font-family: inherit; - border: 1px solid #cccccc; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - color: rgba(0, 0, 0, 0.75); - display: block; - font-size: 0.875rem; - margin: 0 0 1rem 0; - padding: 0.5rem; - height: 2.3125rem; - width: 100%; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: -webkit-box-shadow 0.45s, border-color 0.45s ease-in-out; - -moz-transition: -moz-box-shadow 0.45s, border-color 0.45s ease-in-out; - transition: box-shadow 0.45s, border-color 0.45s ease-in-out; } - input[type="text"]:focus, - input[type="password"]:focus, - input[type="date"]:focus, - input[type="datetime"]:focus, - input[type="datetime-local"]:focus, - input[type="month"]:focus, - input[type="week"]:focus, - input[type="email"]:focus, - input[type="number"]:focus, - input[type="search"]:focus, - input[type="tel"]:focus, - input[type="time"]:focus, - input[type="url"]:focus, - textarea:focus { - -webkit-box-shadow: 0 0 5px #999999; - -moz-box-shadow: 0 0 5px #999999; - box-shadow: 0 0 5px #999999; - border-color: #999999; } - input[type="text"]:focus, - input[type="password"]:focus, - input[type="date"]:focus, - input[type="datetime"]:focus, - input[type="datetime-local"]:focus, - input[type="month"]:focus, - input[type="week"]:focus, - input[type="email"]:focus, - input[type="number"]:focus, - input[type="search"]:focus, - input[type="tel"]:focus, - input[type="time"]:focus, - input[type="url"]:focus, - textarea:focus { - background: #fafafa; - border-color: #999999; - outline: none; } - input[type="text"][disabled], - input[type="password"][disabled], - input[type="date"][disabled], - input[type="datetime"][disabled], - input[type="datetime-local"][disabled], - input[type="month"][disabled], - input[type="week"][disabled], - input[type="email"][disabled], - input[type="number"][disabled], - input[type="search"][disabled], - input[type="tel"][disabled], - input[type="time"][disabled], - input[type="url"][disabled], - textarea[disabled] { - background-color: #dddddd; } - input[type="text"].radius, - input[type="password"].radius, - input[type="date"].radius, - input[type="datetime"].radius, - input[type="datetime-local"].radius, - input[type="month"].radius, - input[type="week"].radius, - input[type="email"].radius, - input[type="number"].radius, - input[type="search"].radius, - input[type="tel"].radius, - input[type="time"].radius, - input[type="url"].radius, - textarea.radius { - -webkit-border-radius: 3px; - border-radius: 3px; } - -/* Add height value for select elements to match text input height */ -select { - height: 2.3125rem; } - -/* Adjust margin for form elements below */ -input[type="file"], -input[type="checkbox"], -input[type="radio"], -select { - margin: 0 0 1rem 0; } - -input[type="checkbox"] + label, -input[type="radio"] + label { - display: inline-block; - margin-left: 0.5rem; - margin-right: 1rem; - margin-bottom: 0; - vertical-align: baseline; } - -/* Normalize file input width */ -input[type="file"] { - width: 100%; } - -/* We add basic fieldset styling */ -fieldset { - border: solid 1px #dddddd; - padding: 1.25rem; - margin: 1.125rem 0; } - fieldset legend { - font-weight: bold; - background: white; - padding: 0 0.1875rem; - margin: 0; - margin-left: -0.1875rem; } - -/* Error Handling */ -[data-abide] .error small.error, [data-abide] span.error, [data-abide] small.error { - display: block; - padding: 0.375rem 0.5625rem 0.5625rem; - margin-top: -1px; - margin-bottom: 1rem; - font-size: 0.75rem; - font-weight: normal; - font-style: italic; - background: #c60f13; - color: white; } -[data-abide] span.error, [data-abide] small.error { - display: none; } - -span.error, small.error { - display: block; - padding: 0.375rem 0.5625rem 0.5625rem; - margin-top: -1px; - margin-bottom: 1rem; - font-size: 0.75rem; - font-weight: normal; - font-style: italic; - background: #c60f13; - color: white; } - -.error input, -.error textarea, -.error select { - margin-bottom: 0; } -.error input[type="checkbox"], -.error input[type="radio"] { - margin-bottom: 1rem; } -.error label, -.error label.error { - color: #c60f13; } -.error small.error { - display: block; - padding: 0.375rem 0.5625rem 0.5625rem; - margin-top: -1px; - margin-bottom: 1rem; - font-size: 0.75rem; - font-weight: normal; - font-style: italic; - background: #c60f13; - color: white; } -.error > label > small { - color: #676767; - background: transparent; - padding: 0; - text-transform: capitalize; - font-style: normal; - font-size: 60%; - margin: 0; - display: inline; } -.error span.error-message { - display: block; } - -input.error, -textarea.error { - margin-bottom: 0; } - -label.error { - color: #c60f13; } - -[class*="block-grid-"] { - display: block; - padding: 0; - margin: 0 -0.625rem; - *zoom: 1; } - [class*="block-grid-"]:before, [class*="block-grid-"]:after { - content: " "; - display: table; } - [class*="block-grid-"]:after { - clear: both; } - [class*="block-grid-"] > li { - display: block; - height: auto; - float: left; - padding: 0 0.625rem 1.25rem; } - -@media only screen { - .small-block-grid-1 > li { - width: 100%; - list-style: none; } - .small-block-grid-1 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-1 > li:nth-of-type(1n+1) { - clear: both; } - - .small-block-grid-2 > li { - width: 50%; - list-style: none; } - .small-block-grid-2 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-2 > li:nth-of-type(2n+1) { - clear: both; } - - .small-block-grid-3 > li { - width: 33.33333%; - list-style: none; } - .small-block-grid-3 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-3 > li:nth-of-type(3n+1) { - clear: both; } - - .small-block-grid-4 > li { - width: 25%; - list-style: none; } - .small-block-grid-4 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-4 > li:nth-of-type(4n+1) { - clear: both; } - - .small-block-grid-5 > li { - width: 20%; - list-style: none; } - .small-block-grid-5 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-5 > li:nth-of-type(5n+1) { - clear: both; } - - .small-block-grid-6 > li { - width: 16.66667%; - list-style: none; } - .small-block-grid-6 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-6 > li:nth-of-type(6n+1) { - clear: both; } - - .small-block-grid-7 > li { - width: 14.28571%; - list-style: none; } - .small-block-grid-7 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-7 > li:nth-of-type(7n+1) { - clear: both; } - - .small-block-grid-8 > li { - width: 12.5%; - list-style: none; } - .small-block-grid-8 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-8 > li:nth-of-type(8n+1) { - clear: both; } - - .small-block-grid-9 > li { - width: 11.11111%; - list-style: none; } - .small-block-grid-9 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-9 > li:nth-of-type(9n+1) { - clear: both; } - - .small-block-grid-10 > li { - width: 10%; - list-style: none; } - .small-block-grid-10 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-10 > li:nth-of-type(10n+1) { - clear: both; } - - .small-block-grid-11 > li { - width: 9.09091%; - list-style: none; } - .small-block-grid-11 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-11 > li:nth-of-type(11n+1) { - clear: both; } - - .small-block-grid-12 > li { - width: 8.33333%; - list-style: none; } - .small-block-grid-12 > li:nth-of-type(n) { - clear: none; } - .small-block-grid-12 > li:nth-of-type(12n+1) { - clear: both; } } -@media only screen and (min-width: 40.063em) { - .medium-block-grid-1 > li { - width: 100%; - list-style: none; } - .medium-block-grid-1 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-1 > li:nth-of-type(1n+1) { - clear: both; } - - .medium-block-grid-2 > li { - width: 50%; - list-style: none; } - .medium-block-grid-2 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-2 > li:nth-of-type(2n+1) { - clear: both; } - - .medium-block-grid-3 > li { - width: 33.33333%; - list-style: none; } - .medium-block-grid-3 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-3 > li:nth-of-type(3n+1) { - clear: both; } - - .medium-block-grid-4 > li { - width: 25%; - list-style: none; } - .medium-block-grid-4 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-4 > li:nth-of-type(4n+1) { - clear: both; } - - .medium-block-grid-5 > li { - width: 20%; - list-style: none; } - .medium-block-grid-5 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-5 > li:nth-of-type(5n+1) { - clear: both; } - - .medium-block-grid-6 > li { - width: 16.66667%; - list-style: none; } - .medium-block-grid-6 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-6 > li:nth-of-type(6n+1) { - clear: both; } - - .medium-block-grid-7 > li { - width: 14.28571%; - list-style: none; } - .medium-block-grid-7 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-7 > li:nth-of-type(7n+1) { - clear: both; } - - .medium-block-grid-8 > li { - width: 12.5%; - list-style: none; } - .medium-block-grid-8 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-8 > li:nth-of-type(8n+1) { - clear: both; } - - .medium-block-grid-9 > li { - width: 11.11111%; - list-style: none; } - .medium-block-grid-9 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-9 > li:nth-of-type(9n+1) { - clear: both; } - - .medium-block-grid-10 > li { - width: 10%; - list-style: none; } - .medium-block-grid-10 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-10 > li:nth-of-type(10n+1) { - clear: both; } - - .medium-block-grid-11 > li { - width: 9.09091%; - list-style: none; } - .medium-block-grid-11 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-11 > li:nth-of-type(11n+1) { - clear: both; } - - .medium-block-grid-12 > li { - width: 8.33333%; - list-style: none; } - .medium-block-grid-12 > li:nth-of-type(n) { - clear: none; } - .medium-block-grid-12 > li:nth-of-type(12n+1) { - clear: both; } } -@media only screen and (min-width: 64.063em) { - .large-block-grid-1 > li { - width: 100%; - list-style: none; } - .large-block-grid-1 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-1 > li:nth-of-type(1n+1) { - clear: both; } - - .large-block-grid-2 > li { - width: 50%; - list-style: none; } - .large-block-grid-2 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-2 > li:nth-of-type(2n+1) { - clear: both; } - - .large-block-grid-3 > li { - width: 33.33333%; - list-style: none; } - .large-block-grid-3 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-3 > li:nth-of-type(3n+1) { - clear: both; } - - .large-block-grid-4 > li { - width: 25%; - list-style: none; } - .large-block-grid-4 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-4 > li:nth-of-type(4n+1) { - clear: both; } - - .large-block-grid-5 > li { - width: 20%; - list-style: none; } - .large-block-grid-5 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-5 > li:nth-of-type(5n+1) { - clear: both; } - - .large-block-grid-6 > li { - width: 16.66667%; - list-style: none; } - .large-block-grid-6 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-6 > li:nth-of-type(6n+1) { - clear: both; } - - .large-block-grid-7 > li { - width: 14.28571%; - list-style: none; } - .large-block-grid-7 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-7 > li:nth-of-type(7n+1) { - clear: both; } - - .large-block-grid-8 > li { - width: 12.5%; - list-style: none; } - .large-block-grid-8 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-8 > li:nth-of-type(8n+1) { - clear: both; } - - .large-block-grid-9 > li { - width: 11.11111%; - list-style: none; } - .large-block-grid-9 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-9 > li:nth-of-type(9n+1) { - clear: both; } - - .large-block-grid-10 > li { - width: 10%; - list-style: none; } - .large-block-grid-10 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-10 > li:nth-of-type(10n+1) { - clear: both; } - - .large-block-grid-11 > li { - width: 9.09091%; - list-style: none; } - .large-block-grid-11 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-11 > li:nth-of-type(11n+1) { - clear: both; } - - .large-block-grid-12 > li { - width: 8.33333%; - list-style: none; } - .large-block-grid-12 > li:nth-of-type(n) { - clear: none; } - .large-block-grid-12 > li:nth-of-type(12n+1) { - clear: both; } } -.keystroke, -kbd { - background-color: #ededed; - border-color: #dddddd; - color: #222222; - border-style: solid; - border-width: 1px; - margin: 0; - font-family: "Consolas", "Menlo", "Courier", monospace; - font-size: 0.875rem; - padding: 0.125rem 0.25rem 0; - -webkit-border-radius: 3px; - border-radius: 3px; } - -/* Foundation Visibility HTML Classes */ -.show-for-small, -.show-for-small-only, -.show-for-medium-down, -.show-for-large-down, -.hide-for-medium, -.hide-for-medium-up, -.hide-for-medium-only, -.hide-for-large, -.hide-for-large-up, -.hide-for-large-only, -.hide-for-xlarge, -.hide-for-xlarge-up, -.hide-for-xlarge-only, -.hide-for-xxlarge-up, -.hide-for-xxlarge-only { - display: inherit !important; } - -.hide-for-small, -.hide-for-small-only, -.hide-for-medium-down, -.show-for-medium, -.show-for-medium-up, -.show-for-medium-only, -.hide-for-large-down, -.show-for-large, -.show-for-large-up, -.show-for-large-only, -.show-for-xlarge, -.show-for-xlarge-up, -.show-for-xlarge-only, -.show-for-xxlarge-up, -.show-for-xxlarge-only { - display: none !important; } - -/* Specific visibility for tables */ -table.show-for-small, table.show-for-small-only, table.show-for-medium-down, table.show-for-large-down, table.hide-for-medium, table.hide-for-medium-up, table.hide-for-medium-only, table.hide-for-large, table.hide-for-large-up, table.hide-for-large-only, table.hide-for-xlarge, table.hide-for-xlarge-up, table.hide-for-xlarge-only, table.hide-for-xxlarge-up, table.hide-for-xxlarge-only { - display: table; } - -thead.show-for-small, thead.show-for-small-only, thead.show-for-medium-down, thead.show-for-large-down, thead.hide-for-medium, thead.hide-for-medium-up, thead.hide-for-medium-only, thead.hide-for-large, thead.hide-for-large-up, thead.hide-for-large-only, thead.hide-for-xlarge, thead.hide-for-xlarge-up, thead.hide-for-xlarge-only, thead.hide-for-xxlarge-up, thead.hide-for-xxlarge-only { - display: table-header-group !important; } - -tbody.show-for-small, tbody.show-for-small-only, tbody.show-for-medium-down, tbody.show-for-large-down, tbody.hide-for-medium, tbody.hide-for-medium-up, tbody.hide-for-medium-only, tbody.hide-for-large, tbody.hide-for-large-up, tbody.hide-for-large-only, tbody.hide-for-xlarge, tbody.hide-for-xlarge-up, tbody.hide-for-xlarge-only, tbody.hide-for-xxlarge-up, tbody.hide-for-xxlarge-only { - display: table-row-group !important; } - -tr.show-for-small, tr.show-for-small-only, tr.show-for-medium-down, tr.show-for-large-down, tr.hide-for-medium, tr.hide-for-medium-up, tr.hide-for-medium-only, tr.hide-for-large, tr.hide-for-large-up, tr.hide-for-large-only, tr.hide-for-xlarge, tr.hide-for-xlarge-up, tr.hide-for-xlarge-only, tr.hide-for-xxlarge-up, tr.hide-for-xxlarge-only { - display: table-row !important; } - -td.show-for-small, td.show-for-small-only, td.show-for-medium-down, td.show-for-large-down, td.hide-for-medium, td.hide-for-medium-up, td.hide-for-large, td.hide-for-large-up, td.hide-for-xlarge, td.hide-for-xlarge-up, td.hide-for-xxlarge-up, -th.show-for-small, -th.show-for-small-only, -th.show-for-medium-down, -th.show-for-large-down, -th.hide-for-medium, -th.hide-for-medium-up, -th.hide-for-large, -th.hide-for-large-up, -th.hide-for-xlarge, -th.hide-for-xlarge-up, -th.hide-for-xxlarge-up { - display: table-cell !important; } - -/* Medium Displays: 641px and up */ -@media only screen and (min-width: 40.063em) { - .hide-for-small, - .hide-for-small-only, - .show-for-medium, - .show-for-medium-down, - .show-for-medium-up, - .show-for-medium-only, - .hide-for-large, - .hide-for-large-up, - .hide-for-large-only, - .hide-for-xlarge, - .hide-for-xlarge-up, - .hide-for-xlarge-only, - .hide-for-xxlarge-up, - .hide-for-xxlarge-only { - display: inherit !important; } - - .show-for-small, - .show-for-small-only, - .hide-for-medium, - .hide-for-medium-down, - .hide-for-medium-up, - .hide-for-medium-only, - .hide-for-large-down, - .show-for-large, - .show-for-large-up, - .show-for-large-only, - .show-for-xlarge, - .show-for-xlarge-up, - .show-for-xlarge-only, - .show-for-xxlarge-up, - .show-for-xxlarge-only { - display: none !important; } - - /* Specific visibility for tables */ - table.hide-for-small, table.hide-for-small-only, table.show-for-medium, table.show-for-medium-down, table.show-for-medium-up, table.show-for-medium-only, table.hide-for-large, table.hide-for-large-up, table.hide-for-large-only, table.hide-for-xlarge, table.hide-for-xlarge-up, table.hide-for-xlarge-only, table.hide-for-xxlarge-up, table.hide-for-xxlarge-only { - display: table; } - - thead.hide-for-small, thead.hide-for-small-only, thead.show-for-medium, thead.show-for-medium-down, thead.show-for-medium-up, thead.show-for-medium-only, thead.hide-for-large, thead.hide-for-large-up, thead.hide-for-large-only, thead.hide-for-xlarge, thead.hide-for-xlarge-up, thead.hide-for-xlarge-only, thead.hide-for-xxlarge-up, thead.hide-for-xxlarge-only { - display: table-header-group !important; } - - tbody.hide-for-small, tbody.hide-for-small-only, tbody.show-for-medium, tbody.show-for-medium-down, tbody.show-for-medium-up, tbody.show-for-medium-only, tbody.hide-for-large, tbody.hide-for-large-up, tbody.hide-for-large-only, tbody.hide-for-xlarge, tbody.hide-for-xlarge-up, tbody.hide-for-xlarge-only, tbody.hide-for-xxlarge-up, tbody.hide-for-xxlarge-only { - display: table-row-group !important; } - - tr.hide-for-small, tr.hide-for-small-only, tr.show-for-medium, tr.show-for-medium-down, tr.show-for-medium-up, tr.show-for-medium-only, tr.hide-for-large, tr.hide-for-large-up, tr.hide-for-large-only, tr.hide-for-xlarge, tr.hide-for-xlarge-up, tr.hide-for-xlarge-only, tr.hide-for-xxlarge-up, tr.hide-for-xxlarge-only { - display: table-row !important; } - - td.hide-for-small, td.hide-for-small-only, td.show-for-medium, td.show-for-medium-down, td.show-for-medium-up, td.show-for-medium-only, td.hide-for-large, td.hide-for-large-up, td.hide-for-large-only, td.hide-for-xlarge, td.hide-for-xlarge-up, td.hide-for-xlarge-only, td.hide-for-xxlarge-up, td.hide-for-xxlarge-only, - th.hide-for-small, - th.hide-for-small-only, - th.show-for-medium, - th.show-for-medium-down, - th.show-for-medium-up, - th.show-for-medium-only, - th.hide-for-large, - th.hide-for-large-up, - th.hide-for-large-only, - th.hide-for-xlarge, - th.hide-for-xlarge-up, - th.hide-for-xlarge-only, - th.hide-for-xxlarge-up, - th.hide-for-xxlarge-only { - display: table-cell !important; } } -/* Large Displays: 1024px and up */ -@media only screen and (min-width: 64.063em) { - .hide-for-small, - .hide-for-small-only, - .hide-for-medium, - .hide-for-medium-down, - .hide-for-medium-only, - .show-for-medium-up, - .show-for-large, - .show-for-large-up, - .show-for-large-only, - .hide-for-xlarge, - .hide-for-xlarge-up, - .hide-for-xlarge-only, - .hide-for-xxlarge-up, - .hide-for-xxlarge-only { - display: inherit !important; } - - .show-for-small-only, - .show-for-medium, - .show-for-medium-down, - .show-for-medium-only, - .hide-for-large, - .hide-for-large-up, - .hide-for-large-only, - .show-for-xlarge, - .show-for-xlarge-up, - .show-for-xlarge-only, - .show-for-xxlarge-up, - .show-for-xxlarge-only { - display: none !important; } - - /* Specific visibility for tables */ - table.hide-for-small, table.hide-for-small-only, table.hide-for-medium, table.hide-for-medium-down, table.hide-for-medium-only, table.show-for-medium-up, table.show-for-large, table.show-for-large-up, table.show-for-large-only, table.hide-for-xlarge, table.hide-for-xlarge-up, table.hide-for-xlarge-only, table.hide-for-xxlarge-up, table.hide-for-xxlarge-only { - display: table; } - - thead.hide-for-small, thead.hide-for-small-only, thead.hide-for-medium, thead.hide-for-medium-down, thead.hide-for-medium-only, thead.show-for-medium-up, thead.show-for-large, thead.show-for-large-up, thead.show-for-large-only, thead.hide-for-xlarge, thead.hide-for-xlarge-up, thead.hide-for-xlarge-only, thead.hide-for-xxlarge-up, thead.hide-for-xxlarge-only { - display: table-header-group !important; } - - tbody.hide-for-small, tbody.hide-for-small-only, tbody.hide-for-medium, tbody.hide-for-medium-down, tbody.hide-for-medium-only, tbody.show-for-medium-up, tbody.show-for-large, tbody.show-for-large-up, tbody.show-for-large-only, tbody.hide-for-xlarge, tbody.hide-for-xlarge-up, tbody.hide-for-xlarge-only, tbody.hide-for-xxlarge-up, tbody.hide-for-xxlarge-only { - display: table-row-group !important; } - - tr.hide-for-small, tr.hide-for-small-only, tr.hide-for-medium, tr.hide-for-medium-down, tr.hide-for-medium-only, tr.show-for-medium-up, tr.show-for-large, tr.show-for-large-up, tr.show-for-large-only, tr.hide-for-xlarge, tr.hide-for-xlarge-up, tr.hide-for-xlarge-only, tr.hide-for-xxlarge-up, tr.hide-for-xxlarge-only { - display: table-row !important; } - - td.hide-for-small, td.hide-for-small-only, td.hide-for-medium, td.hide-for-medium-down, td.hide-for-medium-only, td.show-for-medium-up, td.show-for-large, td.show-for-large-up, td.show-for-large-only, td.hide-for-xlarge, td.hide-for-xlarge-up, td.hide-for-xlarge-only, td.hide-for-xxlarge-up, td.hide-for-xxlarge-only, - th.hide-for-small, - th.hide-for-small-only, - th.hide-for-medium, - th.hide-for-medium-down, - th.hide-for-medium-only, - th.show-for-medium-up, - th.show-for-large, - th.show-for-large-up, - th.show-for-large-only, - th.hide-for-xlarge, - th.hide-for-xlarge-up, - th.hide-for-xlarge-only, - th.hide-for-xxlarge-up, - th.hide-for-xxlarge-only { - display: table-cell !important; } } -/* X-Large Displays: 1441 and up */ -@media only screen and (min-width: 90.063em) { - .hide-for-small, - .hide-for-small-only, - .hide-for-medium, - .hide-for-medium-down, - .hide-for-medium-only, - .show-for-medium-up, - .show-for-large-up, - .hide-for-large-only, - .show-for-xlarge, - .show-for-xlarge-up, - .show-for-xlarge-only, - .hide-for-xxlarge-up, - .hide-for-xxlarge-only { - display: inherit !important; } - - .show-for-small-only, - .show-for-medium, - .show-for-medium-down, - .show-for-medium-only, - .show-for-large, - .show-for-large-only, - .show-for-large-down, - .hide-for-xlarge, - .hide-for-xlarge-up, - .hide-for-xlarge-only, - .show-for-xxlarge-up, - .show-for-xxlarge-only { - display: none !important; } - - /* Specific visibility for tables */ - table.hide-for-small, table.hide-for-small-only, table.hide-for-medium, table.hide-for-medium-down, table.hide-for-medium-only, table.show-for-medium-up, table.show-for-large-up, table.hide-for-large-only, table.show-for-xlarge, table.show-for-xlarge-up, table.show-for-xlarge-only, table.hide-for-xxlarge-up, table.hide-for-xxlarge-only { - display: table; } - - thead.hide-for-small, thead.hide-for-small-only, thead.hide-for-medium, thead.hide-for-medium-down, thead.hide-for-medium-only, thead.show-for-medium-up, thead.show-for-large-up, thead.hide-for-large-only, thead.show-for-xlarge, thead.show-for-xlarge-up, thead.show-for-xlarge-only, thead.hide-for-xxlarge-up, thead.hide-for-xxlarge-only { - display: table-header-group !important; } - - tbody.hide-for-small, tbody.hide-for-small-only, tbody.hide-for-medium, tbody.hide-for-medium-down, tbody.hide-for-medium-only, tbody.show-for-medium-up, tbody.show-for-large-up, tbody.hide-for-large-only, tbody.show-for-xlarge, tbody.show-for-xlarge-up, tbody.show-for-xlarge-only, tbody.hide-for-xxlarge-up, tbody.hide-for-xxlarge-only { - display: table-row-group !important; } - - tr.hide-for-small, tr.hide-for-small-only, tr.hide-for-medium, tr.hide-for-medium-down, tr.hide-for-medium-only, tr.show-for-medium-up, tr.show-for-large-up, tr.hide-for-large-only, tr.show-for-xlarge, tr.show-for-xlarge-up, tr.show-for-xlarge-only, tr.hide-for-xxlarge-up, tr.hide-for-xxlarge-only { - display: table-row !important; } - - td.hide-for-small, td.hide-for-small-only, td.hide-for-medium, td.hide-for-medium-down, td.hide-for-medium-only, td.show-for-medium-up, td.show-for-large-up, td.hide-for-large-only, td.show-for-xlarge, td.show-for-xlarge-up, td.show-for-xlarge-only, td.hide-for-xxlarge-up, td.hide-for-xxlarge-only, - th.hide-for-small, - th.hide-for-small-only, - th.hide-for-medium, - th.hide-for-medium-down, - th.hide-for-medium-only, - th.show-for-medium-up, - th.show-for-large-up, - th.hide-for-large-only, - th.show-for-xlarge, - th.show-for-xlarge-up, - th.show-for-xlarge-only, - th.hide-for-xxlarge-up, - th.hide-for-xxlarge-only { - display: table-cell !important; } } -/* XX-Large Displays: 1920 and up */ -@media only screen and (min-width: 120.063em) { - .hide-for-small, - .hide-for-small-only, - .hide-for-medium, - .hide-for-medium-down, - .hide-for-medium-only, - .show-for-medium-up, - .show-for-large-up, - .hide-for-large-only, - .hide-for-xlarge-only, - .show-for-xlarge-up, - .show-for-xxlarge-up, - .show-for-xxlarge-only { - display: inherit !important; } - - .show-for-small-only, - .show-for-medium, - .show-for-medium-down, - .show-for-medium-only, - .show-for-large, - .show-for-large-only, - .show-for-large-down, - .hide-for-xlarge, - .show-for-xlarge-only, - .hide-for-xxlarge-up, - .hide-for-xxlarge-only { - display: none !important; } - - /* Specific visibility for tables */ - table.hide-for-small, table.hide-for-small-only, table.hide-for-medium, table.hide-for-medium-down, table.hide-for-medium-only, table.show-for-medium-up, table.show-for-large-up, table.hide-for-xlarge-only, table.show-for-xlarge-up, table.show-for-xxlarge-up, table.show-for-xxlarge-only { - display: table; } - - thead.hide-for-small, thead.hide-for-small-only, thead.hide-for-medium, thead.hide-for-medium-down, thead.hide-for-medium-only, thead.show-for-medium-up, thead.show-for-large-up, thead.hide-for-xlarge-only, thead.show-for-xlarge-up, thead.show-for-xxlarge-up, thead.show-for-xxlarge-only { - display: table-header-group !important; } - - tbody.hide-for-small, tbody.hide-for-small-only, tbody.hide-for-medium, tbody.hide-for-medium-down, tbody.hide-for-medium-only, tbody.show-for-medium-up, tbody.show-for-large-up, tbody.hide-for-xlarge-only, tbody.show-for-xlarge-up, tbody.show-for-xxlarge-up, tbody.show-for-xxlarge-only { - display: table-row-group !important; } - - tr.hide-for-small, tr.hide-for-small-only, tr.hide-for-medium, tr.hide-for-medium-down, tr.hide-for-medium-only, tr.show-for-medium-up, tr.show-for-large-up, tr.hide-for-xlarge-only, tr.show-for-xlarge-up, tr.show-for-xxlarge-up, tr.show-for-xxlarge-only { - display: table-row !important; } - - td.hide-for-small, td.hide-for-small-only, td.hide-for-medium, td.hide-for-medium-down, td.hide-for-medium-only, td.show-for-medium-up, td.show-for-large-up, td.hide-for-xlarge-only, td.show-for-xlarge-up, td.show-for-xxlarge-up, td.show-for-xxlarge-only, - th.hide-for-small, - th.hide-for-small-only, - th.hide-for-medium, - th.hide-for-medium-down, - th.hide-for-medium-only, - th.show-for-medium-up, - th.show-for-large-up, - th.hide-for-xlarge-only, - th.show-for-xlarge-up, - th.show-for-xxlarge-up, - th.show-for-xxlarge-only { - display: table-cell !important; } } -/* Orientation targeting */ -.show-for-landscape, -.hide-for-portrait { - display: inherit !important; } - -.hide-for-landscape, -.show-for-portrait { - display: none !important; } - -/* Specific visibility for tables */ -table.hide-for-landscape, table.show-for-portrait { - display: table; } - -thead.hide-for-landscape, thead.show-for-portrait { - display: table-header-group !important; } - -tbody.hide-for-landscape, tbody.show-for-portrait { - display: table-row-group !important; } - -tr.hide-for-landscape, tr.show-for-portrait { - display: table-row !important; } - -td.hide-for-landscape, td.show-for-portrait, -th.hide-for-landscape, -th.show-for-portrait { - display: table-cell !important; } - -@media only screen and (orientation: landscape) { - .show-for-landscape, - .hide-for-portrait { - display: inherit !important; } - - .hide-for-landscape, - .show-for-portrait { - display: none !important; } - - /* Specific visibility for tables */ - table.show-for-landscape, table.hide-for-portrait { - display: table; } - - thead.show-for-landscape, thead.hide-for-portrait { - display: table-header-group !important; } - - tbody.show-for-landscape, tbody.hide-for-portrait { - display: table-row-group !important; } - - tr.show-for-landscape, tr.hide-for-portrait { - display: table-row !important; } - - td.show-for-landscape, td.hide-for-portrait, - th.show-for-landscape, - th.hide-for-portrait { - display: table-cell !important; } } -@media only screen and (orientation: portrait) { - .show-for-portrait, - .hide-for-landscape { - display: inherit !important; } - - .hide-for-portrait, - .show-for-landscape { - display: none !important; } - - /* Specific visibility for tables */ - table.show-for-portrait, table.hide-for-landscape { - display: table; } - - thead.show-for-portrait, thead.hide-for-landscape { - display: table-header-group !important; } - - tbody.show-for-portrait, tbody.hide-for-landscape { - display: table-row-group !important; } - - tr.show-for-portrait, tr.hide-for-landscape { - display: table-row !important; } - - td.show-for-portrait, td.hide-for-landscape, - th.show-for-portrait, - th.hide-for-landscape { - display: table-cell !important; } } -/* Touch-enabled device targeting */ -.show-for-touch { - display: none !important; } - -.hide-for-touch { - display: inherit !important; } - -.touch .show-for-touch { - display: inherit !important; } - -.touch .hide-for-touch { - display: none !important; } - -/* Specific visibility for tables */ -table.hide-for-touch { - display: table; } - -.touch table.show-for-touch { - display: table; } - -thead.hide-for-touch { - display: table-header-group !important; } - -.touch thead.show-for-touch { - display: table-header-group !important; } - -tbody.hide-for-touch { - display: table-row-group !important; } - -.touch tbody.show-for-touch { - display: table-row-group !important; } - -tr.hide-for-touch { - display: table-row !important; } - -.touch tr.show-for-touch { - display: table-row !important; } - -td.hide-for-touch { - display: table-cell !important; } - -.touch td.show-for-touch { - display: table-cell !important; } - -th.hide-for-touch { - display: table-cell !important; } - -.touch th.show-for-touch { - display: table-cell !important; } diff --git a/coin/static/css/foundation.min.css b/coin/static/css/foundation.min.css deleted file mode 100644 index 9a0defdc36632ea6d3ab41edf246c11c1fddb565..0000000000000000000000000000000000000000 --- a/coin/static/css/foundation.min.css +++ /dev/null @@ -1 +0,0 @@ -meta.foundation-version{font-family:"/5.1.0/"}meta.foundation-mq-small{font-family:"/only screen and (max-width: 40em)/";width:0em}meta.foundation-mq-medium{font-family:"/only screen and (min-width:40.063em)/";width:40.063em}meta.foundation-mq-large{font-family:"/only screen and (min-width:64.063em)/";width:64.063em}meta.foundation-mq-xlarge{font-family:"/only screen and (min-width:90.063em)/";width:90.063em}meta.foundation-mq-xxlarge{font-family:"/only screen and (min-width:120.063em)/";width:120.063em}meta.foundation-data-attribute-namespace{font-family:false}html,body{height:100%}*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}html,body{font-size:100%}body{background:#fff;color:#222;padding:0;margin:0;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-weight:normal;font-style:normal;line-height:1;position:relative;cursor:default}a:hover{cursor:pointer}img,object,embed{max-width:100%;height:auto}object,embed{height:100%}img{-ms-interpolation-mode:bicubic}#map_canvas img,#map_canvas embed,#map_canvas object,.map_canvas img,.map_canvas embed,.map_canvas object{max-width:none !important}.left{float:left !important}.right{float:right !important}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.hide{display:none}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px}select{width:100%}.row{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1}.row:before,.row:after{content:" ";display:table}.row:after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0;float:left}.row.collapse .row{margin-left:0;margin-right:0}.row .row{width:auto;margin-left:-0.9375em;margin-right:-0.9375em;margin-top:0;margin-bottom:0;max-width:none;*zoom:1}.row .row:before,.row .row:after{content:" ";display:table}.row .row:after{clear:both}.row .row.collapse{width:auto;margin:0;max-width:none;*zoom:1}.row .row.collapse:before,.row .row.collapse:after{content:" ";display:table}.row .row.collapse:after{clear:both}.column,.columns{padding-left:0.9375em;padding-right:0.9375em;width:100%;float:left}@media only screen{.column.small-centered,.columns.small-centered{margin-left:auto;margin-right:auto;float:none}.column.small-uncentered,.columns.small-uncentered{margin-left:0;margin-right:0;float:left}.column.small-uncentered.opposite,.columns.small-uncentered.opposite{float:right}.small-push-0{left:0%;right:auto}.small-pull-0{right:0%;left:auto}.small-push-1{left:8.33333%;right:auto}.small-pull-1{right:8.33333%;left:auto}.small-push-2{left:16.66667%;right:auto}.small-pull-2{right:16.66667%;left:auto}.small-push-3{left:25%;right:auto}.small-pull-3{right:25%;left:auto}.small-push-4{left:33.33333%;right:auto}.small-pull-4{right:33.33333%;left:auto}.small-push-5{left:41.66667%;right:auto}.small-pull-5{right:41.66667%;left:auto}.small-push-6{left:50%;right:auto}.small-pull-6{right:50%;left:auto}.small-push-7{left:58.33333%;right:auto}.small-pull-7{right:58.33333%;left:auto}.small-push-8{left:66.66667%;right:auto}.small-pull-8{right:66.66667%;left:auto}.small-push-9{left:75%;right:auto}.small-pull-9{right:75%;left:auto}.small-push-10{left:83.33333%;right:auto}.small-pull-10{right:83.33333%;left:auto}.small-push-11{left:91.66667%;right:auto}.small-pull-11{right:91.66667%;left:auto}.column,.columns{position:relative;padding-left:0.9375em;padding-right:0.9375em;float:left}.small-1{width:8.33333%}.small-2{width:16.66667%}.small-3{width:25%}.small-4{width:33.33333%}.small-5{width:41.66667%}.small-6{width:50%}.small-7{width:58.33333%}.small-8{width:66.66667%}.small-9{width:75%}.small-10{width:83.33333%}.small-11{width:91.66667%}.small-12{width:100%}[class*="column"]+[class*="column"]:last-child{float:right}[class*="column"]+[class*="column"].end{float:left}.small-offset-0{margin-left:0% !important}.small-offset-1{margin-left:8.33333% !important}.small-offset-2{margin-left:16.66667% !important}.small-offset-3{margin-left:25% !important}.small-offset-4{margin-left:33.33333% !important}.small-offset-5{margin-left:41.66667% !important}.small-offset-6{margin-left:50% !important}.small-offset-7{margin-left:58.33333% !important}.small-offset-8{margin-left:66.66667% !important}.small-offset-9{margin-left:75% !important}.small-offset-10{margin-left:83.33333% !important}.small-offset-11{margin-left:91.66667% !important}.small-reset-order,.small-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}}@media only screen and (min-width: 40.063em){.column.medium-centered,.columns.medium-centered{margin-left:auto;margin-right:auto;float:none}.column.medium-uncentered,.columns.medium-uncentered{margin-left:0;margin-right:0;float:left}.column.medium-uncentered.opposite,.columns.medium-uncentered.opposite{float:right}.medium-push-0{left:0%;right:auto}.medium-pull-0{right:0%;left:auto}.medium-push-1{left:8.33333%;right:auto}.medium-pull-1{right:8.33333%;left:auto}.medium-push-2{left:16.66667%;right:auto}.medium-pull-2{right:16.66667%;left:auto}.medium-push-3{left:25%;right:auto}.medium-pull-3{right:25%;left:auto}.medium-push-4{left:33.33333%;right:auto}.medium-pull-4{right:33.33333%;left:auto}.medium-push-5{left:41.66667%;right:auto}.medium-pull-5{right:41.66667%;left:auto}.medium-push-6{left:50%;right:auto}.medium-pull-6{right:50%;left:auto}.medium-push-7{left:58.33333%;right:auto}.medium-pull-7{right:58.33333%;left:auto}.medium-push-8{left:66.66667%;right:auto}.medium-pull-8{right:66.66667%;left:auto}.medium-push-9{left:75%;right:auto}.medium-pull-9{right:75%;left:auto}.medium-push-10{left:83.33333%;right:auto}.medium-pull-10{right:83.33333%;left:auto}.medium-push-11{left:91.66667%;right:auto}.medium-pull-11{right:91.66667%;left:auto}.column,.columns{position:relative;padding-left:0.9375em;padding-right:0.9375em;float:left}.medium-1{width:8.33333%}.medium-2{width:16.66667%}.medium-3{width:25%}.medium-4{width:33.33333%}.medium-5{width:41.66667%}.medium-6{width:50%}.medium-7{width:58.33333%}.medium-8{width:66.66667%}.medium-9{width:75%}.medium-10{width:83.33333%}.medium-11{width:91.66667%}.medium-12{width:100%}[class*="column"]+[class*="column"]:last-child{float:right}[class*="column"]+[class*="column"].end{float:left}.medium-offset-0{margin-left:0% !important}.medium-offset-1{margin-left:8.33333% !important}.medium-offset-2{margin-left:16.66667% !important}.medium-offset-3{margin-left:25% !important}.medium-offset-4{margin-left:33.33333% !important}.medium-offset-5{margin-left:41.66667% !important}.medium-offset-6{margin-left:50% !important}.medium-offset-7{margin-left:58.33333% !important}.medium-offset-8{margin-left:66.66667% !important}.medium-offset-9{margin-left:75% !important}.medium-offset-10{margin-left:83.33333% !important}.medium-offset-11{margin-left:91.66667% !important}.medium-reset-order,.medium-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}.push-0{left:0%;right:auto}.pull-0{right:0%;left:auto}.push-1{left:8.33333%;right:auto}.pull-1{right:8.33333%;left:auto}.push-2{left:16.66667%;right:auto}.pull-2{right:16.66667%;left:auto}.push-3{left:25%;right:auto}.pull-3{right:25%;left:auto}.push-4{left:33.33333%;right:auto}.pull-4{right:33.33333%;left:auto}.push-5{left:41.66667%;right:auto}.pull-5{right:41.66667%;left:auto}.push-6{left:50%;right:auto}.pull-6{right:50%;left:auto}.push-7{left:58.33333%;right:auto}.pull-7{right:58.33333%;left:auto}.push-8{left:66.66667%;right:auto}.pull-8{right:66.66667%;left:auto}.push-9{left:75%;right:auto}.pull-9{right:75%;left:auto}.push-10{left:83.33333%;right:auto}.pull-10{right:83.33333%;left:auto}.push-11{left:91.66667%;right:auto}.pull-11{right:91.66667%;left:auto}}@media only screen and (min-width: 64.063em){.column.large-centered,.columns.large-centered{margin-left:auto;margin-right:auto;float:none}.column.large-uncentered,.columns.large-uncentered{margin-left:0;margin-right:0;float:left}.column.large-uncentered.opposite,.columns.large-uncentered.opposite{float:right}.large-push-0{left:0%;right:auto}.large-pull-0{right:0%;left:auto}.large-push-1{left:8.33333%;right:auto}.large-pull-1{right:8.33333%;left:auto}.large-push-2{left:16.66667%;right:auto}.large-pull-2{right:16.66667%;left:auto}.large-push-3{left:25%;right:auto}.large-pull-3{right:25%;left:auto}.large-push-4{left:33.33333%;right:auto}.large-pull-4{right:33.33333%;left:auto}.large-push-5{left:41.66667%;right:auto}.large-pull-5{right:41.66667%;left:auto}.large-push-6{left:50%;right:auto}.large-pull-6{right:50%;left:auto}.large-push-7{left:58.33333%;right:auto}.large-pull-7{right:58.33333%;left:auto}.large-push-8{left:66.66667%;right:auto}.large-pull-8{right:66.66667%;left:auto}.large-push-9{left:75%;right:auto}.large-pull-9{right:75%;left:auto}.large-push-10{left:83.33333%;right:auto}.large-pull-10{right:83.33333%;left:auto}.large-push-11{left:91.66667%;right:auto}.large-pull-11{right:91.66667%;left:auto}.column,.columns{position:relative;padding-left:0.9375em;padding-right:0.9375em;float:left}.large-1{width:8.33333%}.large-2{width:16.66667%}.large-3{width:25%}.large-4{width:33.33333%}.large-5{width:41.66667%}.large-6{width:50%}.large-7{width:58.33333%}.large-8{width:66.66667%}.large-9{width:75%}.large-10{width:83.33333%}.large-11{width:91.66667%}.large-12{width:100%}[class*="column"]+[class*="column"]:last-child{float:right}[class*="column"]+[class*="column"].end{float:left}.large-offset-0{margin-left:0% !important}.large-offset-1{margin-left:8.33333% !important}.large-offset-2{margin-left:16.66667% !important}.large-offset-3{margin-left:25% !important}.large-offset-4{margin-left:33.33333% !important}.large-offset-5{margin-left:41.66667% !important}.large-offset-6{margin-left:50% !important}.large-offset-7{margin-left:58.33333% !important}.large-offset-8{margin-left:66.66667% !important}.large-offset-9{margin-left:75% !important}.large-offset-10{margin-left:83.33333% !important}.large-offset-11{margin-left:91.66667% !important}.large-reset-order,.large-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}.push-0{left:0%;right:auto}.pull-0{right:0%;left:auto}.push-1{left:8.33333%;right:auto}.pull-1{right:8.33333%;left:auto}.push-2{left:16.66667%;right:auto}.pull-2{right:16.66667%;left:auto}.push-3{left:25%;right:auto}.pull-3{right:25%;left:auto}.push-4{left:33.33333%;right:auto}.pull-4{right:33.33333%;left:auto}.push-5{left:41.66667%;right:auto}.pull-5{right:41.66667%;left:auto}.push-6{left:50%;right:auto}.pull-6{right:50%;left:auto}.push-7{left:58.33333%;right:auto}.pull-7{right:58.33333%;left:auto}.push-8{left:66.66667%;right:auto}.pull-8{right:66.66667%;left:auto}.push-9{left:75%;right:auto}.pull-9{right:75%;left:auto}.push-10{left:83.33333%;right:auto}.pull-10{right:83.33333%;left:auto}.push-11{left:91.66667%;right:auto}.pull-11{right:91.66667%;left:auto}}meta.foundation-mq-topbar{font-family:"/only screen and (min-width:40.063em)/";width:58.75em}.contain-to-grid{width:100%;background:#333}.contain-to-grid .top-bar{margin-bottom:0}.fixed{width:100%;left:0;position:fixed;top:0;z-index:99}.fixed.expanded:not(.top-bar){overflow-y:auto;height:auto;width:100%;max-height:100%}.fixed.expanded:not(.top-bar) .title-area{position:fixed;width:100%;z-index:99}.fixed.expanded:not(.top-bar) .top-bar-section{z-index:98;margin-top:45px}.top-bar{overflow:hidden;height:45px;line-height:45px;position:relative;background:#333;margin-bottom:0}.top-bar ul{margin-bottom:0;list-style:none}.top-bar .row{max-width:none}.top-bar form,.top-bar input{margin-bottom:0}.top-bar input{height:auto;padding-top:.35rem;padding-bottom:.35rem;font-size:0.75rem}.top-bar .button{padding-top:.45rem;padding-bottom:.35rem;margin-bottom:0;font-size:0.75rem}.top-bar .title-area{position:relative;margin:0}.top-bar .name{height:45px;margin:0;font-size:16px}.top-bar .name h1{line-height:45px;font-size:1.0625rem;margin:0}.top-bar .name h1 a{font-weight:normal;color:#fff;width:50%;display:block;padding:0 15px}.top-bar .toggle-topbar{position:absolute;right:0;top:0}.top-bar .toggle-topbar a{color:#fff;text-transform:uppercase;font-size:0.8125rem;font-weight:bold;position:relative;display:block;padding:0 15px;height:45px;line-height:45px}.top-bar .toggle-topbar.menu-icon{right:15px;top:50%;margin-top:-16px;padding-left:40px}.top-bar .toggle-topbar.menu-icon a{height:34px;line-height:33px;padding:0;padding-right:25px;color:#fff;position:relative}.top-bar .toggle-topbar.menu-icon a::after{content:"";position:absolute;right:0;display:block;width:16px;top:0;height:0;-webkit-box-shadow:0 10px 0 1px #fff,0 16px 0 1px #fff,0 22px 0 1px #fff;box-shadow:0 10px 0 1px #fff,0 16px 0 1px #fff,0 22px 0 1px #fff}.top-bar.expanded{height:auto;background:transparent}.top-bar.expanded .title-area{background:#333}.top-bar.expanded .toggle-topbar a{color:#888}.top-bar.expanded .toggle-topbar a span{-webkit-box-shadow:0 10px 0 1px #888,0 16px 0 1px #888,0 22px 0 1px #888;box-shadow:0 10px 0 1px #888,0 16px 0 1px #888,0 22px 0 1px #888}.top-bar-section{left:0;position:relative;width:auto;-webkit-transition:left 300ms ease-out;-moz-transition:left 300ms ease-out;transition:left 300ms ease-out}.top-bar-section ul{width:100%;height:auto;display:block;background:#333;font-size:16px;margin:0}.top-bar-section .divider,.top-bar-section [role="separator"]{border-top:solid 1px #1a1a1a;clear:both;height:1px;width:100%}.top-bar-section ul li>a{display:block;width:100%;color:#fff;padding:12px 0 12px 0;padding-left:15px;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-size:0.8125rem;font-weight:normal;background:#333}.top-bar-section ul li>a.button{background:#0086a9;font-size:0.8125rem;padding-right:15px;padding-left:15px}.top-bar-section ul li>a.button:hover{background:#00627b}.top-bar-section ul li>a.button.secondary{background:#f60}.top-bar-section ul li>a.button.secondary:hover{background:#e35b00}.top-bar-section ul li>a.button.success{background:#20ba44}.top-bar-section ul li>a.button.success:hover{background:#199336}.top-bar-section ul li>a.button.alert{background:#c60f13}.top-bar-section ul li>a.button.alert:hover{background:#a20c10}.top-bar-section ul li:hover>a{background:#272727;color:#fff}.top-bar-section ul li.active>a{background:#0086a9;color:#fff}.top-bar-section ul li.active>a:hover{background:#007391;color:#fff}.top-bar-section .has-form{padding:15px}.top-bar-section .has-dropdown{position:relative}.top-bar-section .has-dropdown>a:after{content:"";display:block;width:0;height:0;border:inset 5px;border-color:transparent transparent transparent rgba(255,255,255,0.4);border-left-style:solid;margin-right:15px;margin-top:-4.5px;position:absolute;top:50%;right:0}.top-bar-section .has-dropdown.moved{position:static}.top-bar-section .has-dropdown.moved>.dropdown{display:block}.top-bar-section .dropdown{position:absolute;left:100%;top:0;display:none;z-index:99}.top-bar-section .dropdown li{width:100%;height:auto}.top-bar-section .dropdown li a{font-weight:normal;padding:8px 15px}.top-bar-section .dropdown li a.parent-link{font-weight:normal}.top-bar-section .dropdown li.title h5{margin-bottom:0}.top-bar-section .dropdown li.title h5 a{color:#fff;line-height:22.5px;display:block}.top-bar-section .dropdown li.has-form{padding:8px 15px}.top-bar-section .dropdown li .button{top:auto}.top-bar-section .dropdown label{padding:8px 15px 2px;margin-bottom:0;text-transform:uppercase;color:#777;font-weight:bold;font-size:0.625rem}.js-generated{display:block}@media only screen and (min-width: 40.063em){.top-bar{background:#333;*zoom:1;overflow:visible}.top-bar:before,.top-bar:after{content:" ";display:table}.top-bar:after{clear:both}.top-bar .toggle-topbar{display:none}.top-bar .title-area{float:left}.top-bar .name h1 a{width:auto}.top-bar input,.top-bar .button{font-size:0.875rem;position:relative;top:7px}.top-bar.expanded{background:#333}.contain-to-grid .top-bar{max-width:62.5em;margin:0 auto;margin-bottom:0}.top-bar-section{-webkit-transition:none 0 0;-moz-transition:none 0 0;transition:none 0 0;left:0 !important}.top-bar-section ul{width:auto;height:auto !important;display:inline}.top-bar-section ul li{float:left}.top-bar-section ul li .js-generated{display:none}.top-bar-section li.hover>a:not(.button){background:#272727;color:#fff}.top-bar-section li:not(.has-form) a:not(.button){padding:0 15px;line-height:45px;background:#333}.top-bar-section li:not(.has-form) a:not(.button):hover{background:#272727}.top-bar-section li.active:not(.has-form) a:not(.button){padding:0 15px;line-height:45px;color:#fff;background:#0086a9}.top-bar-section li.active:not(.has-form) a:not(.button):hover{background:#007391}.top-bar-section .has-dropdown>a{padding-right:35px !important}.top-bar-section .has-dropdown>a:after{content:"";display:block;width:0;height:0;border:inset 5px;border-color:rgba(255,255,255,0.4) transparent transparent transparent;border-top-style:solid;margin-top:-2.5px;top:22.5px}.top-bar-section .has-dropdown.moved{position:relative}.top-bar-section .has-dropdown.moved>.dropdown{display:none}.top-bar-section .has-dropdown.hover>.dropdown,.top-bar-section .has-dropdown.not-click:hover>.dropdown{display:block}.top-bar-section .has-dropdown .dropdown li.has-dropdown>a:after{border:none;content:"\00bb";top:1rem;margin-top:-2px;right:5px;line-height:1.2}.top-bar-section .dropdown{left:0;top:auto;background:transparent;min-width:100%}.top-bar-section .dropdown li a{color:#fff;line-height:1;white-space:nowrap;padding:12px 15px;background:#333}.top-bar-section .dropdown li label{white-space:nowrap;background:#333}.top-bar-section .dropdown li .dropdown{left:100%;top:0}.top-bar-section>ul>.divider,.top-bar-section>ul>[role="separator"]{border-bottom:none;border-top:none;border-right:solid 1px #4e4e4e;clear:none;height:45px;width:0}.top-bar-section .has-form{background:#333;padding:0 15px;height:45px}.top-bar-section .right li .dropdown{left:auto;right:0}.top-bar-section .right li .dropdown li .dropdown{right:100%}.top-bar-section .left li .dropdown{right:auto;left:0}.top-bar-section .left li .dropdown li .dropdown{left:100%}.no-js .top-bar-section ul li:hover>a{background:#272727;color:#fff}.no-js .top-bar-section ul li:active>a{background:#0086a9;color:#fff}.no-js .top-bar-section .has-dropdown:hover>.dropdown{display:block}}.breadcrumbs{display:block;padding:0.5625rem 0.875rem 0.5625rem;overflow:hidden;margin-left:0;list-style:none;border-style:solid;border-width:1px;background-color:#ffba8c;border-color:#ffa265;-webkit-border-radius:3px;border-radius:3px}.breadcrumbs>*{margin:0;float:left;font-size:0.6875rem;text-transform:uppercase}.breadcrumbs>*:hover a,.breadcrumbs>*:focus a{text-decoration:underline}.breadcrumbs>* a,.breadcrumbs>* span{text-transform:uppercase;color:#0086a9}.breadcrumbs>*.current{cursor:default;color:#333}.breadcrumbs>*.current a{cursor:default;color:#333}.breadcrumbs>*.current:hover,.breadcrumbs>*.current:hover a,.breadcrumbs>*.current:focus,.breadcrumbs>*.current:focus a{text-decoration:none}.breadcrumbs>*.unavailable{color:#999}.breadcrumbs>*.unavailable a{color:#999}.breadcrumbs>*.unavailable:hover,.breadcrumbs>*.unavailable:hover a,.breadcrumbs>*.unavailable:focus,.breadcrumbs>*.unavailable a:focus{text-decoration:none;color:#999;cursor:default}.breadcrumbs>*:before{content:"/";color:#aaa;margin:0 0.75rem;position:relative;top:1px}.breadcrumbs>*:first-child:before{content:" ";margin:0}.alert-box{border-style:solid;border-width:1px;display:block;font-weight:normal;margin-bottom:1.25rem;position:relative;padding:0.875rem 1.5rem 0.875rem 0.875rem;font-size:0.8125rem;background-color:#0086a9;border-color:#007391;color:#fff}.alert-box .close{font-size:1.375rem;padding:9px 6px 4px;line-height:0;position:absolute;top:50%;margin-top:-0.6875rem;right:0.25rem;color:#333;opacity:0.3}.alert-box .close:hover,.alert-box .close:focus{opacity:0.5}.alert-box.radius{-webkit-border-radius:3px;border-radius:3px}.alert-box.round{-webkit-border-radius:1000px;border-radius:1000px}.alert-box.success{background-color:#20ba44;border-color:#1ca03a;color:#fff}.alert-box.alert{background-color:#c60f13;border-color:#aa0d10;color:#fff}.alert-box.secondary{background-color:#f60;border-color:#db5800;color:#fff}.alert-box.warning{background-color:#f08a24;border-color:#de770f;color:#fff}.alert-box.info{background-color:#a0d3e8;border-color:#74bfdd;color:#572300}.inline-list{margin:0 auto 1.0625rem auto;margin-left:-1.375rem;margin-right:0;padding:0;list-style:none;overflow:hidden}.inline-list>li{list-style:none;float:left;margin-left:1.375rem;display:block}.inline-list>li>*{display:block}button,.button{border-style:solid;border-width:0px;cursor:pointer;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-weight:normal;line-height:normal;margin:0 0 1.25rem;position:relative;text-decoration:none;text-align:center;display:inline-block;padding-top:1rem;padding-right:2rem;padding-bottom:1.0625rem;padding-left:2rem;font-size:1rem;background-color:#0086a9;border-color:#006b87;color:#fff;-webkit-transition:background-color 300ms ease-out;-moz-transition:background-color 300ms ease-out;transition:background-color 300ms ease-out;padding-top:1.0625rem;padding-bottom:1rem;-webkit-appearance:none;border:none;font-weight:normal !important}button:hover,button:focus,.button:hover,.button:focus{background-color:#006b87}button:hover,button:focus,.button:hover,.button:focus{color:#fff}button.secondary,.button.secondary{background-color:#f60;border-color:#cc5200;color:#fff}button.secondary:hover,button.secondary:focus,.button.secondary:hover,.button.secondary:focus{background-color:#cc5200}button.secondary:hover,button.secondary:focus,.button.secondary:hover,.button.secondary:focus{color:#fff}button.success,.button.success{background-color:#20ba44;border-color:#1a9536;color:#fff}button.success:hover,button.success:focus,.button.success:hover,.button.success:focus{background-color:#1a9536}button.success:hover,button.success:focus,.button.success:hover,.button.success:focus{color:#fff}button.alert,.button.alert{background-color:#c60f13;border-color:#9e0c0f;color:#fff}button.alert:hover,button.alert:focus,.button.alert:hover,.button.alert:focus{background-color:#9e0c0f}button.alert:hover,button.alert:focus,.button.alert:hover,.button.alert:focus{color:#fff}button.large,.button.large{padding-top:1.125rem;padding-right:2.25rem;padding-bottom:1.1875rem;padding-left:2.25rem;font-size:1.25rem}button.small,.button.small{padding-top:0.875rem;padding-right:1.75rem;padding-bottom:0.9375rem;padding-left:1.75rem;font-size:0.8125rem}button.tiny,.button.tiny{padding-top:0.625rem;padding-right:1.25rem;padding-bottom:0.6875rem;padding-left:1.25rem;font-size:0.6875rem}button.expand,.button.expand{padding-right:0;padding-left:0;width:100%}button.left-align,.button.left-align{text-align:left;text-indent:0.75rem}button.right-align,.button.right-align{text-align:right;padding-right:0.75rem}button.radius,.button.radius{-webkit-border-radius:3px;border-radius:3px}button.round,.button.round{-webkit-border-radius:1000px;border-radius:1000px}button.disabled,button[disabled],.button.disabled,.button[disabled]{background-color:#0086a9;border-color:#006b87;color:#fff;cursor:default;opacity:0.7;-webkit-box-shadow:none;box-shadow:none}button.disabled:hover,button.disabled:focus,button[disabled]:hover,button[disabled]:focus,.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{background-color:#006b87}button.disabled:hover,button.disabled:focus,button[disabled]:hover,button[disabled]:focus,.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{color:#fff}button.disabled:hover,button.disabled:focus,button[disabled]:hover,button[disabled]:focus,.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{background-color:#0086a9}button.disabled.secondary,button[disabled].secondary,.button.disabled.secondary,.button[disabled].secondary{background-color:#f60;border-color:#cc5200;color:#fff;cursor:default;opacity:0.7;-webkit-box-shadow:none;box-shadow:none}button.disabled.secondary:hover,button.disabled.secondary:focus,button[disabled].secondary:hover,button[disabled].secondary:focus,.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{background-color:#cc5200}button.disabled.secondary:hover,button.disabled.secondary:focus,button[disabled].secondary:hover,button[disabled].secondary:focus,.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{color:#fff}button.disabled.secondary:hover,button.disabled.secondary:focus,button[disabled].secondary:hover,button[disabled].secondary:focus,.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{background-color:#f60}button.disabled.success,button[disabled].success,.button.disabled.success,.button[disabled].success{background-color:#20ba44;border-color:#1a9536;color:#fff;cursor:default;opacity:0.7;-webkit-box-shadow:none;box-shadow:none}button.disabled.success:hover,button.disabled.success:focus,button[disabled].success:hover,button[disabled].success:focus,.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{background-color:#1a9536}button.disabled.success:hover,button.disabled.success:focus,button[disabled].success:hover,button[disabled].success:focus,.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{color:#fff}button.disabled.success:hover,button.disabled.success:focus,button[disabled].success:hover,button[disabled].success:focus,.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{background-color:#20ba44}button.disabled.alert,button[disabled].alert,.button.disabled.alert,.button[disabled].alert{background-color:#c60f13;border-color:#9e0c0f;color:#fff;cursor:default;opacity:0.7;-webkit-box-shadow:none;box-shadow:none}button.disabled.alert:hover,button.disabled.alert:focus,button[disabled].alert:hover,button[disabled].alert:focus,.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{background-color:#9e0c0f}button.disabled.alert:hover,button.disabled.alert:focus,button[disabled].alert:hover,button[disabled].alert:focus,.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{color:#fff}button.disabled.alert:hover,button.disabled.alert:focus,button[disabled].alert:hover,button[disabled].alert:focus,.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{background-color:#c60f13}@media only screen and (min-width: 40.063em){button,.button{display:inline-block}}.button-group{list-style:none;margin:0;left:0;*zoom:1}.button-group:before,.button-group:after{content:" ";display:table}.button-group:after{clear:both}.button-group li{margin:0;float:left}.button-group li>button,.button-group li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group li:first-child button,.button-group li:first-child .button{border-left:0}.button-group li:first-child{margin-left:0}.button-group.radius>*>button,.button-group.radius>* .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.radius>*:first-child button,.button-group.radius>*:first-child .button{border-left:0}.button-group.radius>*:first-child,.button-group.radius>*:first-child>a,.button-group.radius>*:first-child>button,.button-group.radius>*:first-child>.button{-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}.button-group.radius>*:last-child,.button-group.radius>*:last-child>a,.button-group.radius>*:last-child>button,.button-group.radius>*:last-child>.button{-moz-border-radius-bottomright:3px;-moz-border-radius-topright:3px;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}.button-group.round>*>button,.button-group.round>* .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.round>*:first-child button,.button-group.round>*:first-child .button{border-left:0}.button-group.round>*:first-child,.button-group.round>*:first-child>a,.button-group.round>*:first-child>button,.button-group.round>*:first-child>.button{-moz-border-radius-bottomleft:1000px;-moz-border-radius-topleft:1000px;-webkit-border-bottom-left-radius:1000px;-webkit-border-top-left-radius:1000px;border-bottom-left-radius:1000px;border-top-left-radius:1000px}.button-group.round>*:last-child,.button-group.round>*:last-child>a,.button-group.round>*:last-child>button,.button-group.round>*:last-child>.button{-moz-border-radius-bottomright:1000px;-moz-border-radius-topright:1000px;-webkit-border-bottom-right-radius:1000px;-webkit-border-top-right-radius:1000px;border-bottom-right-radius:1000px;border-top-right-radius:1000px}.button-group.even-2 li{width:50%}.button-group.even-2 li>button,.button-group.even-2 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-2 li:first-child button,.button-group.even-2 li:first-child .button{border-left:0}.button-group.even-2 li button,.button-group.even-2 li .button{width:100%}.button-group.even-3 li{width:33.33333%}.button-group.even-3 li>button,.button-group.even-3 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-3 li:first-child button,.button-group.even-3 li:first-child .button{border-left:0}.button-group.even-3 li button,.button-group.even-3 li .button{width:100%}.button-group.even-4 li{width:25%}.button-group.even-4 li>button,.button-group.even-4 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-4 li:first-child button,.button-group.even-4 li:first-child .button{border-left:0}.button-group.even-4 li button,.button-group.even-4 li .button{width:100%}.button-group.even-5 li{width:20%}.button-group.even-5 li>button,.button-group.even-5 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-5 li:first-child button,.button-group.even-5 li:first-child .button{border-left:0}.button-group.even-5 li button,.button-group.even-5 li .button{width:100%}.button-group.even-6 li{width:16.66667%}.button-group.even-6 li>button,.button-group.even-6 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-6 li:first-child button,.button-group.even-6 li:first-child .button{border-left:0}.button-group.even-6 li button,.button-group.even-6 li .button{width:100%}.button-group.even-7 li{width:14.28571%}.button-group.even-7 li>button,.button-group.even-7 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-7 li:first-child button,.button-group.even-7 li:first-child .button{border-left:0}.button-group.even-7 li button,.button-group.even-7 li .button{width:100%}.button-group.even-8 li{width:12.5%}.button-group.even-8 li>button,.button-group.even-8 li .button{border-left:1px solid;border-color:rgba(255,255,255,0.5)}.button-group.even-8 li:first-child button,.button-group.even-8 li:first-child .button{border-left:0}.button-group.even-8 li button,.button-group.even-8 li .button{width:100%}.button-bar{*zoom:1}.button-bar:before,.button-bar:after{content:" ";display:table}.button-bar:after{clear:both}.button-bar .button-group{float:left;margin-right:0.625rem}.button-bar .button-group div{overflow:hidden}.panel{border-style:solid;border-width:1px;border-color:#d8d8d8;margin-bottom:1.25rem;padding:1.25rem;background:#f2f2f2}.panel>:first-child{margin-top:0}.panel>:last-child{margin-bottom:0}.panel h1,.panel h2,.panel h3,.panel h4,.panel h5,.panel h6,.panel p{color:#333}.panel h1,.panel h2,.panel h3,.panel h4,.panel h5,.panel h6{line-height:1;margin-bottom:0.625rem}.panel h1.subheader,.panel h2.subheader,.panel h3.subheader,.panel h4.subheader,.panel h5.subheader,.panel h6.subheader{line-height:1.4}.panel.callout{border-style:solid;border-width:1px;border-color:#b5f0ff;margin-bottom:1.25rem;padding:1.25rem;background:#ebfbff}.panel.callout>:first-child{margin-top:0}.panel.callout>:last-child{margin-bottom:0}.panel.callout h1,.panel.callout h2,.panel.callout h3,.panel.callout h4,.panel.callout h5,.panel.callout h6,.panel.callout p{color:#333}.panel.callout h1,.panel.callout h2,.panel.callout h3,.panel.callout h4,.panel.callout h5,.panel.callout h6{line-height:1;margin-bottom:0.625rem}.panel.callout h1.subheader,.panel.callout h2.subheader,.panel.callout h3.subheader,.panel.callout h4.subheader,.panel.callout h5.subheader,.panel.callout h6.subheader{line-height:1.4}.panel.callout a{color:#0086a9}.panel.radius{-webkit-border-radius:3px;border-radius:3px}.dropdown.button,button.dropdown{position:relative;padding-right:3.5625rem}.dropdown.button:before,button.dropdown:before{position:absolute;content:"";width:0;height:0;display:block;border-style:solid;border-color:#fff transparent transparent transparent;top:50%}.dropdown.button:before,button.dropdown:before{border-width:0.375rem;right:1.40625rem;margin-top:-0.15625rem}.dropdown.button:before,button.dropdown:before{border-color:#fff transparent transparent transparent}.dropdown.button.tiny,button.dropdown.tiny{padding-right:2.625rem}.dropdown.button.tiny:before,button.dropdown.tiny:before{border-width:0.375rem;right:1.125rem;margin-top:-0.125rem}.dropdown.button.tiny:before,button.dropdown.tiny:before{border-color:#fff transparent transparent transparent}.dropdown.button.small,button.dropdown.small{padding-right:3.0625rem}.dropdown.button.small:before,button.dropdown.small:before{border-width:0.4375rem;right:1.3125rem;margin-top:-0.15625rem}.dropdown.button.small:before,button.dropdown.small:before{border-color:#fff transparent transparent transparent}.dropdown.button.large,button.dropdown.large{padding-right:3.625rem}.dropdown.button.large:before,button.dropdown.large:before{border-width:0.3125rem;right:1.71875rem;margin-top:-0.15625rem}.dropdown.button.large:before,button.dropdown.large:before{border-color:#fff transparent transparent transparent}.dropdown.button.secondary:before,button.dropdown.secondary:before{border-color:#333 transparent transparent transparent}.th{line-height:0;display:inline-block;border:solid 4px #fff;max-width:100%;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.2);box-shadow:0 0 0 1px rgba(0,0,0,0.2);-webkit-transition:all 200ms ease-out;-moz-transition:all 200ms ease-out;transition:all 200ms ease-out}.th:hover,.th:focus{-webkit-box-shadow:0 0 6px 1px rgba(0,134,169,0.5);box-shadow:0 0 6px 1px rgba(0,134,169,0.5)}.th.radius{-webkit-border-radius:3px;border-radius:3px}.pricing-table{border:solid 1px #ddd;margin-left:0;margin-bottom:1.25rem}.pricing-table *{list-style:none;line-height:1}.pricing-table .title{background-color:#333;padding:0.9375rem 1.25rem;text-align:center;color:#eee;font-weight:normal;font-size:1rem;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif}.pricing-table .price{background-color:#f6f6f6;padding:0.9375rem 1.25rem;text-align:center;color:#333;font-weight:normal;font-size:2rem;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif}.pricing-table .description{background-color:#fff;padding:0.9375rem;text-align:center;color:#777;font-size:0.75rem;font-weight:normal;line-height:1.4;border-bottom:dotted 1px #ddd}.pricing-table .bullet-item{background-color:#fff;padding:0.9375rem;text-align:center;color:#333;font-size:0.875rem;font-weight:normal;border-bottom:dotted 1px #ddd}.pricing-table .cta-button{background-color:#fff;text-align:center;padding:1.25rem 1.25rem 0}@-webkit-keyframes rotate{from{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotate{from{-moz-transform:rotate(0deg)}to{-moz-transform:rotate(360deg)}}@-o-keyframes rotate{from{-o-transform:rotate(0deg)}to{-o-transform:rotate(360deg)}}@keyframes rotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.slideshow-wrapper{position:relative}.slideshow-wrapper ul{list-style-type:none;margin:0}.slideshow-wrapper ul li,.slideshow-wrapper ul li .orbit-caption{display:none}.slideshow-wrapper ul li:first-child{display:block}.slideshow-wrapper .orbit-container{background-color:transparent}.slideshow-wrapper .orbit-container li{display:block}.slideshow-wrapper .orbit-container li .orbit-caption{display:block}.preloader{display:block;width:40px;height:40px;position:absolute;top:50%;left:50%;margin-top:-20px;margin-left:-20px;border:solid 3px;border-color:#555 #fff;-webkit-border-radius:1000px;border-radius:1000px;-webkit-animation-name:rotate;-webkit-animation-duration:1.5s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:rotate;-moz-animation-duration:1.5s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;-o-animation-name:rotate;-o-animation-duration:1.5s;-o-animation-iteration-count:infinite;-o-animation-timing-function:linear;animation-name:rotate;animation-duration:1.5s;animation-iteration-count:infinite;animation-timing-function:linear}.orbit-container{overflow:hidden;width:100%;position:relative;background:none}.orbit-container .orbit-slides-container{list-style:none;margin:0;padding:0;position:relative;-webkit-transform:translateZ(0)}.orbit-container .orbit-slides-container img{display:block;max-width:100%}.orbit-container .orbit-slides-container>*{position:absolute;top:0;width:100%;margin-left:100%}.orbit-container .orbit-slides-container>*:first-child{margin-left:0%}.orbit-container .orbit-slides-container>* .orbit-caption{position:absolute;bottom:0;background-color:rgba(51,51,51,0.8);color:#fff;width:100%;padding:0.625rem 0.875rem;font-size:0.875rem}.orbit-container .orbit-slide-number{position:absolute;top:10px;left:10px;font-size:12px;color:#fff;background:rgba(0,0,0,0);z-index:10}.orbit-container .orbit-slide-number span{font-weight:700;padding:0.3125rem}.orbit-container .orbit-timer{position:absolute;top:12px;right:10px;height:6px;width:100px;z-index:10}.orbit-container .orbit-timer .orbit-progress{height:3px;background-color:rgba(255,255,255,0.3);display:block;width:0%;position:relative;right:20px;top:5px}.orbit-container .orbit-timer>span{display:none;position:absolute;top:0px;right:0;width:11px;height:14px;border:solid 4px #fff;border-top:none;border-bottom:none}.orbit-container .orbit-timer.paused>span{right:-4px;top:0px;width:11px;height:14px;border:inset 8px;border-right-style:solid;border-color:transparent transparent transparent #fff}.orbit-container .orbit-timer.paused>span.dark{border-color:transparent transparent transparent #333}.orbit-container:hover .orbit-timer>span{display:block}.orbit-container .orbit-prev,.orbit-container .orbit-next{position:absolute;top:45%;margin-top:-25px;width:36px;height:60px;line-height:50px;color:white;background-color:none;text-indent:-9999px !important;z-index:10}.orbit-container .orbit-prev:hover,.orbit-container .orbit-next:hover{background-color:rgba(0,0,0,0.3)}.orbit-container .orbit-prev>span,.orbit-container .orbit-next>span{position:absolute;top:50%;margin-top:-10px;display:block;width:0;height:0;border:inset 10px}.orbit-container .orbit-prev{left:0}.orbit-container .orbit-prev>span{border-right-style:solid;border-color:transparent;border-right-color:#fff}.orbit-container .orbit-prev:hover>span{border-right-color:#fff}.orbit-container .orbit-next{right:0}.orbit-container .orbit-next>span{border-color:transparent;border-left-style:solid;border-left-color:#fff;left:50%;margin-left:-4px}.orbit-container .orbit-next:hover>span{border-left-color:#fff}.orbit-bullets-container{text-align:center}.orbit-bullets{margin:0 auto 30px auto;overflow:hidden;position:relative;top:10px;float:none;text-align:center;display:block}.orbit-bullets li{display:inline-block;width:0.5625rem;height:0.5625rem;background:#ccc;float:none;margin-right:6px;-webkit-border-radius:1000px;border-radius:1000px}.orbit-bullets li.active{background:#999}.orbit-bullets li:last-child{margin-right:0}.touch .orbit-container .orbit-prev,.touch .orbit-container .orbit-next{display:none}.touch .orbit-bullets{display:none}@media only screen and (min-width: 40.063em){.touch .orbit-container .orbit-prev,.touch .orbit-container .orbit-next{display:inherit}.touch .orbit-bullets{display:block}}@media only screen and (max-width: 40em){.orbit-stack-on-small .orbit-slides-container{height:auto !important}.orbit-stack-on-small .orbit-slides-container>*{position:relative;margin-left:0% !important}.orbit-stack-on-small .orbit-timer,.orbit-stack-on-small .orbit-next,.orbit-stack-on-small .orbit-prev,.orbit-stack-on-small .orbit-bullets{display:none}}[data-magellan-expedition]{background:#fff;z-index:50;min-width:100%;padding:10px}[data-magellan-expedition] .sub-nav{margin-bottom:0}[data-magellan-expedition] .sub-nav dd{margin-bottom:0}[data-magellan-expedition] .sub-nav a{line-height:1.8em}.tabs{*zoom:1;margin-bottom:0 !important}.tabs:before,.tabs:after{content:" ";display:table}.tabs:after{clear:both}.tabs dd{position:relative;margin-bottom:0 !important;top:1px;float:left}.tabs dd>a{display:block;background:#efefef;color:#222;padding-top:1rem;padding-right:2rem;padding-bottom:1.0625rem;padding-left:2rem;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-size:1rem}.tabs dd>a:hover{background:#e1e1e1}.tabs dd.active a{background:#fff}.tabs.radius dd:first-child a{-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}.tabs.radius dd:last-child a{-moz-border-radius-bottomright:3px;-moz-border-radius-topright:3px;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}.tabs.vertical dd{position:inherit;float:none;display:block;top:auto}.tabs-content{*zoom:1;margin-bottom:1.5rem;width:100%}.tabs-content:before,.tabs-content:after{content:" ";display:table}.tabs-content:after{clear:both}.tabs-content>.content{display:none;float:left;padding:0.9375em 0;width:100%}.tabs-content>.content.active{display:block}.tabs-content>.content.contained{padding:0.9375em}.tabs-content.vertical{display:block}.tabs-content.vertical>.content{padding:0 0.9375em}@media only screen and (min-width: 40.063em){.tabs.vertical{width:20%;float:left;margin-bottom:1.25rem}.tabs-content.vertical{width:80%;float:left;margin-left:-1px}}.side-nav{display:block;margin:0;padding:0.875rem 0;list-style-type:none;list-style-position:inside;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif}.side-nav li{margin:0 0 0.4375rem 0;font-size:0.875rem}.side-nav li a:not(.button){display:block;color:#0086a9}.side-nav li a:not(.button):hover,.side-nav li a:not(.button):focus{color:#10ceff}.side-nav li.active>a:first-child:not(.button){color:#10ceff;font-weight:normal;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif}.side-nav li.divider{border-top:1px solid;height:0;padding:0;list-style:none;border-top-color:#fff}.accordion{*zoom:1;margin-bottom:0}.accordion:before,.accordion:after{content:" ";display:table}.accordion:after{clear:both}.accordion dd{display:block;margin-bottom:0 !important}.accordion dd.active a{background:#e8e8e8}.accordion dd>a{background:#efefef;color:#222;padding:1rem;display:block;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-size:1rem}.accordion dd>a:hover{background:#e3e3e3}.accordion .content{display:none;padding:0.9375em}.accordion .content.active{display:block;background:#fff}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}.text-justify{text-align:justify !important}@media only screen and (max-width: 40em){.small-only-text-left{text-align:left !important}.small-only-text-right{text-align:right !important}.small-only-text-center{text-align:center !important}.small-only-text-justify{text-align:justify !important}}@media only screen{.small-text-left{text-align:left !important}.small-text-right{text-align:right !important}.small-text-center{text-align:center !important}.small-text-justify{text-align:justify !important}}@media only screen and (min-width: 40.063em) and (max-width: 64em){.medium-only-text-left{text-align:left !important}.medium-only-text-right{text-align:right !important}.medium-only-text-center{text-align:center !important}.medium-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 40.063em){.medium-text-left{text-align:left !important}.medium-text-right{text-align:right !important}.medium-text-center{text-align:center !important}.medium-text-justify{text-align:justify !important}}@media only screen and (min-width: 64.063em) and (max-width: 90em){.large-only-text-left{text-align:left !important}.large-only-text-right{text-align:right !important}.large-only-text-center{text-align:center !important}.large-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 64.063em){.large-text-left{text-align:left !important}.large-text-right{text-align:right !important}.large-text-center{text-align:center !important}.large-text-justify{text-align:justify !important}}@media only screen and (min-width: 90.063em) and (max-width: 120em){.xlarge-only-text-left{text-align:left !important}.xlarge-only-text-right{text-align:right !important}.xlarge-only-text-center{text-align:center !important}.xlarge-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 90.063em){.xlarge-text-left{text-align:left !important}.xlarge-text-right{text-align:right !important}.xlarge-text-center{text-align:center !important}.xlarge-text-justify{text-align:justify !important}}@media only screen and (min-width: 120.063em) and (max-width: 99999999em){.xxlarge-only-text-left{text-align:left !important}.xxlarge-only-text-right{text-align:right !important}.xxlarge-only-text-center{text-align:center !important}.xxlarge-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 120.063em){.xxlarge-text-left{text-align:left !important}.xxlarge-text-right{text-align:right !important}.xxlarge-text-center{text-align:center !important}.xxlarge-text-justify{text-align:justify !important}}div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}a{color:#0086a9;text-decoration:none;line-height:inherit}a:hover,a:focus{color:#007391}a img{border:none}p{font-family:inherit;font-weight:normal;font-size:1rem;line-height:1.6;margin-bottom:1.25rem;text-rendering:optimizeLegibility}p.lead{font-size:1.21875rem;line-height:1.6}p aside{font-size:0.875rem;line-height:1.35;font-style:italic}h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-weight:normal;font-style:normal;color:#222;text-rendering:optimizeLegibility;margin-top:0.2rem;margin-bottom:0.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-size:60%;color:#6f6f6f;line-height:0}h1{font-size:2.125rem}h2{font-size:1.6875rem}h3{font-size:1.375rem}h4{font-size:1.125rem}h5{font-size:1.125rem}h6{font-size:1rem}.subheader{line-height:1.4;color:#6f6f6f;font-weight:normal;margin-top:0.2rem;margin-bottom:0.5rem}hr{border:solid #ddd;border-width:1px 0 0;clear:both;margin:1.25rem 0 1.1875rem;height:0}em,i{font-style:italic;line-height:inherit}strong,b{font-weight:bold;line-height:inherit}small{font-size:60%;line-height:inherit}code{font-family:Consolas,"Liberation Mono",Courier,monospace;font-weight:bold;color:#910b0e}ul,ol,dl{font-size:1rem;line-height:1.6;margin-bottom:1.25rem;list-style-position:outside;font-family:inherit}ul{margin-left:1.1rem}ul.no-bullet{margin-left:0}ul.no-bullet li ul,ul.no-bullet li ol{margin-left:1.25rem;margin-bottom:0;list-style:none}ul li ul,ul li ol{margin-left:1.25rem;margin-bottom:0}ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}ul.square{list-style-type:square;margin-left:1.1rem}ul.circle{list-style-type:circle;margin-left:1.1rem}ul.disc{list-style-type:disc;margin-left:1.1rem}ul.no-bullet{list-style:none}ol{margin-left:1.4rem}ol li ul,ol li ol{margin-left:1.25rem;margin-bottom:0}dl dt{margin-bottom:0.3rem;font-weight:bold}dl dd{margin-bottom:0.75rem}abbr,acronym{text-transform:uppercase;font-size:90%;color:#222;border-bottom:1px dotted #ddd;cursor:help}abbr{text-transform:none}blockquote{margin:0 0 1.25rem;padding:0.5625rem 1.25rem 0 1.1875rem;border-left:1px solid #ddd}blockquote cite{display:block;font-size:0.8125rem;color:#555}blockquote cite:before{content:"\2014 \0020"}blockquote cite a,blockquote cite a:visited{color:#555}blockquote,blockquote p{line-height:1.6;color:#6f6f6f}.vcard{display:inline-block;margin:0 0 1.25rem 0;border:1px solid #ddd;padding:0.625rem 0.75rem}.vcard li{margin:0;display:block}.vcard .fn{font-weight:bold;font-size:0.9375rem}.vevent .summary{font-weight:bold}.vevent abbr{cursor:default;text-decoration:none;font-weight:bold;border:none;padding:0 0.0625rem}@media only screen and (min-width: 40.063em){h1,h2,h3,h4,h5,h6{line-height:1.4}h1{font-size:2.75rem}h2{font-size:2.3125rem}h3{font-size:1.6875rem}h4{font-size:1.4375rem}}.print-only{display:none !important}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.hide-on-print{display:none !important}.print-only{display:block !important}.hide-for-print{display:none !important}.show-for-print{display:inherit !important}}.split.button{position:relative;padding-right:5.0625rem}.split.button span{display:block;height:100%;position:absolute;right:0;top:0;border-left:solid 1px}.split.button span:before{position:absolute;content:"";width:0;height:0;display:block;border-style:inset;top:50%;left:50%}.split.button span:active{background-color:rgba(0,0,0,0.1)}.split.button span{border-left-color:rgba(255,255,255,0.5)}.split.button span{width:3.09375rem}.split.button span:before{border-top-style:solid;border-width:0.375rem;top:48%;margin-left:-0.375rem}.split.button span:before{border-color:#fff transparent transparent transparent}.split.button.secondary span{border-left-color:rgba(255,255,255,0.5)}.split.button.secondary span:before{border-color:#fff transparent transparent transparent}.split.button.alert span{border-left-color:rgba(255,255,255,0.5)}.split.button.success span{border-left-color:rgba(255,255,255,0.5)}.split.button.tiny{padding-right:3.75rem}.split.button.tiny span{width:2.25rem}.split.button.tiny span:before{border-top-style:solid;border-width:0.375rem;top:48%;margin-left:-0.375rem}.split.button.small{padding-right:4.375rem}.split.button.small span{width:2.625rem}.split.button.small span:before{border-top-style:solid;border-width:0.4375rem;top:48%;margin-left:-0.375rem}.split.button.large{padding-right:5.5rem}.split.button.large span{width:3.4375rem}.split.button.large span:before{border-top-style:solid;border-width:0.3125rem;top:48%;margin-left:-0.375rem}.split.button.expand{padding-left:2rem}.split.button.secondary span:before{border-color:#333 transparent transparent transparent}.split.button.radius span{-moz-border-radius-bottomright:3px;-moz-border-radius-topright:3px;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}.split.button.round span{-moz-border-radius-bottomright:1000px;-moz-border-radius-topright:1000px;-webkit-border-bottom-right-radius:1000px;-webkit-border-top-right-radius:1000px;border-bottom-right-radius:1000px;border-top-right-radius:1000px}.reveal-modal-bg{position:fixed;height:100%;width:100%;background:#000;background:rgba(0,0,0,0.45);z-index:98;display:none;top:0;left:0}dialog,.reveal-modal{visibility:hidden;display:none;position:absolute;left:50%;z-index:99;height:auto;margin-left:-40%;width:80%;background-color:#fff;padding:1.25rem;border:solid 1px #666;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.4);box-shadow:0 0 10px rgba(0,0,0,0.4);top:6.25rem}dialog .column,dialog .columns,.reveal-modal .column,.reveal-modal .columns{min-width:0}dialog>:first-child,.reveal-modal>:first-child{margin-top:0}dialog>:last-child,.reveal-modal>:last-child{margin-bottom:0}dialog .close-reveal-modal,.reveal-modal .close-reveal-modal{font-size:1.375rem;line-height:1;position:absolute;top:0.5rem;right:0.6875rem;color:#aaa;font-weight:bold;cursor:pointer}dialog[open]{display:block;visibility:visible}@media only screen and (min-width: 40.063em){dialog,.reveal-modal{padding:1.875rem;top:6.25rem}dialog.tiny,.reveal-modal.tiny{margin-left:-15%;width:30%}dialog.small,.reveal-modal.small{margin-left:-20%;width:40%}dialog.medium,.reveal-modal.medium{margin-left:-30%;width:60%}dialog.large,.reveal-modal.large{margin-left:-35%;width:70%}dialog.xlarge,.reveal-modal.xlarge{margin-left:-47.5%;width:95%}}@media print{dialog,.reveal-modal{background:#fff !important}}.has-tip{border-bottom:dotted 1px #ccc;cursor:help;font-weight:bold;color:#333}.has-tip:hover,.has-tip:focus{border-bottom:dotted 1px #003c4c;color:#0086a9}.has-tip.tip-left,.has-tip.tip-right{float:none !important}.tooltip{display:none;position:absolute;z-index:999;font-weight:normal;font-size:0.875rem;line-height:1.3;padding:0.75rem;max-width:85%;left:50%;width:100%;color:#fff;background:#333}.tooltip>.nub{display:block;left:5px;position:absolute;width:0;height:0;border:solid 5px;border-color:transparent transparent #333 transparent;top:-10px}.tooltip.radius{-webkit-border-radius:3px;border-radius:3px}.tooltip.round{-webkit-border-radius:1000px;border-radius:1000px}.tooltip.round>.nub{left:2rem}.tooltip.opened{color:#0086a9 !important;border-bottom:dotted 1px #003c4c !important}.tap-to-close{display:block;font-size:0.625rem;color:#777;font-weight:normal}@media only screen and (min-width: 40.063em){.tooltip>.nub{border-color:transparent transparent #333 transparent;top:-10px}.tooltip.tip-top>.nub{border-color:#333 transparent transparent transparent;top:auto;bottom:-10px}.tooltip.tip-left,.tooltip.tip-right{float:none !important}.tooltip.tip-left>.nub{border-color:transparent transparent transparent #333;right:-10px;left:auto;top:50%;margin-top:-5px}.tooltip.tip-right>.nub{border-color:transparent #333 transparent transparent;right:auto;left:-10px;top:50%;margin-top:-5px}}.clearing-thumbs,[data-clearing]{*zoom:1;margin-bottom:0;margin-left:0;list-style:none}.clearing-thumbs:before,.clearing-thumbs:after,[data-clearing]:before,[data-clearing]:after{content:" ";display:table}.clearing-thumbs:after,[data-clearing]:after{clear:both}.clearing-thumbs li,[data-clearing] li{float:left;margin-right:10px}.clearing-thumbs[class*="block-grid-"] li,[data-clearing][class*="block-grid-"] li{margin-right:0}.clearing-blackout{background:#333;position:fixed;width:100%;height:100%;top:0;left:0;z-index:998}.clearing-blackout .clearing-close{display:block}.clearing-container{position:relative;z-index:998;height:100%;overflow:hidden;margin:0}.clearing-touch-label{position:absolute;top:50%;left:50%;color:#aaa;font-size:0.6em}.visible-img{height:95%;position:relative}.visible-img img{position:absolute;left:50%;top:50%;margin-left:-50%;max-height:100%;max-width:100%}.clearing-caption{color:#ccc;font-size:0.875em;line-height:1.3;margin-bottom:0;text-align:center;bottom:0;background:#333;width:100%;padding:10px 30px 20px;position:absolute;left:0}.clearing-close{z-index:999;padding-left:20px;padding-top:10px;font-size:30px;line-height:1;color:#ccc;display:none}.clearing-close:hover,.clearing-close:focus{color:#ccc}.clearing-assembled .clearing-container{height:100%}.clearing-assembled .clearing-container .carousel>ul{display:none}.clearing-feature li{display:none}.clearing-feature li.clearing-featured-img{display:block}@media only screen and (min-width: 40.063em){.clearing-main-prev,.clearing-main-next{position:absolute;height:100%;width:40px;top:0}.clearing-main-prev>span,.clearing-main-next>span{position:absolute;top:50%;display:block;width:0;height:0;border:solid 12px}.clearing-main-prev>span:hover,.clearing-main-next>span:hover{opacity:0.8}.clearing-main-prev{left:0}.clearing-main-prev>span{left:5px;border-color:transparent;border-right-color:#ccc}.clearing-main-next{right:0}.clearing-main-next>span{border-color:transparent;border-left-color:#ccc}.clearing-main-prev.disabled,.clearing-main-next.disabled{opacity:0.3}.clearing-assembled .clearing-container .carousel{background:rgba(51,51,51,0.8);height:120px;margin-top:10px;text-align:center}.clearing-assembled .clearing-container .carousel>ul{display:inline-block;z-index:999;height:100%;position:relative;float:none}.clearing-assembled .clearing-container .carousel>ul li{display:block;width:120px;min-height:inherit;float:left;overflow:hidden;margin-right:0;padding:0;position:relative;cursor:pointer;opacity:0.4}.clearing-assembled .clearing-container .carousel>ul li.fix-height img{height:100%;max-width:none}.clearing-assembled .clearing-container .carousel>ul li a.th{border:none;-webkit-box-shadow:none;box-shadow:none;display:block}.clearing-assembled .clearing-container .carousel>ul li img{cursor:pointer !important;width:100% !important}.clearing-assembled .clearing-container .carousel>ul li.visible{opacity:1}.clearing-assembled .clearing-container .carousel>ul li:hover{opacity:0.8}.clearing-assembled .clearing-container .visible-img{background:#333;overflow:hidden;height:85%}.clearing-close{position:absolute;top:10px;right:20px;padding-left:0;padding-top:0}}.progress{background-color:#f6f6f6;height:1.5625rem;border:1px solid #fff;padding:0.125rem;margin-bottom:0.625rem}.progress .meter{background:#0086a9;height:100%;display:block}.progress.secondary .meter{background:#f60;height:100%;display:block}.progress.success .meter{background:#20ba44;height:100%;display:block}.progress.alert .meter{background:#c60f13;height:100%;display:block}.progress.radius{-webkit-border-radius:3px;border-radius:3px}.progress.radius .meter{-webkit-border-radius:2px;border-radius:2px}.progress.round{-webkit-border-radius:1000px;border-radius:1000px}.progress.round .meter{-webkit-border-radius:999px;border-radius:999px}.sub-nav{display:block;width:auto;overflow:hidden;margin:-0.25rem 0 1.125rem;padding-top:0.25rem;margin-right:0;margin-left:-0.75rem}.sub-nav dt{text-transform:uppercase}.sub-nav dt,.sub-nav dd,.sub-nav li{float:left;display:inline;margin-left:1rem;margin-bottom:0.625rem;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;font-weight:normal;font-size:0.875rem;color:#999}.sub-nav dt a,.sub-nav dd a,.sub-nav li a{text-decoration:none;color:#999;padding:0.1875rem 1rem}.sub-nav dt a:hover,.sub-nav dd a:hover,.sub-nav li a:hover{color:#737373}.sub-nav dt.active a,.sub-nav dd.active a,.sub-nav li.active a{-webkit-border-radius:3px;border-radius:3px;font-weight:normal;background:#0086a9;padding:0.1875rem 1rem;cursor:default;color:#fff}.sub-nav dt.active a:hover,.sub-nav dd.active a:hover,.sub-nav li.active a:hover{background:#007391}.joyride-list{display:none}.joyride-tip-guide{display:none;position:absolute;background:#333;color:#fff;z-index:101;top:0;left:2.5%;font-family:inherit;font-weight:normal;width:95%}.lt-ie9 .joyride-tip-guide{max-width:800px;left:50%;margin-left:-400px}.joyride-content-wrapper{width:100%;padding:1.125rem 1.25rem 1.5rem}.joyride-content-wrapper .button{margin-bottom:0 !important}.joyride-tip-guide .joyride-nub{display:block;position:absolute;left:22px;width:0;height:0;border:10px solid #333}.joyride-tip-guide .joyride-nub.top{border-top-style:solid;border-color:#333;border-top-color:transparent !important;border-left-color:transparent !important;border-right-color:transparent !important;top:-20px}.joyride-tip-guide .joyride-nub.bottom{border-bottom-style:solid;border-color:#333 !important;border-bottom-color:transparent !important;border-left-color:transparent !important;border-right-color:transparent !important;bottom:-20px}.joyride-tip-guide .joyride-nub.right{right:-20px}.joyride-tip-guide .joyride-nub.left{left:-20px}.joyride-tip-guide h1,.joyride-tip-guide h2,.joyride-tip-guide h3,.joyride-tip-guide h4,.joyride-tip-guide h5,.joyride-tip-guide h6{line-height:1.25;margin:0;font-weight:bold;color:#fff}.joyride-tip-guide p{margin:0 0 1.125rem 0;font-size:0.875rem;line-height:1.3}.joyride-timer-indicator-wrap{width:50px;height:3px;border:solid 1px #555;position:absolute;right:1.0625rem;bottom:1rem}.joyride-timer-indicator{display:block;width:0;height:inherit;background:#666}.joyride-close-tip{position:absolute;right:12px;top:10px;color:#777 !important;text-decoration:none;font-size:24px;font-weight:normal;line-height:0.5 !important}.joyride-close-tip:hover,.joyride-close-tip:focus{color:#eee !important}.joyride-modal-bg{position:fixed;height:100%;width:100%;background:transparent;background:rgba(0,0,0,0.5);z-index:100;display:none;top:0;left:0;cursor:pointer}.joyride-expose-wrapper{background-color:#ffffff;position:absolute;border-radius:3px;z-index:102;-moz-box-shadow:0 0 30px #fff;-webkit-box-shadow:0 0 15px #fff;box-shadow:0 0 15px #fff}.joyride-expose-cover{background:transparent;border-radius:3px;position:absolute;z-index:9999;top:0;left:0}@media only screen and (min-width: 40.063em){.joyride-tip-guide{width:300px;left:inherit}.joyride-tip-guide .joyride-nub.bottom{border-color:#333 !important;border-bottom-color:transparent !important;border-left-color:transparent !important;border-right-color:transparent !important;bottom:-20px}.joyride-tip-guide .joyride-nub.right{border-color:#333 !important;border-top-color:transparent !important;border-right-color:transparent !important;border-bottom-color:transparent !important;top:22px;left:auto;right:-20px}.joyride-tip-guide .joyride-nub.left{border-color:#333 !important;border-top-color:transparent !important;border-left-color:transparent !important;border-bottom-color:transparent !important;top:22px;left:-20px;right:auto}}.label{font-weight:normal;font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif;text-align:center;text-decoration:none;line-height:1;white-space:nowrap;display:inline-block;position:relative;margin-bottom:inherit;padding:0.25rem 0.5rem 0.375rem;font-size:0.6875rem;background-color:#0086a9;color:#fff}.label.radius{-webkit-border-radius:3px;border-radius:3px}.label.round{-webkit-border-radius:1000px;border-radius:1000px}.label.alert{background-color:#c60f13;color:#fff}.label.success{background-color:#20ba44;color:#fff}.label.secondary{background-color:#f60;color:#fff}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}.text-justify{text-align:justify !important}@media only screen and (max-width: 40em){.small-only-text-left{text-align:left !important}.small-only-text-right{text-align:right !important}.small-only-text-center{text-align:center !important}.small-only-text-justify{text-align:justify !important}}@media only screen{.small-text-left{text-align:left !important}.small-text-right{text-align:right !important}.small-text-center{text-align:center !important}.small-text-justify{text-align:justify !important}}@media only screen and (min-width: 40.063em) and (max-width: 64em){.medium-only-text-left{text-align:left !important}.medium-only-text-right{text-align:right !important}.medium-only-text-center{text-align:center !important}.medium-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 40.063em){.medium-text-left{text-align:left !important}.medium-text-right{text-align:right !important}.medium-text-center{text-align:center !important}.medium-text-justify{text-align:justify !important}}@media only screen and (min-width: 64.063em) and (max-width: 90em){.large-only-text-left{text-align:left !important}.large-only-text-right{text-align:right !important}.large-only-text-center{text-align:center !important}.large-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 64.063em){.large-text-left{text-align:left !important}.large-text-right{text-align:right !important}.large-text-center{text-align:center !important}.large-text-justify{text-align:justify !important}}@media only screen and (min-width: 90.063em) and (max-width: 120em){.xlarge-only-text-left{text-align:left !important}.xlarge-only-text-right{text-align:right !important}.xlarge-only-text-center{text-align:center !important}.xlarge-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 90.063em){.xlarge-text-left{text-align:left !important}.xlarge-text-right{text-align:right !important}.xlarge-text-center{text-align:center !important}.xlarge-text-justify{text-align:justify !important}}@media only screen and (min-width: 120.063em) and (max-width: 99999999em){.xxlarge-only-text-left{text-align:left !important}.xxlarge-only-text-right{text-align:right !important}.xxlarge-only-text-center{text-align:center !important}.xxlarge-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 120.063em){.xxlarge-text-left{text-align:left !important}.xxlarge-text-right{text-align:right !important}.xxlarge-text-center{text-align:center !important}.xxlarge-text-justify{text-align:justify !important}}.off-canvas-wrap{-webkit-backface-visibility:hidden;position:relative;width:100%;overflow-x:hidden}.off-canvas-wrap.move-right,.off-canvas-wrap.move-left{height:100%}.inner-wrap{-webkit-backface-visibility:hidden;position:relative;width:100%;*zoom:1;-webkit-transition:-webkit-transform 500ms ease;-moz-transition:-moz-transform 500ms ease;-ms-transition:-ms-transform 500ms ease;-o-transition:-o-transform 500ms ease;transition:transform 500ms ease}.inner-wrap:before,.inner-wrap:after{content:" ";display:table}.inner-wrap:after{clear:both}nav.tab-bar{-webkit-backface-visibility:hidden;background:#333;color:#fff;height:2.8125rem;line-height:2.8125rem;position:relative}nav.tab-bar h1,nav.tab-bar h2,nav.tab-bar h3,nav.tab-bar h4,nav.tab-bar h5,nav.tab-bar h6{color:#fff;font-weight:bold;line-height:2.8125rem;margin:0}nav.tab-bar h1,nav.tab-bar h2,nav.tab-bar h3,nav.tab-bar h4{font-size:1.125rem}section.left-small{width:2.8125rem;height:2.8125rem;position:absolute;top:0;border-right:solid 1px #1a1a1a;box-shadow:1px 0 0 #4e4e4e;left:0}section.right-small{width:2.8125rem;height:2.8125rem;position:absolute;top:0;border-left:solid 1px #4e4e4e;box-shadow:-1px 0 0 #1a1a1a;right:0}section.tab-bar-section{padding:0 0.625rem;position:absolute;text-align:center;height:2.8125rem;top:0}@media only screen and (min-width: 40.063em){section.tab-bar-section{text-align:left}}section.tab-bar-section.left{left:0;right:2.8125rem}section.tab-bar-section.right{left:2.8125rem;right:0}section.tab-bar-section.middle{left:2.8125rem;right:2.8125rem}a.menu-icon{text-indent:2.1875rem;width:2.8125rem;height:2.8125rem;display:block;line-height:2.0625rem;padding:0;color:#fff;position:relative}a.menu-icon span{position:absolute;display:block;width:1rem;height:0;left:0.8125rem;top:0.3125rem;-webkit-box-shadow:1px 10px 1px 1px #fff,1px 16px 1px 1px #fff,1px 22px 1px 1px #fff;box-shadow:0 10px 0 1px #fff,0 16px 0 1px #fff,0 22px 0 1px #fff}a.menu-icon:hover span{-webkit-box-shadow:1px 10px 1px 1px #b3b3b3,1px 16px 1px 1px #b3b3b3,1px 22px 1px 1px #b3b3b3;box-shadow:0 10px 0 1px #b3b3b3,0 16px 0 1px #b3b3b3,0 22px 0 1px #b3b3b3}.left-off-canvas-menu{-webkit-backface-visibility:hidden;width:250px;top:0;bottom:0;position:absolute;overflow-y:auto;background:#333;z-index:1001;box-sizing:content-box;-webkit-transform:translate3d(-100%, 0, 0);-moz-transform:translate3d(-100%, 0, 0);-ms-transform:translate3d(-100%, 0, 0);-o-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.left-off-canvas-menu *{-webkit-backface-visibility:hidden}.right-off-canvas-menu{-webkit-backface-visibility:hidden;width:250px;top:0;bottom:0;position:absolute;overflow-y:auto;background:#333;z-index:1001;box-sizing:content-box;-webkit-transform:translate3d(100%, 0, 0);-moz-transform:translate3d(100%, 0, 0);-ms-transform:translate3d(100%, 0, 0);-o-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);right:0}ul.off-canvas-list{list-style-type:none;padding:0;margin:0}ul.off-canvas-list li label{padding:0.3rem 0.9375rem;color:#999;text-transform:uppercase;font-weight:bold;background:#444;border-top:1px solid #5e5e5e;border-bottom:none;margin:0}ul.off-canvas-list li a{display:block;padding:0.66667rem;color:rgba(255,255,255,0.7);border-bottom:1px solid #262626}.move-right>.inner-wrap{-webkit-transform:translate3d(250px, 0, 0);-moz-transform:translate3d(250px, 0, 0);-ms-transform:translate3d(250px, 0, 0);-o-transform:translate3d(250px, 0, 0);transform:translate3d(250px, 0, 0)}.move-right a.exit-off-canvas{-webkit-backface-visibility:hidden;transition:background 300ms ease;cursor:pointer;box-shadow:-4px 0 4px rgba(0,0,0,0.5),4px 0 4px rgba(0,0,0,0.5);display:block;position:absolute;background:rgba(255,255,255,0.2);top:0;bottom:0;left:0;right:0;z-index:1002;-webkit-tap-highlight-color:rgba(0,0,0,0)}@media only screen and (min-width: 40.063em){.move-right a.exit-off-canvas:hover{background:rgba(255,255,255,0.05)}}.move-left>.inner-wrap{-webkit-transform:translate3d(-250px, 0, 0);-moz-transform:translate3d(-250px, 0, 0);-ms-transform:translate3d(-250px, 0, 0);-o-transform:translate3d(-250px, 0, 0);transform:translate3d(-250px, 0, 0)}.move-left a.exit-off-canvas{-webkit-backface-visibility:hidden;transition:background 300ms ease;cursor:pointer;box-shadow:-4px 0 4px rgba(0,0,0,0.5),4px 0 4px rgba(0,0,0,0.5);display:block;position:absolute;background:rgba(255,255,255,0.2);top:0;bottom:0;left:0;right:0;z-index:1002;-webkit-tap-highlight-color:rgba(0,0,0,0)}@media only screen and (min-width: 40.063em){.move-left a.exit-off-canvas:hover{background:rgba(255,255,255,0.05)}}.csstransforms.no-csstransforms3d .left-off-canvas-menu{-webkit-transform:translate(-100%, 0);-moz-transform:translate(-100%, 0);-ms-transform:translate(-100%, 0);-o-transform:translate(-100%, 0);transform:translate(-100%, 0)}.csstransforms.no-csstransforms3d .right-off-canvas-menu{-webkit-transform:translate(100%, 0);-moz-transform:translate(100%, 0);-ms-transform:translate(100%, 0);-o-transform:translate(100%, 0);transform:translate(100%, 0)}.csstransforms.no-csstransforms3d .move-left>.inner-wrap{-webkit-transform:translate(-250px, 0);-moz-transform:translate(-250px, 0);-ms-transform:translate(-250px, 0);-o-transform:translate(-250px, 0);transform:translate(-250px, 0)}.csstransforms.no-csstransforms3d .move-right>.inner-wrap{-webkit-transform:translate(250px, 0);-moz-transform:translate(250px, 0);-ms-transform:translate(250px, 0);-o-transform:translate(250px, 0);transform:translate(250px, 0)}.no-csstransforms .left-off-canvas-menu{left:-250px}.no-csstransforms .right-off-canvas-menu{right:-250px}.no-csstransforms .move-left>.inner-wrap{right:250px}.no-csstransforms .move-right>.inner-wrap{left:250px}@media only screen and (max-width: 40em){.f-dropdown{max-width:100%;left:0}}.f-dropdown{position:absolute;left:-9999px;list-style:none;margin-left:0;width:100%;max-height:none;height:auto;background:#fff;border:solid 1px #ccc;font-size:16px;z-index:99;margin-top:2px;max-width:200px}.f-dropdown>*:first-child{margin-top:0}.f-dropdown>*:last-child{margin-bottom:0}.f-dropdown:before{content:"";display:block;width:0;height:0;border:inset 6px;border-color:transparent transparent #fff transparent;border-bottom-style:solid;position:absolute;top:-12px;left:10px;z-index:99}.f-dropdown:after{content:"";display:block;width:0;height:0;border:inset 7px;border-color:transparent transparent #ccc transparent;border-bottom-style:solid;position:absolute;top:-14px;left:9px;z-index:98}.f-dropdown.right:before{left:auto;right:10px}.f-dropdown.right:after{left:auto;right:9px}.f-dropdown li{font-size:0.875rem;cursor:pointer;line-height:1.125rem;margin:0}.f-dropdown li:hover,.f-dropdown li:focus{background:#eee}.f-dropdown li a{display:block;padding:0.5rem;color:#555}.f-dropdown.content{position:absolute;left:-9999px;list-style:none;margin-left:0;padding:1.25rem;width:100%;height:auto;max-height:none;background:#fff;border:solid 1px #ccc;font-size:16px;z-index:99;max-width:200px}.f-dropdown.content>*:first-child{margin-top:0}.f-dropdown.content>*:last-child{margin-bottom:0}.f-dropdown.tiny{max-width:200px}.f-dropdown.small{max-width:300px}.f-dropdown.medium{max-width:500px}.f-dropdown.large{max-width:800px}table{background:#fff;margin-bottom:1.25rem;border:solid 1px #ddd}table thead,table tfoot{background:#f5f5f5}table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:0.5rem 0.625rem 0.625rem;font-size:0.875rem;font-weight:bold;color:#222;text-align:left}table tr th,table tr td{padding:0.5625rem 0.625rem;font-size:0.875rem;color:#222}table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f9f9f9}table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.125rem}form{margin:0 0 1rem}form .row .row{margin:0 -0.5rem}form .row .row .column,form .row .row .columns{padding:0 0.5rem}form .row .row.collapse{margin:0}form .row .row.collapse .column,form .row .row.collapse .columns{padding:0}form .row .row.collapse input{-moz-border-radius-bottomright:0;-moz-border-radius-topright:0;-webkit-border-bottom-right-radius:0;-webkit-border-top-right-radius:0}form .row input.column,form .row input.columns,form .row textarea.column,form .row textarea.columns{padding-left:0.5rem}label{font-size:0.875rem;color:#4d4d4d;cursor:pointer;display:block;font-weight:normal;line-height:1.5;margin-bottom:0}label.right{float:none;text-align:right}label.inline{margin:0 0 1rem 0;padding:0.625rem 0}label small{text-transform:capitalize;color:#676767}select{-webkit-appearance:none !important;background:#fafafa url("data:image/svg+xml;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iM3B4IiB2aWV3Qm94PSIwIDAgNiAzIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2IDMiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIHBvaW50cz0iNS45OTIsMCAyLjk5MiwzIC0wLjAwOCwwICIvPjwvc3ZnPg==") no-repeat;background-position-x:97%;background-position-y:center;border:1px solid #ccc;padding:0.5rem;font-size:0.875rem;-webkit-border-radius:0;border-radius:0}select.radius{-webkit-border-radius:3px;border-radius:3px}select:hover{background:#f3f3f3 url("data:image/svg+xml;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iM3B4IiB2aWV3Qm94PSIwIDAgNiAzIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2IDMiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIHBvaW50cz0iNS45OTIsMCAyLjk5MiwzIC0wLjAwOCwwICIvPjwvc3ZnPg==") no-repeat;background-position-x:97%;background-position-y:center;border-color:#999}select::-ms-expand{display:none}@-moz-document url-prefix(){select{background:#fafafa}select:hover{background:#f3f3f3}}.prefix,.postfix{display:block;position:relative;z-index:2;text-align:center;width:100%;padding-top:0;padding-bottom:0;border-style:solid;border-width:1px;overflow:hidden;font-size:0.875rem;height:2.3125rem;line-height:2.3125rem}.postfix.button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;text-align:center;line-height:2.125rem;border:none}.prefix.button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;text-align:center;line-height:2.125rem;border:none}.prefix.button.radius{-webkit-border-radius:0;border-radius:0;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}.postfix.button.radius{-webkit-border-radius:0;border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-topright:3px;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}.prefix.button.round{-webkit-border-radius:0;border-radius:0;-moz-border-radius-bottomleft:1000px;-moz-border-radius-topleft:1000px;-webkit-border-bottom-left-radius:1000px;-webkit-border-top-left-radius:1000px;border-bottom-left-radius:1000px;border-top-left-radius:1000px}.postfix.button.round{-webkit-border-radius:0;border-radius:0;-moz-border-radius-bottomright:1000px;-moz-border-radius-topright:1000px;-webkit-border-bottom-right-radius:1000px;-webkit-border-top-right-radius:1000px;border-bottom-right-radius:1000px;border-top-right-radius:1000px}span.prefix,label.prefix{background:#f2f2f2;border-right:none;color:#333;border-color:#ccc}span.prefix.radius,label.prefix.radius{-webkit-border-radius:0;border-radius:0;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}span.postfix,label.postfix{background:#f2f2f2;border-left:none;color:#333;border-color:#ccc}span.postfix.radius,label.postfix.radius{-webkit-border-radius:0;border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-topright:3px;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}input[type="text"],input[type="password"],input[type="date"],input[type="datetime"],input[type="datetime-local"],input[type="month"],input[type="week"],input[type="email"],input[type="number"],input[type="search"],input[type="tel"],input[type="time"],input[type="url"],textarea{-webkit-appearance:none;background-color:#fff;font-family:inherit;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);color:rgba(0,0,0,0.75);display:block;font-size:0.875rem;margin:0 0 1rem 0;padding:0.5rem;height:2.3125rem;width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:-webkit-box-shadow 0.45s,border-color 0.45s ease-in-out;-moz-transition:-moz-box-shadow 0.45s,border-color 0.45s ease-in-out;transition:box-shadow 0.45s,border-color 0.45s ease-in-out}input[type="text"]:focus,input[type="password"]:focus,input[type="date"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="month"]:focus,input[type="week"]:focus,input[type="email"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="time"]:focus,input[type="url"]:focus,textarea:focus{-webkit-box-shadow:0 0 5px #999;-moz-box-shadow:0 0 5px #999;box-shadow:0 0 5px #999;border-color:#999}input[type="text"]:focus,input[type="password"]:focus,input[type="date"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="month"]:focus,input[type="week"]:focus,input[type="email"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="time"]:focus,input[type="url"]:focus,textarea:focus{background:#fafafa;border-color:#999;outline:none}input[type="text"][disabled],input[type="password"][disabled],input[type="date"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="month"][disabled],input[type="week"][disabled],input[type="email"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="time"][disabled],input[type="url"][disabled],textarea[disabled]{background-color:#ddd}input[type="text"].radius,input[type="password"].radius,input[type="date"].radius,input[type="datetime"].radius,input[type="datetime-local"].radius,input[type="month"].radius,input[type="week"].radius,input[type="email"].radius,input[type="number"].radius,input[type="search"].radius,input[type="tel"].radius,input[type="time"].radius,input[type="url"].radius,textarea.radius{-webkit-border-radius:3px;border-radius:3px}select{height:2.3125rem}input[type="file"],input[type="checkbox"],input[type="radio"],select{margin:0 0 1rem 0}input[type="checkbox"]+label,input[type="radio"]+label{display:inline-block;margin-left:0.5rem;margin-right:1rem;margin-bottom:0;vertical-align:baseline}input[type="file"]{width:100%}fieldset{border:solid 1px #ddd;padding:1.25rem;margin:1.125rem 0}fieldset legend{font-weight:bold;background:#fff;padding:0 0.1875rem;margin:0;margin-left:-0.1875rem}[data-abide] .error small.error,[data-abide] span.error,[data-abide] small.error{display:block;padding:0.375rem 0.5625rem 0.5625rem;margin-top:-1px;margin-bottom:1rem;font-size:0.75rem;font-weight:normal;font-style:italic;background:#c60f13;color:#fff}[data-abide] span.error,[data-abide] small.error{display:none}span.error,small.error{display:block;padding:0.375rem 0.5625rem 0.5625rem;margin-top:-1px;margin-bottom:1rem;font-size:0.75rem;font-weight:normal;font-style:italic;background:#c60f13;color:#fff}.error input,.error textarea,.error select{margin-bottom:0}.error input[type="checkbox"],.error input[type="radio"]{margin-bottom:1rem}.error label,.error label.error{color:#c60f13}.error small.error{display:block;padding:0.375rem 0.5625rem 0.5625rem;margin-top:-1px;margin-bottom:1rem;font-size:0.75rem;font-weight:normal;font-style:italic;background:#c60f13;color:#fff}.error>label>small{color:#676767;background:transparent;padding:0;text-transform:capitalize;font-style:normal;font-size:60%;margin:0;display:inline}.error span.error-message{display:block}input.error,textarea.error{margin-bottom:0}label.error{color:#c60f13}[class*="block-grid-"]{display:block;padding:0;margin:0 -0.625rem;*zoom:1}[class*="block-grid-"]:before,[class*="block-grid-"]:after{content:" ";display:table}[class*="block-grid-"]:after{clear:both}[class*="block-grid-"]>li{display:block;height:auto;float:left;padding:0 0.625rem 1.25rem}@media only screen{.small-block-grid-1>li{width:100%;list-style:none}.small-block-grid-1>li:nth-of-type(n){clear:none}.small-block-grid-1>li:nth-of-type(1n+1){clear:both}.small-block-grid-2>li{width:50%;list-style:none}.small-block-grid-2>li:nth-of-type(n){clear:none}.small-block-grid-2>li:nth-of-type(2n+1){clear:both}.small-block-grid-3>li{width:33.33333%;list-style:none}.small-block-grid-3>li:nth-of-type(n){clear:none}.small-block-grid-3>li:nth-of-type(3n+1){clear:both}.small-block-grid-4>li{width:25%;list-style:none}.small-block-grid-4>li:nth-of-type(n){clear:none}.small-block-grid-4>li:nth-of-type(4n+1){clear:both}.small-block-grid-5>li{width:20%;list-style:none}.small-block-grid-5>li:nth-of-type(n){clear:none}.small-block-grid-5>li:nth-of-type(5n+1){clear:both}.small-block-grid-6>li{width:16.66667%;list-style:none}.small-block-grid-6>li:nth-of-type(n){clear:none}.small-block-grid-6>li:nth-of-type(6n+1){clear:both}.small-block-grid-7>li{width:14.28571%;list-style:none}.small-block-grid-7>li:nth-of-type(n){clear:none}.small-block-grid-7>li:nth-of-type(7n+1){clear:both}.small-block-grid-8>li{width:12.5%;list-style:none}.small-block-grid-8>li:nth-of-type(n){clear:none}.small-block-grid-8>li:nth-of-type(8n+1){clear:both}.small-block-grid-9>li{width:11.11111%;list-style:none}.small-block-grid-9>li:nth-of-type(n){clear:none}.small-block-grid-9>li:nth-of-type(9n+1){clear:both}.small-block-grid-10>li{width:10%;list-style:none}.small-block-grid-10>li:nth-of-type(n){clear:none}.small-block-grid-10>li:nth-of-type(10n+1){clear:both}.small-block-grid-11>li{width:9.09091%;list-style:none}.small-block-grid-11>li:nth-of-type(n){clear:none}.small-block-grid-11>li:nth-of-type(11n+1){clear:both}.small-block-grid-12>li{width:8.33333%;list-style:none}.small-block-grid-12>li:nth-of-type(n){clear:none}.small-block-grid-12>li:nth-of-type(12n+1){clear:both}}@media only screen and (min-width: 40.063em){.medium-block-grid-1>li{width:100%;list-style:none}.medium-block-grid-1>li:nth-of-type(n){clear:none}.medium-block-grid-1>li:nth-of-type(1n+1){clear:both}.medium-block-grid-2>li{width:50%;list-style:none}.medium-block-grid-2>li:nth-of-type(n){clear:none}.medium-block-grid-2>li:nth-of-type(2n+1){clear:both}.medium-block-grid-3>li{width:33.33333%;list-style:none}.medium-block-grid-3>li:nth-of-type(n){clear:none}.medium-block-grid-3>li:nth-of-type(3n+1){clear:both}.medium-block-grid-4>li{width:25%;list-style:none}.medium-block-grid-4>li:nth-of-type(n){clear:none}.medium-block-grid-4>li:nth-of-type(4n+1){clear:both}.medium-block-grid-5>li{width:20%;list-style:none}.medium-block-grid-5>li:nth-of-type(n){clear:none}.medium-block-grid-5>li:nth-of-type(5n+1){clear:both}.medium-block-grid-6>li{width:16.66667%;list-style:none}.medium-block-grid-6>li:nth-of-type(n){clear:none}.medium-block-grid-6>li:nth-of-type(6n+1){clear:both}.medium-block-grid-7>li{width:14.28571%;list-style:none}.medium-block-grid-7>li:nth-of-type(n){clear:none}.medium-block-grid-7>li:nth-of-type(7n+1){clear:both}.medium-block-grid-8>li{width:12.5%;list-style:none}.medium-block-grid-8>li:nth-of-type(n){clear:none}.medium-block-grid-8>li:nth-of-type(8n+1){clear:both}.medium-block-grid-9>li{width:11.11111%;list-style:none}.medium-block-grid-9>li:nth-of-type(n){clear:none}.medium-block-grid-9>li:nth-of-type(9n+1){clear:both}.medium-block-grid-10>li{width:10%;list-style:none}.medium-block-grid-10>li:nth-of-type(n){clear:none}.medium-block-grid-10>li:nth-of-type(10n+1){clear:both}.medium-block-grid-11>li{width:9.09091%;list-style:none}.medium-block-grid-11>li:nth-of-type(n){clear:none}.medium-block-grid-11>li:nth-of-type(11n+1){clear:both}.medium-block-grid-12>li{width:8.33333%;list-style:none}.medium-block-grid-12>li:nth-of-type(n){clear:none}.medium-block-grid-12>li:nth-of-type(12n+1){clear:both}}@media only screen and (min-width: 64.063em){.large-block-grid-1>li{width:100%;list-style:none}.large-block-grid-1>li:nth-of-type(n){clear:none}.large-block-grid-1>li:nth-of-type(1n+1){clear:both}.large-block-grid-2>li{width:50%;list-style:none}.large-block-grid-2>li:nth-of-type(n){clear:none}.large-block-grid-2>li:nth-of-type(2n+1){clear:both}.large-block-grid-3>li{width:33.33333%;list-style:none}.large-block-grid-3>li:nth-of-type(n){clear:none}.large-block-grid-3>li:nth-of-type(3n+1){clear:both}.large-block-grid-4>li{width:25%;list-style:none}.large-block-grid-4>li:nth-of-type(n){clear:none}.large-block-grid-4>li:nth-of-type(4n+1){clear:both}.large-block-grid-5>li{width:20%;list-style:none}.large-block-grid-5>li:nth-of-type(n){clear:none}.large-block-grid-5>li:nth-of-type(5n+1){clear:both}.large-block-grid-6>li{width:16.66667%;list-style:none}.large-block-grid-6>li:nth-of-type(n){clear:none}.large-block-grid-6>li:nth-of-type(6n+1){clear:both}.large-block-grid-7>li{width:14.28571%;list-style:none}.large-block-grid-7>li:nth-of-type(n){clear:none}.large-block-grid-7>li:nth-of-type(7n+1){clear:both}.large-block-grid-8>li{width:12.5%;list-style:none}.large-block-grid-8>li:nth-of-type(n){clear:none}.large-block-grid-8>li:nth-of-type(8n+1){clear:both}.large-block-grid-9>li{width:11.11111%;list-style:none}.large-block-grid-9>li:nth-of-type(n){clear:none}.large-block-grid-9>li:nth-of-type(9n+1){clear:both}.large-block-grid-10>li{width:10%;list-style:none}.large-block-grid-10>li:nth-of-type(n){clear:none}.large-block-grid-10>li:nth-of-type(10n+1){clear:both}.large-block-grid-11>li{width:9.09091%;list-style:none}.large-block-grid-11>li:nth-of-type(n){clear:none}.large-block-grid-11>li:nth-of-type(11n+1){clear:both}.large-block-grid-12>li{width:8.33333%;list-style:none}.large-block-grid-12>li:nth-of-type(n){clear:none}.large-block-grid-12>li:nth-of-type(12n+1){clear:both}}.keystroke,kbd{background-color:#ededed;border-color:#ddd;color:#222;border-style:solid;border-width:1px;margin:0;font-family:"Consolas","Menlo","Courier",monospace;font-size:0.875rem;padding:0.125rem 0.25rem 0;-webkit-border-radius:3px;border-radius:3px}.show-for-small,.show-for-small-only,.show-for-medium-down,.show-for-large-down,.hide-for-medium,.hide-for-medium-up,.hide-for-medium-only,.hide-for-large,.hide-for-large-up,.hide-for-large-only,.hide-for-xlarge,.hide-for-xlarge-up,.hide-for-xlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge-only{display:inherit !important}.hide-for-small,.hide-for-small-only,.hide-for-medium-down,.show-for-medium,.show-for-medium-up,.show-for-medium-only,.hide-for-large-down,.show-for-large,.show-for-large-up,.show-for-large-only,.show-for-xlarge,.show-for-xlarge-up,.show-for-xlarge-only,.show-for-xxlarge-up,.show-for-xxlarge-only{display:none !important}table.show-for-small,table.show-for-small-only,table.show-for-medium-down,table.show-for-large-down,table.hide-for-medium,table.hide-for-medium-up,table.hide-for-medium-only,table.hide-for-large,table.hide-for-large-up,table.hide-for-large-only,table.hide-for-xlarge,table.hide-for-xlarge-up,table.hide-for-xlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge-only{display:table}thead.show-for-small,thead.show-for-small-only,thead.show-for-medium-down,thead.show-for-large-down,thead.hide-for-medium,thead.hide-for-medium-up,thead.hide-for-medium-only,thead.hide-for-large,thead.hide-for-large-up,thead.hide-for-large-only,thead.hide-for-xlarge,thead.hide-for-xlarge-up,thead.hide-for-xlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge-only{display:table-header-group !important}tbody.show-for-small,tbody.show-for-small-only,tbody.show-for-medium-down,tbody.show-for-large-down,tbody.hide-for-medium,tbody.hide-for-medium-up,tbody.hide-for-medium-only,tbody.hide-for-large,tbody.hide-for-large-up,tbody.hide-for-large-only,tbody.hide-for-xlarge,tbody.hide-for-xlarge-up,tbody.hide-for-xlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge-only{display:table-row-group !important}tr.show-for-small,tr.show-for-small-only,tr.show-for-medium-down,tr.show-for-large-down,tr.hide-for-medium,tr.hide-for-medium-up,tr.hide-for-medium-only,tr.hide-for-large,tr.hide-for-large-up,tr.hide-for-large-only,tr.hide-for-xlarge,tr.hide-for-xlarge-up,tr.hide-for-xlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge-only{display:table-row !important}td.show-for-small,td.show-for-small-only,td.show-for-medium-down,td.show-for-large-down,td.hide-for-medium,td.hide-for-medium-up,td.hide-for-large,td.hide-for-large-up,td.hide-for-xlarge,td.hide-for-xlarge-up,td.hide-for-xxlarge-up,th.show-for-small,th.show-for-small-only,th.show-for-medium-down,th.show-for-large-down,th.hide-for-medium,th.hide-for-medium-up,th.hide-for-large,th.hide-for-large-up,th.hide-for-xlarge,th.hide-for-xlarge-up,th.hide-for-xxlarge-up{display:table-cell !important}@media only screen and (min-width: 40.063em){.hide-for-small,.hide-for-small-only,.show-for-medium,.show-for-medium-down,.show-for-medium-up,.show-for-medium-only,.hide-for-large,.hide-for-large-up,.hide-for-large-only,.hide-for-xlarge,.hide-for-xlarge-up,.hide-for-xlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge-only{display:inherit !important}.show-for-small,.show-for-small-only,.hide-for-medium,.hide-for-medium-down,.hide-for-medium-up,.hide-for-medium-only,.hide-for-large-down,.show-for-large,.show-for-large-up,.show-for-large-only,.show-for-xlarge,.show-for-xlarge-up,.show-for-xlarge-only,.show-for-xxlarge-up,.show-for-xxlarge-only{display:none !important}table.hide-for-small,table.hide-for-small-only,table.show-for-medium,table.show-for-medium-down,table.show-for-medium-up,table.show-for-medium-only,table.hide-for-large,table.hide-for-large-up,table.hide-for-large-only,table.hide-for-xlarge,table.hide-for-xlarge-up,table.hide-for-xlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge-only{display:table}thead.hide-for-small,thead.hide-for-small-only,thead.show-for-medium,thead.show-for-medium-down,thead.show-for-medium-up,thead.show-for-medium-only,thead.hide-for-large,thead.hide-for-large-up,thead.hide-for-large-only,thead.hide-for-xlarge,thead.hide-for-xlarge-up,thead.hide-for-xlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge-only{display:table-header-group !important}tbody.hide-for-small,tbody.hide-for-small-only,tbody.show-for-medium,tbody.show-for-medium-down,tbody.show-for-medium-up,tbody.show-for-medium-only,tbody.hide-for-large,tbody.hide-for-large-up,tbody.hide-for-large-only,tbody.hide-for-xlarge,tbody.hide-for-xlarge-up,tbody.hide-for-xlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge-only{display:table-row-group !important}tr.hide-for-small,tr.hide-for-small-only,tr.show-for-medium,tr.show-for-medium-down,tr.show-for-medium-up,tr.show-for-medium-only,tr.hide-for-large,tr.hide-for-large-up,tr.hide-for-large-only,tr.hide-for-xlarge,tr.hide-for-xlarge-up,tr.hide-for-xlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge-only{display:table-row !important}td.hide-for-small,td.hide-for-small-only,td.show-for-medium,td.show-for-medium-down,td.show-for-medium-up,td.show-for-medium-only,td.hide-for-large,td.hide-for-large-up,td.hide-for-large-only,td.hide-for-xlarge,td.hide-for-xlarge-up,td.hide-for-xlarge-only,td.hide-for-xxlarge-up,td.hide-for-xxlarge-only,th.hide-for-small,th.hide-for-small-only,th.show-for-medium,th.show-for-medium-down,th.show-for-medium-up,th.show-for-medium-only,th.hide-for-large,th.hide-for-large-up,th.hide-for-large-only,th.hide-for-xlarge,th.hide-for-xlarge-up,th.hide-for-xlarge-only,th.hide-for-xxlarge-up,th.hide-for-xxlarge-only{display:table-cell !important}}@media only screen and (min-width: 64.063em){.hide-for-small,.hide-for-small-only,.hide-for-medium,.hide-for-medium-down,.hide-for-medium-only,.show-for-medium-up,.show-for-large,.show-for-large-up,.show-for-large-only,.hide-for-xlarge,.hide-for-xlarge-up,.hide-for-xlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge-only{display:inherit !important}.show-for-small-only,.show-for-medium,.show-for-medium-down,.show-for-medium-only,.hide-for-large,.hide-for-large-up,.hide-for-large-only,.show-for-xlarge,.show-for-xlarge-up,.show-for-xlarge-only,.show-for-xxlarge-up,.show-for-xxlarge-only{display:none !important}table.hide-for-small,table.hide-for-small-only,table.hide-for-medium,table.hide-for-medium-down,table.hide-for-medium-only,table.show-for-medium-up,table.show-for-large,table.show-for-large-up,table.show-for-large-only,table.hide-for-xlarge,table.hide-for-xlarge-up,table.hide-for-xlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge-only{display:table}thead.hide-for-small,thead.hide-for-small-only,thead.hide-for-medium,thead.hide-for-medium-down,thead.hide-for-medium-only,thead.show-for-medium-up,thead.show-for-large,thead.show-for-large-up,thead.show-for-large-only,thead.hide-for-xlarge,thead.hide-for-xlarge-up,thead.hide-for-xlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge-only{display:table-header-group !important}tbody.hide-for-small,tbody.hide-for-small-only,tbody.hide-for-medium,tbody.hide-for-medium-down,tbody.hide-for-medium-only,tbody.show-for-medium-up,tbody.show-for-large,tbody.show-for-large-up,tbody.show-for-large-only,tbody.hide-for-xlarge,tbody.hide-for-xlarge-up,tbody.hide-for-xlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge-only{display:table-row-group !important}tr.hide-for-small,tr.hide-for-small-only,tr.hide-for-medium,tr.hide-for-medium-down,tr.hide-for-medium-only,tr.show-for-medium-up,tr.show-for-large,tr.show-for-large-up,tr.show-for-large-only,tr.hide-for-xlarge,tr.hide-for-xlarge-up,tr.hide-for-xlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge-only{display:table-row !important}td.hide-for-small,td.hide-for-small-only,td.hide-for-medium,td.hide-for-medium-down,td.hide-for-medium-only,td.show-for-medium-up,td.show-for-large,td.show-for-large-up,td.show-for-large-only,td.hide-for-xlarge,td.hide-for-xlarge-up,td.hide-for-xlarge-only,td.hide-for-xxlarge-up,td.hide-for-xxlarge-only,th.hide-for-small,th.hide-for-small-only,th.hide-for-medium,th.hide-for-medium-down,th.hide-for-medium-only,th.show-for-medium-up,th.show-for-large,th.show-for-large-up,th.show-for-large-only,th.hide-for-xlarge,th.hide-for-xlarge-up,th.hide-for-xlarge-only,th.hide-for-xxlarge-up,th.hide-for-xxlarge-only{display:table-cell !important}}@media only screen and (min-width: 90.063em){.hide-for-small,.hide-for-small-only,.hide-for-medium,.hide-for-medium-down,.hide-for-medium-only,.show-for-medium-up,.show-for-large-up,.hide-for-large-only,.show-for-xlarge,.show-for-xlarge-up,.show-for-xlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge-only{display:inherit !important}.show-for-small-only,.show-for-medium,.show-for-medium-down,.show-for-medium-only,.show-for-large,.show-for-large-only,.show-for-large-down,.hide-for-xlarge,.hide-for-xlarge-up,.hide-for-xlarge-only,.show-for-xxlarge-up,.show-for-xxlarge-only{display:none !important}table.hide-for-small,table.hide-for-small-only,table.hide-for-medium,table.hide-for-medium-down,table.hide-for-medium-only,table.show-for-medium-up,table.show-for-large-up,table.hide-for-large-only,table.show-for-xlarge,table.show-for-xlarge-up,table.show-for-xlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge-only{display:table}thead.hide-for-small,thead.hide-for-small-only,thead.hide-for-medium,thead.hide-for-medium-down,thead.hide-for-medium-only,thead.show-for-medium-up,thead.show-for-large-up,thead.hide-for-large-only,thead.show-for-xlarge,thead.show-for-xlarge-up,thead.show-for-xlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge-only{display:table-header-group !important}tbody.hide-for-small,tbody.hide-for-small-only,tbody.hide-for-medium,tbody.hide-for-medium-down,tbody.hide-for-medium-only,tbody.show-for-medium-up,tbody.show-for-large-up,tbody.hide-for-large-only,tbody.show-for-xlarge,tbody.show-for-xlarge-up,tbody.show-for-xlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge-only{display:table-row-group !important}tr.hide-for-small,tr.hide-for-small-only,tr.hide-for-medium,tr.hide-for-medium-down,tr.hide-for-medium-only,tr.show-for-medium-up,tr.show-for-large-up,tr.hide-for-large-only,tr.show-for-xlarge,tr.show-for-xlarge-up,tr.show-for-xlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge-only{display:table-row !important}td.hide-for-small,td.hide-for-small-only,td.hide-for-medium,td.hide-for-medium-down,td.hide-for-medium-only,td.show-for-medium-up,td.show-for-large-up,td.hide-for-large-only,td.show-for-xlarge,td.show-for-xlarge-up,td.show-for-xlarge-only,td.hide-for-xxlarge-up,td.hide-for-xxlarge-only,th.hide-for-small,th.hide-for-small-only,th.hide-for-medium,th.hide-for-medium-down,th.hide-for-medium-only,th.show-for-medium-up,th.show-for-large-up,th.hide-for-large-only,th.show-for-xlarge,th.show-for-xlarge-up,th.show-for-xlarge-only,th.hide-for-xxlarge-up,th.hide-for-xxlarge-only{display:table-cell !important}}@media only screen and (min-width: 120.063em){.hide-for-small,.hide-for-small-only,.hide-for-medium,.hide-for-medium-down,.hide-for-medium-only,.show-for-medium-up,.show-for-large-up,.hide-for-large-only,.hide-for-xlarge-only,.show-for-xlarge-up,.show-for-xxlarge-up,.show-for-xxlarge-only{display:inherit !important}.show-for-small-only,.show-for-medium,.show-for-medium-down,.show-for-medium-only,.show-for-large,.show-for-large-only,.show-for-large-down,.hide-for-xlarge,.show-for-xlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge-only{display:none !important}table.hide-for-small,table.hide-for-small-only,table.hide-for-medium,table.hide-for-medium-down,table.hide-for-medium-only,table.show-for-medium-up,table.show-for-large-up,table.hide-for-xlarge-only,table.show-for-xlarge-up,table.show-for-xxlarge-up,table.show-for-xxlarge-only{display:table}thead.hide-for-small,thead.hide-for-small-only,thead.hide-for-medium,thead.hide-for-medium-down,thead.hide-for-medium-only,thead.show-for-medium-up,thead.show-for-large-up,thead.hide-for-xlarge-only,thead.show-for-xlarge-up,thead.show-for-xxlarge-up,thead.show-for-xxlarge-only{display:table-header-group !important}tbody.hide-for-small,tbody.hide-for-small-only,tbody.hide-for-medium,tbody.hide-for-medium-down,tbody.hide-for-medium-only,tbody.show-for-medium-up,tbody.show-for-large-up,tbody.hide-for-xlarge-only,tbody.show-for-xlarge-up,tbody.show-for-xxlarge-up,tbody.show-for-xxlarge-only{display:table-row-group !important}tr.hide-for-small,tr.hide-for-small-only,tr.hide-for-medium,tr.hide-for-medium-down,tr.hide-for-medium-only,tr.show-for-medium-up,tr.show-for-large-up,tr.hide-for-xlarge-only,tr.show-for-xlarge-up,tr.show-for-xxlarge-up,tr.show-for-xxlarge-only{display:table-row !important}td.hide-for-small,td.hide-for-small-only,td.hide-for-medium,td.hide-for-medium-down,td.hide-for-medium-only,td.show-for-medium-up,td.show-for-large-up,td.hide-for-xlarge-only,td.show-for-xlarge-up,td.show-for-xxlarge-up,td.show-for-xxlarge-only,th.hide-for-small,th.hide-for-small-only,th.hide-for-medium,th.hide-for-medium-down,th.hide-for-medium-only,th.show-for-medium-up,th.show-for-large-up,th.hide-for-xlarge-only,th.show-for-xlarge-up,th.show-for-xxlarge-up,th.show-for-xxlarge-only{display:table-cell !important}}.show-for-landscape,.hide-for-portrait{display:inherit !important}.hide-for-landscape,.show-for-portrait{display:none !important}table.hide-for-landscape,table.show-for-portrait{display:table}thead.hide-for-landscape,thead.show-for-portrait{display:table-header-group !important}tbody.hide-for-landscape,tbody.show-for-portrait{display:table-row-group !important}tr.hide-for-landscape,tr.show-for-portrait{display:table-row !important}td.hide-for-landscape,td.show-for-portrait,th.hide-for-landscape,th.show-for-portrait{display:table-cell !important}@media only screen and (orientation: landscape){.show-for-landscape,.hide-for-portrait{display:inherit !important}.hide-for-landscape,.show-for-portrait{display:none !important}table.show-for-landscape,table.hide-for-portrait{display:table}thead.show-for-landscape,thead.hide-for-portrait{display:table-header-group !important}tbody.show-for-landscape,tbody.hide-for-portrait{display:table-row-group !important}tr.show-for-landscape,tr.hide-for-portrait{display:table-row !important}td.show-for-landscape,td.hide-for-portrait,th.show-for-landscape,th.hide-for-portrait{display:table-cell !important}}@media only screen and (orientation: portrait){.show-for-portrait,.hide-for-landscape{display:inherit !important}.hide-for-portrait,.show-for-landscape{display:none !important}table.show-for-portrait,table.hide-for-landscape{display:table}thead.show-for-portrait,thead.hide-for-landscape{display:table-header-group !important}tbody.show-for-portrait,tbody.hide-for-landscape{display:table-row-group !important}tr.show-for-portrait,tr.hide-for-landscape{display:table-row !important}td.show-for-portrait,td.hide-for-landscape,th.show-for-portrait,th.hide-for-landscape{display:table-cell !important}}.show-for-touch{display:none !important}.hide-for-touch{display:inherit !important}.touch .show-for-touch{display:inherit !important}.touch .hide-for-touch{display:none !important}table.hide-for-touch{display:table}.touch table.show-for-touch{display:table}thead.hide-for-touch{display:table-header-group !important}.touch thead.show-for-touch{display:table-header-group !important}tbody.hide-for-touch{display:table-row-group !important}.touch tbody.show-for-touch{display:table-row-group !important}tr.hide-for-touch{display:table-row !important}.touch tr.show-for-touch{display:table-row !important}td.hide-for-touch{display:table-cell !important}.touch td.show-for-touch{display:table-cell !important}th.hide-for-touch{display:table-cell !important}.touch th.show-for-touch{display:table-cell !important} diff --git a/coin/static/css/local.css b/coin/static/css/local.css index a491c8b3140535fd9d33c8e3263a49b87b6276a5..33438089cd4cd9a1af660f779cb112fb362c4a5b 100644 --- a/coin/static/css/local.css +++ b/coin/static/css/local.css @@ -1,228 +1,188 @@ -/* Titre général */ +body { + font-family: "DejaVu Sans",Verdana,Geneva,sans-serif !important; +} + +/* Main */ -header { - user-select: none; - /* Navigateurs */ - -moz-user-select: none; - -webkit-user-select: none; +#main { + padding: 3em; + padding-bottom: 1em; + min-height: 80vh; } -h1 { - font-size: 2.2em; - margin-bottom: 1em; + +#content { + min-height: 70vh; } -h1 .default-logo:after { - content: "\\_o<"; - color: #FF6600; - font-weight: normal; - font-family: monospace; - text-align: center; - font-size: 1.25em; - display: block; - float: left; - width: 25%; + +/* Menu */ + +#menu { + background: #f8f8f8; + -webkit-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; } -h1 .default-logo:hover:after { - content: "\\_x<"; +#menu .menu-item .fa { + color: mediumseagreen; } -h1:hover:after { - position: absolute; - text-align: center; - z-index: -1; - right: 15%; - left: 25%; +#menu .menu-brand { + max-height: 100%; } -h1 a, h1:after { - color: #0086A9; - font-weight: bold; +#menu a { + color: #111; + text-decoration: none; } -h1 span.columns { - /* avoid having different margins because of h1 font-size */ - padding-left: 0.9375rem; - padding-right: 0.9375rem; +#menu a:hover { + text-decoration: none; } +#menu .menu-items ul { + list-style: none; + padding-left: 0; + margin: 0; + padding-bottom: 0.5em; + padding-top: 0.5em; +} -/* Barre de navigation */ +#menu .menu-items ul:not(:first-child) { + border-top: 1px solid #e7e7e7; +} -.side-nav { - background-color: #FAFAFA; - padding:5px; +#menu .menu-items ul li:hover { + background-color: #f0f0f0; + transition: all 0.3s; +} + +#menu .menu-items ul li a { + display: block; + padding-left: 2em; + padding-top: 10px; + padding-bottom: 10px; } -/* -nav#sidebox { - position: fixed; - z-index: 1; -} +@media (max-width: 900px) { -h3#nav { - background-color: #E8E8FF; - border: 1px solid #E0E0E0; - border-bottom-color: #0086A9; - padding-bottom: 0.25em; - text-indent: 0.25em; - margin-top: 0.25em; - padding-top: 0.1em; - margin-bottom: 0; - color: #FF6600; -}*/ -/* -.side-nav { - padding: 0; - padding-top: 0.75em; - background-color: #E8E8FF; - border: 1px solid #E0E0E0; - border-top: 0 none transparent; - margin-top: 0; -} + #menu { + width: 100%; + position: fixed; + z-index: 1000; + border-bottom: 1px solid #e7e7e7; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + } -.side-nav a { - padding: 0 0.5em 0.2em 0.5em; -} + #menu .menu-brand { + display: inline-block; + padding: 0.6em; + } -.side-nav a:hover, -.side-nav li.active a, -.side-nav li ul li a:hover { - background-color: #0086A9; - color: #FFFFFF !important; - border-radius: 5px; -} + #menu .menu-brand img { + display: none; + } -.side-nav li ul { - list-style-type: disc; - padding-top: 0.25em; -} + #menu .menu-brand h4 { + font-size: 1.2em; + margin-bottom: 0; + } -.side-nav li ul li a:hover { - margin-right: 1em; -} + #menu .menu-toggler { + border: 1px solid #ddd; + border-radius: 4px; + padding: 4px 6px; + position: relative; + background-color: white; + margin-right: 15px; + } -.side-nav li ul li a { - padding-left: 0.25em; - margin-left: -0.25em; -} + #menu .menu-toggler:hover { + background-color: #ddd; + } -.side-nav li.active li a { - background-color: transparent; - color: #0086A9 !important; -} -*/ -/* Titre section principale */ + #menu .menu-toggler .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; + background-color: #888; + } -h2:before { - /*content: url(../img/coinitem.png);*/ - margin-right: 0.25em; -} + #menu .menu-toggler .icon-bar + .icon-bar { + margin-top: 4px; + } -h2 { - color: #FF6600; - /*border-bottom: 2px solid #0086A9;*/ + #menu .menu-items { + flex-basis: 100%; + flex-grow: 1; + flex-direction: column; + } + + #main { + padding: 3em 0; + } } +@media (min-width: 900px) { + #menu { + min-width: 300px; + max-width: 300px; + border-right: 1px solid #e7e7e7; + } -/* panels */ -.panel {} -.panel > h2, -.panel > h3, -.panel > h4, -.panel > h5 { - border-bottom: 1px solid #d8d8d8; - margin-bottom: 1.25rem; - padding-bottom: 0.625rem; -} -.panel.callout > h2, -.panel.callout > h3, -.panel.callout > h4, -.panel.callout > h5 { - border-color: #B5F0FF; -} + #menu .menu-brand { + padding-top: 1.5em; + padding-bottom: 1.5em; + text-align: center; + } + #menu .menu-brand img { + max-width: 80%; + } -/* Tables */ -table.full-width { - width:100%; -} -table.no-border { - border: none; -} -table.no-background {} -table.no-background, -table.no-background thead, -table.no-background tfoot, -table.no-background tr { - background: transparent; -} -.faketable { - font-size: 0.9em; - background-color: #FFFFFF; - border: 1px solid #E0E0E0; - padding: 0.25em; -} -.hint { - font-size: 0.9em; - margin-top: -0.5em; + #menu .menu-toggler { + display: none; + } + + #menu .menu-items { + display: block; + } } +/* Form stuff */ -/* Specific table: Member personnal info */ -#personnal-info { - border-collapse: collapse; -} -#personnal-info td { - vertical-align: top; -} -#personnal-info tr:last-child td { - border-bottom: none; -} -#personnal-info tr td:first-child { - text-align: right; - color: #666; - font-weight: bold; -} -#personnal-info .email td { - /* email address can be reallllly long word */ - overflow-wrap: break-word; - word-wrap: break-word; - word-break: break-all; +.form-group.row label { + text-align: right; } -/* Specific table: mailling-list subscriptions */ -#mail-list-subscriptions .select-col { - min-width: 8rem; -} -#mail-list-subscriptions tr td select:last-child { - margin: 0; /* So that they line-up vertically */ - padding: 0; -} -#mail-list-subscriptions input[type=submit] { - min-width: 100%; -} +/* Login screen */ -/* login page */ -#login-form {} -#login-form table td { - vertical-align: middle; -} -#login-form table input { - margin-bottom: 0; -} -#login-form label { - font-size: 1.2em; +#login-row { + max-width: 600px; } -#password-reset-link { - margin-left: 1em; +#login-form { + max-width: 300px; } -/* New comers panel on login page */ -#newcomers { - margin-top: 3.9375rem; /* h1 margin top + bottom + font-size * line-height = 0.2rem + 0.5rem + 2.3125rem * 1.4 */ + +/* Table in cards */ + +.card-header { + font-size: 1.5rem; +} + +.card tr td:first-child { + width: 33%; + font-weight: bold; + text-align: right; + color: #666; } /* Footer */ @@ -234,243 +194,45 @@ table.no-background tr { opacity: 0.18; widht:100%; border-bottom: 1px solid black; + margin-top: -12px; } #footer .duck { opacity: 0.18; background-image: url('../img/coin.svg'); - background-size: auto 50%; + background-size: auto 100%; background-repeat: no-repeat; - background-position: center top; - height:50px; + background-position: center; + height:25px; } + .licence-sentence { opacity: 0.5; text-align: center; + margin-top: 3px; } -/* Invoices */ -#invoice_details .period { - color:#999; -} - -table.invoice-table tr.total>td { - font-weight:bold; - border-top:2px solid #DDD; -} - -table.invoice-table td.total { - width:100px; -} - -#member-invoices td.unpaid { - color:red; -} -#member-invoices tr.total>td.right { - text-align:right; -} - -#payment-howto {} - -/* Modifs pour les infos */ -td.center { - text-align: center; -} -span.italic { - font-style: italic; -} -/*.button { - border-radius: 2px; - padding: 0.2em 0.5em 0.4em 0.5em; - margin-bottom: auto; - font-size: 0.9em; -}*/ -.boolviewer input { - display: none; -} -.boolviewer input:checked+span:before { - color: #008800; - content: "✔ "; -} -.boolviewer input:not(:checked)+span:before { - color: #FF0000; - content: "✗ "; -} -.pass { - font-weight: bold; -} -.warning { - background-color: #FF7777; - border-radius: 5px; - font-style: italic; -} -.warning:before { - content: "⚠ "; - font-weight: bold; -} - -#graph h3 select { - display: inline; - background-color: transparent; - border: 0 none transparent; - font-family: inherit; - box-shadow: none; - font-size: 0.9em; - width: auto; - margin: 0; - padding: 0; -} -#graph h3 select option { - font-size: 0.6em; -} - -a.cfglink { - white-space: nowrap; -} - -tr.inactive { - opacity: 0.3; -} - -/* Champs éditables */ - -.flatform:before { - content: "Les champs marqués d'un ✎ sont éditables."; -} -.flatform .legend { - clear: both; -} - -.flatfield label { - background-color: #0086A9; - color: #F0F0F0; - font-size: 0.9em; - padding: 0.2em 0.5em; - white-space: nowrap; -} -.flatfield label:before { - content: "✎ "; - color: #E9E9E9; -} - -.flatfield input { - margin-bottom: 0; - border: 1px solid #E9E9E9; - background-color: transparent; - text-overflow: ellipsis; - padding-left: 1em; - box-shadow: none; - font-size: 1.1em; - color: #222222; - width: 90%; -} -.flatfield input::-moz-placeholder { - font-style: italic; -} -.flatfield input:-ms-input-placeholder { - font-style: italic; -} -.flatfield input::-webkit-input-placeholder { - font-style: italic; -} -.flatfield input:focus { - background-color: #FFFFFF; - border: 2px solid #C0C0C0; -} - -form .helptext { - position: relative; - top: -1em; - margin: 0em 1em 0em 1em; - font-style: italic; - font-size: small; -} +/* News feeds */ -/* Feeds */ .feed { font-size:80%; } + .feed .entry { margin-bottom:1em; } + .feed .entry .date { color:gray; font-size:80%; } -.legend .button, .formcontrol .button { - padding: 0.25em 0.5em; - border-radius:5px; - font-size: 0.9em; -} - -.nogap ul { - margin-bottom: 0; -} -.nogap ul li { - list-style-type: none; -} -.errored input { - border-color: #FF0000; - box-shadow: #FF7777 0 0 5px; -} -.formcontrol { - text-align: right; - margin-right: 1em; -} - -.message { - padding: 0.5em; - text-align: center; - margin: 1em 0; -} - -.message.success { - color: #FFFFFF; - background-color: #20BA44; -} - -.message.warning { - color: #620; - background-color: #FFAE00; - font-style: normal; - border-radius: 0; -} - -.message.error { - color: #B90202; - background-color: #FFBABA; -} - - -.eat-up { - margin-top: -1.5em; -} -.message.success:before { - content: "✔ "; -} - -.message.error:before { - content: "✘ "; -} +/* Tweaks for emails */ .dont-break-emails { word-break: keep-all; } -.nowrap { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* List filters links */ - -.list-filter { - text-align: right; -} - -/* Registration */ -.captcha { - display:none; +a.list-group-item { + color: #111; } diff --git a/coin/static/css/normalize.css b/coin/static/css/normalize.css deleted file mode 100644 index 332bc56987267f64fac7a94f5012d903cbf1efcf..0000000000000000000000000000000000000000 --- a/coin/static/css/normalize.css +++ /dev/null @@ -1,410 +0,0 @@ -/*! normalize.css v2.1.2 | MIT License | git.io/normalize */ - -/* ========================================================================== - HTML5 display definitions - ========================================================================== */ - -/** - * Correct `block` display not defined in IE 8/9. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} - -/** - * Correct `inline-block` display not defined in IE 8/9. - */ - -audio, -canvas, -video { - display: inline-block; -} - -/** - * 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. - * Hide the `template` element in IE, Safari, and Firefox < 22. - */ - -[hidden], -template { - display: none; -} - -script { - display: none !important; -} - -/* ========================================================================== - Base - ========================================================================== */ - -/** - * 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; -} - -/* ========================================================================== - Links - ========================================================================== */ - -/** - * Remove the gray background color from active links in IE 10. - */ - -a { - background: transparent; -} - -/** - * Address `outline` inconsistency between Chrome and other browsers. - */ - -a:focus { - outline: thin dotted; -} - -/** - * Improve readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* ========================================================================== - Typography - ========================================================================== */ - -/** - * Address variable `h1` font-size and margin within `section` and `article` - * contexts in Firefox 4+, Safari 5, and Chrome. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Address styling not present in IE 8/9, Safari 5, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/** - * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/** - * Address styling not present in Safari 5 and Chrome. - */ - -dfn { - font-style: italic; -} - -/** - * Address differences between Firefox and other browsers. - */ - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -/** - * Address styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - -/** - * Correct font family set oddly in Safari 5 and Chrome. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -/** - * Improve readability of pre-formatted text in all browsers. - */ - -pre { - white-space: pre-wrap; -} - -/** - * Set consistent quote types. - */ - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -/** - * 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. - */ - -img { - border: 0; -} - -/** - * Correct overflow displayed oddly in IE 9. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* ========================================================================== - Figures - ========================================================================== */ - -/** - * Address margin not present in IE 8/9 and Safari 5. - */ - -figure { - margin: 0; -} - -/* ========================================================================== - Forms - ========================================================================== */ - -/** - * 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. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Correct font family not being inherited in all browsers. - * 2. Correct font size not being inherited in all browsers. - * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. - */ - -button, -input, -select, -textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 2 */ - margin: 0; /* 3 */ -} - -/** - * Address Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -button, -input { - line-height: normal; -} - -/** - * 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 Chrome, Safari 5+, and IE 8+. - * Correct `select` style inheritance in Firefox 4+ and Opera. - */ - -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"], /* 1 */ -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; -} - -/** - * 1. Address box sizing set to `content-box` in IE 8/9. - * 2. Remove excess padding in IE 8/9. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} - -/** - * Remove inner padding and search cancel button in Safari 5 and Chrome - * on OS X. - */ - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * Remove inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/** - * 1. Remove default vertical scrollbar in IE 8/9. - * 2. Improve readability and alignment in all browsers. - */ - -textarea { - overflow: auto; /* 1 */ - vertical-align: top; /* 2 */ -} - -/* ========================================================================== - Tables - ========================================================================== */ - -/** - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -} diff --git a/coin/static/js/foundation.min.js b/coin/static/js/foundation.min.js deleted file mode 100644 index 4c0a673d4ebd7e7fdfa7c858a201a572579f9052..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Foundation Responsive Library - * http://foundation.zurb.com - * Copyright 2014, ZURB - * Free to use under the MIT license. - * http://www.opensource.org/licenses/mit-license.php -*/ -(function(e,t,n,r){"use strict";function l(e){if(typeof e=="string"||e instanceof String)e=e.replace(/^['\\/"]+|(;\s?})+|['\\/"]+$/g,"");return e}var i=function(t){var n=t.length;while(n--)e("head").has("."+t[n]).length===0&&e("head").append('')};i(["foundation-mq-small","foundation-mq-medium","foundation-mq-large","foundation-mq-xlarge","foundation-mq-xxlarge","foundation-data-attribute-namespace"]),e(function(){typeof FastClick!="undefined"&&typeof n.body!="undefined"&&FastClick.attach(n.body)});var s=function(t,r){if(typeof t=="string"){if(r){var i;return r.jquery?i=r[0]:i=r,e(i.querySelectorAll(t))}return e(n.querySelectorAll(t))}return e(t,r)},o=function(e){var t=[];return e||t.push("data"),this.namespace.length>0&&t.push(this.namespace),t.push(this.name),t.join("-")},i=function(t){var n=t.length;while(n--)e("head").has("."+t[n]).length===0&&e("head").append('')},u=function(e){var t=e.split("-"),n=t.length,r=[];while(n--)n!==0?r.push(t[n]):this.namespace.length>0?r.push(this.namespace,t[n]):r.push(t[n]);return r.reverse().join("-")},a=function(t,n){var r=this,i=!s(this).data(this.attr_name(!0));if(typeof t=="string")return this[t].call(this,n);s(this.scope).is("["+this.attr_name()+"]")?(s(this.scope).data(this.attr_name(!0)+"-init",e.extend({},this.settings,n||t,this.data_options(s(this.scope)))),i&&this.events(this.scope)):s("["+this.attr_name()+"]",this.scope).each(function(){var i=!s(this).data(r.attr_name(!0)+"-init");s(this).data(r.attr_name(!0)+"-init",e.extend({},r.settings,n||t,r.data_options(s(this)))),i&&r.events(this)})},f=function(e,t){function n(){t(e[0])}function r(){this.one("load",n);if(/MSIE (\d+\.\d+);/.test(navigator.userAgent)){var e=this.attr("src"),t=e.match(/\?/)?"&":"?";t+="random="+(new Date).getTime(),this.attr("src",e+t)}}if(!e.attr("src")){n();return}e[0].complete||e[0].readyState===4?n():r.call(e)};t.matchMedia=t.matchMedia||function(e,t){var n,r=e.documentElement,i=r.firstElementChild||r.firstChild,s=e.createElement("body"),o=e.createElement("div");return o.id="mq-test-1",o.style.cssText="position:absolute;top:-100em",s.style.background="none",s.appendChild(o),function(e){return o.innerHTML='­',r.insertBefore(s,i),n=o.offsetWidth===42,r.removeChild(s),{matches:n,media:e}}}(n),function(e){function u(){n&&(s(u),jQuery.fx.tick())}var n,r=0,i=["webkit","moz"],s=t.requestAnimationFrame,o=t.cancelAnimationFrame;for(;r").appendTo("head")[0].sheet,global:{namespace:""},init:function(e,t,n,r,i){var o,u=[e,n,r,i],a=[];this.rtl=/rtl/i.test(s("html").attr("dir")),this.scope=e||this.scope,this.set_namespace();if(t&&typeof t=="string"&&!/reflow/i.test(t))this.libs.hasOwnProperty(t)&&a.push(this.init_lib(t,u));else for(var f in this.libs)a.push(this.init_lib(f,t));return e},init_lib:function(e,t){return this.libs.hasOwnProperty(e)?(this.patch(this.libs[e]),t&&t.hasOwnProperty(e)?this.libs[e].init.apply(this.libs[e],[this.scope,t[e]]):(t=t instanceof Array?t:Array(t),this.libs[e].init.apply(this.libs[e],t))):function(){}},patch:function(e){e.scope=this.scope,e.namespace=this.global.namespace,e.rtl=this.rtl,e.data_options=this.utils.data_options,e.attr_name=o,e.add_namespace=u,e.bindings=a,e.S=this.utils.S},inherit:function(e,t){var n=t.split(" "),r=n.length;while(r--)this.utils.hasOwnProperty(n[r])&&(e[n[r]]=this.utils[n[r]])},set_namespace:function(){var t=e(".foundation-data-attribute-namespace").css("font-family");if(/false/i.test(t))return;this.global.namespace=t},libs:{},utils:{S:s,throttle:function(e,t){var n=null;return function(){var r=this,i=arguments;clearTimeout(n),n=setTimeout(function(){e.apply(r,i)},t)}},debounce:function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},data_options:function(t){function a(e){return!isNaN(e-0)&&e!==null&&e!==""&&e!==!1&&e!==!0}function f(t){return typeof t=="string"?e.trim(t):t}var n={},r,i,s,o=function(e){var t=Foundation.global.namespace;return t.length>0?e.data(t+"-options"):e.data("options")},u=o(t);if(typeof u=="object")return u;s=(u||":").split(";"),r=s.length;while(r--)i=s[r].split(":"),/true/i.test(i[1])&&(i[1]=!0),/false/i.test(i[1])&&(i[1]=!1),a(i[1])&&(i[1]=parseInt(i[1],10)),i.length===2&&i[0].length>0&&(n[f(i[0])]=f(i[1]));return n},register_media:function(t,n){Foundation.media_queries[t]===r&&(e("head").append(''),Foundation.media_queries[t]=l(e("."+n).css("font-family")))},add_custom_rule:function(e,t){if(t===r)Foundation.stylesheet.insertRule(e,Foundation.stylesheet.cssRules.length);else{var n=Foundation.media_queries[t];n!==r&&Foundation.stylesheet.insertRule("@media "+Foundation.media_queries[t]+"{ "+e+" }")}},image_loaded:function(e,t){var n=this,r=e.length;e.each(function(){f(n.S(this),function(){r-=1,r==0&&t(e)})})},random_str:function(e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");e||(e=Math.floor(Math.random()*t.length));var n="";while(e--)n+=t[Math.floor(Math.random()*t.length)];return n}}},e.fn.foundation=function(){var e=Array.prototype.slice.call(arguments,0);return this.each(function(){return Foundation.init.apply(Foundation,[this].concat(e)),this})}})(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.interchange={name:"interchange",version:"5.1.1",cache:{},images_loaded:!1,nodes_loaded:!1,settings:{load_attr:"interchange",named_queries:{"default":"only screen",small:Foundation.media_queries.small,medium:Foundation.media_queries.medium,large:Foundation.media_queries.large,xlarge:Foundation.media_queries.xlarge,xxlarge:Foundation.media_queries.xxlarge,landscape:"only screen and (orientation: landscape)",portrait:"only screen and (orientation: portrait)",retina:"only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min--moz-device-pixel-ratio: 2),only screen and (-o-min-device-pixel-ratio: 2/1),only screen and (min-device-pixel-ratio: 2),only screen and (min-resolution: 192dpi),only screen and (min-resolution: 2dppx)"},directives:{replace:function(t,n,r){if(/IMG/.test(t[0].nodeName)){var i=t[0].src;if((new RegExp(n,"i")).test(i))return;return t[0].src=n,r(t[0].src)}var s=t.data(this.data_attr+"-last-path");if(s==n)return;return e.get(n,function(e){t.html(e),t.data(this.data_attr+"-last-path",n),r()})}}},init:function(t,n,r){Foundation.inherit(this,"throttle random_str"),this.data_attr=this.set_data_attr(),e.extend(!0,this.settings,n,r),this.bindings(n,r),this.load("images"),this.load("nodes")},events:function(){var n=this;return e(t).off(".interchange").on("resize.fndtn.interchange",n.throttle(function(){n.resize()},50)),this},resize:function(){var t=this.cache;if(!this.images_loaded||!this.nodes_loaded){setTimeout(e.proxy(this.resize,this),50);return}for(var n in t)if(t.hasOwnProperty(n)){var r=this.results(n,t[n]);r&&this.settings.directives[r.scenario[1]].call(this,r.el,r.scenario[0],function(){if(arguments[0]instanceof Array)var e=arguments[0];else var e=Array.prototype.slice.call(arguments,0);r.el.trigger(r.scenario[1],e)})}},results:function(e,t){var n=t.length;if(n>0){var r=this.S("["+this.add_namespace("data-uuid")+'="'+e+'"]');while(n--){var i,s=t[n][2];this.settings.named_queries.hasOwnProperty(s)?i=matchMedia(this.settings.named_queries[s]):i=matchMedia(s);if(i.matches)return{el:r,scenario:t[n]}}}return!1},load:function(e,t){return(typeof this["cached_"+e]=="undefined"||t)&&this["update_"+e](),this["cached_"+e]},update_images:function(){var e=this.S("img["+this.data_attr+"]"),t=e.length,n=t,r=0,i=this.data_attr;this.cache={},this.cached_images=[],this.images_loaded=t===0;while(n--){r++;if(e[n]){var s=e[n].getAttribute(i)||"";s.length>0&&this.cached_images.push(e[n])}r===t&&(this.images_loaded=!0,this.enhance("images"))}return this},update_nodes:function(){var e=this.S("["+this.data_attr+"]").not("img"),t=e.length,n=t,r=0,i=this.data_attr;this.cached_nodes=[],this.nodes_loaded=t===0;while(n--){r++;var s=e[n].getAttribute(i)||"";s.length>0&&this.cached_nodes.push(e[n]),r===t&&(this.nodes_loaded=!0,this.enhance("nodes"))}return this},enhance:function(n){var r=this["cached_"+n].length;while(r--)this.object(e(this["cached_"+n][r]));return e(t).trigger("resize")},parse_params:function(e,t,n){return[this.trim(e),this.convert_directive(t),this.trim(n)]},convert_directive:function(e){var t=this.trim(e);return t.length>0?t:"replace"},object:function(e){var t=this.parse_data_attr(e),n=[],r=t.length;if(r>0)while(r--){var i=t[r].split(/\((.*?)(\))$/);if(i.length>1){var s=i[0].split(","),o=this.parse_params(s[0],s[1],i[1]);n.push(o)}}return this.store(e,n)},uuid:function(e){function r(){return n.random_str(6)}var t=e||"-",n=this;return r()+r()+t+r()+t+r()+t+r()+t+r()+r()+r()},store:function(e,t){var n=this.uuid(),r=e.data(this.add_namespace("uuid",!0));return this.cache[r]?this.cache[r]:(e.attr(this.add_namespace("data-uuid"),n),this.cache[n]=t)},trim:function(t){return typeof t=="string"?e.trim(t):t},set_data_attr:function(e){return e?this.namespace.length>0?this.namespace+"-"+this.settings.load_attr:this.settings.load_attr:this.namespace.length>0?"data-"+this.namespace+"-"+this.settings.load_attr:"data-"+this.settings.load_attr},parse_data_attr:function(e){var t=e.attr(this.attr_name()).split(/\[(.*?)\]/),n=t.length,r=[];while(n--)t[n].replace(/[\W\d]+/,"").length>4&&r.push(t[n]);return r},reflow:function(){this.load("images",!0),this.load("nodes",!0)}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.equalizer={name:"equalizer",version:"5.1.1",settings:{use_tallest:!0,before_height_change:e.noop,after_height_change:e.noop},init:function(e,t,n){this.bindings(t,n),this.reflow()},events:function(){this.S(t).off(".equalizer").on("resize.fndtn.equalizer",function(e){this.reflow()}.bind(this))},equalize:function(t){var n=!1,r=t.find("["+this.attr_name()+"-watch]"),i=r.first().offset().top,s=t.data(this.attr_name(!0)+"-init");if(r.length===0)return;s.before_height_change(),t.trigger("before-height-change"),r.height("inherit"),r.each(function(){var t=e(this);t.offset().top!==i&&(n=!0)});if(n)return;var o=r.map(function(){return e(this).outerHeight()});if(s.use_tallest){var u=Math.max.apply(null,o);r.height(u)}else{var a=Math.min.apply(null,o);r.height(a)}s.after_height_change(),t.trigger("after-height-change")},reflow:function(){var t=this;this.S("["+this.attr_name()+"]",this.scope).each(function(){t.equalize(e(this))})}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.abide={name:"abide",version:"5.1.1",settings:{live_validate:!0,focus_on_invalid:!0,error_labels:!0,timeout:1e3,patterns:{alpha:/^[a-zA-Z]+$/,alpha_numeric:/^[a-zA-Z0-9]+$/,integer:/^\d+$/,number:/-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/,password:/(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/,card:/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,cvv:/^([0-9]){3,4}$/,email:/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,url:/(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/,domain:/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/,datetime:/([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))/,date:/(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))/,time:/(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}/,dateISO:/\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,month_day_year:/(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/,color:/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/}},timer:null,init:function(e,t,n){this.bindings(t,n)},events:function(t){var n=this,r=n.S(t).attr("novalidate","novalidate"),i=r.data(this.attr_name(!0)+"-init");this.invalid_attr=this.add_namespace("data-invalid"),r.off(".abide").on("submit.fndtn.abide validate.fndtn.abide",function(e){var t=/ajax/i.test(n.S(this).attr(n.attr_name()));return n.validate(n.S(this).find("input, textarea, select").get(),e,t)}).on("reset",function(){return n.reset(e(this))}).find("input, textarea, select").off(".abide").on("blur.fndtn.abide change.fndtn.abide",function(e){n.validate([this],e)}).on("keydown.fndtn.abide",function(t){var r=e(this).closest("form").data("abide-init");r.live_validate===!0&&(clearTimeout(n.timer),n.timer=setTimeout(function(){n.validate([this],t)}.bind(this),r.timeout))})},reset:function(t){t.removeAttr(this.invalid_attr),e(this.invalid_attr,t).removeAttr(this.invalid_attr),e(".error",t).not("small").removeClass("error")},validate:function(e,t,n){var r=this.parse_patterns(e),i=r.length,s=this.S(e[0]).closest("form"),o=/submit/.test(t.type);for(var u=0;u0?[e,this.settings.patterns[r],n]:r.length>0?[e,new RegExp(r),n]:this.settings.patterns.hasOwnProperty(t)?[e,this.settings.patterns[t],n]:(r=/.*/,[e,r,n])},check_validation_and_apply_styles:function(t){var n=t.length,r=[];while(n--){var i=t[n][0],s=t[n][2],o=i.value,u=this.S(i).parent(),a=i.getAttribute(this.add_namespace("data-equalto")),f=i.type==="radio",l=i.type==="checkbox",c=this.S('label[for="'+i.getAttribute("id")+'"]'),h=s?i.value.length>0:!0,p;u.is("label")?p=u.parent():p=u,f&&s?r.push(this.valid_radio(i,s)):l&&s?r.push(this.valid_checkbox(i,s)):a&&s?r.push(this.valid_equal(i,s,p)):t[n][1].test(o)&&h||!s&&i.value.length<1?(this.S(i).removeAttr(this.invalid_attr),p.removeClass("error"),c.length>0&&this.settings.error_labels&&c.removeClass("error"),r.push(!0),e(i).triggerHandler("valid")):(this.S(i).attr(this.invalid_attr,""),p.addClass("error"),c.length>0&&this.settings.error_labels&&c.addClass("error"),r.push(!1),e(i).triggerHandler("invalid"))}return r},valid_checkbox:function(e,t){var e=this.S(e),n=e.is(":checked")||!t;return n?e.removeAttr(this.invalid_attr).parent().removeClass("error"):e.attr(this.invalid_attr,"").parent().addClass("error"),n},valid_radio:function(e,t){var r=e.getAttribute("name"),i=n.getElementsByName(r),s=i.length,o=!1;for(var u=0;u0&&(i(t.target).is("["+r.attr_name()+"-content]")||e.contains(n.first()[0],t.target))){t.stopPropagation();return}r.close.call(r,i("["+r.attr_name()+"-content]"))}).on("opened.fndtn.dropdown","["+r.attr_name()+"-content]",function(){r.settings.opened.call(this)}).on("closed.fndtn.dropdown","["+r.attr_name()+"-content]",function(){r.settings.closed.call(this)}),i(t).off(".dropdown").on("resize.fndtn.dropdown",r.throttle(function(){r.resize.call(r)},50)).trigger("resize")},close:function(e){var t=this;e.each(function(){t.S(this).hasClass(t.settings.active_class)&&(t.S(this).css(Foundation.rtl?"right":"left","-99999px").removeClass(t.settings.active_class),t.S(this).trigger("closed"))})},closeall:function(){var t=this;e.each(t.S("["+this.attr_name()+"-content]"),function(){t.close.call(t,t.S(this))})},open:function(e,t){this.css(e.addClass(this.settings.active_class),t),e.trigger("opened")},data_attr:function(){return this.namespace.length>0?this.namespace+"-"+this.name:this.name},toggle:function(e){var t=this.S("#"+e.data(this.data_attr()));if(t.length===0)return;this.close.call(this,this.S("["+this.attr_name()+"-content]").not(t)),t.hasClass(this.settings.active_class)?this.close.call(this,t):(this.close.call(this,this.S("["+this.attr_name()+"-content]")),this.open.call(this,t,e))},resize:function(){var e=this.S("["+this.attr_name()+"-content].open"),t=this.S("["+this.attr_name()+"='"+e.attr("id")+"']");e.length&&t.length&&this.css(e,t)},css:function(e,n){var r=e.offsetParent(),i=n.offset();i.top-=r.offset().top,i.left-=r.offset().left;if(this.small())e.css({position:"absolute",width:"95%","max-width":"none",top:i.top+n.outerHeight()}),e.css(Foundation.rtl?"right":"left","2.5%");else{if(!Foundation.rtl&&this.S(t).width()>e.outerWidth()+n.offset().left){var s=i.left;e.hasClass("right")&&e.removeClass("right")}else{e.hasClass("right")||e.addClass("right");var s=i.left-(e.outerWidth()-n.outerWidth())}e.attr("style","").css({position:"absolute",top:i.top+n.outerHeight(),left:s})}return e},small:function(){return matchMedia(Foundation.media_queries.small).matches&&!matchMedia(Foundation.media_queries.medium).matches},off:function(){this.S(this.scope).off(".fndtn.dropdown"),this.S("html, body").off(".fndtn.dropdown"),this.S(t).off(".fndtn.dropdown"),this.S("[data-dropdown-content]").off(".fndtn.dropdown"),this.settings.init=!1},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.alert={name:"alert",version:"5.1.1",settings:{animation:"fadeOut",speed:300,callback:function(){}},init:function(e,t,n){this.bindings(t,n)},events:function(){var t=this,n=this.S;e(this.scope).off(".alert").on("click.fndtn.alert","["+this.attr_name()+"] a.close",function(e){var r=n(this).closest("["+t.attr_name()+"]"),i=r.data(t.attr_name(!0)+"-init")||t.settings;e.preventDefault(),r[i.animation](i.speed,function(){n(this).trigger("closed").remove(),i.callback()})})},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs["magellan-expedition"]={name:"magellan-expedition",version:"5.1.1",settings:{active_class:"active",threshold:0,destination_threshold:20,throttle_delay:30},init:function(e,t,n){Foundation.inherit(this,"throttle"),this.bindings(t,n)},events:function(){var n=this,r=n.S,i=n.settings;n.set_expedition_position(),r(n.scope).off(".magellan").on("click.fndtn.magellan","["+n.add_namespace("data-magellan-arrival")+'] a[href^="#"]',function(r){r.preventDefault();var i=e(this).closest("["+n.attr_name()+"]"),s=i.data("magellan-expedition-init"),o=this.hash.split("#").join(""),u=e("a[name="+o+"]");u.length===0&&(u=e("#"+o));var a=u.offset().top;i.css("position")==="fixed"&&(a-=i.outerHeight()),e("html, body").stop().animate({scrollTop:a},700,"swing",function(){t.location.hash="#"+o})}).on("scroll.fndtn.magellan",n.throttle(this.check_for_arrivals.bind(this),i.throttle_delay)).on("resize.fndtn.magellan",n.throttle(this.set_expedition_position.bind(this),i.throttle_delay))},check_for_arrivals:function(){var e=this;e.update_arrivals(),e.update_expedition_positions()},set_expedition_position:function(){var t=this;e("["+this.attr_name()+"=fixed]",t.scope).each(function(n,r){var i=e(this),s=i.attr("styles"),o;i.attr("style",""),o=i.offset().top,i.data(t.data_attr("magellan-top-offset"),o),i.attr("style",s)})},update_expedition_positions:function(){var n=this,r=e(t).scrollTop();e("["+this.attr_name()+"=fixed]",n.scope).each(function(){var t=e(this),i=t.data("magellan-top-offset");if(r>=i){var s=t.prev("["+n.add_namespace("data-magellan-expedition-clone")+"]");s.length===0&&(s=t.clone(),s.removeAttr(n.attr_name()),s.attr(n.add_namespace("data-magellan-expedition-clone"),""),t.before(s)),t.css({position:"fixed",top:0})}else t.prev("["+n.add_namespace("data-magellan-expedition-clone")+"]").remove(),t.attr("style","")})},update_arrivals:function(){var n=this,r=e(t).scrollTop();e("["+this.attr_name()+"]",n.scope).each(function(){var t=e(this),i=i=t.data(n.attr_name(!0)+"-init"),s=n.offsets(t,r),o=t.find("["+n.add_namespace("data-magellan-arrival")+"]"),u=!1;s.each(function(e,r){if(r.viewport_offset>=r.top_offset){var s=t.find("["+n.add_namespace("data-magellan-arrival")+"]");return s.not(r.arrival).removeClass(i.active_class),r.arrival.addClass(i.active_class),u=!0,!0}}),u||o.removeClass(i.active_class)})},offsets:function(t,n){var r=this,i=t.data(r.attr_name(!0)+"-init"),s=n+i.destination_threshold;return t.find("["+r.add_namespace("data-magellan-arrival")+"]").map(function(t,n){var i=e(this).data(r.data_attr("magellan-arrival")),o=e("["+r.add_namespace("data-magellan-destination")+"="+i+"]");if(o.length>0){var u=o.offset().top;return{destination:o,arrival:e(this),top_offset:u,viewport_offset:s}}}).sort(function(e,t){return e.top_offsett.top_offset?1:0})},data_attr:function(e){return this.namespace.length>0?this.namespace+"-"+e:e},off:function(){this.S(this.scope).off(".magellan"),this.S(t).off(".magellan")},reflow:function(){var t=this;e("["+t.add_namespace("data-magellan-expedition-clone")+"]",t.scope).remove()}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.reveal={name:"reveal",version:"5.1.1",locked:!1,settings:{animation:"fadeAndPop",animation_speed:250,close_on_background_click:!0,close_on_esc:!0,dismiss_modal_class:"close-reveal-modal",bg_class:"reveal-modal-bg",open:function(){},opened:function(){},close:function(){},closed:function(){},bg:e(".reveal-modal-bg"),css:{open:{opacity:0,visibility:"visible",display:"block"},close:{opacity:1,visibility:"hidden",display:"none"}}},init:function(t,n,r){e.extend(!0,this.settings,n,r),this.bindings(n,r)},events:function(e){var t=this,r=t.S;return r(this.scope).off(".reveal").on("click.fndtn.reveal","["+this.add_namespace("data-reveal-id")+"]",function(e){e.preventDefault();if(!t.locked){var n=r(this),i=n.data(t.data_attr("reveal-ajax"));t.locked=!0;if(typeof i=="undefined")t.open.call(t,n);else{var s=i===!0?n.attr("href"):i;t.open.call(t,n,{url:s})}}}),r(n).on("click.fndtn.reveal",this.close_targets(),function(e){e.preventDefault();if(!t.locked){var n=r("["+t.attr_name()+"].open").data(t.attr_name(!0)+"-init"),i=r(e.target)[0]===r("."+n.bg_class)[0];if(i&&!n.close_on_background_click)return;t.locked=!0,t.close.call(t,i?r("["+t.attr_name()+"].open"):r(this).closest("["+t.attr_name()+"]"))}}),r("["+t.attr_name()+"]",this.scope).length>0?r(this.scope).on("open.fndtn.reveal",this.settings.open).on("opened.fndtn.reveal",this.settings.opened).on("opened.fndtn.reveal",this.open_video).on("close.fndtn.reveal",this.settings.close).on("closed.fndtn.reveal",this.settings.closed).on("closed.fndtn.reveal",this.close_video):r(this.scope).on("open.fndtn.reveal","["+t.attr_name()+"]",this.settings.open).on("opened.fndtn.reveal","["+t.attr_name()+"]",this.settings.opened).on("opened.fndtn.reveal","["+t.attr_name()+"]",this.open_video).on("close.fndtn.reveal","["+t.attr_name()+"]",this.settings.close).on("closed.fndtn.reveal","["+t.attr_name()+"]",this.settings.closed).on("closed.fndtn.reveal","["+t.attr_name()+"]",this.close_video),!0},key_up_on:function(e){var t=this;return t.S("body").off("keyup.fndtn.reveal").on("keyup.fndtn.reveal",function(e){var n=t.S("["+t.attr_name()+"].open"),r=n.data(t.attr_name(!0)+"-init");r&&e.which===27&&r.close_on_esc&&!t.locked&&t.close.call(t,n)}),!0},key_up_off:function(e){return this.S("body").off("keyup.fndtn.reveal"),!0},open:function(t,n){var r=this;if(t)if(typeof t.selector!="undefined")var i=r.S("#"+t.data(r.data_attr("reveal-id")));else{var i=r.S(this.scope);n=t}else var i=r.S(this.scope);var s=i.data(r.attr_name(!0)+"-init");if(!i.hasClass("open")){var o=r.S("["+r.attr_name()+"].open");typeof i.data("css-top")=="undefined"&&i.data("css-top",parseInt(i.css("top"),10)).data("offset",this.cache_offset(i)),this.key_up_on(i),i.trigger("open"),o.length<1&&this.toggle_bg(i),typeof n=="string"&&(n={url:n});if(typeof n=="undefined"||!n.url){if(o.length>0){var u=o.data(r.attr_name(!0)+"-init");this.hide(o,u.css.close)}this.show(i,s.css.open)}else{var a=typeof n.success!="undefined"?n.success:null;e.extend(n,{success:function(t,n,u){e.isFunction(a)&&a(t,n,u),i.html(t),r.S(i).foundation("section","reflow");if(o.length>0){var f=o.data(r.attr_name(!0));r.hide(o,f.css.close)}r.show(i,s.css.open)}}),e.ajax(n)}}},close:function(e){var e=e&&e.length?e:this.S(this.scope),t=this.S("["+this.attr_name()+"].open"),n=e.data(this.attr_name(!0)+"-init");t.length>0&&(this.locked=!0,this.key_up_off(e),e.trigger("close"),this.toggle_bg(e),this.hide(t,n.css.close,n))},close_targets:function(){var e="."+this.settings.dismiss_modal_class;return this.settings.close_on_background_click?e+", ."+this.settings.bg_class:e},toggle_bg:function(t){var n=t.data(this.attr_name(!0));this.S("."+this.settings.bg_class).length===0&&(this.settings.bg=e("
    ",{"class":this.settings.bg_class}).appendTo("body")),this.settings.bg.filter(":visible").length>0?this.hide(this.settings.bg):this.show(this.settings.bg)},show:function(n,r){if(r){var i=n.data(this.attr_name(!0)+"-init");if(n.parent("body").length===0){var s=n.wrap('
    ').parent(),o=this.settings.rootElement||"body";n.on("closed.fndtn.reveal.wrapped",function(){n.detach().appendTo(s),n.unwrap().unbind("closed.fndtn.reveal.wrapped")}),n.detach().appendTo(o)}if(/pop/i.test(i.animation)){r.top=e(t).scrollTop()-n.data("offset")+"px";var u={top:e(t).scrollTop()+n.data("css-top")+"px",opacity:1};return setTimeout(function(){return n.css(r).animate(u,i.animation_speed,"linear",function(){this.locked=!1,n.trigger("opened")}.bind(this)).addClass("open")}.bind(this),i.animation_speed/2)}if(/fade/i.test(i.animation)){var u={opacity:1};return setTimeout(function(){return n.css(r).animate(u,i.animation_speed,"linear",function(){this.locked=!1,n.trigger("opened")}.bind(this)).addClass("open")}.bind(this),i.animation_speed/2)}return n.css(r).show().css({opacity:1}).addClass("open").trigger("opened")}var i=this.settings;return/fade/i.test(i.animation)?n.fadeIn(i.animation_speed/2):(this.locked=!1,n.show())},hide:function(n,r){if(r){var i=n.data(this.attr_name(!0)+"-init");if(/pop/i.test(i.animation)){var s={top:-e(t).scrollTop()-n.data("offset")+"px",opacity:0};return setTimeout(function(){return n.animate(s,i.animation_speed,"linear",function(){this.locked=!1,n.css(r).trigger("closed")}.bind(this)).removeClass("open")}.bind(this),i.animation_speed/2)}if(/fade/i.test(i.animation)){var s={opacity:0};return setTimeout(function(){return n.animate(s,i.animation_speed,"linear",function(){this.locked=!1,n.css(r).trigger("closed")}.bind(this)).removeClass("open")}.bind(this),i.animation_speed/2)}return n.hide().css(r).removeClass("open").trigger("closed")}var i=this.settings;return/fade/i.test(i.animation)?n.fadeOut(i.animation_speed/2):n.hide()},close_video:function(t){var n=e(".flex-video",t.target),r=e("iframe",n);r.length>0&&(r.attr("data-src",r[0].src),r.attr("src","about:blank"),n.hide())},open_video:function(t){var n=e(".flex-video",t.target),i=n.find("iframe");if(i.length>0){var s=i.attr("data-src");if(typeof s=="string")i[0].src=i.attr("data-src");else{var o=i[0].src;i[0].src=r,i[0].src=o}n.show()}},data_attr:function(e){return this.namespace.length>0?this.namespace+"-"+e:e},cache_offset:function(e){var t=e.show().height()+parseInt(e.css("top"),10);return e.hide(),t},off:function(){e(this.scope).off(".fndtn.reveal")},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.tooltip={name:"tooltip",version:"5.1.1",settings:{additional_inheritable_classes:[],tooltip_class:".tooltip",append_to:"body",touch_close_text:"Tap To Close",disable_for_touch:!1,hover_delay:200,tip_template:function(e,t){return''+t+''}},cache:{},init:function(e,t,n){Foundation.inherit(this,"random_str"),this.bindings(t,n)},events:function(){var t=this,r=t.S;Modernizr.touch?r(n).off(".tooltip").on("click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip","["+this.attr_name()+"]:not(a)",function(n){var i=e.extend({},t.settings,t.data_options(r(this)));i.disable_for_touch||(n.preventDefault(),r(i.tooltip_class).hide(),t.showOrCreateTip(r(this)))}).on("click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip",this.settings.tooltip_class,function(e){e.preventDefault(),r(this).fadeOut -(150)}):r(n).off(".tooltip").on("mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip","["+this.attr_name()+"]",function(e){var n=r(this);if(/enter|over/i.test(e.type))this.timer=setTimeout(function(){var e=t.showOrCreateTip(n)}.bind(this),t.settings.hover_delay);else if(e.type==="mouseout"||e.type==="mouseleave")clearTimeout(this.timer),t.hide(n)})},showOrCreateTip:function(e){var t=this.getTip(e);return t&&t.length>0?this.show(e):this.create(e)},getTip:function(e){var t=this.selector(e),n=null;return t&&(n=this.S('span[data-selector="'+t+'"]'+this.settings.tooltip_class)),typeof n=="object"?n:!1},selector:function(e){var t=e.attr("id"),n=e.attr(this.attr_name())||e.attr("data-selector");return(t&&t.length<1||!t)&&typeof n!="string"&&(n="tooltip"+this.random_str(6),e.attr("data-selector",n)),t&&t.length>0?t:n},create:function(t){var n=e(this.settings.tip_template(this.selector(t),e("
    ").html(t.attr("title")).html())),r=this.inheritable_classes(t);n.addClass(r).appendTo(this.settings.append_to),Modernizr.touch&&n.append(''+this.settings.touch_close_text+""),t.removeAttr("title").attr("title",""),this.show(t)},reposition:function(e,t,n){var r,i,s,o,u,a;t.css("visibility","hidden").show(),r=e.data("width"),i=t.children(".nub"),s=i.outerHeight(),o=i.outerHeight(),this.small()?t.css({width:"100%"}):t.css({width:r?r:"auto"}),a=function(e,t,n,r,i,s){return e.css({top:t?t:"auto",bottom:r?r:"auto",left:i?i:"auto",right:n?n:"auto"}).end()},a(t,e.offset().top+e.outerHeight()+10,"auto","auto",e.offset().left);if(this.small())a(t,e.offset().top+e.outerHeight()+10,"auto","auto",12.5,this.S(this.scope).width()),t.addClass("tip-override"),a(i,-s,"auto","auto",e.offset().left+10);else{var f=e.offset().left;Foundation.rtl&&(f=e.offset().left+e.outerWidth()-t.outerWidth()),a(t,e.offset().top+e.outerHeight()+10,"auto","auto",f),t.removeClass("tip-override"),i.removeAttr("style"),n&&n.indexOf("tip-top")>-1?a(t,e.offset().top-t.outerHeight()-10,"auto","auto",f).removeClass("tip-override"):n&&n.indexOf("tip-left")>-1?a(t,e.offset().top+e.outerHeight()/2-t.outerHeight()/2,"auto","auto",e.offset().left-t.outerWidth()-s).removeClass("tip-override"):n&&n.indexOf("tip-right")>-1&&a(t,e.offset().top+e.outerHeight()/2-t.outerHeight()/2,"auto","auto",e.offset().left+e.outerWidth()+s).removeClass("tip-override")}t.css("visibility","visible").hide()},small:function(){return matchMedia(Foundation.media_queries.small).matches},inheritable_classes:function(t){var n=["tip-top","tip-left","tip-bottom","tip-right","radius","round"].concat(this.settings.additional_inheritable_classes),r=t.attr("class"),i=r?e.map(r.split(" "),function(t,r){if(e.inArray(t,n)!==-1)return t}).join(" "):"";return e.trim(i)},show:function(e){var t=this.getTip(e);return this.reposition(e,t,e.attr("class")),t.fadeIn(150)},hide:function(e){var t=this.getTip(e);return t.fadeOut(150)},reload:function(){var t=e(this);return t.data("fndtn-tooltips")?t.foundationTooltips("destroy").foundationTooltips("init"):t.foundationTooltips("init")},off:function(){this.S(this.scope).off(".fndtn.tooltip"),this.S(this.settings.tooltip_class).each(function(t){e("["+this.attr_name()+"]").get(t).attr("title",e(this).text())}).remove()},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.tab={name:"tab",version:"5.1.1",settings:{active_class:"active",callback:function(){}},init:function(e,t,n){this.bindings(t,n)},events:function(){var e=this,t=this.S;t(this.scope).off(".tab").on("click.fndtn.tab","["+this.attr_name()+"] > dd > a",function(n){n.preventDefault(),n.stopPropagation();var r=t(this).parent(),i=r.closest("["+e.attr_name()+"]"),s=t("#"+this.href.split("#")[1]),o=r.siblings(),u=i.data(e.attr_name(!0)+"-init");t(this).data(e.data_attr("tab-content"))&&(s=t("#"+t(this).data(e.data_attr("tab-content")).split("#")[1])),r.addClass(u.active_class).triggerHandler("opened"),o.removeClass(u.active_class),s.siblings().removeClass(u.active_class).end().addClass(u.active_class),u.callback(r),i.triggerHandler("toggled",[r])})},data_attr:function(e){return this.namespace.length>0?this.namespace+"-"+e:e},off:function(){},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.clearing={name:"clearing",version:"5.1.1",settings:{templates:{viewing:'×'},close_selectors:".clearing-close",touch_label:"← Swipe to Advance →",init:!1,locked:!1},init:function(e,t,n){var r=this;Foundation.inherit(this,"throttle image_loaded"),this.bindings(t,n),r.S(this.scope).is("["+this.attr_name()+"]")?this.assemble(r.S("li",this.scope)):r.S("["+this.attr_name()+"]",this.scope).each(function(){r.assemble(r.S("li",this))})},events:function(e){var n=this,r=n.S;r(this.scope).off(".clearing").on("click.fndtn.clearing","ul["+this.attr_name()+"] li",function(e,t,i){var t=t||r(this),i=i||t,s=t.next("li"),o=t.closest("["+n.attr_name()+"]").data(n.attr_name(!0)+"-init"),u=r(e.target);e.preventDefault(),o||(n.init(),o=t.closest("["+n.attr_name()+"]").data(n.attr_name(!0)+"-init")),i.hasClass("visible")&&t[0]===i[0]&&s.length>0&&n.is_open(t)&&(i=s,u=r("img",i)),n.open(u,t,i),n.update_paddles(i)}).on("click.fndtn.clearing",".clearing-main-next",function(e){n.nav(e,"next")}).on("click.fndtn.clearing",".clearing-main-prev",function(e){n.nav(e,"prev")}).on("click.fndtn.clearing",this.settings.close_selectors,function(e){Foundation.libs.clearing.close(e,this)}).on("keydown.fndtn.clearing",function(e){n.keydown(e)}),r(t).off(".clearing").on("resize.fndtn.clearing",function(){n.resize()}),this.swipe_events(e)},swipe_events:function(e){var t=this,n=t.S;n(this.scope).on("touchstart.fndtn.clearing",".visible-img",function(e){e.touches||(e=e.originalEvent);var t={start_page_x:e.touches[0].pageX,start_page_y:e.touches[0].pageY,start_time:(new Date).getTime(),delta_x:0,is_scrolling:r};n(this).data("swipe-transition",t),e.stopPropagation()}).on("touchmove.fndtn.clearing",".visible-img",function(e){e.touches||(e=e.originalEvent);if(e.touches.length>1||e.scale&&e.scale!==1)return;var r=n(this).data("swipe-transition");typeof r=="undefined"&&(r={}),r.delta_x=e.touches[0].pageX-r.start_page_x,typeof r.is_scrolling=="undefined"&&(r.is_scrolling=!!(r.is_scrolling||Math.abs(r.delta_x)
    ');var r=this.S("#foundationClearingHolder"),i=n.data(this.attr_name(!0)+"-init"),s=n.detach(),o={grid:'",viewing:i.templates.viewing},u='
    '+o.viewing+o.grid+"
    ",a=this.settings.touch_label;Modernizr.touch&&(u=e(u).find(".clearing-touch-label").html(a).end()),r.after(u).remove()},open:function(e,t,n){var r=this,i=n.closest(".clearing-assembled"),s=r.S("div",i).first(),o=r.S(".visible-img",s),u=r.S("img",o).not(e),a=r.S(".clearing-touch-label",s);this.locked()||(u.attr("src",this.load(e)).css("visibility","hidden"),this.image_loaded(u,function(){u.css("visibility","visible"),i.addClass("clearing-blackout"),s.addClass("clearing-container"),o.show(),this.fix_height(n).caption(r.S(".clearing-caption",o),e).center_and_label(u,a).shift(t,n,function(){n.siblings().removeClass("visible"),n.addClass("visible")})}.bind(this)))},close:function(t,n){t.preventDefault();var r=function(e){return/blackout/.test(e.selector)?e:e.closest(".clearing-blackout")}(e(n)),i,s;return n===t.target&&r&&(i=e("div",r).first(),s=e(".visible-img",i),this.settings.prev_index=0,e("ul["+this.attr_name()+"]",r).attr("style","").closest(".clearing-blackout").removeClass("clearing-blackout"),i.removeClass("clearing-container"),s.hide()),!1},is_open:function(e){return e.parent().prop("style").length>0},keydown:function(t){var n=e("ul["+this.attr_name()+"]",".clearing-blackout"),r=this.rtl?37:39,i=this.rtl?39:37,s=27;t.which===r&&this.go(n,"next"),t.which===i&&this.go(n,"prev"),t.which===s&&this.S("a.clearing-close").trigger("click")},nav:function(t,n){var r=e("ul["+this.attr_name()+"]",".clearing-blackout");t.preventDefault(),this.go(r,n)},resize:function(){var t=e("img",".clearing-blackout .visible-img"),n=e(".clearing-touch-label",".clearing-blackout");t.length&&this.center_and_label(t,n)},fix_height:function(e){var t=e.parent().children(),n=this;return t.each(function(){var e=n.S(this),t=e.find("img");e.height()>t.outerHeight()&&e.addClass("fix-height")}).closest("ul").width(t.length*100+"%"),this},update_paddles:function(e){var t=e.closest(".carousel").siblings(".visible-img");e.next().length>0?this.S(".clearing-main-next",t).removeClass("disabled"):this.S(".clearing-main-next",t).addClass("disabled"),e.prev().length>0?this.S(".clearing-main-prev",t).removeClass("disabled"):this.S(".clearing-main-prev",t).addClass("disabled")},center_and_label:function(e,t){return this.rtl?(e.css({marginRight:-(e.outerWidth()/2),marginTop:-(e.outerHeight()/2),left:"auto",right:"50%"}),t.css({marginRight:-(t.outerWidth()/2),marginTop:-(e.outerHeight()/2)-t.outerHeight()-10,left:"auto",right:"50%"})):(e.css({marginLeft:-(e.outerWidth()/2),marginTop:-(e.outerHeight()/2)}),t.css({marginLeft:-(t.outerWidth()/2),marginTop:-(e.outerHeight()/2)-t.outerHeight()-10})),this},load:function(e){if(e[0].nodeName==="A")var t=e.attr("href");else var t=e.parent().attr("href");return this.preload(e),t?t:e.attr("src")},preload:function(e){this.img(e.closest("li").next()).img(e.closest("li").prev())},img:function(e){if(e.length){var t=new Image,n=this.S("a",e);n.length?t.src=n.attr("href"):t.src=this.S("img",e).attr("src")}return this},caption:function(e,t){var n=t.data("caption");return n?e.html(n).show():e.text("").hide(),this},go:function(e,t){var n=this.S(".visible",e),r=n[t]();r.length&&this.S("img",r).trigger("click",[n,r])},shift:function(e,t,n){var r=t.parent(),i=this.settings.prev_index||t.index(),s=this.direction(r,e,t),o=this.rtl?"right":"left",u=parseInt(r.css("left"),10),a=t.outerWidth(),f,l={};t.index()!==i&&!/skip/.test(s)?/left/.test(s)?(this.lock(),l[o]=u+a,r.animate(l,300,this.unlock())):/right/.test(s)&&(this.lock(),l[o]=u-a,r.animate(l,300,this.unlock())):/skip/.test(s)&&(f=t.index()-this.settings.up_count,this.lock(),f>0?(l[o]=-(f*a),r.animate(l,300,this.unlock())):(l[o]=0,r.animate(l,300,this.unlock()))),n()},direction:function(e,t,n){var r=this.S("li",e),i=r.outerWidth()+r.outerWidth()/4,s=Math.floor(this.S(".clearing-container").outerWidth()/i)-1,o=r.index(n),u;return this.settings.up_count=s,this.adjacent(this.settings.prev_index,o)?o>s&&o>this.settings.prev_index?u="right":o>s-1&&o<=this.settings.prev_index?u="left":u=!1:u="skip",this.settings.prev_index=o,u},adjacent:function(e,t){for(var n=t+1;n>=t-1;n--)if(n===e)return!0;return!1},lock:function(){this.settings.locked=!0},unlock:function(){this.settings.locked=!1},locked:function(){return this.settings.locked},off:function(){this.S(this.scope).off(".fndtn.clearing"),this.S(t).off(".fndtn.clearing")},reflow:function(){this.init()}}}(jQuery,this,this.document),!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)}(function(e){function t(e){return u.raw?e:encodeURIComponent(e)}function n(e){return u.raw?e:decodeURIComponent(e)}function r(e){return t(u.json?JSON.stringify(e):String(e))}function i(e){0===e.indexOf('"')&&(e=e.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{e=decodeURIComponent(e.replace(o," "))}catch(t){return}try{return u.json?JSON.parse(e):e}catch(t){}}function s(t,n){var r=u.raw?t:i(t);return e.isFunction(n)?n(r):r}var o=/\+/g,u=e.cookie=function(i,o,l){if(void 0!==o&&!e.isFunction(o)){if(l=e.extend({},u.defaults,l),"number"==typeof l.expires){var p=l.expires,v=l.expires=new Date;v.setDate(v.getDate()+p)}return document.cookie=[t(i),"=",r(o),l.expires?"; expires="+l.expires.toUTCString():"",l.path?"; path="+l.path:"",l.domain?"; domain="+l.domain:"",l.secure?"; secure":""].join("")}for(var m=i?void 0:{},g=document.cookie?document.cookie.split("; "):[],y=0,w=g.length;w>y;y++){var E=g[y].split("="),S=n(E.shift()),x=E.join("=");if(i&&i===S){m=s(x,o);break}i||void 0===(x=s(x))||(m[S]=x)}return m};u.defaults={},e.removeCookie=function(t,n){return void 0!==e.cookie(t)?(e.cookie(t,"",e.extend({},n,{expires:-1})),!0):!1}}),function(e,t,n,r){"use strict";var i=i||!1;Foundation.libs.joyride={name:"joyride",version:"5.1.1",defaults:{expose:!1,modal:!0,tip_location:"bottom",nub_position:"auto",scroll_speed:1500,scroll_animation:"linear",timer:0,start_timer_on_click:!0,start_offset:0,next_button:!0,tip_animation:"fade",pause_after:[],exposed:[],tip_animation_fade_speed:300,cookie_monster:!1,cookie_name:"joyride",cookie_domain:!1,cookie_expires:365,tip_container:"body",tip_location_patterns:{top:["bottom"],bottom:[],left:["right","top","bottom"],right:["left","top","bottom"]},post_ride_callback:function(){},post_step_callback:function(){},pre_step_callback:function(){},pre_ride_callback:function(){},post_expose_callback:function(){},template:{link:'×',timer:'
    ',tip:'
    ',wrapper:'
    ',button:'',modal:'
    ',expose:'
    ',expose_cover:'
    '},expose_add_class:""},init:function(e,t,n){Foundation.inherit(this,"throttle random_str"),this.settings=this.defaults,this.bindings(t,n)},events:function(){var n=this;e(this.scope).off(".joyride").on("click.fndtn.joyride",".joyride-next-tip, .joyride-modal-bg",function(e){e.preventDefault(),this.settings.$li.next().length<1?this.end():this.settings.timer>0?(clearTimeout(this.settings.automate),this.hide(),this.show(),this.startTimer()):(this.hide(),this.show())}.bind(this)).on("click.fndtn.joyride",".joyride-close-tip",function(e){e.preventDefault(),this.end()}.bind(this)),e(t).off(".joyride").on("resize.fndtn.joyride",n.throttle(function(){if(e("["+n.attr_name()+"]").length>0&&n.settings.$next_tip){if(n.settings.exposed.length>0){var t=e(n.settings.exposed);t.each(function(){var t=e(this);n.un_expose(t),n.expose(t)})}n.is_phone()?n.pos_phone():n.pos_default(!1,!0)}},100))},start:function(){var t=this,n=e("["+this.attr_name()+"]",this.scope),r=["timer","scrollSpeed","startOffset","tipAnimationFadeSpeed","cookieExpires"],i=r.length;if(!n.length>0)return;this.settings.init||this.events(),this.settings=n.data(this.attr_name(!0)+"-init"),this.settings.$content_el=n,this.settings.$body=e(this.settings.tip_container),this.settings.body_offset=e(this.settings.tip_container).position(),this.settings.$tip_content=this.settings.$content_el.find("> li"),this.settings.paused=!1,this.settings.attempts=0,typeof e.cookie!="function"&&(this.settings.cookie_monster=!1);if(!this.settings.cookie_monster||this.settings.cookie_monster&&!e.cookie(this.settings.cookie_name))this.settings.$tip_content.each(function(n){var s=e(this);this.settings=e.extend({},t.defaults,t.data_options(s));var o=i;while(o--)t.settings[r[o]]=parseInt(t.settings[r[o]],10);t.create({$li:s,index:n})}),!this.settings.start_timer_on_click&&this.settings.timer>0?(this.show("init"),this.startTimer()):this.show("init")},resume:function(){this.set_li(),this.show()},tip_template:function(t){var n,r;return t.tip_class=t.tip_class||"",n=e(this.settings.template.tip).addClass(t.tip_class),r=e.trim(e(t.li).html())+this.button_text(t.button_text)+this.settings.template.link+this.timer_instance(t.index),n.append(e(this.settings.template.wrapper)),n.first().attr(this.add_namespace("data-index"),t.index),e(".joyride-content-wrapper",n).append(r),n[0]},timer_instance:function(t){var n;return t===0&&this.settings.start_timer_on_click&&this.settings.timer>0||this.settings.timer===0?n="":n=e(this.settings.template.timer)[0].outerHTML,n},button_text:function(t){return this.settings.next_button?(t=e.trim(t)||"Next",t=e(this.settings.template.button).append(t)[0].outerHTML):t="",t},create:function(t){console.log(t.$li);var n=t.$li.attr(this.add_namespace("data-button"))||t.$li.attr(this.add_namespace("data-text")),r=t.$li.attr("class"),i=e(this.tip_template({tip_class:r,index:t.index,button_text:n,li:t.$li}));e(this.settings.tip_container).append(i)},show:function(t){var n=null;this.settings.$li===r||e.inArray(this.settings.$li.index(),this.settings.pause_after)===-1?(this.settings.paused?this.settings.paused=!1:this.set_li(t),this.settings.attempts=0,this.settings.$li.length&&this.settings.$target.length>0?(t&&(this.settings.pre_ride_callback(this.settings.$li.index(),this.settings.$next_tip),this.settings.modal&&this.show_modal()),this.settings.pre_step_callback(this.settings.$li.index(),this.settings.$next_tip),this.settings.modal&&this.settings.expose&&this.expose(),this.settings.tip_settings=e.extend({},this.settings,this.data_options(this.settings.$li)),this.settings.timer=parseInt(this.settings.timer,10),this.settings.tip_settings.tip_location_pattern=this.settings.tip_location_patterns[this.settings.tip_settings.tip_location],/body/i.test(this.settings.$target.selector)||this.scroll_to(),this.is_phone()?this.pos_phone(!0):this.pos_default(!0),n=this.settings.$next_tip.find(".joyride-timer-indicator"),/pop/i.test(this.settings.tip_animation)?(n.width(0),this.settings.timer>0?(this.settings.$next_tip.show(),setTimeout(function(){n.animate({width:n.parent().width()},this.settings.timer,"linear")}.bind(this),this.settings.tip_animation_fade_speed)):this.settings.$next_tip.show()):/fade/i.test(this.settings.tip_animation)&&(n.width(0),this.settings.timer>0?(this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed).show(),setTimeout(function(){n.animate({width:n.parent().width()},this.settings.timer,"linear")}.bind(this),this.settings.tip_animation_fadeSpeed)):this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed)),this.settings.$current_tip=this.settings.$next_tip):this.settings.$li&&this.settings.$target.length<1?this.show():this.end()):this.settings.paused=!0},is_phone:function(){return matchMedia(Foundation.media_queries.small).matches&&!matchMedia(Foundation.media_queries.medium).matches},hide:function(){this.settings.modal&&this.settings.expose&&this.un_expose(),this.settings.modal||e(".joyride-modal-bg").hide(),this.settings.$current_tip.css("visibility","hidden"),setTimeout(e.proxy(function(){this.hide(),this.css("visibility","visible")},this.settings.$current_tip),0),this.settings.post_step_callback(this.settings.$li.index(),this.settings.$current_tip)},set_li:function(e){e?(this.settings.$li=this.settings.$tip_content.eq(this.settings.start_offset),this.set_next_tip(),this.settings.$current_tip=this.settings.$next_tip):(this.settings.$li=this.settings.$li.next(),this.set_next_tip()),this.set_target()},set_next_tip:function(){this.settings.$next_tip=e(".joyride-tip-guide").eq(this.settings.$li.index()),this.settings.$next_tip.data("closed","")},set_target:function(){console.log(this.add_namespace("data-class"));var t=this.settings.$li.attr(this.add_namespace("data-class")),r=this.settings.$li.attr(this.add_namespace("data-id")),i=function(){return r?e(n.getElementById(r)):t?e("."+t).first():e("body")};console.log(t,r),this.settings.$target=i()},scroll_to:function(){var n,r;n=e(t).height()/2,r=Math.ceil(this.settings.$target.offset().top-n+this.settings.$next_tip.outerHeight()),r!=0&&e("html, body").animate({scrollTop:r},this.settings.scroll_speed,"swing")},paused:function(){return e.inArray(this.settings.$li.index()+1,this.settings.pause_after)===-1},restart:function(){this.hide(),this.settings.$li=r,this.show("init")},pos_default:function(n,r){var i=Math.ceil(e(t).height()/2),s=this.settings.$next_tip.offset(),o=this.settings.$next_tip.find(".joyride-nub"),u=Math.ceil(o.outerWidth()/2),a=Math.ceil(o.outerHeight()/2),f=n||!1;f&&(this.settings.$next_tip.css("visibility","hidden"),this.settings.$next_tip.show()),typeof r=="undefined"&&(r=!1),/body/i.test(this.settings.$target.selector)?this.settings.$li.length&&this.pos_modal(o):(this.bottom()?(this.rtl?this.settings.$next_tip.css({top:this.settings.$target.offset().top+a+this.settings.$target.outerHeight(),left:this.settings.$target.offset().left+this.settings.$target.outerWidth()-this.settings.$next_tip.outerWidth()}):this.settings.$next_tip.css({top:this.settings.$target.offset().top+a+this.settings.$target.outerHeight(),left:this.settings.$target.offset().left}),this.nub_position(o,this.settings.tip_settings.nub_position,"top")):this.top()?(this.rtl?this.settings.$next_tip.css({top:this.settings.$target.offset().top-this.settings.$next_tip.outerHeight()-a,left:this.settings.$target.offset().left+this.settings.$target.outerWidth()-this.settings.$next_tip.outerWidth()}):this.settings.$next_tip.css({top:this.settings.$target.offset().top-this.settings.$next_tip.outerHeight()-a,left:this.settings.$target.offset().left}),this.nub_position(o,this.settings.tip_settings.nub_position,"bottom")):this.right()?(this.settings.$next_tip.css({top:this.settings.$target.offset().top,left:this.outerWidth(this.settings.$target)+this.settings.$target.offset().left+u}),this.nub_position(o,this.settings.tip_settings.nub_position,"left")):this.left()&&(this.settings.$next_tip.css({top:this.settings.$target.offset().top,left:this.settings.$target.offset().left-this.outerWidth(this.settings.$next_tip)-u}),this.nub_position(o,this.settings.tip_settings.nub_position,"right")),!this.visible(this.corners(this.settings.$next_tip))&&this.settings.attempts0&&arguments[0]instanceof e)i=arguments[0];else{if(!this.settings.$target||!!/body/i.test(this.settings.$target.selector))return!1;i=this.settings.$target}if(i.length<1)return t.console&&console.error("element not valid",i),!1;n=e(this.settings.template.expose),this.settings.$body.append(n),n.css({top:i.offset().top,left:i.offset().left,width:i.outerWidth(!0),height:i.outerHeight(!0)}),r=e(this.settings.template.expose_cover),s={zIndex:i.css("z-index"),position:i.css("position")},o=i.attr("class")==null?"":i.attr("class"),i.css("z-index",parseInt(n.css("z-index"))+1),s.position=="static"&&i.css("position","relative"),i.data("expose-css",s),i.data("orig-class",o),i.attr("class",o+" "+this.settings.expose_add_class),r.css({top:i.offset().top,left:i.offset().left,width:i.outerWidth(!0),height:i.outerHeight(!0)}),this.settings.modal&&this.show_modal(),this.settings.$body.append(r),n.addClass(u),r.addClass(u),i.data("expose",u),this.settings.post_expose_callback(this.settings.$li.index(),this.settings.$next_tip,i),this.add_exposed(i)},un_expose:function(){var n,r,i,s,o,u=!1;if(arguments.length>0&&arguments[0]instanceof e)r=arguments[0];else{if(!this.settings.$target||!!/body/i.test(this.settings.$target.selector))return!1;r=this.settings.$target}if(r.length<1)return t.console&&console.error("element not valid",r),!1;n=r.data("expose"),i=e("."+n),arguments.length>1&&(u=arguments[1]),u===!0?e(".joyride-expose-wrapper,.joyride-expose-cover").remove():i.remove(),s=r.data("expose-css"),s.zIndex=="auto"?r.css("z-index",""):r.css("z-index",s.zIndex),s.position!=r.css("position")&&(s.position=="static"?r.css("position",""):r.css("position",s.position)),o=r.data("orig-class"),r.attr("class",o),r.removeData("orig-classes"),r.removeData("expose"),r.removeData("expose-z-index"),this.remove_exposed(r)},add_exposed:function(t){this.settings.exposed=this.settings.exposed||[],t instanceof e||typeof t=="object"?this.settings.exposed.push(t[0]):typeof t=="string"&&this.settings.exposed.push(t)},remove_exposed:function(t){var n,r;t instanceof e?n=t[0]:typeof t=="string"&&(n=t),this.settings.exposed=this.settings.exposed||[],r=this.settings.exposed.length;while(r--)if(this.settings.exposed[r]==n){this.settings.exposed.splice(r,1);return}},center:function(){var n=e(t);return this.settings.$next_tip.css({top:(n.height()-this.settings.$next_tip.outerHeight())/2+n.scrollTop(),left:(n.width()-this.settings.$next_tip.outerWidth())/2+n.scrollLeft()}),!0},bottom:function(){return/bottom/i.test(this.settings.tip_settings.tip_location)},top:function(){return/top/i.test(this.settings.tip_settings.tip_location)},right:function(){return/right/i.test(this.settings.tip_settings.tip_location)},left:function(){return/left/i.test(this.settings.tip_settings.tip_location)},corners:function(n){var r=e(t),i=r.height()/2,s=Math.ceil(this.settings.$target.offset().top-i+this.settings.$next_tip.outerHeight()),o=r.width()+r.scrollLeft(),u=r.height()+s,a=r.height()+r.scrollTop(),f=r.scrollTop();return sa&&(a=u),[n.offset().topn.offset().left]},visible:function(e){var t=e.length;while(t--)if(e[t])return!1;return!0},nub_position:function(e,t,n){t==="auto"?e.addClass(n):e.addClass(t)},startTimer:function(){this.settings.$li.length?this.settings.automate=setTimeout(function(){this.hide(),this.show(),this.startTimer()}.bind(this),this.settings.timer):clearTimeout(this.settings.automate)},end:function(){this.settings.cookie_monster&&e.cookie(this.settings.cookie_name,"ridden",{expires:this.settings.cookie_expires,domain:this.settings.cookie_domain}),this.settings.timer>0&&clearTimeout(this.settings.automate),this.settings.modal&&this.settings.expose&&this.un_expose(),this.settings.$next_tip.data("closed",!0),e(".joyride-modal-bg").hide(),this.settings.$current_tip.hide(),this.settings.post_step_callback(this.settings.$li.index(),this.settings.$current_tip),this.settings.post_ride_callback(this.settings.$li.index(),this.settings.$current_tip),e(".joyride-tip-guide").remove()},off:function(){e(this.scope).off(".joyride"),e(t).off(".joyride"),e(".joyride-close-tip, .joyride-next-tip, .joyride-modal-bg").off(".joyride"),e(".joyride-tip-guide, .joyride-modal-bg").remove(),clearTimeout(this.settings.automate),this.settings={}},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";var i=function(){},s=function(i,s){if(i.hasClass(s.slides_container_class))return this;var f=this,l,c=i,h,p,d,v=0,m,g,y=!1,b=!1;f.slides=function(){return c.children(s.slide_selector)},f.slides().first().addClass(s.active_slide_class),f.update_slide_number=function(t){s.slide_number&&(h.find("span:first").text(parseInt(t)+1),h.find("span:last").text(f.slides().length)),s.bullets&&(p.children().removeClass(s.bullets_active_class),e(p.children().get(t)).addClass(s.bullets_active_class))},f.update_active_link=function(t){var n=e('a[data-orbit-link="'+f.slides().eq(t).attr("data-orbit-slide")+'"]');n.siblings().removeClass(s.bullets_active_class),n.addClass(s.bullets_active_class)},f.build_markup=function(){c.wrap('
    '),l=c.parent(),c.addClass(s.slides_container_class),s.navigation_arrows&&(l.append(e('').addClass(s.prev_class)),l.append(e('').addClass(s.next_class))),s.timer&&(d=e("
    ").addClass(s.timer_container_class),d.append(""),d.append(e("
    ").addClass(s.timer_progress_class)),d.addClass(s.timer_paused_class),l.append(d)),s.slide_number&&(h=e("
    ").addClass(s.slide_number_class),h.append(" "+s.slide_number_text+" "),l.append(h)),s.bullets&&(p=e("
      ").addClass(s.bullets_container_class),l.append(p),p.wrap('
      '),f.slides().each(function(t,n){var r=e("
    1. ").attr("data-orbit-slide",t);p.append(r)})),s.stack_on_small&&l.addClass(s.stack_on_small_class)},f._goto=function(t,n){if(t===v)return!1;typeof g=="object"&&g.restart();var r=f.slides(),i="next";y=!0,t=r.length){if(!s.circular)return!1;t=0}else if(t<0){if(!s.circular)return!1;t=r.length-1}var o=e(r.get(v)),u=e(r.get(t));o.css("zIndex",2),o.removeClass(s.active_slide_class),u.css("zIndex",4).addClass(s.active_slide_class),c.trigger("before-slide-change.fndtn.orbit"),s.before_slide_change(),f.update_active_link(t);var a=function(){var e=function(){v=t,y=!1,n===!0&&(g=f.create_timer(),g.start()),f.update_slide_number(v),c.trigger("after-slide-change.fndtn.orbit",[{slide_number:v,total_slides:r.length}]),s.after_slide_change(v,r.length)};c.height()!=u.height()&&s.variable_height?c.animate({height:u.height()},250,"linear",e):e()};if(r.length===1)return a(),!1;var l=function(){i==="next"&&m.next(o,u,a),i==="prev"&&m.prev(o,u,a)};u.height()>c.height()&&s.variable_height?c.animate({height:u.height()},250,"linear",l):l()},f.next=function(e){e.stopImmediatePropagation(),e.preventDefault(),f._goto(v+1)},f.prev=function(e){e.stopImmediatePropagation(),e.preventDefault(),f._goto(v-1)},f.link_custom=function(t){t.preventDefault();var n=e(this).attr("data-orbit-link");if(typeof n=="string"&&(n=e.trim(n))!=""){var r=l.find("[data-orbit-slide="+n+"]");r.index()!=-1&&f._goto(r.index())}},f.link_bullet=function(t){var n=e(this).attr("data-orbit-slide");if(typeof n=="string"&&(n=e.trim(n))!="")if(isNaN(parseInt(n))){var r=l.find("[data-orbit-slide="+n+"]");r.index()!=-1&&f._goto(r.index()+1)}else f._goto(parseInt(n))},f.timer_callback=function(){f._goto(v+1,!0)},f.compute_dimensions=function(){var t=e(f.slides().get(v)),n=t.height();s.variable_height||f.slides().each(function(){e(this).height()>n&&(n=e(this).height())}),c.height(n)},f.create_timer=function(){var e=new o(l.find("."+s.timer_container_class),s,f.timer_callback);return e},f.stop_timer=function(){typeof g=="object"&&g.stop()},f.toggle_timer=function(){var e=l.find("."+s.timer_container_class);e.hasClass(s.timer_paused_class)?(typeof g=="undefined"&&(g=f.create_timer()),g.start()):typeof g=="object"&&g.stop()},f.init=function(){f.build_markup(),s.timer&&(g=f.create_timer(),Foundation.utils.image_loaded(this.slides().children("img"),g.start)),m=new a(s,c),s.animation==="slide"&&(m=new u(s,c)),l.on("click","."+s.next_class,f.next),l.on("click","."+s.prev_class,f.prev),l.on("click","[data-orbit-slide]",f.link_bullet),l.on("click",f.toggle_timer),s.swipe&&l.on("touchstart.fndtn.orbit",function(e){e.touches||(e=e.originalEvent);var t={start_page_x:e.touches[0].pageX,start_page_y:e.touches[0].pageY,start_time:(new Date).getTime(),delta_x:0,is_scrolling:r};l.data("swipe-transition",t),e.stopPropagation()}).on("touchmove.fndtn.orbit",function(e){e.touches||(e=e.originalEvent);if(e.touches.length>1||e.scale&&e.scale!==1)return; -var t=l.data("swipe-transition");typeof t=="undefined"&&(t={}),t.delta_x=e.touches[0].pageX-t.start_page_x,typeof t.is_scrolling=="undefined"&&(t.is_scrolling=!!(t.is_scrolling||Math.abs(t.delta_x) ul",this).first();t.data("index",0);var o=t.parent();o.hasClass("fixed")||o.hasClass(n.sticky_class)?(i.settings.sticky_class=n.sticky_class,i.settings.sticky_topbar=t,t.data("height",o.outerHeight()),t.data("stickyoffset",o.offset().top)):t.data("height",t.outerHeight()),n.assembled||i.assemble(t),n.is_hover?i.S(".has-dropdown",t).addClass("not-click"):i.S(".has-dropdown",t).removeClass("not-click"),i.add_custom_rule(".f-topbar-fixed { padding-top: "+t.data("height")+"px }"),o.hasClass("fixed")&&i.S("body").addClass("f-topbar-fixed")})},toggle:function(n){var r=this;if(n)var i=r.S(n).closest("["+this.attr_name()+"]");else var i=r.S("["+this.attr_name()+"]");var s=i.data(this.attr_name(!0)+"-init"),o=r.S("section, .section",i);r.breakpoint()&&(r.rtl?(o.css({right:"0%"}),e(">.name",o).css({right:"100%"})):(o.css({left:"0%"}),e(">.name",o).css({left:"100%"})),r.S("li.moved",o).removeClass("moved"),i.data("index",0),i.toggleClass("expanded").css("height","")),s.scrolltop?i.hasClass("expanded")?i.parent().hasClass("fixed")&&(s.scrolltop?(i.parent().removeClass("fixed"),i.addClass("fixed"),r.S("body").removeClass("f-topbar-fixed"),t.scrollTo(0,0)):i.parent().removeClass("expanded")):i.hasClass("fixed")&&(i.parent().addClass("fixed"),i.removeClass("fixed"),r.S("body").addClass("f-topbar-fixed")):(i.parent().hasClass(r.settings.sticky_class)&&i.parent().addClass("fixed"),i.parent().hasClass("fixed")&&(i.hasClass("expanded")?(i.addClass("fixed"),i.parent().addClass("expanded"),r.S("body").addClass("f-topbar-fixed")):(i.removeClass("fixed"),i.parent().removeClass("expanded"),r.update_sticky_positioning())))},timer:null,events:function(e){var n=this,r=this.S;r(this.scope).off(".topbar").on("click.fndtn.topbar","["+this.attr_name()+"] .toggle-topbar",function(e){e.preventDefault(),n.toggle(this)}).on("click.fndtn.topbar","["+this.attr_name()+"] li.has-dropdown",function(e){var t=r(this),i=r(e.target),s=t.closest("["+n.attr_name()+"]"),o=s.data(n.attr_name(!0)+"-init");if(i.data("revealId")){n.toggle();return}if(n.breakpoint())return;if(o.is_hover&&!Modernizr.touch)return;e.stopImmediatePropagation(),t.hasClass("hover")?(t.removeClass("hover").find("li").removeClass("hover"),t.parents("li.hover").removeClass("hover")):(t.addClass("hover"),i[0].nodeName==="A"&&i.parent().hasClass("has-dropdown")&&e.preventDefault())}).on("click.fndtn.topbar","["+this.attr_name()+"] .has-dropdown>a",function(e){if(n.breakpoint()){e.preventDefault();var t=r(this),i=t.closest("["+n.attr_name()+"]"),s=i.find("section, .section"),o=t.next(".dropdown").outerHeight(),u=t.closest("li");i.data("index",i.data("index")+1),u.addClass("moved"),n.rtl?(s.css({right:-(100*i.data("index"))+"%"}),s.find(">.name").css({right:100*i.data("index")+"%"})):(s.css({left:-(100*i.data("index"))+"%"}),s.find(">.name").css({left:100*i.data("index")+"%"})),i.css("height",t.siblings("ul").outerHeight(!0)+i.data("height"))}}),r(t).off(".topbar").on("resize.fndtn.topbar",n.throttle(function(){n.resize.call(n)},50)).trigger("resize"),r("body").off(".topbar").on("click.fndtn.topbar touchstart.fndtn.topbar",function(e){var t=r(e.target).closest("li").closest("li.hover");if(t.length>0)return;r("["+n.attr_name()+"] li").removeClass("hover")}),r(this.scope).on("click.fndtn.topbar","["+this.attr_name()+"] .has-dropdown .back",function(e){e.preventDefault();var t=r(this),i=t.closest("["+n.attr_name()+"]"),s=i.find("section, .section"),o=i.data(n.attr_name(!0)+"-init"),u=t.closest("li.moved"),a=u.parent();i.data("index",i.data("index")-1),n.rtl?(s.css({right:-(100*i.data("index"))+"%"}),s.find(">.name").css({right:100*i.data("index")+"%"})):(s.css({left:-(100*i.data("index"))+"%"}),s.find(">.name").css({left:100*i.data("index")+"%"})),i.data("index")===0?i.css("height",""):i.css("height",a.outerHeight(!0)+i.data("height")),setTimeout(function(){u.removeClass("moved")},300)})},resize:function(){var e=this;e.S("["+this.attr_name()+"]").each(function(){var t=e.S(this),r=t.data(e.attr_name(!0)+"-init"),i=t.parent("."+e.settings.sticky_class),s;if(!e.breakpoint()){var o=t.hasClass("expanded");t.css("height","").removeClass("expanded").find("li").removeClass("hover"),o&&e.toggle(t)}i.length>0&&(i.hasClass("fixed")?(i.removeClass("fixed"),s=i.offset().top,e.S(n.body).hasClass("f-topbar-fixed")&&(s-=t.data("height")),t.data("stickyoffset",s),i.addClass("fixed")):(s=i.offset().top,t.data("stickyoffset",s)))})},breakpoint:function(){return!matchMedia(Foundation.media_queries.topbar).matches},assemble:function(t){var n=this,r=t.data(this.attr_name(!0)+"-init"),i=n.S("section",t),s=e("> ul",t).first();i.detach(),n.S(".has-dropdown>a",i).each(function(){var t=n.S(this),i=t.siblings(".dropdown"),s=t.attr("href");if(!i.find(".title.back").length){if(r.mobile_show_parent_link&&s&&s.length>1)var o=e('
    2. '+t.text()+"
    3. ");else var o=e('
    4. ');r.custom_back_text==1?e("h5>a",o).html(r.back_text):e("h5>a",o).html("« "+t.html()),i.prepend(o)}}),i.appendTo(t),this.sticky(),this.assembled(t)},assembled:function(t){t.data(this.attr_name(!0),e.extend({},t.data(this.attr_name(!0)),{assembled:!0}))},height:function(t){var n=0,r=this;return e("> li",t).each(function(){n+=r.S(this).outerHeight(!0)}),n},sticky:function(){var e=this.S(t),n=this;this.S(t).on("scroll",function(){n.update_sticky_positioning()})},update_sticky_positioning:function(){var e="."+this.settings.sticky_class,n=this.S(t),r=this;if(r.S(e).length>0){var i=this.settings.sticky_topbar.data("stickyoffset");r.S(e).hasClass("expanded")||(n.scrollTop()>i?r.S(e).hasClass("fixed")||(r.S(e).addClass("fixed"),r.S("body").addClass("f-topbar-fixed")):n.scrollTop()<=i&&r.S(e).hasClass("fixed")&&(r.S(e).removeClass("fixed"),r.S("body").removeClass("f-topbar-fixed")))}},off:function(){this.S(this.scope).off(".fndtn.topbar"),this.S(t).off(".fndtn.topbar")},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.accordion={name:"accordion",version:"5.1.1",settings:{active_class:"active",toggleable:!0},init:function(e,t,n){this.bindings(t,n)},events:function(){var t=this,n=this.S;n(this.scope).off(".fndtn.accordion").on("click.fndtn.accordion","["+this.attr_name()+"] > dd > a",function(r){var i=n(this).closest("["+t.attr_name()+"]"),s=n("#"+this.href.split("#")[1]),o=n("dd > .content",i),u=e("> dd",i),a=i.data(t.attr_name(!0)+"-init"),f=n("dd > .content."+a.active_class,i),l=n("dd."+a.active_class,i);r.preventDefault();if(f[0]==s[0]&&a.toggleable)return l.toggleClass(a.active_class,!1),s.toggleClass(a.active_class,!1);o.removeClass(a.active_class),u.removeClass(a.active_class),s.addClass(a.active_class).parent().addClass(a.active_class)})},off:function(){},reflow:function(){}}}(jQuery,this,this.document),function(e,t,n,r){"use strict";Foundation.libs.offcanvas={name:"offcanvas",version:"5.1.1",settings:{},init:function(e,t,n){this.events()},events:function(){var e=this.S;e(this.scope).off(".offcanvas").on("click.fndtn.offcanvas",".left-off-canvas-toggle",function(t){t.preventDefault(),e(this).closest(".off-canvas-wrap").toggleClass("move-right")}).on("click.fndtn.offcanvas",".exit-off-canvas",function(t){t.preventDefault(),e(".off-canvas-wrap").removeClass("move-right")}).on("click.fndtn.offcanvas",".right-off-canvas-toggle",function(t){t.preventDefault(),e(this).closest(".off-canvas-wrap").toggleClass("move-left")}).on("click.fndtn.offcanvas",".exit-off-canvas",function(t){t.preventDefault(),e(".off-canvas-wrap").removeClass("move-left")})},reflow:function(){}}}(jQuery,this,this.document); diff --git a/coin/static/js/foundation/foundation.abide.js b/coin/static/js/foundation/foundation.abide.js deleted file mode 100644 index 338d1226fc79364c110990655248c644197a4e72..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.abide.js +++ /dev/null @@ -1,256 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.abide = { - name : 'abide', - - version : '5.1.1', - - settings : { - live_validate : true, - focus_on_invalid : true, - error_labels: true, // labels with a for="inputId" will recieve an `error` class - timeout : 1000, - patterns : { - alpha: /^[a-zA-Z]+$/, - alpha_numeric : /^[a-zA-Z0-9]+$/, - integer: /^\d+$/, - number: /-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/, - - // generic password: upper-case, lower-case, number/special character, and min 8 characters - password : /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, - - // amex, visa, diners - card : /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/, - cvv : /^([0-9]){3,4}$/, - - // http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address - email : /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/, - - url: /(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/, - // abc.de - domain: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/, - - datetime: /([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))/, - // YYYY-MM-DD - date: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))/, - // HH:MM:SS - time : /(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}/, - dateISO: /\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/, - // MM/DD/YYYY - month_day_year : /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/, - - // #FFF or #FFFFFF - color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ - } - }, - - timer : null, - - init : function (scope, method, options) { - this.bindings(method, options); - }, - - events : function (scope) { - var self = this, - form = self.S(scope).attr('novalidate', 'novalidate'), - settings = form.data(this.attr_name(true) + '-init'); - - this.invalid_attr = this.add_namespace('data-invalid'); - - form - .off('.abide') - .on('submit.fndtn.abide validate.fndtn.abide', function (e) { - var is_ajax = /ajax/i.test(self.S(this).attr(self.attr_name())); - return self.validate(self.S(this).find('input, textarea, select').get(), e, is_ajax); - }) - .on('reset', function() { - return self.reset($(this)); - }) - .find('input, textarea, select') - .off('.abide') - .on('blur.fndtn.abide change.fndtn.abide', function (e) { - self.validate([this], e); - }) - .on('keydown.fndtn.abide', function (e) { - var settings = $(this).closest('form').data('abide-init'); - if (settings.live_validate === true) { - clearTimeout(self.timer); - self.timer = setTimeout(function () { - self.validate([this], e); - }.bind(this), settings.timeout); - } - }); - }, - - reset : function (form) { - form.removeAttr(this.invalid_attr); - $(this.invalid_attr, form).removeAttr(this.invalid_attr); - $('.error', form).not('small').removeClass('error'); - }, - - validate : function (els, e, is_ajax) { - var validations = this.parse_patterns(els), - validation_count = validations.length, - form = this.S(els[0]).closest('form'), - submit_event = /submit/.test(e.type); - - // Has to count up to make sure the focus gets applied to the top error - for (var i=0; i < validation_count; i++) { - if (!validations[i] && (submit_event || is_ajax)) { - if (this.settings.focus_on_invalid) els[i].focus(); - form.trigger('invalid'); - this.S(els[i]).closest('form').attr(this.invalid_attr, ''); - return false; - } - } - - if (submit_event || is_ajax) { - form.trigger('valid'); - } - - form.removeAttr(this.invalid_attr); - - if (is_ajax) return false; - - return true; - }, - - parse_patterns : function (els) { - var i = els.length, - el_patterns = []; - - while (i--) { - el_patterns.push(this.pattern(els[i])); - } - - return this.check_validation_and_apply_styles(el_patterns); - }, - - pattern : function (el) { - var type = el.getAttribute('type'), - required = typeof el.getAttribute('required') === 'string'; - - var pattern = el.getAttribute('pattern') || ''; - - if (this.settings.patterns.hasOwnProperty(pattern) && pattern.length > 0) { - return [el, this.settings.patterns[pattern], required]; - } else if (pattern.length > 0) { - return [el, new RegExp(pattern), required]; - } - - if (this.settings.patterns.hasOwnProperty(type)) { - return [el, this.settings.patterns[type], required]; - } - - pattern = /.*/; - - return [el, pattern, required]; - }, - - check_validation_and_apply_styles : function (el_patterns) { - var i = el_patterns.length, - validations = []; - - while (i--) { - var el = el_patterns[i][0], - required = el_patterns[i][2], - value = el.value, - direct_parent = this.S(el).parent(), - is_equal = el.getAttribute(this.add_namespace('data-equalto')), - is_radio = el.type === "radio", - is_checkbox = el.type === "checkbox", - label = this.S('label[for="' + el.getAttribute('id') + '"]'), - valid_length = (required) ? (el.value.length > 0) : true; - - var parent; - - if (!direct_parent.is('label')) { - parent = direct_parent; - } else { - parent = direct_parent.parent(); - } - - if (is_radio && required) { - validations.push(this.valid_radio(el, required)); - } else if (is_checkbox && required) { - validations.push(this.valid_checkbox(el, required)); - } else if (is_equal && required) { - validations.push(this.valid_equal(el, required, parent)); - } else { - - if (el_patterns[i][1].test(value) && valid_length || - !required && el.value.length < 1) { - this.S(el).removeAttr(this.invalid_attr); - parent.removeClass('error'); - if (label.length > 0 && this.settings.error_labels) label.removeClass('error'); - - validations.push(true); - $(el).triggerHandler('valid'); - } else { - this.S(el).attr(this.invalid_attr, ''); - parent.addClass('error'); - if (label.length > 0 && this.settings.error_labels) label.addClass('error'); - - validations.push(false); - $(el).triggerHandler('invalid'); - } - } - } - - return validations; - }, - - valid_checkbox : function(el, required) { - var el = this.S(el), - valid = (el.is(':checked') || !required); - - if (valid) { - el.removeAttr(this.invalid_attr).parent().removeClass('error'); - } else { - el.attr(this.invalid_attr, '').parent().addClass('error'); - } - - return valid; - }, - - valid_radio : function (el, required) { - var name = el.getAttribute('name'), - group = document.getElementsByName(name), - count = group.length, - valid = false; - - // Has to count up to make sure the focus gets applied to the top error - for (var i=0; i < count; i++) { - if (group[i].checked) valid = true; - } - - // Has to count up to make sure the focus gets applied to the top error - for (var i=0; i < count; i++) { - if (valid) { - this.S(group[i]).removeAttr(this.invalid_attr).parent().removeClass('error'); - } else { - this.S(group[i]).attr(this.invalid_attr, '').parent().addClass('error'); - } - } - - return valid; - }, - - valid_equal: function(el, required, parent) { - var from = document.getElementById(el.getAttribute(this.add_namespace('data-equalto'))).value, - to = el.value, - valid = (from === to); - - if (valid) { - this.S(el).removeAttr(this.invalid_attr); - parent.removeClass('error'); - } else { - this.S(el).attr(this.invalid_attr, ''); - parent.addClass('error'); - } - - return valid; - } - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.accordion.js b/coin/static/js/foundation/foundation.accordion.js deleted file mode 100644 index 0f84f7f8f71c5b3773beab30cdfcec2b76a292d3..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.accordion.js +++ /dev/null @@ -1,49 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.accordion = { - name : 'accordion', - - version : '5.1.1', - - settings : { - active_class: 'active', - toggleable: true - }, - - init : function (scope, method, options) { - this.bindings(method, options); - }, - - events : function () { - var self = this; - var S = this.S; - S(this.scope) - .off('.fndtn.accordion') - .on('click.fndtn.accordion', '[' + this.attr_name() + '] > dd > a', function (e) { - var accordion = S(this).closest('[' + self.attr_name() + ']'), - target = S('#' + this.href.split('#')[1]), - siblings = S('dd > .content', accordion), - aunts = $('> dd', accordion), - settings = accordion.data(self.attr_name(true) + '-init'), - active_content = S('dd > .content.' + settings.active_class, accordion), - active_parent = S('dd.' + settings.active_class, accordion); - - e.preventDefault(); - - if (active_content[0] == target[0] && settings.toggleable) { - active_parent.toggleClass(settings.active_class, false); - return target.toggleClass(settings.active_class, false); - } - - siblings.removeClass(settings.active_class); - aunts.removeClass(settings.active_class); - target.addClass(settings.active_class).parent().addClass(settings.active_class); - }); - }, - - off : function () {}, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.alert.js b/coin/static/js/foundation/foundation.alert.js deleted file mode 100644 index 129742705d605e3d1a247f14948c03a8a7ab6ca0..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.alert.js +++ /dev/null @@ -1,37 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.alert = { - name : 'alert', - - version : '5.1.1', - - settings : { - animation: 'fadeOut', - speed: 300, // fade out speed - callback: function (){} - }, - - init : function (scope, method, options) { - this.bindings(method, options); - }, - - events : function () { - var self = this, - S = this.S; - - $(this.scope).off('.alert').on('click.fndtn.alert', '[' + this.attr_name() + '] a.close', function (e) { - var alertBox = S(this).closest('[' + self.attr_name() + ']'), - settings = alertBox.data(self.attr_name(true) + '-init') || self.settings; - - e.preventDefault(); - alertBox[settings.animation](settings.speed, function () { - S(this).trigger('closed').remove(); - settings.callback(); - }); - }); - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.clearing.js b/coin/static/js/foundation/foundation.clearing.js deleted file mode 100644 index b9b6f91a1db698a8343d6ce11a2ffd3574ba323b..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.clearing.js +++ /dev/null @@ -1,485 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.clearing = { - name : 'clearing', - - version: '5.1.1', - - settings : { - templates : { - viewing : '×' + - '' - }, - - // comma delimited list of selectors that, on click, will close clearing, - // add 'div.clearing-blackout, div.visible-img' to close on background click - close_selectors : '.clearing-close', - - touch_label : '← Swipe to Advance →', - - // event initializers and locks - init : false, - locked : false - }, - - init : function (scope, method, options) { - var self = this; - Foundation.inherit(this, 'throttle image_loaded'); - - this.bindings(method, options); - - if (self.S(this.scope).is('[' + this.attr_name() + ']')) { - this.assemble(self.S('li', this.scope)); - } else { - self.S('[' + this.attr_name() + ']', this.scope).each(function () { - self.assemble(self.S('li', this)); - }); - } - }, - - events : function (scope) { - var self = this, - S = self.S; - - S(this.scope) - .off('.clearing') - .on('click.fndtn.clearing', 'ul[' + this.attr_name() + '] li', - function (e, current, target) { - var current = current || S(this), - target = target || current, - next = current.next('li'), - settings = current.closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'), - image = S(e.target); - - e.preventDefault(); - - if (!settings) { - self.init(); - settings = current.closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'); - } - - // if clearing is open and the current image is - // clicked, go to the next image in sequence - if (target.hasClass('visible') && - current[0] === target[0] && - next.length > 0 && self.is_open(current)) { - target = next; - image = S('img', target); - } - - // set current and target to the clicked li if not otherwise defined. - self.open(image, current, target); - self.update_paddles(target); - }) - - .on('click.fndtn.clearing', '.clearing-main-next', - function (e) { self.nav(e, 'next') }) - .on('click.fndtn.clearing', '.clearing-main-prev', - function (e) { self.nav(e, 'prev') }) - .on('click.fndtn.clearing', this.settings.close_selectors, - function (e) { Foundation.libs.clearing.close(e, this) }) - .on('keydown.fndtn.clearing', - function (e) { self.keydown(e) }); - - S(window).off('.clearing').on('resize.fndtn.clearing', - function () { self.resize() }); - - this.swipe_events(scope); - }, - - swipe_events : function (scope) { - var self = this, - S = self.S; - - S(this.scope) - .on('touchstart.fndtn.clearing', '.visible-img', function(e) { - if (!e.touches) { e = e.originalEvent; } - var data = { - start_page_x: e.touches[0].pageX, - start_page_y: e.touches[0].pageY, - start_time: (new Date()).getTime(), - delta_x: 0, - is_scrolling: undefined - }; - - S(this).data('swipe-transition', data); - e.stopPropagation(); - }) - .on('touchmove.fndtn.clearing', '.visible-img', function(e) { - if (!e.touches) { e = e.originalEvent; } - // Ignore pinch/zoom events - if(e.touches.length > 1 || e.scale && e.scale !== 1) return; - - var data = S(this).data('swipe-transition'); - - if (typeof data === 'undefined') { - data = {}; - } - - data.delta_x = e.touches[0].pageX - data.start_page_x; - - if ( typeof data.is_scrolling === 'undefined') { - data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) ); - } - - if (!data.is_scrolling && !data.active) { - e.preventDefault(); - var direction = (data.delta_x < 0) ? 'next' : 'prev'; - data.active = true; - self.nav(e, direction); - } - }) - .on('touchend.fndtn.clearing', '.visible-img', function(e) { - S(this).data('swipe-transition', {}); - e.stopPropagation(); - }); - }, - - assemble : function ($li) { - var $el = $li.parent(); - - if ($el.parent().hasClass('carousel')) return; - $el.after('
      '); - - var holder = this.S('#foundationClearingHolder'), - settings = $el.data(this.attr_name(true) + '-init'), - grid = $el.detach(), - data = { - grid: '', - viewing: settings.templates.viewing - }, - wrapper = '
      ' + data.viewing + - data.grid + '
      ', - touch_label = this.settings.touch_label; - - if (Modernizr.touch) { - wrapper = $(wrapper).find('.clearing-touch-label').html(touch_label).end(); - } - - holder.after(wrapper).remove(); - }, - - open : function ($image, current, target) { - var self = this, - root = target.closest('.clearing-assembled'), - container = self.S('div', root).first(), - visible_image = self.S('.visible-img', container), - image = self.S('img', visible_image).not($image), - label = self.S('.clearing-touch-label', container); - - if (!this.locked()) { - // set the image to the selected thumbnail - image - .attr('src', this.load($image)) - .css('visibility', 'hidden'); - - this.image_loaded(image, function () { - image.css('visibility', 'visible'); - // toggle the gallery - root.addClass('clearing-blackout'); - container.addClass('clearing-container'); - visible_image.show(); - this.fix_height(target) - .caption(self.S('.clearing-caption', visible_image), $image) - .center_and_label(image,label) - .shift(current, target, function () { - target.siblings().removeClass('visible'); - target.addClass('visible'); - }); - }.bind(this)); - } - }, - - close : function (e, el) { - e.preventDefault(); - - var root = (function (target) { - if (/blackout/.test(target.selector)) { - return target; - } else { - return target.closest('.clearing-blackout'); - } - }($(el))), container, visible_image; - - if (el === e.target && root) { - container = $('div', root).first(); - visible_image = $('.visible-img', container); - this.settings.prev_index = 0; - $('ul[' + this.attr_name() + ']', root) - .attr('style', '').closest('.clearing-blackout') - .removeClass('clearing-blackout'); - container.removeClass('clearing-container'); - visible_image.hide(); - } - - return false; - }, - - is_open : function (current) { - return current.parent().prop('style').length > 0; - }, - - keydown : function (e) { - var clearing = $('ul[' + this.attr_name() + ']', '.clearing-blackout'), - NEXT_KEY = this.rtl ? 37 : 39, - PREV_KEY = this.rtl ? 39 : 37, - ESC_KEY = 27; - - if (e.which === NEXT_KEY) this.go(clearing, 'next'); - if (e.which === PREV_KEY) this.go(clearing, 'prev'); - if (e.which === ESC_KEY) this.S('a.clearing-close').trigger('click'); - }, - - nav : function (e, direction) { - var clearing = $('ul[' + this.attr_name() + ']', '.clearing-blackout'); - - e.preventDefault(); - this.go(clearing, direction); - }, - - resize : function () { - var image = $('img', '.clearing-blackout .visible-img'), - label = $('.clearing-touch-label', '.clearing-blackout'); - - if (image.length) { - this.center_and_label(image, label); - } - }, - - // visual adjustments - fix_height : function (target) { - var lis = target.parent().children(), - self = this; - - lis.each(function () { - var li = self.S(this), - image = li.find('img'); - - if (li.height() > image.outerHeight()) { - li.addClass('fix-height'); - } - }) - .closest('ul') - .width(lis.length * 100 + '%'); - - return this; - }, - - update_paddles : function (target) { - var visible_image = target - .closest('.carousel') - .siblings('.visible-img'); - - if (target.next().length > 0) { - this.S('.clearing-main-next', visible_image) - .removeClass('disabled'); - } else { - this.S('.clearing-main-next', visible_image) - .addClass('disabled'); - } - - if (target.prev().length > 0) { - this.S('.clearing-main-prev', visible_image) - .removeClass('disabled'); - } else { - this.S('.clearing-main-prev', visible_image) - .addClass('disabled'); - } - }, - - center_and_label : function (target, label) { - if (!this.rtl) { - target.css({ - marginLeft : -(target.outerWidth() / 2), - marginTop : -(target.outerHeight() / 2) - }); - label.css({ - marginLeft : -(label.outerWidth() / 2), - marginTop : -(target.outerHeight() / 2)-label.outerHeight()-10 - }); - } else { - target.css({ - marginRight : -(target.outerWidth() / 2), - marginTop : -(target.outerHeight() / 2), - left: 'auto', - right: '50%' - }); - label.css({ - marginRight : -(label.outerWidth() / 2), - marginTop : -(target.outerHeight() / 2)-label.outerHeight()-10, - left: 'auto', - right: '50%' - }); - } - return this; - }, - - // image loading and preloading - - load : function ($image) { - if ($image[0].nodeName === "A") { - var href = $image.attr('href'); - } else { - var href = $image.parent().attr('href'); - } - - this.preload($image); - - if (href) return href; - return $image.attr('src'); - }, - - preload : function ($image) { - this - .img($image.closest('li').next()) - .img($image.closest('li').prev()); - }, - - img : function (img) { - if (img.length) { - var new_img = new Image(), - new_a = this.S('a', img); - - if (new_a.length) { - new_img.src = new_a.attr('href'); - } else { - new_img.src = this.S('img', img).attr('src'); - } - } - return this; - }, - - // image caption - - caption : function (container, $image) { - var caption = $image.data('caption'); - - if (caption) { - container - .html(caption) - .show(); - } else { - container - .text('') - .hide(); - } - return this; - }, - - // directional methods - - go : function ($ul, direction) { - var current = this.S('.visible', $ul), - target = current[direction](); - - if (target.length) { - this.S('img', target) - .trigger('click', [current, target]); - } - }, - - shift : function (current, target, callback) { - var clearing = target.parent(), - old_index = this.settings.prev_index || target.index(), - direction = this.direction(clearing, current, target), - dir = this.rtl ? 'right' : 'left', - left = parseInt(clearing.css('left'), 10), - width = target.outerWidth(), - skip_shift; - - var dir_obj = {}; - - // we use jQuery animate instead of CSS transitions because we - // need a callback to unlock the next animation - // needs support for RTL ** - if (target.index() !== old_index && !/skip/.test(direction)){ - if (/left/.test(direction)) { - this.lock(); - dir_obj[dir] = left + width; - clearing.animate(dir_obj, 300, this.unlock()); - } else if (/right/.test(direction)) { - this.lock(); - dir_obj[dir] = left - width; - clearing.animate(dir_obj, 300, this.unlock()); - } - } else if (/skip/.test(direction)) { - // the target image is not adjacent to the current image, so - // do we scroll right or not - skip_shift = target.index() - this.settings.up_count; - this.lock(); - - if (skip_shift > 0) { - dir_obj[dir] = -(skip_shift * width); - clearing.animate(dir_obj, 300, this.unlock()); - } else { - dir_obj[dir] = 0; - clearing.animate(dir_obj, 300, this.unlock()); - } - } - - callback(); - }, - - direction : function ($el, current, target) { - var lis = this.S('li', $el), - li_width = lis.outerWidth() + (lis.outerWidth() / 4), - up_count = Math.floor(this.S('.clearing-container').outerWidth() / li_width) - 1, - target_index = lis.index(target), - response; - - this.settings.up_count = up_count; - - if (this.adjacent(this.settings.prev_index, target_index)) { - if ((target_index > up_count) - && target_index > this.settings.prev_index) { - response = 'right'; - } else if ((target_index > up_count - 1) - && target_index <= this.settings.prev_index) { - response = 'left'; - } else { - response = false; - } - } else { - response = 'skip'; - } - - this.settings.prev_index = target_index; - - return response; - }, - - adjacent : function (current_index, target_index) { - for (var i = target_index + 1; i >= target_index - 1; i--) { - if (i === current_index) return true; - } - return false; - }, - - // lock management - - lock : function () { - this.settings.locked = true; - }, - - unlock : function () { - this.settings.locked = false; - }, - - locked : function () { - return this.settings.locked; - }, - - off : function () { - this.S(this.scope).off('.fndtn.clearing'); - this.S(window).off('.fndtn.clearing'); - }, - - reflow : function () { - this.init(); - } - }; - -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.dropdown.js b/coin/static/js/foundation/foundation.dropdown.js deleted file mode 100644 index 8a75c5c5c6787c989fa75ffb885d424727a71561..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.dropdown.js +++ /dev/null @@ -1,208 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.dropdown = { - name : 'dropdown', - - version : '5.1.1', - - settings : { - active_class: 'open', - is_hover: false, - opened: function(){}, - closed: function(){} - }, - - init : function (scope, method, options) { - Foundation.inherit(this, 'throttle'); - - this.bindings(method, options); - }, - - events : function (scope) { - var self = this, - S = self.S; - - S(this.scope) - .off('.dropdown') - .on('click.fndtn.dropdown', '[' + this.attr_name() + ']', function (e) { - var settings = S(this).data(self.attr_name(true) + '-init') || self.settings; - e.preventDefault(); - if (!settings.is_hover || Modernizr.touch) self.toggle(S(this)); - }) - .on('mouseenter.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) { - var $this = S(this); - clearTimeout(self.timeout); - - if ($this.data(self.data_attr())) { - var dropdown = S('#' + $this.data(self.data_attr())), - target = $this; - } else { - var dropdown = $this; - target = S("[" + self.attr_name() + "='" + dropdown.attr('id') + "']"); - } - - var settings = target.data(self.attr_name(true) + '-init') || self.settings; - - if(S(e.target).data(self.data_attr()) && settings.is_hover) { - self.closeall.call(self); - } - - if (settings.is_hover) self.open.apply(self, [dropdown, target]); - }) - .on('mouseleave.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) { - var $this = S(this); - self.timeout = setTimeout(function () { - if ($this.data(self.data_attr())) { - var settings = $this.data(self.data_attr(true) + '-init') || self.settings; - if (settings.is_hover) self.close.call(self, S('#' + $this.data(self.data_attr()))); - } else { - var target = S('[' + self.attr_name() + '="' + S(this).attr('id') + '"]'), - settings = target.data(self.attr_name(true) + '-init') || self.settings; - if (settings.is_hover) self.close.call(self, $this); - } - }.bind(this), 150); - }) - .on('click.fndtn.dropdown', function (e) { - var parent = S(e.target).closest('[' + self.attr_name() + '-content]'); - - if (S(e.target).data(self.data_attr()) || S(e.target).parent().data(self.data_attr())) { - return; - } - if (!(S(e.target).data('revealId')) && - (parent.length > 0 && (S(e.target).is('[' + self.attr_name() + '-content]') || - $.contains(parent.first()[0], e.target)))) { - e.stopPropagation(); - return; - } - - self.close.call(self, S('[' + self.attr_name() + '-content]')); - }) - .on('opened.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () { - self.settings.opened.call(this); - }) - .on('closed.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () { - self.settings.closed.call(this); - }); - - S(window) - .off('.dropdown') - .on('resize.fndtn.dropdown', self.throttle(function () { - self.resize.call(self); - }, 50)).trigger('resize'); - }, - - close: function (dropdown) { - var self = this; - dropdown.each(function () { - if (self.S(this).hasClass(self.settings.active_class)) { - self.S(this) - .css(Foundation.rtl ? 'right':'left', '-99999px') - .removeClass(self.settings.active_class); - self.S(this).trigger('closed'); - } - }); - }, - - closeall: function() { - var self = this; - $.each(self.S('[' + this.attr_name() + '-content]'), function() { - self.close.call(self, self.S(this)) - }); - }, - - open: function (dropdown, target) { - this - .css(dropdown - .addClass(this.settings.active_class), target); - dropdown.trigger('opened'); - }, - - data_attr: function () { - if (this.namespace.length > 0) { - return this.namespace + '-' + this.name; - } - - return this.name; - }, - - toggle : function (target) { - var dropdown = this.S('#' + target.data(this.data_attr())); - if (dropdown.length === 0) { - // No dropdown found, not continuing - return; - } - - this.close.call(this, this.S('[' + this.attr_name() + '-content]').not(dropdown)); - - if (dropdown.hasClass(this.settings.active_class)) { - this.close.call(this, dropdown); - } else { - this.close.call(this, this.S('[' + this.attr_name() + '-content]')) - this.open.call(this, dropdown, target); - } - }, - - resize : function () { - var dropdown = this.S('[' + this.attr_name() + '-content].open'), - target = this.S("[" + this.attr_name() + "='" + dropdown.attr('id') + "']"); - - if (dropdown.length && target.length) { - this.css(dropdown, target); - } - }, - - css : function (dropdown, target) { - var offset_parent = dropdown.offsetParent(), - position = target.offset(); - - position.top -= offset_parent.offset().top; - position.left -= offset_parent.offset().left; - - if (this.small()) { - dropdown.css({ - position : 'absolute', - width: '95%', - 'max-width': 'none', - top: position.top + target.outerHeight() - }); - dropdown.css(Foundation.rtl ? 'right':'left', '2.5%'); - } else { - if (!Foundation.rtl && this.S(window).width() > dropdown.outerWidth() + target.offset().left) { - var left = position.left; - if (dropdown.hasClass('right')) { - dropdown.removeClass('right'); - } - } else { - if (!dropdown.hasClass('right')) { - dropdown.addClass('right'); - } - var left = position.left - (dropdown.outerWidth() - target.outerWidth()); - } - - dropdown.attr('style', '').css({ - position : 'absolute', - top: position.top + target.outerHeight(), - left: left - }); - } - - return dropdown; - }, - - small : function () { - return matchMedia(Foundation.media_queries.small).matches && - !matchMedia(Foundation.media_queries.medium).matches; - }, - - off: function () { - this.S(this.scope).off('.fndtn.dropdown'); - this.S('html, body').off('.fndtn.dropdown'); - this.S(window).off('.fndtn.dropdown'); - this.S('[data-dropdown-content]').off('.fndtn.dropdown'); - this.settings.init = false; - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.equalizer.js b/coin/static/js/foundation/foundation.equalizer.js deleted file mode 100644 index b68c367c363a9d21b68ccff48a989ccfe0acde7e..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.equalizer.js +++ /dev/null @@ -1,64 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.equalizer = { - name : 'equalizer', - - version : '5.1.1', - - settings : { - use_tallest: true, - before_height_change: $.noop, - after_height_change: $.noop - }, - - init : function (scope, method, options) { - this.bindings(method, options); - this.reflow(); - }, - - events : function () { - this.S(window).off('.equalizer').on('resize.fndtn.equalizer', function(e){ - this.reflow(); - }.bind(this)); - }, - - equalize: function(equalizer) { - var isStacked = false, - vals = equalizer.find('[' + this.attr_name() + '-watch]'), - firstTopOffset = vals.first().offset().top, - settings = equalizer.data(this.attr_name(true)+'-init'); - - if (vals.length === 0) return; - settings.before_height_change(); - equalizer.trigger('before-height-change'); - vals.height('inherit'); - vals.each(function(){ - var el = $(this); - if (el.offset().top !== firstTopOffset) { - isStacked = true; - } - }); - if (isStacked) return; - - var heights = vals.map(function(){ return $(this).outerHeight() }); - if (settings.use_tallest) { - var max = Math.max.apply(null, heights); - vals.height(max); - } else { - var min = Math.min.apply(null, heights); - vals.height(min); - } - settings.after_height_change(); - equalizer.trigger('after-height-change'); - }, - - reflow : function () { - var self = this; - - this.S('[' + this.attr_name() + ']', this.scope).each(function(){ - self.equalize($(this)); - }); - } - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.interchange.js b/coin/static/js/foundation/foundation.interchange.js deleted file mode 100644 index ca8697ccc66600cb22187c62fb5ecb50efdeaedd..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.interchange.js +++ /dev/null @@ -1,326 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.interchange = { - name : 'interchange', - - version : '5.1.1', - - cache : {}, - - images_loaded : false, - nodes_loaded : false, - - settings : { - load_attr : 'interchange', - - named_queries : { - 'default' : 'only screen', - small : Foundation.media_queries.small, - medium : Foundation.media_queries.medium, - large : Foundation.media_queries.large, - xlarge : Foundation.media_queries.xlarge, - xxlarge: Foundation.media_queries.xxlarge, - landscape : 'only screen and (orientation: landscape)', - portrait : 'only screen and (orientation: portrait)', - retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' + - 'only screen and (min--moz-device-pixel-ratio: 2),' + - 'only screen and (-o-min-device-pixel-ratio: 2/1),' + - 'only screen and (min-device-pixel-ratio: 2),' + - 'only screen and (min-resolution: 192dpi),' + - 'only screen and (min-resolution: 2dppx)' - }, - - directives : { - replace: function (el, path, trigger) { - // The trigger argument, if called within the directive, fires - // an event named after the directive on the element, passing - // any parameters along to the event that you pass to trigger. - // - // ex. trigger(), trigger([a, b, c]), or trigger(a, b, c) - // - // This allows you to bind a callback like so: - // $('#interchangeContainer').on('replace', function (e, a, b, c) { - // console.log($(this).html(), a, b, c); - // }); - - if (/IMG/.test(el[0].nodeName)) { - var orig_path = el[0].src; - - if (new RegExp(path, 'i').test(orig_path)) return; - - el[0].src = path; - - return trigger(el[0].src); - } - var last_path = el.data(this.data_attr + '-last-path'); - - if (last_path == path) return; - - return $.get(path, function (response) { - el.html(response); - el.data(this.data_attr + '-last-path', path); - trigger(); - }); - - } - } - }, - - init : function (scope, method, options) { - Foundation.inherit(this, 'throttle random_str'); - - this.data_attr = this.set_data_attr(); - $.extend(true, this.settings, method, options); - - this.bindings(method, options); - this.load('images'); - this.load('nodes'); - }, - - events : function () { - var self = this; - - $(window) - .off('.interchange') - .on('resize.fndtn.interchange', self.throttle(function () { - self.resize(); - }, 50)); - - return this; - }, - - resize : function () { - var cache = this.cache; - - if(!this.images_loaded || !this.nodes_loaded) { - setTimeout($.proxy(this.resize, this), 50); - return; - } - - for (var uuid in cache) { - if (cache.hasOwnProperty(uuid)) { - var passed = this.results(uuid, cache[uuid]); - - if (passed) { - this.settings.directives[passed - .scenario[1]].call(this, passed.el, passed.scenario[0], function () { - if (arguments[0] instanceof Array) { - var args = arguments[0]; - } else { - var args = Array.prototype.slice.call(arguments, 0); - } - - passed.el.trigger(passed.scenario[1], args); - }); - } - } - } - - }, - - results : function (uuid, scenarios) { - var count = scenarios.length; - - if (count > 0) { - var el = this.S('[' + this.add_namespace('data-uuid') + '="' + uuid + '"]'); - - while (count--) { - var mq, rule = scenarios[count][2]; - if (this.settings.named_queries.hasOwnProperty(rule)) { - mq = matchMedia(this.settings.named_queries[rule]); - } else { - mq = matchMedia(rule); - } - if (mq.matches) { - return {el: el, scenario: scenarios[count]}; - } - } - } - - return false; - }, - - load : function (type, force_update) { - if (typeof this['cached_' + type] === 'undefined' || force_update) { - this['update_' + type](); - } - - return this['cached_' + type]; - }, - - update_images : function () { - var images = this.S('img[' + this.data_attr + ']'), - count = images.length, - i = count, - loaded_count = 0, - data_attr = this.data_attr; - - this.cache = {}; - this.cached_images = []; - this.images_loaded = (count === 0); - - while (i--) { - loaded_count++; - if (images[i]) { - var str = images[i].getAttribute(data_attr) || ''; - - if (str.length > 0) { - this.cached_images.push(images[i]); - } - } - - if (loaded_count === count) { - this.images_loaded = true; - this.enhance('images'); - } - } - - return this; - }, - - update_nodes : function () { - var nodes = this.S('[' + this.data_attr + ']').not('img'), - count = nodes.length, - i = count, - loaded_count = 0, - data_attr = this.data_attr; - - this.cached_nodes = []; - // Set nodes_loaded to true if there are no nodes - // this.nodes_loaded = false; - this.nodes_loaded = (count === 0); - - - while (i--) { - loaded_count++; - var str = nodes[i].getAttribute(data_attr) || ''; - - if (str.length > 0) { - this.cached_nodes.push(nodes[i]); - } - - if(loaded_count === count) { - this.nodes_loaded = true; - this.enhance('nodes'); - } - } - - return this; - }, - - enhance : function (type) { - var i = this['cached_' + type].length; - - while (i--) { - this.object($(this['cached_' + type][i])); - } - - return $(window).trigger('resize'); - }, - - parse_params : function (path, directive, mq) { - return [this.trim(path), this.convert_directive(directive), this.trim(mq)]; - }, - - convert_directive : function (directive) { - var trimmed = this.trim(directive); - - if (trimmed.length > 0) { - return trimmed; - } - - return 'replace'; - }, - - object : function(el) { - var raw_arr = this.parse_data_attr(el), - scenarios = [], - i = raw_arr.length; - - if (i > 0) { - while (i--) { - var split = raw_arr[i].split(/\((.*?)(\))$/); - - if (split.length > 1) { - var cached_split = split[0].split(','), - params = this.parse_params(cached_split[0], - cached_split[1], split[1]); - - scenarios.push(params); - } - } - } - - return this.store(el, scenarios); - }, - - uuid : function (separator) { - var delim = separator || "-", - self = this; - - function S4() { - return self.random_str(6); - } - - return (S4() + S4() + delim + S4() + delim + S4() - + delim + S4() + delim + S4() + S4() + S4()); - }, - - store : function (el, scenarios) { - var uuid = this.uuid(), - current_uuid = el.data(this.add_namespace('uuid', true)); - - if (this.cache[current_uuid]) return this.cache[current_uuid]; - - el.attr(this.add_namespace('data-uuid'), uuid); - - return this.cache[uuid] = scenarios; - }, - - trim : function(str) { - if (typeof str === 'string') { - return $.trim(str); - } - - return str; - }, - - set_data_attr: function (init) { - if (init) { - if (this.namespace.length > 0) { - return this.namespace + '-' + this.settings.load_attr; - } - - return this.settings.load_attr; - } - - if (this.namespace.length > 0) { - return 'data-' + this.namespace + '-' + this.settings.load_attr; - } - - return 'data-' + this.settings.load_attr; - }, - - parse_data_attr : function (el) { - var raw = el.attr(this.attr_name()).split(/\[(.*?)\]/), - i = raw.length, - output = []; - - while (i--) { - if (raw[i].replace(/[\W\d]+/, '').length > 4) { - output.push(raw[i]); - } - } - - return output; - }, - - reflow : function () { - this.load('images', true); - this.load('nodes', true); - } - - }; - -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.joyride.js b/coin/static/js/foundation/foundation.joyride.js deleted file mode 100644 index bee29b3a458ff45bdb9cd584dad6bb95cd917fcb..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.joyride.js +++ /dev/null @@ -1,848 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - var Modernizr = Modernizr || false; - - Foundation.libs.joyride = { - name : 'joyride', - - version : '5.1.1', - - defaults : { - expose : false, // turn on or off the expose feature - modal : true, // Whether to cover page with modal during the tour - tip_location : 'bottom', // 'top' or 'bottom' in relation to parent - nub_position : 'auto', // override on a per tooltip bases - scroll_speed : 1500, // Page scrolling speed in milliseconds, 0 = no scroll animation - scroll_animation : 'linear', // supports 'swing' and 'linear', extend with jQuery UI. - timer : 0, // 0 = no timer , all other numbers = timer in milliseconds - start_timer_on_click : true, // true or false - true requires clicking the first button start the timer - start_offset : 0, // the index of the tooltip you want to start on (index of the li) - next_button : true, // true or false to control whether a next button is used - tip_animation : 'fade', // 'pop' or 'fade' in each tip - pause_after : [], // array of indexes where to pause the tour after - exposed : [], // array of expose elements - tip_animation_fade_speed : 300, // when tipAnimation = 'fade' this is speed in milliseconds for the transition - cookie_monster : false, // true or false to control whether cookies are used - cookie_name : 'joyride', // Name the cookie you'll use - cookie_domain : false, // Will this cookie be attached to a domain, ie. '.notableapp.com' - cookie_expires : 365, // set when you would like the cookie to expire. - tip_container : 'body', // Where will the tip be attached - tip_location_patterns : { - top: ['bottom'], - bottom: [], // bottom should not need to be repositioned - left: ['right', 'top', 'bottom'], - right: ['left', 'top', 'bottom'] - }, - post_ride_callback : function (){}, // A method to call once the tour closes (canceled or complete) - post_step_callback : function (){}, // A method to call after each step - pre_step_callback : function (){}, // A method to call before each step - pre_ride_callback : function (){}, // A method to call before the tour starts (passed index, tip, and cloned exposed element) - post_expose_callback : function (){}, // A method to call after an element has been exposed - template : { // HTML segments for tip layout - link : '×', - timer : '
      ', - tip : '
      ', - wrapper : '
      ', - button : '', - modal : '
      ', - expose : '
      ', - expose_cover: '
      ' - }, - expose_add_class : '' // One or more space-separated class names to be added to exposed element - }, - - init : function (scope, method, options) { - Foundation.inherit(this, 'throttle random_str'); - - this.settings = this.defaults; - - this.bindings(method, options) - }, - - events : function () { - var self = this; - - $(this.scope) - .off('.joyride') - .on('click.fndtn.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) { - e.preventDefault(); - - if (this.settings.$li.next().length < 1) { - this.end(); - } else if (this.settings.timer > 0) { - clearTimeout(this.settings.automate); - this.hide(); - this.show(); - this.startTimer(); - } else { - this.hide(); - this.show(); - } - - }.bind(this)) - - .on('click.fndtn.joyride', '.joyride-close-tip', function (e) { - e.preventDefault(); - this.end(); - }.bind(this)); - - $(window) - .off('.joyride') - .on('resize.fndtn.joyride', self.throttle(function () { - if ($('[' + self.attr_name() + ']').length > 0 && self.settings.$next_tip) { - if (self.settings.exposed.length > 0) { - var $els = $(self.settings.exposed); - - $els.each(function () { - var $this = $(this); - self.un_expose($this); - self.expose($this); - }); - } - - if (self.is_phone()) { - self.pos_phone(); - } else { - self.pos_default(false, true); - } - } - }, 100)); - }, - - start : function () { - var self = this, - $this = $('[' + this.attr_name() + ']', this.scope), - integer_settings = ['timer', 'scrollSpeed', 'startOffset', 'tipAnimationFadeSpeed', 'cookieExpires'], - int_settings_count = integer_settings.length; - - if (!$this.length > 0) return; - - if (!this.settings.init) this.events(); - - this.settings = $this.data(this.attr_name(true) + '-init'); - - // non configureable settings - this.settings.$content_el = $this; - this.settings.$body = $(this.settings.tip_container); - this.settings.body_offset = $(this.settings.tip_container).position(); - this.settings.$tip_content = this.settings.$content_el.find('> li'); - this.settings.paused = false; - this.settings.attempts = 0; - - // can we create cookies? - if (typeof $.cookie !== 'function') { - this.settings.cookie_monster = false; - } - - // generate the tips and insert into dom. - if (!this.settings.cookie_monster || this.settings.cookie_monster && !$.cookie(this.settings.cookie_name)) { - this.settings.$tip_content.each(function (index) { - var $this = $(this); - this.settings = $.extend({}, self.defaults, self.data_options($this)) - - // Make sure that settings parsed from data_options are integers where necessary - var i = int_settings_count; - while (i--) { - self.settings[integer_settings[i]] = parseInt(self.settings[integer_settings[i]], 10); - } - self.create({$li : $this, index : index}); - }); - - // show first tip - if (!this.settings.start_timer_on_click && this.settings.timer > 0) { - this.show('init'); - this.startTimer(); - } else { - this.show('init'); - } - - } - }, - - resume : function () { - this.set_li(); - this.show(); - }, - - tip_template : function (opts) { - var $blank, content; - - opts.tip_class = opts.tip_class || ''; - - $blank = $(this.settings.template.tip).addClass(opts.tip_class); - content = $.trim($(opts.li).html()) + - this.button_text(opts.button_text) + - this.settings.template.link + - this.timer_instance(opts.index); - - $blank.append($(this.settings.template.wrapper)); - $blank.first().attr(this.add_namespace('data-index'), opts.index); - $('.joyride-content-wrapper', $blank).append(content); - - return $blank[0]; - }, - - timer_instance : function (index) { - var txt; - - if ((index === 0 && this.settings.start_timer_on_click && this.settings.timer > 0) || this.settings.timer === 0) { - txt = ''; - } else { - txt = $(this.settings.template.timer)[0].outerHTML; - } - return txt; - }, - - button_text : function (txt) { - if (this.settings.next_button) { - txt = $.trim(txt) || 'Next'; - txt = $(this.settings.template.button).append(txt)[0].outerHTML; - } else { - txt = ''; - } - return txt; - }, - - create : function (opts) { - console.log(opts.$li) - var buttonText = opts.$li.attr(this.add_namespace('data-button')) - || opts.$li.attr(this.add_namespace('data-text')), - tipClass = opts.$li.attr('class'), - $tip_content = $(this.tip_template({ - tip_class : tipClass, - index : opts.index, - button_text : buttonText, - li : opts.$li - })); - - $(this.settings.tip_container).append($tip_content); - }, - - show : function (init) { - var $timer = null; - - // are we paused? - if (this.settings.$li === undefined - || ($.inArray(this.settings.$li.index(), this.settings.pause_after) === -1)) { - - // don't go to the next li if the tour was paused - if (this.settings.paused) { - this.settings.paused = false; - } else { - this.set_li(init); - } - - this.settings.attempts = 0; - - if (this.settings.$li.length && this.settings.$target.length > 0) { - if (init) { //run when we first start - this.settings.pre_ride_callback(this.settings.$li.index(), this.settings.$next_tip); - if (this.settings.modal) { - this.show_modal(); - } - } - - this.settings.pre_step_callback(this.settings.$li.index(), this.settings.$next_tip); - - if (this.settings.modal && this.settings.expose) { - this.expose(); - } - - this.settings.tip_settings = $.extend({}, this.settings, this.data_options(this.settings.$li)); - - this.settings.timer = parseInt(this.settings.timer, 10); - - this.settings.tip_settings.tip_location_pattern = this.settings.tip_location_patterns[this.settings.tip_settings.tip_location]; - - // scroll if not modal - if (!/body/i.test(this.settings.$target.selector)) { - this.scroll_to(); - } - - if (this.is_phone()) { - this.pos_phone(true); - } else { - this.pos_default(true); - } - - $timer = this.settings.$next_tip.find('.joyride-timer-indicator'); - - if (/pop/i.test(this.settings.tip_animation)) { - - $timer.width(0); - - if (this.settings.timer > 0) { - - this.settings.$next_tip.show(); - - setTimeout(function () { - $timer.animate({ - width: $timer.parent().width() - }, this.settings.timer, 'linear'); - }.bind(this), this.settings.tip_animation_fade_speed); - - } else { - this.settings.$next_tip.show(); - - } - - - } else if (/fade/i.test(this.settings.tip_animation)) { - - $timer.width(0); - - if (this.settings.timer > 0) { - - this.settings.$next_tip - .fadeIn(this.settings.tip_animation_fade_speed) - .show(); - - setTimeout(function () { - $timer.animate({ - width: $timer.parent().width() - }, this.settings.timer, 'linear'); - }.bind(this), this.settings.tip_animation_fadeSpeed); - - } else { - this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed); - } - } - - this.settings.$current_tip = this.settings.$next_tip; - - // skip non-existant targets - } else if (this.settings.$li && this.settings.$target.length < 1) { - - this.show(); - - } else { - - this.end(); - - } - } else { - - this.settings.paused = true; - - } - - }, - - is_phone : function () { - return matchMedia(Foundation.media_queries.small).matches && - !matchMedia(Foundation.media_queries.medium).matches; - }, - - hide : function () { - if (this.settings.modal && this.settings.expose) { - this.un_expose(); - } - - if (!this.settings.modal) { - $('.joyride-modal-bg').hide(); - } - - // Prevent scroll bouncing...wait to remove from layout - this.settings.$current_tip.css('visibility', 'hidden'); - setTimeout($.proxy(function() { - this.hide(); - this.css('visibility', 'visible'); - }, this.settings.$current_tip), 0); - this.settings.post_step_callback(this.settings.$li.index(), - this.settings.$current_tip); - }, - - set_li : function (init) { - if (init) { - this.settings.$li = this.settings.$tip_content.eq(this.settings.start_offset); - this.set_next_tip(); - this.settings.$current_tip = this.settings.$next_tip; - } else { - this.settings.$li = this.settings.$li.next(); - this.set_next_tip(); - } - - this.set_target(); - }, - - set_next_tip : function () { - this.settings.$next_tip = $(".joyride-tip-guide").eq(this.settings.$li.index()); - this.settings.$next_tip.data('closed', ''); - }, - - set_target : function () { - console.log(this.add_namespace('data-class')) - var cl = this.settings.$li.attr(this.add_namespace('data-class')), - id = this.settings.$li.attr(this.add_namespace('data-id')), - $sel = function () { - if (id) { - return $(document.getElementById(id)); - } else if (cl) { - return $('.' + cl).first(); - } else { - return $('body'); - } - }; - - console.log(cl, id) - - this.settings.$target = $sel(); - }, - - scroll_to : function () { - var window_half, tipOffset; - - window_half = $(window).height() / 2; - tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight()); - - if (tipOffset != 0) { - $('html, body').animate({ - scrollTop: tipOffset - }, this.settings.scroll_speed, 'swing'); - } - }, - - paused : function () { - return ($.inArray((this.settings.$li.index() + 1), this.settings.pause_after) === -1); - }, - - restart : function () { - this.hide(); - this.settings.$li = undefined; - this.show('init'); - }, - - pos_default : function (init, resizing) { - var half_fold = Math.ceil($(window).height() / 2), - tip_position = this.settings.$next_tip.offset(), - $nub = this.settings.$next_tip.find('.joyride-nub'), - nub_width = Math.ceil($nub.outerWidth() / 2), - nub_height = Math.ceil($nub.outerHeight() / 2), - toggle = init || false; - - // tip must not be "display: none" to calculate position - if (toggle) { - this.settings.$next_tip.css('visibility', 'hidden'); - this.settings.$next_tip.show(); - } - - if (typeof resizing === 'undefined') { - resizing = false; - } - - if (!/body/i.test(this.settings.$target.selector)) { - if (this.bottom()) { - if (this.rtl) { - this.settings.$next_tip.css({ - top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()), - left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()}); - } else { - this.settings.$next_tip.css({ - top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()), - left: this.settings.$target.offset().left}); - } - - this.nub_position($nub, this.settings.tip_settings.nub_position, 'top'); - - } else if (this.top()) { - if (this.rtl) { - this.settings.$next_tip.css({ - top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height), - left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()}); - } else { - this.settings.$next_tip.css({ - top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height), - left: this.settings.$target.offset().left}); - } - - this.nub_position($nub, this.settings.tip_settings.nub_position, 'bottom'); - - } else if (this.right()) { - - this.settings.$next_tip.css({ - top: this.settings.$target.offset().top, - left: (this.outerWidth(this.settings.$target) + this.settings.$target.offset().left + nub_width)}); - - this.nub_position($nub, this.settings.tip_settings.nub_position, 'left'); - - } else if (this.left()) { - - this.settings.$next_tip.css({ - top: this.settings.$target.offset().top, - left: (this.settings.$target.offset().left - this.outerWidth(this.settings.$next_tip) - nub_width)}); - - this.nub_position($nub, this.settings.tip_settings.nub_position, 'right'); - - } - - if (!this.visible(this.corners(this.settings.$next_tip)) && this.settings.attempts < this.settings.tip_settings.tip_location_pattern.length) { - - $nub.removeClass('bottom') - .removeClass('top') - .removeClass('right') - .removeClass('left'); - - this.settings.tip_settings.tip_location = this.settings.tip_settings.tip_location_pattern[this.settings.attempts]; - - this.settings.attempts++; - - this.pos_default(); - - } - - } else if (this.settings.$li.length) { - - this.pos_modal($nub); - - } - - if (toggle) { - this.settings.$next_tip.hide(); - this.settings.$next_tip.css('visibility', 'visible'); - } - - }, - - pos_phone : function (init) { - var tip_height = this.settings.$next_tip.outerHeight(), - tip_offset = this.settings.$next_tip.offset(), - target_height = this.settings.$target.outerHeight(), - $nub = $('.joyride-nub', this.settings.$next_tip), - nub_height = Math.ceil($nub.outerHeight() / 2), - toggle = init || false; - - $nub.removeClass('bottom') - .removeClass('top') - .removeClass('right') - .removeClass('left'); - - if (toggle) { - this.settings.$next_tip.css('visibility', 'hidden'); - this.settings.$next_tip.show(); - } - - if (!/body/i.test(this.settings.$target.selector)) { - - if (this.top()) { - - this.settings.$next_tip.offset({top: this.settings.$target.offset().top - tip_height - nub_height}); - $nub.addClass('bottom'); - - } else { - - this.settings.$next_tip.offset({top: this.settings.$target.offset().top + target_height + nub_height}); - $nub.addClass('top'); - - } - - } else if (this.settings.$li.length) { - this.pos_modal($nub); - } - - if (toggle) { - this.settings.$next_tip.hide(); - this.settings.$next_tip.css('visibility', 'visible'); - } - }, - - pos_modal : function ($nub) { - this.center(); - $nub.hide(); - - this.show_modal(); - }, - - show_modal : function () { - if (!this.settings.$next_tip.data('closed')) { - var joyridemodalbg = $('.joyride-modal-bg'); - if (joyridemodalbg.length < 1) { - $('body').append(this.settings.template.modal).show(); - } - - if (/pop/i.test(this.settings.tip_animation)) { - joyridemodalbg.show(); - } else { - joyridemodalbg.fadeIn(this.settings.tip_animation_fade_speed); - } - } - }, - - expose : function () { - var expose, - exposeCover, - el, - origCSS, - origClasses, - randId = 'expose-' + this.random_str(6); - - if (arguments.length > 0 && arguments[0] instanceof $) { - el = arguments[0]; - } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){ - el = this.settings.$target; - } else { - return false; - } - - if(el.length < 1){ - if(window.console){ - console.error('element not valid', el); - } - return false; - } - - expose = $(this.settings.template.expose); - this.settings.$body.append(expose); - expose.css({ - top: el.offset().top, - left: el.offset().left, - width: el.outerWidth(true), - height: el.outerHeight(true) - }); - - exposeCover = $(this.settings.template.expose_cover); - - origCSS = { - zIndex: el.css('z-index'), - position: el.css('position') - }; - - origClasses = el.attr('class') == null ? '' : el.attr('class'); - - el.css('z-index',parseInt(expose.css('z-index'))+1); - - if (origCSS.position == 'static') { - el.css('position','relative'); - } - - el.data('expose-css',origCSS); - el.data('orig-class', origClasses); - el.attr('class', origClasses + ' ' + this.settings.expose_add_class); - - exposeCover.css({ - top: el.offset().top, - left: el.offset().left, - width: el.outerWidth(true), - height: el.outerHeight(true) - }); - - if (this.settings.modal) this.show_modal(); - - this.settings.$body.append(exposeCover); - expose.addClass(randId); - exposeCover.addClass(randId); - el.data('expose', randId); - this.settings.post_expose_callback(this.settings.$li.index(), this.settings.$next_tip, el); - this.add_exposed(el); - }, - - un_expose : function () { - var exposeId, - el, - expose , - origCSS, - origClasses, - clearAll = false; - - if (arguments.length > 0 && arguments[0] instanceof $) { - el = arguments[0]; - } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){ - el = this.settings.$target; - } else { - return false; - } - - if(el.length < 1){ - if (window.console) { - console.error('element not valid', el); - } - return false; - } - - exposeId = el.data('expose'); - expose = $('.' + exposeId); - - if (arguments.length > 1) { - clearAll = arguments[1]; - } - - if (clearAll === true) { - $('.joyride-expose-wrapper,.joyride-expose-cover').remove(); - } else { - expose.remove(); - } - - origCSS = el.data('expose-css'); - - if (origCSS.zIndex == 'auto') { - el.css('z-index', ''); - } else { - el.css('z-index', origCSS.zIndex); - } - - if (origCSS.position != el.css('position')) { - if(origCSS.position == 'static') {// this is default, no need to set it. - el.css('position', ''); - } else { - el.css('position', origCSS.position); - } - } - - origClasses = el.data('orig-class'); - el.attr('class', origClasses); - el.removeData('orig-classes'); - - el.removeData('expose'); - el.removeData('expose-z-index'); - this.remove_exposed(el); - }, - - add_exposed: function(el){ - this.settings.exposed = this.settings.exposed || []; - if (el instanceof $ || typeof el === 'object') { - this.settings.exposed.push(el[0]); - } else if (typeof el == 'string') { - this.settings.exposed.push(el); - } - }, - - remove_exposed: function(el){ - var search, i; - if (el instanceof $) { - search = el[0] - } else if (typeof el == 'string'){ - search = el; - } - - this.settings.exposed = this.settings.exposed || []; - i = this.settings.exposed.length; - - while (i--) { - if (this.settings.exposed[i] == search) { - this.settings.exposed.splice(i, 1); - return; - } - } - }, - - center : function () { - var $w = $(window); - - this.settings.$next_tip.css({ - top : ((($w.height() - this.settings.$next_tip.outerHeight()) / 2) + $w.scrollTop()), - left : ((($w.width() - this.settings.$next_tip.outerWidth()) / 2) + $w.scrollLeft()) - }); - - return true; - }, - - bottom : function () { - return /bottom/i.test(this.settings.tip_settings.tip_location); - }, - - top : function () { - return /top/i.test(this.settings.tip_settings.tip_location); - }, - - right : function () { - return /right/i.test(this.settings.tip_settings.tip_location); - }, - - left : function () { - return /left/i.test(this.settings.tip_settings.tip_location); - }, - - corners : function (el) { - var w = $(window), - window_half = w.height() / 2, - //using this to calculate since scroll may not have finished yet. - tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight()), - right = w.width() + w.scrollLeft(), - offsetBottom = w.height() + tipOffset, - bottom = w.height() + w.scrollTop(), - top = w.scrollTop(); - - if (tipOffset < top) { - if (tipOffset < 0) { - top = 0; - } else { - top = tipOffset; - } - } - - if (offsetBottom > bottom) { - bottom = offsetBottom; - } - - return [ - el.offset().top < top, - right < el.offset().left + el.outerWidth(), - bottom < el.offset().top + el.outerHeight(), - w.scrollLeft() > el.offset().left - ]; - }, - - visible : function (hidden_corners) { - var i = hidden_corners.length; - - while (i--) { - if (hidden_corners[i]) return false; - } - - return true; - }, - - nub_position : function (nub, pos, def) { - if (pos === 'auto') { - nub.addClass(def); - } else { - nub.addClass(pos); - } - }, - - startTimer : function () { - if (this.settings.$li.length) { - this.settings.automate = setTimeout(function () { - this.hide(); - this.show(); - this.startTimer(); - }.bind(this), this.settings.timer); - } else { - clearTimeout(this.settings.automate); - } - }, - - end : function () { - if (this.settings.cookie_monster) { - $.cookie(this.settings.cookie_name, 'ridden', { expires: this.settings.cookie_expires, domain: this.settings.cookie_domain }); - } - - if (this.settings.timer > 0) { - clearTimeout(this.settings.automate); - } - - if (this.settings.modal && this.settings.expose) { - this.un_expose(); - } - - this.settings.$next_tip.data('closed', true); - - $('.joyride-modal-bg').hide(); - this.settings.$current_tip.hide(); - this.settings.post_step_callback(this.settings.$li.index(), this.settings.$current_tip); - this.settings.post_ride_callback(this.settings.$li.index(), this.settings.$current_tip); - $('.joyride-tip-guide').remove(); - }, - - off : function () { - $(this.scope).off('.joyride'); - $(window).off('.joyride'); - $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride'); - $('.joyride-tip-guide, .joyride-modal-bg').remove(); - clearTimeout(this.settings.automate); - this.settings = {}; - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.js b/coin/static/js/foundation/foundation.js deleted file mode 100644 index 7147f4f47c5a946253985e0f4622c026198d878c..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.js +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Foundation Responsive Library - * http://foundation.zurb.com - * Copyright 2014, ZURB - * Free to use under the MIT license. - * http://www.opensource.org/licenses/mit-license.php -*/ - -(function ($, window, document, undefined) { - 'use strict'; - - var header_helpers = function (class_array) { - var i = class_array.length; - - while (i--) { - if($('head').has('.' + class_array[i]).length === 0) { - $('head').append(''); - } - } - }; - - header_helpers([ - 'foundation-mq-small', - 'foundation-mq-medium', - 'foundation-mq-large', - 'foundation-mq-xlarge', - 'foundation-mq-xxlarge', - 'foundation-data-attribute-namespace']); - - // Enable FastClick if present - - $(function() { - if(typeof FastClick !== 'undefined') { - // Don't attach to body if undefined - if (typeof document.body !== 'undefined') { - FastClick.attach(document.body); - } - } - }); - - // private Fast Selector wrapper, - // returns jQuery object. Only use where - // getElementById is not available. - var S = function (selector, context) { - if (typeof selector === 'string') { - if (context) { - var cont; - if (context.jquery) { - cont = context[0]; - } else { - cont = context; - } - return $(cont.querySelectorAll(selector)); - } - - return $(document.querySelectorAll(selector)); - } - - return $(selector, context); - }; - - // Namespace functions. - - var attr_name = function (init) { - var arr = []; - if (!init) arr.push('data'); - if (this.namespace.length > 0) arr.push(this.namespace); - arr.push(this.name); - - return arr.join('-'); - }; - - var header_helpers = function (class_array) { - var i = class_array.length; - - while (i--) { - if($('head').has('.' + class_array[i]).length === 0) { - $('head').append(''); - } - } - }; - - var add_namespace = function (str) { - var parts = str.split('-'), - i = parts.length, - arr = []; - - while(i--) { - if (i !== 0) { - arr.push(parts[i]); - } else { - if (this.namespace.length > 0) { - arr.push(this.namespace, parts[i]); - } else { - arr.push(parts[i]); - } - } - } - - return arr.reverse().join('-'); - }; - - // Event binding and data-options updating. - - var bindings = function (method, options) { - var self = this, - should_bind_events = !S(this).data(this.attr_name(true)); - - if (typeof method === 'string') { - return this[method].call(this, options); - } - - if (S(this.scope).is('[' + this.attr_name() +']')) { - S(this.scope).data(this.attr_name(true) + '-init', $.extend({}, this.settings, (options || method), this.data_options(S(this.scope)))); - - if (should_bind_events) { - this.events(this.scope); - } - - } else { - S('[' + this.attr_name() +']', this.scope).each(function () { - var should_bind_events = !S(this).data(self.attr_name(true) + '-init'); - - S(this).data(self.attr_name(true) + '-init', $.extend({}, self.settings, (options || method), self.data_options(S(this)))); - - if (should_bind_events) { - self.events(this); - } - }); - } - }; - - var single_image_loaded = function (image, callback) { - function loaded () { - callback(image[0]); - } - - function bindLoad () { - this.one('load', loaded); - - if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { - var src = this.attr( 'src' ), - param = src.match( /\?/ ) ? '&' : '?'; - - param += 'random=' + (new Date()).getTime(); - this.attr('src', src + param); - } - } - - if (!image.attr('src')) { - loaded(); - return; - } - - if (image[0].complete || image[0].readyState === 4) { - loaded(); - } else { - bindLoad.call(image); - } - } - - /* - https://github.com/paulirish/matchMedia.js - */ - - window.matchMedia = window.matchMedia || (function( doc, undefined ) { - - "use strict"; - - var bool, - docElem = doc.documentElement, - refNode = docElem.firstElementChild || docElem.firstChild, - // fakeBody required for - fakeBody = doc.createElement( "body" ), - div = doc.createElement( "div" ); - - div.id = "mq-test-1"; - div.style.cssText = "position:absolute;top:-100em"; - fakeBody.style.background = "none"; - fakeBody.appendChild(div); - - return function(q){ - - div.innerHTML = "­"; - - docElem.insertBefore( fakeBody, refNode ); - bool = div.offsetWidth === 42; - docElem.removeChild( fakeBody ); - - return { - matches: bool, - media: q - }; - - }; - - }( document )); - - /* - * jquery.requestAnimationFrame - * https://github.com/gnarf37/jquery-requestAnimationFrame - * Requires jQuery 1.8+ - * - * Copyright (c) 2012 Corey Frang - * Licensed under the MIT license. - */ - - (function( $ ) { - - // requestAnimationFrame polyfill adapted from Erik Möller - // fixes from Paul Irish and Tino Zijdel - // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating - - - var animating, - lastTime = 0, - vendors = ['webkit', 'moz'], - requestAnimationFrame = window.requestAnimationFrame, - cancelAnimationFrame = window.cancelAnimationFrame; - - for(; lastTime < vendors.length && !requestAnimationFrame; lastTime++) { - requestAnimationFrame = window[ vendors[lastTime] + "RequestAnimationFrame" ]; - cancelAnimationFrame = cancelAnimationFrame || - window[ vendors[lastTime] + "CancelAnimationFrame" ] || - window[ vendors[lastTime] + "CancelRequestAnimationFrame" ]; - } - - function raf() { - if ( animating ) { - requestAnimationFrame( raf ); - jQuery.fx.tick(); - } - } - - if ( requestAnimationFrame ) { - // use rAF - window.requestAnimationFrame = requestAnimationFrame; - window.cancelAnimationFrame = cancelAnimationFrame; - jQuery.fx.timer = function( timer ) { - if ( timer() && jQuery.timers.push( timer ) && !animating ) { - animating = true; - raf(); - } - }; - - jQuery.fx.stop = function() { - animating = false; - }; - } else { - // polyfill - window.requestAnimationFrame = function( callback, element ) { - var currTime = new Date().getTime(), - timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ), - id = window.setTimeout( function() { - callback( currTime + timeToCall ); - }, timeToCall ); - lastTime = currTime + timeToCall; - return id; - }; - - window.cancelAnimationFrame = function(id) { - clearTimeout(id); - }; - - } - - }( jQuery )); - - - function removeQuotes (string) { - if (typeof string === 'string' || string instanceof String) { - string = string.replace(/^['\\/"]+|(;\s?})+|['\\/"]+$/g, ''); - } - - return string; - } - - window.Foundation = { - name : 'Foundation', - - version : '5.1.1', - - media_queries : { - small : S('.foundation-mq-small').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), - medium : S('.foundation-mq-medium').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), - large : S('.foundation-mq-large').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), - xlarge: S('.foundation-mq-xlarge').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), - xxlarge: S('.foundation-mq-xxlarge').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, '') - }, - - stylesheet : $('').appendTo('head')[0].sheet, - - global: { - namespace: '' - }, - - init : function (scope, libraries, method, options, response) { - var library_arr, - args = [scope, method, options, response], - responses = []; - - // check RTL - this.rtl = /rtl/i.test(S('html').attr('dir')); - - // set foundation global scope - this.scope = scope || this.scope; - - this.set_namespace(); - - if (libraries && typeof libraries === 'string' && !/reflow/i.test(libraries)) { - if (this.libs.hasOwnProperty(libraries)) { - responses.push(this.init_lib(libraries, args)); - } - } else { - for (var lib in this.libs) { - responses.push(this.init_lib(lib, libraries)); - } - } - - return scope; - }, - - init_lib : function (lib, args) { - if (this.libs.hasOwnProperty(lib)) { - this.patch(this.libs[lib]); - - if (args && args.hasOwnProperty(lib)) { - return this.libs[lib].init.apply(this.libs[lib], [this.scope, args[lib]]); - } - - args = args instanceof Array ? args : Array(args); // PATCH: added this line - return this.libs[lib].init.apply(this.libs[lib], args); - } - - return function () {}; - }, - - patch : function (lib) { - lib.scope = this.scope; - lib.namespace = this.global.namespace; - lib.rtl = this.rtl; - lib['data_options'] = this.utils.data_options; - lib['attr_name'] = attr_name; - lib['add_namespace'] = add_namespace; - lib['bindings'] = bindings; - lib['S'] = this.utils.S; - }, - - inherit : function (scope, methods) { - var methods_arr = methods.split(' '), - i = methods_arr.length; - - while (i--) { - if (this.utils.hasOwnProperty(methods_arr[i])) { - scope[methods_arr[i]] = this.utils[methods_arr[i]]; - } - } - }, - - set_namespace: function () { - var namespace = $('.foundation-data-attribute-namespace').css('font-family'); - - if (/false/i.test(namespace)) return; - - this.global.namespace = namespace; - }, - - libs : {}, - - // methods that can be inherited in libraries - utils : { - - // Description: - // Fast Selector wrapper returns jQuery object. Only use where getElementById - // is not available. - // - // Arguments: - // Selector (String): CSS selector describing the element(s) to be - // returned as a jQuery object. - // - // Scope (String): CSS selector describing the area to be searched. Default - // is document. - // - // Returns: - // Element (jQuery Object): jQuery object containing elements matching the - // selector within the scope. - S : S, - - // Description: - // Executes a function a max of once every n milliseconds - // - // Arguments: - // Func (Function): Function to be throttled. - // - // Delay (Integer): Function execution threshold in milliseconds. - // - // Returns: - // Lazy_function (Function): Function with throttling applied. - throttle : function(func, delay) { - var timer = null; - - return function () { - var context = this, args = arguments; - - clearTimeout(timer); - timer = setTimeout(function () { - func.apply(context, args); - }, delay); - }; - }, - - // Description: - // Executes a function when it stops being invoked for n seconds - // Modified version of _.debounce() http://underscorejs.org - // - // Arguments: - // Func (Function): Function to be debounced. - // - // Delay (Integer): Function execution threshold in milliseconds. - // - // Immediate (Bool): Whether the function should be called at the beginning - // of the delay instead of the end. Default is false. - // - // Returns: - // Lazy_function (Function): Function with debouncing applied. - debounce : function(func, delay, immediate) { - var timeout, result; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) result = func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, delay); - if (callNow) result = func.apply(context, args); - return result; - }; - }, - - // Description: - // Parses data-options attribute - // - // Arguments: - // El (jQuery Object): Element to be parsed. - // - // Returns: - // Options (Javascript Object): Contents of the element's data-options - // attribute. - data_options : function (el) { - var opts = {}, ii, p, opts_arr, - data_options = function (el) { - var namespace = Foundation.global.namespace; - - if (namespace.length > 0) { - return el.data(namespace + '-options'); - } - - return el.data('options'); - }; - - var cached_options = data_options(el); - - if (typeof cached_options === 'object') { - return cached_options; - } - - opts_arr = (cached_options || ':').split(';'), - ii = opts_arr.length; - - function isNumber (o) { - return ! isNaN (o-0) && o !== null && o !== "" && o !== false && o !== true; - } - - function trim(str) { - if (typeof str === 'string') return $.trim(str); - return str; - } - - while (ii--) { - p = opts_arr[ii].split(':'); - - if (/true/i.test(p[1])) p[1] = true; - if (/false/i.test(p[1])) p[1] = false; - if (isNumber(p[1])) p[1] = parseInt(p[1], 10); - - if (p.length === 2 && p[0].length > 0) { - opts[trim(p[0])] = trim(p[1]); - } - } - - return opts; - }, - - // Description: - // Adds JS-recognizable media queries - // - // Arguments: - // Media (String): Key string for the media query to be stored as in - // Foundation.media_queries - // - // Class (String): Class name for the generated tag - register_media : function(media, media_class) { - if(Foundation.media_queries[media] === undefined) { - $('head').append(''); - Foundation.media_queries[media] = removeQuotes($('.' + media_class).css('font-family')); - } - }, - - // Description: - // Add custom CSS within a JS-defined media query - // - // Arguments: - // Rule (String): CSS rule to be appended to the document. - // - // Media (String): Optional media query string for the CSS rule to be - // nested under. - add_custom_rule : function(rule, media) { - if(media === undefined) { - Foundation.stylesheet.insertRule(rule, Foundation.stylesheet.cssRules.length); - } else { - var query = Foundation.media_queries[media]; - if(query !== undefined) { - Foundation.stylesheet.insertRule('@media ' + - Foundation.media_queries[media] + '{ ' + rule + ' }'); - } - } - }, - - // Description: - // Performs a callback function when an image is fully loaded - // - // Arguments: - // Image (jQuery Object): Image(s) to check if loaded. - // - // Callback (Function): Fundation to execute when image is fully loaded. - image_loaded : function (images, callback) { - var self = this, - unloaded = images.length; - - images.each(function(){ - single_image_loaded(self.S(this),function(){ - unloaded -= 1; - if(unloaded == 0){ - callback(images); - } - }); - }); - }, - - // Description: - // Returns a random, alphanumeric string - // - // Arguments: - // Length (Integer): Length of string to be generated. Defaults to random - // integer. - // - // Returns: - // Rand (String): Pseudo-random, alphanumeric string. - random_str : function (length) { - var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); - - if (!length) { - length = Math.floor(Math.random() * chars.length); - } - - var str = ''; - while (length--) { - str += chars[Math.floor(Math.random() * chars.length)]; - } - return str; - } - } - }; - - $.fn.foundation = function () { - var args = Array.prototype.slice.call(arguments, 0); - - return this.each(function () { - Foundation.init.apply(Foundation, [this].concat(args)); - return this; - }); - }; - -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.magellan.js b/coin/static/js/foundation/foundation.magellan.js deleted file mode 100644 index dd6149546bc514d67f2ecf61b495f4c8b81d3614..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.magellan.js +++ /dev/null @@ -1,171 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs['magellan-expedition'] = { - name : 'magellan-expedition', - - version : '5.1.1', - - settings : { - active_class: 'active', - threshold: 0, // pixels from the top of the expedition for it to become fixes - destination_threshold: 20, // pixels from the top of destination for it to be considered active - throttle_delay: 30 // calculation throttling to increase framerate - }, - - init : function (scope, method, options) { - Foundation.inherit(this, 'throttle'); - this.bindings(method, options); - }, - - events : function () { - var self = this, - S = self.S, - settings = self.settings; - - // initialize expedition offset - self.set_expedition_position(); - - - S(self.scope) - .off('.magellan') - .on('click.fndtn.magellan', '[' + self.add_namespace('data-magellan-arrival') + '] a[href^="#"]', function (e) { - e.preventDefault(); - var expedition = $(this).closest('[' + self.attr_name() + ']'), - settings = expedition.data('magellan-expedition-init'); - - var hash = this.hash.split('#').join(''), - target = $('a[name='+hash+']'); - if (target.length === 0) target = $('#'+hash); - - // Account for expedition height if fixed position - var scroll_top = target.offset().top; - if (expedition.css('position') === 'fixed') { - scroll_top = scroll_top - expedition.outerHeight(); - } - - $('html, body').stop().animate({ - 'scrollTop': scroll_top - }, 700, 'swing', function () { - window.location.hash = '#'+hash; - }); - }) - .on('scroll.fndtn.magellan', self.throttle(this.check_for_arrivals.bind(this), settings.throttle_delay)) - .on('resize.fndtn.magellan', self.throttle(this.set_expedition_position.bind(this), settings.throttle_delay)); - }, - - check_for_arrivals : function() { - var self = this; - self.update_arrivals(); - self.update_expedition_positions(); - }, - - set_expedition_position : function() { - var self = this; - $('[' + this.attr_name() + '=fixed]', self.scope).each(function(idx, el) { - var expedition = $(this), - styles = expedition.attr('styles'), // save styles - top_offset; - - expedition.attr('style', ''); - top_offset = expedition.offset().top; - - expedition.data(self.data_attr('magellan-top-offset'), top_offset); - expedition.attr('style', styles); - }); - }, - - update_expedition_positions : function() { - var self = this, - window_top_offset = $(window).scrollTop(); - - $('[' + this.attr_name() + '=fixed]', self.scope).each(function() { - var expedition = $(this), - top_offset = expedition.data('magellan-top-offset'); - - if (window_top_offset >= top_offset) { - // Placeholder allows height calculations to be consistent even when - // appearing to switch between fixed/non-fixed placement - var placeholder = expedition.prev('[' + self.add_namespace('data-magellan-expedition-clone') + ']'); - if (placeholder.length === 0) { - placeholder = expedition.clone(); - placeholder.removeAttr(self.attr_name()); - placeholder.attr(self.add_namespace('data-magellan-expedition-clone'),''); - expedition.before(placeholder); - } - expedition.css({position:'fixed', top: 0}); - } else { - expedition.prev('[' + self.add_namespace('data-magellan-expedition-clone') + ']').remove(); - expedition.attr('style',''); - } - }); - }, - - update_arrivals : function() { - var self = this, - window_top_offset = $(window).scrollTop(); - - $('[' + this.attr_name() + ']', self.scope).each(function() { - var expedition = $(this), - settings = settings = expedition.data(self.attr_name(true) + '-init'), - offsets = self.offsets(expedition, window_top_offset), - arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']'), - active_item = false; - offsets.each(function(idx, item) { - if (item.viewport_offset >= item.top_offset) { - var arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']'); - arrivals.not(item.arrival).removeClass(settings.active_class); - item.arrival.addClass(settings.active_class); - active_item = true; - return true; - } - }); - - if (!active_item) arrivals.removeClass(settings.active_class); - }); - }, - - offsets : function(expedition, window_offset) { - var self = this, - settings = expedition.data(self.attr_name(true) + '-init'), - viewport_offset = (window_offset + settings.destination_threshold); - - return expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']').map(function(idx, el) { - var name = $(this).data(self.data_attr('magellan-arrival')), - dest = $('[' + self.add_namespace('data-magellan-destination') + '=' + name + ']'); - if (dest.length > 0) { - var top_offset = dest.offset().top; - return { - destination : dest, - arrival : $(this), - top_offset : top_offset, - viewport_offset : viewport_offset - } - } - }).sort(function(a, b) { - if (a.top_offset < b.top_offset) return -1; - if (a.top_offset > b.top_offset) return 1; - return 0; - }); - }, - - data_attr: function (str) { - if (this.namespace.length > 0) { - return this.namespace + '-' + str; - } - - return str; - }, - - off : function () { - this.S(this.scope).off('.magellan'); - this.S(window).off('.magellan'); - }, - - reflow : function () { - var self = this; - // remove placeholder expeditions used for height calculation purposes - $('[' + self.add_namespace('data-magellan-expedition-clone') + ']', self.scope).remove(); - } - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.offcanvas.js b/coin/static/js/foundation/foundation.offcanvas.js deleted file mode 100644 index df688ef49471811452a27d77db3435a5c8427828..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.offcanvas.js +++ /dev/null @@ -1,39 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.offcanvas = { - name : 'offcanvas', - - version : '5.1.1', - - settings : {}, - - init : function (scope, method, options) { - this.events(); - }, - - events : function () { - var S = this.S; - - S(this.scope).off('.offcanvas') - .on('click.fndtn.offcanvas', '.left-off-canvas-toggle', function (e) { - e.preventDefault(); - S(this).closest('.off-canvas-wrap').toggleClass('move-right'); - }) - .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e) { - e.preventDefault(); - S(".off-canvas-wrap").removeClass("move-right"); - }) - .on('click.fndtn.offcanvas', '.right-off-canvas-toggle', function (e) { - e.preventDefault(); - S(this).closest(".off-canvas-wrap").toggleClass("move-left"); - }) - .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e) { - e.preventDefault(); - S(".off-canvas-wrap").removeClass("move-left"); - }); - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.orbit.js b/coin/static/js/foundation/foundation.orbit.js deleted file mode 100644 index 4c3b3777a714669ef7a408d6b285bd14ff020935..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.orbit.js +++ /dev/null @@ -1,464 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - var noop = function() {}; - - var Orbit = function(el, settings) { - // Don't reinitialize plugin - if (el.hasClass(settings.slides_container_class)) { - return this; - } - - var self = this, - container, - slides_container = el, - number_container, - bullets_container, - timer_container, - idx = 0, - animate, - timer, - locked = false, - adjust_height_after = false; - - - self.slides = function() { - return slides_container.children(settings.slide_selector); - }; - - self.slides().first().addClass(settings.active_slide_class); - - self.update_slide_number = function(index) { - if (settings.slide_number) { - number_container.find('span:first').text(parseInt(index)+1); - number_container.find('span:last').text(self.slides().length); - } - if (settings.bullets) { - bullets_container.children().removeClass(settings.bullets_active_class); - $(bullets_container.children().get(index)).addClass(settings.bullets_active_class); - } - }; - - self.update_active_link = function(index) { - var link = $('a[data-orbit-link="'+self.slides().eq(index).attr('data-orbit-slide')+'"]'); - link.siblings().removeClass(settings.bullets_active_class); - link.addClass(settings.bullets_active_class); - }; - - self.build_markup = function() { - slides_container.wrap('
      '); - container = slides_container.parent(); - slides_container.addClass(settings.slides_container_class); - - if (settings.navigation_arrows) { - container.append($('').addClass(settings.prev_class)); - container.append($('').addClass(settings.next_class)); - } - - if (settings.timer) { - timer_container = $('
      ').addClass(settings.timer_container_class); - timer_container.append(''); - timer_container.append($('
      ').addClass(settings.timer_progress_class)); - timer_container.addClass(settings.timer_paused_class); - container.append(timer_container); - } - - if (settings.slide_number) { - number_container = $('
      ').addClass(settings.slide_number_class); - number_container.append(' ' + settings.slide_number_text + ' '); - container.append(number_container); - } - - if (settings.bullets) { - bullets_container = $('
        ').addClass(settings.bullets_container_class); - container.append(bullets_container); - bullets_container.wrap('
        '); - self.slides().each(function(idx, el) { - var bullet = $('
      1. ').attr('data-orbit-slide', idx); - bullets_container.append(bullet); - }); - } - - if (settings.stack_on_small) { - container.addClass(settings.stack_on_small_class); - } - }; - - self._goto = function(next_idx, start_timer) { - // if (locked) {return false;} - if (next_idx === idx) {return false;} - if (typeof timer === 'object') {timer.restart();} - var slides = self.slides(); - - var dir = 'next'; - locked = true; - if (next_idx < idx) {dir = 'prev';} - if (next_idx >= slides.length) { - if (!settings.circular) return false; - next_idx = 0; - } else if (next_idx < 0) { - if (!settings.circular) return false; - next_idx = slides.length - 1; - } - - var current = $(slides.get(idx)); - var next = $(slides.get(next_idx)); - - current.css('zIndex', 2); - current.removeClass(settings.active_slide_class); - next.css('zIndex', 4).addClass(settings.active_slide_class); - - slides_container.trigger('before-slide-change.fndtn.orbit'); - settings.before_slide_change(); - self.update_active_link(next_idx); - - var callback = function() { - var unlock = function() { - idx = next_idx; - locked = false; - if (start_timer === true) {timer = self.create_timer(); timer.start();} - self.update_slide_number(idx); - slides_container.trigger('after-slide-change.fndtn.orbit',[{slide_number: idx, total_slides: slides.length}]); - settings.after_slide_change(idx, slides.length); - }; - if (slides_container.height() != next.height() && settings.variable_height) { - slides_container.animate({'height': next.height()}, 250, 'linear', unlock); - } else { - unlock(); - } - }; - - if (slides.length === 1) {callback(); return false;} - - var start_animation = function() { - if (dir === 'next') {animate.next(current, next, callback);} - if (dir === 'prev') {animate.prev(current, next, callback);} - }; - - if (next.height() > slides_container.height() && settings.variable_height) { - slides_container.animate({'height': next.height()}, 250, 'linear', start_animation); - } else { - start_animation(); - } - }; - - self.next = function(e) { - e.stopImmediatePropagation(); - e.preventDefault(); - self._goto(idx + 1); - }; - - self.prev = function(e) { - e.stopImmediatePropagation(); - e.preventDefault(); - self._goto(idx - 1); - }; - - self.link_custom = function(e) { - e.preventDefault(); - var link = $(this).attr('data-orbit-link'); - if ((typeof link === 'string') && (link = $.trim(link)) != "") { - var slide = container.find('[data-orbit-slide='+link+']'); - if (slide.index() != -1) {self._goto(slide.index());} - } - }; - - self.link_bullet = function(e) { - var index = $(this).attr('data-orbit-slide'); - if ((typeof index === 'string') && (index = $.trim(index)) != "") { - if(isNaN(parseInt(index))) - { - var slide = container.find('[data-orbit-slide='+index+']'); - if (slide.index() != -1) {self._goto(slide.index() + 1);} - } - else - { - self._goto(parseInt(index)); - } - } - - } - - self.timer_callback = function() { - self._goto(idx + 1, true); - } - - self.compute_dimensions = function() { - var current = $(self.slides().get(idx)); - var h = current.height(); - if (!settings.variable_height) { - self.slides().each(function(){ - if ($(this).height() > h) { h = $(this).height(); } - }); - } - slides_container.height(h); - }; - - self.create_timer = function() { - var t = new Timer( - container.find('.'+settings.timer_container_class), - settings, - self.timer_callback - ); - return t; - }; - - self.stop_timer = function() { - if (typeof timer === 'object') timer.stop(); - }; - - self.toggle_timer = function() { - var t = container.find('.'+settings.timer_container_class); - if (t.hasClass(settings.timer_paused_class)) { - if (typeof timer === 'undefined') {timer = self.create_timer();} - timer.start(); - } - else { - if (typeof timer === 'object') {timer.stop();} - } - }; - - self.init = function() { - self.build_markup(); - if (settings.timer) { - timer = self.create_timer(); - Foundation.utils.image_loaded(this.slides().children('img'), timer.start); - } - animate = new FadeAnimation(settings, slides_container); - if (settings.animation === 'slide') - animate = new SlideAnimation(settings, slides_container); - container.on('click', '.'+settings.next_class, self.next); - container.on('click', '.'+settings.prev_class, self.prev); - container.on('click', '[data-orbit-slide]', self.link_bullet); - container.on('click', self.toggle_timer); - if (settings.swipe) { - container.on('touchstart.fndtn.orbit', function(e) { - if (!e.touches) {e = e.originalEvent;} - var data = { - start_page_x: e.touches[0].pageX, - start_page_y: e.touches[0].pageY, - start_time: (new Date()).getTime(), - delta_x: 0, - is_scrolling: undefined - }; - container.data('swipe-transition', data); - e.stopPropagation(); - }) - .on('touchmove.fndtn.orbit', function(e) { - if (!e.touches) { e = e.originalEvent; } - // Ignore pinch/zoom events - if(e.touches.length > 1 || e.scale && e.scale !== 1) return; - - var data = container.data('swipe-transition'); - if (typeof data === 'undefined') {data = {};} - - data.delta_x = e.touches[0].pageX - data.start_page_x; - - if ( typeof data.is_scrolling === 'undefined') { - data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) ); - } - - if (!data.is_scrolling && !data.active) { - e.preventDefault(); - var direction = (data.delta_x < 0) ? (idx+1) : (idx-1); - data.active = true; - self._goto(direction); - } - }) - .on('touchend.fndtn.orbit', function(e) { - container.data('swipe-transition', {}); - e.stopPropagation(); - }) - } - container.on('mouseenter.fndtn.orbit', function(e) { - if (settings.timer && settings.pause_on_hover) { - self.stop_timer(); - } - }) - .on('mouseleave.fndtn.orbit', function(e) { - if (settings.timer && settings.resume_on_mouseout) { - timer.start(); - } - }); - - $(document).on('click', '[data-orbit-link]', self.link_custom); - $(window).on('resize', self.compute_dimensions); - Foundation.utils.image_loaded(this.slides().children('img'), self.compute_dimensions); - Foundation.utils.image_loaded(this.slides().children('img'), function() { - container.prev('.preloader').css('display', 'none'); - self.update_slide_number(0); - self.update_active_link(0); - slides_container.trigger('ready.fndtn.orbit'); - }); - }; - - self.init(); - }; - - var Timer = function(el, settings, callback) { - var self = this, - duration = settings.timer_speed, - progress = el.find('.'+settings.timer_progress_class), - start, - timeout, - left = -1; - - this.update_progress = function(w) { - var new_progress = progress.clone(); - new_progress.attr('style', ''); - new_progress.css('width', w+'%'); - progress.replaceWith(new_progress); - progress = new_progress; - }; - - this.restart = function() { - clearTimeout(timeout); - el.addClass(settings.timer_paused_class); - left = -1; - self.update_progress(0); - }; - - this.start = function() { - if (!el.hasClass(settings.timer_paused_class)) {return true;} - left = (left === -1) ? duration : left; - el.removeClass(settings.timer_paused_class); - start = new Date().getTime(); - progress.animate({'width': '100%'}, left, 'linear'); - timeout = setTimeout(function() { - self.restart(); - callback(); - }, left); - el.trigger('timer-started.fndtn.orbit') - }; - - this.stop = function() { - if (el.hasClass(settings.timer_paused_class)) {return true;} - clearTimeout(timeout); - el.addClass(settings.timer_paused_class); - var end = new Date().getTime(); - left = left - (end - start); - var w = 100 - ((left / duration) * 100); - self.update_progress(w); - el.trigger('timer-stopped.fndtn.orbit'); - }; - }; - - var SlideAnimation = function(settings, container) { - var duration = settings.animation_speed; - var is_rtl = ($('html[dir=rtl]').length === 1); - var margin = is_rtl ? 'marginRight' : 'marginLeft'; - var animMargin = {}; - animMargin[margin] = '0%'; - - this.next = function(current, next, callback) { - current.animate({marginLeft:'-100%'}, duration); - next.animate(animMargin, duration, function() { - current.css(margin, '100%'); - callback(); - }); - }; - - this.prev = function(current, prev, callback) { - current.animate({marginLeft:'100%'}, duration); - prev.css(margin, '-100%'); - prev.animate(animMargin, duration, function() { - current.css(margin, '100%'); - callback(); - }); - }; - }; - - var FadeAnimation = function(settings, container) { - var duration = settings.animation_speed; - var is_rtl = ($('html[dir=rtl]').length === 1); - var margin = is_rtl ? 'marginRight' : 'marginLeft'; - - this.next = function(current, next, callback) { - next.css({'margin':'0%', 'opacity':'0.01'}); - next.animate({'opacity':'1'}, duration, 'linear', function() { - current.css('margin', '100%'); - callback(); - }); - }; - - this.prev = function(current, prev, callback) { - prev.css({'margin':'0%', 'opacity':'0.01'}); - prev.animate({'opacity':'1'}, duration, 'linear', function() { - current.css('margin', '100%'); - callback(); - }); - }; - }; - - - Foundation.libs = Foundation.libs || {}; - - Foundation.libs.orbit = { - name: 'orbit', - - version: '5.1.1', - - settings: { - animation: 'slide', - timer_speed: 10000, - pause_on_hover: true, - resume_on_mouseout: false, - animation_speed: 500, - stack_on_small: false, - navigation_arrows: true, - slide_number: true, - slide_number_text: 'of', - container_class: 'orbit-container', - stack_on_small_class: 'orbit-stack-on-small', - next_class: 'orbit-next', - prev_class: 'orbit-prev', - timer_container_class: 'orbit-timer', - timer_paused_class: 'paused', - timer_progress_class: 'orbit-progress', - slides_container_class: 'orbit-slides-container', - slide_selector: '*', - bullets_container_class: 'orbit-bullets', - bullets_active_class: 'active', - slide_number_class: 'orbit-slide-number', - caption_class: 'orbit-caption', - active_slide_class: 'active', - orbit_transition_class: 'orbit-transitioning', - bullets: true, - circular: true, - timer: true, - variable_height: false, - swipe: true, - before_slide_change: noop, - after_slide_change: noop - }, - - init : function (scope, method, options) { - var self = this; - this.bindings(method, options); - }, - - events : function (instance) { - var orbit_instance = new Orbit(this.S(instance), this.S(instance).data('orbit-init')); - this.S(instance).data(self.name + '-instance', orbit_instance); - }, - - reflow : function () { - var self = this; - - if (self.S(self.scope).is('[data-orbit]')) { - var $el = self.S(self.scope); - var instance = $el.data(self.name + '-instance'); - instance.compute_dimensions(); - } else { - self.S('[data-orbit]', self.scope).each(function(idx, el) { - var $el = self.S(el); - var opts = self.data_options($el); - var instance = $el.data(self.name + '-instance'); - instance.compute_dimensions(); - }); - } - } - }; - - -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.reveal.js b/coin/static/js/foundation/foundation.reveal.js deleted file mode 100644 index 659bec4fa95d42f918337afcc454d288323b4d4d..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.reveal.js +++ /dev/null @@ -1,399 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.reveal = { - name : 'reveal', - - version : '5.1.1', - - locked : false, - - settings : { - animation: 'fadeAndPop', - animation_speed: 250, - close_on_background_click: true, - close_on_esc: true, - dismiss_modal_class: 'close-reveal-modal', - bg_class: 'reveal-modal-bg', - open: function(){}, - opened: function(){}, - close: function(){}, - closed: function(){}, - bg : $('.reveal-modal-bg'), - css : { - open : { - 'opacity': 0, - 'visibility': 'visible', - 'display' : 'block' - }, - close : { - 'opacity': 1, - 'visibility': 'hidden', - 'display': 'none' - } - } - }, - - init : function (scope, method, options) { - $.extend(true, this.settings, method, options); - this.bindings(method, options); - }, - - events : function (scope) { - var self = this, - S = self.S; - - S(this.scope) - .off('.reveal') - .on('click.fndtn.reveal', '[' + this.add_namespace('data-reveal-id') + ']', function (e) { - e.preventDefault(); - - if (!self.locked) { - var element = S(this), - ajax = element.data(self.data_attr('reveal-ajax')); - - self.locked = true; - - if (typeof ajax === 'undefined') { - self.open.call(self, element); - } else { - var url = ajax === true ? element.attr('href') : ajax; - - self.open.call(self, element, {url: url}); - } - } - }); - - S(document) - .on('click.fndtn.reveal', this.close_targets(), function (e) { - - e.preventDefault(); - - if (!self.locked) { - var settings = S('[' + self.attr_name() + '].open').data(self.attr_name(true) + '-init'), - bg_clicked = S(e.target)[0] === S('.' + settings.bg_class)[0]; - - if (bg_clicked && !settings.close_on_background_click) { - return; - } - - self.locked = true; - self.close.call(self, bg_clicked ? S('[' + self.attr_name() + '].open') : S(this).closest('[' + self.attr_name() + ']')); - } - }); - - if(S('[' + self.attr_name() + ']', this.scope).length > 0) { - S(this.scope) - // .off('.reveal') - .on('open.fndtn.reveal', this.settings.open) - .on('opened.fndtn.reveal', this.settings.opened) - .on('opened.fndtn.reveal', this.open_video) - .on('close.fndtn.reveal', this.settings.close) - .on('closed.fndtn.reveal', this.settings.closed) - .on('closed.fndtn.reveal', this.close_video); - } else { - S(this.scope) - // .off('.reveal') - .on('open.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.open) - .on('opened.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.opened) - .on('opened.fndtn.reveal', '[' + self.attr_name() + ']', this.open_video) - .on('close.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.close) - .on('closed.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.closed) - .on('closed.fndtn.reveal', '[' + self.attr_name() + ']', this.close_video); - } - - return true; - }, - - // PATCH #3: turning on key up capture only when a reveal window is open - key_up_on : function (scope) { - var self = this; - - // PATCH #1: fixing multiple keyup event trigger from single key press - self.S('body').off('keyup.fndtn.reveal').on('keyup.fndtn.reveal', function ( event ) { - var open_modal = self.S('[' + self.attr_name() + '].open'), - settings = open_modal.data(self.attr_name(true) + '-init'); - // PATCH #2: making sure that the close event can be called only while unlocked, - // so that multiple keyup.fndtn.reveal events don't prevent clean closing of the reveal window. - if ( settings && event.which === 27 && settings.close_on_esc && !self.locked) { // 27 is the keycode for the Escape key - self.close.call(self, open_modal); - } - }); - - return true; - }, - - // PATCH #3: turning on key up capture only when a reveal window is open - key_up_off : function (scope) { - this.S('body').off('keyup.fndtn.reveal'); - return true; - }, - - open : function (target, ajax_settings) { - var self = this; - if (target) { - if (typeof target.selector !== 'undefined') { - var modal = self.S('#' + target.data(self.data_attr('reveal-id'))); - } else { - var modal = self.S(this.scope); - - ajax_settings = target; - } - } else { - var modal = self.S(this.scope); - } - - var settings = modal.data(self.attr_name(true) + '-init'); - - if (!modal.hasClass('open')) { - var open_modal = self.S('[' + self.attr_name() + '].open'); - - if (typeof modal.data('css-top') === 'undefined') { - modal.data('css-top', parseInt(modal.css('top'), 10)) - .data('offset', this.cache_offset(modal)); - } - - this.key_up_on(modal); // PATCH #3: turning on key up capture only when a reveal window is open - modal.trigger('open'); - - if (open_modal.length < 1) { - this.toggle_bg(modal); - } - - if (typeof ajax_settings === 'string') { - ajax_settings = { - url: ajax_settings - }; - } - - if (typeof ajax_settings === 'undefined' || !ajax_settings.url) { - if (open_modal.length > 0) { - var open_modal_settings = open_modal.data(self.attr_name(true) + '-init'); - this.hide(open_modal, open_modal_settings.css.close); - } - - this.show(modal, settings.css.open); - } else { - var old_success = typeof ajax_settings.success !== 'undefined' ? ajax_settings.success : null; - - $.extend(ajax_settings, { - success: function (data, textStatus, jqXHR) { - if ( $.isFunction(old_success) ) { - old_success(data, textStatus, jqXHR); - } - - modal.html(data); - self.S(modal).foundation('section', 'reflow'); - - if (open_modal.length > 0) { - var open_modal_settings = open_modal.data(self.attr_name(true)); - self.hide(open_modal, open_modal_settings.css.close); - } - self.show(modal, settings.css.open); - } - }); - - $.ajax(ajax_settings); - } - } - }, - - close : function (modal) { - var modal = modal && modal.length ? modal : this.S(this.scope), - open_modals = this.S('[' + this.attr_name() + '].open'), - settings = modal.data(this.attr_name(true) + '-init'); - - if (open_modals.length > 0) { - this.locked = true; - this.key_up_off(modal); // PATCH #3: turning on key up capture only when a reveal window is open - modal.trigger('close'); - this.toggle_bg(modal); - this.hide(open_modals, settings.css.close, settings); - } - }, - - close_targets : function () { - var base = '.' + this.settings.dismiss_modal_class; - - if (this.settings.close_on_background_click) { - return base + ', .' + this.settings.bg_class; - } - - return base; - }, - - toggle_bg : function (modal) { - var settings = modal.data(this.attr_name(true)); - - if (this.S('.' + this.settings.bg_class).length === 0) { - this.settings.bg = $('
        ', {'class': this.settings.bg_class}) - .appendTo('body'); - } - - if (this.settings.bg.filter(':visible').length > 0) { - this.hide(this.settings.bg); - } else { - this.show(this.settings.bg); - } - }, - - show : function (el, css) { - // is modal - if (css) { - var settings = el.data(this.attr_name(true) + '-init'); - if (el.parent('body').length === 0) { - var placeholder = el.wrap('
        ').parent(), - rootElement = this.settings.rootElement || 'body'; - - el.on('closed.fndtn.reveal.wrapped', function() { - el.detach().appendTo(placeholder); - el.unwrap().unbind('closed.fndtn.reveal.wrapped'); - }); - - el.detach().appendTo(rootElement); - } - - if (/pop/i.test(settings.animation)) { - css.top = $(window).scrollTop() - el.data('offset') + 'px'; - var end_css = { - top: $(window).scrollTop() + el.data('css-top') + 'px', - opacity: 1 - }; - - return setTimeout(function () { - return el - .css(css) - .animate(end_css, settings.animation_speed, 'linear', function () { - this.locked = false; - el.trigger('opened'); - }.bind(this)) - .addClass('open'); - }.bind(this), settings.animation_speed / 2); - } - - if (/fade/i.test(settings.animation)) { - var end_css = {opacity: 1}; - - return setTimeout(function () { - return el - .css(css) - .animate(end_css, settings.animation_speed, 'linear', function () { - this.locked = false; - el.trigger('opened'); - }.bind(this)) - .addClass('open'); - }.bind(this), settings.animation_speed / 2); - } - - return el.css(css).show().css({opacity: 1}).addClass('open').trigger('opened'); - } - - var settings = this.settings; - - // should we animate the background? - if (/fade/i.test(settings.animation)) { - return el.fadeIn(settings.animation_speed / 2); - } - - this.locked = false; - - return el.show(); - }, - - hide : function (el, css) { - // is modal - if (css) { - var settings = el.data(this.attr_name(true) + '-init'); - if (/pop/i.test(settings.animation)) { - var end_css = { - top: - $(window).scrollTop() - el.data('offset') + 'px', - opacity: 0 - }; - - return setTimeout(function () { - return el - .animate(end_css, settings.animation_speed, 'linear', function () { - this.locked = false; - el.css(css).trigger('closed'); - }.bind(this)) - .removeClass('open'); - }.bind(this), settings.animation_speed / 2); - } - - if (/fade/i.test(settings.animation)) { - var end_css = {opacity: 0}; - - return setTimeout(function () { - return el - .animate(end_css, settings.animation_speed, 'linear', function () { - this.locked = false; - el.css(css).trigger('closed'); - }.bind(this)) - .removeClass('open'); - }.bind(this), settings.animation_speed / 2); - } - - return el.hide().css(css).removeClass('open').trigger('closed'); - } - - var settings = this.settings; - - // should we animate the background? - if (/fade/i.test(settings.animation)) { - return el.fadeOut(settings.animation_speed / 2); - } - - return el.hide(); - }, - - close_video : function (e) { - var video = $('.flex-video', e.target), - iframe = $('iframe', video); - - if (iframe.length > 0) { - iframe.attr('data-src', iframe[0].src); - iframe.attr('src', 'about:blank'); - video.hide(); - } - }, - - open_video : function (e) { - var video = $('.flex-video', e.target), - iframe = video.find('iframe'); - - if (iframe.length > 0) { - var data_src = iframe.attr('data-src'); - if (typeof data_src === 'string') { - iframe[0].src = iframe.attr('data-src'); - } else { - var src = iframe[0].src; - iframe[0].src = undefined; - iframe[0].src = src; - } - video.show(); - } - }, - - data_attr: function (str) { - if (this.namespace.length > 0) { - return this.namespace + '-' + str; - } - - return str; - }, - - cache_offset : function (modal) { - var offset = modal.show().height() + parseInt(modal.css('top'), 10); - - modal.hide(); - - return offset; - }, - - off : function () { - $(this.scope).off('.fndtn.reveal'); - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.tab.js b/coin/static/js/foundation/foundation.tab.js deleted file mode 100644 index 24bece04c6c12da2a149266bc567b973cb133c82..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.tab.js +++ /dev/null @@ -1,58 +0,0 @@ -/*jslint unparam: true, browser: true, indent: 2 */ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.tab = { - name : 'tab', - - version : '5.1.1', - - settings : { - active_class: 'active', - callback : function () {} - }, - - init : function (scope, method, options) { - this.bindings(method, options); - }, - - events : function () { - var self = this, - S = this.S; - - S(this.scope).off('.tab').on('click.fndtn.tab', '[' + this.attr_name() + '] > dd > a', function (e) { - e.preventDefault(); - e.stopPropagation(); - - var tab = S(this).parent(), - tabs = tab.closest('[' + self.attr_name() + ']'), - target = S('#' + this.href.split('#')[1]), - siblings = tab.siblings(), - settings = tabs.data(self.attr_name(true) + '-init'); - - // allow usage of data-tab-content attribute instead of href - if (S(this).data(self.data_attr('tab-content'))) { - target = S('#' + S(this).data(self.data_attr('tab-content')).split('#')[1]); - } - - tab.addClass(settings.active_class).triggerHandler('opened'); - siblings.removeClass(settings.active_class); - target.siblings().removeClass(settings.active_class).end().addClass(settings.active_class); - settings.callback(tab); - tabs.triggerHandler('toggled', [tab]); - }); - }, - - data_attr: function (str) { - if (this.namespace.length > 0) { - return this.namespace + '-' + str; - } - - return str; - }, - - off : function () {}, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.tooltip.js b/coin/static/js/foundation/foundation.tooltip.js deleted file mode 100644 index cffc9d609f840ffbb345288dac20499738187ae1..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.tooltip.js +++ /dev/null @@ -1,215 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.tooltip = { - name : 'tooltip', - - version : '5.1.1', - - settings : { - additional_inheritable_classes : [], - tooltip_class : '.tooltip', - append_to: 'body', - touch_close_text: 'Tap To Close', - disable_for_touch: false, - hover_delay: 200, - tip_template : function (selector, content) { - return '' + content + ''; - } - }, - - cache : {}, - - init : function (scope, method, options) { - Foundation.inherit(this, 'random_str'); - this.bindings(method, options); - }, - - events : function () { - var self = this, - S = self.S; - - if (Modernizr.touch) { - S(document) - .off('.tooltip') - .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip', - '[' + this.attr_name() + ']:not(a)', function (e) { - var settings = $.extend({}, self.settings, self.data_options(S(this))); - if (!settings.disable_for_touch) { - e.preventDefault(); - S(settings.tooltip_class).hide(); - self.showOrCreateTip(S(this)); - } - }) - .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip', - this.settings.tooltip_class, function (e) { - e.preventDefault(); - S(this).fadeOut(150); - }); - } else { - S(document) - .off('.tooltip') - .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip', - '[' + this.attr_name() + ']', function (e) { - var $this = S(this); - - if (/enter|over/i.test(e.type)) { - this.timer = setTimeout(function () { - var tip = self.showOrCreateTip($this); - }.bind(this), self.settings.hover_delay); - } else if (e.type === 'mouseout' || e.type === 'mouseleave') { - clearTimeout(this.timer); - self.hide($this); - } - }); - } - }, - - showOrCreateTip : function ($target) { - var $tip = this.getTip($target); - - if ($tip && $tip.length > 0) { - return this.show($target); - } - - return this.create($target); - }, - - getTip : function ($target) { - var selector = this.selector($target), - tip = null; - - if (selector) { - tip = this.S('span[data-selector="' + selector + '"]' + this.settings.tooltip_class); - } - - return (typeof tip === 'object') ? tip : false; - }, - - selector : function ($target) { - var id = $target.attr('id'), - dataSelector = $target.attr(this.attr_name()) || $target.attr('data-selector'); - - if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') { - dataSelector = 'tooltip' + this.random_str(6); - $target.attr('data-selector', dataSelector); - } - - return (id && id.length > 0) ? id : dataSelector; - }, - - create : function ($target) { - var $tip = $(this.settings.tip_template(this.selector($target), $('
        ').html($target.attr('title')).html())), - classes = this.inheritable_classes($target); - - $tip.addClass(classes).appendTo(this.settings.append_to); - if (Modernizr.touch) { - $tip.append(''+this.settings.touch_close_text+''); - } - $target.removeAttr('title').attr('title',''); - this.show($target); - }, - - reposition : function (target, tip, classes) { - var width, nub, nubHeight, nubWidth, column, objPos; - - tip.css('visibility', 'hidden').show(); - - width = target.data('width'); - nub = tip.children('.nub'); - nubHeight = nub.outerHeight(); - nubWidth = nub.outerHeight(); - - if(this.small()) { - tip.css({'width' : '100%' }); - } else { - tip.css({'width' : (width) ? width : 'auto'}); - } - - objPos = function (obj, top, right, bottom, left, width) { - return obj.css({ - 'top' : (top) ? top : 'auto', - 'bottom' : (bottom) ? bottom : 'auto', - 'left' : (left) ? left : 'auto', - 'right' : (right) ? right : 'auto' - }).end(); - }; - - objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left); - - if (this.small()) { - objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, this.S(this.scope).width()); - tip.addClass('tip-override'); - objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left + 10); - } else { - var left = target.offset().left; - if (Foundation.rtl) { - left = target.offset().left + target.outerWidth() - tip.outerWidth(); - } - - objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left); - tip.removeClass('tip-override'); - nub.removeAttr( 'style' ); - if (classes && classes.indexOf('tip-top') > -1) { - objPos(tip, (target.offset().top - tip.outerHeight() - 10), 'auto', 'auto', left) - .removeClass('tip-override'); - } else if (classes && classes.indexOf('tip-left') > -1) { - objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight)) - .removeClass('tip-override'); - } else if (classes && classes.indexOf('tip-right') > -1) { - objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight)) - .removeClass('tip-override'); - } - } - - tip.css('visibility', 'visible').hide(); - }, - - small : function () { - return matchMedia(Foundation.media_queries.small).matches; - }, - - inheritable_classes : function (target) { - var inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'radius', 'round'].concat(this.settings.additional_inheritable_classes), - classes = target.attr('class'), - filtered = classes ? $.map(classes.split(' '), function (el, i) { - if ($.inArray(el, inheritables) !== -1) { - return el; - } - }).join(' ') : ''; - - return $.trim(filtered); - }, - - show : function ($target) { - var $tip = this.getTip($target); - - this.reposition($target, $tip, $target.attr('class')); - return $tip.fadeIn(150); - }, - - hide : function ($target) { - var $tip = this.getTip($target); - - return $tip.fadeOut(150); - }, - - // deprecate reload - reload : function () { - var $self = $(this); - - return ($self.data('fndtn-tooltips')) ? $self.foundationTooltips('destroy').foundationTooltips('init') : $self.foundationTooltips('init'); - }, - - off : function () { - this.S(this.scope).off('.fndtn.tooltip'); - this.S(this.settings.tooltip_class).each(function (i) { - $('[' + this.attr_name() + ']').get(i).attr('title', $(this).text()); - }).remove(); - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/foundation.topbar.js b/coin/static/js/foundation/foundation.topbar.js deleted file mode 100644 index 5190848485766a26ed508abc3bc8a13dd8460e22..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/foundation.topbar.js +++ /dev/null @@ -1,387 +0,0 @@ -;(function ($, window, document, undefined) { - 'use strict'; - - Foundation.libs.topbar = { - name : 'topbar', - - version: '5.1.1', - - settings : { - index : 0, - sticky_class : 'sticky', - custom_back_text: true, - back_text: 'Back', - is_hover: true, - mobile_show_parent_link: false, - scrolltop : true // jump to top when sticky nav menu toggle is clicked - }, - - init : function (section, method, options) { - Foundation.inherit(this, 'add_custom_rule register_media throttle'); - var self = this; - - self.register_media('topbar', 'foundation-mq-topbar'); - - this.bindings(method, options); - - self.S('[' + this.attr_name() + ']', this.scope).each(function () { - var topbar = self.S(this), - settings = topbar.data(self.attr_name(true) + '-init'), - section = self.S('section', this), - titlebar = $('> ul', this).first(); - - topbar.data('index', 0); - - var topbarContainer = topbar.parent(); - if(topbarContainer.hasClass('fixed') || topbarContainer.hasClass(settings.sticky_class)) { - self.settings.sticky_class = settings.sticky_class; - self.settings.sticky_topbar = topbar; - topbar.data('height', topbarContainer.outerHeight()); - topbar.data('stickyoffset', topbarContainer.offset().top); - } else { - topbar.data('height', topbar.outerHeight()); - } - - if (!settings.assembled) self.assemble(topbar); - - if (settings.is_hover) { - self.S('.has-dropdown', topbar).addClass('not-click'); - } else { - self.S('.has-dropdown', topbar).removeClass('not-click'); - } - - // Pad body when sticky (scrolled) or fixed. - self.add_custom_rule('.f-topbar-fixed { padding-top: ' + topbar.data('height') + 'px }'); - - if (topbarContainer.hasClass('fixed')) { - self.S('body').addClass('f-topbar-fixed'); - } - }); - - }, - - toggle: function (toggleEl) { - var self = this; - - if (toggleEl) { - var topbar = self.S(toggleEl).closest('[' + this.attr_name() + ']'); - } else { - var topbar = self.S('[' + this.attr_name() + ']'); - } - - var settings = topbar.data(this.attr_name(true) + '-init'); - - var section = self.S('section, .section', topbar); - - if (self.breakpoint()) { - if (!self.rtl) { - section.css({left: '0%'}); - $('>.name', section).css({left: '100%'}); - } else { - section.css({right: '0%'}); - $('>.name', section).css({right: '100%'}); - } - - self.S('li.moved', section).removeClass('moved'); - topbar.data('index', 0); - - topbar - .toggleClass('expanded') - .css('height', ''); - } - - if (settings.scrolltop) { - if (!topbar.hasClass('expanded')) { - if (topbar.hasClass('fixed')) { - topbar.parent().addClass('fixed'); - topbar.removeClass('fixed'); - self.S('body').addClass('f-topbar-fixed'); - } - } else if (topbar.parent().hasClass('fixed')) { - if (settings.scrolltop) { - topbar.parent().removeClass('fixed'); - topbar.addClass('fixed'); - self.S('body').removeClass('f-topbar-fixed'); - - window.scrollTo(0,0); - } else { - topbar.parent().removeClass('expanded'); - } - } - } else { - if(topbar.parent().hasClass(self.settings.sticky_class)) { - topbar.parent().addClass('fixed'); - } - - if(topbar.parent().hasClass('fixed')) { - if (!topbar.hasClass('expanded')) { - topbar.removeClass('fixed'); - topbar.parent().removeClass('expanded'); - self.update_sticky_positioning(); - } else { - topbar.addClass('fixed'); - topbar.parent().addClass('expanded'); - self.S('body').addClass('f-topbar-fixed'); - } - } - } - }, - - timer : null, - - events : function (bar) { - var self = this, - S = this.S; - - S(this.scope) - .off('.topbar') - .on('click.fndtn.topbar', '[' + this.attr_name() + '] .toggle-topbar', function (e) { - e.preventDefault(); - self.toggle(this); - }) - .on('click.fndtn.topbar', '[' + this.attr_name() + '] li.has-dropdown', function (e) { - var li = S(this), - target = S(e.target), - topbar = li.closest('[' + self.attr_name() + ']'), - settings = topbar.data(self.attr_name(true) + '-init'); - - if(target.data('revealId')) { - self.toggle(); - return; - } - - if (self.breakpoint()) return; - if (settings.is_hover && !Modernizr.touch) return; - - e.stopImmediatePropagation(); - - if (li.hasClass('hover')) { - li - .removeClass('hover') - .find('li') - .removeClass('hover'); - - li.parents('li.hover') - .removeClass('hover'); - } else { - li.addClass('hover'); - - if (target[0].nodeName === 'A' && target.parent().hasClass('has-dropdown')) { - e.preventDefault(); - } - } - }) - .on('click.fndtn.topbar', '[' + this.attr_name() + '] .has-dropdown>a', function (e) { - if (self.breakpoint()) { - - e.preventDefault(); - - var $this = S(this), - topbar = $this.closest('[' + self.attr_name() + ']'), - section = topbar.find('section, .section'), - dropdownHeight = $this.next('.dropdown').outerHeight(), - $selectedLi = $this.closest('li'); - - topbar.data('index', topbar.data('index') + 1); - $selectedLi.addClass('moved'); - - if (!self.rtl) { - section.css({left: -(100 * topbar.data('index')) + '%'}); - section.find('>.name').css({left: 100 * topbar.data('index') + '%'}); - } else { - section.css({right: -(100 * topbar.data('index')) + '%'}); - section.find('>.name').css({right: 100 * topbar.data('index') + '%'}); - } - - topbar.css('height', $this.siblings('ul').outerHeight(true) + topbar.data('height')); - } - }); - - S(window).off('.topbar').on('resize.fndtn.topbar', self.throttle(function () { - self.resize.call(self); - }, 50)).trigger('resize'); - - S('body').off('.topbar').on('click.fndtn.topbar touchstart.fndtn.topbar', function (e) { - var parent = S(e.target).closest('li').closest('li.hover'); - - if (parent.length > 0) { - return; - } - - S('[' + self.attr_name() + '] li').removeClass('hover'); - }); - - // Go up a level on Click - S(this.scope).on('click.fndtn.topbar', '[' + this.attr_name() + '] .has-dropdown .back', function (e) { - e.preventDefault(); - - var $this = S(this), - topbar = $this.closest('[' + self.attr_name() + ']'), - section = topbar.find('section, .section'), - settings = topbar.data(self.attr_name(true) + '-init'), - $movedLi = $this.closest('li.moved'), - $previousLevelUl = $movedLi.parent(); - - topbar.data('index', topbar.data('index') - 1); - - if (!self.rtl) { - section.css({left: -(100 * topbar.data('index')) + '%'}); - section.find('>.name').css({left: 100 * topbar.data('index') + '%'}); - } else { - section.css({right: -(100 * topbar.data('index')) + '%'}); - section.find('>.name').css({right: 100 * topbar.data('index') + '%'}); - } - - if (topbar.data('index') === 0) { - topbar.css('height', ''); - } else { - topbar.css('height', $previousLevelUl.outerHeight(true) + topbar.data('height')); - } - - setTimeout(function () { - $movedLi.removeClass('moved'); - }, 300); - }); - }, - - resize : function () { - var self = this; - self.S('[' + this.attr_name() + ']').each(function () { - var topbar = self.S(this), - settings = topbar.data(self.attr_name(true) + '-init'); - - var stickyContainer = topbar.parent('.' + self.settings.sticky_class); - var stickyOffset; - - if (!self.breakpoint()) { - var doToggle = topbar.hasClass('expanded'); - topbar - .css('height', '') - .removeClass('expanded') - .find('li') - .removeClass('hover'); - - if(doToggle) { - self.toggle(topbar); - } - } - - if(stickyContainer.length > 0) { - if(stickyContainer.hasClass('fixed')) { - // Remove the fixed to allow for correct calculation of the offset. - stickyContainer.removeClass('fixed'); - - stickyOffset = stickyContainer.offset().top; - if(self.S(document.body).hasClass('f-topbar-fixed')) { - stickyOffset -= topbar.data('height'); - } - - topbar.data('stickyoffset', stickyOffset); - stickyContainer.addClass('fixed'); - } else { - stickyOffset = stickyContainer.offset().top; - topbar.data('stickyoffset', stickyOffset); - } - } - - }); - }, - - breakpoint : function () { - return !matchMedia(Foundation.media_queries['topbar']).matches; - }, - - assemble : function (topbar) { - var self = this, - settings = topbar.data(this.attr_name(true) + '-init'), - section = self.S('section', topbar), - titlebar = $('> ul', topbar).first(); - - // Pull element out of the DOM for manipulation - section.detach(); - - self.S('.has-dropdown>a', section).each(function () { - var $link = self.S(this), - $dropdown = $link.siblings('.dropdown'), - url = $link.attr('href'); - - if (!$dropdown.find('.title.back').length) { - if (settings.mobile_show_parent_link && url && url.length > 1) { - var $titleLi = $('
      2. ' + $link.text() +'
      3. '); - } else { - var $titleLi = $('
      4. '); - } - - // Copy link to subnav - if (settings.custom_back_text == true) { - $('h5>a', $titleLi).html(settings.back_text); - } else { - $('h5>a', $titleLi).html('« ' + $link.html()); - } - $dropdown.prepend($titleLi); - } - }); - - // Put element back in the DOM - section.appendTo(topbar); - - // check for sticky - this.sticky(); - - this.assembled(topbar); - }, - - assembled : function (topbar) { - topbar.data(this.attr_name(true), $.extend({}, topbar.data(this.attr_name(true)), {assembled: true})); - }, - - height : function (ul) { - var total = 0, - self = this; - - $('> li', ul).each(function () { total += self.S(this).outerHeight(true); }); - - return total; - }, - - sticky : function () { - var $window = this.S(window), - self = this; - - this.S(window).on('scroll', function() { - self.update_sticky_positioning(); - }); - }, - - update_sticky_positioning: function() { - var klass = '.' + this.settings.sticky_class, - $window = this.S(window), - self = this; - - - if (self.S(klass).length > 0) { - var distance = this.settings.sticky_topbar.data('stickyoffset'); - if (!self.S(klass).hasClass('expanded')) { - if ($window.scrollTop() > (distance)) { - if (!self.S(klass).hasClass('fixed')) { - self.S(klass).addClass('fixed'); - self.S('body').addClass('f-topbar-fixed'); - } - } else if ($window.scrollTop() <= distance) { - if (self.S(klass).hasClass('fixed')) { - self.S(klass).removeClass('fixed'); - self.S('body').removeClass('f-topbar-fixed'); - } - } - } - } - }, - - off : function () { - this.S(this.scope).off('.fndtn.topbar'); - this.S(window).off('.fndtn.topbar'); - }, - - reflow : function () {} - }; -}(jQuery, this, this.document)); diff --git a/coin/static/js/foundation/jquery.cookie.js b/coin/static/js/foundation/jquery.cookie.js deleted file mode 100644 index ed014621b83e040b241eecdb0ad2e65a0897d9d4..0000000000000000000000000000000000000000 --- a/coin/static/js/foundation/jquery.cookie.js +++ /dev/null @@ -1,8 +0,0 @@ -/*! - * jQuery Cookie Plugin v1.4.0 - * https://github.com/carhartl/jquery-cookie - * - * Copyright 2013 Klaus Hartl - * Released under the MIT license - */ -!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{a=decodeURIComponent(a.replace(g," "))}catch(b){return}try{return h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setDate(k.getDate()+j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0!==a.cookie(b)?(a.cookie(b,"",a.extend({},c,{expires:-1})),!0):!1}}); diff --git a/coin/static/js/vendor/bootstrap.js b/coin/static/js/vendor/bootstrap.js new file mode 100644 index 0000000000000000000000000000000000000000..c4c0d1f95cd3ca1b97ed8e7f7f22a91fa24b4edf --- /dev/null +++ b/coin/static/js/vendor/bootstrap.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;nthis._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
      ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:''}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t0,FastClick.prototype.deviceIsIOS=/iP(ad|hone|od)/.test(navigator.userAgent),FastClick.prototype.deviceIsIOS4=FastClick.prototype.deviceIsIOS&&/OS 4_\d(_\d)?/.test(navigator.userAgent),FastClick.prototype.deviceIsIOSWithBadTarget=FastClick.prototype.deviceIsIOS&&/OS ([6-9]|\d{2})_\d/.test(navigator.userAgent),FastClick.prototype.needsClick=function(a){"use strict";switch(a.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(a.disabled)return!0;break;case"input":if(this.deviceIsIOS&&"file"===a.type||a.disabled)return!0;break;case"label":case"video":return!0}return/\bneedsclick\b/.test(a.className)},FastClick.prototype.needsFocus=function(a){"use strict";switch(a.nodeName.toLowerCase()){case"textarea":return!0;case"select":return!this.deviceIsAndroid;case"input":switch(a.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return!1}return!a.disabled&&!a.readOnly;default:return/\bneedsfocus\b/.test(a.className)}},FastClick.prototype.sendClick=function(a,b){"use strict";var c,d;document.activeElement&&document.activeElement!==a&&document.activeElement.blur(),d=b.changedTouches[0],c=document.createEvent("MouseEvents"),c.initMouseEvent(this.determineEventType(a),!0,!0,window,1,d.screenX,d.screenY,d.clientX,d.clientY,!1,!1,!1,!1,0,null),c.forwardedTouchEvent=!0,a.dispatchEvent(c)},FastClick.prototype.determineEventType=function(a){"use strict";return this.deviceIsAndroid&&"select"===a.tagName.toLowerCase()?"mousedown":"click"},FastClick.prototype.focus=function(a){"use strict";var b;this.deviceIsIOS&&a.setSelectionRange&&0!==a.type.indexOf("date")&&"time"!==a.type?(b=a.value.length,a.setSelectionRange(b,b)):a.focus()},FastClick.prototype.updateScrollParent=function(a){"use strict";var b,c;if(b=a.fastClickScrollParent,!b||!b.contains(a)){c=a;do{if(c.scrollHeight>c.offsetHeight){b=c,a.fastClickScrollParent=c;break}c=c.parentElement}while(c)}b&&(b.fastClickLastScrollTop=b.scrollTop)},FastClick.prototype.getTargetElementFromEventTarget=function(a){"use strict";return a.nodeType===Node.TEXT_NODE?a.parentNode:a},FastClick.prototype.onTouchStart=function(a){"use strict";var b,c,d;if(a.targetTouches.length>1)return!0;if(b=this.getTargetElementFromEventTarget(a.target),c=a.targetTouches[0],this.deviceIsIOS){if(d=window.getSelection(),d.rangeCount&&!d.isCollapsed)return!0;if(!this.deviceIsIOS4){if(c.identifier===this.lastTouchIdentifier)return a.preventDefault(),!1;this.lastTouchIdentifier=c.identifier,this.updateScrollParent(b)}}return this.trackingClick=!0,this.trackingClickStart=a.timeStamp,this.targetElement=b,this.touchStartX=c.pageX,this.touchStartY=c.pageY,a.timeStamp-this.lastClickTime<200&&a.preventDefault(),!0},FastClick.prototype.touchHasMoved=function(a){"use strict";var b=a.changedTouches[0],c=this.touchBoundary;return Math.abs(b.pageX-this.touchStartX)>c||Math.abs(b.pageY-this.touchStartY)>c?!0:!1},FastClick.prototype.onTouchMove=function(a){"use strict";return this.trackingClick?((this.targetElement!==this.getTargetElementFromEventTarget(a.target)||this.touchHasMoved(a))&&(this.trackingClick=!1,this.targetElement=null),!0):!0},FastClick.prototype.findControl=function(a){"use strict";return void 0!==a.control?a.control:a.htmlFor?document.getElementById(a.htmlFor):a.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")},FastClick.prototype.onTouchEnd=function(a){"use strict";var b,c,d,e,f,g=this.targetElement;if(!this.trackingClick)return!0;if(a.timeStamp-this.lastClickTime<200)return this.cancelNextClick=!0,!0;if(this.cancelNextClick=!1,this.lastClickTime=a.timeStamp,c=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,this.deviceIsIOSWithBadTarget&&(f=a.changedTouches[0],g=document.elementFromPoint(f.pageX-window.pageXOffset,f.pageY-window.pageYOffset)||g,g.fastClickScrollParent=this.targetElement.fastClickScrollParent),d=g.tagName.toLowerCase(),"label"===d){if(b=this.findControl(g)){if(this.focus(g),this.deviceIsAndroid)return!1;g=b}}else if(this.needsFocus(g))return a.timeStamp-c>100||this.deviceIsIOS&&window.top!==window&&"input"===d?(this.targetElement=null,!1):(this.focus(g),this.deviceIsIOS4&&"select"===d||(this.targetElement=null,a.preventDefault()),!1);return this.deviceIsIOS&&!this.deviceIsIOS4&&(e=g.fastClickScrollParent,e&&e.fastClickLastScrollTop!==e.scrollTop)?!0:(this.needsClick(g)||(a.preventDefault(),this.sendClick(g,a)),!1)},FastClick.prototype.onTouchCancel=function(){"use strict";this.trackingClick=!1,this.targetElement=null},FastClick.prototype.onMouse=function(a){"use strict";return this.targetElement?a.forwardedTouchEvent?!0:a.cancelable?!this.needsClick(this.targetElement)||this.cancelNextClick?(a.stopImmediatePropagation?a.stopImmediatePropagation():a.propagationStopped=!0,a.stopPropagation(),a.preventDefault(),!1):!0:!0:!0},FastClick.prototype.onClick=function(a){"use strict";var b;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):"submit"===a.target.type&&0===a.detail?!0:(b=this.onMouse(a),b||(this.targetElement=null),b)},FastClick.prototype.destroy=function(){"use strict";var a=this.layer;this.deviceIsAndroid&&(a.removeEventListener("mouseover",this.onMouse,!0),a.removeEventListener("mousedown",this.onMouse,!0),a.removeEventListener("mouseup",this.onMouse,!0)),a.removeEventListener("click",this.onClick,!0),a.removeEventListener("touchstart",this.onTouchStart,!1),a.removeEventListener("touchmove",this.onTouchMove,!1),a.removeEventListener("touchend",this.onTouchEnd,!1),a.removeEventListener("touchcancel",this.onTouchCancel,!1)},FastClick.notNeeded=function(a){"use strict";var b,c;if("undefined"==typeof window.ontouchstart)return!0;if(c=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!FastClick.prototype.deviceIsAndroid)return!0;if(b=document.querySelector("meta[name=viewport]")){if(-1!==b.content.indexOf("user-scalable=no"))return!0;if(c>31&&window.innerWidth<=window.screen.width)return!0}}return"none"===a.style.msTouchAction?!0:!1},FastClick.attach=function(a){"use strict";return new FastClick(a)},"undefined"!=typeof define&&define.amd?define(function(){"use strict";return FastClick}):"undefined"!=typeof module&&module.exports?(module.exports=FastClick.attach,module.exports.FastClick=FastClick):window.FastClick=FastClick; diff --git a/coin/static/js/vendor/jquery.cookie.js b/coin/static/js/vendor/jquery.cookie.js deleted file mode 100644 index ed014621b83e040b241eecdb0ad2e65a0897d9d4..0000000000000000000000000000000000000000 --- a/coin/static/js/vendor/jquery.cookie.js +++ /dev/null @@ -1,8 +0,0 @@ -/*! - * jQuery Cookie Plugin v1.4.0 - * https://github.com/carhartl/jquery-cookie - * - * Copyright 2013 Klaus Hartl - * Released under the MIT license - */ -!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{a=decodeURIComponent(a.replace(g," "))}catch(b){return}try{return h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setDate(k.getDate()+j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0!==a.cookie(b)?(a.cookie(b,"",a.extend({},c,{expires:-1})),!0):!1}}); diff --git a/coin/static/js/vendor/jquery.js b/coin/static/js/vendor/jquery.js index 22ac81bfbb8b60c1ec33e8fdee35084d4cdad20a..a1c07fd803b5fc9c54f44e31123ae4fa11e134b0 100644 --- a/coin/static/js/vendor/jquery.js +++ b/coin/static/js/vendor/jquery.js @@ -1,26 +1,2 @@ -/*! - * jQuery JavaScript Library v2.1.0 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-01-23T21:10Z - */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){function c(a){var b=a.length,c=ab.type(a);return"function"===c||ab.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}function d(a,b,c){if(ab.isFunction(b))return ab.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return ab.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(hb.test(b))return ab.filter(b,a,c);b=ab.filter(b,a)}return ab.grep(a,function(a){return U.call(b,a)>=0!==c})}function e(a,b){for(;(a=a[b])&&1!==a.nodeType;);return a}function f(a){var b=ob[a]={};return ab.each(a.match(nb)||[],function(a,c){b[c]=!0}),b}function g(){$.removeEventListener("DOMContentLoaded",g,!1),a.removeEventListener("load",g,!1),ab.ready()}function h(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=ab.expando+Math.random()}function i(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(ub,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:tb.test(c)?ab.parseJSON(c):c}catch(e){}sb.set(a,b,c)}else c=void 0;return c}function j(){return!0}function k(){return!1}function l(){try{return $.activeElement}catch(a){}}function m(a,b){return ab.nodeName(a,"table")&&ab.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function n(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function o(a){var b=Kb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function p(a,b){for(var c=0,d=a.length;d>c;c++)rb.set(a[c],"globalEval",!b||rb.get(b[c],"globalEval"))}function q(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(rb.hasData(a)&&(f=rb.access(a),g=rb.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)ab.event.add(b,e,j[e][c])}sb.hasData(a)&&(h=sb.access(a),i=ab.extend({},h),sb.set(b,i))}}function r(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&ab.nodeName(a,b)?ab.merge([a],c):c}function s(a,b){var c=b.nodeName.toLowerCase();"input"===c&&yb.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}function t(b,c){var d=ab(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:ab.css(d[0],"display");return d.detach(),e}function u(a){var b=$,c=Ob[a];return c||(c=t(a,b),"none"!==c&&c||(Nb=(Nb||ab("