diff --git a/Current Todo.txt b/Current Todo.txt new file mode 100644 index 0000000..04b9697 --- /dev/null +++ b/Current Todo.txt @@ -0,0 +1 @@ +1) check out the merge \ No newline at end of file diff --git a/LoFi_Mockups.pdf b/LoFi_Mockups.pdf new file mode 100644 index 0000000..304ef0d Binary files /dev/null and b/LoFi_Mockups.pdf differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..37e2de2 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# Cryptocurrency Trading Software + +We will create an automated cryptocurrency trading application that will be automatically buy and sell different cryptocurrencies on the Binace marketplace using the Binance API. We will incorperate many alogorithms to make trading more profitable and efficient. Some of the simple algorithms that we will incorperate into this software application will be stop losses (buy/sell when the cryptocurrency falls below a certain price), limit orders (buy/sell when it rises above a certain price). We will also be incorperating an arbitrage strategy which will essentially be finding the most profitable path between multiple exchanges in order to earn the most amount of money (hint graphs and dijkstras). Another feature of our software will be using NLP to analyze text data from investor relations hearings and/or expert reports in order to find valuable information on whether or not to buy or sell a given coin. (this will be using a similar ranking algorithm from autocorrect, we will also update the weight of each expert, hint, The expert problem) There are many other algorothms we hope to implement into our trading software that will make our algorithms more suited for dealing with the cryptocurrency market. + +Some of the data structures we will implement include directed graphs for arbitrage monitoring, maps for the NLP tasks and trees for the experts problem. + +We will primarily be using Java to build the application backend. To link it with the application frontend, we will be using javascript. On the frontend we will use bootstrap and react to create an exception, realtime application. The website will also include user functionality in which users are allowed to create accounts and update their profiles with information they deem important to the success of their trading profile. +# Discovery Engine +Another project that we can possibly create a discovery engine for tracking recent trends and areas of innovation. We would be able to track which areas are rife for opportunity using a compilation of google trends data and google searches and output to the user which areas have experienced high growth but have not yet reached a bigger audience. This could come into play into many applications. One example is for entrepreneurs looking to find which new ideas to work on in order to catch onto a growing trend that consumers want. This type of discovery engine could also be used for discovering new songs, etc. The algorithms in this idea would track the greatest rate of change in popularity of several general topics. The algorithm can also track how "deep" in a topic that this article is and use a variety of factors to determine the weight put on the page. For instance if the query is related to fashion chances are that the user would prefer to first see global and large fashion trends and as they query further are shown more niche topics. + +As with the previous project, Java will be used to build the backend, and Javascript, Node.js, react, bootstrap, to build the frontend. The GUI can also feature user functionality. +# Auto song mixing application +Another project idea is to create a music transition application that creates seamless transitions between any number of songs. The algorithm will use a deep learning GAN trained on a database of songs in order to expertly create transitions that match the pace, style and bpm of different songs. The application would have to use some sort of learning protocols in order to build on the data and the projects algorithms will deal with splicing the correct data of the songs and feeding them to the learning unit. This algorithm although subjective would have to have to deal with transfering audio files to reasonale data that our GAN can interpret. + +As with the previous project, Java will be used to build the backend, and Javascript, Node.js, react, bootstrap, to build the frontend. The GUI can also feature realtime mixing of uploaded songs so as to give the user a more interactive GUI. + +We were thinking of creating a web based GUI that allows users to view their transition matching take place in front of them. + +Our team comes from many different backgrounds. Two of our team members have experience working with machine learning and deep learning models and this will come in hand when we will incorperate NLP into our software. Three of our team members have experience working with web applications and this will be useful in creating an exception user interface and user experience. Finally we have a person on our team who has mutiple years of experience in the cryptocurrency market and understands the limitations of Binance and the Binance API. One of our weaknesses include incorperating all the various parts of the project that can be combined to convey information to the user on the frontend. We will be meeting up quite frequently in order to ensure that all componenets of the application match up as expected and all team members are on track. diff --git a/Term Project Specifications.pdf b/Term Project Specifications.pdf new file mode 100644 index 0000000..db9eb50 Binary files /dev/null and b/Term Project Specifications.pdf differ diff --git a/config/cs32_checks.xml b/config/cs32_checks.xml new file mode 100644 index 0000000..9dc4934 --- /dev/null +++ b/config/cs32_checks.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/db.sqlite3 b/data/db.sqlite3 new file mode 100644 index 0000000..14a6ae9 Binary files /dev/null and b/data/db.sqlite3 differ diff --git a/data/sqlite3.exe b/data/sqlite3.exe new file mode 100644 index 0000000..2eb15ab Binary files /dev/null and b/data/sqlite3.exe differ diff --git a/jars/binance-api-client-1.0.0.jar b/jars/binance-api-client-1.0.0.jar new file mode 100644 index 0000000..dc1f2a4 Binary files /dev/null and b/jars/binance-api-client-1.0.0.jar differ diff --git a/jars/retrofit-2.5.0.jar b/jars/retrofit-2.5.0.jar new file mode 100644 index 0000000..13dce3c Binary files /dev/null and b/jars/retrofit-2.5.0.jar differ diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..5cb1c17 --- /dev/null +++ b/pom.xml @@ -0,0 +1,245 @@ + + + 4.0.0 + edu.brown.cs + cs32-term-project + jar + 1.0 + + + UTF-8 + + + + + net.sf.jopt-simple + jopt-simple + 4.8 + + + + junit + junit + 4.12 + + + + org.hamcrest + hamcrest-all + 1.3 + + + + org.jetbrains + annotations + 16.0.2 + + + + com.binance.api + binance-api-client + 1.0.0 + system + ${project.basedir}/jars/binance-api-client-1.0.0.jar + + + + com.twilio.sdk + twilio + 7.37.2 + + + + + org.slf4j + slf4j-api + 1.7.22 + + + + com.squareup.retrofit2 + retrofit + 2.5.0 + + + + com.squareup.retrofit2 + converter-jackson + 2.5.0 + + + + org.apache.commons + commons-lang3 + 3.0 + + + + org.slf4j + slf4j-jdk14 + 1.7.22 + + + + commons-codec + commons-codec + 1.9 + + + + com.google.guava + guava + 21.0 + + + + com.google.code.gson + gson + 2.8.0 + + + + com.sparkjava + spark-core + [2.7.2,) + + + + com.sparkjava + spark-template-freemarker + 2.3 + + + + org.xerial + sqlite-jdbc + 3.16.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.8 + 1.8 + -Xlint:all + true + true + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + jacoco-initialize + initialize + + prepare-agent + + + + jacoco-site + verify + + report + + + + + + + + + + + + + maven-project-info-reports-plugin + 2.7 + + + false + + false + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.5 + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + + javadoc + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + config/cs32_checks.xml + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.6 + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.20.1 + + + org.jacoco + jacoco-maven-plugin + + + + + report + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.3 + + + + Max + + Low + + + + + diff --git a/run b/run new file mode 100755 index 0000000..2d8fdae --- /dev/null +++ b/run @@ -0,0 +1,49 @@ +#!/bin/sh + +# To run our code, we must have it in our classpath. +# We use $(ls target/*.jar) instead of target/stars-1.0.jar so that +# this script can be reused in other projects more easily. + +TARGET=$(ls target/*.jar 2>/dev/null) +if [ -z "$TARGET" ]; then + echo "No jar file in target/, try 'mvn package'". + exit 1 +fi + +# In the pom.xml, we've already explained other what libraries we +# depend on. Maven downloaded them, and put them "somewhere" (our +# repository). Now we ask maven to build up the CLASSPATH that let us +# run against those libraries. + +# First, we put the CLASSPATH in .classpath if the pom.xml is newer +# than out existing .classpath file. (We avoid this command if +# .classpath is fresh, since it's rather slow.) +if [ ! .mvn-classpath -nt pom.xml ]; then + mvn dependency:build-classpath -Dmdep.outputFile=.mvn-classpath -q +fi + +# Now, we set $CP to the contents of the .classpath file. +CP=$(cat .mvn-classpath) + +# We're trying to make the script more reusable by finding the package +# name, instead of hard coding. But this relies on some conventions +# in naming. You'll have to call your class "Main" and use our +# recommended package structure. + +# Find Main.java. It should be in a package below your username package. +MAIN=$(ls src/main/java/edu/brown/cs/*/*/Main.java) +[ -z "$MAIN" ] && echo "You need a Main.java" && exit 1 +[ ! -e "$MAIN" ] && echo "You can only have one Main.java" && exit 1 +STUDENT=$(basename $(dirname $(dirname $MAIN))) +MAINPKG=$(basename $(dirname $MAIN)) + +# No guarantees yet, but we're trying to support Windows, which uses a +# different Path Separator in classpaths. +PATHSEP=":" +if [ "$OSTYPE" = 'cygwin' -o "$OSTYPE" = 'msys' ]; then + PATHSEP=";" +fi + +# The symbol "$@" passes the command-line arguments from +# this script to your Java program. +java -ea -cp "$TARGET$PATHSEP$CP" edu.brown.cs.$STUDENT.$MAINPKG.Main "$@" diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..f2a15a0 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/main/.DS_Store b/src/main/.DS_Store new file mode 100644 index 0000000..e77e520 Binary files /dev/null and b/src/main/.DS_Store differ diff --git a/src/main/java/edu/brown/cs/term/connection/DatabaseConnection.java b/src/main/java/edu/brown/cs/term/connection/DatabaseConnection.java new file mode 100644 index 0000000..cf17a18 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/connection/DatabaseConnection.java @@ -0,0 +1,114 @@ +package edu.brown.cs.term.connection; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import edu.brown.cs.term.errorhandlers.SQLErrorHandler; + +/** + * This is the class for DatabaseConnection. It models a connection to + * a database which can created PreparedStatements and set new + * connections. + * + * @author Chrissy + */ +public abstract class DatabaseConnection { + + private static Connection conn = null; + + /** + * This method creates PreparedStatements from a passed in sql string. + * + * @param sql + * is the sql string that will be used to create + * PreparedStatements. + * @return the PreparedStatement created from the passed in sql + * String. + * @throws Exception + * throws the exception. + */ + public static PreparedStatement prepareStatement(String sql) + throws Exception { + if (connectionIsEstablished()) { + try { + return conn.prepareStatement(sql); + } catch (SQLException e) { + throw new DatabaseException( + SQLErrorHandler.getGenericErrorMessage(e)); + } + } else { + throw new DatabaseException( + "ERROR: no database is currently connected, please " + + "first load in a database"); + } + + } + + /** + * This method sets the connection for a DatabaseConnection. It first + * checks to make sure the passed in database file exists. Then it + * uses DriveManager to get a connection from the database. + * + * @param db + * is the String that is the path to the database that will + * be set to + */ + public static void setConnection(String db) { + conn = null; + File tmpFile = new File(db); + if (!tmpFile.exists() || tmpFile.isDirectory()) { + System.out + .println("ERROR: " + db + " SQL database file does not exist"); + return; + } + + try { + Class.forName("org.sqlite.JDBC"); + } catch (ClassNotFoundException e) { + System.out.println("ERROR: Something went wrong finding JDBC class"); + } + String urlToDB = "jdbc:sqlite:" + db; + try { + conn = DriverManager.getConnection(urlToDB); + } catch (SQLException e) { + System.out.println( + "ERROR: Something went wrong when trying to establish a connection"); + } + } + + /** + * This method determines whether or not the DatabaseConnection has + * been established or not. + * + * @return true if the DatabaseConnection was established and false + * otherwise. + */ + public static boolean connectionIsEstablished() { + try { + return conn != null && !conn.isClosed(); + } catch (SQLException e) { + System.out.println( + "ERROR: Something went wrong when trying to check if the connection " + + "is closed"); + return false; + } + } + + /** + * This method closes the Database Connection. + */ + public static void closeConnection() { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + System.out.println( + "ERROR: Something went wrong when closing the connection"); + } + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/connection/DatabaseException.java b/src/main/java/edu/brown/cs/term/connection/DatabaseException.java new file mode 100644 index 0000000..f48b115 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/connection/DatabaseException.java @@ -0,0 +1,28 @@ +package edu.brown.cs.term.connection; + +/** + * This is the DatabaseException class. It handles exceptions that occur when + * creating a prepared statements from the connection. + * @author Chrissy + * + */ +public class DatabaseException extends Exception { + + /** + * This is the constructor for a DatabaseException that takes in no + * parameters. + */ + public DatabaseException() { + super(); + } + + /** + * This is the constructor for a DatabaseConnection that will take in the + * error message for the exception. + * @param message + * is the informative error message that describes the exception. + */ + public DatabaseException(String message) { + super(message); + } +} diff --git a/src/main/java/edu/brown/cs/term/database/CrypthubUser.java b/src/main/java/edu/brown/cs/term/database/CrypthubUser.java new file mode 100644 index 0000000..2966f03 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/database/CrypthubUser.java @@ -0,0 +1,605 @@ +package edu.brown.cs.term.database; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.account.Account; +import com.binance.api.client.domain.account.AssetBalance; +import com.binance.api.client.exception.BinanceApiException; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.connection.DatabaseConnection; +import edu.brown.cs.term.errorhandlers.SQLErrorHandler; +import edu.brown.cs.term.general.Tuple; +import edu.brown.cs.term.trading.Symbols; + +public class CrypthubUser { + private Gson GSON; + private BinanceApiRestClient client; + private Set symbols = Symbols.getAllSymbols(); + + public CrypthubUser() { + GSON = new Gson(); + } + + /** + * Checks if a user exists in the database. + * + * @param username + * Username of the potential user. + * @return JSON Object that indicates if a user exists in the database + * as well as the username. + */ + public String checkUser(String username) { + String st = "SELECT USERNAME FROM USER WHERE USERNAME = ? LIMIT 1"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, username); + ResultSet rs = prep.executeQuery(); + Map exists; + if (rs.next()) { + exists = ImmutableMap.of("username", username, "exists", true, + "error", false); + } else { + exists = ImmutableMap.of("username", username, "exists", false, + "error", false); + } + rs.close(); + return GSON.toJson(exists); + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return GSON.toJson(ImmutableMap.of("username", username, "exists", + false, "error", true)); + } catch (Exception e1) { + System.out.println(e1.getMessage()); + return GSON.toJson(ImmutableMap.of("username", username, "exists", + false, "error", true)); + } + } + + /** + * Adds a user to the database + * + * @param username + * username of the user + * @param password + * password of the user + * @param firstName + * first name of the user + * @param lastName + * last name of the user + * @return JSON Object that indicates if the user has been added to + * the database + */ + public String addUser(String username, String password, String firstName, + String lastName) { + String st + = "INSERT INTO USER (FIRSTNAME, LASTNAME, USERNAME, PASSWORD) " + + "VALUES (?, ?, ?, ?)"; + try (PreparedStatement prep + = DatabaseConnection.prepareStatement(st);) { + prep.setString(1, firstName); + prep.setString(2, lastName); + prep.setString(3, username); + prep.setString(4, password); + prep.addBatch(); + prep.executeBatch(); + prep.close(); + return checkUser(username); + } catch (SQLException e) { + return checkUser(username); + } catch (Exception e1) { + return checkUser(username); + } + } + + /** + * Adds a user to the database (WITH PHONE NUMBER) + * + * @param username + * username of the user + * @param password + * password of the user + * @param firstName + * first name of the user + * @param lastName + * last name of the user + * @param number + * phone number of the user + * @return JSON Object that indicates if the user has been added to + * the database + */ + public String addUser(String username, String password, String firstName, + String lastName, String number) { + String st + = "INSERT INTO USER (FIRSTNAME, LASTNAME, USERNAME, PASSWORD, PHONE) " + + "VALUES (?, ?, ?, ?, ?)"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, firstName); + prep.setString(2, lastName); + prep.setString(3, username); + prep.setString(4, password); + prep.setString(5, number); + prep.addBatch(); + prep.executeBatch(); + prep.close(); + return checkUser(username); + } catch (SQLException e) { + return checkUser(username); + } catch (Exception e1) { + return checkUser(username); + } + } + + /** + * Logins a user. + * + * @param username + * username of the user + * @param password + * password of the user + * @return Json object representing if the login exists in the + * database + */ + public String login(String username, String password) { + String st + = "SELECT USERNAME, FIRSTNAME, LASTNAME FROM USER WHERE USERNAME = ? AND PASSWORD = ?"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, username); + prep.setString(2, password); + ResultSet rs = prep.executeQuery(); + if (rs.next()) { + return GSON.toJson(ImmutableMap.of("username", username, + "firstname", rs.getString(2), "lastname", rs.getString(3), + "login_found", true, "error", false)); + } + return GSON.toJson(ImmutableMap.of("username", username, "firstname", + "", "lastname", "", "login_found", false, "error", false)); + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return GSON.toJson(ImmutableMap.of("username", username, "firstname", + "", "lastname", "", "login_found", false, "error", true)); + + } catch (Exception e1) { + System.out.println(e1.getMessage()); + return GSON.toJson(ImmutableMap.of("username", username, "firstname", + "", "lastname", "", "login_found", false, "error", true)); + + } + } + + /** + * Adds a public and private key to the user. + * + * @param username + * username of the user + * @param publicKey + * public key of the user + * @return JSON Object indicating that the execution was successful + */ + public String addPublicKey(String username, String publicKey) { + String st = "UPDATE USER SET PUBLIC_KEY = ? WHERE USERNAME = ?"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, publicKey); + prep.setString(2, username); + prep.executeUpdate(); + return GSON + .toJson(ImmutableMap.of("username", username, "success", true)); + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return GSON + .toJson(ImmutableMap.of("username", username, "success", false)); + } catch (Exception e1) { + System.out.println(e1.getMessage()); + return GSON + .toJson(ImmutableMap.of("username", username, "success", false)); + } + } + + /** + * Adds a public and private key to the user. + * + * @param username + * username of the user + * @param privateKey + * private key of the user + * @return JSON Object indicating that the execution was successful + */ + public String addPrivateKey(String username, String privateKey) { + + String st = "UPDATE USER SET PRIVATE_KEY = ? WHERE USERNAME = ?"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, privateKey); + prep.setString(2, username); + prep.executeUpdate(); + return GSON.toJson(ImmutableMap.of("success", true)); + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return GSON.toJson(ImmutableMap.of("success", false)); + } catch (Exception e1) { + System.out.println(e1.getMessage()); + return GSON.toJson(ImmutableMap.of("success", false)); + } + } + + /** + * Adds a public and private key to the user. + * + * @param username + * username of the user + * @param publicKey + * public key of the user + * @param privateKey + * private key of the user + * @return JSON Object indicating that the execution was successful + */ + public String addPublicPrivateKey(String username, String publicKey, + String privateKey) { + + if (!this.verifyKeys(publicKey, privateKey)) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + + String st + = "UPDATE USER SET PUBLIC_KEY = ?, PRIVATE_KEY = ? WHERE USERNAME = ?"; + try { + PreparedStatement prep = DatabaseConnection.prepareStatement(st); + prep.setString(1, publicKey); + prep.setString(2, privateKey); + prep.setString(3, username); + prep.executeUpdate(); + prep.close(); + return GSON.toJson(ImmutableMap.of("success", true)); + } catch (SQLException e) { + return GSON.toJson(ImmutableMap.of("success", false)); + } catch (Exception e) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + } + + /** + * Verify the keys of the user. + * + * @param publicKey + * Public binance key of the user + * @param privateKey + * private binance key of the user + * @return true if keys are valid, false if not. + */ + public boolean verifyKeys(String publicKey, String privateKey) { + BinanceApiClientFactory fact + = BinanceApiClientFactory.newInstance(publicKey, privateKey); + BinanceApiRestClient client = fact.newRestClient(); + try { + Account acc = client.getAccount(); + return true; + } catch (BinanceApiException e) { + return false; + } + } + + /** + * Returns true if the keys are valid. + * + * @param publicKey + * Public key + * @param privateKey + * Private key + * @return true if the keys are valid + */ + public String keysValid(String publicKey, String privateKey) { + if (verifyKeys(publicKey, privateKey)) { + return GSON.toJson(ImmutableMap.of("valid", true)); + } else { + return GSON.toJson(ImmutableMap.of("valid", false)); + } + } + + /** + * Gets the public and private key based on a given username + * + * @param username + * username of the user + * @return Tuple representing both the public and private key + */ + public Tuple getPublicPrivateKey(String username) { + if (checkUser(username).contains("\"exists\":false")) { + return new Tuple<>("", ""); + } + + String st + = "SELECT PUBLIC_KEY, PRIVATE_KEY FROM USER WHERE USERNAME = ?"; + try { + PreparedStatement prep = DatabaseConnection.prepareStatement(st); + prep.setString(1, username); + ResultSet rs = prep.executeQuery(); + String publicKey = ""; + String privateKey = ""; + if (rs.next()) { + publicKey = rs.getString(1); + privateKey = rs.getString(2); + } + return new Tuple<>(publicKey, privateKey); + } catch (SQLException e) { + return new Tuple<>("", ""); + } catch (Exception e) { + return new Tuple<>("", ""); + } + } + + /** + * Keys exist and valid. + * + * @param username + * username of the user + * @return true if the keys exist in the database and are valid + * Binance Keys + */ + public String keysExistAndValid(String username) { + if (getPublicPrivateKey(username).equals(new Tuple<>("", ""))) { + return GSON.toJson( + ImmutableMap.of("keys_exist", false, "keys_valid", false)); + } else { + Tuple keys = getPublicPrivateKey(username); + if (verifyKeys(keys.getSecondEntry(), keys.getSecondEntry())) { + return GSON.toJson( + ImmutableMap.of("keys_exist", true, "keys_valid", true)); + } else { + return GSON.toJson( + ImmutableMap.of("keys_exist", true, "keys_valid", true)); + } + } + } + + /** + * Gets the wallet of the users and displays the entire wallet thats + * greater than 0. + * + * @param username + * of the user + * @return JSON containing all the balances of the user. + */ + public String wallet(String username) { + if (getPublicPrivateKey(username).equals(new Tuple<>("", ""))) { + ImmutableMap map + = ImmutableMap.of("keys_set", false); + return GSON.toJson(map); + } else { + Tuple tuple = getPublicPrivateKey(username); + String public_key = tuple.getFirstEntry(); + String private_key = tuple.getSecondEntry(); + // TODO: check if public/private key is valid + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(public_key, private_key); + client = factory.newRestClient(); + Account acc = client.getAccount(); + List assets = acc.getBalances(); + List possAssets = new ArrayList<>(); + List tradable = new ArrayList<>(); + double totalAmount = 0; + boolean totalAccurate = true; + for (AssetBalance asset : assets) { + if (Double.parseDouble(asset.getFree()) > 0.0001 + || Double.parseDouble(asset.getLocked()) > 0.0001) { + possAssets.add(asset); + if (symbols.contains(asset.getAsset() + "ETH") + || asset.getAsset().equals("ETH")) { + tradable.add(asset); + } + double value = valueOfAsset(asset); + if (totalAmount == 0) { + totalAccurate = false; + } + totalAmount += value; + } + } + return GSON.toJson(ImmutableMap.of("keys_set", true, "assets", + possAssets, "tradable", tradable, "total", totalAmount, + "accurateTotal", totalAccurate)); + } + } + + /** + * Gets the total amount of $ in a users wallet + * @param username + * username of a user + * @return $ amount returned as a double of all the assets in the + * account + */ + public double totalAmount(String username) { + List assets = assetsInWallet(username); + if (assets.size() == 0) { + return 0; + } + double totalAmount = 0; + for (AssetBalance asset : assets) { + totalAmount = totalAmount + valueOfAsset(asset); + } + return totalAmount; + } + + /** + * Inserts amount of money into a db. + * @param username + * username of the user + * @param value + * amount of money that the user has in their account + * @return String representing success + */ + public String insertAmounts(String username, double value) { + String time = new Timestamp(System.currentTimeMillis()).toString(); + String st + = "INSERT INTO VALUE (USERNAME, TIME, AMOUNT) VALUES (?, ?, ?);"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, username); + prep.setString(2, time); + prep.setDouble(3, value); + prep.addBatch(); + prep.executeBatch(); + return GSON.toJson(ImmutableMap.of("success", true)); + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return GSON.toJson(ImmutableMap.of("success", false)); + } catch (Exception f) { + System.out.println(f.getMessage()); + return GSON.toJson(ImmutableMap.of("success", false)); + } + } + + private double valueOfAsset(AssetBalance asset) { + if (asset.getAsset().equals("USDT")) { + return Double.parseDouble(asset.getFree()) + + Double.parseDouble(asset.getLocked()); + } else { + try { + String symbol = asset.getAsset() + "USDT"; + return (Double.parseDouble(asset.getFree()) + + Double.parseDouble(asset.getLocked())) + * Double.parseDouble(client.getPrice(symbol).getPrice()); + } catch (BinanceApiException e) { + try { + String symbol = asset.getAsset() + "ETH"; + return (Double.parseDouble(asset.getFree()) + + Double.parseDouble(asset.getLocked())) + * Double.parseDouble(client.getPrice(symbol).getPrice()) + * Double.parseDouble(client.getPrice("ETHUSDT").getPrice()); + } catch (BinanceApiException f) { + return 0; + } + } + } + } + + /** + * Gets all the symbols in the wallet. + * @param username + * username of the user + * @return all the symbols that correspond to the users database + */ + public Set symbolsInWallet(String username) { + Set possAssets = new HashSet<>(); + if (getPublicPrivateKey(username).equals(new Tuple<>("", ""))) { + return possAssets; + } else { + Tuple tuple = getPublicPrivateKey(username); + String public_key = tuple.getFirstEntry(); + String private_key = tuple.getSecondEntry(); + // TODO: check if public/private key is valid + + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(public_key, private_key); + BinanceApiRestClient client = factory.newRestClient(); + Account acc = client.getAccount(); + + List assets = acc.getBalances(); + possAssets = new HashSet<>(); + for (AssetBalance asset : assets) { + if (Double.parseDouble(asset.getFree()) > 0.000001 + || Double.parseDouble(asset.getLocked()) > 0.000001) { + String coin = asset.getAsset(); + + if (coin.equals("BTC")) { + possAssets.add("BTCUSDT"); + } else if (coin.equals("ETH")) { + possAssets.add("ETHUSDT"); + } else if (coin.equals("USDT")) { + continue; + } else { + possAssets.add(coin + "ETH"); + } + } + } + return possAssets; + } + } + + /** + * gets all the assets in a users wallet and returns a list + * @param username + * username of the user + * @return all the assets in a users wallet + */ + public List assetsInWallet(String username) { + if (getPublicPrivateKey(username).equals(new Tuple<>("", ""))) { + return new ArrayList<>(); + } else { + Tuple tuple = getPublicPrivateKey(username); + String public_key = tuple.getFirstEntry(); + String private_key = tuple.getSecondEntry(); + + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(public_key, private_key); + client = factory.newRestClient(); + Account acc = client.getAccount(); + + List assets = acc.getBalances(); + List possAssets = new ArrayList<>(); + for (AssetBalance asset : assets) { + if (Double.parseDouble(asset.getFree()) > 0.000001 + || Double.parseDouble(asset.getLocked()) > 0.000001) { + possAssets.add(asset); + } + } + return possAssets; + } + } + + /** + * Gets the historical wallet amount over time of the user + * @param username + * username of the user + * @param numOfDataPoints + * number of entries you want to receive + * @return String representing the the wallet value over time + */ + public String historicalWalletValue(String username, + int numOfDataPoints) { + String st + = "SELECT * FROM VALUE WHERE USERNAME = ? ORDER BY TIME DESC LIMIT ?;"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, username); + prep.setInt(2, numOfDataPoints); + ResultSet rs = prep.executeQuery(); + List amounts = new ArrayList<>(); + while (rs.next()) { + amounts.add(new Amount(rs.getString(2), rs.getDouble(3))); + } + rs.close(); + return GSON.toJson(ImmutableMap.of("success", true, "username", + username, "amounts", amounts)); + } catch (Exception e) { + System.out.println(e.getMessage()); + return GSON.toJson(ImmutableMap.of("success", false)); + } + } + + /** + * Class for getting the amount from a user. + */ + private class Amount { + private String time; + private double value; + + public Amount(String t, double v) { + this.time = t; + this.value = v; + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/database/ReadDatabase.java b/src/main/java/edu/brown/cs/term/database/ReadDatabase.java new file mode 100644 index 0000000..5ac057f --- /dev/null +++ b/src/main/java/edu/brown/cs/term/database/ReadDatabase.java @@ -0,0 +1,68 @@ +package edu.brown.cs.term.database; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + +import edu.brown.cs.term.errorhandlers.SQLErrorHandler; + +/** + * Reads the database and returns the connection from a given + * filepath. + */ +public final class ReadDatabase { + + private ReadDatabase() { + } + + /** + * Sets up a connection with the database. + * + * @param filepath + * filpath to the database file + * @return Connection if it is found, null if it is not found. + */ + public static Connection setupConnection(String filepath) { + if (!isValidDb(filepath)) { + System.out.println("ERROR: database is not valid"); + return null; + } + try { + Class.forName("org.sqlite.JDBC"); + } catch (ClassNotFoundException e) { + System.out.println("ERROR: JDBC class not found"); + return null; + } + String urlToDB = "jdbc:sqlite:" + filepath; + try { + Connection conn = DriverManager.getConnection(urlToDB); + Statement stat = conn.createStatement(); + stat.executeUpdate("PRAGMA foreign_keys = ON;"); + return conn; + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return null; + } + } + + /** + * Returns true if the filepath is a valid filepath to a database. + * False if it is not. + * + * @param filepath + * possible filepath to the database. + * @return true if the filepath points to a valid db file. + */ + public static boolean isValidDb(String filepath) { + File f = new File(filepath); + final String extension = ".sqlite3"; + if (!f.exists() || filepath.length() <= extension.length() + || filepath.substring(filepath.length() - extension.length() - 1) + .equals(extension)) { + return false; + } + return true; + } +} diff --git a/src/main/java/edu/brown/cs/term/database/Trades.java b/src/main/java/edu/brown/cs/term/database/Trades.java new file mode 100644 index 0000000..2587de4 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/database/Trades.java @@ -0,0 +1,228 @@ +package edu.brown.cs.term.database; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.binance.api.client.domain.account.Order; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.connection.DatabaseConnection; +import edu.brown.cs.term.errorhandlers.SQLErrorHandler; +import websockets.RsiWebSocket; + +public class Trades { + private static Gson GSON; + + public Trades() { + GSON = new Gson(); + } + + /** + * Adds a trade to the database. + * @param username + * username of user + * @param ord + * order + * @return GSON representing whether adding the username was a success + */ + public int addTrade(String username, Order ord) { + float price = Float.parseFloat(ord.getPrice()); + StringBuilder sb = new StringBuilder(); + sb.append(ord.getType()); + sb.append(" "); + sb.append(ord.getSide()); + String type = sb.toString(); + float quantity = Float.parseFloat(ord.getOrigQty()); + String symbol = ord.getSymbol(); + String status = ord.getStatus().toString(); + int orderId = new Long(ord.getOrderId()).intValue(); + + String time = new Timestamp(System.currentTimeMillis()).toString(); + String st + = "INSERT INTO TRADES (PRICE, TYPE, QUANTITY, SYMBOL, ORDER_TIME, ORDER_ID, USERNAME, STATUS) " + + "VALUES(?, ?, ?, ?, ?, ?, ?, ?);"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setFloat(1, price); + prep.setString(2, type); + prep.setFloat(3, quantity); + prep.setString(4, symbol); + prep.setString(5, time); + prep.setInt(6, orderId); + prep.setString(7, username); + prep.setString(8, status); + prep.addBatch(); + prep.executeBatch(); + + RsiWebSocket.sendCustomTradingUpdateMessage(username, ord.getOrderId(), + "Welcome to your new trade"); + + return orderId; + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return 0; // TODO throw an exception. + } catch (Exception e) { + return 0; + } + } + + public String getTrade(String username, Order order) { + String st = "SELECT * FROM TRADES WHERE USERNAME = ? AND ORDER_ID = ?"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, username); + prep.setLong(2, new Long(order.getOrderId()).intValue()); + ResultSet rs = prep.executeQuery(); + + if (rs.next()) { + Map trade + = buildJSONTrade(rs.getFloat(1), rs.getString(2), + rs.getFloat(3), rs.getString(4), rs.getString(5), + rs.getInt(6), rs.getString(7), rs.getString(8), true); + return GSON.toJson(trade); + } + Map trade = buildJSONTrade(0, "", 0, "", + new Timestamp(System.currentTimeMillis()).toString(), 0, + username, "", false); + rs.close(); + return GSON.toJson(trade); + } catch (SQLException e) { + Map trade = buildJSONTrade(0, "", 0, "", + new Timestamp(System.currentTimeMillis()).toString(), 0, + username, "", false); + return GSON.toJson(trade); + } catch (Exception e) { + Map trade = buildJSONTrade(0, "", 0, "", + new Timestamp(System.currentTimeMillis()).toString(), 0, + username, "", false); + return GSON.toJson(trade); + } + } + + private Map buildJSONTrade(float price, String type, + float quantity, String symbol, String time, int order_id, + String username, String status, boolean success) { + Map map = new ImmutableMap.Builder() + .put("price", price).put("type", type).put("quantity", quantity) + .put("symbol", symbol).put("time", time).put("order_id", order_id) + .put("username", username).put("status", status) + .put("success", success).build(); + return map; + } + + /** + * Gets all the trades from the user + * @param username + * username of the user + * @return JSON representing all the trades + */ + public List> getAllTrades(String username) { + String st + = "SELECT PRICE, TYPE, QUANTITY, SYMBOL, ORDER_TIME, ORDER_ID, USERNAME, STATUS FROM TRADES WHERE USERNAME = ? ORDER BY ORDER_TIME DESC"; + List> trades = new ArrayList<>(); + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, username); + ResultSet rs = prep.executeQuery(); + while (rs.next()) { + + Map trade + = buildJSONTrade(rs.getFloat(1), rs.getString(2), + rs.getFloat(3), rs.getString(4), rs.getString(5), + rs.getInt(6), rs.getString(7), rs.getString(8), true); + trades.add(trade); + } + rs.close(); + return trades; + } catch (SQLException e) { + System.out.println(SQLErrorHandler.getGenericErrorMessage(e)); + return trades; + } catch (Exception e1) { + System.out.println(e1.getMessage()); + return trades; + } + } + + /** + * Modifies the trade status of an order for a user. + * @param username + * username of the user + * @param order + * order of the user + * @return JSON String representing success and failure + */ + public String updateTrade(String username, Order ord, String message) { + float price = Float.parseFloat(ord.getPrice()); + StringBuilder sb = new StringBuilder(); + sb.append(ord.getType()); + sb.append(" "); + sb.append(ord.getSide()); + String type = sb.toString(); + float quantity = Float.parseFloat(ord.getOrigQty()); + String symbol = ord.getSymbol(); + String status = ord.getStatus().toString(); + int orderId = new Long(ord.getOrderId()).intValue(); + + String time = new Timestamp(System.currentTimeMillis()).toString(); + + String st + = "UPDATE TRADES SET PRICE = ?, SET TYPE = ?, SET QUANTITY = ?, SET SYMBOL = ?, SET ORDER_TIME = ?, SET STATUS = ? WHERE USERNAME = ? AND ORDER_ID = ?"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setFloat(1, price); + prep.setString(2, type); + prep.setFloat(3, quantity); + prep.setString(4, symbol); + prep.setString(5, time); + prep.setString(6, status); + prep.setString(7, username); + prep.setInt(8, orderId); + prep.executeUpdate(); + + Map trade = this.buildJSONTrade(price, type, + quantity, symbol, time, orderId, username, status, true); + + RsiWebSocket.sendCustomTradingUpdateMessage(username, ord.getOrderId(), + message); + + return GSON.toJson(ImmutableMap.of("success", true)); + } catch (SQLException e) { + return GSON.toJson(ImmutableMap.of("success", false)); + } catch (Exception e) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + } + + /** + * Modifies the trade status of an order for a user. + * @param username + * username of the user + * @param order + * order of the user + * @return JSON String representing success and failure + */ + public String modifyTradeStatus(String username, int orderId, + String status) { + String st + = "UPDATE TRADES SET STATUS = ? WHERE USERNAME = ? AND ORDER_ID = ?"; + try ( + PreparedStatement prep = DatabaseConnection.prepareStatement(st)) { + prep.setString(1, status); + prep.setString(2, username); + prep.setInt(3, orderId); + prep.executeUpdate(); + return GSON.toJson(ImmutableMap.of("success", true)); + } catch (SQLException e) { + return GSON.toJson(ImmutableMap.of("success", false)); + } catch (Exception e) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/errorhandlers/SQLErrorHandler.java b/src/main/java/edu/brown/cs/term/errorhandlers/SQLErrorHandler.java new file mode 100644 index 0000000..58d0da7 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/errorhandlers/SQLErrorHandler.java @@ -0,0 +1,24 @@ +package edu.brown.cs.term.errorhandlers; + +import java.sql.SQLException; + +/** + * This class is used by all the classes the query the database, ActorTable, + * FilmTable, DatabaseConnection, etc. to produce a generic SQL error message + * from the passed in SQLException e. + * @author Chrissy + * + */ +public abstract class SQLErrorHandler { + + /** + * This method takes in a SQLException and returns a generic error message. + * @param e + * is the SQLException this method is getting an error message for. + * @return a String that is the generic SQL error message. + */ + public static String getGenericErrorMessage(SQLException e) { + String errorMessage = e.getMessage().replace("[SQLITE_ERROR] ", ""); + return "ERROR: " + errorMessage; + } +} diff --git a/src/main/java/edu/brown/cs/term/general/Tuple.java b/src/main/java/edu/brown/cs/term/general/Tuple.java new file mode 100644 index 0000000..fafb240 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/general/Tuple.java @@ -0,0 +1,66 @@ +package edu.brown.cs.term.general; + +import java.util.Objects; + +/** + * Holds 2 values of type T and E. + * + * @param first entry of the tuple of type T + * @param second entry of the tuple of type E + */ +public class Tuple { + private T firstEntry; + private E secondEntry; + + /** + * Constructor for Tuple. + * + * @param first first entry to be held in the tuple. + * @param second seocnd entry to be held in the tuple. + */ + public Tuple(T first, E second) { + firstEntry = first; + secondEntry = second; + } + + /** + * Gets the first entry of the Tuple. + * + * @return first entry of type T. + */ + public T getFirstEntry() { + return firstEntry; + } + + /** + * Gets the second entry of the Tuple. + * + * @return second entry of type E. + */ + public E getSecondEntry() { + return secondEntry; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple tuple = (Tuple) o; + return Objects.equals(firstEntry, tuple.firstEntry) + && Objects.equals(secondEntry, tuple.secondEntry); + } + + @Override + public int hashCode() { + return Objects.hash(firstEntry, secondEntry); + } + + @Override + public String toString() { + return "(" + firstEntry + "," +secondEntry + ")"; + } +} diff --git a/src/main/java/edu/brown/cs/term/gui/TermSparkHandlers.java b/src/main/java/edu/brown/cs/term/gui/TermSparkHandlers.java new file mode 100644 index 0000000..d167b8d --- /dev/null +++ b/src/main/java/edu/brown/cs/term/gui/TermSparkHandlers.java @@ -0,0 +1,174 @@ +package edu.brown.cs.term.gui; + +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import spark.ModelAndView; +import spark.Request; +import spark.Response; +import spark.TemplateViewRoute; + +/** + * This class holds all the SparkHandlers for the GUI. + * + * @author Chrissy + * + */ +public class TermSparkHandlers { + private static final Gson GSON = new Gson(); + + /** + * Handles requests to the front page of the website. + * + * @author Chrissy + * + */ + public static class CryptoFrontHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "index.ftl"); + } + } + + /** + * Handles request to the about page of the website. + * @author AT1924 + */ + public static class AboutHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "about.ftl"); + } + } + + /** + * Handles request to the contact page of the website. + * @author AT1924 + */ + public static class ContactHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "contactUs.ftl"); + } + } + + /** + * Handles request to the contact page of the website. + * @author AT1924 + */ + public static class TradesHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "trades.ftl"); + } + } + + /** + * Handles request to the news page of the website. + * @author AT1924 + */ + public static class NewsHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "news.ftl"); + } + } + + /** + * Handles request for the signup page of the website. + * @author Chrissy + */ + public static class SignUpHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "signup.ftl"); + } + } + + // /** + // * Handles request for the signup page of the website. + // * @author Chrissy + // */ + // public static class SignUpPostHandler implements Route { + // @Override + // public Object handle(Request req, Response res) { + // QueryParamsMap qm = req.queryMap(); + // String error = qm.value("error"); + // System.out.println("HERE" + error); + // //String error = "error"; + // //Map variables = ImmutableMap.of(); + // return GSON.toJson(error); + // } + // } + + /** + * Handles request for the login page of the website. + * @author Chrissy + */ + public static class SignUpPostHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + String error = req.params("error"); + System.out.println("im in the post handler"); + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "signup.ftl"); + } + } + + /** + * Handles request for the login page of the website. + * @author Chrissy + */ + public static class LogInHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "login.ftl"); + } + } + + /** + * Handles request to the profile page of the website. + * @author AT1924 + */ + public static class ProfileHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "profile.ftl"); + } + } + + /** + * Handles request to the strategy page of the website. + * @author AT1924 + */ + public static class StrategyHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "strategy.ftl"); + } + } + + /** + * Handles request to the strategy page of the website. + * @author AT1924 + */ + public static class StrategyFormHandler implements TemplateViewRoute { + @Override + public ModelAndView handle(Request req, Response res) { + Map variables = ImmutableMap.of(); + return new ModelAndView(variables, "strategy-after.ftl"); + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/gui/TradingHandler.java b/src/main/java/edu/brown/cs/term/gui/TradingHandler.java new file mode 100644 index 0000000..ebe11c7 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/gui/TradingHandler.java @@ -0,0 +1,125 @@ +package edu.brown.cs.term.gui; + +import java.util.HashSet; +import java.util.Set; + +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.TimeInForce; +import com.binance.api.client.domain.account.NewOrder; +import com.binance.api.client.exception.BinanceApiException; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.general.Tuple; +import edu.brown.cs.term.thread.BuyThread; +import edu.brown.cs.term.thread.SellThread; +import edu.brown.cs.term.thread.TradingAlgorithmThread; +import spark.QueryParamsMap; +import spark.Request; +import spark.Response; +import spark.Route; + +public class TradingHandler { + private static final Gson GSON = new Gson(); + + public static class FullTradeSellHandler implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String symbol = qm.value("symbol"); + String username = qm.value("username"); + String sellPrice = qm.value("sell_price"); + String buyPrice = qm.value("buy_price"); + String stopPrice = qm.value("stop_price"); + String quantity = qm.value("quantity"); + + StringBuilder builder = new StringBuilder(); + builder.append(username); + builder.append(" "); + builder.append(symbol); + builder.append(" SELL"); + + SellThread st = new SellThread(username, builder.toString(), symbol, + sellPrice, buyPrice, stopPrice, quantity); + return GSON.toJson(ImmutableMap.of("success", true)); + } + } + + public static class FullTradeBuyHandler implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String symbol = qm.value("symbol"); + String username = qm.value("username"); + String sellPrice = qm.value("sell_price"); + String buyPrice = qm.value("buy_price"); + String stopPrice = qm.value("stop_price"); + String quantity = qm.value("quantity"); + + StringBuilder builder = new StringBuilder(); + builder.append(username); + builder.append(" "); + builder.append(symbol); + builder.append(" BUY"); + BuyThread bt = new BuyThread(username, builder.toString(), symbol, + buyPrice, sellPrice, stopPrice, quantity); + return GSON.toJson(ImmutableMap.of("success", true)); + } + } + + public static class ValidOrders implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String symbol = qm.value("symbol"); + String sellPrice = qm.value("sell_price"); + String buyPrice = qm.value("buy_price"); + String quantity = qm.value("quantity"); + String username = qm.value("username"); + CrypthubUser user = new CrypthubUser(); + // TODO: make sure public private keys are valid + Tuple keys = user.getPublicPrivateKey(username); + String publicKey = keys.getFirstEntry(); + String privateKey = keys.getSecondEntry(); + BinanceApiClientFactory fact + = BinanceApiClientFactory.newInstance(publicKey, privateKey); + BinanceApiRestClient client = fact.newRestClient(); + + try { + client.newOrderTest(NewOrder.limitSell(symbol, TimeInForce.GTC, + quantity, sellPrice)); + client.newOrderTest(NewOrder.limitBuy(symbol, TimeInForce.GTC, + quantity, buyPrice)); + return GSON.toJson(ImmutableMap.of("success", true)); + } catch (BinanceApiException e) { + return GSON.toJson( + ImmutableMap.of("success", false, "error", e.toString())); + } + } + } + + public static class AlgorithmicTrader implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + System.out.println(username); + String upper_limit = qm.value("upper_limit"); + String lower_limit = qm.value("lower_limit"); + String multiplier = qm.value("multiplier"); + String fraction = qm.value("fraction"); + String[] coins = qm.value("coins").split(" "); + Set coins_set = new HashSet<>(); + for (String coin : coins) { + coins_set.add(coin.trim()); + } + System.out.println(coins_set); + TradingAlgorithmThread td + = new TradingAlgorithmThread(username, "sample_thread", + coins_set, upper_limit, lower_limit, multiplier, fraction); + return GSON.toJson(ImmutableMap.of("success", true)); + } + } +} diff --git a/src/main/java/edu/brown/cs/term/gui/UserHandler.java b/src/main/java/edu/brown/cs/term/gui/UserHandler.java new file mode 100644 index 0000000..6543321 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/gui/UserHandler.java @@ -0,0 +1,159 @@ +package edu.brown.cs.term.gui; + +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.database.Trades; +import edu.brown.cs.term.repl.Main; +import edu.brown.cs.term.thread.PopulateValuesDBThread; +import edu.brown.cs.term.thread.WalletThread; +import spark.QueryParamsMap; +import spark.Request; +import spark.Response; +import spark.Route; + +public class UserHandler { + + public static class CheckUser implements Route { + @Override + public Object handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + CrypthubUser user = new CrypthubUser(); + return user.checkUser(username); + } + } + + public static class AddUser implements Route { + @Override + public Object handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + String password = qm.value("password"); + String firstName = qm.value("firstName"); + String lastName = qm.value("lastName"); + String number = qm.value("number"); + CrypthubUser user = new CrypthubUser(); + return user.addUser(username, password, firstName, lastName, number); + } + } + + public static class VerifyLogin implements Route { + @Override + public Object handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + String password = qm.value("password"); + CrypthubUser user = new CrypthubUser(); + return user.login(username, password); + } + } + + public static class UpdatePublicPrivateKeys implements Route { + @Override + public Object handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + String public_key = qm.value("publicKey"); + String private_key = qm.value("privateKey"); + CrypthubUser user = new CrypthubUser(); + return user.addPublicPrivateKey(username, public_key, private_key); + } + } + + public static class UpdateKeys implements Route { + @Override + public Object handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + String publicKey = qm.value("publicKey"); + String privateKey = qm.value("privateKey"); + CrypthubUser user = new CrypthubUser(); + return user.addPublicPrivateKey(username, publicKey, privateKey); + } + } + + /** + * This handles the post request for converting street names to + * coordinates. + * + * @author Chrissy + */ + public static class GetUsersTrades implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + Trades trade = new Trades(); + List> userTrades = trade.getAllTrades(username); + + Map variables + = ImmutableMap.of("trades", userTrades); + return Main.GSON.toJson(variables); + } + } + + /** + * Gets the wallet information of a particular user. + */ + public static class GetWalletInformation implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + CrypthubUser user = new CrypthubUser(); + return user.wallet(username); + } + } + + /** + * Checks if the keys are valid and exists in the database. + */ + public static class CheckKeysAndInDB implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + CrypthubUser user = new CrypthubUser(); + return user.keysExistAndValid(username); + } + } + + public static class CheckKeys implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String public_key = qm.value("public_key"); + String private_key = qm.value("private_key"); + CrypthubUser user = new CrypthubUser(); + return user.keysValid(public_key, private_key); + } + } + + public static class startWalletUpdates implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + WalletThread t = new WalletThread(username); + return Main.GSON.toJson(ImmutableMap.of("success", true)); + } + } + + public static class getGraphInfo implements Route { + @Override + public String handle(Request req, Response res) { + QueryParamsMap qm = req.queryMap(); + String username = qm.value("username"); + CrypthubUser user = new CrypthubUser(); + if(!Main.threadMap.contains(username + " populator")){ + PopulateValuesDBThread thread = new + PopulateValuesDBThread(username); + } + return user.historicalWalletValue(username, 20); + } + } +} diff --git a/src/main/java/edu/brown/cs/term/parsing/FormatChecker.java b/src/main/java/edu/brown/cs/term/parsing/FormatChecker.java new file mode 100644 index 0000000..475a3a3 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/parsing/FormatChecker.java @@ -0,0 +1,52 @@ +package edu.brown.cs.term.parsing; + +/** + * This abstract class holds methods that check strings for the correct format. + * + * @author Chrissy + * + */ +public abstract class FormatChecker { + + /** + * This method checks to see if a given String contains only digits and + * decimals, and also accepts Strings that have the negative sign. + * + * @param input + * is the String that the function checks if it only contains digits + * and decimals and possibly a negative sign. + * + * @return this method returns true if input contains only digits and + * decimals, and false otherwise. + */ + public static boolean stringIsANumber(String input) { + return input.matches("-?\\d+(\\.\\d+)?"); + } + + /** + * This method checks to see if a given String is a non-negative integer, + * meaning it only contains digits from 0 to 9. + * + * @param input + * is the String that will be checked to be an non-negative integer. + * @return this method returns true if input is a non-negative integer, and + * false otherwise. + */ + public static boolean stringIsNonNegativeInteger(String input) { + return input.matches("[0-9]+"); + } + + /** + * This method checks if a given input String is a non-negative number, + * meaning it can contain decimals and digits, but not a negative sign or any + * other characters. + * + * @param input + * is the String that will be checked to be an non-negative number. + * @return this method will return true if the input is a non-negative number + * and false otherwise. + */ + public static boolean stringIsNonNegativeNumber(String input) { + return input.matches("\\d*\\.?\\d+"); + } +} diff --git a/src/main/java/edu/brown/cs/term/parsing/GenericFileParser.java b/src/main/java/edu/brown/cs/term/parsing/GenericFileParser.java new file mode 100644 index 0000000..0f896f8 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/parsing/GenericFileParser.java @@ -0,0 +1,99 @@ +package edu.brown.cs.term.parsing; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; + +/** + * GenericFileParser checks to see if a given CSV file is of the correct format, + * meaning it has the correct header, and it parses a given CSV file into an + * arary of String, where each line in the CSV is stored as a String. + * + * @author Chrissy + * + */ +public class GenericFileParser { + + private String correctHeader; + + /** + * Constructor of GenericFileParser. This is used for files that are CSV files + * + * @param correctHeader + * is the header that the CSV should have + */ + public GenericFileParser(String correctHeader) { + this.correctHeader = correctHeader; + } + + /** + * This is the overloaded constructor for the GenericFileParser. This is used + * for files that doesn't need to have a correct header (ie is not a CSV + * file). + */ + public GenericFileParser() { + this.correctHeader = null; + } + + /** + * This method checks to see if he inputted header file, is the correct header + * for this given instance of GenericFileParser. + * + * @param headert + * is what is passed in and compared to the known correctHeader. + * @return this returns a boolean stating whether or not the passed in header + * (the one of a given CSV file) matches what we have determined to be + * a correct header. + */ + private boolean headerIsCorrect(String header) { + return correctHeader.equals(header); + } + + /** + * This method parses all the lines of a file into an array of String. Also, + * it first checks if a given file can be found and whether or not the file + * has the correct header. + * + * @param filename + * is the path to the CSV file that we are going to read from. + * @return this returns an ArrayList of type string, where each string is a + * line of the CSV. + */ + public ArrayList parseLinesToStringArray(String filename) { + ArrayList linesOfCSV = new ArrayList(); + String currLine = ""; + try (BufferedReader bufferedReader = new BufferedReader( + new FileReader(filename))) { + + /* + * First check if the header of the CSV file is correct or not, before + * parsing the other lines. + */ + currLine = bufferedReader.readLine(); + if (correctHeader != null && !this.headerIsCorrect(currLine)) { + System.out.println("ERROR: " + filename + + " misformatted, the header should read: " + correctHeader); + return null; + } else { + if (correctHeader == null) { + linesOfCSV.add(currLine); + } + while ((currLine = bufferedReader.readLine()) != null) { + linesOfCSV.add(currLine); + } + } + } catch (FileNotFoundException e) { + System.out.println("ERROR: could not find " + filename); + return null; + } catch (IOException e) { + System.out + .println("ERROR: something went wrong while reading " + filename); + return null; + } + + return linesOfCSV; + } + +} diff --git a/src/main/java/edu/brown/cs/term/repl/Main.java b/src/main/java/edu/brown/cs/term/repl/Main.java new file mode 100644 index 0000000..791b66c --- /dev/null +++ b/src/main/java/edu/brown/cs/term/repl/Main.java @@ -0,0 +1,193 @@ +package edu.brown.cs.term.repl; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.util.HashSet; + +import com.google.gson.Gson; + +import edu.brown.cs.term.connection.DatabaseConnection; +import edu.brown.cs.term.gui.TermSparkHandlers; +import edu.brown.cs.term.gui.TermSparkHandlers.CryptoFrontHandler; +import edu.brown.cs.term.gui.TermSparkHandlers.TradesHandler; +import edu.brown.cs.term.gui.TradingHandler; +import edu.brown.cs.term.gui.UserHandler; +import freemarker.template.Configuration; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import spark.ExceptionHandler; +import spark.Request; +import spark.Response; +import spark.Spark; +import spark.template.freemarker.FreeMarkerEngine; +import websockets.RsiWebSocket; + +/** + * The Main class of our project. This is where execution begins. + * + * @author jj + */ +public final class Main { + + private static final int DEFAULT_PORT = 4567; + public static final Gson GSON = new Gson(); + public static HashSet threadMap = new HashSet<>(); + + /** + * The initial method called when execution begins. + * + * @param args + * An array of command line arguments + */ + public static void main(String[] args) { + new Main(args).run(); + } + + private String[] args; + + private Main(String[] args) { + this.args = args; + } + + private void run() { + // Parse command line arguments + OptionParser parser = new OptionParser(); + parser.accepts("gui"); + parser.accepts("port").withRequiredArg().ofType(Integer.class) + .defaultsTo(DEFAULT_PORT); + OptionSet options = parser.parse(args); + + if (options.has("gui")) { + runSparkServer((int) options.valueOf("port")); + } + + DatabaseConnection.setConnection("data/db.sqlite3"); + } + + private static FreeMarkerEngine createEngine() { + Configuration config = new Configuration(); + File templates + = new File("src/main/resources/spark/template/freemarker"); + try { + config.setDirectoryForTemplateLoading(templates); + } catch (IOException ioe) { + System.out.printf("ERROR: Unable use %s for template loading.%n", + templates); + System.exit(1); + } + return new FreeMarkerEngine(config); + } + + @SuppressWarnings("unchecked") + private void runSparkServer(int port) { + Spark.port(port); + Spark.externalStaticFileLocation("src/main/resources/static"); + Spark.exception(Exception.class, new ExceptionPrinter()); + + FreeMarkerEngine freeMarker = createEngine(); + + // Setup Spark Routes + this.setUpSparkRoutes(freeMarker); + } + + private void setUpSparkRoutes(FreeMarkerEngine freeMarker) { + Spark.webSocket("/rsi", RsiWebSocket.class); + // Spark.webSocket("/walletSocket", WalletSocket.class); + Spark.get("/home", new CryptoFrontHandler(), freeMarker); + Spark.get("/about", new TermSparkHandlers.AboutHandler(), freeMarker); + Spark.get("/contact", new TermSparkHandlers.ContactHandler(), + freeMarker); + Spark.get("/news", new TermSparkHandlers.NewsHandler(), freeMarker); + Spark.get("/profile", new TermSparkHandlers.ProfileHandler(), + freeMarker); + Spark.get("/trades", new TradesHandler(), freeMarker); + Spark.get("/strategy", new TermSparkHandlers.StrategyHandler(), + freeMarker); + Spark.get("/strategyForm", new TermSparkHandlers.StrategyFormHandler(), + freeMarker); + Spark.get("/signup", new TermSparkHandlers.SignUpHandler(), + freeMarker); + Spark.post("/signUpUser", new UserHandler.AddUser()); + Spark.get("/login", new TermSparkHandlers.LogInHandler(), freeMarker); + Spark.post("/checkUser", new UserHandler.CheckUser()); + Spark.post("/verifyLogin", new UserHandler.VerifyLogin()); + Spark.post("/getUserTrades", new UserHandler.GetUsersTrades()); + Spark.post("/getWallet", new UserHandler.GetWalletInformation()); + + Spark.post("/updateKeys", new UserHandler.UpdatePublicPrivateKeys()); + Spark.post("/checkKeyValidity", new UserHandler.CheckKeys()); + Spark.post("/validKeysInDb", new UserHandler.CheckKeysAndInDB()); + Spark.post("/validManual", new TradingHandler.ValidOrders()); + Spark.post("/startFullTradeBuy", + new TradingHandler.FullTradeBuyHandler()); + Spark.post("/startFullTradeSell", + new TradingHandler.FullTradeSellHandler()); + Spark.post("/tradingAlgo", new TradingHandler.AlgorithmicTrader()); + Spark.post("/populateValue", new UserHandler.startWalletUpdates()); + Spark.post("/getGraphData", new UserHandler.getGraphInfo()); + + } + + /** + * Display an error page when an exception occurs in the server. + * + * @author jj + */ + private static class ExceptionPrinter implements ExceptionHandler { + @Override + public void handle(Exception e, Request req, Response res) { + res.status(500); + StringWriter stacktrace = new StringWriter(); + try (PrintWriter pw = new PrintWriter(stacktrace)) { + pw.println("
");
+        e.printStackTrace(pw);
+        pw.println("
"); + } + res.body(stacktrace.toString()); + } + } + + private static String testDecimal(String lastPrice, double percentGain) { + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double sellPrice = Double.valueOf(lastPrice); + double buyPrice = sellPrice - (sellPrice * percentGain); + BigDecimal bp = new BigDecimal(buyPrice, MathContext.DECIMAL64); + String[] s = bp.toString().split("\\."); + System.out.println(s[0] + ": " + s[1]); + int length = s[1].length(); + String finalBuyPrice = ""; + if (length > decimalLength) { + int difference = length - decimalLength; + String decimal = ""; + decimal = s[1].substring(0, s[1].length() - difference); + StringBuilder sb = new StringBuilder(); + sb.append(s[0]); + sb.append("."); + sb.append(decimal); + finalBuyPrice = sb.toString(); + } else { + finalBuyPrice = bp.toString(); + } + System.out.println("Final buy price is " + finalBuyPrice); + return finalBuyPrice; + } + + private static String testBigDecimal(String lastPrice, + double percentGain) { + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double sellPrice = Double.valueOf(lastPrice); + double buyPrice = sellPrice - (sellPrice * percentGain); + BigDecimal bd = new BigDecimal(buyPrice).setScale(decimalLength, + RoundingMode.HALF_DOWN); + System.out.println("BigDecimal price: " + bd.toPlainString()); + return bd.toPlainString(); + } + +} diff --git a/src/main/java/edu/brown/cs/term/tests/BinanceAPITest.java b/src/main/java/edu/brown/cs/term/tests/BinanceAPITest.java new file mode 100644 index 0000000..701f23e --- /dev/null +++ b/src/main/java/edu/brown/cs/term/tests/BinanceAPITest.java @@ -0,0 +1,66 @@ +package edu.brown.cs.term.tests; + +import com.binance.api.client.BinanceApiAsyncRestClient; +import com.binance.api.client.BinanceApiCallback; +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.BinanceApiWebSocketClient; +import com.binance.api.client.domain.event.AggTradeEvent; +import com.binance.api.client.exception.BinanceApiException; +import org.junit.Before; +import org.junit.Test; + +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; +import static junit.framework.TestCase.assertEquals; + +/** + * Tests the Binance API Functionality + */ +public class BinanceAPITest { + private String APIkey = "qW9xUO8kNpHHnxb0dJjStRrzE7tN0oTlPCbah4IWdxkgyAa5vqJXzSME6IYlDhrp"; + private String secretKey = "PXEisYYJhKd6T36nC8mH05AoZl4gcyytcz1Gd5Ybin1iv6GeS27rXySsaAn3Z5Mp"; + + + /** + * Tests if connection successfully connects to the server and gets the server + * time successfully. + */ + @Test + public void assertConnectionToServer() { + BinanceApiClientFactory fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiRestClient client = fact.newRestClient(); + client.ping(); + assertNotNull(client); + long serverTime = client.getServerTime(); + assertNotNull(serverTime); + assertTrue(serverTime > 0); + } + + /** + * Successfully tests the Websockets functionality of binance + */ + @Test + public void webSocketsBinance() { + BinanceApiClientFactory fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiWebSocketClient client = fact.newWebSocketClient(); + for(int i = 0; i< 500000; i++) { + client.onAggTradeEvent("ethbtc", new BinanceApiCallback() { + @Override + public void onResponse(AggTradeEvent aggTradeEvent) throws BinanceApiException { + System.out.println(aggTradeEvent.getPrice()); + assertTrue(true); + } + }); + } + } + + @Test + public void getPrice(){ + BinanceApiClientFactory fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiRestClient client = fact.newRestClient(); + System.out.println(client.getAllPrices()); + } + + +} diff --git a/src/main/java/edu/brown/cs/term/tests/DatabaseTests.java b/src/main/java/edu/brown/cs/term/tests/DatabaseTests.java new file mode 100644 index 0000000..0abdafa --- /dev/null +++ b/src/main/java/edu/brown/cs/term/tests/DatabaseTests.java @@ -0,0 +1,102 @@ +package edu.brown.cs.term.tests; + +import edu.brown.cs.term.connection.DatabaseConnection; +import edu.brown.cs.term.database.Trades; +import edu.brown.cs.term.database.CrypthubUser; +import org.junit.Before; +import org.junit.Test; + +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; +import static junit.framework.TestCase.assertEquals; + +public class DatabaseTests { + + @Before + public void connect(){ + DatabaseConnection.setConnection("data/db.sqlite3"); + } + + /** + * Checks if we can add a user successfully to the database. + */ + @Test + public void checkAndAddUser(){ + CrypthubUser user = new CrypthubUser(); + int i = 0; + StringBuilder sb = new StringBuilder(); + String characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + while(i<10){ + sb.append(characterSet.charAt((int)(Math.random()*characterSet.length()))); + i++; + } + assertTrue(user.checkUser(sb.toString()).contains("\"exists\":false")); + user.addUser(sb.toString(), "pass", "John", "Smith"); + assertTrue(user.checkUser(sb.toString()).contains("\"exists\":true")); + } + + /** + * Checks if a user exists in the database. + */ + @Test + public void checkUser(){ + CrypthubUser user = new CrypthubUser(); + int i = 0; + StringBuilder sb = new StringBuilder(); + String characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + while(i<10){ + sb.append(characterSet.charAt((int)(Math.random()*characterSet.length()))); + i++; + } + user.addUser(sb.toString(), "pass", "John", "Smith"); + assertTrue(user.login(sb.toString(), "pass").contains("\"login_found\":true")); + assertTrue(user.login(sb.toString(), "pass1").contains("\"login_found\":false")); + } + + /** + * Tests adding a public and private key to the DB. + */ + @Test + public void addPublicPrivate(){ + CrypthubUser user = new CrypthubUser(); + int i = 0; + StringBuilder sb = new StringBuilder(); + String characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + while(i<10){ + sb.append(characterSet.charAt((int)(Math.random()*characterSet.length()))); + i++; + } + user.addUser(sb.toString(), "pass", "John", "Smith"); + assertTrue(user.addPublicPrivateKey(sb.toString(), "test1", + "test2").contains("\"success\":true")); + assertTrue(user.addPublicPrivateKey("22", "test1", + "test2").contains("\"success\":false")); + } + + /** + * tests getting a public and private key from the database. + */ + @Test + public void getPublicPrivate(){ + CrypthubUser user = new CrypthubUser(); + System.out.println(user.getPublicPrivateKey("22BCWTTWTE").toString()); + } + + /** + * Tests getting the wallet information for all the assets above 0. + */ + @Test + public void getWalletInformation(){ + CrypthubUser user = new CrypthubUser(); + assertTrue(user.wallet("js").contains("\"assets\":\"ETH\"")); + } + + @Test + public void insertValueIntoValueDatabase(){ + CrypthubUser user = new CrypthubUser(); + assertTrue(user.insertAmounts("js", + user.totalAmount("js")).contains("\"success\":true")); + } + + +} diff --git a/src/main/java/edu/brown/cs/term/tests/MultithreadingTests.java b/src/main/java/edu/brown/cs/term/tests/MultithreadingTests.java new file mode 100644 index 0000000..b793477 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/tests/MultithreadingTests.java @@ -0,0 +1,17 @@ +package edu.brown.cs.term.tests; + +import edu.brown.cs.term.connection.DatabaseConnection; +import edu.brown.cs.term.thread.WalletThread; +import org.junit.Before; +import org.junit.Test; + +public class MultithreadingTests { + @Before + public void setup(){ + DatabaseConnection.setConnection("data/db.sqlite3"); + } + + @Test + public void WalletTest(){ + } +} diff --git a/src/main/java/edu/brown/cs/term/thread/BuyThread.java b/src/main/java/edu/brown/cs/term/thread/BuyThread.java new file mode 100644 index 0000000..24935eb --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/BuyThread.java @@ -0,0 +1,55 @@ +package edu.brown.cs.term.thread; + +import edu.brown.cs.term.trading.FullTradeBuy; + +public class BuyThread implements Runnable { + String name; + Thread t; + String symbol; + String buyPrice; + String sellPrice; + String stopPrice; + String quantity; + String username; + + public BuyThread(String user, String thread, String symb, String bP, + String sP, String stopP, String quant) { + username = user; + name = thread; + symbol = symb; + sellPrice = sP; + buyPrice = bP; + stopPrice = stopP; + quantity = quant; + t = new Thread(this, name); + t.start(); + } + + @Override + public void run() { + try { + FullTradeBuy ftb = new FullTradeBuy(username); + ftb.fullTrade(symbol, buyPrice, sellPrice, stopPrice, quantity); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted."); + } + } + + public void setSellPrice(String sp) { + sellPrice = sp; + } + + public void setBuyPrice(String bp) { + buyPrice = bp; + } + + public void setStopPrice(String stop) { + stopPrice = stop; + } + + public void setQuantity(String quant) { + quantity = quant; + } + +} diff --git a/src/main/java/edu/brown/cs/term/thread/MaThread.java b/src/main/java/edu/brown/cs/term/thread/MaThread.java new file mode 100644 index 0000000..7b79c4e --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/MaThread.java @@ -0,0 +1,46 @@ +package edu.brown.cs.term.thread; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.binance.api.client.domain.market.CandlestickInterval; + +import edu.brown.cs.term.trading.MovingAverage; + +public class MaThread implements Runnable{ + String username; + String name; + Set symbols; + String multiplier; + Thread t; + MovingAverage ma; + Map maMap = new HashMap(); + Map sdMap = new HashMap(); + public MaThread(String user, String thread, Set symb, String mult) { + username = user; + name = thread; + symbols = symb; + multiplier = mult; + t = new Thread(this, name); + t.start(); + } + public void run() { + try { + ma = new MovingAverage(CandlestickInterval.HALF_HOURLY, username, symbols, multiplier); + ma.calculate(); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted"); + } + } + + public Map getMAMap() { + return ma.getMAMap(); + } + + public Map getSDMap() { + return ma.getSDMap(); + } + +} diff --git a/src/main/java/edu/brown/cs/term/thread/PopulateValuesDBThread.java b/src/main/java/edu/brown/cs/term/thread/PopulateValuesDBThread.java new file mode 100644 index 0000000..96cf7e6 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/PopulateValuesDBThread.java @@ -0,0 +1,31 @@ +package edu.brown.cs.term.thread; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.repl.Main; + +public class PopulateValuesDBThread implements Runnable { + private String username; + private CrypthubUser chUser; + Thread t; + + public PopulateValuesDBThread(String user) { + username = user; + chUser = new CrypthubUser(); + Main.threadMap.add(user + " populator"); + t = new Thread(this, user + " populator"); + t.start(); + } + + @Override + public void run() { + try { + chUser.insertAmounts(username, chUser.totalAmount(username)); + while (true) { + chUser.insertAmounts(username, chUser.totalAmount(username)); + Thread.sleep(5000); + } + } catch (InterruptedException e) { + System.out.println("ERROR: Interrupted thread"); + } + } +} diff --git a/src/main/java/edu/brown/cs/term/thread/RSINotifierThread.java b/src/main/java/edu/brown/cs/term/thread/RSINotifierThread.java new file mode 100644 index 0000000..a9bed8c --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/RSINotifierThread.java @@ -0,0 +1,44 @@ +package edu.brown.cs.term.thread; + +import java.util.HashSet; +import java.util.Set; + +import com.binance.api.client.domain.market.CandlestickInterval; + +import edu.brown.cs.term.trading.RSINotifier; + +public class RSINotifierThread implements Runnable { + private CandlestickInterval interval = CandlestickInterval.HALF_HOURLY; + private String username = "js"; + private String name; + private Set symbols = new HashSet(); + private String rsiLimitHigh; + private String rsiLimitLow; + private Thread t; + private RSINotifier rsiNotifier; + + public RSINotifierThread(String user, String thread, Set symb, + String highLimit, String lowLimit) { + username = user; + name = thread; + symbols = symb; + rsiLimitHigh = highLimit; + rsiLimitLow = lowLimit; + name = thread; + t = new Thread(this, name); + t.start(); + } + + @Override + public void run() { + try { + rsiNotifier = new RSINotifier(interval, username, symbols, + rsiLimitHigh, rsiLimitLow); + rsiNotifier.calculate(); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted."); + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/thread/RsiThread.java b/src/main/java/edu/brown/cs/term/thread/RsiThread.java new file mode 100644 index 0000000..fceccd7 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/RsiThread.java @@ -0,0 +1,42 @@ +package edu.brown.cs.term.thread; + +import java.util.Map; +import java.util.Set; + +import com.binance.api.client.domain.market.CandlestickInterval; + +import edu.brown.cs.term.trading.RSICalculator; +import websockets.RsiWebSocket; + +public class RsiThread implements Runnable { + String name; + Thread t; + RSICalculator rsi; + private String username; + private Set symbols; + private RsiWebSocket webSocket; + + public RsiThread(String user, String thread, Set symb) { + name = thread; + username = user; + symbols = symb; + t = new Thread(this, name); + t.start(); + } + + @Override + public void run() { + try { + rsi = new RSICalculator(CandlestickInterval.HALF_HOURLY, username, symbols); + rsi.calculate(); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted"); + } + } + + public Map getRSIMap() { + return rsi.getRSIMap(); + } + +} diff --git a/src/main/java/edu/brown/cs/term/thread/SellThread.java b/src/main/java/edu/brown/cs/term/thread/SellThread.java new file mode 100644 index 0000000..6ca7aa9 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/SellThread.java @@ -0,0 +1,52 @@ +package edu.brown.cs.term.thread; + +import edu.brown.cs.term.trading.FullTradeSell; + +public class SellThread implements Runnable { + String name; + Thread t; + String symbol; + String sellPrice; + String buyPrice; + String stopPrice; + String quantity; + String username; + public SellThread(String user, String thread, String symb, String sP, + String bP, String stopP, String quant) { + name = thread; + symbol = symb; + sellPrice = sP; + buyPrice = bP; + stopPrice = stopP; + quantity = quant; + username = user; + t = new Thread(this, name); + t.start(); + } + + public void run() { + try { + FullTradeSell fts = new FullTradeSell(username); + fts.fullTrade(symbol, sellPrice, buyPrice, stopPrice, quantity); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted."); + } + } + public void setSellPrice(String sp) { + sellPrice = sp; + } + + public void setBuyPrice(String bp) { + buyPrice = bp; + } + + public void setStopPrice(String stop) { + stopPrice = stop; + } + + public void setQuantity(String quant) { + quantity = quant; + } + +} diff --git a/src/main/java/edu/brown/cs/term/thread/TradingAlgorithmThread.java b/src/main/java/edu/brown/cs/term/thread/TradingAlgorithmThread.java new file mode 100644 index 0000000..a6847ae --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/TradingAlgorithmThread.java @@ -0,0 +1,40 @@ +package edu.brown.cs.term.thread; +import java.util.List; +import java.util.Set; + +import com.binance.api.client.domain.market.CandlestickInterval; + +import edu.brown.cs.term.trading.TradingAlgorithm; +public class TradingAlgorithmThread implements Runnable { + String name; + Thread t; + Set symbols; + CandlestickInterval interval = CandlestickInterval.HALF_HOURLY; + String upperRSI; + String lowerRSI; + String multiplier; + String fraction; + String username; + public TradingAlgorithmThread(String user, String thread, Set symb, + String upperLimit, String lowerLimit, String mult, String frac) { + username = user; + name = thread; + symbols = symb; + upperRSI = upperLimit; + lowerRSI = lowerLimit; + multiplier = mult; + fraction = frac; + t = new Thread(this, name); + t.start(); + } + + public void run() { + try { + TradingAlgorithm ta = new TradingAlgorithm(interval, username, symbols, upperRSI, + lowerRSI, multiplier, fraction); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted"); + } + } +} diff --git a/src/main/java/edu/brown/cs/term/thread/TsThread.java b/src/main/java/edu/brown/cs/term/thread/TsThread.java new file mode 100644 index 0000000..87211a7 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/TsThread.java @@ -0,0 +1,33 @@ +package edu.brown.cs.term.thread; + +import java.util.Set; + +import com.binance.api.client.domain.market.CandlestickInterval; +import edu.brown.cs.term.trading.RSICalculator; +import edu.brown.cs.term.trading.TrailingStop; + +public class TsThread implements Runnable{ + String name; + Thread t; + String username; + Set symbols; + double stopPercent = 0.10; + public TsThread(String user, String thread, + Set symb, String percent) { + username = user; + stopPercent = Double.valueOf(percent); + name = thread; + t = new Thread(this, name); + t.start(); + } + public void run() { + try { + TrailingStop ts = new TrailingStop(username, symbols, stopPercent); + ts.calculate(); + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(name + " was interrupted"); + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/thread/WalletThread.java b/src/main/java/edu/brown/cs/term/thread/WalletThread.java new file mode 100644 index 0000000..b85323f --- /dev/null +++ b/src/main/java/edu/brown/cs/term/thread/WalletThread.java @@ -0,0 +1,32 @@ +package edu.brown.cs.term.thread; + +import edu.brown.cs.term.database.CrypthubUser; +import websockets.RsiWebSocket; + +public class WalletThread implements Runnable { + private String username; + Thread t; + CrypthubUser chUser; + + public WalletThread(String user) { + username = user; + chUser = new CrypthubUser(); + t = new Thread(this, username + "wallet"); + t.start(); + } + + @Override + public void run() { + try { + while (true) { + double total = chUser.totalAmount(username); + RsiWebSocket.sendWalletUpdate(total, username); + chUser.insertAmounts(username, total); + Thread.sleep(3000); + } + } catch (InterruptedException e) { + System.out.println("Wallet Thread was interrupted"); + } + } + +} diff --git a/src/main/java/edu/brown/cs/term/trading/FullTradeBuy.java b/src/main/java/edu/brown/cs/term/trading/FullTradeBuy.java new file mode 100644 index 0000000..49f505e --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/FullTradeBuy.java @@ -0,0 +1,199 @@ +package edu.brown.cs.term.trading; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Set; + +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.TimeInForce; +import com.binance.api.client.domain.account.NewOrder; +import com.binance.api.client.domain.account.NewOrderResponse; +import com.binance.api.client.domain.account.Order; +import com.binance.api.client.domain.account.request.CancelOrderRequest; +import com.binance.api.client.domain.account.request.OrderStatusRequest; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.database.Trades; +import edu.brown.cs.term.general.Tuple; +import websockets.RsiWebSocket; + +public class FullTradeBuy { + private String APIkey + = "aXGg0J5kFv08YOytKZrCav9rWnjgzdFx3BvjIjY5M2gQQCaYSEdznhAGG4kspVr2"; + private String secretKey + = "pgbthhPJBg8FS29FCeyYvlF5ay1CV0we4xxilxL9pytc5djb7RxDCs7k4kChthMI"; + private String username = "js"; + private BinanceApiClientFactory fact; + private BinanceApiRestClient client; + private Trades trades; + private Set symbols; + private Gson GSON; + private String message = ""; + private int orderId; + + public FullTradeBuy(String user) { + GSON = new Gson(); + username = user; + setPublicPrivateKey(username); + trades = new Trades(); + } + + /** + * Sets the public and private key for use in trading. + * @param username + * username of the user + * @return String representing JSON object + */ + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + APIkey = keys.getFirstEntry(); + secretKey = keys.getSecondEntry(); + fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client = fact.newRestClient(); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + public void fullTrade(String symbol, String buyPrice, String sellPrice, + String stopPrice, String quantity) { + NewOrderResponse buy = placeBuyOrder(symbol, buyPrice, quantity); + NewOrderResponse sell = checkAndSell(buy, symbol, sellPrice, false); + monitorForStop(sell, symbol, stopPrice, false); + } + + public NewOrderResponse placeBuyOrder(String symbol, String buyPrice, + String quantity) { + double lastPrice = Double + .valueOf(client.get24HrPriceStatistics(symbol).getLastPrice()); + double priceBuy = Double.valueOf(buyPrice); + if (!username.equals("")) { + NewOrderResponse res = client.newOrder( + NewOrder.limitBuy(symbol, TimeInForce.GTC, quantity, buyPrice)); + trades.addTrade(username, client.getOrderStatus( + new OrderStatusRequest(symbol, res.getOrderId()))); + return res; + } else { + System.out.println("ERROR: Please login before making a trade."); + return null; + } + } + + public NewOrderResponse checkAndSell(NewOrderResponse buy, String symbol, + String sellPrice, boolean buyFilled) { + NewOrderResponse res = null; + while (!buyFilled) { + Order order = client.getOrderStatus( + new OrderStatusRequest(symbol, buy.getOrderId())); + if (order.getStatus().toString().equals("FILLED")) { + buyFilled = true; + double assetAmount = Double.valueOf(buy.getOrigQty()); + res = client.newOrder(NewOrder.limitSell(symbol, TimeInForce.GTC, + buy.getOrigQty(), sellPrice)); + trades.updateTrade(username, + client.getOrderStatus( + new OrderStatusRequest(symbol, buy.getOrderId())), + message); + trades.addTrade(username, client.getOrderStatus( + new OrderStatusRequest(symbol, res.getOrderId()))); + } else { + message + = "Buy not complete. Time is: " + java.time.LocalTime.now(); + System.out.println(message); + RsiWebSocket.sendCustomTradingUpdateMessage(username, + buy.getOrderId(), message); + try { + Thread.sleep(30000); + } catch (Exception e) { + System.out.println("Thread interrupted."); + } + } + } + return res; + } + + public void monitorForStop(NewOrderResponse sell, String symbol, + String stopPrice, boolean sellFilled) { + while (!sellFilled) { + Order order = client.getOrderStatus( + new OrderStatusRequest(symbol, sell.getOrderId())); + if (order.getStatus().toString().equals("FILLED")) { + message = "Sell complete. Good trade."; + RsiWebSocket.sendCustomTradingUpdateMessage(username, + sell.getOrderId(), message); + System.out.println(message); + + sellFilled = true; + trades.updateTrade(username, + client.getOrderStatus( + new OrderStatusRequest(symbol, sell.getOrderId())), + message); + break; + } else { + double currentPrice = Double + .valueOf(client.get24HrPriceStatistics(symbol).getLastPrice()); + double stop = Double.valueOf(stopPrice); + if (currentPrice < stop) { + try { + Thread.sleep(60000); + } catch (Exception e) { + System.out.println("Thread interrupted"); + } + + String newCurrent + = client.get24HrPriceStatistics(symbol).getLastPrice(); + if (Double.valueOf(newCurrent) >= stop) { + continue; + } else { + message = "Current price still below stop price. Cancelling " + + "previous sell and generating stop sell. Time is: " + + java.time.LocalTime.now(); + RsiWebSocket.sendCustomTradingUpdateMessage(username, + sell.getOrderId(), message); + System.out.println(message); + client.cancelOrder( + new CancelOrderRequest(symbol, sell.getOrderId())); + trades.updateTrade(username, + client.getOrderStatus( + new OrderStatusRequest(symbol, sell.getOrderId())), + message); + + double asset = Double.valueOf(sell.getOrigQty()); + String[] splits = newCurrent.split("\\."); + int decimalLength = splits[1].length(); + double sp = Double.valueOf(newCurrent) + - (Double.valueOf(newCurrent) * 0.0025); + BigDecimal bd = new BigDecimal(sp).setScale(decimalLength, + RoundingMode.HALF_DOWN); + NewOrderResponse res = client + .newOrder(NewOrder.limitSell(symbol, TimeInForce.GTC, + sell.getOrigQty(), bd.toPlainString())); + message = "Stop buy posted. Price of " + newCurrent + + ". Awaiting completion. Bad trade. Time is " + + java.time.LocalTime.now(); + trades.addTrade(username, client.getOrderStatus( + new OrderStatusRequest(symbol, res.getOrderId()))); + System.out.println(message); + } + } else { + message + = "Monitoring for stop loss or sell completion. Time is: " + + java.time.LocalTime.now(); + System.out.println(message); + RsiWebSocket.sendCustomTradingUpdateMessage(username, + sell.getOrderId(), message); + try { + Thread.sleep(10000); + } catch (Exception e) { + System.out.println("Thread interrupted."); + } + } + } + } + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/FullTradeSell.java b/src/main/java/edu/brown/cs/term/trading/FullTradeSell.java new file mode 100644 index 0000000..65fe484 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/FullTradeSell.java @@ -0,0 +1,227 @@ +package edu.brown.cs.term.trading; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Set; + +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.TimeInForce; +import com.binance.api.client.domain.account.NewOrder; +import com.binance.api.client.domain.account.NewOrderResponse; +import com.binance.api.client.domain.account.Order; +import com.binance.api.client.domain.account.request.CancelOrderRequest; +import com.binance.api.client.domain.account.request.OrderStatusRequest; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.database.Trades; +import edu.brown.cs.term.general.Tuple; +import websockets.RsiWebSocket; + +public class FullTradeSell { + // private String APIkey = + // "qW9xUO8kNpHHnxb0dJjStRrzE7tN0oTlPCbah4IWdxkgyAa5vqJXzSME6IYlDhrp"; + // private String secretKey = + // "PXEisYYJhKd6T36nC8mH05AoZl4gcyytcz1Gd5Ybin1iv6GeS27rXySsaAn3Z5Mp"; + private String APIkey = ""; + private String secretKey = ""; + private String username = "js"; + private BinanceApiClientFactory fact; + private BinanceApiRestClient client; + private Trades trades; + private Set symbols; + private String message = ""; + private Gson GSON; + + // TODO: figure out how this works + public FullTradeSell(String user) { + GSON = new Gson(); + username = user; + setPublicPrivateKey(username); + trades = new Trades(); // Intializes Trades DB + } + + /** + * Sets the public and private key for use in trading. + * @param username + * username of the user + * @return String representing JSON object + */ + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + this.username = username; + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + APIkey = keys.getFirstEntry(); + secretKey = keys.getSecondEntry(); + fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client = fact.newRestClient(); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + public void fullTrade(String symbol, String sellPrice, String buyPrice, + String stopPrice, String quantity) { + NewOrderResponse sell = placeSellOrder(symbol, sellPrice, quantity); + NewOrderResponse buy = checkAndBuy(sell, symbol, buyPrice, false); + monitorForStop(buy, sell, symbol, stopPrice, false); + } + + public NewOrderResponse placeSellOrder(String symbol, String sellPrice, + String quantity) { + double lastPrice = Double + .valueOf(client.get24HrPriceStatistics(symbol).getLastPrice()); + double sell = Double.valueOf(sellPrice); + if (!username.equals("")) { + // double amountFree = + // Double.valueOf(client.getAccount().getAssetBalance(symbol.substring(0,3)).getFree()); + // double amountToSell = amountFree / frac; + NewOrderResponse res = client.newOrder(NewOrder.limitSell(symbol, + TimeInForce.GTC, quantity, sellPrice)); + trades.addTrade(username, client.getOrderStatus( + new OrderStatusRequest(symbol, res.getOrderId()))); + message + = "Sell posted for " + quantity + " " + symbol.substring(0, 3) + + ". Time is " + java.time.LocalTime.now(); + RsiWebSocket.sendCustomTradingUpdateMessage(username, res.getOrderId(), message); + System.out.println(message); + + return res; + // } else if (!username.equals("")) { + // System.out.println("ERROR: Current price is higher than sell + // price"); + // return null; + } else { + System.out.println("ERROR: Please login before making a trade."); + return null; + } + } + + public NewOrderResponse checkAndBuy(NewOrderResponse sell, String symbol, + String buyPrice, boolean sellFilled) { + NewOrderResponse res = null; + while (!sellFilled) { + Order order = client.getOrderStatus( + new OrderStatusRequest(symbol, sell.getOrderId())); + if (order.getStatus().toString().equals("FILLED")) { + message = "Sell has been filled. Posting buy. Time is: " + + java.time.LocalTime.now(); + RsiWebSocket.sendCustomTradingUpdateMessage(username, + sell.getOrderId(), message); + sellFilled = true; + double assetAmount = Double.valueOf(sell.getPrice()) + * Double.valueOf(sell.getOrigQty()); + double buyQuant = assetAmount / Double.valueOf(buyPrice); + BigDecimal bd + = new BigDecimal(buyQuant).setScale(2, RoundingMode.HALF_DOWN); + trades.updateTrade(username, + client.getOrderStatus( + new OrderStatusRequest(symbol, sell.getOrderId())), + message); + res = client.newOrder(NewOrder.limitBuy(symbol, TimeInForce.GTC, + bd.toPlainString(), buyPrice)); + trades.addTrade(username, client.getOrderStatus( + new OrderStatusRequest(symbol, res.getOrderId()))); + } else { + message = "Sell not complete. Time is: " + + java.time.LocalTime.now(); + System.out.println(message); + RsiWebSocket.sendCustomTradingUpdateMessage(username, sell.getOrderId(), + message); + try { + Thread.sleep(30000); + } catch (Exception e) { + System.out.println("Thread interrupted"); + } + } + } + return res; + } + + public void monitorForStop(NewOrderResponse buy, NewOrderResponse sell, + String symbol, String stopPrice, boolean buyFilled) { + while (!buyFilled) { + Order order = client.getOrderStatus( + new OrderStatusRequest(symbol, buy.getOrderId())); + if (order.getStatus().toString().equals("FILLED")) { + message = "Buy complete. Good trade. Time is: " + + java.time.LocalTime.now(); + RsiWebSocket.sendCustomTradingUpdateMessage(username, buy.getOrderId(), message); + System.out.println(message); + trades.updateTrade(username, + client.getOrderStatus( + new OrderStatusRequest(symbol, buy.getOrderId())), + message); + buyFilled = true; + } else { + double currentPrice = Double + .valueOf(client.get24HrPriceStatistics(symbol).getLastPrice()); + double stop = Double.valueOf(stopPrice); + if (currentPrice > stop) { + try { + Thread.sleep(60000); + } catch (Exception e) { + System.out.println("Thread interrupted"); + } + + double newCurrent = Double.valueOf( + client.get24HrPriceStatistics(symbol).getLastPrice()); + if (newCurrent <= stop) { + continue; + } else { + message = "Stop price exceeded. Cancelling previous" + + " buy and generating stop buy order. Time is: " + + java.time.LocalTime.now(); + RsiWebSocket.sendCustomTradingUpdateMessage(username, buy.getOrderId(), message); + System.out.println(message); + client.cancelOrder( + new CancelOrderRequest(symbol, buy.getOrderId())); + trades.updateTrade(username, + client.getOrderStatus( + new OrderStatusRequest(symbol, buy.getOrderId())), + message); + + String price + = client.get24HrPriceStatistics(symbol).getLastPrice(); + String[] splits = price.split("\\."); + int decimalLength = splits[1].length(); + double valPrice = Double.valueOf(price) * 1.0025; + BigDecimal bd = new BigDecimal(valPrice) + .setScale(decimalLength, RoundingMode.HALF_DOWN); + double quant = Double.valueOf(sell.getOrigQty()) + * Double.valueOf(sell.getPrice()); + double stopQuant = quant / bd.doubleValue(); + BigDecimal sd = new BigDecimal(stopQuant).setScale(2, + RoundingMode.HALF_DOWN); + NewOrderResponse res = client + .newOrder(NewOrder.limitBuy(symbol, TimeInForce.GTC, + sd.toPlainString(), bd.toPlainString())); + message = "Stop buy posted. Price of " + price + + ". Awaiting completion. Bad trade. Time is " + + java.time.LocalTime.now(); + RsiWebSocket.sendCustomTradingUpdateMessage(username, buy.getOrderId(), message); + trades.addTrade(username, client.getOrderStatus( + new OrderStatusRequest(symbol, res.getOrderId()))); + System.out.println(message); + buyFilled = true; + } + } else { + message = "Monitoring for stop loss or buy completion. Time is: " + + java.time.LocalTime.now(); + System.out.println(message); + RsiWebSocket.sendCustomTradingUpdateMessage(username, buy.getOrderId(), + message); + + try { + Thread.sleep(30000); + } catch (Exception e) { + System.out.println("Thread interrupted"); + } + } + } + } + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/MovingAverage.java b/src/main/java/edu/brown/cs/term/trading/MovingAverage.java new file mode 100644 index 0000000..12fc871 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/MovingAverage.java @@ -0,0 +1,332 @@ +package edu.brown.cs.term.trading; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import com.binance.api.client.BinanceApiAsyncRestClient; +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.market.Candlestick; +import com.binance.api.client.domain.market.CandlestickInterval; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.general.Tuple; +import websockets.RsiWebSocket; + +public class MovingAverage { + Map currentMA = new HashMap(); + Map currentSD = new HashMap(); + Map> previousMAs + = new HashMap>(); + Map> previousSDs + = new HashMap>(); + Map> previousCandles + = new HashMap>(); + Map firstNewCandle = new HashMap(); + Map twilioHold = new HashMap(); + List rsiVals = new ArrayList(); + boolean finishedInitialCalculations = false; + double bandMultiplier = 2; + String username = "js"; + private Gson GSON; + CandlestickInterval interval = CandlestickInterval.HALF_HOURLY; + private String APIkey + = "aXGg0J5kFv08YOytKZrCav9rWnjgzdFx3BvjIjY5M2gQQCaYSEdznhAGG4kspVr2"; + private String secretKey + = "pgbthhPJBg8FS29FCeyYvlF5ay1CV0we4xxilxL9pytc5djb7RxDCs7k4kChthMI"; + private String twilioKey = "AC740a42cac1fc2a9567eb53594736f458"; + private String twilioSecret = "9478ee8347691c3410cce9c8f00e0681"; + private boolean finishedInitialCalculation = false; + private BinanceApiClientFactory fact; + private BinanceApiRestClient client; + private Set symbols = new HashSet(); + private String message; + + public MovingAverage(CandlestickInterval i, String user, + Set symb, String multiplier) { + interval = i; + symbols = symb; + bandMultiplier = Double.valueOf(multiplier); + GSON = new Gson(); + username = user; + setPublicPrivateKey(username); + } + + public void calculate() { + runCalculations(symbols); + } + + private void runCalculations(Set symbols) { + initiateCalculation(symbols); + while (finishedInitialCalculation) { + continueCalculation(symbols); + } + } + + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + this.username = username; + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + APIkey = keys.getFirstEntry(); + secretKey = keys.getSecondEntry(); + fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client = fact.newRestClient(); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + private void initiateCalculation(Set symbols) { + initializeMaps(symbols); + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = factory.newAsyncRestClient(); + for (String symbol : symbols) { + CompletableFuture time = new CompletableFuture(); + client.getServerTime(response -> { + time.complete(response.getServerTime()); + }); + long endTime = -1; + try { + endTime = time.get(); + } catch (Exception e) { + System.out.println("Time was not retrieved."); + } + long startTime = endTime - (128 * 60 * 60 * 1000); + CompletableFuture> candles + = new CompletableFuture>(); + List candlesticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 256, startTime, endTime, + (List response) -> { + candles.complete(response); + }); + try { + candlesticks = candles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + int start = 0; + int end = 21; + while (currentMA.get(symbol) == 0.0) { + if (end < 257) { + List group21 = candlesticks.subList(start, end); + double firstAverage = calculateAverage(group21); + double firstSD = calculateStandardDev(group21, firstAverage); + previousMAs.get(symbol).add(firstAverage); + previousSDs.get(symbol).add(firstSD); + start++; + end++; + } + if (end == 257) { + currentMA.replace(symbol, previousMAs.get(symbol) + .get(previousMAs.get(symbol).size() - 1)); + currentSD.replace(symbol, previousSDs.get(symbol) + .get(previousMAs.get(symbol).size() - 1)); + message = symbol + " Current Moving Average: " + + currentMA.get(symbol); +// this.updateFrontEnd(message); + + previousCandles.get(symbol) + .add(candlesticks.get(candlesticks.size() - 1)); + finishedInitialCalculation = true; + } + } + } + } + + private void continueCalculation(Set symbols) { + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = factory.newAsyncRestClient(); + for (String symbol : symbols) { + List previous = previousCandles.get(symbol); + Candlestick previousC = previous.get(previous.size() - 1); + CompletableFuture time = new CompletableFuture(); + client.getServerTime(response -> { + time.complete(response.getServerTime()); + }); + long endTime = -1; + try { + endTime = time.get(); + } catch (Exception e) { + System.out.println("Time was not retrieved."); + } + long startTime = endTime - (long) (10.5 * 3600 * 1000); + CompletableFuture> candles + = new CompletableFuture>(); + List candlesticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 21, startTime, endTime, + (List response) -> { + candles.complete(response); + }); + try { + candlesticks = candles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + if (firstNewCandle.get(symbol) == false) { + double currentAverage = calculateAverage(candlesticks); + double currentStandardDev + = calculateStandardDev(candlesticks, currentAverage); + previousMAs.get(symbol).set(previousMAs.get(symbol).size() - 1, + currentAverage); + previousSDs.get(symbol).set(previousMAs.get(symbol).size() - 1, + currentStandardDev); + currentMA.replace(symbol, currentAverage); + currentSD.replace(symbol, currentStandardDev); + + message = symbol + " Lower Band: " + Double.toString( + (currentAverage - bandMultiplier * currentStandardDev)); + System.out.println(message); +// this.updateFrontEnd(message); + + message = symbol + " Current MA No New Candle Yet: " + + Double.toString(currentAverage); + System.out.println(message); +// this.updateFrontEnd(message); + + message = symbol + " Upper Band: " + Double.toString( + (currentAverage + bandMultiplier * currentStandardDev)); + System.out.println(message); +// this.updateFrontEnd(message); + + if (!candlesticks.get(candlesticks.size() - 1).getOpenTime() + .equals(previousCandles.get(symbol) + .get(previousCandles.get(symbol).size() - 1) + .getOpenTime())) { + firstNewCandle.replace(symbol, true); + } + } else { + if (!candlesticks.get(candlesticks.size() - 1).getOpenTime() + .equals(previousCandles.get(symbol) + .get(previousCandles.get(symbol).size() - 1) + .getOpenTime())) { + previousCandles.get(symbol) + .add(candlesticks.get(candlesticks.size() - 1)); + long tempStart = startTime - (long) (0.5 * 3600 * 1000); + CompletableFuture> tempCandles + = new CompletableFuture>(); + List tempSticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 22, tempStart, + endTime, (List response) -> { + tempCandles.complete(response); + }); + try { + tempSticks = tempCandles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + double previousAverage + = calculateAverage(tempSticks.subList(0, 21)); + double previousSD = calculateStandardDev( + tempSticks.subList(0, 21), previousAverage); + previousMAs.get(symbol).set(previousMAs.get(symbol).size() - 1, + previousAverage); + previousSDs.get(symbol).set(previousSDs.get(symbol).size() - 1, + previousSD); + + message = symbol + " Current MA Old Candle Final: " + + previousAverage; + + System.out.println(message); +// this.updateFrontEnd(message); + + double newAverage = calculateAverage(candlesticks); + double newSD = calculateStandardDev(candlesticks, newAverage); + previousMAs.get(symbol).add(newAverage); + previousSDs.get(symbol).add(newSD); + currentMA.replace(symbol, newAverage); + currentSD.replace(symbol, newSD); + + message = symbol + " Current MA New Candle: " + newAverage; + System.out.println(message); +// this.updateFrontEnd(message); + + } else { + double currentAverage = calculateAverage(candlesticks); + double currentStandardDev + = calculateStandardDev(candlesticks, currentAverage); + previousMAs.get(symbol).set(previousMAs.get(symbol).size() - 1, + currentAverage); + previousSDs.get(symbol).set(previousMAs.get(symbol).size() - 1, + currentStandardDev); + currentMA.replace(symbol, currentAverage); + currentSD.replace(symbol, currentStandardDev); + + message = symbol + " Lower Band: " + Double.toString( + (currentAverage - bandMultiplier * currentStandardDev)); + System.out.println(message); +// this.updateFrontEnd(message); + + message = symbol + " Current MA: " + currentAverage; + System.out.println(message); +// this.updateFrontEnd(message); + + message = symbol + " Upper Band: " + Double.toString( + (currentAverage + bandMultiplier * currentStandardDev)); + System.out.println(message); +// this.updateFrontEnd(message); + } + } + } + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + System.out.println("Thread interrupted"); + } + } + + private void initializeMaps(Set symbols) { + for (String symbol : symbols) { + currentMA.put(symbol, 0.0); + currentSD.put(symbol, 0.0); + previousMAs.put(symbol, new ArrayList()); + previousSDs.put(symbol, new ArrayList()); + previousCandles.put(symbol, new ArrayList()); + firstNewCandle.put(symbol, false); + } + } + + private double calculateAverage(List candles) { + double sum = 0.0; + for (Candlestick c : candles) { + sum += Double.parseDouble(c.getClose()); + } + double average = sum / candles.size(); + return average; + } + + private double calculateStandardDev(List candles, + double currentAverage) { + double sum = 0.0; + for (Candlestick c : candles) { + sum += Math.pow((Double.parseDouble(c.getClose()) - currentAverage), + 2); + } + double variance = sum / (candles.size() - 1); + double standardDev = Math.sqrt(variance); + return standardDev; + } + + public Map getMAMap() { + return currentMA; + } + + public Map getSDMap() { + return currentSD; + } + + private void updateFrontEnd(String message) { + if (username != null) { + RsiWebSocket.sendAutomaticradingUpdateMessage(username, message); + } + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/RSICalculator.java b/src/main/java/edu/brown/cs/term/trading/RSICalculator.java new file mode 100644 index 0000000..39f96c2 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/RSICalculator.java @@ -0,0 +1,414 @@ +package edu.brown.cs.term.trading; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import com.binance.api.client.BinanceApiAsyncRestClient; +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.market.Candlestick; +import com.binance.api.client.domain.market.CandlestickInterval; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.twilio.Twilio; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.general.Tuple; +import websockets.RsiWebSocket; + +public class RSICalculator { + + Map currentRSI = new HashMap(); + private Map> prevGains + = new HashMap>(); + private Map> prevLosses + = new HashMap>(); + private Map> previousCandles + = new HashMap>(); + private Map firstNewCandle + = new HashMap(); + private Map twilioHold = new HashMap(); + private List rsiVals = new ArrayList(); + private boolean finishedInitialCalculations = false; + private CandlestickInterval interval = CandlestickInterval.HALF_HOURLY; + private Map intervalConversion + = new HashMap(); + private String APIkey + = "aXGg0J5kFv08YOytKZrCav9rWnjgzdFx3BvjIjY5M2gQQCaYSEdznhAGG4kspVr2"; + private String secretKey + = "pgbthhPJBg8FS29FCeyYvlF5ay1CV0we4xxilxL9pytc5djb7RxDCs7k4kChthMI"; + private String twilioKey = "AC740a42cac1fc2a9567eb53594736f458"; + private String twilioSecret = "9478ee8347691c3410cce9c8f00e0681"; + private Set symbols = new HashSet(); + private String username = "js"; + private BinanceApiClientFactory fact; + private BinanceApiRestClient client; + private Gson GSON; + + public RSICalculator(CandlestickInterval i, String user, + Set symb) { + GSON = new Gson(); + Twilio.init(twilioKey, twilioSecret); + username = user; + interval = i; + symbols = symb; + setPublicPrivateKey(username); + setIntervalConversions(); + } + + public void calculate() { + runCalculationsCurrent(symbols); + } + + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + this.username = username; + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + APIkey = keys.getFirstEntry(); + secretKey = keys.getSecondEntry(); + fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client = fact.newRestClient(); + System.out.println("here1"); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + private void runCalculationsCurrent(Set symbols) { + initiateCalculation(symbols); + while (finishedInitialCalculations) { + continueCalculation(symbols); + } + } + + private void initiateCalculation(Set symbols) { + initializeMaps(symbols); + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = factory.newAsyncRestClient(); + System.out.println("here2"); + for (String symbol : symbols) { + CompletableFuture time = new CompletableFuture(); + client.getServerTime(response -> { + time.complete(response.getServerTime()); + }); + long endTime = -1; + try { + endTime = time.get(); + } catch (Exception e) { + System.out.println("Time was not retrieved."); + } + long startTime + = endTime - (256 * intervalConversion.get(interval) * 60 * 1000); + CompletableFuture> candles + = new CompletableFuture>(); + List candlesticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 256, startTime, endTime, + (List response) -> { + candles.complete(response); + }); + try { + candlesticks = candles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + int count = 15; + while (currentRSI.get(symbol) == -1.0) { + // if previous gains and losses are populated, use wilder smoothing + if (count > 15) { + List prev_gains = prevGains.get(symbol); + double previousGain = prev_gains.get(prev_gains.size() - 1); + List prev_loss = prevLosses.get(symbol); + double previousLoss = prev_loss.get(prev_loss.size() - 1); + + double lastDiff = Double + .parseDouble(candlesticks.get(count).getClose()) + - Double.parseDouble(candlesticks.get(count - 1).getClose()); + + double rsi = rsiFromDiff(lastDiff, previousGain, previousLoss, + symbol, true); + count++; + + } else { + List firstFifteen = candlesticks.subList(0, 15); + List differences = getDifferences(firstFifteen); + List gainsClipped = clipGains(differences); + List lossesClipped = clipLoss(differences); + + double gain_average = averageGains(gainsClipped); + double loss_average = averageLoss(lossesClipped); + prevGains.get(symbol).add(gain_average); + prevLosses.get(symbol).add(loss_average); + double rs = gain_average / loss_average; + double rsi = 100 - 100 / (1 + rs); + rsiVals.add(rsi); + count++; + } + if (count == 256) { + double lastRSI = rsiVals.get(rsiVals.size() - 1); + currentRSI.replace(symbol, lastRSI); + previousCandles.get(symbol) + .add(candlesticks.get(candlesticks.size() - 1)); + String message + = symbol + " Current RSI: " + Double.toString(lastRSI); + System.out.println(message); +// updateFrontEnd(message); + finishedInitialCalculations = true; + } + } + } + + } + + private void continueCalculation(Set symbols) { + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = factory.newAsyncRestClient(); + for (String symbol : symbols) { + List previous = previousCandles.get(symbol); + Candlestick previousC = previous.get(previous.size() - 1); + CompletableFuture time = new CompletableFuture(); + client.getServerTime(response -> { + time.complete(response.getServerTime()); + }); + long endTime = -1; + try { + endTime = time.get(); + } catch (Exception e) { + System.out.println("Time was not retrieved."); + } + long startTime = endTime - (2 * 3600 * 1000); + CompletableFuture> candles + = new CompletableFuture>(); + List candlesticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 4, startTime, endTime, + (List response) -> { + candles.complete(response); + }); + try { + candlesticks = candles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + if (firstNewCandle.get(symbol) == false) { + List prev_gains = prevGains.get(symbol); + double prev_gain = prev_gains.get(prev_gains.size() - 2); + List prev_losses = prevLosses.get(symbol); + double prev_loss = prev_losses.get(prev_losses.size() - 2); + double lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 1).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()); + + double rsi + = rsiFromDiff(lastDiff, prev_gain, prev_loss, symbol, false); + String message = symbol + " Current RSI No New Candle Yet: " + + Double.toString(rsi); + System.out.println(message); +// this.updateFrontEnd(message); + currentRSI.replace(symbol, rsi); + if (!candlesticks.get(candlesticks.size() - 1).getOpenTime() + .equals(previousCandles.get(symbol) + .get(previousCandles.get(symbol).size() - 1) + .getOpenTime())) { + firstNewCandle.replace(symbol, true); + } + } else { + if (!candlesticks.get(candlesticks.size() - 1).getOpenTime() + .equals(previousCandles.get(symbol) + .get(previousCandles.get(symbol).size() - 1) + .getOpenTime())) { + previousCandles.get(symbol) + .add(candlesticks.get(candlesticks.size() - 1)); + + double prev_gain = prevGains.get(symbol) + .get(prevGains.get(symbol).size() - 2); + double prev_loss = prevLosses.get(symbol) + .get(prevGains.get(symbol).size() - 2); + double lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 3).getClose()); + + double rsi + = rsiFromDiff(lastDiff, prev_gain, prev_loss, symbol, false); + currentRSI.replace(symbol, rsi); + String message = symbol + " Current RSI Old Candle Final: " + + Double.toString(rsi); + System.out.println(message); +// this.updateFrontEnd(message); + + double prev_gain_new = prevGains.get(symbol) + .get(prevGains.get(symbol).size() - 1); + double prev_loss_new = prevLosses.get(symbol) + .get(prevLosses.get(symbol).size() - 1); + + lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 1).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()); + + rsi = rsiFromDiff(lastDiff, prev_gain_new, prev_loss_new, symbol, + true); + currentRSI.replace(symbol, rsi); + message = symbol + " Current RSI New Candle: " + + Double.toString(rsi); + System.out.println(message); +// this.updateFrontEnd(message); + + } else { + double prev_gain = prevGains.get(symbol) + .get(prevGains.get(symbol).size() - 2); + double prev_loss = prevLosses.get(symbol) + .get(prevLosses.get(symbol).size() - 2); + double lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 1).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()); + double rsi + = rsiFromDiff(lastDiff, prev_gain, prev_loss, symbol, false); + currentRSI.replace(symbol, rsi); + String message + = symbol + " Current RSI: " + Double.toString(rsi); + System.out.println(message); +// updateFrontEnd(message); + } + } + } + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + System.out.println("Thread interrupted"); + continueCalculation(symbols); + } + } + + private List getDifferences(List candles) { + List diffs = new ArrayList(); + for (int i = 1; i < candles.size(); i++) { + double diff = Double.parseDouble(candles.get(i).getClose()) + - Double.parseDouble(candles.get(i - 1).getClose()); + diffs.add(diff); + } + return diffs; + } + + private List clipGains(List differences) { + List gains = differences; + for (double gain : gains) { + if (gain < 0) { + gain = 0; + } + } + return gains; + } + + private List clipLoss(List differences) { + List losses = differences; + for (double loss : losses) { + if (loss > 0) { + loss = 0; + } + } + return losses; + } + + private double averageGains(List gains) { + double sum = 0; + for (double gain : gains) { + sum += gain; + } + double average = sum / 14; + return average; + } + + private double averageLoss(List losses) { + double sum = 0; + for (double loss : losses) { + sum += Math.abs(loss); + } + double average = sum / 14; + return average; + } + + private void initializeMaps(Set symbols) { + for (String symbol : symbols) { + currentRSI.put(symbol, -1.0); + prevGains.put(symbol, new ArrayList()); + prevLosses.put(symbol, new ArrayList()); + previousCandles.put(symbol, new ArrayList()); + firstNewCandle.put(symbol, false); + twilioHold.put(symbol, false); + + } + } + + private double rsiFromDiff(double lastDiff, double previousGain, + double previousLoss, String symbol, boolean newCandle) { + double rsi = -1.0; + if (lastDiff < 0) { + double gain_average = previousGain * 13 / 14; + double loss_average = (Math.abs(previousLoss * 13 - lastDiff)) / 14; + if (newCandle) { + prevGains.get(symbol).add(gain_average); + prevLosses.get(symbol).add(loss_average); + } else { + prevGains.get(symbol).set(prevGains.get(symbol).size() - 1, + gain_average); + prevLosses.get(symbol).set(prevLosses.get(symbol).size() - 1, + loss_average); + } + double rs = gain_average / loss_average; + rsi = 100 - 100 / (1 + rs); + rsiVals.add(rsi); + + } else { + double gain_average = (previousGain * 13 + lastDiff) / 14; + double loss_average = (Math.abs(previousLoss * 13)) / 14; + if (newCandle) { + prevGains.get(symbol).add(gain_average); + prevLosses.get(symbol).add(loss_average); + } else { + prevGains.get(symbol).set(prevGains.get(symbol).size() - 1, + gain_average); + prevLosses.get(symbol).set(prevLosses.get(symbol).size() - 1, + loss_average); + } + double rs = gain_average / loss_average; + rsi = 100 - 100 / (1 + rs); + rsiVals.add(rsi); + } + return rsi; + } + + public Map getRSIMap() { + return currentRSI; + } + + public void setInterval(CandlestickInterval setInterval) { + interval = setInterval; + } + + public void setIntervalConversions() { + intervalConversion.put(CandlestickInterval.HALF_HOURLY, 30); + intervalConversion.put(CandlestickInterval.HOURLY, 60); + intervalConversion.put(CandlestickInterval.TWO_HOURLY, 120); + intervalConversion.put(CandlestickInterval.FOUR_HOURLY, 240); + intervalConversion.put(CandlestickInterval.EIGHT_HOURLY, 480); + intervalConversion.put(CandlestickInterval.TWELVE_HOURLY, 720); + intervalConversion.put(CandlestickInterval.DAILY, 1440); + + } + + private void updateFrontEnd(String message) { + if (username != null) { + RsiWebSocket.sendAutomaticradingUpdateMessage(username, message); + } + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/RSINotifier.java b/src/main/java/edu/brown/cs/term/trading/RSINotifier.java new file mode 100644 index 0000000..ccdfda6 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/RSINotifier.java @@ -0,0 +1,467 @@ +package edu.brown.cs.term.trading; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import com.binance.api.client.BinanceApiAsyncRestClient; +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.market.Candlestick; +import com.binance.api.client.domain.market.CandlestickInterval; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.twilio.Twilio; +import com.twilio.rest.api.v2010.account.Message; +import com.twilio.type.PhoneNumber; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.general.Tuple; +import websockets.RsiWebSocket; + +public class RSINotifier { + Map currentRSI = new HashMap(); + Map> prevGains + = new HashMap>(); + Map> prevLosses + = new HashMap>(); + Map> previousCandles + = new HashMap>(); + Map firstNewCandle = new HashMap(); + Map twilioHold = new HashMap(); + Map intervalConversion + = new HashMap(); + List rsiVals = new ArrayList(); + boolean finishedInitialCalculations = false; + String username = "js"; + CandlestickInterval interval = CandlestickInterval.HALF_HOURLY; + Set symbols = new HashSet(); + double rsiLimitHigh; + double rsiLimitLow; + List messages; + BinanceApiClientFactory fact; + BinanceApiRestClient client; + private String APIkey + = "qW9xUO8kNpHHnxb0dJjStRrzE7tN0oTlPCbah4IWdxkgyAa5vqJXzSME6IYlDhrp"; + private String secretKey + = "PXEisYYJhKd6T36nC8mH05AoZl4gcyytcz1Gd5Ybin1iv6GeS27rXySsaAn3Z5Mp"; + private String twilioKey = "AC740a42cac1fc2a9567eb53594736f458"; + private String twilioSecret = "9478ee8347691c3410cce9c8f00e0681"; + private static final Gson GSON = new Gson(); + + public RSINotifier(CandlestickInterval i, String user, Set symb, + String highLimit, String lowLimit) { + Twilio.init(twilioKey, twilioSecret); + username = user; + setPublicPrivateKey(username); + interval = i; + symbols = symb; + rsiLimitHigh = Double.valueOf(highLimit); + rsiLimitLow = Double.valueOf(lowLimit); + messages = new ArrayList(); + setIntervalConversions(); + } + + public void calculate() { + runCalculationsCurrent(symbols); + } + + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + this.username = username; + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + APIkey = keys.getFirstEntry(); + secretKey = keys.getSecondEntry(); + fact = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client = fact.newRestClient(); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + private void runCalculationsCurrent(Set symbols) { + initiateCalculation(symbols); + while (finishedInitialCalculations) { + continueCalculation(symbols); + } + } + + private void initiateCalculation(Set symbols) { + initializeMaps(symbols); + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = factory.newAsyncRestClient(); + messages = new ArrayList(); + for (String symbol : symbols) { + CompletableFuture time = new CompletableFuture(); + client.getServerTime(response -> { + time.complete(response.getServerTime()); + }); + long endTime = -1; + try { + endTime = time.get(); + } catch (Exception e) { + System.out.println("Time was not retrieved."); + } + long startTime + = endTime - (256 * intervalConversion.get(interval) * 60 * 1000); + CompletableFuture> candles + = new CompletableFuture>(); + List candlesticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 256, startTime, endTime, + (List response) -> { + candles.complete(response); + }); + try { + candlesticks = candles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + int count = 15; + while (currentRSI.get(symbol) == -1.0) { + // if previous gains and losses are populated, use wilder smoothing + if (count > 15) { + List prev_gains = prevGains.get(symbol); + double previousGain = prev_gains.get(prev_gains.size() - 1); + List prev_loss = prevLosses.get(symbol); + double previousLoss = prev_loss.get(prev_loss.size() - 1); + + double lastDiff = Double + .parseDouble(candlesticks.get(count).getClose()) + - Double.parseDouble(candlesticks.get(count - 1).getClose()); + + double rsi = rsiFromDiff(lastDiff, previousGain, previousLoss, + symbol, true); + count++; + + } else { + List firstFifteen = candlesticks.subList(0, 15); + List differences = getDifferences(firstFifteen); + List gainsClipped = clipGains(differences); + List lossesClipped = clipLoss(differences); + + double gain_average = averageGains(gainsClipped); + double loss_average = averageLoss(lossesClipped); + prevGains.get(symbol).add(gain_average); + prevLosses.get(symbol).add(loss_average); + double rs = gain_average / loss_average; + double rsi = 100 - 100 / (1 + rs); + rsiVals.add(rsi); + count++; + } + if (count == 256) { + double lastRSI = rsiVals.get(rsiVals.size() - 1); + currentRSI.replace(symbol, lastRSI); + previousCandles.get(symbol) + .add(candlesticks.get(candlesticks.size() - 1)); + String message + = symbol + " Current RSI: " + Double.toString(lastRSI); + System.out.println(message); + messages.add(message); + RsiWebSocket.sendRSIUpdateMessage(messages, username); + finishedInitialCalculations = true; + } + } + } + } + + private void continueCalculation(Set symbols) { + BinanceApiClientFactory factory + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = factory.newAsyncRestClient(); + messages = new ArrayList(); + for (String symbol : symbols) { + List previous = previousCandles.get(symbol); + Candlestick previousC = previous.get(previous.size() - 1); + CompletableFuture time = new CompletableFuture(); + client.getServerTime(response -> { + time.complete(response.getServerTime()); + }); + long endTime = -1; + try { + endTime = time.get(); + } catch (Exception e) { + System.out.println("Time was not retrieved."); + } + long startTime + = endTime - (4 * intervalConversion.get(interval) * 60 * 1000); + CompletableFuture> candles + = new CompletableFuture>(); + List candlesticks = new ArrayList(); + client.getCandlestickBars(symbol, interval, 4, startTime, endTime, + (List response) -> { + candles.complete(response); + }); + try { + candlesticks = candles.get(); + } catch (Exception e) { + System.out.println("Error getting candlesticks."); + } + if (firstNewCandle.get(symbol) == false) { + List prev_gains = prevGains.get(symbol); + double prev_gain = prev_gains.get(prev_gains.size() - 2); + List prev_losses = prevLosses.get(symbol); + double prev_loss = prev_losses.get(prev_losses.size() - 2); + double lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 1).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()); + + double rsi + = rsiFromDiff(lastDiff, prev_gain, prev_loss, symbol, false); + String rsiMessage = symbol + " Current RSI No New Candle Yet: " + + Double.toString(rsi); + System.out.println(rsiMessage); + messages.add(rsiMessage); + currentRSI.replace(symbol, rsi); + if (currentRSI.get(symbol) > rsiLimitHigh + && twilioHold.get(symbol) == false) { + Message message + = Message.creator(new PhoneNumber("+13185723217"), + new PhoneNumber("+13186159356"), + symbol + " RSI is greater than " + rsiLimitHigh + "!").create(); + twilioHold.replace(symbol, true); + } else if (currentRSI.get(symbol) < rsiLimitLow + && twilioHold.get(symbol) == false) { + Message message + = Message + .creator(new PhoneNumber("+13185723217"), + new PhoneNumber("+13186159356"), + symbol + " RSI is less than " + rsiLimitLow) + .create(); + twilioHold.replace(symbol, true); + } + if (!candlesticks.get(candlesticks.size() - 1).getOpenTime() + .equals(previousCandles.get(symbol) + .get(previousCandles.get(symbol).size() - 1) + .getOpenTime())) { + firstNewCandle.replace(symbol, true); + + } + } else { + if (!candlesticks.get(candlesticks.size() - 1).getOpenTime() + .equals(previousCandles.get(symbol) + .get(previousCandles.get(symbol).size() - 1) + .getOpenTime())) { + previousCandles.get(symbol) + .add(candlesticks.get(candlesticks.size() - 1)); + + double prev_gain = prevGains.get(symbol) + .get(prevGains.get(symbol).size() - 2); + double prev_loss = prevLosses.get(symbol) + .get(prevGains.get(symbol).size() - 2); + double lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 3).getClose()); + + double rsi + = rsiFromDiff(lastDiff, prev_gain, prev_loss, symbol, false); + currentRSI.replace(symbol, rsi); + String messageRSI = symbol + " Current RSI Old Candle Final: " + + Double.toString(rsi); + System.out.println(messageRSI); + messages.add(messageRSI); + + double prev_gain_new = prevGains.get(symbol) + .get(prevGains.get(symbol).size() - 1); + double prev_loss_new = prevLosses.get(symbol) + .get(prevLosses.get(symbol).size() - 1); + + lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 1).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()); + + rsi = rsiFromDiff(lastDiff, prev_gain_new, prev_loss_new, symbol, + true); + currentRSI.replace(symbol, rsi); + messageRSI = symbol + " Current RSI New Candle: " + + Double.toString(rsi); + System.out.println(messageRSI); + messages.add(messageRSI); + } else { + double prev_gain = prevGains.get(symbol) + .get(prevGains.get(symbol).size() - 2); + double prev_loss = prevLosses.get(symbol) + .get(prevLosses.get(symbol).size() - 2); + double lastDiff = Double.parseDouble( + candlesticks.get(candlesticks.size() - 1).getClose()) + - Double.parseDouble( + candlesticks.get(candlesticks.size() - 2).getClose()); + + double rsi + = rsiFromDiff(lastDiff, prev_gain, prev_loss, symbol, false); + currentRSI.replace(symbol, rsi); + if (currentRSI.get(symbol) > rsiLimitHigh + && twilioHold.get(symbol) == false) { + Message message = Message + .creator(new PhoneNumber("+13185723217"), + new PhoneNumber("+13186159356"), + symbol + " RSI is greater than " + rsiLimitHigh) + .create(); + twilioHold.replace(symbol, true); + } else if (currentRSI.get(symbol) < rsiLimitLow + && twilioHold.get(symbol) == false) { + Message message + = Message + .creator(new PhoneNumber("+13185723217"), + new PhoneNumber("+13186159356"), + symbol + " RSI is less than " + rsiLimitLow) + .create(); + twilioHold.replace(symbol, true); + } + String messageRSI + = symbol + " Current RSI: " + Double.toString(rsi); + System.out.println(messageRSI); + messages.add(messageRSI); + + } + } + } + + RsiWebSocket.sendRSIUpdateMessage(messages, username); + + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + System.out.println("Thread interrupted"); + } + } + + private List getDifferences(List candles) { + List diffs = new ArrayList(); + for (int i = 1; i < candles.size(); i++) { + double diff = Double.parseDouble(candles.get(i).getClose()) + - Double.parseDouble(candles.get(i - 1).getClose()); + diffs.add(diff); + } + return diffs; + } + + private List clipGains(List differences) { + List gains = differences; + for (double gain : gains) { + if (gain < 0) { + gain = 0; + } + } + return gains; + } + + private List clipLoss(List differences) { + List losses = differences; + for (double loss : losses) { + if (loss > 0) { + loss = 0; + } + } + return losses; + } + + private double averageGains(List gains) { + double sum = 0; + for (double gain : gains) { + sum += gain; + } + double average = sum / 14; + return average; + } + + private double averageLoss(List losses) { + double sum = 0; + for (double loss : losses) { + sum += Math.abs(loss); + } + double average = sum / 14; + return average; + } + + private void initializeMaps(Set symbols) { + for (String symbol : symbols) { + currentRSI.put(symbol, -1.0); + prevGains.put(symbol, new ArrayList()); + prevLosses.put(symbol, new ArrayList()); + previousCandles.put(symbol, new ArrayList()); + firstNewCandle.put(symbol, false); + twilioHold.put(symbol, false); + } + } + + private double rsiFromDiff(double lastDiff, double previousGain, + double previousLoss, String symbol, boolean newCandle) { + double rsi = -1.0; + if (lastDiff < 0) { + double gain_average = previousGain * 13 / 14; + double loss_average = (Math.abs(previousLoss * 13 - lastDiff)) / 14; + if (newCandle) { + prevGains.get(symbol).add(gain_average); + prevLosses.get(symbol).add(loss_average); + } else { + prevGains.get(symbol).set(prevGains.get(symbol).size() - 1, + gain_average); + prevLosses.get(symbol).set(prevLosses.get(symbol).size() - 1, + loss_average); + } + double rs = gain_average / loss_average; + rsi = 100 - 100 / (1 + rs); + rsiVals.add(rsi); + + } else { + double gain_average = (previousGain * 13 + lastDiff) / 14; + double loss_average = (Math.abs(previousLoss * 13)) / 14; + if (newCandle) { + prevGains.get(symbol).add(gain_average); + prevLosses.get(symbol).add(loss_average); + } else { + prevGains.get(symbol).set(prevGains.get(symbol).size() - 1, + gain_average); + prevLosses.get(symbol).set(prevLosses.get(symbol).size() - 1, + loss_average); + } + double rs = gain_average / loss_average; + rsi = 100 - 100 / (1 + rs); + rsiVals.add(rsi); + } + return rsi; + } + + public Map getRSIMap() { + return currentRSI; + } + + public void setInterval(CandlestickInterval setInterval) { + interval = setInterval; + } + + public void setRSIHigh(double high) { + rsiLimitHigh = high; + } + + public double getRSIHigh() { + return rsiLimitHigh; + } + + public void setRSILow(double low) { + rsiLimitLow = low; + } + + public double getRSILow() { + return rsiLimitLow; + } + + public void setIntervalConversions() { + intervalConversion.put(CandlestickInterval.HALF_HOURLY, 30); + intervalConversion.put(CandlestickInterval.HOURLY, 60); + intervalConversion.put(CandlestickInterval.TWO_HOURLY, 120); + intervalConversion.put(CandlestickInterval.FOUR_HOURLY, 240); + intervalConversion.put(CandlestickInterval.EIGHT_HOURLY, 480); + intervalConversion.put(CandlestickInterval.TWELVE_HOURLY, 720); + intervalConversion.put(CandlestickInterval.DAILY, 1440); + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/Symbols.java b/src/main/java/edu/brown/cs/term/trading/Symbols.java new file mode 100644 index 0000000..7ddc425 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/Symbols.java @@ -0,0 +1,36 @@ +package edu.brown.cs.term.trading; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.market.TickerPrice; + +public class Symbols { + + public static Set getAllSymbols() { + String APIkey + = "qW9xUO8kNpHHnxb0dJjStRrzE7tN0oTlPCbah4IWdxkgyAa5vqJXzSME6IYlDhrp"; + String secretKey + = "PXEisYYJhKd6T36nC8mH05AoZl4gcyytcz1Gd5Ybin1iv6GeS27rXySsaAn3Z5Mp"; + BinanceApiClientFactory fact + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiRestClient client = fact.newRestClient(); + List tickers = client.getAllPrices(); + return convertTickersToSymbols(tickers); + } + + private static Set convertTickersToSymbols( + List tickers) { + if (tickers == null) { + return new HashSet<>(); + } + Set symbols = new HashSet<>(); + for (TickerPrice onePrice : tickers) { + symbols.add(onePrice.getSymbol()); + } + return symbols; + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/TradingAlgorithm.java b/src/main/java/edu/brown/cs/term/trading/TradingAlgorithm.java new file mode 100644 index 0000000..7740999 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/TradingAlgorithm.java @@ -0,0 +1,233 @@ +package edu.brown.cs.term.trading; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.market.Candlestick; +import com.binance.api.client.domain.market.CandlestickInterval; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.general.Tuple; +import edu.brown.cs.term.thread.BuyThread; +import edu.brown.cs.term.thread.MaThread; +import edu.brown.cs.term.thread.RsiThread; +import edu.brown.cs.term.thread.SellThread; +import websockets.RsiWebSocket; + +public class TradingAlgorithm { + + RsiThread rsi2; + MaThread ma2; + private String APIkey + = "qW9xUO8kNpHHnxb0dJjStRrzE7tN0oTlPCbah4IWdxkgyAa5vqJXzSME6IYlDhrp"; + private String secretKey + = "PXEisYYJhKd6T36nC8mH05AoZl4gcyytcz1Gd5Ybin1iv6GeS27rXySsaAn3Z5Mp"; + private boolean tradeNotFound = true; + Map foundMap = new HashMap(); + BinanceApiClientFactory fact3; + BinanceApiRestClient client3; + Set symbols = new HashSet(); + double rsiLimitHigh = 85.0; + double rsiLimitLow = 15.0; + double multiplier = 2.0; + double percentGain = 10.0; + double fraction = 4.0; + String username = "js"; + String message = ""; + CandlestickInterval interval = CandlestickInterval.HALF_HOURLY; + FullTradeSell fts = null; + FullTradeBuy ftb = null; + private Gson GSON; + + public TradingAlgorithm(CandlestickInterval i, String user, + Set symb, String upper, String lower, String mult, + String frac) { + interval = i; + username = user; + GSON = new Gson(); + setPublicPrivateKey(username); + symbols = symb; + rsiLimitHigh = Double.valueOf(upper); + rsiLimitLow = Double.valueOf(lower); + multiplier = Double.valueOf(mult); + fraction = Double.valueOf(frac); + fts = new FullTradeSell(username); + ftb = new FullTradeBuy(username); + rsi2 = new RsiThread(username, "TaRsiThread", symbols); + ma2 = new MaThread(username, "TaMaThread", symbols, mult); + initializeMaps(symbols); + + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + + } + while (true) { + System.out.println(rsi2.getRSIMap()); + if (rsi2 != null && ma2 != null && rsi2.getRSIMap() != null + && ma2.getMAMap() != null) { + System.out.println("true"); + findTrade(); + } else { + System.out.println("false"); + } + } + + } + + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + this.username = username; + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + this.APIkey = keys.getFirstEntry(); + this.secretKey = keys.getSecondEntry(); + fact3 = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client3 = fact3.newRestClient(); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + public void findTrade() { + StringBuilder sb = new StringBuilder(); + sb.append("Looking for trade in these markets: "); + for (String symbol : symbols) { + sb.append(symbol + ", "); + } + sb.deleteCharAt(sb.length() - 2); + sb.append(". Time is: " + java.time.LocalTime.now()); + message = sb.toString(); + System.out.println(message); + this.updateFrontEnd(message); + + for (String symbol : symbols) { + if (!foundMap.get(symbol)) { + long endTime = client3.getServerTime(); + long startTime = endTime - (3600 * 1000); + List candlesticks = client3.getCandlestickBars(symbol, + CandlestickInterval.HALF_HOURLY, 2, startTime, endTime); + double upperBand = ma2.getMAMap().get(symbol) + + (multiplier * ma2.getSDMap().get(symbol)); + double lowerBand = ma2.getMAMap().get(symbol) + - (multiplier * ma2.getSDMap().get(symbol)); + double currentRSI = rsi2.getRSIMap().get(symbol); + if (currentRSI > rsiLimitHigh && Double.parseDouble(candlesticks + .get(candlesticks.size() - 1).getClose()) > upperBand) { + message = "RSI and MA upper limit hit. Making a trade on " + + symbol.substring(0, 3) + ". Time is: " + + java.time.LocalTime.now(); + System.out.println(message); + this.updateFrontEnd(message); + + String lastPrice + = client3.get24HrPriceStatistics(symbol).getLastPrice(); + double sellPrice = Double.valueOf(lastPrice); + double buyPrice = sellPrice - (sellPrice * percentGain); + String finalBuyPrice = sellToBuyPrice(lastPrice, percentGain); + String finalStopPrice = sellToStopPrice(lastPrice, percentGain); + String quantity = client3.getAccount() + .getAssetBalance(symbol.substring(0, 3)).getFree(); + double quant = Double.parseDouble(quantity); + double quantToTrade = quant / fraction; + BigDecimal quantBD = new BigDecimal(quantToTrade).setScale(2, + RoundingMode.HALF_DOWN); + SellThread st + = new SellThread("TaSellThread", username, symbol, lastPrice, + finalBuyPrice, finalStopPrice, quantBD.toPlainString()); + foundMap.replace(symbol, true); + } else if (currentRSI < rsiLimitLow + && Double.parseDouble(candlesticks.get(candlesticks.size() - 1) + .getClose()) < lowerBand) { + message = "RSI and MA lower limits hit. Making a trade on " + + symbol.substring(0, 3) + ". Time is: " + + java.time.LocalTime.now(); + System.out.println(message); + this.updateFrontEnd(message); + String lastPrice + = client3.get24HrPriceStatistics(symbol).getLastPrice(); + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double buyPrice = Double.valueOf(lastPrice); + String finalSellPrice = buyToSellPrice(lastPrice, percentGain); + String finalStopPrice = buyToStopPrice(lastPrice, percentGain); + String quantity + = client3.getAccount().getAssetBalance(symbol).getFree(); + double quant = Double.parseDouble(quantity); + double quantToTrade = quant / fraction; + BigDecimal quantBD = new BigDecimal(quantToTrade).setScale(2, + RoundingMode.HALF_DOWN); + BuyThread bt + = new BuyThread(username, "TaBuyThread", symbol, lastPrice, + finalSellPrice, finalStopPrice, quantBD.toPlainString()); + foundMap.replace(symbol, true); + } + } + } + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + + } + + } + + private void initializeMaps(Set symbols) { + for (String symbol : symbols) { + foundMap.put(symbol, false); + } + } + + private String sellToBuyPrice(String lastPrice, double percentGain) { + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double sellPrice = Double.valueOf(lastPrice); + double buyPrice = sellPrice - (sellPrice * percentGain); + BigDecimal bp = new BigDecimal(buyPrice).setScale(decimalLength, + RoundingMode.HALF_DOWN); + return bp.toPlainString(); + } + + private String sellToStopPrice(String lastPrice, double percentGain) { + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double sellPrice = Double.valueOf(lastPrice); + double stopPrice = sellPrice * (1.00 + (percentGain / 2.00)); + BigDecimal bp = new BigDecimal(stopPrice).setScale(decimalLength, + RoundingMode.HALF_UP); + return bp.toPlainString(); + } + + private String buyToSellPrice(String lastPrice, double percentGain) { + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double buyPrice = Double.valueOf(lastPrice); + double sellPrice = buyPrice * (1.00 + percentGain); + BigDecimal bp = new BigDecimal(sellPrice).setScale(decimalLength, + RoundingMode.HALF_UP); + return bp.toPlainString(); + } + + private String buyToStopPrice(String lastPrice, double percentGain) { + String[] splits = lastPrice.split("\\."); + int decimalLength = splits[1].length(); + double buyPrice = Double.valueOf(lastPrice); + double stopPrice = buyPrice - (buyPrice * (percentGain / 2.0)); + BigDecimal sp = new BigDecimal(stopPrice).setScale(decimalLength, + RoundingMode.HALF_DOWN); + return sp.toPlainString(); + } + + private void updateFrontEnd(String message) { + RsiWebSocket.sendAutomaticradingUpdateMessage(username, message); + } +} diff --git a/src/main/java/edu/brown/cs/term/trading/TrailingStop.java b/src/main/java/edu/brown/cs/term/trading/TrailingStop.java new file mode 100644 index 0000000..c4fcc88 --- /dev/null +++ b/src/main/java/edu/brown/cs/term/trading/TrailingStop.java @@ -0,0 +1,135 @@ +package edu.brown.cs.term.trading; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import com.binance.api.client.BinanceApiAsyncRestClient; +import com.binance.api.client.BinanceApiClientFactory; +import com.binance.api.client.BinanceApiRestClient; +import com.binance.api.client.domain.market.CandlestickInterval; +import com.binance.api.client.domain.market.TickerStatistics; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.general.Tuple; +import edu.brown.cs.term.thread.SellThread; + +public class TrailingStop { + private String APIkey = + "qW9xUO8kNpHHnxb0dJjStRrzE7tN0oTlPCbah4IWdxkgyAa5vqJXzSME6IYlDhrp"; + private String secretKey = + "PXEisYYJhKd6T36nC8mH05AoZl4gcyytcz1Gd5Ybin1iv6GeS27rXySsaAn3Z5Mp"; + private Map priceMap = new HashMap(); + private Map executedMap + = new HashMap(); + private double stopPercent = 0.10; + private String username; + private Set symbols; + BinanceApiClientFactory fact2; + BinanceApiRestClient client2; + String message = ""; + private Gson GSON; + + public TrailingStop(String user, + Set symb, double percent) { + username = user; + symbols = symb; + stopPercent = percent; + setPublicPrivateKey(username); + initializeMaps(symbols); + } + + public String setPublicPrivateKey(String username) { + CrypthubUser user = new CrypthubUser(); + this.username = username; + Tuple keys = user.getPublicPrivateKey(username); + if (keys.equals(new Tuple<>("", ""))) { + return GSON.toJson(ImmutableMap.of("success", false)); + } + this.APIkey = keys.getFirstEntry(); + this.secretKey = keys.getSecondEntry(); + fact2 = BinanceApiClientFactory.newInstance(APIkey, secretKey); + client2 = fact2.newRestClient(); + return GSON.toJson(ImmutableMap.of("success", true)); + } + + public void calculate() { + while(true) { + monitorPrice(); + } + } + + public void monitorPrice() { + BinanceApiClientFactory fact + = BinanceApiClientFactory.newInstance(APIkey, secretKey); + BinanceApiAsyncRestClient client = fact.newAsyncRestClient(); + StringBuilder sb = new StringBuilder(); + sb.append("Checking for trailing stop for these assets: "); + for (String symbol : symbols) { + sb.append(symbol + ", "); + } + sb.substring(0, sb.length()-2); + sb.append(". Time is " + java.time.LocalTime.now()); + message = sb.toString(); + System.out.println(message); + for (String symbol : symbols) { + CompletableFuture ticker + = new CompletableFuture(); + client.get24HrPriceStatistics(symbol, + (TickerStatistics response) -> { + ticker.complete(response); + }); + TickerStatistics ts = null; + try { + ts = ticker.get(); + } catch (Exception e) { + System.out.println("Error getting ticker"); + } + String price = ts.getLastPrice(); + Double priceVal = Double.parseDouble(price); + if (priceVal >= priceMap.get(symbol)) { + priceMap.replace(symbol, priceVal); + } else { + double decrease = priceMap.get(symbol) - priceVal; + double percentLoss = decrease / priceMap.get(symbol); + if (percentLoss > stopPercent && !executedMap.get(symbol)) { + // execute stop loss order with fulltrade function; + message = "Stop loss condition found for " + symbol + + ". Executing stop order. Time is: " + + java.time.LocalTime.now(); + System.out.println(message); + String[] splits = price.split("\\."); + int decimalLength = splits[1].length(); + double valBuy = priceVal - (priceVal * stopPercent); + double valStop = priceVal * (1.0 + stopPercent/2.0); + BigDecimal bdStop = new BigDecimal(valStop) + .setScale(decimalLength, RoundingMode.HALF_UP); + BigDecimal bdBuy = new BigDecimal(valBuy) + .setScale(decimalLength, RoundingMode.HALF_UP); + String quantity = client2.getAccount().getAssetBalance(symbol.substring(0, 3)).getFree(); + SellThread st = new SellThread("TsSellThread", username, symbol, + price, bdBuy.toPlainString(), + bdStop.toPlainString(), quantity); + } + } + } + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + System.out.println("Thread interrupted"); + } + } + + private void initializeMaps(Set symbols) { + for (String symbol : symbols) { + priceMap.put(symbol, -1.0); + executedMap.put(symbol, false); + } + } + +} diff --git a/src/main/java/websockets/RsiWebSocket.java b/src/main/java/websockets/RsiWebSocket.java new file mode 100644 index 0000000..017ac93 --- /dev/null +++ b/src/main/java/websockets/RsiWebSocket.java @@ -0,0 +1,179 @@ +package websockets; + +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import edu.brown.cs.term.database.CrypthubUser; +import edu.brown.cs.term.thread.RSINotifierThread; +import edu.brown.cs.term.thread.RsiThread; + +@WebSocket +public class RsiWebSocket { + private static final Gson GSON = new Gson(); + private static final Queue sessions + = new ConcurrentLinkedQueue<>(); + private static final Map usernames + = new ConcurrentHashMap<>(); + private RsiThread rsi; + + public static enum MESSAGE_TYPE { + CONNECT, UPDATE_RSI, UPDATE_TRADE, SET_USERNAME, START_RSI, WALLET_INFO, UPDATE_AUTOMATIC + } + + @OnWebSocketConnect + public void connected(Session session) { + sessions.add(session); + JsonObject js = new JsonObject(); + js.addProperty("type", MESSAGE_TYPE.CONNECT.ordinal()); + String sendThis = GSON.toJson(js); + + try { + session.getRemote().sendString(sendThis); + } catch (IOException e) { + System.out.println("ERROR: " + e.getMessage()); + } + + } + + @OnWebSocketClose + public void closed(Session session, int statusCode, String reason) { + if (sessions.contains(session)) { + sessions.remove(session); + session.close(statusCode, reason); + } + } + + public static void sendRSIUpdateMessage(List messages, + String username) { + System.out.println("SEND RSI UPDATE"); + JsonObject updateMessage = new JsonObject(); + updateMessage.addProperty("type", MESSAGE_TYPE.UPDATE_RSI.ordinal()); + + JsonObject payload = new JsonObject(); + JsonArray messageArray = new JsonArray(); + for (String message : messages) { + messageArray.add(message); + } + + payload.add("message", messageArray); + + updateMessage.add("payload", payload); + + for (Session currSession : sessions) { + try { + currSession.getRemote().sendString(GSON.toJson(updateMessage)); + } catch (IOException e) { + System.out.println("ERROR: " + e.getMessage()); + } + } + + } + + public static void sendWalletUpdate(double walletValue, + String username) { + JsonObject updateMessage = new JsonObject(); + updateMessage.addProperty("type", MESSAGE_TYPE.WALLET_INFO.ordinal()); + + JsonObject payload = new JsonObject(); + + payload.addProperty("amount", walletValue); + + updateMessage.add("payload", payload); + + for (Session currSession : sessions) { + try { + currSession.getRemote().sendString(GSON.toJson(updateMessage)); + } catch (IOException e) { + System.out.println("ERROR: " + e.getMessage()); + } + } + } + + public static void sendAutomaticradingUpdateMessage(String username, + String message) { + JsonObject updateMessage = new JsonObject(); + updateMessage.addProperty("type", + MESSAGE_TYPE.UPDATE_AUTOMATIC.ordinal()); + + JsonObject payload = new JsonObject(); + payload.addProperty("message", message); + + updateMessage.add("payload", payload); + + for (Session currSession : sessions) { + try { + currSession.getRemote().sendString(GSON.toJson(updateMessage)); + } catch (IOException e) { + System.out.println("ERROR: " + e.getMessage()); + } + + } + } + + public static void sendCustomTradingUpdateMessage(String username, + Long orderId, String message) { + JsonObject updateMessage = new JsonObject(); + updateMessage.addProperty("type", MESSAGE_TYPE.UPDATE_TRADE.ordinal()); + + JsonObject payload = new JsonObject(); + payload.addProperty("message", message); + payload.addProperty("orderId", orderId); + + updateMessage.add("payload", payload); + + for (Session currSession : sessions) { + try { + currSession.getRemote().sendString(GSON.toJson(updateMessage)); + } catch (IOException e) { + System.out.println("ERROR: " + e.getMessage()); + } + + } + } + + @OnWebSocketMessage + public void message(Session session, String message) throws IOException { + JsonObject received = GSON.fromJson(message, JsonObject.class); + int messageType = received.get("type").getAsInt(); + JsonObject receivedPayload; + Set symbols = new HashSet(); + String username; + + switch (messageType) { + case 3: + receivedPayload = received.get("payload").getAsJsonObject(); + username = receivedPayload.get("username").getAsString(); + usernames.put(session, username); + break; + + case 4: + receivedPayload = received.get("payload").getAsJsonObject(); + username = receivedPayload.get("username").getAsString(); + + CrypthubUser user = new CrypthubUser(); + symbols = user.symbolsInWallet(username); + + System.out.println(symbols.toString()); + new RSINotifierThread(username, "hello", symbols, "50", "50"); + + break; + } + + } +} diff --git a/src/main/resources/.DS_Store b/src/main/resources/.DS_Store new file mode 100644 index 0000000..beb74f9 Binary files /dev/null and b/src/main/resources/.DS_Store differ diff --git a/src/main/resources/spark/.DS_Store b/src/main/resources/spark/.DS_Store new file mode 100644 index 0000000..7e319d2 Binary files /dev/null and b/src/main/resources/spark/.DS_Store differ diff --git a/src/main/resources/spark/template/.DS_Store b/src/main/resources/spark/template/.DS_Store new file mode 100644 index 0000000..86f4984 Binary files /dev/null and b/src/main/resources/spark/template/.DS_Store differ diff --git a/src/main/resources/spark/template/freemarker/.DS_Store b/src/main/resources/spark/template/freemarker/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/src/main/resources/spark/template/freemarker/.DS_Store differ diff --git a/src/main/resources/spark/template/freemarker/about.ftl b/src/main/resources/spark/template/freemarker/about.ftl new file mode 100644 index 0000000..4486d94 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/about.ftl @@ -0,0 +1,154 @@ + + + +<#include "head.ftl"> +<@head title = "About Page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "About Us"/> + + +
+
+
+
+
+ + + +
+
+
+

What is Crypthub?

+

Crypthub is a consumer based cryptocurrency trading software. Using algorithmic trading strategies Crypthub safely and efficiently invests your capital into the cryptocurrency market using the Binance API.

+ Get Started +
+
+ + +
+
+ + +<#include "newsletter.ftl"> + + +
+
+
+

Meet Our Team

+

Our experts can always help you with any of your questions!

+
+
+
+ + +
+ +
+
+

Pavlo Lyalyutskyy

+ Algorithmic Consultant +
+
+ + + +
+
+
+
+

Pavlo Lyalyutskyy

+ Algorithmic Consultant +
+

"I built my first depth first search at age 3, and it only took 3 lines of code."

+
+
+ +
+
+
+

Sean Nathan

+ Cryptocurrency Expert +
+
+ + + +
+
+
+
+

Sean Nathan

+ Cryptocurrency Expert +
+

Born and raised in the gritty south, Sean Nathan spent his childhood fighting tooth and nail to become one of the best traders this side of the Mississippi.

+
+
+ + +
+
+
+

Christine Wang

+ Head of Design +
+
+ + + +
+
+
+
+

Christine Wang

+ Head of Design +
+

"while (! (succeed = try()));"

+
+
+ +
+
+
+

Akhil Trehan

+ Product Manager +
+
+ + + +
+
+
+
+

Akhil Trehan

+ Product Manager +
+

"If all else fails, try text-align: center.g"

+
+
+
+
+ + + +<#include "footer.ftl"> + + + +<#include "scripts.ftl"> + + + diff --git a/src/main/resources/spark/template/freemarker/contactUs.ftl b/src/main/resources/spark/template/freemarker/contactUs.ftl new file mode 100644 index 0000000..bc493ad --- /dev/null +++ b/src/main/resources/spark/template/freemarker/contactUs.ftl @@ -0,0 +1,112 @@ + + + +<#include "head.ftl"> +<@head title = "Contact Us Page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Contact Us"/> + + +
+
+
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+
Way to Contact:
+
+ + + +
+ + +
+
+
+
+ +
+ +
+ + + + + +
+ +
+ + +
+
+
+ + +<#include "newsletter.ftl"> + +<#include "footer.ftl"> + + + +<#include "scripts.ftl"> + + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/film.ftl b/src/main/resources/spark/template/freemarker/film.ftl new file mode 100644 index 0000000..395688d --- /dev/null +++ b/src/main/resources/spark/template/freemarker/film.ftl @@ -0,0 +1,22 @@ +<#assign content> + +
+

Film: ${filmName}

+
+ +

Actors in ${filmName}:

+ +
+ +
+ + +<#include "bacon.ftl"> + + diff --git a/src/main/resources/spark/template/freemarker/footer.ftl b/src/main/resources/spark/template/freemarker/footer.ftl new file mode 100644 index 0000000..007319c --- /dev/null +++ b/src/main/resources/spark/template/freemarker/footer.ftl @@ -0,0 +1,65 @@ + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/head.ftl b/src/main/resources/spark/template/freemarker/head.ftl new file mode 100644 index 0000000..d175d23 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/head.ftl @@ -0,0 +1,49 @@ + + +<#macro head title = "Crypthub"> + + + + ${title} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/spark/template/freemarker/header.ftl b/src/main/resources/spark/template/freemarker/header.ftl new file mode 100644 index 0000000..8f3aa2c --- /dev/null +++ b/src/main/resources/spark/template/freemarker/header.ftl @@ -0,0 +1,35 @@ + + + + +<#macro header showLogo = "true"> + + +
+
+
+
+ <#if showLogo == "true"> + + + + Log In + +
+
+ + + + + + diff --git a/src/main/resources/spark/template/freemarker/index.ftl b/src/main/resources/spark/template/freemarker/index.ftl new file mode 100644 index 0000000..288ea07 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/index.ftl @@ -0,0 +1,287 @@ + + + +<#include "head.ftl"> +<@head title = "Home page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header showLogo = "true"/> + + +
+
+
+
+
+

Optimized Investing and Algorithmic Strategies to +
+
+
+

+ +

Utilize Crypthub's specialized cryptocurrency trading strategies.

+
+ Sign up now +
+
+
+ +
+
+
+
+ + + +
+
+
+

Our Features

+

Bitcoin is the simplest way to exchange money at very low cost.

+
+ +
+ +
+ +
+

Mobile Text Notification

+

Crypthub employs instant RSI text notifications in order to update you whenever, about the status of your investments.

+
+
+ +
+ +
+

Safe & Secure

+

Crypthub prioritizes the security of your money. We use constant key validation in order to legitimize trades.

+
+
+ +
+ +
+

Wallet

+

Crypthub's API connection with Binance allows secure cryptocurrency wallet transactions.

+
+
+ +
+ +
+

Experts Support

+

Crypthub's experts are constantly reviewing market information to provide you with optimal algorithms and support for your trades.

+
+
+ +
+ +
+

Instant Exchange

+

User trades are instantly processed using the Binance API in order to keep the user's financial information relevant.

+
+
+ +
+ +
+

Recuring Buys

+

Cyrpthub utilizes asynchronous algorithm capabilities when using the Binance API to constantly trade your capital. Cyrpthub stays on top of the market and your trades.

+
+
+
+
+
+ + +
+
+
+
+
+ +
+ +
+

Got you Wherever you are.

+
    +
  • +

    By leveraging Binance's API, our trading platform allows you to make trades from anywhere in the world.

  • +
  • +

    Even as you move, your trades won't! We'll keep them safe and running, while you live your life.

  • +
  • +

    We can notify you by text when the RSI has reached a favorable point, from wherever you are, so long as you have a valid number.

  • +
+
+
+
+
+ map +
+ + + + Hey there!
We absolutely love crypthub!
+
+
+
+
+ + + + Hi, Join us now!!
Crythub has made day trading so much easier
+
+
+
+
+ + + + Whats up?!
The manual trades have saved me so much time.
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ +
+ +
+

Frequently Asked Questions

+

We know this whole crypto trading thing can be scary at first. We're here to try to make it as simple as possible.

+
+
+
+ + +
+
+ +
How do we conduct the trades?
+
+

We utilize the Binance API to conduct buy and sell trades. This is why users who wish to use + our platform will have to submit their public and private keys.

+
+ +
Is my information safe?
+
+

Yes! We store your password in a safe place and never reveal your secret or public API keys.

+
+ +
When can I start trading?
+
+

After you make and verify your account. In addition, once you submit valid public and private API keys for binance you can begin trading.

+
+ +
How can I track my trade?
+
+

Please visit the trades page when logged in and it will show you the manual trades and the automatic trade that is running.

+
+ +
Where should I start?
+
+

Read up on our adivce pages on buying and selling crypto and see examples of manual trades before conducting one of your own!

+
+
+
+
+ +
+ +
+
+
+
+ + + + + + +<#include "footer.ftl"> + + + + +<#include "scripts.ftl"> + + + + + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/login.ftl b/src/main/resources/spark/template/freemarker/login.ftl new file mode 100644 index 0000000..efeefb9 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/login.ftl @@ -0,0 +1,104 @@ + + + +<#include "head.ftl"> +<@head title = "Log in Page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Log in"/> + + + + + +<#include "newsletter.ftl"> + +<#include "footer.ftl"> + + +<#include "scripts.ftl"> + + + + + + diff --git a/src/main/resources/spark/template/freemarker/news.ftl b/src/main/resources/spark/template/freemarker/news.ftl new file mode 100644 index 0000000..41717d7 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/news.ftl @@ -0,0 +1,465 @@ + + + +<#include "head.ftl"> +<@head title = "News Page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + + +
+
+
+
+

Investing Using Algorithmic Optimization

+

Utilize Crypthub's specialized cryptocurrency trading strategies.

+
+ + +
+
+
+ +
+
+
+
+ + + + +
+
+
+
+

What is Bitcoin

+
Bitcoin is an innovative payment network and a new kind of money.
+

Bitcoin is one of the most important inventions in all of human history. For the first time ever, anyone can send or receive any amount of money with anyone else, anywhere on the planet, conveniently and without restriction. It’s the dawn of a better, more free world.

+ Get Started +
+
+
+ +
+
+
+ + + + +
+
+
+

Our Features

+

Bitcoin is the simplest way to exchange money at very low cost.

+
+
+ +
+ +
+

Mobile Apps

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+ Readmore +
+
+ +
+ +
+

Safe & Secure

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+ Readmore +
+
+ +
+ +
+

Wallet

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+ Readmore +
+
+ +
+ +
+

Experts Support

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+ Readmore +
+
+ +
+ +
+

Instant Exchange

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+ Readmore +
+
+ +
+ +
+

Recuring Buys

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+ Readmore +
+
+
+
+
+ + + + +
+
+
+

Get Started With Bitcoin

+

Start learning about Bitcoin with interactive tutorials. It’s fun, easy, and takes only a few minutes!

+
+
+
+
+
+ # +
+

Create Your Wallet

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+
+
+
+ # +
+

Create Your Wallet

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+
+
+
+ # +
+

Create Your Wallet

+

Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+
+
+
+ + + + +
+
+
+
+
+

60

+

Support
Countries

+ +
+
+
+
+

12K

+

Transactions
per hour

+ +
+
+
+
+

5B

+

Largest
Transactions

+ +
+
+
+
+

240

+

Years
of Experience

+ +
+
+
+
+
+ + + + +
+
+
+

Meet Our Team

+

Our experts in the field of crypto currency can always help you with any of your questions!

+
+
+
+ +
+
+
+

Tom Binegar

+ Business Development +
+
+ + + +
+
+
+
+

Tom Binegar

+ Marketing Director +
+

Jackson Nash is a full-time faculty member of the Marketing and Behavioural Science Division at the Sauder School of Business at UBC. He leads the Entrepreneurship Group, in the undergraduate and graduate programs, teaching actively in both of these.

+
+
+ +
+
+
+

Jackson Nash

+ Business Development +
+
+ + + +
+
+
+
+

Jackson Nash

+ Marketing Director +
+

Jackson Nash is a full-time faculty member of the Marketing and Behavioural Science Division at the Sauder School of Business at UBC. He leads the Entrepreneurship Group, in the undergraduate and graduate programs, teaching actively in both of these.

+
+
+ +
+
+
+

Tom Binegar

+ Business Development +
+
+ + + +
+
+
+
+

Aaron Ballance

+ Ceo Bitcoin +
+

Jackson Nash is a full-time faculty member of the Marketing and Behavioural Science Division at the Sauder School of Business at UBC. He leads the Entrepreneurship Group, in the undergraduate and graduate programs, teaching actively in both of these.

+
+
+ +
+
+
+

Melissa Barth

+ Product Manager +
+
+ + + +
+
+
+
+

Melissa Barth

+ Product Manager +
+

Jackson Nash is a full-time faculty member of the Marketing and Behavioural Science Division at the Sauder School of Business at UBC. He leads the Entrepreneurship Group, in the undergraduate and graduate programs, teaching actively in both of these.

+
+
+ +
+
+
+

Katy Abrams

+ Head of Design +
+
+ + + +
+
+
+
+

Katy Abrams

+ Head of Design +
+

Jackson Nash is a full-time faculty member of the Marketing and Behavioural Science Division at the Sauder School of Business at UBC. He leads the Entrepreneurship Group, in the undergraduate and graduate programs, teaching actively in both of these.

+
+
+
+
+ + + + +
+
+
+
+ + +
+
+ +
+
+
+
+ + + + + + + + + + +
+
+
+

Latest News

+

Bitcoin is the simplest way to exchange money at very low cost.

+
+ +
+
+ + + +<#include "footer.ftl"> + + +<#include "scripts.ftl"> + + + + + diff --git a/src/main/resources/spark/template/freemarker/newsletter.ftl b/src/main/resources/spark/template/freemarker/newsletter.ftl new file mode 100644 index 0000000..87693d3 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/newsletter.ftl @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/page_info.ftl b/src/main/resources/spark/template/freemarker/page_info.ftl new file mode 100644 index 0000000..bc0e4b4 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/page_info.ftl @@ -0,0 +1,20 @@ + + +<#macro pageInfo name = "Home"> + + + + +
+
+

${name}

+
+ Home + ${name} +
+
+
+ + + + \ No newline at end of file diff --git a/src/main/resources/spark/template/freemarker/profile.ftl b/src/main/resources/spark/template/freemarker/profile.ftl new file mode 100644 index 0000000..22765f2 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/profile.ftl @@ -0,0 +1,370 @@ + + + +<#include "head.ftl"> +<@head title = "Profile Page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Profile"/> + + + + + +<#----> + + + +<#----> +<#----> + +
+
+
+
+
+

Welcome

+
+

+ + Performance +

+

Manage your account settings and your wallet here.

+
+
+
+ +
+
+
+
+

Wallet

+ +
+
+ +
+ +
+
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
RSI Text Notifier + +
+
+ +
+
+
+ +
+
+
Trailing Stop + +
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+ + + + + + + + +<#include "newsletter.ftl"> + + +<#include "footer.ftl"> + + +<#include "scripts.ftl"> + + + + + + +--> + + + + diff --git a/src/main/resources/spark/template/freemarker/scripts.ftl b/src/main/resources/spark/template/freemarker/scripts.ftl new file mode 100644 index 0000000..68985db --- /dev/null +++ b/src/main/resources/spark/template/freemarker/scripts.ftl @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/spark/template/freemarker/signup.ftl b/src/main/resources/spark/template/freemarker/signup.ftl new file mode 100644 index 0000000..3fbdd8b --- /dev/null +++ b/src/main/resources/spark/template/freemarker/signup.ftl @@ -0,0 +1,98 @@ + + + +<#include "head.ftl"> +<@head title = "Sign Up Page"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Sign up"/> + + + + + + + +<#include "newsletter.ftl"> + +<#include "footer.ftl"> + + +<#include "scripts.ftl"> + + + + + diff --git a/src/main/resources/spark/template/freemarker/strategy-after.ftl b/src/main/resources/spark/template/freemarker/strategy-after.ftl new file mode 100644 index 0000000..dbdca64 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/strategy-after.ftl @@ -0,0 +1,68 @@ + + + +<#include "head.ftl"> +<@head title = "Trading Page"/> + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Strategy"/> + + + + + + +<#include "newsletter.ftl"> + +<#include "footer.ftl"> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/strategy-form.ftl b/src/main/resources/spark/template/freemarker/strategy-form.ftl new file mode 100644 index 0000000..73c679f --- /dev/null +++ b/src/main/resources/spark/template/freemarker/strategy-form.ftl @@ -0,0 +1,208 @@ + + + +
+

Manual Trade

+
+
+ +
    +
  • Choose coin
  • +
  • Trade details
  • +
  • Finalize
  • +
+ +
+

Wallet information

+

Choose the coin to pair with ETH

+
+
+
+ +
+ +
+ +
+
+

BUY Trade details

+

Let us know what you want in your trade

+ +
+
+
+ +
+
+ +
+
+
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ + + +
+
+

Finalize trade

+

Whenever your ready

+
+

Coin chosen

+
+ +

Trade Details

+

Quantity:

+

Buy price:

+

Sell price:

+

Stop price:

+
+ + + +
+
+
+
+ + + + + + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/strategy.ftl b/src/main/resources/spark/template/freemarker/strategy.ftl new file mode 100644 index 0000000..9cd5510 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/strategy.ftl @@ -0,0 +1,96 @@ + + + +<#include "head.ftl"> +<@head title = "Trading Page"/> + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Strategy"/> + + + + + + + + + +<#include "footer.ftl"> + + + + +<#include "scripts.ftl"> + + + + + + + + + diff --git a/src/main/resources/spark/template/freemarker/trade-table.ftl b/src/main/resources/spark/template/freemarker/trade-table.ftl new file mode 100644 index 0000000..b724d78 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/trade-table.ftl @@ -0,0 +1,33 @@ + + + + + +
+ +
+ + + + + + + + + + + +
Date (last updated)PairTypePriceQuantityStatus
+
+
+ + + + +
+
+
+ + + + diff --git a/src/main/resources/spark/template/freemarker/trades.ftl b/src/main/resources/spark/template/freemarker/trades.ftl new file mode 100644 index 0000000..bf32bd6 --- /dev/null +++ b/src/main/resources/spark/template/freemarker/trades.ftl @@ -0,0 +1,56 @@ + + + +<#include "head.ftl"> +<@head title = "Your Trades"/> + + + +
+
+
+ +<#include "header.ftl"> +<@header/> + +<#include "page_info.ftl"> +<@pageInfo name = "Your Trades"/> + +
+
+
+
+ blockchain picture +
+
+

Personalized Realtime Trade Information.

+ Users have access to detailed realtime information about all trades they have submitted and the status of their open algorithmic trades. +
+
+ +
+
+ + +
+

Manage your trades here

+ <#include "trade-table.ftl"> + +

+ +
+ +<#include "newsletter.ftl"> + +<#include "footer.ftl"> + + +<#include "scripts.ftl"> + + + + + + + + diff --git a/src/main/resources/static/.DS_Store b/src/main/resources/static/.DS_Store new file mode 100644 index 0000000..dc996d5 Binary files /dev/null and b/src/main/resources/static/.DS_Store differ diff --git a/src/main/resources/static/css/about.css b/src/main/resources/static/css/about.css new file mode 100644 index 0000000..1056c00 --- /dev/null +++ b/src/main/resources/static/css/about.css @@ -0,0 +1,357 @@ +.double-bg{ + background: url('/img/section-bg.svg') no-repeat center left; bread-bg.png + background-size: contain +} + +.dream-faq-area dt { + cursor: pointer; + padding: 15px; + border-bottom: 18px solid rgba(255, 255, 255, 0.1); + margin-bottom: 0; + color: #fff; + font-weight: 500; +} + +.dream-faq-area dt { + color: #222; + border-bottom: 1px solid #f2f4f8; +} + +.dream-faq-area dt:first-child { + border-top: 1px solid #f2f4f8; +} + +.dream-faq-area dt:first-child { + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +.dream-faq-area dd { + margin: 0; + padding: 15px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + + + .faq-timeline-area{ + background: url('/img/bread-bg.png') no-repeat center center; + background-size: cover +} + +.section-padding-100 { + padding-top: 100px; + padding-bottom: 100px; +} + +.section-heading h2 { + font-size: 30px; + text-transform: capitalize; + margin-bottom: 15px; +} + +.section-heading > p { + margin-bottom: 0; + line-height: 2; + font-size: 16px; + max-width: 600px; + margin: 0 auto; +} + +.light-version .dream-faq-area dt { + color: #222; + border-bottom: 1px solid #f2f4f8; +} + +.light-version .dream-faq-area dt:first-child { + border-top: 1px solid #f2f4f8; +} + +.section-heading { + position: relative; + z-index: 1; + margin-bottom: 80px; +} + +.about-us-area { + position: relative; + z-index: 1; +} + +.welcome-meter { + position: relative; + z-index: 1; +} + +/* +================================================ + Map style +================================================ +*/ + +.spread-map{ + padding: 100px 0; + overflow: hidden; +} +.spread-map .sec-title{ + margin-bottom: 0 +} +.spread-map .counter-container{ + margin-top: 20px +} +@media (max-width: 767px){ + .spread-map .map-container{ + margin-top: 30px + } + .token-allocation .visa{ + margin-bottom: 30px + } +} +.spread-map .s-list-icon{ + position: absolute; + top: 8px; + padding: 7px; + border: 1px solid; + left: 0; +} +.spread-map .s-list-desc{ + padding-left: 45px; +} +.counter-wrapper{ + position: relative; + margin-top: 20px; + color: #222; + z-index: 5; +} +.counter-wrapper .icon-box { + position: relative; + width: 50px; + height: 50px; + margin-bottom: 20px; + border: 2px solid #ffb426; +} +.counter-wrapper .icon-box img{ + position: absolute; + max-width: 30px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + + +.dream-dots { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + margin-bottom: 30px; +} + +.dream-dots span { + width: 8px; + height: 8px; + background-color: #fff; + border-radius: 50%; + margin-right: 5px; +} + +.dream-dots span:first-child { + background-color: #00a8ff; +} + +.dream-dots span:nth-child(2) { + background-color: #9c88ff; +} + +.dream-dots span:nth-child(3) { + background-color: #fbc531; +} + +.dream-dots span:nth-child(4) { + background-color: #4cd137; +} + +.dream-dots span:nth-child(5) { + background-color: #487eb0; +} + +.dream-dots span:nth-child(6) { + background-color: #e84118; +} + +.dream-dots span:nth-child(7) { + background-color: #8c7ae6; +} + +.who-we-contant h4 { + margin-bottom: 20px; + font-size: 30px; +} + + +.s-list li { + margin-bottom: 10px; + color: #777; + position: relative; + font-size: 15px; +} + +.counter-wrapper .counter{ + color: #ffb426; + font-size: 20px; + text-align: left; + font-weight: 700; + font-family: 'Roboto', sans-serif; + margin-bottom: 5px; +} +.counter-wrapper h5{ + font-family: 'Open Sans', sans-serif; + font-weight: 400; + font-size: 14px; + line-height: 24px; +} + + +.floater-2 { + -webkit-animation: floater-2 infinite 4s ease-in-out; + -moz-animation: floater-2 infinite 4s ease-in-out; + animation: floater-2 infinite 4s ease-in-out; + animation-fill-mode: forwards; +} + +.gt-start-earning-anim-m3 { + width: 76px; + position: absolute; + left: -90px; + right: 0; + margin: 0 auto; + top: 0px; + z-index: 1; + opacity: 0.80; +} + +.gt-start-earning-anim-bar2 { + width: 3px; + height: 37px; + transform-origin: center bottom; + position: absolute; + left: -136px; + right: 0; + margin: 0 auto; + top: 282px; + z-index: 1; +} + +.gt-start-earning-anim-bg { + max-width: 115%; + position: relative; + left: -20px; + top: 84px; +} + +.gt-start-earning-anim-m1 { + width: 82px; + position: absolute; + left: -10px; + right: 0; + margin: 0 auto; + top: 138px; + z-index: 1; +} + +.gt-start-earning-anim-m2 { + width: 76px; + position: absolute; + left: 40px; + right: 0; + margin: 0 auto; + top: 56px; + z-index: 1; + opacity: 0.80; +} + +.ad-3 { + animation-duration: 3s; +} + +.ad-3 { + animation-duration: 3s; +} + +.ad-2-5 { + animation-duration: 2.5s; +} + +.ad-3-5 { + animation-duration: 3.5s; +} + +.gt-transparency-anim-bg { + /*width: 100%;*/ + max-width: 115%; + position: relative; + left: -20px; +} +.rain { + -webkit-animation: rain infinite 2s ease-in-out; + -moz-animation: rain infinite 2s ease-in-out; + animation: rain infinite 2s ease-in-out; + animation-fill-mode: forwards; +} +.gt-transparency-anim-rain-1 { + width: 100%; + position: absolute; + left: 0; + top: -100px; +} +.ad-2-5 { + animation-duration: 2.5s; +} +.gt-transparency-anim-rain-2 { + width: 100%; + position: absolute; + left: 0; + top: -100px; +} +.cloudmove-1 { + -webkit-animation: cloudmove-1 infinite 5s ease-in-out; + -moz-animation: cloudmove-1 infinite 5s ease-in-out; + animation: cloudmove-1 infinite 5s ease-in-out; + animation-fill-mode: forwards; +} +.gt-transparency-anim-cloud-1 { + width: 180px; + position: absolute; + left: 0; + top: 30px; +} +.gt-transparency-anim-cloud-2 { + width: 130px; + position: absolute; + right: 20px; + top: 10px; +} +.cloudmove-2 { + -webkit-animation: cloudmove-2 infinite 4s ease-in-out; + -moz-animation: cloudmove-2 infinite 4s ease-in-out; + animation: cloudmove-2 infinite 4s ease-in-out; + animation-fill-mode: forwards; +} + + +@-webkit-keyframes floater-2 {0% {transform: translate3d(0px, 0px, 0px);}50% {transform: translate3d(0px, -10px, 0px);}100% {transform: translate3d(0px, 0px, 0px);}} +@keyframes floater-2 {0% {transform: translate3d(0px, 0px, 0px);}50% {transform: translate3d(0px, -10px, 0px);}100% {transform: translate3d(0px, 0px, 0px);}} + +@-webkit-keyframes cloudmove-1 {0% {transform: translate3d(-50px, 40px, 0px);}50% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(-50px, 40px, 0px);}} +@keyframes cloudmove-1 {0% {transform: translate3d(-50px, 40px, 0px);}50% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(-50px, 40px, 0px);}} + +@-webkit-keyframes cloudmove-2 {0% {transform: translate3d(40px, 20px, 0px);}50% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(40px, 20px, 0px);}} +@keyframes cloudmove-2 {0% {transform: translate3d(40px, 20px, 0px);}50% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(40px, 20px, 0px);}} + +@-webkit-keyframes cloudmove-3 {0% {transform: translate3d(40px, 20px, 0px);}50% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(40px, 20px, 0px);}} +@keyframes cloudmove-3 {0% {transform: translate3d(-50px, 40px, 0px);}50% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(-50px, 40px, 0px);}} + +@-webkit-keyframes rain {0% {transform:translateY(0);opacity: 0;}50% {opacity: 1;}100% {transform:translateY(100px);opacity: 0;}} +@keyframes rain {0% {transform:translateY(0);opacity: 0;}50% {opacity: 1;}100% {transform:translateY(100px);opacity: 0;}} + +@-webkit-keyframes cloudmove {0% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(800px, 0px, 0px);}} +@keyframes cloudmove {0% {transform: translate3d(0px, 0px, 0px);}100% {transform: translate3d(800px, 0px, 0px);}} + + diff --git a/src/main/resources/static/css/animate.css b/src/main/resources/static/css/animate.css new file mode 100755 index 0000000..98f29c2 --- /dev/null +++ b/src/main/resources/static/css/animate.css @@ -0,0 +1,3494 @@ +@charset "UTF-8"; + +/*! + * animate.css -http://daneden.me/animate + * Version - 3.6.0 + * Licensed under the MIT license - http://opensource.org/licenses/MIT + * + * Copyright (c) 2018 Daniel Eden + */ + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.animated.infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +@-webkit-keyframes bounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } +} + +@keyframes bounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } +} + +.bounce { + -webkit-animation-name: bounce; + animation-name: bounce; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} + +@-webkit-keyframes flash { + from, + 50%, + to { + opacity: 1; + } + + 25%, + 75% { + opacity: 0; + } +} + +@keyframes flash { + from, + 50%, + to { + opacity: 1; + } + + 25%, + 75% { + opacity: 0; + } +} + +.flash { + -webkit-animation-name: flash; + animation-name: flash; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse; +} + +@-webkit-keyframes rubberBand { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes rubberBand { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.rubberBand { + -webkit-animation-name: rubberBand; + animation-name: rubberBand; +} + +@-webkit-keyframes shake { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +@keyframes shake { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +.shake { + -webkit-animation-name: shake; + animation-name: shake; +} + +@-webkit-keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg); + } + + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg); + } + + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg); + } + + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg); + } + + 50% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg); + } + + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg); + } + + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg); + } + + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg); + } + + 50% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +.headShake { + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + -webkit-animation-name: headShake; + animation-name: headShake; +} + +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg); + } + + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg); + } + + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg); + } + + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg); + } + + to { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg); + } +} + +@keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg); + } + + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg); + } + + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg); + } + + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg); + } + + to { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg); + } +} + +.swing { + -webkit-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing; +} + +@-webkit-keyframes tada { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 10%, + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + } + + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes tada { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 10%, + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + } + + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.tada { + -webkit-animation-name: tada; + animation-name: tada; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes wobble { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + } + + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + } + + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + } + + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + } + + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes wobble { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + } + + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + } + + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + } + + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + } + + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.wobble { + -webkit-animation-name: wobble; + animation-name: wobble; +} + +@-webkit-keyframes jello { + from, + 11.1%, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg); + } + + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg); + } + + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg); + } + + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg); + } + + 66.6% { + -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); + transform: skewX(-0.78125deg) skewY(-0.78125deg); + } + + 77.7% { + -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); + transform: skewX(0.390625deg) skewY(0.390625deg); + } + + 88.8% { + -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + } +} + +@keyframes jello { + from, + 11.1%, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg); + } + + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg); + } + + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg); + } + + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg); + } + + 66.6% { + -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); + transform: skewX(-0.78125deg) skewY(-0.78125deg); + } + + 77.7% { + -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); + transform: skewX(0.390625deg) skewY(0.390625deg); + } + + 88.8% { + -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + } +} + +.jello { + -webkit-animation-name: jello; + animation-name: jello; + -webkit-transform-origin: center; + transform-origin: center; +} + +@-webkit-keyframes bounceIn { + from, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes bounceIn { + from, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.bounceIn { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-name: bounceIn; + animation-name: bounceIn; +} + +@-webkit-keyframes bounceInDown { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInDown { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown; +} + +@-webkit-keyframes bounceInLeft { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInLeft { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft; +} + +@-webkit-keyframes bounceInRight { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInRight { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight; +} + +@-webkit-keyframes bounceInUp { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInUp { + from, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + + from { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp; +} + +@-webkit-keyframes bounceOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} + +@keyframes bounceOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} + +.bounceOut { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-name: bounceOut; + animation-name: bounceOut; +} + +@-webkit-keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +.bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown; +} + +@-webkit-keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +.bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft; +} + +@-webkit-keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +.bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight; +} + +@-webkit-keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +.bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp; +} + +@-webkit-keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +@-webkit-keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +@-webkit-keyframes fadeInDownBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInDownBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig; +} + +@-webkit-keyframes fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +@-webkit-keyframes fadeInLeftBig { + from { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInLeftBig { + from { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig; +} + +@-webkit-keyframes fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +@-webkit-keyframes fadeInRightBig { + from { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInRightBig { + from { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig; +} + +@-webkit-keyframes fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeInUpBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes fadeInUpBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig; +} + +@-webkit-keyframes fadeOut { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +@-webkit-keyframes fadeOutDown { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes fadeOutDown { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +@-webkit-keyframes fadeOutDownBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes fadeOutDownBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +.fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig; +} + +@-webkit-keyframes fadeOutLeft { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes fadeOutLeft { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +@-webkit-keyframes fadeOutLeftBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes fadeOutLeftBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +.fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig; +} + +@-webkit-keyframes fadeOutRight { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@keyframes fadeOutRight { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +@-webkit-keyframes fadeOutRightBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes fadeOutRightBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +.fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig; +} + +@-webkit-keyframes fadeOutUp { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes fadeOutUp { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes fadeOutUpBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes fadeOutUpBig { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +.fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig; +} + +@-webkit-keyframes flip { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95); + transform: perspective(400px) scale3d(0.95, 0.95, 0.95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +@keyframes flip { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95); + transform: perspective(400px) scale3d(0.95, 0.95, 0.95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +.animated.flip { + -webkit-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip; +} + +@-webkit-keyframes flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +.flipInX { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInX; + animation-name: flipInX; +} + +@-webkit-keyframes flipInY { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes flipInY { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + } + + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +.flipInY { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInY; + animation-name: flipInY; +} + +@-webkit-keyframes flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@keyframes flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +.flipOutX { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; +} + +@-webkit-keyframes flipOutY { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0; + } +} + +@keyframes flipOutY { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1; + } + + to { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0; + } +} + +.flipOutY { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY; +} + +@-webkit-keyframes lightSpeedIn { + from { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + opacity: 1; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes lightSpeedIn { + from { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + opacity: 1; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.lightSpeedIn { + -webkit-animation-name: lightSpeedIn; + animation-name: lightSpeedIn; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} + +@-webkit-keyframes lightSpeedOut { + from { + opacity: 1; + } + + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} + +@keyframes lightSpeedOut { + from { + opacity: 1; + } + + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} + +.lightSpeedOut { + -webkit-animation-name: lightSpeedOut; + animation-name: lightSpeedOut; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} + +@-webkit-keyframes rotateIn { + from { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateIn { + from { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn; +} + +@-webkit-keyframes rotateInDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft; +} + +@-webkit-keyframes rotateInDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight; +} + +@-webkit-keyframes rotateInUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft; +} + +@-webkit-keyframes rotateInUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes rotateInUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight; +} + +@-webkit-keyframes rotateOut { + from { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0; + } +} + +@keyframes rotateOut { + from { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1; + } + + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0; + } +} + +.rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut; +} + +@-webkit-keyframes rotateOutDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } +} + +@keyframes rotateOutDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } +} + +.rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft; +} + +@-webkit-keyframes rotateOutDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +@keyframes rotateOutDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +.rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight; +} + +@-webkit-keyframes rotateOutUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +@keyframes rotateOutUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +.rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft; +} + +@-webkit-keyframes rotateOutUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0; + } +} + +.rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight; +} + +@-webkit-keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, + 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40%, + 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} + +@keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, + 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40%, + 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} + +.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; + -webkit-animation-name: hinge; + animation-name: hinge; +} + +@-webkit-keyframes jackInTheBox { + from { + opacity: 0; + -webkit-transform: scale(0.1) rotate(30deg); + transform: scale(0.1) rotate(30deg); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + } + + 50% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 70% { + -webkit-transform: rotate(3deg); + transform: rotate(3deg); + } + + to { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes jackInTheBox { + from { + opacity: 0; + -webkit-transform: scale(0.1) rotate(30deg); + transform: scale(0.1) rotate(30deg); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + } + + 50% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 70% { + -webkit-transform: rotate(3deg); + transform: rotate(3deg); + } + + to { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +.jackInTheBox { + -webkit-animation-name: jackInTheBox; + animation-name: jackInTheBox; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollIn { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes rollIn { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollOut { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + } +} + +@keyframes rollOut { + from { + opacity: 1; + } + + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + } +} + +.rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut; +} + +@-webkit-keyframes zoomIn { + from { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 50% { + opacity: 1; + } +} + +@keyframes zoomIn { + from { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + 50% { + opacity: 1; + } +} + +.zoomIn { + -webkit-animation-name: zoomIn; + animation-name: zoomIn; +} + +@-webkit-keyframes zoomInDown { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInDown { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInDown { + -webkit-animation-name: zoomInDown; + animation-name: zoomInDown; +} + +@-webkit-keyframes zoomInLeft { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInLeft { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInLeft { + -webkit-animation-name: zoomInLeft; + animation-name: zoomInLeft; +} + +@-webkit-keyframes zoomInRight { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInRight { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInRight { + -webkit-animation-name: zoomInRight; + animation-name: zoomInRight; +} + +@-webkit-keyframes zoomInUp { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomInUp { + from { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomInUp { + -webkit-animation-name: zoomInUp; + animation-name: zoomInUp; +} + +@-webkit-keyframes zoomOut { + from { + opacity: 1; + } + + 50% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + to { + opacity: 0; + } +} + +@keyframes zoomOut { + from { + opacity: 1; + } + + 50% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + + to { + opacity: 0; + } +} + +.zoomOut { + -webkit-animation-name: zoomOut; + animation-name: zoomOut; +} + +@-webkit-keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomOutDown { + -webkit-animation-name: zoomOutDown; + animation-name: zoomOutDown; +} + +@-webkit-keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0); + transform: scale(0.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center; + } +} + +@keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0); + transform: scale(0.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center; + } +} + +.zoomOutLeft { + -webkit-animation-name: zoomOutLeft; + animation-name: zoomOutLeft; +} + +@-webkit-keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(2000px, 0, 0); + transform: scale(0.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center; + } +} + +@keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + } + + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(2000px, 0, 0); + transform: scale(0.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center; + } +} + +.zoomOutRight { + -webkit-animation-name: zoomOutRight; + animation-name: zoomOutRight; +} + +@-webkit-keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +@keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} + +.zoomOutUp { + -webkit-animation-name: zoomOutUp; + animation-name: zoomOutUp; +} + +@-webkit-keyframes slideInDown { + from { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInDown { + from { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown; +} + +@-webkit-keyframes slideInLeft { + from { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInLeft { + from { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft; +} + +@-webkit-keyframes slideInRight { + from { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInRight { + from { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight; +} + +@-webkit-keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slideInUp { + -webkit-animation-name: slideInUp; + animation-name: slideInUp; +} + +@-webkit-keyframes slideOutDown { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes slideOutDown { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +.slideOutDown { + -webkit-animation-name: slideOutDown; + animation-name: slideOutDown; +} + +@-webkit-keyframes slideOutLeft { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes slideOutLeft { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft; +} + +@-webkit-keyframes slideOutRight { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@keyframes slideOutRight { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight; +} + +@-webkit-keyframes slideOutUp { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes slideOutUp { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp; +} diff --git a/src/main/resources/static/css/bootstrap-slider.css b/src/main/resources/static/css/bootstrap-slider.css new file mode 100644 index 0000000..ce200f2 --- /dev/null +++ b/src/main/resources/static/css/bootstrap-slider.css @@ -0,0 +1,328 @@ +/*! ======================================================= + VERSION 10.6.1 +========================================================= */ +/*! ========================================================= + * bootstrap-slider.js + * + * Maintainers: + * Kyle Kemp + * - Twitter: @seiyria + * - Github: seiyria + * Rohit Kalkur + * - Twitter: @Rovolutionary + * - Github: rovolution + * + * ========================================================= + * + * bootstrap-slider is released under the MIT License + * Copyright (c) 2019 Kyle Kemp, Rohit Kalkur, and contributors + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ========================================================= */ +.slider { + display: inline-block; + vertical-align: middle; + position: relative; +} +.slider.slider-horizontal { + width: 210px; + height: 20px; +} +.slider.slider-horizontal .slider-track { + height: 10px; + width: 100%; + margin-top: -5px; + top: 50%; + left: 0; +} +.slider.slider-horizontal .slider-selection, +.slider.slider-horizontal .slider-track-low, +.slider.slider-horizontal .slider-track-high { + height: 100%; + top: 0; + bottom: 0; +} +.slider.slider-horizontal .slider-tick, +.slider.slider-horizontal .slider-handle { + margin-left: -10px; +} +.slider.slider-horizontal .slider-tick.triangle, +.slider.slider-horizontal .slider-handle.triangle { + position: relative; + top: 50%; + -ms-transform: translateY(-50%); + transform: translateY(-50%); + border-width: 0 10px 10px 10px; + width: 0; + height: 0; + border-bottom-color: #2e6da4; + margin-top: 0; +} +.slider.slider-horizontal .slider-tick-container { + white-space: nowrap; + position: absolute; + top: 0; + left: 0; + width: 100%; +} +.slider.slider-horizontal .slider-tick-label-container { + white-space: nowrap; + margin-top: 20px; +} +.slider.slider-horizontal .slider-tick-label-container .slider-tick-label { + padding-top: 4px; + display: inline-block; + text-align: center; +} +.slider.slider-horizontal .tooltip { + -ms-transform: translateX(-50%); + transform: translateX(-50%); +} +.slider.slider-horizontal.slider-rtl .slider-track { + left: initial; + right: 0; +} +.slider.slider-horizontal.slider-rtl .slider-tick, +.slider.slider-horizontal.slider-rtl .slider-handle { + margin-left: initial; + margin-right: -10px; +} +.slider.slider-horizontal.slider-rtl .slider-tick-container { + left: initial; + right: 0; +} +.slider.slider-horizontal.slider-rtl .tooltip { + -ms-transform: translateX(50%); + transform: translateX(50%); +} +.slider.slider-vertical { + height: 210px; + width: 20px; +} +.slider.slider-vertical .slider-track { + width: 10px; + height: 100%; + left: 25%; + top: 0; +} +.slider.slider-vertical .slider-selection { + width: 100%; + left: 0; + top: 0; + bottom: 0; +} +.slider.slider-vertical .slider-track-low, +.slider.slider-vertical .slider-track-high { + width: 100%; + left: 0; + right: 0; +} +.slider.slider-vertical .slider-tick, +.slider.slider-vertical .slider-handle { + margin-top: -10px; +} +.slider.slider-vertical .slider-tick.triangle, +.slider.slider-vertical .slider-handle.triangle { + border-width: 10px 0 10px 10px; + width: 1px; + height: 1px; + border-left-color: #2e6da4; + border-right-color: #2e6da4; + margin-left: 0; + margin-right: 0; +} +.slider.slider-vertical .slider-tick-label-container { + white-space: nowrap; +} +.slider.slider-vertical .slider-tick-label-container .slider-tick-label { + padding-left: 4px; +} +.slider.slider-vertical .tooltip { + -ms-transform: translateY(-50%); + transform: translateY(-50%); +} +.slider.slider-vertical.slider-rtl .slider-track { + left: initial; + right: 25%; +} +.slider.slider-vertical.slider-rtl .slider-selection { + left: initial; + right: 0; +} +.slider.slider-vertical.slider-rtl .slider-tick.triangle, +.slider.slider-vertical.slider-rtl .slider-handle.triangle { + border-width: 10px 10px 10px 0; +} +.slider.slider-vertical.slider-rtl .slider-tick-label-container .slider-tick-label { + padding-left: initial; + padding-right: 4px; +} +.slider.slider-disabled .slider-handle { + background-image: -webkit-linear-gradient(top, #dfdfdf 0%, #bebebe 100%); + background-image: -o-linear-gradient(top, #dfdfdf 0%, #bebebe 100%); + background-image: linear-gradient(to bottom, #dfdfdf 0%, #bebebe 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf', endColorstr='#ffbebebe', GradientType=0); +} +.slider.slider-disabled .slider-track { + background-image: -webkit-linear-gradient(top, #e5e5e5 0%, #e9e9e9 100%); + background-image: -o-linear-gradient(top, #e5e5e5 0%, #e9e9e9 100%); + background-image: linear-gradient(to bottom, #e5e5e5 0%, #e9e9e9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5', endColorstr='#ffe9e9e9', GradientType=0); + cursor: not-allowed; +} +.slider input { + display: none; +} +.slider .tooltip { + pointer-events: none; +} +.slider .tooltip.top { + margin-top: -36px; +} +.slider .tooltip-inner { + white-space: nowrap; + max-width: none; +} +.slider .hide { + display: none; +} +.slider-track { + position: absolute; + cursor: pointer; + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #f9f9f9 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #f9f9f9 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #f9f9f9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -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); + border-radius: 4px; +} +.slider-selection { + position: absolute; + background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; +} +.slider-selection.tick-slider-selection { + background-image: -webkit-linear-gradient(top, #8ac1ef 0%, #82b3de 100%); + background-image: -o-linear-gradient(top, #8ac1ef 0%, #82b3de 100%); + background-image: linear-gradient(to bottom, #8ac1ef 0%, #82b3de 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef', endColorstr='#ff82b3de', GradientType=0); +} +.slider-track-low, +.slider-track-high { + position: absolute; + background: transparent; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; +} +.slider-handle { + position: absolute; + top: 0; + width: 20px; + height: 20px; + background-color: #337ab7; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + filter: none; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + border: 0px solid transparent; +} +.slider-handle:hover { + cursor: pointer; +} +.slider-handle.round { + border-radius: 50%; +} +.slider-handle.triangle { + background: transparent none; +} +.slider-handle.custom { + background: transparent none; +} +.slider-handle.custom::before { + line-height: 20px; + font-size: 20px; + content: '\2605'; + color: #726204; +} +.slider-tick { + position: absolute; + cursor: pointer; + width: 20px; + height: 20px; + background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + filter: none; + opacity: 0.8; + border: 0px solid transparent; +} +.slider-tick.round { + border-radius: 50%; +} +.slider-tick.triangle { + background: transparent none; +} +.slider-tick.custom { + background: transparent none; +} +.slider-tick.custom::before { + line-height: 20px; + font-size: 20px; + content: '\2605'; + color: #726204; +} +.slider-tick.in-selection { + background-image: -webkit-linear-gradient(top, #8ac1ef 0%, #82b3de 100%); + background-image: -o-linear-gradient(top, #8ac1ef 0%, #82b3de 100%); + background-image: linear-gradient(to bottom, #8ac1ef 0%, #82b3de 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef', endColorstr='#ff82b3de', GradientType=0); + opacity: 1; +} diff --git a/src/main/resources/static/css/bootstrap-slider.min.css b/src/main/resources/static/css/bootstrap-slider.min.css new file mode 100644 index 0000000..f8e395b --- /dev/null +++ b/src/main/resources/static/css/bootstrap-slider.min.css @@ -0,0 +1,41 @@ +/*! ======================================================= + VERSION 10.6.1 +========================================================= */ +/*! ========================================================= + * bootstrap-slider.js + * + * Maintainers: + * Kyle Kemp + * - Twitter: @seiyria + * - Github: seiyria + * Rohit Kalkur + * - Twitter: @Rovolutionary + * - Github: rovolution + * + * ========================================================= + * + * bootstrap-slider is released under the MIT License + * Copyright (c) 2019 Kyle Kemp, Rohit Kalkur, and contributors + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{position:relative;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#2e6da4;margin-top:0}.slider.slider-horizontal .slider-tick-container{white-space:nowrap;position:absolute;top:0;left:0;width:100%}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap;margin-top:20px}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{padding-top:4px;display:inline-block;text-align:center}.slider.slider-horizontal .tooltip{-ms-transform:translateX(-50%);transform:translateX(-50%)}.slider.slider-horizontal.slider-rtl .slider-track{left:initial;right:0}.slider.slider-horizontal.slider-rtl .slider-tick,.slider.slider-horizontal.slider-rtl .slider-handle{margin-left:initial;margin-right:-10px}.slider.slider-horizontal.slider-rtl .slider-tick-container{left:initial;right:0}.slider.slider-horizontal.slider-rtl .tooltip{-ms-transform:translateX(50%);transform:translateX(50%)}.slider.slider-vertical{height:210px;width:20px}.slider.slider-vertical .slider-track{width:10px;height:100%;left:25%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#2e6da4;border-right-color:#2e6da4;margin-left:0;margin-right:0}.slider.slider-vertical .slider-tick-label-container{white-space:nowrap}.slider.slider-vertical .slider-tick-label-container .slider-tick-label{padding-left:4px}.slider.slider-vertical .tooltip{-ms-transform:translateY(-50%);transform:translateY(-50%)}.slider.slider-vertical.slider-rtl .slider-track{left:initial;right:25%}.slider.slider-vertical.slider-rtl .slider-selection{left:initial;right:0}.slider.slider-vertical.slider-rtl .slider-tick.triangle,.slider.slider-vertical.slider-rtl .slider-handle.triangle{border-width:10px 10px 10px 0}.slider.slider-vertical.slider-rtl .slider-tick-label-container .slider-tick-label{padding-left:initial;padding-right:4px}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-image:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip{pointer-events:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap;max-width:none}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-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);border-radius:4px}.slider-selection{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:-o-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:linear-gradient(to bottom,#8ac1ef 0,#82b3de 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef',endColorstr='#ff82b3de',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;background:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;top:0;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7',endColorstr='#ff2e6da4',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle:hover{cursor:pointer}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute;cursor:pointer;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:-o-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:linear-gradient(to bottom,#8ac1ef 0,#82b3de 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef',endColorstr='#ff82b3de',GradientType=0);opacity:1} \ No newline at end of file diff --git a/src/main/resources/static/css/bootstrap.min.css b/src/main/resources/static/css/bootstrap.min.css new file mode 100755 index 0000000..8b17a8e --- /dev/null +++ b/src/main/resources/static/css/bootstrap.min.css @@ -0,0 +1,9281 @@ +/*! + * Bootstrap v4.0.0 (https://getbootstrap.com) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 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, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --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%; + -ms-text-size-adjust: 100%; + -ms-overflow-style: scrollbar; + -webkit-tap-highlight-color: transparent +} + +@-ms-viewport { + width: device-width +} + +article, +aside, +dialog, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section { + display: block +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + 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 +} + +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 +} + +dfn { + font-style: italic +} + +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; + -webkit-text-decoration-skip: objects +} + +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: monospace, monospace; + font-size: 1em +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + -ms-overflow-style: scrollbar +} + +figure { + margin: 0 0 1rem +} + +img { + vertical-align: middle; + border-style: none +} + +svg:not(:root) { + overflow: hidden +} + +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: 1rem +} + +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 +} + +[type=reset], +[type=submit], +button, +html [type=button] { + -webkit-appearance: button +} + +[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-cancel-button, +[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-family: inherit; + font-weight: 500; + line-height: 1.2; + color: inherit +} + +.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, +kbd, +pre, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace +} + +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: -webkit-box; + 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%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100% +} + +.col-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none +} + +.col-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% +} + +.col-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% +} + +.col-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% +} + +.col-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% +} + +.col-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% +} + +.col-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% +} + +.col-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% +} + +.col-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% +} + +.col-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% +} + +.col-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% +} + +.col-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% +} + +.col-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% +} + +.order-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1 +} + +.order-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13 +} + +.order-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0 +} + +.order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1 +} + +.order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2 +} + +.order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3 +} + +.order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4 +} + +.order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5 +} + +.order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6 +} + +.order-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7 +} + +.order-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8 +} + +.order-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9 +} + +.order-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10 +} + +.order-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11 +} + +.order-12 { + -webkit-box-ordinal-group: 13; + -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; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100% + } + .col-sm-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-sm-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-sm-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-sm-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-sm-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-sm-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-sm-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-sm-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-sm-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-sm-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-sm-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-sm-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-sm-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-sm-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1 + } + .order-sm-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13 + } + .order-sm-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0 + } + .order-sm-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1 + } + .order-sm-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2 + } + .order-sm-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3 + } + .order-sm-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4 + } + .order-sm-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5 + } + .order-sm-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6 + } + .order-sm-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7 + } + .order-sm-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8 + } + .order-sm-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9 + } + .order-sm-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10 + } + .order-sm-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11 + } + .order-sm-12 { + -webkit-box-ordinal-group: 13; + -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; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100% + } + .col-md-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-md-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-md-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-md-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-md-3half { + -webkit-box-flex: 0; + -ms-flex: 0 0 29%; + flex: 0 0 29%; + max-width: 29% + } + + .col-md-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-md-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-md-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-md-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-md-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-md-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-md-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-md-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-md-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-md-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1 + } + .order-md-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13 + } + .order-md-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0 + } + .order-md-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1 + } + .order-md-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2 + } + .order-md-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3 + } + .order-md-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4 + } + .order-md-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5 + } + .order-md-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6 + } + .order-md-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7 + } + .order-md-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8 + } + .order-md-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9 + } + .order-md-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10 + } + .order-md-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11 + } + .order-md-12 { + -webkit-box-ordinal-group: 13; + -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; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100% + } + .col-lg-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-lg-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-lg-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-lg-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-lg-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-lg-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-lg-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-lg-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-lg-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-lg-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-lg-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-lg-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-lg-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-lg-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1 + } + .order-lg-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13 + } + .order-lg-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0 + } + .order-lg-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1 + } + .order-lg-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2 + } + .order-lg-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3 + } + .order-lg-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4 + } + .order-lg-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5 + } + .order-lg-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6 + } + .order-lg-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7 + } + .order-lg-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8 + } + .order-lg-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9 + } + .order-lg-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10 + } + .order-lg-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11 + } + .order-lg-12 { + -webkit-box-ordinal-group: 13; + -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; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100% + } + .col-xl-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-xl-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-xl-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-xl-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-xl-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-xl-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-xl-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-xl-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-xl-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-xl-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-xl-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-xl-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-xl-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-xl-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1 + } + .order-xl-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13 + } + .order-xl-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0 + } + .order-xl-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1 + } + .order-xl-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2 + } + .order-xl-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3 + } + .order-xl-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4 + } + .order-xl-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5 + } + .order-xl-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6 + } + .order-xl-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7 + } + .order-xl-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8 + } + .order-xl-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9 + } + .order-xl-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10 + } + .order-xl-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11 + } + .order-xl-12 { + -webkit-box-ordinal-group: 13; + -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%; + max-width: 100%; + margin-bottom: 1rem; + background-color: transparent +} + +.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 .table { + background-color: #fff +} + +.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-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, .05) +} + +.table-hover tbody tr:hover { + background-color: rgba(0, 0, 0, .075) +} + +.table-primary, +.table-primary>td, +.table-primary>th { + background-color: #b8daff +} + +.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-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-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-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-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-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-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-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: #212529; + border-color: #32383e +} + +.table .thead-light th { + color: #495057; + background-color: #e9ecef; + border-color: #dee2e6 +} + +.table-dark { + color: #fff; + background-color: #212529 +} + +.table-dark td, +.table-dark th, +.table-dark thead th { + border-color: #32383e +} + +.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 { + 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; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .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; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .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; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .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; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .table-responsive-xl>.table-bordered { + border: 0 + } +} + +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar +} + +.table-responsive>.table-bordered { + border: 0 +} + +.form-control { + display: block; + width: 100%; + padding: .375rem .75rem; + font-size: 1rem; + 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 +} + +.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:not([size]):not([multiple]) { + height: calc(2.25rem + 2px) +} + +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; + background-color: transparent; + border: solid transparent; + border-width: 1px 0 +} + +.form-control-plaintext.form-control-lg, +.form-control-plaintext.form-control-sm, +.input-group-lg>.form-control-plaintext.form-control, +.input-group-lg>.input-group-append>.form-control-plaintext.btn, +.input-group-lg>.input-group-append>.form-control-plaintext.input-group-text, +.input-group-lg>.input-group-prepend>.form-control-plaintext.btn, +.input-group-lg>.input-group-prepend>.form-control-plaintext.input-group-text, +.input-group-sm>.form-control-plaintext.form-control, +.input-group-sm>.input-group-append>.form-control-plaintext.btn, +.input-group-sm>.input-group-append>.form-control-plaintext.input-group-text, +.input-group-sm>.input-group-prepend>.form-control-plaintext.btn, +.input-group-sm>.input-group-prepend>.form-control-plaintext.input-group-text { + padding-right: 0; + padding-left: 0 +} + +.form-control-sm, +.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-sm>.input-group-append>select.btn:not([size]):not([multiple]), +.input-group-sm>.input-group-append>select.input-group-text:not([size]):not([multiple]), +.input-group-sm>.input-group-prepend>select.btn:not([size]):not([multiple]), +.input-group-sm>.input-group-prepend>select.input-group-text:not([size]):not([multiple]), +.input-group-sm>select.form-control:not([size]):not([multiple]), +select.form-control-sm:not([size]):not([multiple]) { + height: calc(1.8125rem + 2px) +} + +.form-control-lg, +.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-lg>.input-group-append>select.btn:not([size]):not([multiple]), +.input-group-lg>.input-group-append>select.input-group-text:not([size]):not([multiple]), +.input-group-lg>.input-group-prepend>select.btn:not([size]):not([multiple]), +.input-group-lg>.input-group-prepend>select.input-group-text:not([size]):not([multiple]), +.input-group-lg>select.form-control:not([size]):not([multiple]), +select.form-control-lg:not([size]):not([multiple]) { + height: calc(2.875rem + 2px) +} + +.form-group { + margin-bottom: 1rem +} + +.form-text { + display: block; + margin-top: .25rem +} + +.form-row { + display: -webkit-box; + 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: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-align: center; + -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: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba(40, 167, 69, .8); + border-radius: .2rem +} + +.custom-select.is-valid, +.form-control.is-valid, +.was-validated .custom-select:valid, +.was-validated .form-control:valid { + border-color: #28a745 +} + +.custom-select.is-valid:focus, +.form-control.is-valid:focus, +.was-validated .custom-select:valid:focus, +.was-validated .form-control: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, +.form-control.is-valid~.valid-feedback, +.form-control.is-valid~.valid-tooltip, +.was-validated .custom-select:valid~.valid-feedback, +.was-validated .custom-select:valid~.valid-tooltip, +.was-validated .form-control:valid~.valid-feedback, +.was-validated .form-control: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 { + background-color: #71dd8a +} + +.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 { + 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 1px #fff, 0 0 0 .2rem rgba(40, 167, 69, .25) +} + +.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~.custom-file-label::before, +.was-validated .custom-file-input:valid~.custom-file-label::before { + border-color: inherit +} + +.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 { + 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: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba(220, 53, 69, .8); + border-radius: .2rem +} + +.custom-select.is-invalid, +.form-control.is-invalid, +.was-validated .custom-select:invalid, +.was-validated .form-control:invalid { + border-color: #dc3545 +} + +.custom-select.is-invalid:focus, +.form-control.is-invalid:focus, +.was-validated .custom-select:invalid:focus, +.was-validated .form-control: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, +.form-control.is-invalid~.invalid-feedback, +.form-control.is-invalid~.invalid-tooltip, +.was-validated .custom-select:invalid~.invalid-feedback, +.was-validated .custom-select:invalid~.invalid-tooltip, +.was-validated .form-control:invalid~.invalid-feedback, +.was-validated .form-control: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 { + background-color: #efa2a9 +} + +.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 { + 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 1px #fff, 0 0 0 .2rem rgba(220, 53, 69, .25) +} + +.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~.custom-file-label::before, +.was-validated .custom-file-input:invalid~.custom-file-label::before { + border-color: inherit +} + +.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 { + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) +} + +.form-inline { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center +} + +.form-inline .form-check { + width: 100% +} + +@media (min-width:576px) { + .form-inline label { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 0 + } + .form-inline .form-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -webkit-box-align: center; + -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 .input-group { + width: auto + } + .form-inline .form-check { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + width: auto; + padding-left: 0 + } + .form-inline .form-check-input { + position: relative; + margin-top: 0; + margin-right: .25rem; + margin-left: 0 + } + .form-inline .custom-control { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center + } + .form-inline .custom-control-label { + margin-bottom: 0 + } +} + +.btn { + display: inline-block; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + 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 +} + +.btn:focus, +.btn:hover { + 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 +} + +.btn:not(:disabled):not(.disabled) { + cursor: pointer +} + +.btn:not(:disabled):not(.disabled).active, +.btn:not(:disabled):not(.disabled):active { + background-image: none +} + +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(0, 123, 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(0, 123, 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(108, 117, 125, .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(108, 117, 125, .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(40, 167, 69, .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(40, 167, 69, .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(23, 162, 184, .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(23, 162, 184, .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(255, 193, 7, .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(255, 193, 7, .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(220, 53, 69, .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(220, 53, 69, .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(248, 249, 250, .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(248, 249, 250, .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(52, 58, 64, .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(52, 58, 64, .5) +} + +.btn-outline-primary { + color: #007bff; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent; + background-image: none; + 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; + background-color: transparent +} + +.btn-link:hover { + color: #0056b3; + text-decoration: underline; + background-color: transparent; + border-color: transparent +} + +.btn-link.focus, +.btn-link:focus { + text-decoration: underline; + border-color: transparent; + box-shadow: none +} + +.btn-link.disabled, +.btn-link:disabled { + color: #6c757d +} + +.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 { + opacity: 0; + transition: opacity .15s linear +} + +.fade.show { + opacity: 1 +} + +.collapse { + display: none +} + +.collapse.show { + display: block +} + +tr.collapse.show { + display: table-row +} + +tbody.collapse.show { + display: table-row-group +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + transition: height .35s ease +} + +.dropdown, +.dropup { + position: relative +} + +.dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + 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 +} + +.dropup .dropdown-menu { + margin-top: 0; + margin-bottom: .125rem +} + +.dropup .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + 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 { + margin-top: 0; + margin-left: .125rem +} + +.dropright .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid transparent; + 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 { + margin-top: 0; + margin-right: .125rem +} + +.dropleft .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: .255em; + vertical-align: .255em; + content: "" +} + +.dropleft .dropdown-toggle::after { + display: none +} + +.dropleft .dropdown-toggle::before { + display: inline-block; + width: 0; + height: 0; + 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-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; + 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 +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + vertical-align: middle +} + +.btn-group-vertical>.btn, +.btn-group>.btn { + position: relative; + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 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-group .btn+.btn, +.btn-group .btn+.btn-group, +.btn-group .btn-group+.btn, +.btn-group .btn-group+.btn-group, +.btn-group-vertical .btn+.btn, +.btn-group-vertical .btn+.btn-group, +.btn-group-vertical .btn-group+.btn, +.btn-group-vertical .btn-group+.btn-group { + margin-left: -1px +} + +.btn-toolbar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start +} + +.btn-toolbar .input-group { + width: auto +} + +.btn-group>.btn:first-child { + margin-left: 0 +} + +.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 { + margin-left: 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 { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center +} + +.btn-group-vertical .btn, +.btn-group-vertical .btn-group { + width: 100% +} + +.btn-group-vertical>.btn+.btn, +.btn-group-vertical>.btn+.btn-group, +.btn-group-vertical>.btn-group+.btn, +.btn-group-vertical>.btn-group+.btn-group { + margin-top: -1px; + margin-left: 0 +} + +.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: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + width: 100% +} + +.input-group>.custom-file, +.input-group>.custom-select, +.input-group>.form-control { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0 +} + +.input-group>.custom-file:focus, +.input-group>.custom-select:focus, +.input-group>.form-control:focus { + z-index: 3 +} + +.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 { + margin-left: -1px +} + +.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: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -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::before { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.input-group>.custom-file:not(:first-child) .custom-file-label, +.input-group>.custom-file:not(:first-child) .custom-file-label::before { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.input-group-append, +.input-group-prepend { + display: -webkit-box; + display: -ms-flexbox; + display: flex +} + +.input-group-append .btn, +.input-group-prepend .btn { + position: relative; + z-index: 2 +} + +.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: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -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>.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: -webkit-inline-box; + 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; + background-color: #007bff +} + +.custom-control-input:focus~.custom-control-label::before { + box-shadow: 0 0 0 1px #fff, 0 0 0 .2rem rgba(0, 123, 255, .25) +} + +.custom-control-input:active~.custom-control-label::before { + color: #fff; + background-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 { + margin-bottom: 0 +} + +.custom-control-label::before { + position: absolute; + top: .25rem; + left: 0; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + content: ""; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #dee2e6 +} + +.custom-control-label::after { + position: absolute; + top: .25rem; + left: 0; + display: block; + width: 1rem; + height: 1rem; + content: ""; + background-repeat: no-repeat; + background-position: center center; + background-size: 50% 50% +} + +.custom-checkbox .custom-control-label::before { + border-radius: .25rem +} + +.custom-checkbox .custom-control-input:checked~.custom-control-label::before { + background-color: #007bff +} + +.custom-checkbox .custom-control-input:checked~.custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%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 { + background-color: #007bff +} + +.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%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::before { + background-color: #007bff +} + +.custom-radio .custom-control-input:checked~.custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%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-select { + display: inline-block; + width: 100%; + height: calc(2.25rem + 2px); + padding: .375rem 1.75rem .375rem .75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%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; + background-size: 8px 10px; + 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: inset 0 1px 2px rgba(0, 0, 0, .075), 0 0 5px rgba(128, 189, 255, .5) +} + +.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 { + opacity: 0 +} + +.custom-select-sm { + height: calc(1.8125rem + 2px); + padding-top: .375rem; + padding-bottom: .375rem; + font-size: 75% +} + +.custom-select-lg { + height: calc(2.875rem + 2px); + padding-top: .375rem; + padding-bottom: .375rem; + font-size: 125% +} + +.custom-file { + position: relative; + display: inline-block; + width: 100%; + height: calc(2.25rem + 2px); + margin-bottom: 0 +} + +.custom-file-input { + position: relative; + z-index: 2; + width: 100%; + height: calc(2.25rem + 2px); + margin: 0; + opacity: 0 +} + +.custom-file-input:focus~.custom-file-control { + border-color: #80bdff; + box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25) +} + +.custom-file-input:focus~.custom-file-control::before { + border-color: #80bdff +} + +.custom-file-input:lang(en)~.custom-file-label::after { + content: "Browse" +} + +.custom-file-label { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 1; + height: calc(2.25rem + 2px); + padding: .375rem .75rem; + 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(calc(2.25rem + 2px) - 1px * 2); + padding: .375rem .75rem; + line-height: 1.5; + color: #495057; + content: "Browse"; + background-color: #e9ecef; + border-left: 1px solid #ced4da; + border-radius: 0 .25rem .25rem 0 +} + +.nav { + display: -webkit-box; + 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 +} + +.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 { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + text-align: center +} + +.nav-justified .nav-item { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -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: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding: .5rem 1rem +} + +.navbar>.container, +.navbar>.container-fluid { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -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: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -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%; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + -webkit-box-align: center; + -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:not(:disabled):not(.disabled) { + cursor: pointer +} + +.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 { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start + } + .navbar-expand-sm .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-sm .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important; + -ms-flex-preferred-size: auto; + flex-basis: auto + } + .navbar-expand-sm .navbar-toggler { + display: none + } + .navbar-expand-sm .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +@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 { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start + } + .navbar-expand-md .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-md .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important; + -ms-flex-preferred-size: auto; + flex-basis: auto + } + .navbar-expand-md .navbar-toggler { + display: none + } + .navbar-expand-md .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +@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 { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start + } + .navbar-expand-lg .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-lg .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important; + -ms-flex-preferred-size: auto; + flex-basis: auto + } + .navbar-expand-lg .navbar-toggler { + display: none + } + .navbar-expand-lg .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +@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 { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start + } + .navbar-expand-xl .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-xl .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important; + -ms-flex-preferred-size: auto; + flex-basis: auto + } + .navbar-expand-xl .navbar-toggler { + display: none + } + .navbar-expand-xl .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +.navbar-expand { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -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 { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute +} + +.navbar-expand .navbar-nav .dropdown-menu-right { + right: 0; + left: auto +} + +.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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important; + -ms-flex-preferred-size: auto; + flex-basis: auto +} + +.navbar-expand .navbar-toggler { + display: none +} + +.navbar-expand .dropup .dropdown-menu { + top: auto; + bottom: 100% +} + +.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;charset=utf8,%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;charset=utf8,%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: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -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 { + -webkit-box-flex: 1; + -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: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column +} + +.card-deck .card { + margin-bottom: 15px +} + +@media (min-width:576px) { + .card-deck { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px + } + .card-deck .card { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px + } +} + +.card-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column +} + +.card-group>.card { + margin-bottom: 15px +} + +@media (min-width:576px) { + .card-group { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap + } + .card-group>.card { + -webkit-box-flex: 1; + -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:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } + .card-group>.card:first-child .card-header, + .card-group>.card:first-child .card-img-top { + border-top-right-radius: 0 + } + .card-group>.card:first-child .card-footer, + .card-group>.card:first-child .card-img-bottom { + border-bottom-right-radius: 0 + } + .card-group>.card:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + .card-group>.card:last-child .card-header, + .card-group>.card:last-child .card-img-top { + border-top-left-radius: 0 + } + .card-group>.card:last-child .card-footer, + .card-group>.card:last-child .card-img-bottom { + border-bottom-left-radius: 0 + } + .card-group>.card:only-child { + border-radius: .25rem + } + .card-group>.card:only-child .card-header, + .card-group>.card:only-child .card-img-top { + border-top-left-radius: .25rem; + border-top-right-radius: .25rem + } + .card-group>.card:only-child .card-footer, + .card-group>.card:only-child .card-img-bottom { + border-bottom-right-radius: .25rem; + border-bottom-left-radius: .25rem + } + .card-group>.card:not(:first-child):not(:last-child):not(:only-child) { + border-radius: 0 + } + .card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer, + .card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header, + .card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, + .card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top { + border-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 + } + .card-columns .card { + display: inline-block; + width: 100% + } +} + +.breadcrumb { + display: -webkit-box; + 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::before { + display: inline-block; + padding-right: .5rem; + padding-left: .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: -webkit-box; + 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 { + 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-link:not(:disabled):not(.disabled) { + cursor: pointer +} + +.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 +} + +.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 +} + +.badge-primary[href]:focus, +.badge-primary[href]:hover { + color: #fff; + text-decoration: none; + background-color: #0062cc +} + +.badge-secondary { + color: #fff; + background-color: #6c757d +} + +.badge-secondary[href]:focus, +.badge-secondary[href]:hover { + color: #fff; + text-decoration: none; + background-color: #545b62 +} + +.badge-success { + color: #fff; + background-color: #28a745 +} + +.badge-success[href]:focus, +.badge-success[href]:hover { + color: #fff; + text-decoration: none; + background-color: #1e7e34 +} + +.badge-info { + color: #fff; + background-color: #17a2b8 +} + +.badge-info[href]:focus, +.badge-info[href]:hover { + color: #fff; + text-decoration: none; + background-color: #117a8b +} + +.badge-warning { + color: #212529; + background-color: #ffc107 +} + +.badge-warning[href]:focus, +.badge-warning[href]:hover { + color: #212529; + text-decoration: none; + background-color: #d39e00 +} + +.badge-danger { + color: #fff; + background-color: #dc3545 +} + +.badge-danger[href]:focus, +.badge-danger[href]:hover { + color: #fff; + text-decoration: none; + background-color: #bd2130 +} + +.badge-light { + color: #212529; + background-color: #f8f9fa +} + +.badge-light[href]:focus, +.badge-light[href]:hover { + color: #212529; + text-decoration: none; + background-color: #dae0e5 +} + +.badge-dark { + color: #fff; + background-color: #343a40 +} + +.badge-dark[href]:focus, +.badge-dark[href]:hover { + color: #fff; + text-decoration: none; + background-color: #1d2124 +} + +.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: -webkit-box; + display: -ms-flexbox; + display: flex; + height: 1rem; + overflow: hidden; + font-size: .75rem; + background-color: #e9ecef; + border-radius: .25rem +} + +.progress-bar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + color: #fff; + text-align: center; + background-color: #007bff; + transition: width .6s ease +} + +.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 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start +} + +.media-body { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.list-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -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 { + 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:focus, +.list-group-item:hover { + z-index: 1; + text-decoration: none +} + +.list-group-item.disabled, +.list-group-item:disabled { + color: #6c757d; + background-color: #fff +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #007bff; + border-color: #007bff +} + +.list-group-flush .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0 +} + +.list-group-flush:first-child .list-group-item:first-child { + border-top: 0 +} + +.list-group-flush:last-child .list-group-item:last-child { + 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:focus, +.close:hover { + color: #000; + text-decoration: none; + opacity: .75 +} + +.close:not(:disabled):not(.disabled) { + cursor: pointer +} + +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none +} + +.modal-open { + overflow: hidden +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + outline: 0 +} + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto +} + +.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, -25%); + transform: translate(0, -25%) +} + +.modal.show .modal-dialog { + -webkit-transform: translate(0, 0); + transform: translate(0, 0) +} + +.modal-dialog-centered { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + min-height: calc(100% - (.5rem * 2)) +} + +.modal-content { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -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; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000 +} + +.modal-backdrop.fade { + opacity: 0 +} + +.modal-backdrop.show { + opacity: .5 +} + +.modal-header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 1rem; + border-bottom: 1px solid #e9ecef; + border-top-left-radius: .3rem; + border-top-right-radius: .3rem +} + +.modal-header .close { + padding: 1rem; + margin: -1rem -1rem -1rem auto +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5 +} + +.modal-body { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1rem +} + +.modal-footer { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + padding: 1rem; + border-top: 1px solid #e9ecef +} + +.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-centered { + min-height: calc(100% - (1.75rem * 2)) + } + .modal-sm { + max-width: 300px + } +} + +@media (min-width:992px) { + .modal-lg { + max-width: 800px + } +} + +.tooltip { + position: absolute; + z-index: 1070; + display: block; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + 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, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + 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::after, +.bs-popover-auto[x-placement^=top] .arrow::before, +.bs-popover-top .arrow::after, +.bs-popover-top .arrow::before { + border-width: .5rem .5rem 0 +} + +.bs-popover-auto[x-placement^=top] .arrow::before, +.bs-popover-top .arrow::before { + bottom: 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-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::after, +.bs-popover-auto[x-placement^=right] .arrow::before, +.bs-popover-right .arrow::after, +.bs-popover-right .arrow::before { + border-width: .5rem .5rem .5rem 0 +} + +.bs-popover-auto[x-placement^=right] .arrow::before, +.bs-popover-right .arrow::before { + left: 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-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::after, +.bs-popover-auto[x-placement^=bottom] .arrow::before, +.bs-popover-bottom .arrow::after, +.bs-popover-bottom .arrow::before { + border-width: 0 .5rem .5rem .5rem +} + +.bs-popover-auto[x-placement^=bottom] .arrow::before, +.bs-popover-bottom .arrow::before { + top: 0; + border-bottom-color: rgba(0, 0, 0, .25) +} + +.bs-popover-auto[x-placement^=bottom] .arrow::after, +.bs-popover-bottom .arrow::after { + top: 1px; + 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::after, +.bs-popover-auto[x-placement^=left] .arrow::before, +.bs-popover-left .arrow::after, +.bs-popover-left .arrow::before { + border-width: .5rem 0 .5rem .5rem +} + +.bs-popover-auto[x-placement^=left] .arrow::before, +.bs-popover-left .arrow::before { + right: 0; + border-left-color: rgba(0, 0, 0, .25) +} + +.bs-popover-auto[x-placement^=left] .arrow::after, +.bs-popover-left .arrow::after { + right: 1px; + border-left-color: #fff +} + +.popover-header { + padding: .5rem .75rem; + margin-bottom: 0; + font-size: 1rem; + color: inherit; + 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-inner { + position: relative; + width: 100%; + overflow: hidden +} + +.carousel-item { + position: relative; + display: none; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + transition: -webkit-transform .6s ease; + transition: transform .6s ease; + transition: transform .6s ease, -webkit-transform .6s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px +} + +.carousel-item-next, +.carousel-item-prev, +.carousel-item.active { + display: block +} + +.carousel-item-next, +.carousel-item-prev { + position: absolute; + top: 0 +} + +.carousel-item-next.carousel-item-left, +.carousel-item-prev.carousel-item-right { + -webkit-transform: translateX(0); + transform: translateX(0) +} + +@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) { + .carousel-item-next.carousel-item-left, + .carousel-item-prev.carousel-item-right { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.active.carousel-item-right, +.carousel-item-next { + -webkit-transform: translateX(100%); + transform: translateX(100%) +} + +@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) { + .active.carousel-item-right, + .carousel-item-next { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } +} + +.active.carousel-item-left, +.carousel-item-prev { + -webkit-transform: translateX(-100%); + transform: translateX(-100%) +} + +@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) { + .active.carousel-item-left, + .carousel-item-prev { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } +} + +.carousel-control-next, +.carousel-control-prev { + position: absolute; + top: 0; + bottom: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + width: 15%; + color: #fff; + text-align: center; + opacity: .5 +} + +.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: transparent no-repeat center center; + background-size: 100% 100% +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml;charset=utf8,%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;charset=utf8,%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: 10px; + left: 0; + z-index: 15; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + padding-left: 0; + margin-right: 15%; + margin-left: 15%; + list-style: none +} + +.carousel-indicators li { + position: relative; + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + width: 30px; + height: 3px; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + background-color: rgba(255, 255, 255, .5) +} + +.carousel-indicators li::before { + position: absolute; + top: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: "" +} + +.carousel-indicators li::after { + position: absolute; + bottom: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: "" +} + +.carousel-indicators .active { + background-color: #fff +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center +} + +.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 { + 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-circle { + border-radius: 50%!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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important +} + +.d-inline-flex { + display: -webkit-inline-box!important; + 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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important + } + .d-sm-inline-flex { + display: -webkit-inline-box!important; + 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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important + } + .d-md-inline-flex { + display: -webkit-inline-box!important; + 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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important + } + .d-lg-inline-flex { + display: -webkit-inline-box!important; + 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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important + } + .d-xl-inline-flex { + display: -webkit-inline-box!important; + 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: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important + } + .d-print-inline-flex { + display: -webkit-inline-box!important; + 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 { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: row!important; + flex-direction: row!important +} + +.flex-column { + -webkit-box-orient: vertical!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: column!important; + flex-direction: column!important +} + +.flex-row-reverse { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -ms-flex-direction: row-reverse!important; + flex-direction: row-reverse!important +} + +.flex-column-reverse { + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -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 +} + +.justify-content-start { + -webkit-box-pack: start!important; + -ms-flex-pack: start!important; + justify-content: flex-start!important +} + +.justify-content-end { + -webkit-box-pack: end!important; + -ms-flex-pack: end!important; + justify-content: flex-end!important +} + +.justify-content-center { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important +} + +.justify-content-between { + -webkit-box-pack: justify!important; + -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 { + -webkit-box-align: start!important; + -ms-flex-align: start!important; + align-items: flex-start!important +} + +.align-items-end { + -webkit-box-align: end!important; + -ms-flex-align: end!important; + align-items: flex-end!important +} + +.align-items-center { + -webkit-box-align: center!important; + -ms-flex-align: center!important; + align-items: center!important +} + +.align-items-baseline { + -webkit-box-align: baseline!important; + -ms-flex-align: baseline!important; + align-items: baseline!important +} + +.align-items-stretch { + -webkit-box-align: stretch!important; + -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 { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: row!important; + flex-direction: row!important + } + .flex-sm-column { + -webkit-box-orient: vertical!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: column!important; + flex-direction: column!important + } + .flex-sm-row-reverse { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -ms-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-sm-column-reverse { + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -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 + } + .justify-content-sm-start { + -webkit-box-pack: start!important; + -ms-flex-pack: start!important; + justify-content: flex-start!important + } + .justify-content-sm-end { + -webkit-box-pack: end!important; + -ms-flex-pack: end!important; + justify-content: flex-end!important + } + .justify-content-sm-center { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important + } + .justify-content-sm-between { + -webkit-box-pack: justify!important; + -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 { + -webkit-box-align: start!important; + -ms-flex-align: start!important; + align-items: flex-start!important + } + .align-items-sm-end { + -webkit-box-align: end!important; + -ms-flex-align: end!important; + align-items: flex-end!important + } + .align-items-sm-center { + -webkit-box-align: center!important; + -ms-flex-align: center!important; + align-items: center!important + } + .align-items-sm-baseline { + -webkit-box-align: baseline!important; + -ms-flex-align: baseline!important; + align-items: baseline!important + } + .align-items-sm-stretch { + -webkit-box-align: stretch!important; + -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 { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: row!important; + flex-direction: row!important + } + .flex-md-column { + -webkit-box-orient: vertical!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: column!important; + flex-direction: column!important + } + .flex-md-row-reverse { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -ms-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-md-column-reverse { + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -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 + } + .justify-content-md-start { + -webkit-box-pack: start!important; + -ms-flex-pack: start!important; + justify-content: flex-start!important + } + .justify-content-md-end { + -webkit-box-pack: end!important; + -ms-flex-pack: end!important; + justify-content: flex-end!important + } + .justify-content-md-center { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important + } + .justify-content-md-between { + -webkit-box-pack: justify!important; + -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 { + -webkit-box-align: start!important; + -ms-flex-align: start!important; + align-items: flex-start!important + } + .align-items-md-end { + -webkit-box-align: end!important; + -ms-flex-align: end!important; + align-items: flex-end!important + } + .align-items-md-center { + -webkit-box-align: center!important; + -ms-flex-align: center!important; + align-items: center!important + } + .align-items-md-baseline { + -webkit-box-align: baseline!important; + -ms-flex-align: baseline!important; + align-items: baseline!important + } + .align-items-md-stretch { + -webkit-box-align: stretch!important; + -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 { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: row!important; + flex-direction: row!important + } + .flex-lg-column { + -webkit-box-orient: vertical!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: column!important; + flex-direction: column!important + } + .flex-lg-row-reverse { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -ms-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-lg-column-reverse { + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -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 + } + .justify-content-lg-start { + -webkit-box-pack: start!important; + -ms-flex-pack: start!important; + justify-content: flex-start!important + } + .justify-content-lg-end { + -webkit-box-pack: end!important; + -ms-flex-pack: end!important; + justify-content: flex-end!important + } + .justify-content-lg-center { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important + } + .justify-content-lg-between { + -webkit-box-pack: justify!important; + -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 { + -webkit-box-align: start!important; + -ms-flex-align: start!important; + align-items: flex-start!important + } + .align-items-lg-end { + -webkit-box-align: end!important; + -ms-flex-align: end!important; + align-items: flex-end!important + } + .align-items-lg-center { + -webkit-box-align: center!important; + -ms-flex-align: center!important; + align-items: center!important + } + .align-items-lg-baseline { + -webkit-box-align: baseline!important; + -ms-flex-align: baseline!important; + align-items: baseline!important + } + .align-items-lg-stretch { + -webkit-box-align: stretch!important; + -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 { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: row!important; + flex-direction: row!important + } + .flex-xl-column { + -webkit-box-orient: vertical!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: column!important; + flex-direction: column!important + } + .flex-xl-row-reverse { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -ms-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-xl-column-reverse { + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -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 + } + .justify-content-xl-start { + -webkit-box-pack: start!important; + -ms-flex-pack: start!important; + justify-content: flex-start!important + } + .justify-content-xl-end { + -webkit-box-pack: end!important; + -ms-flex-pack: end!important; + justify-content: flex-end!important + } + .justify-content-xl-center { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important + } + .justify-content-xl-between { + -webkit-box-pack: justify!important; + -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 { + -webkit-box-align: start!important; + -ms-flex-align: start!important; + align-items: flex-start!important + } + .align-items-xl-end { + -webkit-box-align: end!important; + -ms-flex-align: end!important; + align-items: flex-end!important + } + .align-items-xl-center { + -webkit-box-align: center!important; + -ms-flex-align: center!important; + align-items: center!important + } + .align-items-xl-baseline { + -webkit-box-align: baseline!important; + -ms-flex-align: baseline!important; + align-items: baseline!important + } + .align-items-xl-stretch { + -webkit-box-align: stretch!important; + -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 + } +} + +.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; + -webkit-clip-path: inset(50%); + clip-path: inset(50%); + border: 0 +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + overflow: visible; + clip: auto; + white-space: normal; + -webkit-clip-path: none; + clip-path: none +} + +.w-25 { + width: 25%!important +} + +.w-50 { + width: 50%!important +} + +.w-75 { + width: 75%!important +} + +.w-100 { + width: 100%!important +} + +.h-25 { + height: 25%!important +} + +.h-50 { + height: 50%!important +} + +.h-75 { + height: 75%!important +} + +.h-100 { + height: 100%!important +} + +.mw-100 { + max-width: 100%!important +} + +.mh-100 { + max-height: 100%!important +} + +.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-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-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-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-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-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-justify { + text-align: justify!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-normal { + font-weight: 400!important +} + +.font-weight-bold { + font-weight: 700!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: #0062cc!important +} + +.text-secondary { + color: #6c757d!important +} + +a.text-secondary:focus, +a.text-secondary:hover { + color: #545b62!important +} + +.text-success { + color: #28a745!important +} + +a.text-success:focus, +a.text-success:hover { + color: #1e7e34!important +} + +.text-info { + color: #17a2b8!important +} + +a.text-info:focus, +a.text-info:hover { + color: #117a8b!important +} + +.text-warning { + color: #ffc107!important +} + +a.text-warning:focus, +a.text-warning:hover { + color: #d39e00!important +} + +.text-danger { + color: #dc3545!important +} + +a.text-danger:focus, +a.text-danger:hover { + color: #bd2130!important +} + +.text-light { + color: #f8f9fa!important +} + +a.text-light:focus, +a.text-light:hover { + color: #dae0e5!important +} + +.text-dark { + color: #343a40!important +} + +a.text-dark:focus, +a.text-dark:hover { + color: #1d2124!important +} + +.text-muted { + color: #6c757d!important +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0 +} + +.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 #999; + 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 #ddd!important + } +} + + +/*# sourceMappingURL=bootstrap.min.css.map */= \ No newline at end of file diff --git a/src/main/resources/static/css/font-awesome.min.css b/src/main/resources/static/css/font-awesome.min.css new file mode 100755 index 0000000..d29304c --- /dev/null +++ b/src/main/resources/static/css/font-awesome.min.css @@ -0,0 +1,3044 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@font-face { + font-family: 'FontAwesome'; + src: url('../icon-fonts/fontawesome-webfont.eot?v=4.7.0'); + src: url('../icon-fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../icon-fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../icon-fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../icon-fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../icon-fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal +} + +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale +} + +.fa-lg { + font-size: 1.33333333em; + line-height: .75em; + vertical-align: -15% +} + +.fa-2x { + font-size: 2em +} + +.fa-3x { + font-size: 3em +} + +.fa-4x { + font-size: 4em +} + +.fa-5x { + font-size: 5em +} + +.fa-fw { + width: 1.28571429em; + text-align: center +} + +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none +} + +.fa-ul>li { + position: relative +} + +. fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: .14285714em; + text-align: center +} + +.fa-li .fa-lg { + left: -1.85714286em +} + +.fa-border { + padding: .2em .25em .15em; + border: solid .08em #eee; + border-radius: .1em +} + +.fa-pull-left { + float: left +} + +.fa-pull-right { + float: right +} + +.fa.fa-pull-left { + margin-right: .3em +} + +.fa.fa-pull-right { + margin-left: .3em +} + +.pull-right { + float: right +} + +.pull-left { + float: left +} + +.fa.pull-left { + margin-right: .3em +} + +.fa.pull-right { + margin-left: .3em +} + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear +} + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8) +} + +@-webkit-keyframes fa-spi { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg) + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg) + } +} + +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg) +} + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg) +} + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg) +} + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1) +} + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1) +} + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none +} + +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle +} + +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center +} + +.fa-stack-1x { + line-height: inherit +} + +.fa-stack-2x { + font-size: 2em +} + +.fa-inverse { + color: #fff +} + +.fa-glass:before { + content: "\f000" +} + +.fa-music:before { + content: "\f001" +} + +.fa-search:before { + content: "\f002" +} + +.fa-envelope-o:before { + content: "\f003" +} + +.fa-heart:before { + content: "\f004" +} + +.fa-star:before { + content: "\f005" +} + +.fa-star-o:before { + content: "\f006" +} + +.fa-user:before { + content: "\f007" +} + +.fa-film:before { + content: "\f008" +} + +.fa-th-large:before { + content: "\f009" +} + +.fa-th:before { + content: "\f00a" +} + +.fa-th-list:before { + content: "\f00b" +} + +.fa-check:before { + content: "\f00c" +} + +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d" +} + +.fa-search-plus:before { + content: "\f00e" +} + +.fa-search-minus:before { + content: "\f010" +} + +.fa-power-off:before { + content: "\f011" +} + +.fa-signal:before { + content: "\f012" +} + +.fa-gear:before, +.fa-cog:before { + content: "\f013" +} + +.fa-trash-o:before { + content: "\f014" +} + +.fa-home:before { + content: "\f015" +} + +.fa-file-o:before { + content: "\f016" +} + +.fa-clock-o:before { + content: "\f017" +} + +.fa-road:before { + content: "\f018" +} + +.fa-download:before { + content: "\f019" +} + +.fa-arrow-circle-o-down:before { + content: "\f01a" +} + +.fa-arrow-circle-o-up:before { + content: "\f01b" +} + +.fa-inbox:before { + content: "\f01c" +} + +.fa-play-circle-o:before { + content: "\f01d" +} + +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e" +} + +.fa-refresh:before { + content: "\f021" +} + +.fa-list-alt:before { + content: "\f022" +} + +.fa-lock:before { + content: "\f023" +} + +.fa-flag:before { + content: "\f024" +} + +.fa-headphones:before { + content: "\f025" +} + +.fa-volume-off:before { + content: "\f026" +} + +.fa-volume-down:before { + content: "\f027" +} + +.fa-volume-up:before { + content: "\f028" +} + +.fa-qrcode:before { + content: "\f029" +} + +.fa-barcode:before { + content: "\f02a" +} + +.fa-tag:before { + content: "\f02b" +} + +.fa-tags:before { + content: "\f02c" +} + +.fa-book:before { + content: "\f02d" +} + +.fa-bookmark:before { + content: "\f02e" +} + +.fa-print:before { + content: "\f02f" +} + +.fa-camera:before { + content: "\f030" +} + +.fa-font:before { + content: "\f031" +} + +.fa-bold:before { + content: "\f032" +} + +.fa-italic:before { + content: "\f033" +} + +.fa-text-height:before { + content: "\f034" +} + +.fa-text-width:before { + content: "\f035" +} + +.fa-align-left:before { + content: "\f036" +} + +.fa-align-center:before { + content: "\f037" +} + +.fa-align-right:before { + content: "\f038" +} + +.fa-align-justify:before { + content: "\f039" +} + +.fa-list:before { + content: "\f03a" +} + +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b" +} + +.fa-indent:before { + content: "\f03c" +} + +.fa-video-camera:before { + content: "\f03d" +} + +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e" +} + +.fa-pencil:before { + content: "\f040" +} + +.fa-map-marker:before { + content: "\f041" +} + +.fa-adjust:before { + content: "\f042" +} + +.fa-tint:before { + content: "\f043" +} + +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044" +} + +.fa-share-square-o:before { + content: "\f045" +} + +.fa-check-square-o:before { + content: "\f046" +} + +.fa-arrows:before { + content: "\f047" +} + +.fa-step-backward:before { + content: "\f048" +} + +.fa-fast-backward:before { + content: "\f049" +} + +.fa-backward:before { + content: "\f04a" +} + +.fa-play:before { + content: "\f04b" +} + +.fa-pause:before { + content: "\f04c" +} + +.fa-stop:before { + content: "\f04d" +} + +.fa-forward:before { + content: "\f04e" +} + +.fa-fast-forward:before { + content: "\f050" +} + +.fa-step-forward:before { + content: "\f051" +} + +.fa-eject:before { + content: "\f052" +} + +.fa-chevron-left:before { + content: "\f053" +} + +.fa-chevron-right:before { + content: "\f054" +} + +.fa-plus-circle:before { + content: "\f055" +} + +.fa-minus-circle:before { + content: "\f056" +} + +.fa-times-circle:before { + content: "\f057" +} + +.fa-check-circle:before { + content: "\f058" +} + +.fa-question-circle:before { + content: "\f059" +} + +.fa-info-circle:before { + content: "\f05a" +} + +.fa-crosshairs:before { + content: "\f05b" +} + +.fa-times-circle-o:before { + content: "\f05c" +} + +.fa-check-circle-o:before { + content: "\f05d" +} + +.fa-ban:before { + content: "\f05e" +} + +.fa-arrow-left:before { + content: "\f060" +} + +.fa-arrow-right:before { + content: "\f061" +} + +.fa-arrow-up:before { + content: "\f062" +} + +.fa-arrow-down:before { + content: "\f063" +} + +.fa-mail-forward:before, +.fa-share:before { + content: "\f064" +} + +.fa-expand:before { + content: "\f065" +} + +.fa-compress:before { + content: "\f066" +} + +.fa-plus:before { + content: "\f067" +} + +.fa-minus:before { + content: "\f068" +} + +.fa-asterisk:before { + content: "\f069" +} + +.fa-exclamation-circle:before { + content: "\f06a" +} + +.fa-gift:before { + content: "\f06b" +} + +.fa-leaf:before { + content: "\f06c" +} + +.fa-fire:before { + content: "\f06d" +} + +.fa-eye:before { + content: "\f06e" +} + +.fa-eye-slash:before { + content: "\f070" +} + +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071" +} + +.fa-plane:before { + content: "\f072" +} + +.fa-calendar:before { + content: "\f073" +} + +.fa-random:before { + content: "\f074" +} + +.fa-comment:before { + content: "\f075" +} + +.fa-magnet:before { + content: "\f076" +} + +.fa-chevron-up:before { + content: "\f077" +} + +.fa-chevron-down:before { + content: "\f078" +} + +.fa-retweet:before { + content: "\f079" +} + +.fa-shopping-cart:before { + content: "\f07a" +} + +.fa-folder:before { + content: "\f07b" +} + +.fa-folder-open:before { + content: "\f07c" +} + +.fa-arrows-v:before { + content: "\f07d" +} + +.fa-arrows-h:before { + content: "\f07e" +} + +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080" +} + +.fa-twitter-square:before { + content: "\f081" +} + +.fa-facebook-square:before { + content: "\f082" +} + +.fa-camera-retro:before { + content: "\f083" +} + +.fa-key:before { + content: "\f084" +} + +.fa-gears:before, +.fa-cogs:before { + content: "\f085" +} + +.fa-comments:before { + content: "\f086" +} + +.fa-thumbs-o-up:before { + content: "\f087" +} + +.fa-thumbs-o-down:before { + content: "\f088" +} + +.fa-star-half:before { + content: "\f089" +} + +.fa-heart-o:before { + content: "\f08a" +} + +.fa-sign-out:before { + content: "\f08b" +} + +.fa-linkedin-square:before { + content: "\f08c" +} + +.fa-thumb-tack:before { + content: "\f08d" +} + +.fa-external-link:before { + content: "\f08e" +} + +.fa-sign-in:before { + content: "\f090" +} + +.fa-trophy:before { + content: "\f091" +} + +.fa-github-square:before { + content: "\f092" +} + +.fa-upload:before { + content: "\f093" +} + +.fa-lemon-o:before { + content: "\f094" +} + +.fa-phone:before { + content: "\f095" +} + +.fa-square-o:before { + content: "\f096" +} + +.fa-bookmark-o:before { + content: "\f097" +} + +.fa-phone-square:before { + content: "\f098" +} + +.fa-twitter:before { + content: "\f099" +} + +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a" +} + +.fa-github:before { + content: "\f09b" +} + +.fa-unlock:before { + content: "\f09c" +} + +.fa-credit-card:before { + content: "\f09d" +} + +.fa-feed:before, +.fa-rss:before { + content: "\f09e" +} + +.fa-hdd-o:before { + content: "\f0a0" +} + +.fa-bullhorn:before { + content: "\f0a1" +} + +.fa-bell:before { + content: "\f0f3" +} + +.fa-certificate:before { + content: "\f0a3" +} + +.fa-hand-o-right:before { + content: "\f0a4" +} + +.fa-hand-o-left:before { + content: "\f0a5" +} + +.fa-hand-o-up:before { + content: "\f0a6" +} + +.fa-hand-o-down:before { + content: "\f0a7" +} + +.fa-arrow-circle-left:before { + content: "\f0a8" +} + +.fa-arrow-circle-right:before { + content: "\f0a9" +} + +.fa-arrow-circle-up:before { + content: "\f0aa" +} + +.fa-arrow-circle-down:before { + content: "\f0ab" +} + +.fa-globe:before { + content: "\f0ac" +} + +.fa-wrench:before { + content: "\f0ad" +} + +.fa-tasks:before { + content: "\f0ae" +} + +.fa-filter:before { + content: "\f0b0" +} + +.fa-briefcase:before { + content: "\f0b1" +} + +.fa-arrows-alt:before { + content: "\f0b2" +} + +.fa-group:before, +.fa-users:before { + content: "\f0c0" +} + +.fa-chain:before, +.fa-link:before { + content: "\f0c1" +} + +.fa-cloud:before { + content: "\f0c2" +} + +.fa-flask:before { + content: "\f0c3" +} + +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4" +} + +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5" +} + +.fa-paperclip:before { + content: "\f0c6" +} + +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7" +} + +.fa-square:before { + content: "\f0c8" +} + +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9" +} + +.fa-list-ul:before { + content: "\f0ca" +} + +.fa-list-ol:before { + content: "\f0cb" +} + +.fa-strikethrough:before { + content: "\f0cc" +} + +.fa-underline:before { + content: "\f0cd" +} + +.fa-table:before { + content: "\f0ce" +} + +.fa-magic:before { + content: "\f0d0" +} + +.fa-truck:before { + content: "\f0d1" +} + +.fa-pinterest:before { + content: "\f0d2" +} + +.fa-pinterest-square:before { + content: "\f0d3" +} + +.fa-google-plus-square:before { + content: "\f0d4" +} + +.fa-google-plus:before { + content: "\f0d5" +} + +.fa-money:before { + content: "\f0d6" +} + +.fa-caret-down:before { + content: "\f0d7" +} + +.fa-caret-up:before { + content: "\f0d8" +} + +.fa-caret-left:before { + content: "\f0d9" +} + +.fa-caret-right:before { + content: "\f0da" +} + +.fa-columns:before { + content: "\f0db" +} + +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc" +} + +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd" +} + +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de" +} + +.fa-envelope:before { + content: "\f0e0" +} + +.fa-linkedin:before { + content: "\f0e1" +} + +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2" +} + +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3" +} + +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4" +} + +.fa-comment-o:before { + content: "\f0e5" +} + +.fa-comments-o:before { + content: "\f0e6" +} + +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7" +} + +.fa-sitemap:before { + content: "\f0e8" +} + +.fa-umbrella:before { + content: "\f0e9" +} + +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea" +} + +.fa-lightbulb-o:before { + content: "\f0eb" +} + +.fa-exchange:before { + content: "\f0ec" +} + +.fa-cloud-download:before { + content: "\f0ed" +} + +.fa-cloud-upload:before { + content: "\f0ee" +} + +.fa-user-md:before { + content: "\f0f0" +} + +.fa-stethoscope:before { + content: "\f0f1" +} + +.fa-suitcase:before { + content: "\f0f2" +} + +.fa-bell-o:before { + content: "\f0a2" +} + +.fa-coffee:before { + content: "\f0f4" +} + +.fa-cutlery:before { + content: "\f0f5" +} + +.fa-file-text-o:before { + content: "\f0f6" +} + +.fa-building-o:before { + content: "\f0f7" +} + +.fa-hospital-o:before { + content: "\f0f8" +} + +.fa-ambulance:before { + content: "\f0f9" +} + +.fa-medkit:before { + content: "\f0fa" +} + +.fa-fighter-jet:before { + content: "\f0fb" +} + +.fa-beer:before { + content: "\f0fc" +} + +.fa-h-square:before { + content: "\f0fd" +} + +.fa-plus-square:before { + content: "\f0fe" +} + +.fa-angle-double-left:before { + content: "\f100" +} + +.fa-angle-double-right:before { + content: "\f101" +} + +.fa-angle-double-up:before { + content: "\f102" +} + +.fa-angle-double-down:before { + content: "\f103" +} + +.fa-angle-left:before { + content: "\f104" +} + +.fa-angle-right:before { + content: "\f105" +} + +.fa-angle-up:before { + content: "\f106" +} + +.fa-angle-down:before { + content: "\f107" +} + +.fa-desktop:before { + content: "\f108" +} + +.fa-laptop:before { + content: "\f109" +} + +.fa-tablet:before { + content: "\f10a" +} + +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b" +} + +.fa-circle-o:before { + content: "\f10c" +} + +.fa-quote-left:before { + content: "\f10d" +} + +.fa-quote-right:before { + content: "\f10e" +} + +.fa-spinner:before { + content: "\f110" +} + +.fa-circle:before { + content: "\f111" +} + +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112" +} + +.fa-github-alt:before { + content: "\f113" +} + +.fa-folder-o:before { + content: "\f114" +} + +.fa-folder-open-o:before { + content: "\f115" +} + +.fa-smile-o:before { + content: "\f118" +} + +.fa-frown-o:before { + content: "\f119" +} + +.fa-meh-o:before { + content: "\f11a" +} + +.fa-gamepad:before { + content: "\f11b" +} + +.fa-keyboard-o:before { + content: "\f11c" +} + +.fa-flag-o:before { + content: "\f11d" +} + +.fa-flag-checkered:before { + content: "\f11e" +} + +.fa-terminal:before { + content: "\f120" +} + +.fa-code:before { + content: "\f121" +} + +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122" +} + +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123" +} + +.fa-location-arrow:before { + content: "\f124" +} + +.fa-crop:before { + content: "\f125" +} + +.fa-code-fork:before { + content: "\f126" +} + +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127" +} + +.fa-question:before { + content: "\f128" +} + +.fa-info:before { + content: "\f129" +} + +.fa-exclamation:before { + content: "\f12a" +} + +.fa-superscript:before { + content: "\f12b" +} + +.fa-subscript:before { + content: "\f12c" +} + +.fa-eraser:before { + content: "\f12d" +} + +.fa-puzzle-piece:before { + content: "\f12e" +} + +.fa-microphone:before { + content: "\f130" +} + +.fa-microphone-slash:before { + content: "\f131" +} + +.fa-shield:before { + content: "\f132" +} + +.fa-calendar-o:before { + content: "\f133" +} + +.fa-fire-extinguisher:before { + content: "\f134" +} + +.fa-rocket:before { + content: "\f135" +} + +.fa-maxcdn:before { + content: "\f136" +} + +.fa-chevron-circle-left:before { + content: "\f137" +} + +.fa-chevron-circle-right:before { + content: "\f138" +} + +.fa-chevron-circle-up:before { + content: "\f139" +} + +.fa-chevron-circle-down:before { + content: "\f13a" +} + +.fa-html5:before { + content: "\f13b" +} + +.fa-css3:before { + content: "\f13c" +} + +.fa-anchor:before { + content: "\f13d" +} + +.fa-unlock-alt:before { + content: "\f13e" +} + +.fa-bullseye:before { + content: "\f140" +} + +.fa-ellipsis-h:before { + content: "\f141" +} + +.fa-ellipsis-v:before { + content: "\f142" +} + +.fa-rss-square:before { + content: "\f143" +} + +.fa-play-circle:before { + content: "\f144" +} + +.fa-ticket:before { + content: "\f145" +} + +.fa-minus-square:before { + content: "\f146" +} + +.fa-minus-square-o:before { + content: "\f147" +} + +.fa-level-up:before { + content: "\f148" +} + +.fa-level-down:before { + content: "\f149" +} + +.fa-check-square:before { + content: "\f14a" +} + +.fa-pencil-square:before { + content: "\f14b" +} + +.fa-external-link-square:before { + content: "\f14c" +} + +.fa-share-square:before { + content: "\f14d" +} + +.fa-compass:before { + content: "\f14e" +} + +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150" +} + +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151" +} + +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152" +} + +.fa-euro:before, +.fa-eur:before { + content: "\f153" +} + +.fa-gbp:before { + content: "\f154" +} + +.fa-dollar:before, +.fa-usd:before { + content: "\f155" +} + +.fa-rupee:before, +.fa-inr:before { + content: "\f156" +} + +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157" +} + +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158" +} + +.fa-won:before, +.fa-krw:before { + content: "\f159" +} + +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a" +} + +.fa-file:before { + content: "\f15b" +} + +.fa-file-text:before { + content: "\f15c" +} + +.fa-sort-alpha-asc:before { + content: "\f15d" +} + +.fa-sort-alpha-desc:before { + content: "\f15e" +} + +.fa-sort-amount-asc:before { + content: "\f160" +} + +.fa-sort-amount-desc:before { + content: "\f161" +} + +.fa-sort-numeric-asc:before { + content: "\f162" +} + +.fa-sort-numeric-desc:before { + content: "\f163" +} + +.fa-thumbs-up:before { + content: "\f164" +} + +.fa-thumbs-down:before { + content: "\f165" +} + +.fa-youtube-square:before { + content: "\f166" +} + +.fa-youtube:before { + content: "\f167" +} + +.fa-xing:before { + content: "\f168" +} + +.fa-xing-square:before { + content: "\f169" +} + +.fa-youtube-play:before { + content: "\f16a" +} + +.fa-dropbox:before { + content: "\f16b" +} + +.fa-stack-overflow:before { + content: "\f16c" +} + +.fa-instagram:before { + content: "\f16d" +} + +.fa-flickr:before { + content: "\f16e" +} + +.fa-adn:before { + content: "\f170" +} + +.fa-bitbucket:before { + content: "\f171" +} + +.fa-bitbucket-square:before { + content: "\f172" +} + +.fa-tumblr:before { + content: "\f173" +} + +.fa-tumblr-square:before { + content: "\f174" +} + +.fa-long-arrow-down:before { + content: "\f175" +} + +.fa-long-arrow-up:before { + content: "\f176" +} + +.fa-long-arrow-left:before { + content: "\f177" +} + +.fa-long-arrow-right:before { + content: "\f178" +} + +.fa-apple:before { + content: "\f179" +} + +.fa-windows:before { + content: "\f17a" +} + +.fa-android:before { + content: "\f17b" +} + +.fa-linux:before { + content: "\f17c" +} + +.fa-dribbble:before { + content: "\f17d" +} + +.fa-skype:before { + content: "\f17e" +} + +.fa-foursquare:before { + content: "\f180" +} + +.fa-trello:before { + content: "\f181" +} + +.fa-female:before { + content: "\f182" +} + +.fa-male:before { + content: "\f183" +} + +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184" +} + +.fa-sun-o:before { + content: "\f185" +} + +.fa-moon-o:before { + content: "\f186" +} + +.fa-archive:before { + content: "\f187" +} + +.fa-bug:before { + content: "\f188" +} + +.fa-vk:before { + content: "\f189" +} + +.fa-weibo:before { + content: "\f18a" +} + +.fa-renren:before { + content: "\f18b" +} + +.fa-pagelines:before { + content: "\f18c" +} + +.fa-stack-exchange:before { + content: "\f18d" +} + +.fa-arrow-circle-o-right:before { + content: "\f18e" +} + +.fa-arrow-circle-o-left:before { + content: "\f190" +} + +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191" +} + +.fa-dot-circle-o:before { + content: "\f192" +} + +.fa-wheelchair:before { + content: "\f193" +} + +.fa-vimeo-square:before { + content: "\f194" +} + +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195" +} + +.fa-plus-square-o:before { + content: "\f196" +} + +.fa-space-shuttle:before { + content: "\f197" +} + +.fa-slack:before { + content: "\f198" +} + +.fa-envelope-square:before { + content: "\f199" +} + +.fa-wordpress:before { + content: "\f19a" +} + +.fa-openid:before { + content: "\f19b" +} + +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c" +} + +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d" +} + +.fa-yahoo:before { + content: "\f19e" +} + +.fa-google:before { + content: "\f1a0" +} + +.fa-reddit:before { + content: "\f1a1" +} + +.fa-reddit-square:before { + content: "\f1a2" +} + +.fa-stumbleupon-circle:before { + content: "\f1a3" +} + +.fa-stumbleupon:before { + content: "\f1a4" +} + +.fa-delicious:before { + content: "\f1a5" +} + +.fa-digg:before { + content: "\f1a6" +} + +.fa-pied-piper-pp:before { + content: "\f1a7" +} + +.fa-pied-piper-alt:before { + content: "\f1a8" +} + +.fa-drupal:before { + content: "\f1a9" +} + +.fa-joomla:before { + content: "\f1aa" +} + +.fa-language:before { + content: "\f1ab" +} + +.fa-fax:before { + content: "\f1ac" +} + +.fa-building:before { + content: "\f1ad" +} + +.fa-child:before { + content: "\f1ae" +} + +.fa-paw:before { + content: "\f1b0" +} + +.fa-spoon:before { + content: "\f1b1" +} + +.fa-cube:before { + content: "\f1b2" +} + +.fa-cubes:before { + content: "\f1b3" +} + +.fa-behance:before { + content: "\f1b4" +} + +.fa-behance-square:before { + content: "\f1b5" +} + +.fa-steam:before { + content: "\f1b6" +} + +.fa-steam-square:before { + content: "\f1b7" +} + +.fa-recycle:before { + content: "\f1b8" +} + +.fa-automobile:before, +.fa-car:before { + content: "\f1b9" +} + +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba" +} + +.fa-tree:before { + content: "\f1bb" +} + +.fa-spotify:before { + content: "\f1bc" +} + +.fa-deviantart:before { + content: "\f1bd" +} + +.fa-soundcloud:before { + content: "\f1be" +} + +.fa-database:before { + content: "\f1c0" +} + +.fa-file-pdf-o:before { + content: "\f1c1" +} + +.fa-file-word-o:before { + content: "\f1c2" +} + +.fa-file-excel-o:before { + content: "\f1c3" +} + +.fa-file-powerpoint-o:before { + content: "\f1c4" +} + +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5" +} + +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6" +} + +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7" +} + +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8" +} + +.fa-file-code-o:before { + content: "\f1c9" +} + +.fa-vine:before { + content: "\f1ca" +} + +.fa-codepen:before { + content: "\f1cb" +} + +.fa-jsfiddle:before { + content: "\f1cc" +} + +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd" +} + +.fa-circle-o-notch:before { + content: "\f1ce" +} + +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0" +} + +.fa-ge:before, +.fa-empire:before { + content: "\f1d1" +} + +.fa-git-square:before { + content: "\f1d2" +} + +.fa-git:before { + content: "\f1d3" +} + +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4" +} + +.fa-tencent-weibo:before { + content: "\f1d5" +} + +.fa-qq:before { + content: "\f1d6" +} + +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7" +} + +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8" +} + +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9" +} + +.fa-history:before { + content: "\f1da" +} + +.fa-circle-thin:before { + content: "\f1db" +} + +.fa-header:before { + content: "\f1dc" +} + +.fa-paragraph:before { + content: "\f1dd" +} + +.fa-sliders:before { + content: "\f1de" +} + +.fa-share-alt:before { + content: "\f1e0" +} + +.fa-share-alt-square:before { + content: "\f1e1" +} + +.fa-bomb:before { + content: "\f1e2" +} + +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3" +} + +.fa-tty:before { + content: "\f1e4" +} + +.fa-binoculars:before { + content: "\f1e5" +} + +.fa-plug:before { + content: "\f1e6" +} + +.fa-slideshare:before { + content: "\f1e7" +} + +.fa-twitch:before { + content: "\f1e8" +} + +.fa-yelp:before { + content: "\f1e9" +} + +.fa-newspaper-o:before { + content: "\f1ea" +} + +.fa-wifi:before { + content: "\f1eb" +} + +.fa-calculator:before { + content: "\f1ec" +} + +.fa-paypal:before { + content: "\f1ed" +} + +.fa-google-wallet:before { + content: "\f1ee" +} + +.fa-cc-visa:before { + content: "\f1f0" +} + +.fa-cc-mastercard:before { + content: "\f1f1" +} + +.fa-cc-discover:before { + content: "\f1f2" +} + +.fa-cc-amex:before { + content: "\f1f3" +} + +.fa-cc-paypal:before { + content: "\f1f4" +} + +.fa-cc-stripe:before { + content: "\f1f5" +} + +.fa-bell-slash:before { + content: "\f1f6" +} + +.fa-bell-slash-o:before { + content: "\f1f7" +} + +.fa-trash:before { + content: "\f1f8" +} + +.fa-copyright:before { + content: "\f1f9" +} + +.fa-at:before { + content: "\f1fa" +} + +.fa-eyedropper:before { + content: "\f1fb" +} + +.fa-paint-brush:before { + content: "\f1fc" +} + +.fa-birthday-cake:before { + content: "\f1fd" +} + +.fa-area-chart:before { + content: "\f1fe" +} + +.fa-pie-chart:before { + content: "\f200" +} + +.fa-line-chart:before { + content: "\f201" +} + +.fa-lastfm:before { + content: "\f202" +} + +.fa-lastfm-square:before { + content: "\f203" +} + +.fa-toggle-off:before { + content: "\f204" +} + +.fa-toggle-on:before { + content: "\f205" +} + +.fa-bicycle:before { + content: "\f206" +} + +.fa-bus:before { + content: "\f207" +} + +.fa-ioxhost:before { + content: "\f208" +} + +.fa-angellist:before { + content: "\f209" +} + +.fa-cc:before { + content: "\f20a" +} + +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b" +} + +.fa-meanpath:before { + content: "\f20c" +} + +.fa-buysellads:before { + content: "\f20d" +} + +.fa-connectdevelop:before { + content: "\f20e" +} + +.fa-dashcube:before { + content: "\f210" +} + +.fa-forumbee:before { + content: "\f211" +} + +.fa-leanpub:before { + content: "\f212" +} + +.fa-sellsy:before { + content: "\f213" +} + +.fa-shirtsinbulk:before { + content: "\f214" +} + +.fa-simplybuilt:before { + content: "\f215" +} + +.fa-skyatlas:before { + content: "\f216" +} + +.fa-cart-plus:before { + content: "\f217" +} + +.fa-cart-arrow-down:before { + content: "\f218" +} + +.fa-diamond:before { + content: "\f219" +} + +.fa-ship:before { + content: "\f21a" +} + +.fa-user-secret:before { + content: "\f21b" +} + +.fa-motorcycle:before { + content: "\f21c" +} + +.fa-street-view:before { + content: "\f21d" +} + +.fa-heartbeat:before { + content: "\f21e" +} + +.fa-venus:before { + content: "\f221" +} + +.fa-mars:before { + content: "\f222" +} + +.fa-mercury:before { + content: "\f223" +} + +.fa-intersex:before, +.fa-transgender:before { + content: "\f224" +} + +.fa-transgender-alt:before { + content: "\f225" +} + +.fa-venus-double:before { + content: "\f226" +} + +.fa-mars-double:before { + content: "\f227" +} + +.fa-venus-mars:before { + content: "\f228" +} + +.fa-mars-stroke:before { + content: "\f229" +} + +.fa-mars-stroke-v:before { + content: "\f22a" +} + +.fa-mars-stroke-h:before { + content: "\f22b" +} + +.fa-neuter:before { + content: "\f22c" +} + +.fa-genderless:before { + content: "\f22d" +} + +.fa-facebook-official:before { + content: "\f230" +} + +.fa-pinterest-p:before { + content: "\f231" +} + +.fa-whatsapp:before { + content: "\f232" +} + +.fa-server:before { + content: "\f233" +} + +.fa-user-plus:before { + content: "\f234" +} + +.fa-user-times:before { + content: "\f235" +} + +.fa-hotel:before, +.fa-bed:before { + content: "\f236" +} + +.fa-viacoin:before { + content: "\f237" +} + +.fa-train:before { + content: "\f238" +} + +.fa-subway:before { + content: "\f239" +} + +.fa-medium:before { + content: "\f23a" +} + +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b" +} + +.fa-optin-monster:before { + content: "\f23c" +} + +.fa-opencart:before { + content: "\f23d" +} + +.fa-expeditedssl:before { + content: "\f23e" +} + +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240" +} + +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241" +} + +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242" +} + +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243" +} + +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244" +} + +.fa-mouse-pointer:before { + content: "\f245" +} + +.fa-i-cursor:before { + content: "\f246" +} + +.fa-object-group:before { + content: "\f247" +} + +.fa-object-ungroup:before { + content: "\f248" +} + +.fa-sticky-note:before { + content: "\f249" +} + +.fa-sticky-note-o:before { + content: "\f24a" +} + +.fa-cc-jcb:before { + content: "\f24b" +} + +.fa-cc-diners-club:before { + content: "\f24c" +} + +.fa-clone:before { + content: "\f24d" +} + +.fa-balance-scale:before { + content: "\f24e" +} + +.fa-hourglass-o:before { + content: "\f250" +} + +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251" +} + +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252" +} + +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253" +} + +.fa-hourglass:before { + content: "\f254" +} + +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255" +} + +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256" +} + +.fa-hand-scissors-o:before { + content: "\f257" +} + +.fa-hand-lizard-o:before { + content: "\f258" +} + +.fa-hand-spock-o:before { + content: "\f259" +} + +.fa-hand-pointer-o:before { + content: "\f25a" +} + +.fa-hand-peace-o:before { + content: "\f25b" +} + +.fa-trademark:before { + content: "\f25c" +} + +.fa-registered:before { + content: "\f25d" +} + +.fa-creative-commons:before { + content: "\f25e" +} + +.fa-gg:before { + content: "\f260" +} + +.fa-gg-circle:before { + content: "\f261" +} + +.fa-tripadvisor:before { + content: "\f262" +} + +.fa-odnoklassniki:before { + content: "\f263" +} + +.fa-odnoklassniki-square:before { + content: "\f264" +} + +.fa-get-pocket:before { + content: "\f265" +} + +.fa-wikipedia-w:before { + content: "\f266" +} + +.fa-safari:before { + content: "\f267" +} + +.fa-chrome:before { + content: "\f268" +} + +.fa-firefox:before { + content: "\f269" +} + +.fa-opera:before { + content: "\f26a" +} + +.fa-internet-explorer:before { + content: "\f26b" +} + +.fa-tv:before, +.fa-television:before { + content: "\f26c" +} + +.fa-contao:before { + content: "\f26d" +} + +.fa-500px:before { + content: "\f26e" +} + +.fa-amazon:before { + content: "\f270" +} + +.fa-calendar-plus-o:before { + content: "\f271" +} + +.fa-calendar-minus-o:before { + content: "\f272" +} + +.fa-calendar-times-o:before { + content: "\f273" +} + +.fa-calendar-check-o:before { + content: "\f274" +} + +.fa-industry:before { + content: "\f275" +} + +.fa-map-pin:before { + content: "\f276" +} + +.fa-map-signs:before { + content: "\f277" +} + +.fa-map-o:before { + content: "\f278" +} + +.fa-map:before { + content: "\f279" +} + +.fa-commenting:before { + content: "\f27a" +} + +.fa-commenting-o:before { + content: "\f27b" +} + +.fa-houzz:before { + content: "\f27c" +} + +.fa-vimeo:before { + content: "\f27d" +} + +.fa-black-tie:before { + content: "\f27e" +} + +.fa-fonticons:before { + content: "\f280" +} + +.fa-reddit-alien:before { + content: "\f281" +} + +.fa-edge:before { + content: "\f282" +} + +.fa-credit-card-alt:before { + content: "\f283" +} + +.fa-codiepie:before { + content: "\f284" +} + +.fa-modx:before { + content: "\f285" +} + +.fa-fort-awesome:before { + content: "\f286" +} + +.fa-usb:before { + content: "\f287" +} + +.fa-product-hunt:before { + content: "\f288" +} + +.fa-mixcloud:before { + content: "\f289" +} + +.fa-scribd:before { + content: "\f28a" +} + +.fa-pause-circle:before { + content: "\f28b" +} + +.fa-pause-circle-o:before { + content: "\f28c" +} + +.fa-stop-circle:before { + content: "\f28d" +} + +.fa-stop-circle-o:before { + content: "\f28e" +} + +.fa-shopping-bag:before { + content: "\f290" +} + +.fa-shopping-basket:before { + content: "\f291" +} + +.fa-hashtag:before { + content: "\f292" +} + +.fa-bluetooth:before { + content: "\f293" +} + +.fa-bluetooth-b:before { + content: "\f294" +} + +.fa-percent:before { + content: "\f295" +} + +.fa-gitlab:before { + content: "\f296" +} + +.fa-wpbeginner:before { + content: "\f297" +} + +.fa-wpforms:before { + content: "\f298" +} + +.fa-envira:before { + content: "\f299" +} + +.fa-universal-access:before { + content: "\f29a" +} + +.fa-wheelchair-alt:before { + content: "\f29b" +} + +.fa-question-circle-o:before { + content: "\f29c" +} + +.fa-blind:before { + content: "\f29d" +} + +.fa-audio-description:before { + content: "\f29e" +} + +.fa-volume-control-phone:before { + content: "\f2a0" +} + +.fa-braille:before { + content: "\f2a1" +} + +.fa-assistive-listening-systems:before { + content: "\f2a2" +} + +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3" +} + +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4" +} + +.fa-glide:before { + content: "\f2a5" +} + +.fa-glide-g:before { + content: "\f2a6" +} + +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7" +} + +.fa-low-vision:before { + content: "\f2a8" +} + +.fa-viadeo:before { + content: "\f2a9" +} + +.fa-viadeo-square:before { + content: "\f2aa" +} + +.fa-snapchat:before { + content: "\f2ab" +} + +.fa-snapchat-ghost:before { + content: "\f2ac" +} + +.fa-snapchat-square:before { + content: "\f2ad" +} + +.fa-pied-piper:before { + content: "\f2ae" +} + +.fa-first-order:before { + content: "\f2b0" +} + +.fa-yoast:before { + content: "\f2b1" +} + +.fa-themeisle:before { + content: "\f2b2" +} + +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3" +} + +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4" +} + +.fa-handshake-o:before { + content: "\f2b5" +} + +.fa-envelope-open:before { + content: "\f2b6" +} + +.fa-envelope-open-o:before { + content: "\f2b7" +} + +.fa-linode:before { + content: "\f2b8" +} + +.fa-address-book:before { + content: "\f2b9" +} + +.fa-address-book-o:before { + content: "\f2ba" +} + +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb" +} + +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc" +} + +.fa-user-circle:before { + content: "\f2bd" +} + +.fa-user-circle-o:before { + content: "\f2be" +} + +.fa-user-o:before { + content: "\f2c0" +} + +.fa-id-badge:before { + content: "\f2c1" +} + +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2" +} + +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3" +} + +.fa-quora:before { + content: "\f2c4" +} + +.fa-free-code-camp:before { + content: "\f2c5" +} + +.fa-telegram:before { + content: "\f2c6" +} + +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7" +} + +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8" +} + +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9" +} + +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca" +} + +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb" +} + +.fa-shower:before { + content: "\f2cc" +} + +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd" +} + +.fa-podcast:before { + content: "\f2ce" +} + +.fa-window-maximize:before { + content: "\f2d0" +} + +.fa-window-minimize:before { + content: "\f2d1" +} + +.fa-window-restore:before { + content: "\f2d2" +} + +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3" +} + +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4" +} + +.fa-bandcamp:before { + content: "\f2d5" +} + +.fa-grav:before { + content: "\f2d6" +} + +.fa-etsy:before { + content: "\f2d7" +} + +.fa-imdb:before { + content: "\f2d8" +} + +.fa-ravelry:before { + content: "\f2d9" +} + +.fa-eercast:before { + content: "\f2da" +} + +.fa-microchip:before { + content: "\f2db" +} + +.fa-snowflake-o:before { + content: "\f2dc" +} + +.fa-superpowers:before { + content: "\f2dd" +} + +.fa-wpexplorer:before { + content: "\f2de" +} + +.fa-meetup:before { + content: "\f2e0" +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0 +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto +} \ No newline at end of file diff --git a/src/main/resources/static/css/html5bp.css b/src/main/resources/static/css/html5bp.css new file mode 100644 index 0000000..294e019 --- /dev/null +++ b/src/main/resources/static/css/html5bp.css @@ -0,0 +1,304 @@ +/*! HTML5 Boilerplate v4.3.0 | MIT License | http://h5bp.com/ */ + +/* + * What follows is the result of much research on cross-browser styling. + * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, + * Kroc Camen, and the H5BP dev community and team. + */ + +/* ========================================================================== + Base styles: opinionated defaults + ========================================================================== */ + +html, +button, +input, +select, +textarea { + color: #222; +} + +html { + font-size: 1em; + line-height: 1.4; +} + +/* + * Remove text-shadow in selection highlight: h5bp.com/i + * These selection rule sets have to be separate. + * Customize the background color to match your design. + */ + +::-moz-selection { + background: #b3d4fc; + text-shadow: none; +} + +::selection { + background: #b3d4fc; + text-shadow: none; +} + +/* + * A better looking default horizontal rule + */ + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; + margin: 1em 0; + padding: 0; +} + +/* + * Remove the gap between images, videos, audio and canvas and the bottom of + * their containers: h5bp.com/i/440 + */ + +audio, +canvas, +img, +video { + vertical-align: middle; +} + +/* + * Remove default fieldset styles. + */ + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +/* + * Allow only vertical resizing of textareas. + */ + +textarea { + resize: vertical; +} + +/* ========================================================================== + Browse Happy prompt + ========================================================================== */ + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +/* ========================================================================== + Author's custom styles + ========================================================================== */ + + + + + + + + + + + + + + + + + +/* ========================================================================== + Helper classes + ========================================================================== */ + +/* + * Image replacement + */ + +.ir { + background-color: transparent; + border: 0; + overflow: hidden; + /* IE 6/7 fallback */ + *text-indent: -9999px; +} + +.ir:before { + content: ""; + display: block; + width: 0; + height: 150%; +} + +/* + * Hide from both screenreaders and browsers: h5bp.com/u + */ + +.hidden { + display: none !important; + visibility: hidden; +} + +/* + * Hide only visually, but have it available for screenreaders: h5bp.com/v + */ + +.visuallyhidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +/* + * Extends the .visuallyhidden class to allow the element to be focusable + * when navigated to via the keyboard: h5bp.com/p + */ + +.visuallyhidden.focusable:active, +.visuallyhidden.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; +} + +/* + * Hide visually and from screenreaders, but maintain layout + */ + +.invisible { + visibility: hidden; +} + +/* + * Clearfix: contain floats + * + * For modern browsers + * 1. The space content is one way to avoid an Opera bug when the + * `contenteditable` attribute is included anywhere else in the document. + * Otherwise it causes space to appear at the top and bottom of elements + * that receive the `clearfix` class. + * 2. The use of `table` rather than `block` is only necessary if using + * `:before` to contain the top-margins of child elements. + */ + +.clearfix:before, +.clearfix:after { + content: " "; /* 1 */ + display: table; /* 2 */ +} + +.clearfix:after { + clear: both; +} + +/* + * For IE 6/7 only + * Include this rule to trigger hasLayout and contain floats. + */ + +.clearfix { + *zoom: 1; +} + +/* ========================================================================== + EXAMPLE Media Queries for Responsive Design. + These examples override the primary ('mobile first') styles. + Modify as content requires. + ========================================================================== */ + +@media only screen and (min-width: 35em) { + /* Style adjustments for viewports that meet the condition */ +} + +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + /* Style adjustments for high resolution devices */ +} + +/* ========================================================================== + Print styles. + Inlined to avoid required HTTP connection: h5bp.com/r + ========================================================================== */ + +@media print { + * { + background: transparent !important; + color: #000 !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) ")"; + } + + /* + * Don't show links for images, or javascript/internal links + */ + + .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; /* 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; + } +} diff --git a/src/main/resources/static/css/normalize.css b/src/main/resources/static/css/normalize.css new file mode 100644 index 0000000..42e24d6 --- /dev/null +++ b/src/main/resources/static/css/normalize.css @@ -0,0 +1,527 @@ +/*! normalize.css v1.1.3 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +/** + * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4. + * Known issue: no IE 6 support. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/** + * 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-size: 100%; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Address `font-family` inconsistency between `textarea` and other form + * elements. + */ + +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/** + * Address margins handled incorrectly in IE 6/7. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/** + * 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 font sizes and margins set differently in IE 6/7. + * Address font sizes within `section` and `article` in Firefox 4+, Safari 5, + * and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.67em; + margin: 2.33em 0; +} + +/** + * Address styling not present in IE 7/8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/** + * Address styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address differences between Firefox and other browsers. + * Known issue: no IE 6/7 normalization. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Address styling not present in IE 6/7/8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address margins set differently in IE 6/7. + */ + +p, +pre { + margin: 1em 0; +} + +/** + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/** + * Improve readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/** + * Address CSS quotes not supported in IE 6/7. + */ + +q { + quotes: none; +} + +/** + * Address `quotes` property not supported in Safari 4. + */ + +q:before, +q:after { + content: ''; + content: none; +} + +/** + * 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; +} + +/* ========================================================================== + Lists + ========================================================================== */ + +/** + * Address margins set differently in IE 6/7. + */ + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/** + * Address paddings set differently in IE 6/7. + */ + +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/** + * Correct list images handled incorrectly in IE 7. + */ + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3. + * 2. Improve image quality when scaled in IE 7. + */ + +img { + border: 0; /* 1 */ + -ms-interpolation-mode: bicubic; /* 2 */ +} + +/** + * Correct overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/** + * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/** + * Correct margin displayed oddly in IE 6/7. + */ + +form { + margin: 0; +} + +/** + * 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 6/7/8/9. + * 2. Correct text not wrapping in Firefox 3. + * 3. Correct alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; + white-space: normal; /* 2 */ + *margin-left: -7px; /* 3 */ +} + +/** + * 1. Correct font size not being inherited in all browsers. + * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5, + * and Chrome. + * 3. Improve appearance and consistency in all browsers. + */ + +button, +input, +select, +textarea { + font-size: 100%; /* 1 */ + margin: 0; /* 2 */ + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ +} + +/** + * Address Firefox 3+ 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 6+. + * 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. + * 4. Remove inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + *overflow: visible; /* 4 */ +} + +/** + * 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. + * 3. Remove excess padding in IE 7. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ +} + +/** + * 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 3+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * 1. Remove default vertical scrollbar in IE 6/7/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/src/main/resources/static/css/owl.carousel.css b/src/main/resources/static/css/owl.carousel.css new file mode 100755 index 0000000..015c7a6 --- /dev/null +++ b/src/main/resources/static/css/owl.carousel.css @@ -0,0 +1,233 @@ +/** + * Owl Carousel v2.2.1 + * Copyright 2013-2017 David Deutsch + * Licensed under () + */ + + +/* + * Owl Carousel - Core + */ + +.owl-carousel { + display: none; + width: 100%; + -webkit-tap-highlight-color: transparent; + /* position relative and z-index fix webkit rendering fonts issue */ + position: relative; + z-index: 1; +} + +.owl-carousel .owl-stage { + position: relative; + -ms-touch-action: pan-Y; + -moz-backface-visibility: hidden; + /* fix firefox animation glitch */ +} + +.owl-carousel .owl-stage:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.owl-carousel .owl-stage-outer { + position: relative; + overflow: hidden; + /* fix for flashing background */ + -webkit-transform: translate3d(0px, 0px, 0px); +} + +.owl-carousel .owl-wrapper, +.owl-carousel .owl-item { + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); +} + +.owl-carousel .owl-item { + position: relative; + min-height: 1px; + float: left; + -webkit-backface-visibility: hidden; + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; +} + +.owl-carousel .owl-item img { + display: block; + width: 100%; +} + +.owl-carousel .owl-nav.disabled, +.owl-carousel .owl-dots.disabled { + display: none; +} + +.owl-carousel .owl-nav .owl-prev, +.owl-carousel .owl-nav .owl-next, +.owl-carousel .owl-dot { + cursor: pointer; + cursor: hand; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.owl-carousel.owl-loaded { + display: block; +} + +.owl-carousel.owl-loading { + opacity: 0; + display: block; +} + +.owl-carousel.owl-hidden { + opacity: 0; +} + +.owl-carousel.owl-refresh .owl-item { + visibility: hidden; +} + +.owl-carousel.owl-drag .owl-item { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.owl-carousel.owl-grab { + cursor: move; + cursor: grab; +} + +.owl-carousel.owl-rtl { + direction: rtl; +} + +.owl-carousel.owl-rtl .owl-item { + float: right; +} + + +/* No Js */ + +.no-js .owl-carousel { + display: block; +} + + +/* + * Owl Carousel - Animate Plugin + */ + +.owl-carousel .animated { + animation-duration: 1000ms; + animation-fill-mode: both; +} + +.owl-carousel .owl-animated-in { + z-index: 0; +} + +.owl-carousel .owl-animated-out { + z-index: 1; +} + +.owl-carousel .fadeOut { + animation-name: fadeOut; +} + +@keyframes fadeOut { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + + +/* + * Owl Carousel - Auto Height Plugin + */ + +.owl-height { + transition: height 500ms ease-in-out; +} + + +/* + * Owl Carousel - Lazy Load Plugin + */ + +.owl-carousel .owl-item .owl-lazy { + opacity: 0; + transition: opacity 400ms ease; +} + +.owl-carousel .owl-item img.owl-lazy { + transform-style: preserve-3d; +} + + +/* + * Owl Carousel - Video Plugin + */ + +.owl-carousel .owl-video-wrapper { + position: relative; + height: 100%; + background: #000; +} + +.owl-carousel .owl-video-play-icon { + position: absolute; + height: 80px; + width: 80px; + left: 50%; + top: 50%; + margin-left: -40px; + margin-top: -40px; + background: url("owl.video.play.png") no-repeat; + cursor: pointer; + z-index: 1; + -webkit-backface-visibility: hidden; + transition: transform 100ms ease; +} + +.owl-carousel .owl-video-play-icon:hover { + -ms-transform: scale(1.3, 1.3); + transform: scale(1.3, 1.3); +} + +.owl-carousel .owl-video-playing .owl-video-tn, +.owl-carousel .owl-video-playing .owl-video-play-icon { + display: none; +} + +.owl-carousel .owl-video-tn { + opacity: 0; + height: 100%; + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + transition: opacity 400ms ease; +} + +.owl-carousel .owl-video-frame { + position: relative; + z-index: 1; + height: 100%; + width: 100%; +} \ No newline at end of file diff --git a/src/main/resources/static/css/particles.css b/src/main/resources/static/css/particles.css new file mode 100755 index 0000000..c4a5ac8 --- /dev/null +++ b/src/main/resources/static/css/particles.css @@ -0,0 +1,58 @@ +/* ---- reset ---- */ + +body { + margin: 0; + font-family: "Lato", sans-serif; +} + +canvas { + display: block; + vertical-align: bottom; +} + + +/* ---- particles.js container ---- */ + +#particles-js { + position: absolute; + width: 100%; + height: 100%; +} + + +/* ---- stats.js ---- */ + +.count-particles { + position: absolute; + top: 48px; + left: 0; + width: 80px; + color: #13E8E9; + font-size: .8em; + text-align: left; + text-indent: 4px; + line-height: 14px; + padding-bottom: 2px; + font-family: Helvetica, Arial, sans-serif; + font-weight: bold; +} + +.js-count-particles { + font-size: 1.1em; +} + +#stats, +.count-particles { + -webkit-user-select: none; + margin-top: 5px; + margin-left: 5px; +} + +#stats { + border-radius: 3px 3px 0 0; + overflow: hidden; +} + +.count-particles { + border-radius: 0 0 3px 3px; +} \ No newline at end of file diff --git a/src/main/resources/static/css/strategy-form.css b/src/main/resources/static/css/strategy-form.css new file mode 100755 index 0000000..967f158 --- /dev/null +++ b/src/main/resources/static/css/strategy-form.css @@ -0,0 +1,245 @@ +/*form styles*/ +#msform { + text-align: center; + position: relative; + margin-top: 30px; + min-height: 100px; +} + +#msform fieldset { + background: white; + border: 0 none; + border-radius: 0px; + box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.4); + padding: 20px 30px; + box-sizing: border-box; + width: 80%; + margin: 0 10%; + min-height: 200px; + + /*stacking fieldsets above each other*/ + position: relative; +} + +/*Hide all except first fieldset*/ +#msform fieldset:not(:first-of-type) { + display: none; +} + +/*inputs*/ +#msform input { + padding: 15px; + border: 1px solid #ccc; + border-radius: 0px; + margin-bottom: 10px; + width: 80%; + box-sizing: border-box; + font-family: montserrat; + color: #2C3E50; + font-size: 13px; + margin-left: 10px; +} + +.popover-icon-strategy { + font-size: 12px; +} + +.strategy-form-label { + color: #75849a; + font-size: 15px; +} + +#msform .coin-input { + padding: 15px; + border: 1px solid #ccc; + border-radius: 0px; + margin-bottom: 10px; + margin-right: 20px; + width: auto; + box-sizing: border-box; + font-family: montserrat; + color: #2C3E50; + font-size: 13px; +} + + #msform textarea { + padding: 15px; + border: 1px solid #ccc; + border-radius: 0px; + margin-bottom: 10px; + width: 100%; + box-sizing: border-box; + font-family: montserrat; + color: #2C3E50; + font-size: 13px; +} + +#msform input:focus, #msform textarea:focus { + -moz-box-shadow: none !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + border: 1px solid #20509e; + outline-width: 0; + transition: All 0.5s ease-in; + -webkit-transition: All 0.5s ease-in; + -moz-transition: All 0.5s ease-in; + -o-transition: All 0.5s ease-in; +} + +/*buttons*/ +#msform .action-button { + width: 100px; + font-weight: bold; + color: white; + border: 0 none; + border-radius: 25px; + cursor: pointer; + padding: 10px 5px; + margin: 10px 5px; +} + +#msform .action-button:hover, #msform .action-button:focus { + box-shadow: 0 0 0 2px white, 0 0 0 3px #20509e; +} + +#msform .action-button-previous { + width: 100px; + background: #C5C5F1; + font-weight: bold; + color: white; + border: 0 none; + border-radius: 25px; + cursor: pointer; + padding: 10px 5px; + margin: 10px 5px; +} + +.action-button-previous { + width: 100px; + background: #C5C5F1; + font-weight: bold; + color: white; + border: 0 none; + border-radius: 25px; + cursor: pointer; + padding: 10px 5px; + margin: 10px 5px; +} + + + +#msform .action-button-previous:hover, #msform .action-button-previous:focus { + box-shadow: 0 0 0 2px white, 0 0 0 3px #C5C5F1; +} + +/*headings*/ +.fs-title { + font-size: 18px; + text-transform: uppercase; + color: #2C3E50; + margin-bottom: 10px; + letter-spacing: 2px; + font-weight: bold; +} + +.fs-subtitle { + font-weight: normal; + font-size: 13px; + color: #666; + margin-bottom: 20px; +} + +.fs-finalize-title { + font-size: 18px; + color: #2C3E50; + margin-bottom: 10px; + margin-top: 10px; + letter-spacing: 2px; + font-weight: bold; +} + +.fs-finalize-subtitle { + font-weight: normal; + margin-bottom: 6px; + font-size: 16px; + color: #666; +} + +/*progressbar*/ +#progressbar { + margin-bottom: 30px; + overflow: hidden; + /*CSS counters to number the steps*/ + counter-reset: step; +} + +#progressbar li { + list-style-type: none; + color: #666; + text-transform: uppercase; + font-size: 9px; + width: 33.33%; + float: left; + position: relative; + letter-spacing: 1px; +} + +#progressbar li:before { + content: counter(step); + counter-increment: step; + width: 24px; + height: 24px; + line-height: 26px; + display: block; + font-size: 12px; + color: #333; + background: white; + border-radius: 25px; + margin: 0 auto 10px auto; +} + +/*progressbar connectors*/ +#progressbar li:after { + content: ''; + width: 100%; + height: 2px; + background: white; + position: absolute; + left: -50%; + top: 9px; + z-index: -1; /*put it behind the numbers*/ +} + +#progressbar li:first-child:after { + /*connector not needed before the first step*/ + content: none; +} + +/*marking active/completed steps green*/ +/*The number of the step and the connector before it = green*/ +#progressbar li.active:before, #progressbar li.active:after { + background: #20509e; + color: white; +} + + +/* Not relevant to this form */ +.dme_link { + margin-top: 30px; + text-align: center; +} +.dme_link a { + background: #FFF; + font-weight: bold; + color: #20509e; + border: 0 none; + border-radius: 25px; + cursor: pointer; + padding: 5px 25px; + font-size: 12px; +} + +.dme_link a:hover, .dme_link a:focus { + background: #C5C5F1; + text-decoration: none; +} \ No newline at end of file diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css new file mode 100755 index 0000000..56cd04c --- /dev/null +++ b/src/main/resources/static/css/style.css @@ -0,0 +1,2151 @@ + +@font-face { + font-family: 'Futura'; + src: url("../fonts/Futura.woff"); +} + +html, +body { + height: 100%; + font-family: "Lato", sans-serif; + -webkit-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: #20509e; + margin: 0; + font-weight: 500; + font-family: "Futura", sans-serif; +} + +h1 { + font-size: 70px; +} + +h2 { + font-size: 48px; +} + +h3 { + font-size: 30px; +} + +h4 { + font-size: 24px; +} + +h5 { + font-size: 20px; +} + +h6 { + font-size: 14px; +} + +p { + font-size: 15.7px; + color: #75849a; + line-height: 1.6; +} + +img { + max-width: 100%; +} + +#footer-logo { + max-width: calc(80px + 35%); +} + +#header-logo { + max-width: calc(55px + 6.5vw) +} + +input:focus, +select:focus, +button:focus, +textarea:focus { + outline: none; +} + +a:hover, +a:focus { + text-decoration: none; + outline: none; +} + +ul, +ol { + padding: 0; + margin: 0; +} + +/*--------------------- + Helper CSS +-----------------------*/ + +.spad { + padding-top: 70px; + padding-bottom: 90px; +} + +.section-title { + margin-bottom: 60px; +} + +.section-title h2 { + margin-bottom: 20px; +} + +.section-title p { + margin-bottom: 0; +} + +.set-bg { + background-repeat: no-repeat; + background-size: cover; + background-position: center 0; +} + +.text-white h1, +.text-white h2, +.text-white h3, +.text-white h4, +.text-white h5, +.text-white p, +.text-white span, +.text-white li, +.text-white a { + color: #fff; +} + +/*--------------------- + Commom elements +-----------------------*/ + +.animation, .staggered-animation { + visibility: hidden; +} + + +/* Buttons */ + +.site-btn { + position: relative; + display: inline-block; + padding: 13px 10px; + font-size: 16px; + font-weight: 500; + line-height: 20px; + border-radius: 50px; + font-family: "Futura", sans-serif; + min-width: 150px; + text-align: center; + border: 2px solid #7ad4cc; + cursor: pointer; + color: #fff; +} + +.site-btn:hover { + color: #fff; +} + +.form-btn { + color: black; + padding: 10px 25px; +} + +.form-btn:hover { + color: #3e2bce; +} + +.site-btn.no-radius { + border-radius: 2px; +} + +.site-btn.sb-full-- { + display: block; + width: 100%; + border-radius: 0; +} + +.site-btn.sb-gradients { + padding: 17px 32px; + border: none; + color: #fff; +} + +.site-btn.sb-gradients.sbg-line { + color: #20509e; + z-index: 1; +} + +.site-btn.sb-gradients.sbg-line:after { + position: absolute; + content: ''; + width: calc(100% - 4px); + height: calc(100% - 4px); + background: #fff; + top: 2px; + left: 2px; + z-index: -1; + border-radius: 50px; +} + +.site-btn.sb-gradients.sbg-line:hover { + color: #20509e; +} + +.gradient-bg, +.site-btn.sb-gradients, +.member-social a:hover, +.single-blog-page .social-share a:hover, +.comment .comment-content .c-btn:hover, +.comment-form label { + /* FF3.6-15 */ + /* Chrome10-25,Safari5.1-6 */ + background: -webkit-gradient(linear, left top, right top, from(#3e2bce), color-stop(100%, #2dd3aa), color-stop(100%, #2dd3aa), to(#2dd3aa)); + background: -o-linear-gradient(left, #3e2bce 0%, #2dd3aa 100%, #2dd3aa 100%, #2dd3aa 100%); + background: linear-gradient(to right, #3e2bce 0%, #2dd3aa 100%, #2dd3aa 100%, #2dd3aa 100%); + /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3e2bce', endColorstr='#2dd3aa', GradientType=1); + /* IE6-9 */ +} + +/* Image Popup */ + +.img-popup-warp .mfp-content, +.img-popup-warp.mfp-ready.mfp-removing .mfp-content { + opacity: 0; + -webkit-transform: scale(0.8); + -ms-transform: scale(0.8); + transform: scale(0.8); + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; +} + +.img-popup-warp.mfp-ready .mfp-content { + opacity: 1; + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); +} + +/* Preloder */ + +#preloder { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 999999; + background: #fff; +} + +.loader { + width: 40px; + height: 40px; + position: absolute; + top: 50%; + left: 50%; + margin-top: -13px; + margin-left: -13px; + border-radius: 60px; + animation: loader 0.8s linear infinite; + -webkit-animation: loader 0.8s linear infinite; +} + +#profile-preloader { + width: 40px; + height: 40px; + position: absolute; + top: 50%; + left: 50%; + margin-top: -13px; + margin-left: -13px; + border-radius: 60px; + animation: loader 1.0s linear infinite; + -webkit-animation: loader 1.0s linear infinite; +} + +.profile-subtitle { + /*margin-left: 20px;*/ + height: 30px; + border: none; + border-bottom: 2px solid #2e6da43b; + font-size: 16px; + margin-bottom: 2.5em; + margin-top: 1em; +} + +.activated-tab { + color: black; +} + +#custom-preloader, #manual-preloader { + width: 40px; + height: 40px; + position: absolute; + top: 60%; + left: 50%; + margin-top: -13px; + margin-left: -13px; + border-radius: 60px; + animation: loader 1.0s linear infinite; + -webkit-animation: loader 1.0s linear infinite; +} + +@keyframes loader { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + border: 4px solid #f44336; + border-left-color: transparent; + } + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + border: 4px solid #673ab7; + border-left-color: transparent; + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + border: 4px solid #f44336; + border-left-color: transparent; + } +} + +@-webkit-keyframes loader { + 0% { + -webkit-transform: rotate(0deg); + border: 4px solid #f44336; + border-left-color: transparent; + } + 50% { + -webkit-transform: rotate(180deg); + border: 4px solid #673ab7; + border-left-color: transparent; + } + 100% { + -webkit-transform: rotate(360deg); + border: 4px solid #f44336; + border-left-color: transparent; + } +} + +/*--------------------- + Header section +-----------------------*/ + +.header-section { + position: absolute; + width: 100%; + top: 0; + padding: 20px 50px 0; + z-index: 99; +} + +.header-section .site-btn { + float: right; + margin-left: 60px; +} + +.header-section .responsive-bar, +.header-section .user { + display: none; +} + +.main-menu { + float: right; +} + +.menu-list { + list-style: none; +} + +.menu-list li { + display: inline; +} + +.menu-list li a { + display: inline-block; + font-family: "Futura", sans-serif; + font-size: 16px; + padding: 10px 5px; + margin-right: 30px; + color: #fff; +} + +.header-section #welcomeHeader { + text-align: right; + color: #fff; + margin-right: 30px; + margin-bottom: 5px; +} + +/*--------------------- + Hero Section +-----------------------*/ + +.hero-section { + height: 900px; + padding-top: 150px; + display: block; + /*background-image: url("../img/hero-background4.jpg");*/ + background-size: cover; + background-color: black; + background-position: right top; + background-repeat: no-repeat; + position: relative; + overflow: hidden; +} + +.hero-section .laptop-image { + width: 685px; + max-width: none; + position: relative; + left: 80px; +} + +.hero-text { + padding-top: 60px; +} + +.hero-text h2 { + font-size: 70px; + /*margin-bottom: 35px;*/ +} + +.hero-text h2 span { + font-size: 70px; + color: #ffffff; +} + +.hero-text h4 { + color: #75849a; + font-size: 22px; +} + +.hero-subscribe-from { + margin-top: 50px; + display: block; +} + +.hero-subscribe-from input { + width: 315px; + border: 1px solid #ebebeb; + background: #fff; + height: 48px; + padding: 0 25px; + border-radius: 50px; + font-family: "Futura", sans-serif; + font-size: 16px; + margin-right: 8px; + margin-bottom: 20px; +} + +/*--------------------- + About Section +-----------------------*/ + +.about-section .container { + position: relative; +} + +.about-text h2 { + font-size: 48px; + margin-bottom: 25px; +} + +.about-text h3 { + font-size: 36px; + margin-top: 25px; + margin-bottom: 25px; + +} + +.about-text h5 { + font-family: "Lato", sans-serif; + margin-bottom: 10px; +} + +.about-text p { + font-size: 18px; +} + +.about-img { + border-radius: 10px; + position: absolute; + top: -50px; + width: 500px; +} +#bitcoin { + -webkit-box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + border-radius: 10px; +} + +/*--------------------- + Feature Section +-----------------------*/ + +.features-section .container { + margin-bottom: -45px; +} + +.feature { + margin-bottom: 45px; +} + +.feature i { + font-size: 48px; + float: left; + padding-top: 10px; +} + +.feature .feature-content { + padding-left: 70px; +} + +.feature .feature-content h4 { + margin-bottom: 15px; +} + +.feature .readmore { + text-decoration: underline; + line-height: 1.2; +} + + +/*--------------------- + Fact Section +-----------------------*/ + +/*.fact-section { + padding: 100px 0; +} + +.fact { + display: inline-block; + position: relative; +} + +.fact h2 { + float: left; + color: #16d0c5; + font-size: 60px; + margin-right: 20px; +} + +.fact p { + float: left; + padding-top: 14px; + line-height: 1.4; + color: #fff; + text-transform: uppercase; +} + +.fact i { + position: absolute; + right: -20px; + top: -10px; + font-size: 90px; + color: #fff; + z-index: 0; + opacity: 0.1; +}*/ + +/*--------------------- + Trade Section +-----------------------*/ +#trade-before-log-in { + margin-top: 100px; +} + +#trade-before-row { + text-align: right; +} + +#blockchain { + -webkit-box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + border-radius: 10px; + +} + +#blockchain:hover { + -webkit-box-shadow: 1px 14px 43px rgba(33, 54, 61, 0.15); + box-shadow: 1px 14px 43px rgba(33, 54, 61, 0.15); +} + +#trade-before-info{ + text-align: center; + font-size: 20px; +} + +.trade { + position: relative; + display: inline-block; + padding: 13px 10px; + font-size: 16px; + font-weight: 500; + line-height: 20px; + border-radius: 50px; + font-family: "Futura", sans-serif; + min-width: 150px; + text-align: center; + border: 2px solid #7ad4cc; + cursor: pointer; + color: black; +} + +/*--------------------- + Wallet Section +-----------------------*/ + +.wallet { + background: #fff; + display: inline-block; + width: 360px; + margin: 0 10px; + text-align: center; + padding: 50px 10px; + -webkit-box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + border-radius: 10px; + position: relative; +} + +.wallet h2 { + font-size: 22px; + margin-bottom: 5px; +} + +.wallet span { + font-size: 14px; + color: #75849a; + display: block; +} + +.wallet .wallet-text { + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; + opacity: 1; + height: 250px; +} + +.wallet:hover { + -webkit-box-shadow: 1px 14px 43px rgba(33, 54, 61, 0.15); + box-shadow: 1px 14px 43px rgba(33, 54, 61, 0.15); +} + +.wallet-img { + width: 230px; + height: 230px; + display: inline-block; + border-radius: 50%; + margin-bottom: 25px; +} + +.wallet-meta { + padding-left: 85px; +} + +.wallet-info { + padding: 50px 60px 10px; + position: absolute; + width: 100%; + top: 0; + left: 0; + text-align: left; + opacity: 0; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; + height: 100px; + overflow-y: auto; +} + +.wallet-info p { + display: block; + padding-top: 25px; + margin-bottom: 0; +} + +.wallet-img.mf { + width: 60px; + height: 60px; + opacity: 1; + float: left; + margin-bottom: 0; +} + +.asset { + position: relative; + display: inline-block; + padding: 13px 10px; + font-size: 16px; + font-weight: 500; + line-height: 20px; + border-radius: 50px; + font-family: "Futura", sans-serif; + min-width: 150px; + text-align: center; + border: 2px solid #7ad4cc; + cursor: pointer; + color: black; +} + +.assets-container { + margin-bottom: 20px; + overflow-y: auto; + max-height: 200px; +} + +/*--------------------- + Team Section +-----------------------*/ + +.team-section { + background: #f3f7f9; + overflow: hidden; +} + +.team-members { + margin: 0 -10px; +} + +.team-members { + text-align: center; +} + +.member { + background: #fff; + width: calc(20% - 25px); + display: inline-block; + margin: 0 10px; + text-align: center; + padding: 50px 10px; + -webkit-box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + box-shadow: 1px 1px 1px rgba(33, 54, 61, 0.15); + border-radius: 10px; + position: relative; +} + +.member h2 { + font-size: 22px; + margin-bottom: 5px; +} + +.member span { + font-size: 14px; + color: #75849a; + display: block; +} + +.member .member-text { + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; + opacity: 1; +} + +.member:hover { + -webkit-box-shadow: 1px 14px 43px rgba(33, 54, 61, 0.15); + box-shadow: 1px 14px 43px rgba(33, 54, 61, 0.15); +} + +.member:hover .member-info { + opacity: 1; +} + +.member:hover .member-text { + opacity: 0; +} + +.member-img { + width: 230px; + height: 230px; + display: inline-block; + border-radius: 50%; + margin-bottom: 25px; +} + +.member-social { + padding-top: 25px; + background: #fff; + position: relative; + z-index: 2; +} + +.member-social a { + width: 50px; + height: 50px; + display: inline-block; + border-radius: 50%; + background: #cbd3df; + color: #fff; + padding-top: 13px; + margin: 0 8px; +} + +.member-meta { + padding-left: 85px; +} + +.member-info { + padding: 50px 60px 10px; + position: absolute; + width: 100%; + top: 0; + left: 0; + text-align: left; + opacity: 0; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; + height: 380px; + overflow-y: auto; +} + +.member-info p { + display: block; + padding-top: 25px; + margin-bottom: 0; +} + +.member-img.mf { + width: 60px; + height: 60px; + opacity: 1; + float: left; + margin-bottom: 0; +} + +/*--------------------- + Review Section +-----------------------*/ + +.review-meta-slider { + position: relative; + width: 300px; +} + +.author-meta { + padding: 50px 0 70px; + position: relative; + text-align: center; +} + +.author-meta:last-child { + margin-right: 0; +} + +.author-avatar { + width: 80px; + height: 80px; + border: 6px solid #fff; + border-radius: 50%; + -webkit-box-shadow: 0px 16px 21px rgba(33, 54, 61, 0.15); + box-shadow: 0px 16px 21px rgba(33, 54, 61, 0.15); + display: inline-block; +} + +.author-avatar h4 { + font-size: 22px; +} + +.author-avatar p { + font-size: 14px; +} + +.author-name { + position: absolute; + width: 280px; + left: -50%; + bottom: -10px; + margin-left: -50px; + text-align: center; + visibility: hidden; +} + +.center .author-meta { + top: -6px; +} + +.center .author-name { + visibility: visible; +} + +.center .author-avatar { + width: 100px; + height: 100px; +} + +.review-text p { + font-size: 22px; +} + +.review-text-slider .owl-nav { + padding-top: 15px; +} + +.review-text-slider .owl-prev, +.review-text-slider .owl-next { + width: 50px; + height: 50px; + display: inline-block; + background: #cbd3df; + color: #fff; + font-size: 24px; + text-align: center; + margin-right: 10px; + border-radius: 50%; + padding-top: 8px; +} + +.pull-3 { + right: 66.666667%; +} + +.push-8 { + left: 33.333333%; +} + +/*--------------------- + Newsletter Section +-----------------------*/ + +.newsletter-section { + padding: 50px 0; +} + +.newsletter-text h2 { + font-size: 36px; + margin-bottom: 10px; +} + +.newsletter-text p { + margin-bottom: 0; +} + +.newsletter-form { + position: relative; + margin-top: 20px; + padding-left: 40px; +} + +.newsletter-form input { + width: 100%; + font-size: 16px; + padding: 12px 30px; + border: none; + border-radius: 50px; + padding-right: 160px; + background: rgba(255, 255, 255, 0.2); + color: #fff; +} + +.newsletter-form button { + position: absolute; + right: 0; + top: 0; + height: 100%; + border: none; + border-radius: 0px 50px 50px 0px; + min-width: 140px; + background: #fff; + color: #20509e; + font-size: 14px; + font-weight: 600; + cursor: pointer; +} + +.newsletter-form a { + padding-top: 12px; + position: absolute; + right: 0; + top: 0; + height: 100%; + border: none; + border-radius: 0px 50px 50px 0px; + min-width: 140px; + background: #fff; + color: #20509e; + font-size: 14px; + font-weight: 600; + cursor: pointer; + text-align: center; +} + +.newsletter-form ::-webkit-input-placeholder { + color: #fff; +} + +.newsletter-form :-ms-input-placeholder { + color: #fff; +} + +.newsletter-form ::-ms-input-placeholder { + color: #fff; +} + +.newsletter-form ::placeholder { + color: #fff; +} + +.newsletter-button { + text-align: center; +} + +/*--------------------- + Blog Section +-----------------------*/ + +.blog-section { + background: #f3f7f9; +} + +.blog-thumb { + margin-bottom: 0; +} + +.blog-text { + background: #fff; + padding: 30px; + -webkit-box-shadow: 0px 23px 49px rgba(33, 54, 61, 0.1); + box-shadow: 0px 23px 49px rgba(33, 54, 61, 0.1); +} + +.blog-text .post-date { + font-size: 14px; + font-family: "Futura", sans-serif; + color: #16d0c5; + text-transform: uppercase; + margin-bottom: 15px; + display: block; + letter-spacing: 2px; +} + +.blog-text .blog-title { + font-size: 22px; + margin-bottom: 20px; +} + +.blog-text .blog-title a { + color: #20509e; +} + +.blog-text .post-meta a { + font-size: 13px; + color: #75849a; + margin-right: 25px; +} + +.blog-text .post-meta a:last-child { + margin-right: 0; +} + +.blog-text .post-meta a span { + color: #cbd3df; +} + +.blog-text .post-meta a i { + color: #16d0c5; +} + +.post-loadmore { + width: 100%; + border-radius: 0px; +} + +.post-loadmore.site-btn.sb-gradients.sbg-line:after { + border-radius: 0px; +} + +/*--------------------- + Footer Section +-----------------------*/ + +.footer-widget span { + color: #acb9cc; +} + +.footer-widget p { + margin-bottom: 20px; +} + +.footer-widget .widget-title { + margin-bottom: 30px; + font-size: 20px; +} + +.footer-widget ul { + list-style: none; +} + +.footer-widget ul a, span { + font-size: 16px; + color: #75849a; + display: block; + margin-bottom: 12px; +} + +.footer-widget ul li:last-child a { + margin-bottom: 0; +} + +.social a { + width: 40px; + height: 40px; + border-radius: 50%; + color: #fff; + display: inline-block; + margin-right: 10px; + text-align: center; + padding-top: 7px; + font-size: 18px; +} + +.social a:last-child { + margin-right: 0; +} + +.social .facebook { + background: #4b6cd0; +} + +.social .youtube { + background: #f03b3b; +} + +.social .instagram { + background: #bb8950; +} + +.social .twitter { + background: #49a7f3; +} + +.footer-bottom { + border-top: 1px solid #ebebeb; + padding: 30px 0; +} + +.footer-nav { + list-style: none; +} + +.footer-nav li { + display: inline-block; +} + +.footer-nav li a, .footer-nav-element { + color: #75849a; + font-size: 14px; + margin-left: 20px; +} + +.footer-download-buttons { + max-width: calc(30px + 7.5vw); +} + + +/*--------------------- + Other Pages +---------------------- +======================*/ + +.page-info-section { + /*height: 300px;*/ + background-image: url("../img/page-background.jpg"); + background-size: cover; + background-color: #f3f7f9; + background-position: right top; + background-repeat: no-repeat; + position: relative; + overflow: hidden; + display: block; + padding-top: 100px; +} + +.page-info-section h2 { + font-size: 48px; +} + +.page-info-section .container{ + padding: 25px; +} + +.site-beradcamb { + padding-top: 10px; +} + +.site-beradcamb a { + color: #20509e; + font-size: 16px; +} + +.site-beradcamb span { + color: #acb9cc; + font-size: 16px; +} + +.site-beradcamb i { + margin: 0 3px; +} + +/*--------------------- + Blog page +-----------------------*/ + +.blog-page .blog-item { + margin-bottom: 30px; +} + +.blog-page .readmore { + color: #20509e; +} + +.blog-page .readmore i { + color: #16d0c5; +} + +.bi-feature .post-meta { + margin-bottom: 30px; +} + +.bi-feature .blog-text .blog-title { + font-size: 36px; +} + +.widget-area { + padding: 30px; + -webkit-box-shadow: 0px 23px 49px rgba(33, 54, 61, 0.15); + box-shadow: 0px 23px 49px rgba(33, 54, 61, 0.15); + margin-bottom: 32px; +} + +.widget-area .widget-title { + margin-bottom: 25px; +} + +.widget-area .widget { + margin-bottom: 20px; +} + +.widget-area .widget .widget-title { + padding-bottom: 30px; + margin-bottom: 30px; + border-bottom: 1px solid #ebebeb; + line-height: 24px; +} + +.widget-area .widget ul { + list-style: none; +} + +.widget-area .widget ul a { + display: inline-block; + font-size: 16px; + color: #20509e; + margin-bottom: 20px; +} + +.widget-area .widget ul a:hover { + color: #16d0c5; +} + +.widget-area .widget .popular-posts span { + color: #16d0c5; + font-size: 12px; + display: block; + margin-bottom: 7px; + text-transform: uppercase; +} + +.widget-area .widget .popular-posts h5 a { + font-size: 18px; + color: #20509e; +} + +.widget-area .widget .popular-posts h5 a:hover { + color: #20509e; +} + +.widget-area .widget .twitter-widget li { + margin-bottom: 20px; +} + +.widget-area .widget .twitter-widget span { + color: #16d0c5; + font-size: 12px; + display: block; + text-transform: uppercase; +} + +.widget-area .widget .twitter-widget h5 { + font-size: 18px; + color: #20509e; + margin-bottom: 5px; +} + +.widget-area .widget .twitter-widget a { + font-size: 18px; + color: #1f6ae5; + display: block; + margin-bottom: 5px; +} + +.widget-area .widget .twitter-widget a:hover { + color: #1f6ae5; +} + +.widget-area .widget-subscribe-from { + padding-top: 10px; + display: block; +} + +.widget-area .widget-subscribe-from input { + margin-right: 0; + margin-bottom: 20px; + width: 100%; + background: #f3f7f9; + border: 1px solid #ebebeb; + padding: 15px 20px; + font-size: 14px; +} + +.single-blog-page blockquote { + font-size: 24px; + color: #20509e; + padding-left: 25px; + border-left: 2px solid #16d0c5; + line-height: normal; + margin: 40px 0; + display: block; +} + +.single-blog-page blockquote span { + display: block; + font-size: 16px; + color: #16d0c5; + padding-top: 10px; +} + +.single-blog-page .post-tags a { + display: inline-block; + font-size: 11px; + text-transform: uppercase; + padding: 6px 15px; + margin-right: 2px; + margin-top: 5px; + color: #75849a; + background: #f3f7f9; + border: 1px solid #ebebeb; + margin-right: 5px; +} + +.single-blog-page .social-share { + display: block; + text-align: right; +} + +.single-blog-page .social-share p { + display: inline-block; + font-size: 14px; + margin-right: 10px; + color: #595959; +} + +.single-blog-page .social-share a { + display: inline-block; + width: 40px; + height: 40px; + margin-left: 8px; + text-align: center; + border-radius: 40px; + background: #f3f7f9; + color: #75849a; + padding-top: 9px; + font-size: 14px; + -webkit-box-shadow: 0 0 0 1px #ebebeb; + box-shadow: 0 0 0 1px #ebebeb; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; +} + +.single-blog-page .social-share a:hover { + color: #fff; +} + +.releted-posts { + padding-top: 50px; + margin-top: 25px; + border-top: 1px solid #ebebeb; +} + +.releted-posts .blog-item { + padding-top: 25px; +} + +.releted-posts .blog-text { + -webkit-box-shadow: 0 0 0 1px #ebebeb; + box-shadow: 0 0 0 1px #ebebeb; + padding: 28px 28px 20px; +} + +.releted-posts .blog-text .blog-title { + font-size: 22px; +} + +.releted-posts .post-meta { + margin-bottom: 0; +} + +.comment-area { + padding-top: 50px; +} + +.comment-list { + padding-top: 40px; + margin-top: 25px; + border-top: 1px solid #ebebeb; + list-style: none; +} + +.comment-list .replay-comment-list { + list-style: none; + margin-left: 14%; +} + +.comment { + margin-bottom: 40px; +} + +.comment .comment-avator { + float: left; + width: 70px; + height: 70px; + border-radius: 50%; +} + +.comment .comment-content { + padding-left: 100px; +} + +.comment .comment-content h5 { + font-size: 18px; + margin-bottom: 10px; +} + +.comment .comment-content h5 span { + font-size: 12px; + color: #acb9cc; + font-family: "Lato", sans-serif; +} + +.comment .comment-content p { + margin-bottom: 0; +} + +.comment .comment-content .c-btn { + font-family: "Futura", sans-serif; + display: inline-block; + font-size: 14px; + border: 1px solid #ebebeb; + background: #f3f7f9; + color: #20509e; + padding: 4px 25px; + border-radius: 2px; + margin-right: 5px; + margin-top: 20px; +} + +.comment .comment-content .c-btn:hover { + color: #fff; +} + +.comment-form .form-group { + position: relative; + padding: 1px; + margin-bottom: 20px; +} + +.comment-form input, +.comment-form textarea { + width: 100%; + padding: 11px 20px; + border: none; + border: 1px solid #e5e5e5; + position: relative; + z-index: 1; + -webkit-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; +} + +.comment-form input:focus, +.comment-form textarea:focus { + border-color: transparent; +} + +.comment-form input:focus+label, +.comment-form textarea:focus+label { + opacity: 1; +} + +.comment-form label { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + display: block; + opacity: 0; + -webkit-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; +} + +.comment-form textarea { + height: 115px; + display: -ms-grid; + display: grid; +} + +/*--------------------- + Contact page +-----------------------*/ + +.contact-form { + padding-right: 35px; +} + +.contact-form h5 { + font-size: 16px; + font-family: "Lato", sans-serif; +} + +.contact-form h5 span { + color: #16d0c5; +} + +.contact-form .form-group { + position: relative; + margin-bottom: 20px; +} + +.contact-form .form-group span { + position: absolute; + right: 0; + top: 10px; + font-size: 16px; + color: #7bc063; + opacity: 0; + -webkit-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; +} + +.contact-form .form-group span.active { + opacity: 1; +} + +.contact-form .check-form { + padding-right: 20px; +} + +.contact-form input, +.contact-form textarea { + width: 100%; + height: 50px; + border: none; + border-bottom: 1px solid #ebebeb; + font-size: 16px; + padding-bottom: 10px; + color: #20509e; +} + +.contact-form input:focus, +.contact-form textarea:focus { + border-color: #20509e; +} + +.contact-form textarea { + padding-bottom: 10px; + padding-top: 10px; + height: 115px; +} + +.contact-form .contact-type .ct-label, input[type=checkbox] { + display: inline-block; + position: relative; + padding-left: 20px; + margin-bottom: 12px; + margin-right: 40px; + cursor: pointer; + font-size: 16px; + color: #acb9cc; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.contact-form .contact-type .ct-label input { + position: absolute; + opacity: 0; + cursor: pointer; +} + +.contact-form .contact-type .ct-label input:checked~.checkmark:after { + content: '\f111'; + color: #16d0c5; +} + +.contact-form .contact-type .ct-label .checkmark { + position: absolute; + top: 3px; + left: 0; + height: 25px; + width: 25px; +} + +.contact-form .contact-type .ct-label .checkmark:after { + position: absolute; + content: "\f10c"; + font-family: 'FontAwesome'; + font-size: 14px; +} + +.contact-form .contact-type .ct-label:last-child { + margin-right: 0; +} + +.contact-form ::-webkit-input-placeholder { + color: #acb9cc; +} + +.contact-form :-ms-input-placeholder { + color: #acb9cc; +} + +.contact-form ::-ms-input-placeholder { + color: #acb9cc; +} + +.contact-form ::placeholder { + color: #acb9cc; +} + +.map { + height: 390px; + -webkit-box-shadow: 0px 23px 49px rgba(33, 54, 61, 0.15); + box-shadow: 0px 23px 49px rgba(33, 54, 61, 0.15); +} + +/*--------------------- + Strategy page +-----------------------*/ + +#custom-form, #manual-form { + margin-bottom: 5em; + min-height: 600px; +} + +.after-log-in { + min-height: 800px; +} + +.form-info-title { + margin: 30px; + padding-top: 2em; +} + +.strategy-column { + flex: 1; + min-width: 50%; + min-height: 800px; + border-bottom: 1px solid #ebebebeb; +} + +#manual-side { + background-image: + linear-gradient( #17a2b833, #fff), url(../img/signup.jpg) + +} + +#total-arrow-up { + color: #2dd3aa; +} + +#total-arrow-down { + color: #ff7979; +} + +#custom-side { + background-image: + linear-gradient( #fff, #fff0), url(../img/device.png) + +} + +#success-message { + margin: 5em; +} + +#before-container { + margin-top: 25px; +} +.strategy-page { + margin-bottom: 2em; +} + +#opening-for-strategy { + max-height: 680px; + +} + +#actual-strategy-forms { + min-height: 1000px; + max-height: 1000px; + height: 100%; +} + +.strategy-form { + /*padding-right: 35px;*/ + width: 100%; + margin-bottom: 2em; +} + +.strategy-form #title { + margin-bottom: 1em; + margin-top: 3em; +} + +.strategy-form h5 { + font-size: 16px; + font-family: "Lato", sans-serif; +} + +.strategy-form h5 span { + color: #16d0c5; +} + +.strategy-form .form-group { + position: relative; + margin-bottom: 20px; +} + +.strategy-form .strategy-row { + padding-bottom: 40px; + padding-top: 50px; +} + + +.strategy-form .form-group span { + position: absolute; + right: 0; + top: 10px; + font-size: 16px; + color: #7bc063; + opacity: 0; + -webkit-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; +} + +.strategy-form .form-group span.active { + opacity: 1; +} + +.strategy-form .check-form { + padding-right: 20px; +} + +.strategy-form input, +.strategy-form textarea { + width: 100%; + height: 50px; + border: none; + border-bottom: 1px solid #ebebeb; + font-size: 16px; + padding-bottom: 10px; + color: #20509e; +} + +.strategy-form input:focus, +.strategy-form textarea:focus { + border-color: #20509e; +} + +.strategy-form textarea { + padding-bottom: 10px; + padding-top: 10px; + height: 115px; +} + +.strategy-form .strategy-type .st-label, input[type=checkbox] { + display: inline-block; + position: relative; + padding-left: 20px; + margin-bottom: 12px; + margin-right: 40px; + cursor: pointer; + font-size: 16px; + color: #acb9cc; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.strategy-form .strategy-type .st-label input { + position: absolute; + opacity: 0; + cursor: pointer; +} + +.strategy-form .strategy-type .st-label input:checked~.checkmark:after { + content: '\f111'; + color: #16d0c5; +} + +.strategy-form .strategy-type .st-label .checkmark { + position: absolute; + top: 3px; + left: 0; + height: 25px; + width: 25px; +} + +.strategy-form .strategy-type .st-label .checkmark:after { + position: absolute; + content: "\f10c"; + font-family: 'FontAwesome'; + font-size: 14px; +} + +.strategy-form .strategy-type .st-label:last-child { + margin-right: 0; +} + +.strategy-form ::-webkit-input-placeholder { + color: #acb9cc; +} + +.strategy-form :-ms-input-placeholder { + color: #acb9cc; +} + +.strategy-form ::-ms-input-placeholder { + color: #acb9cc; +} + +.strategy-form ::placeholder { + color: #acb9cc; +} + +.strategy-display { + display: inline-flex; +} + +/*--------------------- + Sign up page +-----------------------*/ + +.signup-form { + padding-right: 35px; + padding-bottom: 10px; +} + + +.signup-form input, +.signup-form textarea { + width: 100%; + height: 50px; + border: none; + border-bottom: 1px solid #ebebeb; + font-size: 16px; + color: #20509e; +} + +.signup-form input:focus, +.signup-form textarea:focus { + border-color: #20509e; +} + +/*--------------------- + Trades ppage +-----------------------*/ + +.trades-page { + padding-top: 2.5em; +} + + + +/*--------------------- + Log in page +-----------------------*/ + +.indicator { + position: absolute; + z-index: 9; + width: 2.2em; + height: 2.2em; + cursor: pointer; +} + +.indicator-item { + width: 30px; + height: 30px; + left: 50%; + top: 50%; + margin: -15px 0 0 -15px; + position: absolute; + border-radius: 50%; + border: 2px solid #e35583; + -webkit-animation: pulse 0.6s infinite alternate; + animation: pulse 0.6s infinite alternate; +} + +@-webkit-keyframes pulse { + from { -webkit-transform: scale3d(0.5,0.5,1); } + to { -webkit-transform: scale3d(1,1,1); } +} + +@keyframes pulse { + from { -webkit-transform: scale3d(0.5,0.5,1); transform: scale3d(0.5,0.5,1); } + to { -webkit-transform: scale3d(1,1,1); transform: scale3d(1,1,1); } +} + +.indicator:hover .indicator-item { + border-color: #071e33; +} + +.indicator:first-child { + top: 10%; + left: 40%; +} + +.indicator:nth-child(2) { + top: 19%; + left: 13%; +} + +.indicator:nth-child(3) { + top: 40%; + left: 50%; +} + +.indicator:nth-child(4) { + top: 20%; + left: 70%; +} + +.indicator-content { + position: absolute; + z-index: 99; + width: 250px; + left: 50%; + bottom: 100%; + font-size: 14px; + line-height: 1.4; + text-align: left; + font-weight: 400; + color: #fffaf0; + background: transparent; + opacity: 0; + margin: 0 0 20px -150px; + cursor: default; + pointer-events: none; + font-family: 'open-sans', cursive; + -webkit-font-smoothing: antialiased; + -webkit-transition: opacity 0.3s 0.3s; + transition: opacity 0.3s 0.3s; +} + +.indicator:hover .indicator-content { + opacity: 1; + pointer-events: auto; + -webkit-transition-delay: 0s; + transition-delay: 0s; +} + +.indicator-content span { + display: block; +} + +.indicator-text { + border-bottom: 3px solid #ffb426; + overflow: hidden; + -webkit-transform: scale3d(0,1,1); + transform: scale3d(0,1,1); + -webkit-transition: -webkit-transform 0.3s 0.3s; + transition: transform 0.3s 0.3s; +} + +.indicator:hover .indicator-text { + -webkit-transition-delay: 0s; + transition-delay: 0s; + -webkit-transform: scale3d(1,1,1); + transform: scale3d(1,1,1); +} + +.indicator-inner { + background: #1e3953; + padding: 10px 15px; + -webkit-transform: translate3d(0,100%,0); + transform: translate3d(0,100%,0); + webkit-transition: -webkit-transform 0.3s; + transition: transform 0.3s; +} + +.indicator:hover .indicator-inner { + -webkit-transition-delay: 0.3s; + transition-delay: 0.3s; + -webkit-transform: translate3d(0,0,0); + transform: translate3d(0,0,0); +} + + +.login-form { + padding-right: 35px; +} + +.password-container { + position: relative; +} + +.password-container input { + padding-right: 30px; +} + +.password-container i { + position: absolute; + right: 20px; + padding: 10px 12px; +} + +.login-form input, +.login-form textarea { + width: 100%; + height: 50px; + border: none; + border-bottom: 1px solid #ebebeb; + font-size: 16px; + color: #2B5FD9; +} + +.login-form input:focus, +.login-form textarea:focus { + border-color: #20509e; +} + +#have-account { + padding-top: 20px; +} + + + +/*------------------ + Responsive +---------------------*/ + +@media (min-width: 1200px) { + .container { + max-width: 1170px; + } + +} + +@media (max-width: 1585px) { + .hero-section .laptop-image { + left: 0; + } +} + +@media (max-width: 1425px) { + .header-section .site-btn { + margin-left: 0; + } + + .page-info-section { + /*background-position: right 30% top;*/ + } + + .hero-section { + background-position: right 30% top; + } + .hero-section .laptop-image { + width: auto; + max-width: 100%; + top: 70px; + } + .about-img { + left: -50px; + width: 600px; + } +} + +@media (min-width: 1199px) and (max-width: 1390px) { + .member { + padding: 35px 10px; + } + .member-img { + width: 160px; + height: 160px; + } + .member-info { + padding: 50px 27px 10px; + height: 275px; + } + .member-social a { + margin: 0 5px; + } +} + +/* Medium screen : 992px. */ + +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .menu-list li a { + margin-right: 15px; + } + .hero-section, + .page-info-section { + background-position: right 23% top; + } + + .about-img { + left: 0px; + width: 480px; + } + .member { + width: calc(33.333333% - 25px); + margin-bottom: 30px; + } + .team-members { + text-align: center; + } + .fact h2 { + font-size: 45px; + margin-right: 10px; + } + .fact p { + padding-top: 7px; + } + .fact i { + font-size: 67px; + } +} diff --git a/src/main/resources/static/css/test.css b/src/main/resources/static/css/test.css new file mode 100644 index 0000000..06f8b85 --- /dev/null +++ b/src/main/resources/static/css/test.css @@ -0,0 +1 @@ +.mfp-bg{top:0;left:0;width:100%;height:100%;z-index:1042;overflow:hidden;position:fixed;background:#0b0b0b;opacity:.8;filter:alpha(opacity=80)}.mfp-wrap{top:0;left:0;width:100%;height:100%;z-index:1043;position:fixed;outline:0!important;-webkit-backface-visibility:hidden}.mfp-container{text-align:center;position:absolute;width:100%;height:100%;left:0;top:0;padding:0 8px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.mfp-container:before{content:'';display:inline-block;height:100%;vertical-align:middle}.mfp-align-top .mfp-container:before{display:none}.mfp-content{position:relative;display:inline-block;vertical-align:middle;margin:0 auto;text-align:left;z-index:1045}.mfp-ajax-holder .mfp-content,.mfp-inline-holder .mfp-content{width:100%;cursor:auto}.mfp-ajax-cur{cursor:progress}.mfp-zoom-out-cur,.mfp-zoom-out-cur .mfp-image-holder .mfp-close{cursor:-moz-zoom-out;cursor:-webkit-zoom-out;cursor:zoom-out}.mfp-zoom{cursor:pointer;cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.mfp-auto-cursor .mfp-content{cursor:auto}.mfp-arrow,.mfp-close,.mfp-counter,.mfp-preloader{-webkit-user-select:none;-moz-user-select:none;user-select:none}.mfp-loading.mfp-figure{display:none}.mfp-hide{display:none!important}.mfp-preloader{color:#ccc;position:absolute;top:50%;width:auto;text-align:center;margin-top:-.8em;left:8px;right:8px;z-index:1044}.mfp-preloader a{color:#ccc}.mfp-preloader a:hover{color:#fff}.mfp-s-error .mfp-content,.mfp-s-ready .mfp-preloader{display:none}button.mfp-arrow,button.mfp-close{overflow:visible;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;display:block;outline:0;padding:0;z-index:1046;-webkit-box-shadow:none;box-shadow:none}button::-moz-focus-inner{padding:0;border:0}.mfp-close{width:44px;height:44px;line-height:44px;position:absolute;right:0;top:0;text-decoration:none;text-align:center;opacity:.65;filter:alpha(opacity=65);padding:0 0 18px 10px;color:#fff;font-style:normal;font-size:28px;font-family:Arial,Baskerville,monospace}.mfp-close:focus,.mfp-close:hover{opacity:1;filter:alpha(opacity=100)}.mfp-close:active{top:1px}.mfp-close-btn-in .mfp-close{color:#333}.mfp-iframe-holder .mfp-close,.mfp-image-holder .mfp-close{color:#fff;right:-6px;text-align:right;padding-right:6px;width:100%}.mfp-counter{position:absolute;top:0;right:0;color:#ccc;font-size:12px;line-height:18px;white-space:nowrap}.mfp-arrow{position:absolute;opacity:.65;filter:alpha(opacity=65);margin:-55px 0 0;top:50%;padding:0;width:90px;height:110px;-webkit-tap-highlight-color:transparent}.mfp-arrow:active{margin-top:-54px}.mfp-arrow:focus,.mfp-arrow:hover{opacity:1;filter:alpha(opacity=100)}.mfp-arrow .mfp-a,.mfp-arrow .mfp-b,.mfp-arrow:after,.mfp-arrow:before{content:'';display:block;width:0;height:0;position:absolute;left:0;top:0;margin-top:35px;margin-left:35px;border:inset transparent}.mfp-arrow .mfp-a,.mfp-arrow:after{border-top-width:13px;border-bottom-width:13px;top:8px}.mfp-arrow .mfp-b,.mfp-arrow:before{border-top-width:21px;border-bottom-width:21px;opacity:.7}.mfp-arrow-left{left:0}.mfp-arrow-left .mfp-a,.mfp-arrow-left:after{border-right:17px solid #fff;margin-left:31px}.mfp-arrow-left .mfp-b,.mfp-arrow-left:before{margin-left:25px;border-right:27px solid #3f3f3f}.mfp-arrow-right{right:0}.mfp-arrow-right .mfp-a,.mfp-arrow-right:after{border-left:17px solid #fff;margin-left:39px}.mfp-arrow-right .mfp-b,.mfp-arrow-right:before{border-left:27px solid #3f3f3f}.mfp-iframe-holder{padding-top:40px;padding-bottom:40px}.mfp-iframe-holder .mfp-content{line-height:0;width:100%;max-width:900px}.mfp-iframe-holder .mfp-close{top:-40px}.mfp-iframe-scaler{width:100%;height:0;overflow:hidden;padding-top:56.25%}.mfp-iframe-scaler iframe{position:absolute;display:block;top:0;left:0;width:100%;height:100%;box-shadow:0 0 8px rgba(0,0,0,.6);background:#000}img.mfp-img{width:auto;max-width:100%;height:auto;display:block;line-height:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:40px 0;margin:0 auto}.mfp-figure{line-height:0}.mfp-figure:after{content:'';position:absolute;left:0;top:40px;bottom:40px;display:block;right:0;width:auto;height:auto;z-index:-1;box-shadow:0 0 8px rgba(0,0,0,.6);background:#444}.mfp-figure small{color:#bdbdbd;display:block;font-size:12px;line-height:14px}.mfp-figure figure{margin:0}.mfp-bottom-bar{margin-top:-36px;position:absolute;top:100%;left:0;width:100%;cursor:auto}.mfp-title{text-align:left;line-height:18px;color:#f3f3f3;word-wrap:break-word;padding-right:36px}.mfp-image-holder .mfp-content{max-width:100%}.mfp-gallery .mfp-image-holder .mfp-figure{cursor:pointer}@media screen and (max-width:800px) and (orientation:landscape),screen and (max-height:300px){.mfp-img-mobile .mfp-image-holder{padding-left:0;padding-right:0}.mfp-img-mobile img.mfp-img{padding:0}.mfp-img-mobile .mfp-figure:after{top:0;bottom:0}.mfp-img-mobile .mfp-figure small{display:inline;margin-left:5px}.mfp-img-mobile .mfp-bottom-bar{background:rgba(0,0,0,.6);bottom:0;margin:0;top:auto;padding:3px 5px;position:fixed;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.mfp-img-mobile .mfp-bottom-bar:empty{padding:0}.mfp-img-mobile .mfp-counter{right:5px;top:3px}.mfp-img-mobile .mfp-close{top:0;right:0;width:35px;height:35px;line-height:35px;background:rgba(0,0,0,.6);position:fixed;text-align:center;padding:0}}@media all and (max-width:900px){.mfp-arrow{-webkit-transform:scale(0.75);transform:scale(0.75)}.mfp-arrow-left{-webkit-transform-origin:0;transform-origin:0}.mfp-arrow-right{-webkit-transform-origin:100%;transform-origin:100%}.mfp-container{padding-left:6px;padding-right:6px}}.mfp-ie7 .mfp-img{padding:0}.mfp-ie7 .mfp-bottom-bar{width:600px;left:50%;margin-left:-300px;margin-top:5px;padding-bottom:5px}.mfp-ie7 .mfp-container{padding:0}.mfp-ie7 .mfp-content{padding-top:44px}.mfp-ie7 .mfp-close{top:0;right:0;padding-top:0} \ No newline at end of file diff --git a/src/main/resources/static/css/themify-icons.css b/src/main/resources/static/css/themify-icons.css new file mode 100755 index 0000000..736e4bf --- /dev/null +++ b/src/main/resources/static/css/themify-icons.css @@ -0,0 +1,1081 @@ +@font-face { + font-family: 'themify'; + src:url('../icon-fonts/themify.eot?-fvbane'); + src:url('../icon-fonts/themify.eot?#iefix-fvbane') format('embedded-opentype'), + url('../icon-fonts/themify.woff?-fvbane') format('woff'), + url('../icon-fonts/themify.ttf?-fvbane') format('truetype'), + url('../icon-fonts/themify.svg?-fvbane#themify') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="ti-"], [class*=" ti-"] { + font-family: 'themify'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.ti-wand:before { + content: "\e600"; +} +.ti-volume:before { + content: "\e601"; +} +.ti-user:before { + content: "\e602"; +} +.ti-unlock:before { + content: "\e603"; +} +.ti-unlink:before { + content: "\e604"; +} +.ti-trash:before { + content: "\e605"; +} +.ti-thought:before { + content: "\e606"; +} +.ti-target:before { + content: "\e607"; +} +.ti-tag:before { + content: "\e608"; +} +.ti-tablet:before { + content: "\e609"; +} +.ti-star:before { + content: "\e60a"; +} +.ti-spray:before { + content: "\e60b"; +} +.ti-signal:before { + content: "\e60c"; +} +.ti-shopping-cart:before { + content: "\e60d"; +} +.ti-shopping-cart-full:before { + content: "\e60e"; +} +.ti-settings:before { + content: "\e60f"; +} +.ti-search:before { + content: "\e610"; +} +.ti-zoom-in:before { + content: "\e611"; +} +.ti-zoom-out:before { + content: "\e612"; +} +.ti-cut:before { + content: "\e613"; +} +.ti-ruler:before { + content: "\e614"; +} +.ti-ruler-pencil:before { + content: "\e615"; +} +.ti-ruler-alt:before { + content: "\e616"; +} +.ti-bookmark:before { + content: "\e617"; +} +.ti-bookmark-alt:before { + content: "\e618"; +} +.ti-reload:before { + content: "\e619"; +} +.ti-plus:before { + content: "\e61a"; +} +.ti-pin:before { + content: "\e61b"; +} +.ti-pencil:before { + content: "\e61c"; +} +.ti-pencil-alt:before { + content: "\e61d"; +} +.ti-paint-roller:before { + content: "\e61e"; +} +.ti-paint-bucket:before { + content: "\e61f"; +} +.ti-na:before { + content: "\e620"; +} +.ti-mobile:before { + content: "\e621"; +} +.ti-minus:before { + content: "\e622"; +} +.ti-medall:before { + content: "\e623"; +} +.ti-medall-alt:before { + content: "\e624"; +} +.ti-marker:before { + content: "\e625"; +} +.ti-marker-alt:before { + content: "\e626"; +} +.ti-arrow-up:before { + content: "\e627"; +} +.ti-arrow-right:before { + content: "\e628"; +} +.ti-arrow-left:before { + content: "\e629"; +} +.ti-arrow-down:before { + content: "\e62a"; +} +.ti-lock:before { + content: "\e62b"; +} +.ti-location-arrow:before { + content: "\e62c"; +} +.ti-link:before { + content: "\e62d"; +} +.ti-layout:before { + content: "\e62e"; +} +.ti-layers:before { + content: "\e62f"; +} +.ti-layers-alt:before { + content: "\e630"; +} +.ti-key:before { + content: "\e631"; +} +.ti-import:before { + content: "\e632"; +} +.ti-image:before { + content: "\e633"; +} +.ti-heart:before { + content: "\e634"; +} +.ti-heart-broken:before { + content: "\e635"; +} +.ti-hand-stop:before { + content: "\e636"; +} +.ti-hand-open:before { + content: "\e637"; +} +.ti-hand-drag:before { + content: "\e638"; +} +.ti-folder:before { + content: "\e639"; +} +.ti-flag:before { + content: "\e63a"; +} +.ti-flag-alt:before { + content: "\e63b"; +} +.ti-flag-alt-2:before { + content: "\e63c"; +} +.ti-eye:before { + content: "\e63d"; +} +.ti-export:before { + content: "\e63e"; +} +.ti-exchange-vertical:before { + content: "\e63f"; +} +.ti-desktop:before { + content: "\e640"; +} +.ti-cup:before { + content: "\e641"; +} +.ti-crown:before { + content: "\e642"; +} +.ti-comments:before { + content: "\e643"; +} +.ti-comment:before { + content: "\e644"; +} +.ti-comment-alt:before { + content: "\e645"; +} +.ti-close:before { + content: "\e646"; +} +.ti-clip:before { + content: "\e647"; +} +.ti-angle-up:before { + content: "\e648"; +} +.ti-angle-right:before { + content: "\e649"; +} +.ti-angle-left:before { + content: "\e64a"; +} +.ti-angle-down:before { + content: "\e64b"; +} +.ti-check:before { + content: "\e64c"; +} +.ti-check-box:before { + content: "\e64d"; +} +.ti-camera:before { + content: "\e64e"; +} +.ti-announcement:before { + content: "\e64f"; +} +.ti-brush:before { + content: "\e650"; +} +.ti-briefcase:before { + content: "\e651"; +} +.ti-bolt:before { + content: "\e652"; +} +.ti-bolt-alt:before { + content: "\e653"; +} +.ti-blackboard:before { + content: "\e654"; +} +.ti-bag:before { + content: "\e655"; +} +.ti-move:before { + content: "\e656"; +} +.ti-arrows-vertical:before { + content: "\e657"; +} +.ti-arrows-horizontal:before { + content: "\e658"; +} +.ti-fullscreen:before { + content: "\e659"; +} +.ti-arrow-top-right:before { + content: "\e65a"; +} +.ti-arrow-top-left:before { + content: "\e65b"; +} +.ti-arrow-circle-up:before { + content: "\e65c"; +} +.ti-arrow-circle-right:before { + content: "\e65d"; +} +.ti-arrow-circle-left:before { + content: "\e65e"; +} +.ti-arrow-circle-down:before { + content: "\e65f"; +} +.ti-angle-double-up:before { + content: "\e660"; +} +.ti-angle-double-right:before { + content: "\e661"; +} +.ti-angle-double-left:before { + content: "\e662"; +} +.ti-angle-double-down:before { + content: "\e663"; +} +.ti-zip:before { + content: "\e664"; +} +.ti-world:before { + content: "\e665"; +} +.ti-wheelchair:before { + content: "\e666"; +} +.ti-view-list:before { + content: "\e667"; +} +.ti-view-list-alt:before { + content: "\e668"; +} +.ti-view-grid:before { + content: "\e669"; +} +.ti-uppercase:before { + content: "\e66a"; +} +.ti-upload:before { + content: "\e66b"; +} +.ti-underline:before { + content: "\e66c"; +} +.ti-truck:before { + content: "\e66d"; +} +.ti-timer:before { + content: "\e66e"; +} +.ti-ticket:before { + content: "\e66f"; +} +.ti-thumb-up:before { + content: "\e670"; +} +.ti-thumb-down:before { + content: "\e671"; +} +.ti-text:before { + content: "\e672"; +} +.ti-stats-up:before { + content: "\e673"; +} +.ti-stats-down:before { + content: "\e674"; +} +.ti-split-v:before { + content: "\e675"; +} +.ti-split-h:before { + content: "\e676"; +} +.ti-smallcap:before { + content: "\e677"; +} +.ti-shine:before { + content: "\e678"; +} +.ti-shift-right:before { + content: "\e679"; +} +.ti-shift-left:before { + content: "\e67a"; +} +.ti-shield:before { + content: "\e67b"; +} +.ti-notepad:before { + content: "\e67c"; +} +.ti-server:before { + content: "\e67d"; +} +.ti-quote-right:before { + content: "\e67e"; +} +.ti-quote-left:before { + content: "\e67f"; +} +.ti-pulse:before { + content: "\e680"; +} +.ti-printer:before { + content: "\e681"; +} +.ti-power-off:before { + content: "\e682"; +} +.ti-plug:before { + content: "\e683"; +} +.ti-pie-chart:before { + content: "\e684"; +} +.ti-paragraph:before { + content: "\e685"; +} +.ti-panel:before { + content: "\e686"; +} +.ti-package:before { + content: "\e687"; +} +.ti-music:before { + content: "\e688"; +} +.ti-music-alt:before { + content: "\e689"; +} +.ti-mouse:before { + content: "\e68a"; +} +.ti-mouse-alt:before { + content: "\e68b"; +} +.ti-money:before { + content: "\e68c"; +} +.ti-microphone:before { + content: "\e68d"; +} +.ti-menu:before { + content: "\e68e"; +} +.ti-menu-alt:before { + content: "\e68f"; +} +.ti-map:before { + content: "\e690"; +} +.ti-map-alt:before { + content: "\e691"; +} +.ti-loop:before { + content: "\e692"; +} +.ti-location-pin:before { + content: "\e693"; +} +.ti-list:before { + content: "\e694"; +} +.ti-light-bulb:before { + content: "\e695"; +} +.ti-Italic:before { + content: "\e696"; +} +.ti-info:before { + content: "\e697"; +} +.ti-infinite:before { + content: "\e698"; +} +.ti-id-badge:before { + content: "\e699"; +} +.ti-hummer:before { + content: "\e69a"; +} +.ti-home:before { + content: "\e69b"; +} +.ti-help:before { + content: "\e69c"; +} +.ti-headphone:before { + content: "\e69d"; +} +.ti-harddrives:before { + content: "\e69e"; +} +.ti-harddrive:before { + content: "\e69f"; +} +.ti-gift:before { + content: "\e6a0"; +} +.ti-game:before { + content: "\e6a1"; +} +.ti-filter:before { + content: "\e6a2"; +} +.ti-files:before { + content: "\e6a3"; +} +.ti-file:before { + content: "\e6a4"; +} +.ti-eraser:before { + content: "\e6a5"; +} +.ti-envelope:before { + content: "\e6a6"; +} +.ti-download:before { + content: "\e6a7"; +} +.ti-direction:before { + content: "\e6a8"; +} +.ti-direction-alt:before { + content: "\e6a9"; +} +.ti-dashboard:before { + content: "\e6aa"; +} +.ti-control-stop:before { + content: "\e6ab"; +} +.ti-control-shuffle:before { + content: "\e6ac"; +} +.ti-control-play:before { + content: "\e6ad"; +} +.ti-control-pause:before { + content: "\e6ae"; +} +.ti-control-forward:before { + content: "\e6af"; +} +.ti-control-backward:before { + content: "\e6b0"; +} +.ti-cloud:before { + content: "\e6b1"; +} +.ti-cloud-up:before { + content: "\e6b2"; +} +.ti-cloud-down:before { + content: "\e6b3"; +} +.ti-clipboard:before { + content: "\e6b4"; +} +.ti-car:before { + content: "\e6b5"; +} +.ti-calendar:before { + content: "\e6b6"; +} +.ti-book:before { + content: "\e6b7"; +} +.ti-bell:before { + content: "\e6b8"; +} +.ti-basketball:before { + content: "\e6b9"; +} +.ti-bar-chart:before { + content: "\e6ba"; +} +.ti-bar-chart-alt:before { + content: "\e6bb"; +} +.ti-back-right:before { + content: "\e6bc"; +} +.ti-back-left:before { + content: "\e6bd"; +} +.ti-arrows-corner:before { + content: "\e6be"; +} +.ti-archive:before { + content: "\e6bf"; +} +.ti-anchor:before { + content: "\e6c0"; +} +.ti-align-right:before { + content: "\e6c1"; +} +.ti-align-left:before { + content: "\e6c2"; +} +.ti-align-justify:before { + content: "\e6c3"; +} +.ti-align-center:before { + content: "\e6c4"; +} +.ti-alert:before { + content: "\e6c5"; +} +.ti-alarm-clock:before { + content: "\e6c6"; +} +.ti-agenda:before { + content: "\e6c7"; +} +.ti-write:before { + content: "\e6c8"; +} +.ti-window:before { + content: "\e6c9"; +} +.ti-widgetized:before { + content: "\e6ca"; +} +.ti-widget:before { + content: "\e6cb"; +} +.ti-widget-alt:before { + content: "\e6cc"; +} +.ti-wallet:before { + content: "\e6cd"; +} +.ti-video-clapper:before { + content: "\e6ce"; +} +.ti-video-camera:before { + content: "\e6cf"; +} +.ti-vector:before { + content: "\e6d0"; +} +.ti-themify-logo:before { + content: "\e6d1"; +} +.ti-themify-favicon:before { + content: "\e6d2"; +} +.ti-themify-favicon-alt:before { + content: "\e6d3"; +} +.ti-support:before { + content: "\e6d4"; +} +.ti-stamp:before { + content: "\e6d5"; +} +.ti-split-v-alt:before { + content: "\e6d6"; +} +.ti-slice:before { + content: "\e6d7"; +} +.ti-shortcode:before { + content: "\e6d8"; +} +.ti-shift-right-alt:before { + content: "\e6d9"; +} +.ti-shift-left-alt:before { + content: "\e6da"; +} +.ti-ruler-alt-2:before { + content: "\e6db"; +} +.ti-receipt:before { + content: "\e6dc"; +} +.ti-pin2:before { + content: "\e6dd"; +} +.ti-pin-alt:before { + content: "\e6de"; +} +.ti-pencil-alt2:before { + content: "\e6df"; +} +.ti-palette:before { + content: "\e6e0"; +} +.ti-more:before { + content: "\e6e1"; +} +.ti-more-alt:before { + content: "\e6e2"; +} +.ti-microphone-alt:before { + content: "\e6e3"; +} +.ti-magnet:before { + content: "\e6e4"; +} +.ti-line-double:before { + content: "\e6e5"; +} +.ti-line-dotted:before { + content: "\e6e6"; +} +.ti-line-dashed:before { + content: "\e6e7"; +} +.ti-layout-width-full:before { + content: "\e6e8"; +} +.ti-layout-width-default:before { + content: "\e6e9"; +} +.ti-layout-width-default-alt:before { + content: "\e6ea"; +} +.ti-layout-tab:before { + content: "\e6eb"; +} +.ti-layout-tab-window:before { + content: "\e6ec"; +} +.ti-layout-tab-v:before { + content: "\e6ed"; +} +.ti-layout-tab-min:before { + content: "\e6ee"; +} +.ti-layout-slider:before { + content: "\e6ef"; +} +.ti-layout-slider-alt:before { + content: "\e6f0"; +} +.ti-layout-sidebar-right:before { + content: "\e6f1"; +} +.ti-layout-sidebar-none:before { + content: "\e6f2"; +} +.ti-layout-sidebar-left:before { + content: "\e6f3"; +} +.ti-layout-placeholder:before { + content: "\e6f4"; +} +.ti-layout-menu:before { + content: "\e6f5"; +} +.ti-layout-menu-v:before { + content: "\e6f6"; +} +.ti-layout-menu-separated:before { + content: "\e6f7"; +} +.ti-layout-menu-full:before { + content: "\e6f8"; +} +.ti-layout-media-right-alt:before { + content: "\e6f9"; +} +.ti-layout-media-right:before { + content: "\e6fa"; +} +.ti-layout-media-overlay:before { + content: "\e6fb"; +} +.ti-layout-media-overlay-alt:before { + content: "\e6fc"; +} +.ti-layout-media-overlay-alt-2:before { + content: "\e6fd"; +} +.ti-layout-media-left-alt:before { + content: "\e6fe"; +} +.ti-layout-media-left:before { + content: "\e6ff"; +} +.ti-layout-media-center-alt:before { + content: "\e700"; +} +.ti-layout-media-center:before { + content: "\e701"; +} +.ti-layout-list-thumb:before { + content: "\e702"; +} +.ti-layout-list-thumb-alt:before { + content: "\e703"; +} +.ti-layout-list-post:before { + content: "\e704"; +} +.ti-layout-list-large-image:before { + content: "\e705"; +} +.ti-layout-line-solid:before { + content: "\e706"; +} +.ti-layout-grid4:before { + content: "\e707"; +} +.ti-layout-grid3:before { + content: "\e708"; +} +.ti-layout-grid2:before { + content: "\e709"; +} +.ti-layout-grid2-thumb:before { + content: "\e70a"; +} +.ti-layout-cta-right:before { + content: "\e70b"; +} +.ti-layout-cta-left:before { + content: "\e70c"; +} +.ti-layout-cta-center:before { + content: "\e70d"; +} +.ti-layout-cta-btn-right:before { + content: "\e70e"; +} +.ti-layout-cta-btn-left:before { + content: "\e70f"; +} +.ti-layout-column4:before { + content: "\e710"; +} +.ti-layout-column3:before { + content: "\e711"; +} +.ti-layout-column2:before { + content: "\e712"; +} +.ti-layout-accordion-separated:before { + content: "\e713"; +} +.ti-layout-accordion-merged:before { + content: "\e714"; +} +.ti-layout-accordion-list:before { + content: "\e715"; +} +.ti-ink-pen:before { + content: "\e716"; +} +.ti-info-alt:before { + content: "\e717"; +} +.ti-help-alt:before { + content: "\e718"; +} +.ti-headphone-alt:before { + content: "\e719"; +} +.ti-hand-point-up:before { + content: "\e71a"; +} +.ti-hand-point-right:before { + content: "\e71b"; +} +.ti-hand-point-left:before { + content: "\e71c"; +} +.ti-hand-point-down:before { + content: "\e71d"; +} +.ti-gallery:before { + content: "\e71e"; +} +.ti-face-smile:before { + content: "\e71f"; +} +.ti-face-sad:before { + content: "\e720"; +} +.ti-credit-card:before { + content: "\e721"; +} +.ti-control-skip-forward:before { + content: "\e722"; +} +.ti-control-skip-backward:before { + content: "\e723"; +} +.ti-control-record:before { + content: "\e724"; +} +.ti-control-eject:before { + content: "\e725"; +} +.ti-comments-smiley:before { + content: "\e726"; +} +.ti-brush-alt:before { + content: "\e727"; +} +.ti-youtube:before { + content: "\e728"; +} +.ti-vimeo:before { + content: "\e729"; +} +.ti-twitter:before { + content: "\e72a"; +} +.ti-time:before { + content: "\e72b"; +} +.ti-tumblr:before { + content: "\e72c"; +} +.ti-skype:before { + content: "\e72d"; +} +.ti-share:before { + content: "\e72e"; +} +.ti-share-alt:before { + content: "\e72f"; +} +.ti-rocket:before { + content: "\e730"; +} +.ti-pinterest:before { + content: "\e731"; +} +.ti-new-window:before { + content: "\e732"; +} +.ti-microsoft:before { + content: "\e733"; +} +.ti-list-ol:before { + content: "\e734"; +} +.ti-linkedin:before { + content: "\e735"; +} +.ti-layout-sidebar-2:before { + content: "\e736"; +} +.ti-layout-grid4-alt:before { + content: "\e737"; +} +.ti-layout-grid3-alt:before { + content: "\e738"; +} +.ti-layout-grid2-alt:before { + content: "\e739"; +} +.ti-layout-column4-alt:before { + content: "\e73a"; +} +.ti-layout-column3-alt:before { + content: "\e73b"; +} +.ti-layout-column2-alt:before { + content: "\e73c"; +} +.ti-instagram:before { + content: "\e73d"; +} +.ti-google:before { + content: "\e73e"; +} +.ti-github:before { + content: "\e73f"; +} +.ti-flickr:before { + content: "\e740"; +} +.ti-facebook:before { + content: "\e741"; +} +.ti-dropbox:before { + content: "\e742"; +} +.ti-dribbble:before { + content: "\e743"; +} +.ti-apple:before { + content: "\e744"; +} +.ti-android:before { + content: "\e745"; +} +.ti-save:before { + content: "\e746"; +} +.ti-save-alt:before { + content: "\e747"; +} +.ti-yahoo:before { + content: "\e748"; +} +.ti-wordpress:before { + content: "\e749"; +} +.ti-vimeo-alt:before { + content: "\e74a"; +} +.ti-twitter-alt:before { + content: "\e74b"; +} +.ti-tumblr-alt:before { + content: "\e74c"; +} +.ti-trello:before { + content: "\e74d"; +} +.ti-stack-overflow:before { + content: "\e74e"; +} +.ti-soundcloud:before { + content: "\e74f"; +} +.ti-sharethis:before { + content: "\e750"; +} +.ti-sharethis-alt:before { + content: "\e751"; +} +.ti-reddit:before { + content: "\e752"; +} +.ti-pinterest-alt:before { + content: "\e753"; +} +.ti-microsoft-alt:before { + content: "\e754"; +} +.ti-linux:before { + content: "\e755"; +} +.ti-jsfiddle:before { + content: "\e756"; +} +.ti-joomla:before { + content: "\e757"; +} +.ti-html5:before { + content: "\e758"; +} +.ti-flickr-alt:before { + content: "\e759"; +} +.ti-email:before { + content: "\e75a"; +} +.ti-drupal:before { + content: "\e75b"; +} +.ti-dropbox-alt:before { + content: "\e75c"; +} +.ti-css3:before { + content: "\e75d"; +} +.ti-rss:before { + content: "\e75e"; +} +.ti-rss-alt:before { + content: "\e75f"; +} diff --git a/src/main/resources/static/css/trade-table.css b/src/main/resources/static/css/trade-table.css new file mode 100644 index 0000000..f0b75e8 --- /dev/null +++ b/src/main/resources/static/css/trade-table.css @@ -0,0 +1,101 @@ + +h1{ + font-size: 30px; + color: #fff; + text-transform: uppercase; + font-weight: 300; + text-align: center; + margin-bottom: 15px; +} +table{ + width:100%; + table-layout: fixed; + +} +.tbl-header{ + background-color: lavender; + } +.tbl-content{ + max-height: 400px; + overflow-x:auto; + margin-top: 0px; + border: 1px solid rgba(255,255,255,0.3); +} +th{ + padding: 20px 15px; + text-align: left; + font-weight: 500; + font-size: 12px; + text-transform: uppercase; +} + +.trade-message { + margin-bottom: 0; + margin-top: 0; + font-size: 10px; +} + +td{ + padding: 15px; + text-align: left; + vertical-align:middle; + font-weight: 300; + font-size: 12px; + border-bottom: solid 1px rgba(255,255,255,0.1); +} + +tr { + border-top: 2px solid #f3f3f38a; +} + + +/* demo styles */ + +@import url(https://fonts.googleapis.com/css?family=Roboto:400,500,300,700); +body{ + font-family: 'Roboto', sans-serif; +} +#trade-table{ + margin: 50px; + margin-bottom: 100px; + border: 3px solid #f9f9f9cc +} + + +/* follow me template */ +.made-with-love { + margin-top: 40px; + padding: 10px; + clear: left; + text-align: center; + font-size: 10px; + font-family: arial; + color: #fff; +} +.made-with-love i { + font-style: normal; + color: #F50057; + font-size: 14px; + position: relative; + top: 2px; +} +.made-with-love a { + color: #fff; + text-decoration: none; +} +.made-with-love a:hover { + text-decoration: underline; +} + + +/* for custom scrollbar for webkit browser*/ + +::-webkit-scrollbar { + width: 6px; +} +::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); +} +::-webkit-scrollbar-thumb { + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); +} \ No newline at end of file diff --git a/src/main/resources/static/css/typing.css b/src/main/resources/static/css/typing.css new file mode 100644 index 0000000..bc370c4 --- /dev/null +++ b/src/main/resources/static/css/typing.css @@ -0,0 +1,27 @@ +#cursor { + display: inline-block; + vertical-align: middle; + width: 3px; + height: 50px; + background-color: white; +} + +#text { + display: inline-block; + vertical-align: middle; + color: white; + letter-spacing: 2px; +} + +@keyframes blink { + from, to { + background-color: transparent + } + 50% { + background-color: white; + } +} + +#typing-container { + min-height: 86px; +} \ No newline at end of file diff --git a/src/main/resources/static/fonts/Futura.woff b/src/main/resources/static/fonts/Futura.woff new file mode 100755 index 0000000..455a183 Binary files /dev/null and b/src/main/resources/static/fonts/Futura.woff differ diff --git a/src/main/resources/static/icon-fonts/Flaticon.eot b/src/main/resources/static/icon-fonts/Flaticon.eot new file mode 100755 index 0000000..8f83151 Binary files /dev/null and b/src/main/resources/static/icon-fonts/Flaticon.eot differ diff --git a/src/main/resources/static/icon-fonts/Flaticon.svg b/src/main/resources/static/icon-fonts/Flaticon.svg new file mode 100755 index 0000000..a4739b6 --- /dev/null +++ b/src/main/resources/static/icon-fonts/Flaticon.svg @@ -0,0 +1,1180 @@ + + + + + +Created by FontForge 20120731 at Wed Nov 2 08:15:58 2016 + By Apache +Created by Apache with FontForge 2.0 (http://fontforge.sf.net) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/icon-fonts/Flaticon.woff b/src/main/resources/static/icon-fonts/Flaticon.woff new file mode 100755 index 0000000..8eadce0 Binary files /dev/null and b/src/main/resources/static/icon-fonts/Flaticon.woff differ diff --git a/src/main/resources/static/icon-fonts/fontawesome-webfont.eot b/src/main/resources/static/icon-fonts/fontawesome-webfont.eot new file mode 100755 index 0000000..e9f60ca Binary files /dev/null and b/src/main/resources/static/icon-fonts/fontawesome-webfont.eot differ diff --git a/src/main/resources/static/icon-fonts/fontawesome-webfont.svg b/src/main/resources/static/icon-fonts/fontawesome-webfont.svg new file mode 100755 index 0000000..855c845 --- /dev/null +++ b/src/main/resources/static/icon-fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/icon-fonts/fontawesome-webfont.woff b/src/main/resources/static/icon-fonts/fontawesome-webfont.woff new file mode 100755 index 0000000..400014a Binary files /dev/null and b/src/main/resources/static/icon-fonts/fontawesome-webfont.woff differ diff --git a/src/main/resources/static/icon-fonts/fontawesome-webfont.woff2 b/src/main/resources/static/icon-fonts/fontawesome-webfont.woff2 new file mode 100755 index 0000000..4d13fc6 Binary files /dev/null and b/src/main/resources/static/icon-fonts/fontawesome-webfont.woff2 differ diff --git a/src/main/resources/static/icon-fonts/themify.eot b/src/main/resources/static/icon-fonts/themify.eot new file mode 100755 index 0000000..9ec298b Binary files /dev/null and b/src/main/resources/static/icon-fonts/themify.eot differ diff --git a/src/main/resources/static/icon-fonts/themify.svg b/src/main/resources/static/icon-fonts/themify.svg new file mode 100755 index 0000000..3d53854 --- /dev/null +++ b/src/main/resources/static/icon-fonts/themify.svg @@ -0,0 +1,362 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/icon-fonts/themify.ttf b/src/main/resources/static/icon-fonts/themify.ttf new file mode 100755 index 0000000..5d627e7 Binary files /dev/null and b/src/main/resources/static/icon-fonts/themify.ttf differ diff --git a/src/main/resources/static/icon-fonts/themify.woff b/src/main/resources/static/icon-fonts/themify.woff new file mode 100755 index 0000000..847ebd1 Binary files /dev/null and b/src/main/resources/static/icon-fonts/themify.woff differ diff --git a/src/main/resources/static/img/.DS_Store b/src/main/resources/static/img/.DS_Store new file mode 100644 index 0000000..9bbaa0f Binary files /dev/null and b/src/main/resources/static/img/.DS_Store differ diff --git a/src/main/resources/static/img/Crypthub_2ndLogo.png b/src/main/resources/static/img/Crypthub_2ndLogo.png new file mode 100755 index 0000000..ae75b23 Binary files /dev/null and b/src/main/resources/static/img/Crypthub_2ndLogo.png differ diff --git a/src/main/resources/static/img/Crypthub_Logo.png b/src/main/resources/static/img/Crypthub_Logo.png new file mode 100644 index 0000000..035cceb Binary files /dev/null and b/src/main/resources/static/img/Crypthub_Logo.png differ diff --git a/src/main/resources/static/img/Crypthub_logo_formatted.png b/src/main/resources/static/img/Crypthub_logo_formatted.png new file mode 100755 index 0000000..2bfd891 Binary files /dev/null and b/src/main/resources/static/img/Crypthub_logo_formatted.png differ diff --git a/src/main/resources/static/img/Crypthub_mainLogo.png b/src/main/resources/static/img/Crypthub_mainLogo.png new file mode 100755 index 0000000..c7f53e5 Binary files /dev/null and b/src/main/resources/static/img/Crypthub_mainLogo.png differ diff --git a/src/main/resources/static/img/about-img.png b/src/main/resources/static/img/about-img.png new file mode 100755 index 0000000..e4d6e00 Binary files /dev/null and b/src/main/resources/static/img/about-img.png differ diff --git a/src/main/resources/static/img/animated-img1.gif b/src/main/resources/static/img/animated-img1.gif new file mode 100644 index 0000000..d441e24 Binary files /dev/null and b/src/main/resources/static/img/animated-img1.gif differ diff --git a/src/main/resources/static/img/appstore.svg b/src/main/resources/static/img/appstore.svg new file mode 100644 index 0000000..78b142a --- /dev/null +++ b/src/main/resources/static/img/appstore.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/static/img/atom.png b/src/main/resources/static/img/atom.png new file mode 100644 index 0000000..0ff0219 Binary files /dev/null and b/src/main/resources/static/img/atom.png differ diff --git a/src/main/resources/static/img/bank-bitcoin.jpg b/src/main/resources/static/img/bank-bitcoin.jpg new file mode 100644 index 0000000..37e8faa Binary files /dev/null and b/src/main/resources/static/img/bank-bitcoin.jpg differ diff --git a/src/main/resources/static/img/blockchain.png b/src/main/resources/static/img/blockchain.png new file mode 100644 index 0000000..b5cb988 Binary files /dev/null and b/src/main/resources/static/img/blockchain.png differ diff --git a/src/main/resources/static/img/blog/1.jpg b/src/main/resources/static/img/blog/1.jpg new file mode 100755 index 0000000..6d074d1 Binary files /dev/null and b/src/main/resources/static/img/blog/1.jpg differ diff --git a/src/main/resources/static/img/blog/2.jpg b/src/main/resources/static/img/blog/2.jpg new file mode 100755 index 0000000..d40e3c3 Binary files /dev/null and b/src/main/resources/static/img/blog/2.jpg differ diff --git a/src/main/resources/static/img/blog/3.jpg b/src/main/resources/static/img/blog/3.jpg new file mode 100755 index 0000000..f6036ad Binary files /dev/null and b/src/main/resources/static/img/blog/3.jpg differ diff --git a/src/main/resources/static/img/blog/4.jpg b/src/main/resources/static/img/blog/4.jpg new file mode 100755 index 0000000..3a35595 Binary files /dev/null and b/src/main/resources/static/img/blog/4.jpg differ diff --git a/src/main/resources/static/img/blog/5.jpg b/src/main/resources/static/img/blog/5.jpg new file mode 100755 index 0000000..a9b16b2 Binary files /dev/null and b/src/main/resources/static/img/blog/5.jpg differ diff --git a/src/main/resources/static/img/blog/6.jpg b/src/main/resources/static/img/blog/6.jpg new file mode 100755 index 0000000..427d3fc Binary files /dev/null and b/src/main/resources/static/img/blog/6.jpg differ diff --git a/src/main/resources/static/img/blog/7.jpg b/src/main/resources/static/img/blog/7.jpg new file mode 100755 index 0000000..5868762 Binary files /dev/null and b/src/main/resources/static/img/blog/7.jpg differ diff --git a/src/main/resources/static/img/blog/comment/1.jpg b/src/main/resources/static/img/blog/comment/1.jpg new file mode 100755 index 0000000..81e1dff Binary files /dev/null and b/src/main/resources/static/img/blog/comment/1.jpg differ diff --git a/src/main/resources/static/img/blog/comment/2.jpg b/src/main/resources/static/img/blog/comment/2.jpg new file mode 100755 index 0000000..75dd4d7 Binary files /dev/null and b/src/main/resources/static/img/blog/comment/2.jpg differ diff --git a/src/main/resources/static/img/blog/comment/3.jpg b/src/main/resources/static/img/blog/comment/3.jpg new file mode 100755 index 0000000..da0a66e Binary files /dev/null and b/src/main/resources/static/img/blog/comment/3.jpg differ diff --git a/src/main/resources/static/img/bread-bg.png b/src/main/resources/static/img/bread-bg.png new file mode 100644 index 0000000..4d2a884 Binary files /dev/null and b/src/main/resources/static/img/bread-bg.png differ diff --git a/src/main/resources/static/img/btc2.png b/src/main/resources/static/img/btc2.png new file mode 100644 index 0000000..cde3291 Binary files /dev/null and b/src/main/resources/static/img/btc2.png differ diff --git a/src/main/resources/static/img/btc3.png b/src/main/resources/static/img/btc3.png new file mode 100644 index 0000000..aee943a Binary files /dev/null and b/src/main/resources/static/img/btc3.png differ diff --git a/src/main/resources/static/img/christine.jpeg b/src/main/resources/static/img/christine.jpeg new file mode 100644 index 0000000..6e2902e Binary files /dev/null and b/src/main/resources/static/img/christine.jpeg differ diff --git a/src/main/resources/static/img/circle.png b/src/main/resources/static/img/circle.png new file mode 100644 index 0000000..17d2c7e Binary files /dev/null and b/src/main/resources/static/img/circle.png differ diff --git a/src/main/resources/static/img/cloud-1.png b/src/main/resources/static/img/cloud-1.png new file mode 100644 index 0000000..e7c5556 Binary files /dev/null and b/src/main/resources/static/img/cloud-1.png differ diff --git a/src/main/resources/static/img/cloud-2.png b/src/main/resources/static/img/cloud-2.png new file mode 100644 index 0000000..5206cce Binary files /dev/null and b/src/main/resources/static/img/cloud-2.png differ diff --git a/src/main/resources/static/img/coin.png b/src/main/resources/static/img/coin.png new file mode 100644 index 0000000..69dac64 Binary files /dev/null and b/src/main/resources/static/img/coin.png differ diff --git a/src/main/resources/static/img/connect.jpg b/src/main/resources/static/img/connect.jpg new file mode 100644 index 0000000..cefd04e Binary files /dev/null and b/src/main/resources/static/img/connect.jpg differ diff --git a/src/main/resources/static/img/contact.jpg b/src/main/resources/static/img/contact.jpg new file mode 100644 index 0000000..633b693 Binary files /dev/null and b/src/main/resources/static/img/contact.jpg differ diff --git a/src/main/resources/static/img/device.png b/src/main/resources/static/img/device.png new file mode 100644 index 0000000..e500d4f Binary files /dev/null and b/src/main/resources/static/img/device.png differ diff --git a/src/main/resources/static/img/digitization.jpg b/src/main/resources/static/img/digitization.jpg new file mode 100644 index 0000000..ffdd698 Binary files /dev/null and b/src/main/resources/static/img/digitization.jpg differ diff --git a/src/main/resources/static/img/faq.jpg b/src/main/resources/static/img/faq.jpg new file mode 100644 index 0000000..038e29c Binary files /dev/null and b/src/main/resources/static/img/faq.jpg differ diff --git a/src/main/resources/static/img/faq1.png b/src/main/resources/static/img/faq1.png new file mode 100644 index 0000000..676ed21 Binary files /dev/null and b/src/main/resources/static/img/faq1.png differ diff --git a/src/main/resources/static/img/flavicon.png b/src/main/resources/static/img/flavicon.png new file mode 100755 index 0000000..42ea836 Binary files /dev/null and b/src/main/resources/static/img/flavicon.png differ diff --git a/src/main/resources/static/img/hero-background4.jpg b/src/main/resources/static/img/hero-background4.jpg new file mode 100644 index 0000000..e1f603f Binary files /dev/null and b/src/main/resources/static/img/hero-background4.jpg differ diff --git a/src/main/resources/static/img/hero-bg.png b/src/main/resources/static/img/hero-bg.png new file mode 100755 index 0000000..d23a361 Binary files /dev/null and b/src/main/resources/static/img/hero-bg.png differ diff --git a/src/main/resources/static/img/laptop.png b/src/main/resources/static/img/laptop.png new file mode 100755 index 0000000..72bed8b Binary files /dev/null and b/src/main/resources/static/img/laptop.png differ diff --git a/src/main/resources/static/img/logo.png b/src/main/resources/static/img/logo.png new file mode 100755 index 0000000..0726b51 Binary files /dev/null and b/src/main/resources/static/img/logo.png differ diff --git a/src/main/resources/static/img/main-bg.png b/src/main/resources/static/img/main-bg.png new file mode 100644 index 0000000..704d9be Binary files /dev/null and b/src/main/resources/static/img/main-bg.png differ diff --git a/src/main/resources/static/img/main-bg2.png b/src/main/resources/static/img/main-bg2.png new file mode 100644 index 0000000..bd3a88f Binary files /dev/null and b/src/main/resources/static/img/main-bg2.png differ diff --git a/src/main/resources/static/img/map-marker.png b/src/main/resources/static/img/map-marker.png new file mode 100755 index 0000000..a0ae795 Binary files /dev/null and b/src/main/resources/static/img/map-marker.png differ diff --git a/src/main/resources/static/img/map.jpg b/src/main/resources/static/img/map.jpg new file mode 100644 index 0000000..76538b2 Binary files /dev/null and b/src/main/resources/static/img/map.jpg differ diff --git a/src/main/resources/static/img/map.svg b/src/main/resources/static/img/map.svg new file mode 100644 index 0000000..5d19292 --- /dev/null +++ b/src/main/resources/static/img/map.svg @@ -0,0 +1,3096 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/img/member/1.jpg b/src/main/resources/static/img/member/1.jpg new file mode 100755 index 0000000..8ea78b0 Binary files /dev/null and b/src/main/resources/static/img/member/1.jpg differ diff --git a/src/main/resources/static/img/member/2.jpg b/src/main/resources/static/img/member/2.jpg new file mode 100755 index 0000000..ab8855f Binary files /dev/null and b/src/main/resources/static/img/member/2.jpg differ diff --git a/src/main/resources/static/img/member/3.jpg b/src/main/resources/static/img/member/3.jpg new file mode 100755 index 0000000..eee88a1 Binary files /dev/null and b/src/main/resources/static/img/member/3.jpg differ diff --git a/src/main/resources/static/img/member/4.jpg b/src/main/resources/static/img/member/4.jpg new file mode 100755 index 0000000..3d53d1e Binary files /dev/null and b/src/main/resources/static/img/member/4.jpg differ diff --git a/src/main/resources/static/img/member/5.jpg b/src/main/resources/static/img/member/5.jpg new file mode 100755 index 0000000..31d0e93 Binary files /dev/null and b/src/main/resources/static/img/member/5.jpg differ diff --git a/src/main/resources/static/img/page-background-prev.jpg b/src/main/resources/static/img/page-background-prev.jpg new file mode 100644 index 0000000..bd0cf00 Binary files /dev/null and b/src/main/resources/static/img/page-background-prev.jpg differ diff --git a/src/main/resources/static/img/page-background.jpg b/src/main/resources/static/img/page-background.jpg new file mode 100644 index 0000000..a73baad Binary files /dev/null and b/src/main/resources/static/img/page-background.jpg differ diff --git a/src/main/resources/static/img/page-info-bg.png b/src/main/resources/static/img/page-info-bg.png new file mode 100755 index 0000000..4a1cfbd Binary files /dev/null and b/src/main/resources/static/img/page-info-bg.png differ diff --git a/src/main/resources/static/img/pavlo.jpg b/src/main/resources/static/img/pavlo.jpg new file mode 100644 index 0000000..f757302 Binary files /dev/null and b/src/main/resources/static/img/pavlo.jpg differ diff --git a/src/main/resources/static/img/playstore.svg b/src/main/resources/static/img/playstore.svg new file mode 100644 index 0000000..0967440 --- /dev/null +++ b/src/main/resources/static/img/playstore.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/static/img/process-icons/1.png b/src/main/resources/static/img/process-icons/1.png new file mode 100755 index 0000000..c861f47 Binary files /dev/null and b/src/main/resources/static/img/process-icons/1.png differ diff --git a/src/main/resources/static/img/process-icons/2.png b/src/main/resources/static/img/process-icons/2.png new file mode 100755 index 0000000..5174b2f Binary files /dev/null and b/src/main/resources/static/img/process-icons/2.png differ diff --git a/src/main/resources/static/img/process-icons/3.png b/src/main/resources/static/img/process-icons/3.png new file mode 100755 index 0000000..ecdde21 Binary files /dev/null and b/src/main/resources/static/img/process-icons/3.png differ diff --git a/src/main/resources/static/img/process-line.png b/src/main/resources/static/img/process-line.png new file mode 100755 index 0000000..36cb631 Binary files /dev/null and b/src/main/resources/static/img/process-line.png differ diff --git a/src/main/resources/static/img/quote.png b/src/main/resources/static/img/quote.png new file mode 100755 index 0000000..a13d935 Binary files /dev/null and b/src/main/resources/static/img/quote.png differ diff --git a/src/main/resources/static/img/rain-2.png b/src/main/resources/static/img/rain-2.png new file mode 100644 index 0000000..7f5220c Binary files /dev/null and b/src/main/resources/static/img/rain-2.png differ diff --git a/src/main/resources/static/img/review/1.jpg b/src/main/resources/static/img/review/1.jpg new file mode 100755 index 0000000..f351d65 Binary files /dev/null and b/src/main/resources/static/img/review/1.jpg differ diff --git a/src/main/resources/static/img/review/2.jpg b/src/main/resources/static/img/review/2.jpg new file mode 100755 index 0000000..d355e36 Binary files /dev/null and b/src/main/resources/static/img/review/2.jpg differ diff --git a/src/main/resources/static/img/review/3.jpg b/src/main/resources/static/img/review/3.jpg new file mode 100755 index 0000000..4ac7302 Binary files /dev/null and b/src/main/resources/static/img/review/3.jpg differ diff --git a/src/main/resources/static/img/sean.jpg b/src/main/resources/static/img/sean.jpg new file mode 100644 index 0000000..2b3c78f Binary files /dev/null and b/src/main/resources/static/img/sean.jpg differ diff --git a/src/main/resources/static/img/section-bg.svg b/src/main/resources/static/img/section-bg.svg new file mode 100644 index 0000000..f07f1b4 --- /dev/null +++ b/src/main/resources/static/img/section-bg.svg @@ -0,0 +1,17 @@ + + + + 0FA68E48-CA51-4825-8DFD-E71B601B2D3F + Created with sketchtool. + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/img/section-icon-1.svg b/src/main/resources/static/img/section-icon-1.svg new file mode 100644 index 0000000..23277a0 --- /dev/null +++ b/src/main/resources/static/img/section-icon-1.svg @@ -0,0 +1,34 @@ + + + + icon - Collaborate + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/img/section-icon-2.svg b/src/main/resources/static/img/section-icon-2.svg new file mode 100644 index 0000000..6a303e5 --- /dev/null +++ b/src/main/resources/static/img/section-icon-2.svg @@ -0,0 +1,33 @@ + + + + icon- Safety + Created with Sketch. + + + + + + + + + + + + + + + + + + 18 + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/img/signup.jpg b/src/main/resources/static/img/signup.jpg new file mode 100644 index 0000000..fdf8e9b Binary files /dev/null and b/src/main/resources/static/img/signup.jpg differ diff --git a/src/main/resources/static/img/world.jpg b/src/main/resources/static/img/world.jpg new file mode 100644 index 0000000..2e7ea01 Binary files /dev/null and b/src/main/resources/static/img/world.jpg differ diff --git a/src/main/resources/static/js/autocorrect.js b/src/main/resources/static/js/autocorrect.js new file mode 100644 index 0000000..b506d1c --- /dev/null +++ b/src/main/resources/static/js/autocorrect.js @@ -0,0 +1,79 @@ + +// Waits for DOM to load before running +$(document).ready(() => { + // Variables to keep track of autocorrect state + let currInput = '', + suggestionList = []; + + //use jQuery to get reference to the HTML element with an id of "suggestions". + const $suggestions = $('#suggestions'); + + // Listen for keypress events. If a user presses a key, autocorrect their input. + $(document).keyup(event => { + console.log("key being clicked"); + + currInput = document.getElementById("user-input").value; + + // if the input is all whitespace, empty the select box don't call the ac command. + if (currInput.trim() === "") { + $suggestions.empty(); + return; + } + + const postParameters = {input: currInput, universe: "autocorrect"}; + + //Make a POST request to the "/suggestions" endpoint with the word information + $.post("/suggestions", postParameters, responseJSON => { + + // Parse the JSON response into a JavaScript object. + const responseObject = JSON.parse(responseJSON); + suggestionList = responseObject.suggestions; + + const limit = suggestionList.length >= 6 ? 6 : suggestionList.length; + const restOfInput = suggestionList[0]; + let newHTML = []; + for (let i = 1; i < limit; i++) { + newHTML.push('' + restOfInput + suggestionList[i] + ''); + } + $suggestions.html(newHTML.join("")); + }); + + $suggestions.empty(); + }); +}); + +$(function(){ + $('input[name="prefix"]').click(function(){ + let value = $('input[name="prefix"]:checked', '#prefix-form').val(); + postParameters = {command: "prefix", setting: value}; + $.post("/settings", postParameters); + }); +}); + +$(function(){ + $('input[name="whitespace"]').click(function(){ + let value = $('input[name="whitespace"]:checked', '#whitespace-form').val(); + postParameters = {command: "whitespace", setting: value}; + $.post("/settings", postParameters); + }); +}); + +$(function(){ + $('input[name="smart"]').click(function(){ + let value = $('input[name="smart"]:checked', '#smart-form').val(); + postParameters = {command: "smart", setting: value}; + + $.post("/settings", postParameters); + }); +}); + +$(function(){ + $('input[name="led"]').click(function(){ + let value = $('input[name="led"]:checked', '#led-form').val(); + postParameters = {command: "led", setting: value}; + + $.post("/settings", postParameters); + }); +}); + + diff --git a/src/main/resources/static/js/bacon.js b/src/main/resources/static/js/bacon.js new file mode 100644 index 0000000..3d7f699 --- /dev/null +++ b/src/main/resources/static/js/bacon.js @@ -0,0 +1,91 @@ + +function capitalizeFirstLetter(str) { + var splitStr = str.toLowerCase().split(' '); + for (var i = 0; i < splitStr.length; i++) { + // You do not need to check if i is larger than splitStr length, as your for does that for you + // Assign it back to the array + splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); + } + // Directly return the joined string + return splitStr.join(' '); +} + +// Waits for DOM to load before running +$(document).ready(() => { + // Variables to keep track of autocorrect state + let sourceActor = '', + destActor = '', + sourceSuggestionList = [], + destSuggestionList = []; + + //use jQuery to get reference to the HTML element with an id of "suggestions". + const $sourceSuggestions = $('#source-suggestions'); + const $destSuggestions = $('#dest-suggestions'); + + // Listen for keypress events. If a user presses a key, autocorrect their input. + $("#source-actor").keyup(event => { + console.log("key being clicked"); + + sourceActor = document.getElementById("source-actor").value; + + // if the input is all whitespace, empty the select box don't call the ac command. + if (sourceActor.trim() === "") { + $sourceSuggestions.empty(); + return; + } + + const postParametersSource ={input: sourceActor, universe: "bacon"}; + + //Make a POST request to the "/suggestions" endpoint with the word information + $.post("/suggestions", postParametersSource, responseJSON => { + + // Parse the JSON response into a JavaScript object. + const responseObject = JSON.parse(responseJSON); + sourceSuggestionList = responseObject.suggestions; + + const limit = sourceSuggestionList.length >= 6 ? 6 : sourceSuggestionList.length; + const restOfInput = capitalizeFirstLetter(sourceSuggestionList[0]); + let newHTML = []; + for (let i = 1; i < limit; i++) { + newHTML.push('' + restOfInput + capitalizeFirstLetter(sourceSuggestionList[i]) + ''); + } + $sourceSuggestions.html(newHTML.join("")); + }); + + $sourceSuggestions.empty(); + }); + + $("#dest-actor").keyup(event => { + console.log("key being clicked"); + + destActor = document.getElementById("dest-actor").value; + + // if the input is all whitespace, empty the select box don't call the ac command. + if (destActor.trim() === "") { + $destSuggestions.empty(); + return; + } + + const postParametersDest ={input: destActor, universe: "bacon"}; + + //Make a POST request to the "/suggestions" endpoint with the word information + $.post("/suggestions", postParametersDest, responseJSON => { + + // Parse the JSON response into a JavaScript object. + const responseObject = JSON.parse(responseJSON); + destSuggestionList = responseObject.suggestions; + + const limit = destSuggestionList.length >= 6 ? 6 : destSuggestionList.length; + const restOfInput = capitalizeFirstLetter(destSuggestionList[0]); + let newHTML = []; + for (let i = 1; i < limit; i++) { + newHTML.push('' + restOfInput + capitalizeFirstLetter(destSuggestionList[i]) + ''); + } + $destSuggestions.html(newHTML.join("")); + }); + + $destSuggestions.empty(); + }); +}); + + diff --git a/src/main/resources/static/js/bootstrap-slider.min.js b/src/main/resources/static/js/bootstrap-slider.min.js new file mode 100644 index 0000000..d7a45f9 --- /dev/null +++ b/src/main/resources/static/js/bootstrap-slider.min.js @@ -0,0 +1,699 @@ +/*! ======================================================= + VERSION 10.6.1 +========================================================= */ + +"use strict"; +var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a) { + return typeof a +} + +:function(a) { + return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol": typeof a +} + +, +windowIsDefined="object"===("undefined"==typeof window?"undefined":_typeof(window)); +!function(a) { + if("function"==typeof define&&define.amd)define(["jquery"], a); + else if("object"===("undefined"==typeof module?"undefined": _typeof(module))&&module.exports) { + var b; + try { + b=require("jquery") + } + catch(c) { + b=null + } + module.exports=a(b) + } + else window&&(window.Slider=a(window.jQuery)) +} + +(function(a) { + var b="slider", c="bootstrapSlider"; + windowIsDefined&&!window.console&&(window.console= {} + ), windowIsDefined&&!window.console.log&&(window.console.log=function() {} + ), windowIsDefined&&!window.console.warn&&(window.console.warn=function() {} + ); + var d; + return function(a) { + function b() {} + function c(a) { + function c(b) { + b.prototype.option||(b.prototype.option=function(b) { + a.isPlainObject(b)&&(this.options=a.extend(!0, this.options, b)) + } + ) + } + function e(b, c) { + a.fn[b]=function(e) { + if("string"==typeof e) { + for(var g=d.call(arguments, 1), h=0, i=this.length; + i>h; + h++) { + var j=this[h], k=a.data(j, b); + if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)) { + var l=k[e].apply(k, g); + if(void 0!==l&&l!==k)return l + } + else f("no such method '"+e+"' for "+b+" instance"); + else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'") + } + return this + } + var m=this.map(function() { + var d=a.data(this, b); + return d?(d.option(e), d._init()): (d=new c(this, e), a.data(this, b, d)), a(this) + } + ); + return!m||m.length>1?m:m[0] + } + } + if(a) { + var f="undefined"==typeof console?b:function(a) { + console.error(a) + } + ; + return a.bridget=function(a, b) { + c(b), e(a, b) + } + , a.bridget + } + } + var d=Array.prototype.slice; + c(a) + } + (a), function(a) { + function e(b, c) { + function d(a, b) { + var c="data-slider-"+b.replace(/_/g, "-"), d=a.getAttribute(c); + try { + return JSON.parse(d) + } + catch(e) { + return d + } + } + this._state= { + value: null, enabled:null, offset:null, size:null, percentage:null, inDrag:!1, over:!1, tickIndex:null + } + , this.ticksCallbackMap= {} + , this.handleCallbackMap= {} + , "string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b), c=c?c: {} + ; + for(var e=Object.keys(this.defaultOptions), f=c.hasOwnProperty("min"), g=c.hasOwnProperty("max"), i=0; + i0, this.ticksAreValid||(this.options.lock_to_ticks=!1), "auto"===this.options.rtl) { + var l=window.getComputedStyle(this.element); + null!=l?this.options.rtl="rtl"===l.direction: this.options.rtl="rtl"===this.element.style.direction + } + "vertical"!==this.options.orientation||"top"!==this.options.tooltip_position&&"bottom"!==this.options.tooltip_position?"horizontal"!==this.options.orientation||"left"!==this.options.tooltip_position&&"right"!==this.options.tooltip_position||(this.options.tooltip_position="top"):this.options.rtl?this.options.tooltip_position="left":this.options.tooltip_position="right"; + var m, n, o, p, q, r=this.element.style.width, s=!1, t=this.element.parentNode; + if(this.sliderElem)s=!0; + else { + this.sliderElem=document.createElement("div"), this.sliderElem.className="slider"; + var u=document.createElement("div"); + u.className="slider-track", n=document.createElement("div"), n.className="slider-track-low", m=document.createElement("div"), m.className="slider-selection", o=document.createElement("div"), o.className="slider-track-high", p=document.createElement("div"), p.className="slider-handle min-slider-handle", p.setAttribute("role", "slider"), p.setAttribute("aria-valuemin", this.options.min), p.setAttribute("aria-valuemax", this.options.max), q=document.createElement("div"), q.className="slider-handle max-slider-handle", q.setAttribute("role", "slider"), q.setAttribute("aria-valuemin", this.options.min), q.setAttribute("aria-valuemax", this.options.max), u.appendChild(n), u.appendChild(m), u.appendChild(o), this.rangeHighlightElements=[]; + var v=this.options.rangeHighlights; + if(Array.isArray(v)&&v.length>0)for(var w=0; + w0) { + for(this.ticksContainer=document.createElement("div"), this.ticksContainer.className="slider-tick-container", i=0; + i0)for(this.tickLabelContainer=document.createElement("div"), this.tickLabelContainer.className="slider-tick-label-container", i=0; + i0&&(g||(this.options.max=Math.max.apply(Math, this.options.ticks)), f||(this.options.min=Math.min.apply(Math, this.options.ticks))), Array.isArray(this.options.value)?(this.options.range=!0, this._state.value=this.options.value):this.options.range?this._state.value=[this.options.value, this.options.max]:this._state.value=this.options.value, this.trackLow=n||this.trackLow, this.trackSelection=m||this.trackSelection, this.trackHigh=o||this.trackHigh, "none"===this.options.selection?(this._addClass(this.trackLow, "hide"), this._addClass(this.trackSelection, "hide"), this._addClass(this.trackHigh, "hide")):("after"===this.options.selection||"before"===this.options.selection)&&(this._removeClass(this.trackLow, "hide"), this._removeClass(this.trackSelection, "hide"), this._removeClass(this.trackHigh, "hide")), this.handle1=p||this.handle1, this.handle2=q||this.handle2, s===!0)for(this._removeClass(this.handle1, "round triangle"), this._removeClass(this.handle2, "round triangle hide"), i=0; + ib.max?b.max:a + } + , toValue:function(a) { + var b=a/100*(this.options.max-this.options.min), c=!0; + if(this.options.ticks_positions.length>0) { + for(var d, e, f, g=0, i=1; + i0) { + for(var b, c, d, e=0, f=0; + f0?this.options.ticks[f-1]: 0, d=f>0?this.options.ticks_positions[f-1]:0, c=this.options.ticks[f], e=this.options.ticks_positions[f]; + break + } + if(f>0) { + var g=(a-b)/(c-b); + return d+g*(e-d) + } + } + return 100*(a-this.options.min)/(this.options.max-this.options.min) + } + } + , logarithmic: { + toValue:function(a) { + var b=1-this.options.min, c=Math.log(this.options.min+b), d=Math.log(this.options.max+b), e=Math.exp(c+(d-c)*a/100)-b; + return Math.round(e)===d?d: (e=this.options.min+Math.round((e-this.options.min)/this.options.step)*this.options.step, h.linear.getValue(e, this.options)) + } + , toPercentage:function(a) { + if(this.options.max===this.options.min)return 0; + var b=1-this.options.min, c=Math.log(this.options.max+b), d=Math.log(this.options.min+b), e=Math.log(a+b); + return 100*(e-d)/(c-d) + } + } + } + ; + d=function(a, b) { + return e.call(this, a, b), this + } + , d.prototype= { + _init:function() {} + , constructor:d, defaultOptions: { + id:"", min:0, max:10, step:1, precision:0, orientation:"horizontal", value:5, range:!1, selection:"before", tooltip:"show", tooltip_split:!1, lock_to_ticks:!1, handle:"round", reversed:!1, rtl:"auto", enabled:!0, formatter:function(a) { + return Array.isArray(a)?a[0]+" : "+a[1]: a + } + , natural_arrow_keys:!1, ticks:[], ticks_positions:[], ticks_labels:[], ticks_snap_bounds:0, ticks_tooltip:!1, scale:"linear", focus:!1, tooltip_position:null, labelledby:null, rangeHighlights:[] + } + , getElement:function() { + return this.sliderElem + } + , getValue:function() { + return this.options.range?this._state.value: this._state.value[0] + } + , setValue:function(a, b, c) { + a||(a=0); + var d=this.getValue(); + this._state.value=this._validateInputValue(a); + var e=this._applyPrecision.bind(this); + this.options.range?(this._state.value[0]=e(this._state.value[0]), this._state.value[1]=e(this._state.value[1]), this.ticksAreValid&&this.options.lock_to_ticks&&(this._state.value[0]=this.options.ticks[this._getClosestTickIndex(this._state.value[0])], this._state.value[1]=this.options.ticks[this._getClosestTickIndex(this._state.value[1])]), this._state.value[0]=Math.max(this.options.min, Math.min(this.options.max, this._state.value[0])), this._state.value[1]=Math.max(this.options.min, Math.min(this.options.max, this._state.value[1]))): (this._state.value=e(this._state.value), this.ticksAreValid&&this.options.lock_to_ticks&&(this._state.value=this.options.ticks[this._getClosestTickIndex(this._state.value)]), this._state.value=[Math.max(this.options.min, Math.min(this.options.max, this._state.value))], this._addClass(this.handle2, "hide"), "after"===this.options.selection?this._state.value[1]=this.options.max:this._state.value[1]=this.options.min), this._setTickIndex(), this.options.max>this.options.min?this._state.percentage=[this._toPercentage(this._state.value[0]), this._toPercentage(this._state.value[1]), 100*this.options.step/(this.options.max-this.options.min)]:this._state.percentage=[0, 0, 100], this._layout(); + var f=this.options.range?this._state.value: this._state.value[0]; + this._setDataVal(f), b===!0&&this._trigger("slide", f); + var g=!1; + return g=Array.isArray(f)?d[0]!==f[0]||d[1]!==f[1]:d!==f, g&&c===!0&&this._trigger("change", { + oldValue: d, newValue:f + } + ), this + } + , destroy:function() { + this._removeSliderEventHandlers(), this.sliderElem.parentNode.removeChild(this.sliderElem), this.element.style.display="", this._cleanUpEventCallbacksMap(), this.element.removeAttribute("data"), a&&(this._unbindJQueryEventHandlers(), f===b&&this.$element.removeData(f), this.$element.removeData(c)) + } + , disable:function() { + return this._state.enabled=!1, this.handle1.removeAttribute("tabindex"), this.handle2.removeAttribute("tabindex"), this._addClass(this.sliderElem, "slider-disabled"), this._trigger("slideDisabled"), this + } + , enable:function() { + return this._state.enabled=!0, this.handle1.setAttribute("tabindex", 0), this.handle2.setAttribute("tabindex", 0), this._removeClass(this.sliderElem, "slider-disabled"), this._trigger("slideEnabled"), this + } + , toggle:function() { + return this._state.enabled?this.disable(): this.enable(), this + } + , isEnabled:function() { + return this._state.enabled + } + , on:function(a, b) { + return this._bindNonQueryEventHandler(a, b), this + } + , off:function(b, c) { + a?(this.$element.off(b, c), this.$sliderElem.off(b, c)): this._unbindNonQueryEventHandler(b, c) + } + , getAttribute:function(a) { + return a?this.options[a]: this.options + } + , setAttribute:function(a, b) { + return this.options[a]=b, this + } + , refresh:function(d) { + var g=this.getValue(); + return this._removeSliderEventHandlers(), e.call(this, this.element, this.options), d&&d.useCurrentValue===!0&&this.setValue(g), a&&(f===b?(a.data(this.element, b, this), a.data(this.element, c, this)): a.data(this.element, c, this)), this + } + , relayout:function() { + return this._resize(), this + } + , _removeTooltipListener:function(a, b) { + this.handle1.removeEventListener(a, b, !1), this.handle2.removeEventListener(a, b, !1) + } + , _removeSliderEventHandlers:function() { + if(this.handle1.removeEventListener("keydown", this.handle1Keydown, !1), this.handle2.removeEventListener("keydown", this.handle2Keydown, !1), this.options.ticks_tooltip) { + for(var a=this.ticksContainer.getElementsByClassName("slider-tick"), b=0; + b0&&a.options.ticks_positions[c]||a._toPercentage(a.options.ticks[c])): f=a._toPercentage(e), d.value[0]=e, d.percentage[0]=f, a._setToolTipOnMouseOver(d), a._showTooltip() + } + ; + return b.addEventListener("mouseenter", d, !1), d + } + , addMouseLeave:function(a, b) { + var c=function() { + a._hideTooltip() + } + ; + return b.addEventListener("mouseleave", c, !1), c + } + } + } + , _layout:function() { + var a, b; + if(a=this.options.reversed?[100-this._state.percentage[0], this.options.range?100-this._state.percentage[1]: this._state.percentage[1]]:[this._state.percentage[0], this._state.percentage[1]], this.handle1.style[this.stylePos]=a[0]+"%", this.handle1.setAttribute("aria-valuenow", this._state.value[0]), b=this.options.formatter(this._state.value[0]), isNaN(b)?this.handle1.setAttribute("aria-valuetext", b):this.handle1.removeAttribute("aria-valuetext"), this.handle2.style[this.stylePos]=a[1]+"%", this.handle2.setAttribute("aria-valuenow", this._state.value[1]), b=this.options.formatter(this._state.value[1]), isNaN(b)?this.handle2.setAttribute("aria-valuetext", b):this.handle2.removeAttribute("aria-valuetext"), this.rangeHighlightElements.length>0&&Array.isArray(this.options.rangeHighlights)&&this.options.rangeHighlights.length>0)for(var c=0; + c0) { + var h, i="vertical"===this.options.orientation?"height": "width"; + h="vertical"===this.options.orientation?"marginTop": this.options.rtl?"marginRight":"marginLeft"; + var j=this._state.size/(this.options.ticks.length-1); + if(this.tickLabelContainer) { + var k=0; + if(0===this.options.ticks_positions.length)"vertical"!==this.options.orientation&&(this.tickLabelContainer.style[h]=-j/2+"px"), k=this.tickLabelContainer.offsetHeight; + else for(l=0; + lk&&(k=this.tickLabelContainer.childNodes[l].offsetHeight); + "horizontal"===this.options.orientation&&(this.sliderElem.style.marginBottom=k+"px") + } + for(var l=0; + l=a[0]&&m<=a[1]&&this._addClass(this.ticks[l], "in-selection"): "after"===this.options.selection&&m>=a[0]?this._addClass(this.ticks[l], "in-selection"):"before"===this.options.selection&&m<=a[0]&&this._addClass(this.ticks[l], "in-selection"), this.tickLabels[l]&&(this.tickLabels[l].style[i]=j+"px", "vertical"!==this.options.orientation&&void 0!==this.options.ticks_positions[l]?(this.tickLabels[l].style.position="absolute", this.tickLabels[l].style[this.stylePos]=m+"%", this.tickLabels[l].style[h]=-j/2+"px"):"vertical"===this.options.orientation&&(this.options.rtl?this.tickLabels[l].style.marginRight=this.sliderElem.offsetWidth+"px":this.tickLabels[l].style.marginLeft=this.sliderElem.offsetWidth+"px", this.tickLabelContainer.style[h]=this.sliderElem.offsetWidth/2*-1+"px"), this._removeClass(this.tickLabels[l], "label-in-selection label-is-selection"), this.options.range?m>=a[0]&&m<=a[1]&&(this._addClass(this.tickLabels[l], "label-in-selection"), (m===a[0]||a[1])&&this._addClass(this.tickLabels[l], "label-is-selection")):("after"===this.options.selection&&m>=a[0]?this._addClass(this.tickLabels[l], "label-in-selection"):"before"===this.options.selection&&m<=a[0]&&this._addClass(this.tickLabels[l], "label-in-selection"), m===a[0]&&this._addClass(this.tickLabels[l], "label-is-selection"))) + } + } + var n; + if(this.options.range) { + n=this.options.formatter(this._state.value), this._setText(this.tooltipInner, n), this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%"; + var o=this.options.formatter(this._state.value[0]); + this._setText(this.tooltipInner_min, o); + var p=this.options.formatter(this._state.value[1]); + this._setText(this.tooltipInner_max, p), this.tooltip_min.style[this.stylePos]=a[0]+"%", this.tooltip_max.style[this.stylePos]=a[1]+"%" + } + else n=this.options.formatter(this._state.value[0]), this._setText(this.tooltipInner, n), this.tooltip.style[this.stylePos]=a[0]+"%"; + if("vertical"===this.options.orientation)this.trackLow.style.top="0", this.trackLow.style.height=Math.min(a[0], a[1])+"%", this.trackSelection.style.top=Math.min(a[0], a[1])+"%", this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%", this.trackHigh.style.bottom="0", this.trackHigh.style.height=100-Math.min(a[0], a[1])-Math.abs(a[0]-a[1])+"%"; + else { + "right"===this.stylePos?this.trackLow.style.right="0": this.trackLow.style.left="0", this.trackLow.style.width=Math.min(a[0], a[1])+"%", "right"===this.stylePos?this.trackSelection.style.right=Math.min(a[0], a[1])+"%":this.trackSelection.style.left=Math.min(a[0], a[1])+"%", this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%", "right"===this.stylePos?this.trackHigh.style.left="0":this.trackHigh.style.right="0", this.trackHigh.style.width=100-Math.min(a[0], a[1])-Math.abs(a[0]-a[1])+"%"; + var q=this.tooltip_min.getBoundingClientRect(), r=this.tooltip_max.getBoundingClientRect(); + "bottom"===this.options.tooltip_position?q.right>r.left?(this._removeClass(this.tooltip_max, "bottom"), this._addClass(this.tooltip_max, "top"), this.tooltip_max.style.top="", this.tooltip_max.style.bottom="22px"): (this._removeClass(this.tooltip_max, "top"), this._addClass(this.tooltip_max, "bottom"), this.tooltip_max.style.top=this.tooltip_min.style.top, this.tooltip_max.style.bottom=""):q.right>r.left?(this._removeClass(this.tooltip_max, "top"), this._addClass(this.tooltip_max, "bottom"), this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max, "bottom"), this._addClass(this.tooltip_max, "top"), this.tooltip_max.style.top=this.tooltip_min.style.top) + } + } + , _createHighlightRange:function(a, b) { + return this._isHighlightRange(a, b)?a>b? { + start: b, size:a-b + } + : { + start: a, size:b-a + } + :null + } + , _isHighlightRange:function(a, b) { + return a>=0&&100>=a&&b>=0&&100>=b?!0: !1 + } + , _resize:function(a) { + this._state.offset=this._offset(this.sliderElem), this._state.size=this.sliderElem[this.sizePos], this._layout() + } + , _removeProperty:function(a, b) { + a.style.removeProperty?a.style.removeProperty(b): a.style.removeAttribute(b) + } + , _mousedown:function(a) { + if(!this._state.enabled)return!1; + a.preventDefault&&a.preventDefault(), this._state.offset=this._offset(this.sliderElem), this._state.size=this.sliderElem[this.sizePos]; + var b=this._getPercentage(a); + if(this.options.range) { + var c=Math.abs(this._state.percentage[0]-b), d=Math.abs(this._state.percentage[1]-b); + this._state.dragged=d>c?0: 1, this._adjustPercentageForRangeSliders(b) + } + else this._state.dragged=0; + this._state.percentage[this._state.dragged]=b, this.touchCapable&&(document.removeEventListener("touchmove", this.mousemove, !1), document.removeEventListener("touchend", this.mouseup, !1)), this.mousemove&&document.removeEventListener("mousemove", this.mousemove, !1), this.mouseup&&document.removeEventListener("mouseup", this.mouseup, !1), this.mousemove=this._mousemove.bind(this), this.mouseup=this._mouseup.bind(this), this.touchCapable&&(document.addEventListener("touchmove", this.mousemove, !1), document.addEventListener("touchend", this.mouseup, !1)), document.addEventListener("mousemove", this.mousemove, !1), document.addEventListener("mouseup", this.mouseup, !1), this._state.inDrag=!0; + var e=this._calculateValue(); + return this._trigger("slideStart", e), this.setValue(e, !1, !0), a.returnValue=!1, this.options.focus&&this._triggerFocusOnHandle(this._state.dragged), !0 + } + , _touchstart:function(a) { + this._mousedown(a) + } + , _triggerFocusOnHandle:function(a) { + 0===a&&this.handle1.focus(), 1===a&&this.handle2.focus() + } + , _keydown:function(a, b) { + if(!this._state.enabled)return!1; + var c; + switch(b.keyCode) { + case 37: case 40:c=-1; + break; + case 39: case 38:c=1 + } + if(c) { + if(this.options.natural_arrow_keys) { + var d="horizontal"===this.options.orientation, e="vertical"===this.options.orientation, f=this.options.rtl, g=this.options.reversed; + d?f?g||(c=-c): g&&(c=-c):e&&(g||(c=-c)) + } + var h; + if(this.ticksAreValid&&this.options.lock_to_ticks) { + var i=void 0; + i=this.options.ticks.indexOf(this._state.value[a]), -1===i&&(i=0, window.console.warn("(lock_to_ticks) _keydown: index should not be -1")), i+=c, i=Math.max(0, Math.min(this.options.ticks.length-1, i)), h=this.options.ticks[i] + } + else h=this._state.value[a]+c*this.options.step; + var j=this._toPercentage(h); + if(this._state.keyCtrl=a, this.options.range) { + this._adjustPercentageForRangeSliders(j); + var k=this._state.keyCtrl?this._state.value[0]: h, l=this._state.keyCtrl?h:this._state.value[1]; + h=[Math.max(this.options.min, Math.min(this.options.max, k)), Math.max(this.options.min, Math.min(this.options.max, l))] + } + else h=Math.max(this.options.min, Math.min(this.options.max, h)); + return this._trigger("slideStart", h), this.setValue(h, !0, !0), this._trigger("slideStop", h), this._pauseEvent(b), delete this._state.keyCtrl, !1 + } + } + , _pauseEvent:function(a) { + a.stopPropagation&&a.stopPropagation(), a.preventDefault&&a.preventDefault(), a.cancelBubble=!0, a.returnValue=!1 + } + , _mousemove:function(a) { + if(!this._state.enabled)return!1; + var b=this._getPercentage(a); + this._adjustPercentageForRangeSliders(b), this._state.percentage[this._state.dragged]=b; + var c=this._calculateValue(!0); + return this.setValue(c, !0, !0), !1 + } + , _touchmove:function(a) { + void 0!==a.changedTouches&&a.preventDefault&&a.preventDefault() + } + , _adjustPercentageForRangeSliders:function(a) { + if(this.options.range) { + var b=this._getNumDigitsAfterDecimalPlace(a); + b=b?b-1: 0; + var c=this._applyToFixedAndParseFloat(a, b); + 0===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[1], b)c?(this._state.percentage[1]=this._state.percentage[0], this._state.dragged=0):0===this._state.keyCtrl&&this._toPercentage(this._state.value[1])a&&(this._state.percentage[1]=this._state.percentage[0], this._state.keyCtrl=0, this.handle1.focus()) + } + } + , _mouseup:function(a) { + if(!this._state.enabled)return!1; + var b=this._getPercentage(a); + this._adjustPercentageForRangeSliders(b), this._state.percentage[this._state.dragged]=b, this.touchCapable&&(document.removeEventListener("touchmove", this.mousemove, !1), document.removeEventListener("touchend", this.mouseup, !1)), document.removeEventListener("mousemove", this.mousemove, !1), document.removeEventListener("mouseup", this.mouseup, !1), this._state.inDrag=!1, this._state.over===!1&&this._hideTooltip(); + var c=this._calculateValue(!0); + return this.setValue(c, !1, !0), this._trigger("slideStop", c), this._state.dragged=null, !1 + } + , _setValues:function(a, b) { + var c=0===a?0: 100; + this._state.percentage[a]!==c&&(b.data[a]=this._toValue(this._state.percentage[a]), b.data[a]=this._applyPrecision(b.data[a])) + } + , _calculateValue:function(a) { + var b= {} + ; + return this.options.range?(b.data=[this.options.min, this.options.max], this._setValues(0, b), this._setValues(1, b), a&&(b.data[0]=this._snapToClosestTick(b.data[0]), b.data[1]=this._snapToClosestTick(b.data[1]))): (b.data=this._toValue(this._state.percentage[0]), b.data=parseFloat(b.data), b.data=this._applyPrecision(b.data), a&&(b.data=this._snapToClosestTick(b.data))), b.data + } + , _snapToClosestTick:function(a) { + for(var b=[a, 1/0], c=0; + ce&&(b=e, c=d) + } + return c + } + , _setTickIndex:function() { + this.ticksAreValid&&(this._state.tickIndex=[this.options.ticks.indexOf(this._state.value[0]), this.options.ticks.indexOf(this._state.value[1])]) + } + } + , a&&a.fn&&(a.fn.slider?(windowIsDefined&&window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSlider namespace instead."), f=c):(a.bridget(b, d), f=b), a.bridget(c, d), a(function() { + a("input[data-provide=slider]")[f]() + } + )) + } + (a), d +} + +); \ No newline at end of file diff --git a/src/main/resources/static/js/bootstrap.js b/src/main/resources/static/js/bootstrap.js new file mode 100644 index 0000000..af3e1bf --- /dev/null +++ b/src/main/resources/static/js/bootstrap.js @@ -0,0 +1,3944 @@ +/*! + * Bootstrap v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery'), require('popper.js')) : + typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) : + (factory((global.bootstrap = {}),global.jQuery,global.Popper)); +}(this, (function (exports,$,Popper) { 'use strict'; + + $ = $ && $.hasOwnProperty('default') ? $['default'] : $; + Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper; + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; + } + + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): util.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Util = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Private TransitionEnd Helpers + * ------------------------------------------------------------------------ + */ + var TRANSITION_END = 'transitionend'; + var MAX_UID = 1000000; + var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) + + function toType(obj) { + return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); + } + + function getSpecialTransitionEndEvent() { + return { + bindType: TRANSITION_END, + delegateType: TRANSITION_END, + handle: function handle(event) { + if ($$$1(event.target).is(this)) { + return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params + } + + return undefined; // eslint-disable-line no-undefined + } + }; + } + + function transitionEndEmulator(duration) { + var _this = this; + + var called = false; + $$$1(this).one(Util.TRANSITION_END, function () { + called = true; + }); + setTimeout(function () { + if (!called) { + Util.triggerTransitionEnd(_this); + } + }, duration); + return this; + } + + function setTransitionEndSupport() { + $$$1.fn.emulateTransitionEnd = transitionEndEmulator; + $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); + } + /** + * -------------------------------------------------------------------------- + * Public Util Api + * -------------------------------------------------------------------------- + */ + + + var Util = { + TRANSITION_END: 'bsTransitionEnd', + getUID: function getUID(prefix) { + do { + // eslint-disable-next-line no-bitwise + prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here + } while (document.getElementById(prefix)); + + return prefix; + }, + getSelectorFromElement: function getSelectorFromElement(element) { + var selector = element.getAttribute('data-target'); + + if (!selector || selector === '#') { + selector = element.getAttribute('href') || ''; + } + + try { + return document.querySelector(selector) ? selector : null; + } catch (err) { + return null; + } + }, + getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { + if (!element) { + return 0; + } // Get transition-duration of the element + + + var transitionDuration = $$$1(element).css('transition-duration'); + var floatTransitionDuration = parseFloat(transitionDuration); // Return 0 if element or transition duration is not found + + if (!floatTransitionDuration) { + return 0; + } // If multiple durations are defined, take the first + + + transitionDuration = transitionDuration.split(',')[0]; + return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER; + }, + reflow: function reflow(element) { + return element.offsetHeight; + }, + triggerTransitionEnd: function triggerTransitionEnd(element) { + $$$1(element).trigger(TRANSITION_END); + }, + // TODO: Remove in v5 + supportsTransitionEnd: function supportsTransitionEnd() { + return Boolean(TRANSITION_END); + }, + isElement: function isElement(obj) { + return (obj[0] || obj).nodeType; + }, + typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { + for (var property in configTypes) { + if (Object.prototype.hasOwnProperty.call(configTypes, property)) { + var expectedTypes = configTypes[property]; + var value = config[property]; + var valueType = value && Util.isElement(value) ? 'element' : toType(value); + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); + } + } + } + } + }; + setTransitionEndSupport(); + return Util; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): alert.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Alert = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'alert'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.alert'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Selector = { + DISMISS: '[data-dismiss="alert"]' + }; + var Event = { + CLOSE: "close" + EVENT_KEY, + CLOSED: "closed" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + ALERT: 'alert', + FADE: 'fade', + SHOW: 'show' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Alert = + /*#__PURE__*/ + function () { + function Alert(element) { + this._element = element; + } // Getters + + + var _proto = Alert.prototype; + + // Public + _proto.close = function close(element) { + var rootElement = this._element; + + if (element) { + rootElement = this._getRootElement(element); + } + + var customEvent = this._triggerCloseEvent(rootElement); + + if (customEvent.isDefaultPrevented()) { + return; + } + + this._removeElement(rootElement); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._element = null; + }; // Private + + + _proto._getRootElement = function _getRootElement(element) { + var selector = Util.getSelectorFromElement(element); + var parent = false; + + if (selector) { + parent = document.querySelector(selector); + } + + if (!parent) { + parent = $$$1(element).closest("." + ClassName.ALERT)[0]; + } + + return parent; + }; + + _proto._triggerCloseEvent = function _triggerCloseEvent(element) { + var closeEvent = $$$1.Event(Event.CLOSE); + $$$1(element).trigger(closeEvent); + return closeEvent; + }; + + _proto._removeElement = function _removeElement(element) { + var _this = this; + + $$$1(element).removeClass(ClassName.SHOW); + + if (!$$$1(element).hasClass(ClassName.FADE)) { + this._destroyElement(element); + + return; + } + + var transitionDuration = Util.getTransitionDurationFromElement(element); + $$$1(element).one(Util.TRANSITION_END, function (event) { + return _this._destroyElement(element, event); + }).emulateTransitionEnd(transitionDuration); + }; + + _proto._destroyElement = function _destroyElement(element) { + $$$1(element).detach().trigger(Event.CLOSED).remove(); + }; // Static + + + Alert._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $element = $$$1(this); + var data = $element.data(DATA_KEY); + + if (!data) { + data = new Alert(this); + $element.data(DATA_KEY, data); + } + + if (config === 'close') { + data[config](this); + } + }); + }; + + Alert._handleDismiss = function _handleDismiss(alertInstance) { + return function (event) { + if (event) { + event.preventDefault(); + } + + alertInstance.close(this); + }; + }; + + _createClass(Alert, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }]); + + return Alert; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Alert._jQueryInterface; + $$$1.fn[NAME].Constructor = Alert; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Alert._jQueryInterface; + }; + + return Alert; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): button.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Button = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'button'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.button'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ClassName = { + ACTIVE: 'active', + BUTTON: 'btn', + FOCUS: 'focus' + }; + var Selector = { + DATA_TOGGLE_CARROT: '[data-toggle^="button"]', + DATA_TOGGLE: '[data-toggle="buttons"]', + INPUT: 'input', + ACTIVE: '.active', + BUTTON: '.btn' + }; + var Event = { + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, + FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY) + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Button = + /*#__PURE__*/ + function () { + function Button(element) { + this._element = element; + } // Getters + + + var _proto = Button.prototype; + + // Public + _proto.toggle = function toggle() { + var triggerChangeEvent = true; + var addAriaPressed = true; + var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0]; + + if (rootElement) { + var input = this._element.querySelector(Selector.INPUT); + + if (input) { + if (input.type === 'radio') { + if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) { + triggerChangeEvent = false; + } else { + var activeElement = rootElement.querySelector(Selector.ACTIVE); + + if (activeElement) { + $$$1(activeElement).removeClass(ClassName.ACTIVE); + } + } + } + + if (triggerChangeEvent) { + if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) { + return; + } + + input.checked = !this._element.classList.contains(ClassName.ACTIVE); + $$$1(input).trigger('change'); + } + + input.focus(); + addAriaPressed = false; + } + } + + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE)); + } + + if (triggerChangeEvent) { + $$$1(this._element).toggleClass(ClassName.ACTIVE); + } + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._element = null; + }; // Static + + + Button._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + if (!data) { + data = new Button(this); + $$$1(this).data(DATA_KEY, data); + } + + if (config === 'toggle') { + data[config](); + } + }); + }; + + _createClass(Button, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }]); + + return Button; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { + event.preventDefault(); + var button = event.target; + + if (!$$$1(button).hasClass(ClassName.BUTTON)) { + button = $$$1(button).closest(Selector.BUTTON); + } + + Button._jQueryInterface.call($$$1(button), 'toggle'); + }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { + var button = $$$1(event.target).closest(Selector.BUTTON)[0]; + $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Button._jQueryInterface; + $$$1.fn[NAME].Constructor = Button; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Button._jQueryInterface; + }; + + return Button; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): carousel.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Carousel = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'carousel'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.carousel'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key + + var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key + + var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch + + var Default = { + interval: 5000, + keyboard: true, + slide: false, + pause: 'hover', + wrap: true + }; + var DefaultType = { + interval: '(number|boolean)', + keyboard: 'boolean', + slide: '(boolean|string)', + pause: '(string|boolean)', + wrap: 'boolean' + }; + var Direction = { + NEXT: 'next', + PREV: 'prev', + LEFT: 'left', + RIGHT: 'right' + }; + var Event = { + SLIDE: "slide" + EVENT_KEY, + SLID: "slid" + EVENT_KEY, + KEYDOWN: "keydown" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY, + TOUCHEND: "touchend" + EVENT_KEY, + LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + CAROUSEL: 'carousel', + ACTIVE: 'active', + SLIDE: 'slide', + RIGHT: 'carousel-item-right', + LEFT: 'carousel-item-left', + NEXT: 'carousel-item-next', + PREV: 'carousel-item-prev', + ITEM: 'carousel-item' + }; + var Selector = { + ACTIVE: '.active', + ACTIVE_ITEM: '.active.carousel-item', + ITEM: '.carousel-item', + NEXT_PREV: '.carousel-item-next, .carousel-item-prev', + INDICATORS: '.carousel-indicators', + DATA_SLIDE: '[data-slide], [data-slide-to]', + DATA_RIDE: '[data-ride="carousel"]' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Carousel = + /*#__PURE__*/ + function () { + function Carousel(element, config) { + this._items = null; + this._interval = null; + this._activeElement = null; + this._isPaused = false; + this._isSliding = false; + this.touchTimeout = null; + this._config = this._getConfig(config); + this._element = $$$1(element)[0]; + this._indicatorsElement = this._element.querySelector(Selector.INDICATORS); + + this._addEventListeners(); + } // Getters + + + var _proto = Carousel.prototype; + + // Public + _proto.next = function next() { + if (!this._isSliding) { + this._slide(Direction.NEXT); + } + }; + + _proto.nextWhenVisible = function nextWhenVisible() { + // Don't call next when the page isn't visible + // or the carousel or its parent isn't visible + if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') { + this.next(); + } + }; + + _proto.prev = function prev() { + if (!this._isSliding) { + this._slide(Direction.PREV); + } + }; + + _proto.pause = function pause(event) { + if (!event) { + this._isPaused = true; + } + + if (this._element.querySelector(Selector.NEXT_PREV)) { + Util.triggerTransitionEnd(this._element); + this.cycle(true); + } + + clearInterval(this._interval); + this._interval = null; + }; + + _proto.cycle = function cycle(event) { + if (!event) { + this._isPaused = false; + } + + if (this._interval) { + clearInterval(this._interval); + this._interval = null; + } + + if (this._config.interval && !this._isPaused) { + this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); + } + }; + + _proto.to = function to(index) { + var _this = this; + + this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); + + var activeIndex = this._getItemIndex(this._activeElement); + + if (index > this._items.length - 1 || index < 0) { + return; + } + + if (this._isSliding) { + $$$1(this._element).one(Event.SLID, function () { + return _this.to(index); + }); + return; + } + + if (activeIndex === index) { + this.pause(); + this.cycle(); + return; + } + + var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; + + this._slide(direction, this._items[index]); + }; + + _proto.dispose = function dispose() { + $$$1(this._element).off(EVENT_KEY); + $$$1.removeData(this._element, DATA_KEY); + this._items = null; + this._config = null; + this._element = null; + this._interval = null; + this._isPaused = null; + this._isSliding = null; + this._activeElement = null; + this._indicatorsElement = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._addEventListeners = function _addEventListeners() { + var _this2 = this; + + if (this._config.keyboard) { + $$$1(this._element).on(Event.KEYDOWN, function (event) { + return _this2._keydown(event); + }); + } + + if (this._config.pause === 'hover') { + $$$1(this._element).on(Event.MOUSEENTER, function (event) { + return _this2.pause(event); + }).on(Event.MOUSELEAVE, function (event) { + return _this2.cycle(event); + }); + + if ('ontouchstart' in document.documentElement) { + // If it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + $$$1(this._element).on(Event.TOUCHEND, function () { + _this2.pause(); + + if (_this2.touchTimeout) { + clearTimeout(_this2.touchTimeout); + } + + _this2.touchTimeout = setTimeout(function (event) { + return _this2.cycle(event); + }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval); + }); + } + } + }; + + _proto._keydown = function _keydown(event) { + if (/input|textarea/i.test(event.target.tagName)) { + return; + } + + switch (event.which) { + case ARROW_LEFT_KEYCODE: + event.preventDefault(); + this.prev(); + break; + + case ARROW_RIGHT_KEYCODE: + event.preventDefault(); + this.next(); + break; + + default: + } + }; + + _proto._getItemIndex = function _getItemIndex(element) { + this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : []; + return this._items.indexOf(element); + }; + + _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { + var isNextDirection = direction === Direction.NEXT; + var isPrevDirection = direction === Direction.PREV; + + var activeIndex = this._getItemIndex(activeElement); + + var lastItemIndex = this._items.length - 1; + var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; + + if (isGoingToWrap && !this._config.wrap) { + return activeElement; + } + + var delta = direction === Direction.PREV ? -1 : 1; + var itemIndex = (activeIndex + delta) % this._items.length; + return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; + }; + + _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { + var targetIndex = this._getItemIndex(relatedTarget); + + var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)); + + var slideEvent = $$$1.Event(Event.SLIDE, { + relatedTarget: relatedTarget, + direction: eventDirectionName, + from: fromIndex, + to: targetIndex + }); + $$$1(this._element).trigger(slideEvent); + return slideEvent; + }; + + _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { + if (this._indicatorsElement) { + var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)); + $$$1(indicators).removeClass(ClassName.ACTIVE); + + var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; + + if (nextIndicator) { + $$$1(nextIndicator).addClass(ClassName.ACTIVE); + } + } + }; + + _proto._slide = function _slide(direction, element) { + var _this3 = this; + + var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); + + var activeElementIndex = this._getItemIndex(activeElement); + + var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); + + var nextElementIndex = this._getItemIndex(nextElement); + + var isCycling = Boolean(this._interval); + var directionalClassName; + var orderClassName; + var eventDirectionName; + + if (direction === Direction.NEXT) { + directionalClassName = ClassName.LEFT; + orderClassName = ClassName.NEXT; + eventDirectionName = Direction.LEFT; + } else { + directionalClassName = ClassName.RIGHT; + orderClassName = ClassName.PREV; + eventDirectionName = Direction.RIGHT; + } + + if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) { + this._isSliding = false; + return; + } + + var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); + + if (slideEvent.isDefaultPrevented()) { + return; + } + + if (!activeElement || !nextElement) { + // Some weirdness is happening, so we bail + return; + } + + this._isSliding = true; + + if (isCycling) { + this.pause(); + } + + this._setActiveIndicatorElement(nextElement); + + var slidEvent = $$$1.Event(Event.SLID, { + relatedTarget: nextElement, + direction: eventDirectionName, + from: activeElementIndex, + to: nextElementIndex + }); + + if ($$$1(this._element).hasClass(ClassName.SLIDE)) { + $$$1(nextElement).addClass(orderClassName); + Util.reflow(nextElement); + $$$1(activeElement).addClass(directionalClassName); + $$$1(nextElement).addClass(directionalClassName); + var transitionDuration = Util.getTransitionDurationFromElement(activeElement); + $$$1(activeElement).one(Util.TRANSITION_END, function () { + $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE); + $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName); + _this3._isSliding = false; + setTimeout(function () { + return $$$1(_this3._element).trigger(slidEvent); + }, 0); + }).emulateTransitionEnd(transitionDuration); + } else { + $$$1(activeElement).removeClass(ClassName.ACTIVE); + $$$1(nextElement).addClass(ClassName.ACTIVE); + this._isSliding = false; + $$$1(this._element).trigger(slidEvent); + } + + if (isCycling) { + this.cycle(); + } + }; // Static + + + Carousel._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = _objectSpread({}, Default, $$$1(this).data()); + + if (typeof config === 'object') { + _config = _objectSpread({}, _config, config); + } + + var action = typeof config === 'string' ? config : _config.slide; + + if (!data) { + data = new Carousel(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'number') { + data.to(config); + } else if (typeof action === 'string') { + if (typeof data[action] === 'undefined') { + throw new TypeError("No method named \"" + action + "\""); + } + + data[action](); + } else if (_config.interval) { + data.pause(); + data.cycle(); + } + }); + }; + + Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { + var selector = Util.getSelectorFromElement(this); + + if (!selector) { + return; + } + + var target = $$$1(selector)[0]; + + if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) { + return; + } + + var config = _objectSpread({}, $$$1(target).data(), $$$1(this).data()); + + var slideIndex = this.getAttribute('data-slide-to'); + + if (slideIndex) { + config.interval = false; + } + + Carousel._jQueryInterface.call($$$1(target), config); + + if (slideIndex) { + $$$1(target).data(DATA_KEY).to(slideIndex); + } + + event.preventDefault(); + }; + + _createClass(Carousel, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Carousel; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); + $$$1(window).on(Event.LOAD_DATA_API, function () { + var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)); + + for (var i = 0, len = carousels.length; i < len; i++) { + var $carousel = $$$1(carousels[i]); + + Carousel._jQueryInterface.call($carousel, $carousel.data()); + } + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Carousel._jQueryInterface; + $$$1.fn[NAME].Constructor = Carousel; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Carousel._jQueryInterface; + }; + + return Carousel; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): collapse.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Collapse = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'collapse'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.collapse'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Default = { + toggle: true, + parent: '' + }; + var DefaultType = { + toggle: 'boolean', + parent: '(string|element)' + }; + var Event = { + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + SHOW: 'show', + COLLAPSE: 'collapse', + COLLAPSING: 'collapsing', + COLLAPSED: 'collapsed' + }; + var Dimension = { + WIDTH: 'width', + HEIGHT: 'height' + }; + var Selector = { + ACTIVES: '.show, .collapsing', + DATA_TOGGLE: '[data-toggle="collapse"]' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Collapse = + /*#__PURE__*/ + function () { + function Collapse(element, config) { + this._isTransitioning = false; + this._element = element; + this._config = this._getConfig(config); + this._triggerArray = $$$1.makeArray(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); + var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); + + for (var i = 0, len = toggleList.length; i < len; i++) { + var elem = toggleList[i]; + var selector = Util.getSelectorFromElement(elem); + var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) { + return foundElem === element; + }); + + if (selector !== null && filterElement.length > 0) { + this._selector = selector; + + this._triggerArray.push(elem); + } + } + + this._parent = this._config.parent ? this._getParent() : null; + + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._element, this._triggerArray); + } + + if (this._config.toggle) { + this.toggle(); + } + } // Getters + + + var _proto = Collapse.prototype; + + // Public + _proto.toggle = function toggle() { + if ($$$1(this._element).hasClass(ClassName.SHOW)) { + this.hide(); + } else { + this.show(); + } + }; + + _proto.show = function show() { + var _this = this; + + if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) { + return; + } + + var actives; + var activesData; + + if (this._parent) { + actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) { + return elem.getAttribute('data-parent') === _this._config.parent; + }); + + if (actives.length === 0) { + actives = null; + } + } + + if (actives) { + activesData = $$$1(actives).not(this._selector).data(DATA_KEY); + + if (activesData && activesData._isTransitioning) { + return; + } + } + + var startEvent = $$$1.Event(Event.SHOW); + $$$1(this._element).trigger(startEvent); + + if (startEvent.isDefaultPrevented()) { + return; + } + + if (actives) { + Collapse._jQueryInterface.call($$$1(actives).not(this._selector), 'hide'); + + if (!activesData) { + $$$1(actives).data(DATA_KEY, null); + } + } + + var dimension = this._getDimension(); + + $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); + this._element.style[dimension] = 0; + + if (this._triggerArray.length) { + $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); + } + + this.setTransitioning(true); + + var complete = function complete() { + $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW); + _this._element.style[dimension] = ''; + + _this.setTransitioning(false); + + $$$1(_this._element).trigger(Event.SHOWN); + }; + + var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); + var scrollSize = "scroll" + capitalizedDimension; + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + this._element.style[dimension] = this._element[scrollSize] + "px"; + }; + + _proto.hide = function hide() { + var _this2 = this; + + if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) { + return; + } + + var startEvent = $$$1.Event(Event.HIDE); + $$$1(this._element).trigger(startEvent); + + if (startEvent.isDefaultPrevented()) { + return; + } + + var dimension = this._getDimension(); + + this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; + Util.reflow(this._element); + $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); + var triggerArrayLength = this._triggerArray.length; + + if (triggerArrayLength > 0) { + for (var i = 0; i < triggerArrayLength; i++) { + var trigger = this._triggerArray[i]; + var selector = Util.getSelectorFromElement(trigger); + + if (selector !== null) { + var $elem = $$$1([].slice.call(document.querySelectorAll(selector))); + + if (!$elem.hasClass(ClassName.SHOW)) { + $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); + } + } + } + } + + this.setTransitioning(true); + + var complete = function complete() { + _this2.setTransitioning(false); + + $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); + }; + + this._element.style[dimension] = ''; + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + }; + + _proto.setTransitioning = function setTransitioning(isTransitioning) { + this._isTransitioning = isTransitioning; + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._config = null; + this._parent = null; + this._element = null; + this._triggerArray = null; + this._isTransitioning = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + config.toggle = Boolean(config.toggle); // Coerce string values + + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._getDimension = function _getDimension() { + var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH); + return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; + }; + + _proto._getParent = function _getParent() { + var _this3 = this; + + var parent = null; + + if (Util.isElement(this._config.parent)) { + parent = this._config.parent; // It's a jQuery object + + if (typeof this._config.parent.jquery !== 'undefined') { + parent = this._config.parent[0]; + } + } else { + parent = document.querySelector(this._config.parent); + } + + var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; + var children = [].slice.call(parent.querySelectorAll(selector)); + $$$1(children).each(function (i, element) { + _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); + }); + return parent; + }; + + _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { + if (element) { + var isOpen = $$$1(element).hasClass(ClassName.SHOW); + + if (triggerArray.length) { + $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); + } + } + }; // Static + + + Collapse._getTargetFromElement = function _getTargetFromElement(element) { + var selector = Util.getSelectorFromElement(element); + return selector ? document.querySelector(selector) : null; + }; + + Collapse._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $this = $$$1(this); + var data = $this.data(DATA_KEY); + + var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {}); + + if (!data && _config.toggle && /show|hide/.test(config)) { + _config.toggle = false; + } + + if (!data) { + data = new Collapse(this, _config); + $this.data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Collapse, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Collapse; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + // preventDefault only for elements (which change the URL) not inside the collapsible element + if (event.currentTarget.tagName === 'A') { + event.preventDefault(); + } + + var $trigger = $$$1(this); + var selector = Util.getSelectorFromElement(this); + var selectors = [].slice.call(document.querySelectorAll(selector)); + $$$1(selectors).each(function () { + var $target = $$$1(this); + var data = $target.data(DATA_KEY); + var config = data ? 'toggle' : $trigger.data(); + + Collapse._jQueryInterface.call($target, config); + }); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Collapse._jQueryInterface; + $$$1.fn[NAME].Constructor = Collapse; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Collapse._jQueryInterface; + }; + + return Collapse; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): dropdown.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Dropdown = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'dropdown'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.dropdown'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key + + var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key + + var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key + + var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key + + var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) + + var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, + KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY, + KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + DISABLED: 'disabled', + SHOW: 'show', + DROPUP: 'dropup', + DROPRIGHT: 'dropright', + DROPLEFT: 'dropleft', + MENURIGHT: 'dropdown-menu-right', + MENULEFT: 'dropdown-menu-left', + POSITION_STATIC: 'position-static' + }; + var Selector = { + DATA_TOGGLE: '[data-toggle="dropdown"]', + FORM_CHILD: '.dropdown form', + MENU: '.dropdown-menu', + NAVBAR_NAV: '.navbar-nav', + VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' + }; + var AttachmentMap = { + TOP: 'top-start', + TOPEND: 'top-end', + BOTTOM: 'bottom-start', + BOTTOMEND: 'bottom-end', + RIGHT: 'right-start', + RIGHTEND: 'right-end', + LEFT: 'left-start', + LEFTEND: 'left-end' + }; + var Default = { + offset: 0, + flip: true, + boundary: 'scrollParent', + reference: 'toggle', + display: 'dynamic' + }; + var DefaultType = { + offset: '(number|string|function)', + flip: 'boolean', + boundary: '(string|element)', + reference: '(string|element)', + display: 'string' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Dropdown = + /*#__PURE__*/ + function () { + function Dropdown(element, config) { + this._element = element; + this._popper = null; + this._config = this._getConfig(config); + this._menu = this._getMenuElement(); + this._inNavbar = this._detectNavbar(); + + this._addEventListeners(); + } // Getters + + + var _proto = Dropdown.prototype; + + // Public + _proto.toggle = function toggle() { + if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) { + return; + } + + var parent = Dropdown._getParentFromElement(this._element); + + var isActive = $$$1(this._menu).hasClass(ClassName.SHOW); + + Dropdown._clearMenus(); + + if (isActive) { + return; + } + + var relatedTarget = { + relatedTarget: this._element + }; + var showEvent = $$$1.Event(Event.SHOW, relatedTarget); + $$$1(parent).trigger(showEvent); + + if (showEvent.isDefaultPrevented()) { + return; + } // Disable totally Popper.js for Dropdown in Navbar + + + if (!this._inNavbar) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)'); + } + + var referenceElement = this._element; + + if (this._config.reference === 'parent') { + referenceElement = parent; + } else if (Util.isElement(this._config.reference)) { + referenceElement = this._config.reference; // Check if it's jQuery element + + if (typeof this._config.reference.jquery !== 'undefined') { + referenceElement = this._config.reference[0]; + } + } // If boundary is not `scrollParent`, then set position to `static` + // to allow the menu to "escape" the scroll parent's boundaries + // https://github.com/twbs/bootstrap/issues/24251 + + + if (this._config.boundary !== 'scrollParent') { + $$$1(parent).addClass(ClassName.POSITION_STATIC); + } + + this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()); + } // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + + + if ('ontouchstart' in document.documentElement && $$$1(parent).closest(Selector.NAVBAR_NAV).length === 0) { + $$$1(document.body).children().on('mouseover', null, $$$1.noop); + } + + this._element.focus(); + + this._element.setAttribute('aria-expanded', true); + + $$$1(this._menu).toggleClass(ClassName.SHOW); + $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget)); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(this._element).off(EVENT_KEY); + this._element = null; + this._menu = null; + + if (this._popper !== null) { + this._popper.destroy(); + + this._popper = null; + } + }; + + _proto.update = function update() { + this._inNavbar = this._detectNavbar(); + + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } + }; // Private + + + _proto._addEventListeners = function _addEventListeners() { + var _this = this; + + $$$1(this._element).on(Event.CLICK, function (event) { + event.preventDefault(); + event.stopPropagation(); + + _this.toggle(); + }); + }; + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, this.constructor.Default, $$$1(this._element).data(), config); + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + return config; + }; + + _proto._getMenuElement = function _getMenuElement() { + if (!this._menu) { + var parent = Dropdown._getParentFromElement(this._element); + + if (parent) { + this._menu = parent.querySelector(Selector.MENU); + } + } + + return this._menu; + }; + + _proto._getPlacement = function _getPlacement() { + var $parentDropdown = $$$1(this._element.parentNode); + var placement = AttachmentMap.BOTTOM; // Handle dropup + + if ($parentDropdown.hasClass(ClassName.DROPUP)) { + placement = AttachmentMap.TOP; + + if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.TOPEND; + } + } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { + placement = AttachmentMap.RIGHT; + } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { + placement = AttachmentMap.LEFT; + } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.BOTTOMEND; + } + + return placement; + }; + + _proto._detectNavbar = function _detectNavbar() { + return $$$1(this._element).closest('.navbar').length > 0; + }; + + _proto._getPopperConfig = function _getPopperConfig() { + var _this2 = this; + + var offsetConf = {}; + + if (typeof this._config.offset === 'function') { + offsetConf.fn = function (data) { + data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets) || {}); + return data; + }; + } else { + offsetConf.offset = this._config.offset; + } + + var popperConfig = { + placement: this._getPlacement(), + modifiers: { + offset: offsetConf, + flip: { + enabled: this._config.flip + }, + preventOverflow: { + boundariesElement: this._config.boundary + } + } // Disable Popper.js if we have a static display + + }; + + if (this._config.display === 'static') { + popperConfig.modifiers.applyStyle = { + enabled: false + }; + } + + return popperConfig; + }; // Static + + + Dropdown._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' ? config : null; + + if (!data) { + data = new Dropdown(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + Dropdown._clearMenus = function _clearMenus(event) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { + return; + } + + var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); + + for (var i = 0, len = toggles.length; i < len; i++) { + var parent = Dropdown._getParentFromElement(toggles[i]); + + var context = $$$1(toggles[i]).data(DATA_KEY); + var relatedTarget = { + relatedTarget: toggles[i] + }; + + if (event && event.type === 'click') { + relatedTarget.clickEvent = event; + } + + if (!context) { + continue; + } + + var dropdownMenu = context._menu; + + if (!$$$1(parent).hasClass(ClassName.SHOW)) { + continue; + } + + if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) { + continue; + } + + var hideEvent = $$$1.Event(Event.HIDE, relatedTarget); + $$$1(parent).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + continue; + } // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().off('mouseover', null, $$$1.noop); + } + + toggles[i].setAttribute('aria-expanded', 'false'); + $$$1(dropdownMenu).removeClass(ClassName.SHOW); + $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget)); + } + }; + + Dropdown._getParentFromElement = function _getParentFromElement(element) { + var parent; + var selector = Util.getSelectorFromElement(element); + + if (selector) { + parent = document.querySelector(selector); + } + + return parent || element.parentNode; + }; // eslint-disable-next-line complexity + + + Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { + // If not input/textarea: + // - And not a key in REGEXP_KEYDOWN => not a dropdown command + // If input/textarea: + // - If space key => not a dropdown command + // - If key is other than escape + // - If key is not up or down => not a dropdown command + // - If trigger inside the menu => not a dropdown command + if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $$$1(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) { + return; + } + + var parent = Dropdown._getParentFromElement(this); + + var isActive = $$$1(parent).hasClass(ClassName.SHOW); + + if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { + if (event.which === ESCAPE_KEYCODE) { + var toggle = parent.querySelector(Selector.DATA_TOGGLE); + $$$1(toggle).trigger('focus'); + } + + $$$1(this).trigger('click'); + return; + } + + var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)); + + if (items.length === 0) { + return; + } + + var index = items.indexOf(event.target); + + if (event.which === ARROW_UP_KEYCODE && index > 0) { + // Up + index--; + } + + if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { + // Down + index++; + } + + if (index < 0) { + index = 0; + } + + items[index].focus(); + }; + + _createClass(Dropdown, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Dropdown; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + event.preventDefault(); + event.stopPropagation(); + + Dropdown._jQueryInterface.call($$$1(this), 'toggle'); + }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { + e.stopPropagation(); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Dropdown._jQueryInterface; + $$$1.fn[NAME].Constructor = Dropdown; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Dropdown._jQueryInterface; + }; + + return Dropdown; + }($, Popper); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): modal.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Modal = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'modal'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.modal'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var Default = { + backdrop: true, + keyboard: true, + focus: true, + show: true + }; + var DefaultType = { + backdrop: '(boolean|string)', + keyboard: 'boolean', + focus: 'boolean', + show: 'boolean' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + RESIZE: "resize" + EVENT_KEY, + CLICK_DISMISS: "click.dismiss" + EVENT_KEY, + KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY, + MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY, + MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + SCROLLBAR_MEASURER: 'modal-scrollbar-measure', + BACKDROP: 'modal-backdrop', + OPEN: 'modal-open', + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + DIALOG: '.modal-dialog', + DATA_TOGGLE: '[data-toggle="modal"]', + DATA_DISMISS: '[data-dismiss="modal"]', + FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', + STICKY_CONTENT: '.sticky-top' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Modal = + /*#__PURE__*/ + function () { + function Modal(element, config) { + this._config = this._getConfig(config); + this._element = element; + this._dialog = element.querySelector(Selector.DIALOG); + this._backdrop = null; + this._isShown = false; + this._isBodyOverflowing = false; + this._ignoreBackdropClick = false; + this._scrollbarWidth = 0; + } // Getters + + + var _proto = Modal.prototype; + + // Public + _proto.toggle = function toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + }; + + _proto.show = function show(relatedTarget) { + var _this = this; + + if (this._isTransitioning || this._isShown) { + return; + } + + if ($$$1(this._element).hasClass(ClassName.FADE)) { + this._isTransitioning = true; + } + + var showEvent = $$$1.Event(Event.SHOW, { + relatedTarget: relatedTarget + }); + $$$1(this._element).trigger(showEvent); + + if (this._isShown || showEvent.isDefaultPrevented()) { + return; + } + + this._isShown = true; + + this._checkScrollbar(); + + this._setScrollbar(); + + this._adjustDialog(); + + $$$1(document.body).addClass(ClassName.OPEN); + + this._setEscapeEvent(); + + this._setResizeEvent(); + + $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { + return _this.hide(event); + }); + $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { + $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { + if ($$$1(event.target).is(_this._element)) { + _this._ignoreBackdropClick = true; + } + }); + }); + + this._showBackdrop(function () { + return _this._showElement(relatedTarget); + }); + }; + + _proto.hide = function hide(event) { + var _this2 = this; + + if (event) { + event.preventDefault(); + } + + if (this._isTransitioning || !this._isShown) { + return; + } + + var hideEvent = $$$1.Event(Event.HIDE); + $$$1(this._element).trigger(hideEvent); + + if (!this._isShown || hideEvent.isDefaultPrevented()) { + return; + } + + this._isShown = false; + var transition = $$$1(this._element).hasClass(ClassName.FADE); + + if (transition) { + this._isTransitioning = true; + } + + this._setEscapeEvent(); + + this._setResizeEvent(); + + $$$1(document).off(Event.FOCUSIN); + $$$1(this._element).removeClass(ClassName.SHOW); + $$$1(this._element).off(Event.CLICK_DISMISS); + $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS); + + if (transition) { + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, function (event) { + return _this2._hideModal(event); + }).emulateTransitionEnd(transitionDuration); + } else { + this._hideModal(); + } + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY); + this._config = null; + this._element = null; + this._dialog = null; + this._backdrop = null; + this._isShown = null; + this._isBodyOverflowing = null; + this._ignoreBackdropClick = null; + this._scrollbarWidth = null; + }; + + _proto.handleUpdate = function handleUpdate() { + this._adjustDialog(); + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._showElement = function _showElement(relatedTarget) { + var _this3 = this; + + var transition = $$$1(this._element).hasClass(ClassName.FADE); + + if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { + // Don't move modal's DOM position + document.body.appendChild(this._element); + } + + this._element.style.display = 'block'; + + this._element.removeAttribute('aria-hidden'); + + this._element.scrollTop = 0; + + if (transition) { + Util.reflow(this._element); + } + + $$$1(this._element).addClass(ClassName.SHOW); + + if (this._config.focus) { + this._enforceFocus(); + } + + var shownEvent = $$$1.Event(Event.SHOWN, { + relatedTarget: relatedTarget + }); + + var transitionComplete = function transitionComplete() { + if (_this3._config.focus) { + _this3._element.focus(); + } + + _this3._isTransitioning = false; + $$$1(_this3._element).trigger(shownEvent); + }; + + if (transition) { + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration); + } else { + transitionComplete(); + } + }; + + _proto._enforceFocus = function _enforceFocus() { + var _this4 = this; + + $$$1(document).off(Event.FOCUSIN) // Guard against infinite focus loop + .on(Event.FOCUSIN, function (event) { + if (document !== event.target && _this4._element !== event.target && $$$1(_this4._element).has(event.target).length === 0) { + _this4._element.focus(); + } + }); + }; + + _proto._setEscapeEvent = function _setEscapeEvent() { + var _this5 = this; + + if (this._isShown && this._config.keyboard) { + $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) { + if (event.which === ESCAPE_KEYCODE) { + event.preventDefault(); + + _this5.hide(); + } + }); + } else if (!this._isShown) { + $$$1(this._element).off(Event.KEYDOWN_DISMISS); + } + }; + + _proto._setResizeEvent = function _setResizeEvent() { + var _this6 = this; + + if (this._isShown) { + $$$1(window).on(Event.RESIZE, function (event) { + return _this6.handleUpdate(event); + }); + } else { + $$$1(window).off(Event.RESIZE); + } + }; + + _proto._hideModal = function _hideModal() { + var _this7 = this; + + this._element.style.display = 'none'; + + this._element.setAttribute('aria-hidden', true); + + this._isTransitioning = false; + + this._showBackdrop(function () { + $$$1(document.body).removeClass(ClassName.OPEN); + + _this7._resetAdjustments(); + + _this7._resetScrollbar(); + + $$$1(_this7._element).trigger(Event.HIDDEN); + }); + }; + + _proto._removeBackdrop = function _removeBackdrop() { + if (this._backdrop) { + $$$1(this._backdrop).remove(); + this._backdrop = null; + } + }; + + _proto._showBackdrop = function _showBackdrop(callback) { + var _this8 = this; + + var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; + + if (this._isShown && this._config.backdrop) { + this._backdrop = document.createElement('div'); + this._backdrop.className = ClassName.BACKDROP; + + if (animate) { + this._backdrop.classList.add(animate); + } + + $$$1(this._backdrop).appendTo(document.body); + $$$1(this._element).on(Event.CLICK_DISMISS, function (event) { + if (_this8._ignoreBackdropClick) { + _this8._ignoreBackdropClick = false; + return; + } + + if (event.target !== event.currentTarget) { + return; + } + + if (_this8._config.backdrop === 'static') { + _this8._element.focus(); + } else { + _this8.hide(); + } + }); + + if (animate) { + Util.reflow(this._backdrop); + } + + $$$1(this._backdrop).addClass(ClassName.SHOW); + + if (!callback) { + return; + } + + if (!animate) { + callback(); + return; + } + + var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration); + } else if (!this._isShown && this._backdrop) { + $$$1(this._backdrop).removeClass(ClassName.SHOW); + + var callbackRemove = function callbackRemove() { + _this8._removeBackdrop(); + + if (callback) { + callback(); + } + }; + + if ($$$1(this._element).hasClass(ClassName.FADE)) { + var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + + $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration); + } else { + callbackRemove(); + } + } else if (callback) { + callback(); + } + }; // ---------------------------------------------------------------------- + // the following methods are used to handle overflowing modals + // todo (fat): these should probably be refactored out of modal.js + // ---------------------------------------------------------------------- + + + _proto._adjustDialog = function _adjustDialog() { + var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; + + if (!this._isBodyOverflowing && isModalOverflowing) { + this._element.style.paddingLeft = this._scrollbarWidth + "px"; + } + + if (this._isBodyOverflowing && !isModalOverflowing) { + this._element.style.paddingRight = this._scrollbarWidth + "px"; + } + }; + + _proto._resetAdjustments = function _resetAdjustments() { + this._element.style.paddingLeft = ''; + this._element.style.paddingRight = ''; + }; + + _proto._checkScrollbar = function _checkScrollbar() { + var rect = document.body.getBoundingClientRect(); + this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; + this._scrollbarWidth = this._getScrollbarWidth(); + }; + + _proto._setScrollbar = function _setScrollbar() { + var _this9 = this; + + if (this._isBodyOverflowing) { + // Note: DOMNode.style.paddingRight returns the actual value or '' if not set + // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding + + $$$1(fixedContent).each(function (index, element) { + var actualPadding = element.style.paddingRight; + var calculatedPadding = $$$1(element).css('padding-right'); + $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); + }); // Adjust sticky content margin + + $$$1(stickyContent).each(function (index, element) { + var actualMargin = element.style.marginRight; + var calculatedMargin = $$$1(element).css('margin-right'); + $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); + }); // Adjust body padding + + var actualPadding = document.body.style.paddingRight; + var calculatedPadding = $$$1(document.body).css('padding-right'); + $$$1(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); + } + }; + + _proto._resetScrollbar = function _resetScrollbar() { + // Restore fixed content padding + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + $$$1(fixedContent).each(function (index, element) { + var padding = $$$1(element).data('padding-right'); + $$$1(element).removeData('padding-right'); + element.style.paddingRight = padding ? padding : ''; + }); // Restore sticky content + + var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT)); + $$$1(elements).each(function (index, element) { + var margin = $$$1(element).data('margin-right'); + + if (typeof margin !== 'undefined') { + $$$1(element).css('margin-right', margin).removeData('margin-right'); + } + }); // Restore body padding + + var padding = $$$1(document.body).data('padding-right'); + $$$1(document.body).removeData('padding-right'); + document.body.style.paddingRight = padding ? padding : ''; + }; + + _proto._getScrollbarWidth = function _getScrollbarWidth() { + // thx d.walsh + var scrollDiv = document.createElement('div'); + scrollDiv.className = ClassName.SCROLLBAR_MEASURER; + document.body.appendChild(scrollDiv); + var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return scrollbarWidth; + }; // Static + + + Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = _objectSpread({}, Default, $$$1(this).data(), typeof config === 'object' && config ? config : {}); + + if (!data) { + data = new Modal(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](relatedTarget); + } else if (_config.show) { + data.show(relatedTarget); + } + }); + }; + + _createClass(Modal, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Modal; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + var _this10 = this; + + var target; + var selector = Util.getSelectorFromElement(this); + + if (selector) { + target = document.querySelector(selector); + } + + var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $$$1(target).data(), $$$1(this).data()); + + if (this.tagName === 'A' || this.tagName === 'AREA') { + event.preventDefault(); + } + + var $target = $$$1(target).one(Event.SHOW, function (showEvent) { + if (showEvent.isDefaultPrevented()) { + // Only register focus restorer if modal will actually get shown + return; + } + + $target.one(Event.HIDDEN, function () { + if ($$$1(_this10).is(':visible')) { + _this10.focus(); + } + }); + }); + + Modal._jQueryInterface.call($$$1(target), config, this); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Modal._jQueryInterface; + $$$1.fn[NAME].Constructor = Modal; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Modal._jQueryInterface; + }; + + return Modal; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): tooltip.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Tooltip = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'tooltip'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.tooltip'; + var EVENT_KEY = "." + DATA_KEY; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var CLASS_PREFIX = 'bs-tooltip'; + var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); + var DefaultType = { + animation: 'boolean', + template: 'string', + title: '(string|element|function)', + trigger: 'string', + delay: '(number|object)', + html: 'boolean', + selector: '(string|boolean)', + placement: '(string|function)', + offset: '(number|string)', + container: '(string|element|boolean)', + fallbackPlacement: '(string|array)', + boundary: '(string|element)' + }; + var AttachmentMap = { + AUTO: 'auto', + TOP: 'top', + RIGHT: 'right', + BOTTOM: 'bottom', + LEFT: 'left' + }; + var Default = { + animation: true, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + selector: false, + placement: 'top', + offset: 0, + container: false, + fallbackPlacement: 'flip', + boundary: 'scrollParent' + }; + var HoverState = { + SHOW: 'show', + OUT: 'out' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + INSERTED: "inserted" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + FOCUSOUT: "focusout" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY + }; + var ClassName = { + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + TOOLTIP: '.tooltip', + TOOLTIP_INNER: '.tooltip-inner', + ARROW: '.arrow' + }; + var Trigger = { + HOVER: 'hover', + FOCUS: 'focus', + CLICK: 'click', + MANUAL: 'manual' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Tooltip = + /*#__PURE__*/ + function () { + function Tooltip(element, config) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)'); + } // private + + + this._isEnabled = true; + this._timeout = 0; + this._hoverState = ''; + this._activeTrigger = {}; + this._popper = null; // Protected + + this.element = element; + this.config = this._getConfig(config); + this.tip = null; + + this._setListeners(); + } // Getters + + + var _proto = Tooltip.prototype; + + // Public + _proto.enable = function enable() { + this._isEnabled = true; + }; + + _proto.disable = function disable() { + this._isEnabled = false; + }; + + _proto.toggleEnabled = function toggleEnabled() { + this._isEnabled = !this._isEnabled; + }; + + _proto.toggle = function toggle(event) { + if (!this._isEnabled) { + return; + } + + if (event) { + var dataKey = this.constructor.DATA_KEY; + var context = $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + context._activeTrigger.click = !context._activeTrigger.click; + + if (context._isWithActiveTrigger()) { + context._enter(null, context); + } else { + context._leave(null, context); + } + } else { + if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) { + this._leave(null, this); + + return; + } + + this._enter(null, this); + } + }; + + _proto.dispose = function dispose() { + clearTimeout(this._timeout); + $$$1.removeData(this.element, this.constructor.DATA_KEY); + $$$1(this.element).off(this.constructor.EVENT_KEY); + $$$1(this.element).closest('.modal').off('hide.bs.modal'); + + if (this.tip) { + $$$1(this.tip).remove(); + } + + this._isEnabled = null; + this._timeout = null; + this._hoverState = null; + this._activeTrigger = null; + + if (this._popper !== null) { + this._popper.destroy(); + } + + this._popper = null; + this.element = null; + this.config = null; + this.tip = null; + }; + + _proto.show = function show() { + var _this = this; + + if ($$$1(this.element).css('display') === 'none') { + throw new Error('Please use show on visible elements'); + } + + var showEvent = $$$1.Event(this.constructor.Event.SHOW); + + if (this.isWithContent() && this._isEnabled) { + $$$1(this.element).trigger(showEvent); + var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element); + + if (showEvent.isDefaultPrevented() || !isInTheDom) { + return; + } + + var tip = this.getTipElement(); + var tipId = Util.getUID(this.constructor.NAME); + tip.setAttribute('id', tipId); + this.element.setAttribute('aria-describedby', tipId); + this.setContent(); + + if (this.config.animation) { + $$$1(tip).addClass(ClassName.FADE); + } + + var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; + + var attachment = this._getAttachment(placement); + + this.addAttachmentClass(attachment); + var container = this.config.container === false ? document.body : $$$1(document).find(this.config.container); + $$$1(tip).data(this.constructor.DATA_KEY, this); + + if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) { + $$$1(tip).appendTo(container); + } + + $$$1(this.element).trigger(this.constructor.Event.INSERTED); + this._popper = new Popper(this.element, tip, { + placement: attachment, + modifiers: { + offset: { + offset: this.config.offset + }, + flip: { + behavior: this.config.fallbackPlacement + }, + arrow: { + element: Selector.ARROW + }, + preventOverflow: { + boundariesElement: this.config.boundary + } + }, + onCreate: function onCreate(data) { + if (data.originalPlacement !== data.placement) { + _this._handlePopperPlacementChange(data); + } + }, + onUpdate: function onUpdate(data) { + _this._handlePopperPlacementChange(data); + } + }); + $$$1(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().on('mouseover', null, $$$1.noop); + } + + var complete = function complete() { + if (_this.config.animation) { + _this._fixTransition(); + } + + var prevHoverState = _this._hoverState; + _this._hoverState = null; + $$$1(_this.element).trigger(_this.constructor.Event.SHOWN); + + if (prevHoverState === HoverState.OUT) { + _this._leave(null, _this); + } + }; + + if ($$$1(this.tip).hasClass(ClassName.FADE)) { + var transitionDuration = Util.getTransitionDurationFromElement(this.tip); + $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + } else { + complete(); + } + } + }; + + _proto.hide = function hide(callback) { + var _this2 = this; + + var tip = this.getTipElement(); + var hideEvent = $$$1.Event(this.constructor.Event.HIDE); + + var complete = function complete() { + if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { + tip.parentNode.removeChild(tip); + } + + _this2._cleanTipClass(); + + _this2.element.removeAttribute('aria-describedby'); + + $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN); + + if (_this2._popper !== null) { + _this2._popper.destroy(); + } + + if (callback) { + callback(); + } + }; + + $$$1(this.element).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + return; + } + + $$$1(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().off('mouseover', null, $$$1.noop); + } + + this._activeTrigger[Trigger.CLICK] = false; + this._activeTrigger[Trigger.FOCUS] = false; + this._activeTrigger[Trigger.HOVER] = false; + + if ($$$1(this.tip).hasClass(ClassName.FADE)) { + var transitionDuration = Util.getTransitionDurationFromElement(tip); + $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + } else { + complete(); + } + + this._hoverState = ''; + }; + + _proto.update = function update() { + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } + }; // Protected + + + _proto.isWithContent = function isWithContent() { + return Boolean(this.getTitle()); + }; + + _proto.addAttachmentClass = function addAttachmentClass(attachment) { + $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + }; + + _proto.getTipElement = function getTipElement() { + this.tip = this.tip || $$$1(this.config.template)[0]; + return this.tip; + }; + + _proto.setContent = function setContent() { + var tip = this.getTipElement(); + this.setElementContent($$$1(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()); + $$$1(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW); + }; + + _proto.setElementContent = function setElementContent($element, content) { + var html = this.config.html; + + if (typeof content === 'object' && (content.nodeType || content.jquery)) { + // Content is a DOM node or a jQuery + if (html) { + if (!$$$1(content).parent().is($element)) { + $element.empty().append(content); + } + } else { + $element.text($$$1(content).text()); + } + } else { + $element[html ? 'html' : 'text'](content); + } + }; + + _proto.getTitle = function getTitle() { + var title = this.element.getAttribute('data-original-title'); + + if (!title) { + title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; + } + + return title; + }; // Private + + + _proto._getAttachment = function _getAttachment(placement) { + return AttachmentMap[placement.toUpperCase()]; + }; + + _proto._setListeners = function _setListeners() { + var _this3 = this; + + var triggers = this.config.trigger.split(' '); + triggers.forEach(function (trigger) { + if (trigger === 'click') { + $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) { + return _this3.toggle(event); + }); + } else if (trigger !== Trigger.MANUAL) { + var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN; + var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT; + $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) { + return _this3._enter(event); + }).on(eventOut, _this3.config.selector, function (event) { + return _this3._leave(event); + }); + } + + $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () { + return _this3.hide(); + }); + }); + + if (this.config.selector) { + this.config = _objectSpread({}, this.config, { + trigger: 'manual', + selector: '' + }); + } else { + this._fixTitle(); + } + }; + + _proto._fixTitle = function _fixTitle() { + var titleType = typeof this.element.getAttribute('data-original-title'); + + if (this.element.getAttribute('title') || titleType !== 'string') { + this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); + this.element.setAttribute('title', ''); + } + }; + + _proto._enter = function _enter(event, context) { + var dataKey = this.constructor.DATA_KEY; + context = context || $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + if (event) { + context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; + } + + if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { + context._hoverState = HoverState.SHOW; + return; + } + + clearTimeout(context._timeout); + context._hoverState = HoverState.SHOW; + + if (!context.config.delay || !context.config.delay.show) { + context.show(); + return; + } + + context._timeout = setTimeout(function () { + if (context._hoverState === HoverState.SHOW) { + context.show(); + } + }, context.config.delay.show); + }; + + _proto._leave = function _leave(event, context) { + var dataKey = this.constructor.DATA_KEY; + context = context || $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + if (event) { + context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; + } + + if (context._isWithActiveTrigger()) { + return; + } + + clearTimeout(context._timeout); + context._hoverState = HoverState.OUT; + + if (!context.config.delay || !context.config.delay.hide) { + context.hide(); + return; + } + + context._timeout = setTimeout(function () { + if (context._hoverState === HoverState.OUT) { + context.hide(); + } + }, context.config.delay.hide); + }; + + _proto._isWithActiveTrigger = function _isWithActiveTrigger() { + for (var trigger in this._activeTrigger) { + if (this._activeTrigger[trigger]) { + return true; + } + } + + return false; + }; + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, this.constructor.Default, $$$1(this.element).data(), typeof config === 'object' && config ? config : {}); + + if (typeof config.delay === 'number') { + config.delay = { + show: config.delay, + hide: config.delay + }; + } + + if (typeof config.title === 'number') { + config.title = config.title.toString(); + } + + if (typeof config.content === 'number') { + config.content = config.content.toString(); + } + + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + return config; + }; + + _proto._getDelegateConfig = function _getDelegateConfig() { + var config = {}; + + if (this.config) { + for (var key in this.config) { + if (this.constructor.Default[key] !== this.config[key]) { + config[key] = this.config[key]; + } + } + } + + return config; + }; + + _proto._cleanTipClass = function _cleanTipClass() { + var $tip = $$$1(this.getTipElement()); + var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + + if (tabClass !== null && tabClass.length) { + $tip.removeClass(tabClass.join('')); + } + }; + + _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) { + var popperInstance = popperData.instance; + this.tip = popperInstance.popper; + + this._cleanTipClass(); + + this.addAttachmentClass(this._getAttachment(popperData.placement)); + }; + + _proto._fixTransition = function _fixTransition() { + var tip = this.getTipElement(); + var initConfigAnimation = this.config.animation; + + if (tip.getAttribute('x-placement') !== null) { + return; + } + + $$$1(tip).removeClass(ClassName.FADE); + this.config.animation = false; + this.hide(); + this.show(); + this.config.animation = initConfigAnimation; + }; // Static + + + Tooltip._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' && config; + + if (!data && /dispose|hide/.test(config)) { + return; + } + + if (!data) { + data = new Tooltip(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Tooltip, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "NAME", + get: function get() { + return NAME; + } + }, { + key: "DATA_KEY", + get: function get() { + return DATA_KEY; + } + }, { + key: "Event", + get: function get() { + return Event; + } + }, { + key: "EVENT_KEY", + get: function get() { + return EVENT_KEY; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Tooltip; + }(); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + + $$$1.fn[NAME] = Tooltip._jQueryInterface; + $$$1.fn[NAME].Constructor = Tooltip; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Tooltip._jQueryInterface; + }; + + return Tooltip; + }($, Popper); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): popover.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Popover = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'popover'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.popover'; + var EVENT_KEY = "." + DATA_KEY; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var CLASS_PREFIX = 'bs-popover'; + var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); + + var Default = _objectSpread({}, Tooltip.Default, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }); + + var DefaultType = _objectSpread({}, Tooltip.DefaultType, { + content: '(string|element|function)' + }); + + var ClassName = { + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + TITLE: '.popover-header', + CONTENT: '.popover-body' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + INSERTED: "inserted" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + FOCUSOUT: "focusout" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Popover = + /*#__PURE__*/ + function (_Tooltip) { + _inheritsLoose(Popover, _Tooltip); + + function Popover() { + return _Tooltip.apply(this, arguments) || this; + } + + var _proto = Popover.prototype; + + // Overrides + _proto.isWithContent = function isWithContent() { + return this.getTitle() || this._getContent(); + }; + + _proto.addAttachmentClass = function addAttachmentClass(attachment) { + $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + }; + + _proto.getTipElement = function getTipElement() { + this.tip = this.tip || $$$1(this.config.template)[0]; + return this.tip; + }; + + _proto.setContent = function setContent() { + var $tip = $$$1(this.getTipElement()); // We use append for html objects to maintain js events + + this.setElementContent($tip.find(Selector.TITLE), this.getTitle()); + + var content = this._getContent(); + + if (typeof content === 'function') { + content = content.call(this.element); + } + + this.setElementContent($tip.find(Selector.CONTENT), content); + $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); + }; // Private + + + _proto._getContent = function _getContent() { + return this.element.getAttribute('data-content') || this.config.content; + }; + + _proto._cleanTipClass = function _cleanTipClass() { + var $tip = $$$1(this.getTipElement()); + var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')); + } + }; // Static + + + Popover._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' ? config : null; + + if (!data && /destroy|hide/.test(config)) { + return; + } + + if (!data) { + data = new Popover(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Popover, null, [{ + key: "VERSION", + // Getters + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "NAME", + get: function get() { + return NAME; + } + }, { + key: "DATA_KEY", + get: function get() { + return DATA_KEY; + } + }, { + key: "Event", + get: function get() { + return Event; + } + }, { + key: "EVENT_KEY", + get: function get() { + return EVENT_KEY; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Popover; + }(Tooltip); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + + $$$1.fn[NAME] = Popover._jQueryInterface; + $$$1.fn[NAME].Constructor = Popover; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Popover._jQueryInterface; + }; + + return Popover; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): scrollspy.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var ScrollSpy = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'scrollspy'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.scrollspy'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Default = { + offset: 10, + method: 'auto', + target: '' + }; + var DefaultType = { + offset: 'number', + method: 'string', + target: '(string|element)' + }; + var Event = { + ACTIVATE: "activate" + EVENT_KEY, + SCROLL: "scroll" + EVENT_KEY, + LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + DROPDOWN_ITEM: 'dropdown-item', + DROPDOWN_MENU: 'dropdown-menu', + ACTIVE: 'active' + }; + var Selector = { + DATA_SPY: '[data-spy="scroll"]', + ACTIVE: '.active', + NAV_LIST_GROUP: '.nav, .list-group', + NAV_LINKS: '.nav-link', + NAV_ITEMS: '.nav-item', + LIST_ITEMS: '.list-group-item', + DROPDOWN: '.dropdown', + DROPDOWN_ITEMS: '.dropdown-item', + DROPDOWN_TOGGLE: '.dropdown-toggle' + }; + var OffsetMethod = { + OFFSET: 'offset', + POSITION: 'position' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var ScrollSpy = + /*#__PURE__*/ + function () { + function ScrollSpy(element, config) { + var _this = this; + + this._element = element; + this._scrollElement = element.tagName === 'BODY' ? window : element; + this._config = this._getConfig(config); + this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS); + this._offsets = []; + this._targets = []; + this._activeTarget = null; + this._scrollHeight = 0; + $$$1(this._scrollElement).on(Event.SCROLL, function (event) { + return _this._process(event); + }); + this.refresh(); + + this._process(); + } // Getters + + + var _proto = ScrollSpy.prototype; + + // Public + _proto.refresh = function refresh() { + var _this2 = this; + + var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION; + var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; + var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; + this._offsets = []; + this._targets = []; + this._scrollHeight = this._getScrollHeight(); + var targets = [].slice.call(document.querySelectorAll(this._selector)); + targets.map(function (element) { + var target; + var targetSelector = Util.getSelectorFromElement(element); + + if (targetSelector) { + target = document.querySelector(targetSelector); + } + + if (target) { + var targetBCR = target.getBoundingClientRect(); + + if (targetBCR.width || targetBCR.height) { + // TODO (fat): remove sketch reliance on jQuery position/offset + return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector]; + } + } + + return null; + }).filter(function (item) { + return item; + }).sort(function (a, b) { + return a[0] - b[0]; + }).forEach(function (item) { + _this2._offsets.push(item[0]); + + _this2._targets.push(item[1]); + }); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(this._scrollElement).off(EVENT_KEY); + this._element = null; + this._scrollElement = null; + this._config = null; + this._selector = null; + this._offsets = null; + this._targets = null; + this._activeTarget = null; + this._scrollHeight = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {}); + + if (typeof config.target !== 'string') { + var id = $$$1(config.target).attr('id'); + + if (!id) { + id = Util.getUID(NAME); + $$$1(config.target).attr('id', id); + } + + config.target = "#" + id; + } + + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._getScrollTop = function _getScrollTop() { + return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; + }; + + _proto._getScrollHeight = function _getScrollHeight() { + return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); + }; + + _proto._getOffsetHeight = function _getOffsetHeight() { + return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; + }; + + _proto._process = function _process() { + var scrollTop = this._getScrollTop() + this._config.offset; + + var scrollHeight = this._getScrollHeight(); + + var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); + + if (this._scrollHeight !== scrollHeight) { + this.refresh(); + } + + if (scrollTop >= maxScroll) { + var target = this._targets[this._targets.length - 1]; + + if (this._activeTarget !== target) { + this._activate(target); + } + + return; + } + + if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { + this._activeTarget = null; + + this._clear(); + + return; + } + + var offsetLength = this._offsets.length; + + for (var i = offsetLength; i--;) { + var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); + + if (isActiveTarget) { + this._activate(this._targets[i]); + } + } + }; + + _proto._activate = function _activate(target) { + this._activeTarget = target; + + this._clear(); + + var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style + + + queries = queries.map(function (selector) { + return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]"); + }); + var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(',')))); + + if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { + $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); + $link.addClass(ClassName.ACTIVE); + } else { + // Set triggered link as active + $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active + // With both
    and