EveSa commited on
Commit
ad78747
·
0 Parent(s):

Initial Commit

Browse files
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.pt filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ .venv/**
2
+ data/**
3
+ src/__pycache__
4
+ model/**
5
+ html5up-helios/**
6
+ **/__pycache__/**
.pre-commit-config.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v2.3.0
4
+ hooks:
5
+ - id: check-yaml
6
+ - id: end-of-file-fixer
7
+ - id: trailing-whitespace
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile, Image, Container
2
+
3
+ FROM python:3.8.10
4
+
5
+ ADD src/ requirements.txt .
6
+
7
+ RUN pip install -r requirements.txt
8
+
9
+ CMD ["python3", "./src/api.py"]
10
+
11
+ EXPOSE 3000
Documentation.md ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Les objectifs du projet
2
+
3
+ L'objectif du projet est de mettre en place une <strong>plateforme de requête</strong> d'un modèle de langue permettant la <strong>génération de résumé d'article de presse.</strong>
4
+
5
+ # Une description du système ou des données auxquelles l’interface permet d’accéder
6
+
7
+
8
+ Le projet utilisera pour l'entraînement du modèle de langue le corpus issu de 'Newsroom: A Dataset of 1.3 Million Summaries with Diverse Extractive Strategies' (Grusky et al., NAACL 2018) newsroom assemblé par Max Grusky et ses collègues en 2018. Newsroom est un corpus parallèle rassemblant 1,3 millions articles de presse et leur résumé en anglais. Les résumés sont réalisés en utilisant les méthodes d'extraction comme d'abstraction ainsi que des méthodes mixtes. Ce corpus est disponible sur HuggingFace mais necessite un téléchargement préalable pour des raisons de protection des données.
9
+
10
+
11
+ # La méthodologie
12
+
13
+ ## Répartition du travail
14
+ Nous avons décidé de travailler avec le logiciel de gestion de version Github en mettant en place un système de verification des commit avec un pull request.
15
+ Cette méthode permet à chaque participant du projet d'observer les modifications effectuées par les autres membres avant d'accepter de fondre en une seule les branches main et les modifications proposées.
16
+
17
+ ## Problèmes rencontrés et résolution
18
+ - Problème Mojibake depuis les fichiers jsonl : encodage en cp1252 et decodage en utf-8 avec ignore pour éviter les erreurs sur les caractères utf-8 présents dans le fichier à l'encodage
19
+ - Répétition des mots à cause de la ponctuation : suppresion de la ponctuation avec `strip`
20
+ - Agglomération des pronoms et des verbes : remplacement des `'` par des espaces avant le `split`
21
+ - Split des noms propres composés ('Ivory Coast', 'Inter Milan') :
22
+ - Problème des mots non disponibles dans le vocabulaire
23
+ - Problème de la qualité du corpus :
24
+ - Résumés tronqués : "Did', 'Tatum', "O'Neal's", 'latest', 'battle', 'with', 'ex-husband', 'John', 'McEnroe', 'put', 'her', 'back', 'on', 'drugs?', 'The', '"Paper', 'Moon"star', 'checked', 'herself', 'into', "L.A.'s", 'Promises', 'rehab', 'facility', 'after', 'a', 'friend', 'caught', 'her', 'smoking', 'crack,', 'according', 'to', 'The', 'National', 'Enquirer.', "O'Neal", 'emerged', 'clean', 'and', 'sober', 'from', "Promises'", '34-day', 'recovery', 'program', 'in', 'late', 'July,', 'the', 'tab', 'reports.', 'The', 'actress', 'is', 'said', 'to', 'have', 'plunged', 'into', 'her', 'old', 'habits', 'because', 'of'"
25
+ - Résumés plus proche de titres que de résumés
26
+ - Prise en compte du padding dans l'apprentissage --> utilisation de la fonctionnalité ignore_index de NLLLoss avec un padding d'une valeur à -100
27
+
28
+
29
+ ## Les étapes du projet
30
+
31
+ # Implémentation
32
+ ## modélisation
33
+
34
+ Nous avons décidé dans un premier temps de modéliser une LSTM pour le résuméautomatique sur labase du réseau de neurone réalisé en cours.
35
+ Pour ce faire nous nous sommes beaucoup inspirée du kaggle https://www.kaggle.com/code/columbine/seq2seq-pytorch ainsi que de la documentation de PyTorch https://pytorch.org/tutorials/beginner/nlp/sequence_models_tutorial.html#example-an-lstm-for-part-of-speech-tagging
36
+ ## modules et API utilisés
37
+ ## Langages de programmation
38
+
39
+ # Les résultats (fichiers output, visualisations…)
40
+
41
+ ## Les metriques d'évaluation
42
+ - ROUGE
43
+ - BLEU
44
+ - QAEval
45
+ - Meteor
46
+ - BERTScore
47
+
48
+
49
+ # Discussion des résultats
50
+ ce que vous auriez aimé faire et ce que vous avez pu faire par exemple
requirements.txt ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ anyio==3.6.2
2
+ click==8.1.3
3
+ fastapi==0.92.0
4
+ h11==0.14.0
5
+ idna==3.4
6
+ Jinja2==3.1.2
7
+ joblib==1.2.0
8
+ MarkupSafe==2.1.2
9
+ nltk==3.8.1
10
+ numpy==1.24.2
11
+ nvidia-cublas-cu11==11.10.3.66
12
+ nvidia-cuda-nvrtc-cu11==11.7.99
13
+ nvidia-cuda-runtime-cu11==11.7.99
14
+ nvidia-cudnn-cu11==8.5.0.96
15
+ pandas==1.5.3
16
+ pydantic==1.10.5
17
+ python-dateutil==2.8.2
18
+ python-multipart==0.0.6
19
+ pytz==2022.7.1
20
+ regex==2022.10.31
21
+ six==1.16.0
22
+ sniffio==1.3.0
23
+ starlette==0.25.0
24
+ torch==1.13.1
25
+ tqdm==4.65.0
26
+ typing_extensions==4.5.0
27
+ uvicorn==0.20.0
src/api.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uvicorn
2
+ from fastapi import FastAPI, Form, Request
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.templating import Jinja2Templates
5
+
6
+ from inference import inferenceAPI
7
+
8
+ # from transformers import RobertaTokenizerFast, EncoderDecoderModel
9
+
10
+ # ------- MODELE HUGGING FACE QUI MARCHE BIEN ------------------------------------
11
+ # device = 'cuda' if torch.cuda.is_available() else 'cpu'
12
+ # ckpt = 'mrm8488/camembert2camembert_shared-finetuned-french-summarization'
13
+ # tokenizer = RobertaTokenizerFast.from_pretrained(ckpt)
14
+ # model = EncoderDecoderModel.from_pretrained(ckpt).to(device)
15
+
16
+ # def generate_summary(text):
17
+ # inputs = tokenizer([text], padding="max_length", truncation=True, max_length=512, return_tensors="pt")
18
+ # input_ids = inputs.input_ids.to(device)
19
+ # attention_mask = inputs.attention_mask.to(device)
20
+ # output = model.generate(input_ids, attention_mask=attention_mask)
21
+ # return tokenizer.decode(output[0], skip_special_tokens=True)
22
+ # ----------------------------------------------------------------------------------
23
+
24
+
25
+ # ------ NOTRE MODELE --------------------------------------------------------------
26
+ # appel de la fonction inférence, adaptée pour une entrée txt
27
+ def summarize(text: str):
28
+ return " ".join(inferenceAPI(text))
29
+
30
+
31
+ # ----------------------------------------------------------------------------------
32
+
33
+ # -------- API ---------------------------------------------------------------------
34
+ app = FastAPI()
35
+
36
+ # static pour tout ce qui est css
37
+ templates = Jinja2Templates(directory="templates")
38
+ app.mount("/static", StaticFiles(directory="static"), name="static")
39
+ app.mount("/templates", StaticFiles(directory="templates"), name="templates")
40
+
41
+
42
+ @app.get("/")
43
+ async def index(request: Request):
44
+ return templates.TemplateResponse("index.html.jinja", {"request": request})
45
+
46
+
47
+ # pour donner les predictions
48
+ @app.post("/")
49
+ async def prediction(request: Request, text: str = Form(...)):
50
+ summary = summarize(text)
51
+ return templates.TemplateResponse(
52
+ "index.html.jinja", {"request": request, "text": text, "summary": summary}
53
+ )
54
+
55
+
56
+ # ------------------------------------------------------------------------------------
57
+
58
+
59
+ # pour lancer le serveur et le reload à chaque changement sauvegardé dans le repo
60
+ if __name__ == "__main__":
61
+ uvicorn.run("api:app", port=8000, reload=True)
src/dataloader.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Get data and adapt it for training
3
+ -----------
4
+ - nettoyage de l'encodage
5
+ - Ajout de token <START> et <END>
6
+ TO DO :
7
+ - Nettoyage des contractions
8
+ - enlever les \xad
9
+ - enlever ponctuation et () []
10
+ - s'occuper des noms propres (mots commençant par une majuscule qui se suivent)
11
+ Création d'un Vectoriserà partir du vocabulaire :
12
+
13
+ """
14
+ import string
15
+ from collections import Counter
16
+
17
+ import pandas as pd
18
+ import torch
19
+ from nltk import word_tokenize
20
+
21
+ # nltk.download('punkt')
22
+
23
+
24
+ class Data:
25
+ """
26
+ A class used to get data from file
27
+ ...
28
+
29
+ Attributes
30
+ ----------
31
+ path : str
32
+ the path to the file containing the data
33
+
34
+ Methods
35
+ -------
36
+ open()
37
+ open the jsonl file with pandas
38
+ clean_data(text_type)
39
+ clean the data got by opening the file and adds <start> and
40
+ <end> tokens depending on the text_type
41
+ get_words()
42
+ get the dataset vocabulary
43
+ make_dataset()
44
+ create a dataset with cleaned data
45
+ """
46
+
47
+ def __init__(self, path: str) -> None:
48
+ self.path = path
49
+
50
+ def open(self) -> pd.DataFrame:
51
+ """
52
+ Open the file containing the data
53
+ """
54
+ return pd.read_json(path_or_buf=self.path, lines=True)
55
+
56
+ def clean_data(self, text_type: str) -> list:
57
+ """
58
+ Clean data from encoding error, punctuation, etc...
59
+ To Do :
60
+ #nettoyer les données
61
+
62
+ Parameters
63
+ ----------
64
+ text_type : str
65
+ allow to differenciate between 'text' and 'summary'
66
+ to add <start> and <end> tokens to summaries
67
+
68
+ Returns
69
+ ----------
70
+ list of list
71
+ list of tokenised texts
72
+
73
+ """
74
+ dataset = self.open()
75
+
76
+ texts = dataset[text_type]
77
+ texts = texts.str.encode("cp1252", "ignore")
78
+ texts = texts.str.decode("utf-8", "ignore")
79
+
80
+ tokenized_texts = []
81
+ # - Nettoyage des contractions
82
+ # - enlever les \xad
83
+ # text.translate(str.maketrans('', '', string.punctuation))
84
+ # - enlever ponctuation et () []
85
+ # - s'occuper des noms propres (mots commençant par une majuscule qui se suivent)
86
+ for text in texts:
87
+ text = text.translate(str.maketrans("", "", string.punctuation))
88
+ text = word_tokenize(text)
89
+ tokenized_texts.append(text)
90
+
91
+ if text_type == "summary":
92
+ return [["<start>", *summary, "<end>"] for summary in tokenized_texts]
93
+ return tokenized_texts
94
+
95
+ def pad_sequence(self):
96
+ """
97
+ pad summary with empty token
98
+ """
99
+ texts = self.clean_data("text")
100
+ summaries = self.clean_data("summary")
101
+ padded_summary = []
102
+ for text, summary in zip(texts, summaries):
103
+ if len(summary) != len(text):
104
+ summary += ["<empty>"] * (len(text) - len(summary))
105
+ padded_summary.append(summary)
106
+ return texts, padded_summary
107
+
108
+ def get_words(self) -> list:
109
+ """
110
+ Create a dictionnary of the data vocabulary
111
+ """
112
+ texts, summaries = self.clean_data("text"), self.clean_data("summary")
113
+ text_words = [word for text in texts for word in text]
114
+ summary_words = [word for text in summaries for word in text]
115
+ return text_words + summary_words
116
+
117
+ def make_dataset(self) -> pd.DataFrame:
118
+ """
119
+ Create a Pandas Dataframe with cleaned data
120
+ --------------------
121
+ param: self: Data
122
+ return: pd.DataFrame
123
+ """
124
+ texts, summaries = self.clean_data("text"), self.clean_data("summary")
125
+ return pd.DataFrame(list(zip(texts, summaries)), columns=["text", "summary"])
126
+
127
+
128
+ class Vectoriser:
129
+ """
130
+ A class used to vectorise data
131
+ ...
132
+
133
+ Attributes
134
+ ----------
135
+ vocab : list
136
+ list of the vocab
137
+
138
+ Methods
139
+ -------
140
+ encode(tokens)
141
+ transforms a list of tokens to their corresponding idx
142
+ in form of troch tensor
143
+ decode(word_idx_tensor)
144
+ converts a tensor to a list of tokens
145
+ vectorize(row)
146
+ encode an entire row from the dataset
147
+ """
148
+
149
+ def __init__(self, vocab) -> None:
150
+ self.vocab = vocab
151
+ self.word_count = Counter(word.lower().strip(",.\\-") for word in self.vocab)
152
+ self.idx_to_token = sorted([t for t, c in self.word_count.items() if c > 1])
153
+ self.token_to_idx = {t: i for i, t in enumerate(self.idx_to_token)}
154
+
155
+ def encode(self, tokens) -> torch.tensor:
156
+ """
157
+ Encode une phrase selon les mots qu'elle contient
158
+ selon les mots contenus dans le dictionnaire.
159
+ À NOTER :
160
+ Si un mot n'est pas contenu dans le dictionnaire,
161
+ associe un index fixe au mot qui sera ignoré au décodage.
162
+ ---------
163
+ :params: tokens : list
164
+ les mots de la phrase sous forme de liste
165
+ :return: words_idx : tensor
166
+ Un tensor contenant les index des mots de la phrase
167
+ """
168
+ if type(tokens) == list:
169
+ words_idx = torch.tensor(
170
+ [
171
+ self.token_to_idx.get(t.lower(), len(self.token_to_idx))
172
+ for t in tokens
173
+ ],
174
+ dtype=torch.long,
175
+ )
176
+
177
+ # Permet d'encoder mots par mots
178
+ elif type(tokens) == str:
179
+ words_idx = torch.tensor(self.token_to_idx.get(tokens.lower()))
180
+
181
+ return words_idx
182
+
183
+ def decode(self, words_idx_tensor) -> list:
184
+ """
185
+ Decode une phrase selon le procédé inverse que la fonction encode
186
+ """
187
+ words_idx_tensor = words_idx_tensor.argmax(dim=-1)
188
+ idxs = words_idx_tensor.tolist()
189
+ if type(idxs) == int:
190
+ words = [self.idx_to_token[idxs]]
191
+ else:
192
+ words = []
193
+ for idx in idxs:
194
+ if idx != len(self.idx_to_token):
195
+ words.append(self.idx_to_token[idx])
196
+ return words
197
+
198
+ def beam_search(self, words_idx_tensor) -> list:
199
+ pass
200
+
201
+ def vectorize(self, row) -> torch.tensor:
202
+ """
203
+ Encode les données d'une ligne du dataframe
204
+ ----------
205
+ :params: row : dataframe
206
+ une ligne du dataframe (un coupe texte-résumé)
207
+ :returns: text_idx : tensor
208
+ le tensor correspondant aux mots du textes
209
+ :returns: summary_idx: tensor
210
+ le tensr correspondant aux mots du résumé
211
+ """
212
+ text_idx = self.encode(row["text"])
213
+ summary_idx = self.encode(row["summary"])
214
+ return (text_idx, summary_idx)
src/inference.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Allows to predict the summary for a given entry text
3
+ """
4
+ import torch
5
+ from nltk import word_tokenize
6
+
7
+ import dataloader
8
+ from model import Decoder, Encoder, EncoderDecoderModel
9
+
10
+ # On doit loader les données pour avoir le Vectoriser > sauvegarder "words" dans un fichiers et le loader par la suite ??
11
+ ### À CHANGER POUR N'AVOIR À LOADER QUE LE VECTORISER
12
+ data1 = dataloader.Data("data/train_extract.jsonl")
13
+ data2 = dataloader.Data("data/dev_extract.jsonl")
14
+ train_dataset = data1.make_dataset()
15
+ dev_dataset = data2.make_dataset()
16
+ words = data1.get_words()
17
+
18
+ vectoriser = dataloader.Vectoriser(words)
19
+ word_counts = vectoriser.word_count
20
+
21
+
22
+ def inferenceAPI(text: str) -> str:
23
+ """
24
+ Predict the summary for an input text
25
+ --------
26
+ Parameter
27
+ text: str
28
+ the text to sumarize
29
+ Return
30
+ str
31
+ The summary for the input text
32
+ """
33
+ text = word_tokenize(text)
34
+ # On défini les paramètres d'entrée pour le modèle
35
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
36
+ encoder = Encoder(len(vectoriser.idx_to_token) + 1, 256, 512, 0.5, device).to(
37
+ device
38
+ )
39
+ decoder = Decoder(len(vectoriser.idx_to_token) + 1, 256, 512, 0.5, device).to(
40
+ device
41
+ )
42
+
43
+ # On instancie le modèle
44
+ model = EncoderDecoderModel(encoder, decoder, device)
45
+
46
+ model.load_state_dict(torch.load("model/model.pt", map_location=device))
47
+ model.eval()
48
+ model.to(device)
49
+
50
+ # On vectorise le texte
51
+ source = vectoriser.encode(text)
52
+ source = source.to(device)
53
+
54
+ # On fait passer le texte dans le modèle
55
+ with torch.no_grad():
56
+ output = model(source).to(device)
57
+ output.to(device)
58
+ return vectoriser.decode(output)
59
+
60
+
61
+ # if __name__ == "__main__":
62
+ # # inference()
63
+ # print(inferenceAPI("If you choose to use these attributes in logged messages, you need to exercise some care. In the above example, for instance, the Formatter has been set up with a format string which expects ‘clientip’ and ‘user’ in the attribute dictionary of the LogRecord. If these are missing, the message will not be logged because a string formatting exception will occur. So in this case, you always need to pass the extra dictionary with these keys."))
src/model.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Defines the Encoder, Decoder and Sequence to Sequence models
3
+ used in this projet
4
+ """
5
+ import logging
6
+
7
+ import torch
8
+
9
+ import dataloader
10
+
11
+ logging.basicConfig(level=logging.DEBUG)
12
+
13
+ data1 = dataloader.Data("data_extract/train_extract.jsonl")
14
+ words = data1.get_words()
15
+ vectoriser = dataloader.Vectoriser(words)
16
+
17
+
18
+ class Encoder(torch.nn.Module):
19
+ def __init__(
20
+ self,
21
+ vocab_size: int,
22
+ embeddings_dim: int,
23
+ hidden_size: int,
24
+ dropout: int,
25
+ device,
26
+ ):
27
+ # Une idiosyncrasie de torch, pour qu'iel puisse faire sa magie
28
+ super().__init__()
29
+ self.device = device
30
+ # On ajoute un mot supplémentaire au vocabulaire :
31
+ # on s'en servira pour les mots inconnus
32
+ self.embeddings = torch.nn.Embedding(vocab_size, embeddings_dim)
33
+ self.embeddings.to(device)
34
+ self.hidden = torch.nn.LSTM(embeddings_dim, hidden_size, dropout=dropout)
35
+ # Comme on va calculer la log-vraisemblance,
36
+ # c'est le log-softmax qui nous intéresse
37
+ self.dropout = torch.nn.Dropout(dropout)
38
+ self.dropout.to(self.device)
39
+ # Dropout
40
+
41
+ def forward(self, inpt):
42
+ inpt.to(self.device)
43
+ emb = self.dropout(self.embeddings(inpt)).to(self.device)
44
+ emb = emb.to(self.device)
45
+
46
+ output, (hidden, cell) = self.hidden(emb)
47
+ output.to(self.device)
48
+ hidden = hidden.to(self.device)
49
+ cell = cell.to(self.device)
50
+
51
+ return hidden, cell
52
+
53
+
54
+ class Decoder(torch.nn.Module):
55
+ def __init__(
56
+ self,
57
+ vocab_size: int,
58
+ embeddings_dim: int,
59
+ hidden_size: int,
60
+ dropout: int,
61
+ device,
62
+ ):
63
+ # Une idiosyncrasie de torch, pour qu'iel puisse faire sa magie
64
+ super().__init__()
65
+ self.device = device
66
+ # On ajoute un mot supplémentaire au vocabulaire :
67
+ # on s'en servira pour les mots inconnus
68
+ self.vocab_size = vocab_size
69
+ self.embeddings = torch.nn.Embedding(vocab_size, embeddings_dim)
70
+ self.hidden = torch.nn.LSTM(embeddings_dim, hidden_size, dropout=dropout)
71
+ self.output = torch.nn.Linear(hidden_size, vocab_size)
72
+ # Comme on va calculer la log-vraisemblance,
73
+ # c'est le log-softmax qui nous intéresse
74
+ self.dropout = torch.nn.Dropout(dropout)
75
+
76
+ def forward(self, input, hidden, cell):
77
+ input = input.unsqueeze(0)
78
+ input = input.to(self.device)
79
+ emb = self.dropout(self.embeddings(input)).to(self.device)
80
+ emb = emb.to(self.device)
81
+
82
+ output, (hidden, cell) = self.hidden(emb, (hidden, cell))
83
+ output = output.to(self.device)
84
+ out = self.output(output.squeeze(0)).to(self.device)
85
+ return out, hidden, cell
86
+
87
+
88
+ class EncoderDecoderModel(torch.nn.Module):
89
+ def __init__(self, encoder, decoder, device):
90
+ # Une idiosyncrasie de torch, pour qu'iel puisse faire sa magie
91
+ super().__init__()
92
+ self.encoder = encoder
93
+ self.decoder = decoder
94
+ self.device = device
95
+
96
+ def forward(self, source, num_beams=3):
97
+ # CHANGER LA TARGET LEN POUR QQCH DE MODULABLE
98
+ target_len = int(1 * source.shape[0]) # Taille du texte que l'on recherche
99
+ target_vocab_size = self.decoder.vocab_size # Taille du mot
100
+
101
+ # tensor to store decoder outputs
102
+ outputs = torch.zeros(target_len, target_vocab_size).to(
103
+ self.device
104
+ ) # Instenciation d'une matrice de zeros de taille (taille du texte, taille du mot)
105
+ outputs.to(
106
+ self.device
107
+ ) # Une idiosyncrasie de torch pour mettre le tensor sur le GPU
108
+
109
+ # last hidden state of the encoder is used as the initial hidden state of the decoder
110
+ source.to(
111
+ self.device
112
+ ) # Une idiosyncrasie de torch pour mettre le tensor sur le GPU
113
+ hidden, cell = self.encoder(source) # Encode le texte sous forme de vecteur
114
+ hidden.to(
115
+ self.device
116
+ ) # Une idiosyncrasie de torch pour mettre le tensor sur le GPU
117
+ cell.to(
118
+ self.device
119
+ ) # Une idiosyncrasie de torch pour mettre le tensor sur le GPU
120
+
121
+ # first input to the decoder is the <start> token.
122
+ input = vectoriser.encode("<start>") # Mot de départ du MOdèle
123
+ input.to(self.device) # idiosyncrasie de torch pour mmettre sur GPU
124
+
125
+ ### DÉBUT DE L'INSTANCIATION TEST ###
126
+ # If you wonder, b stands for better
127
+ values = None
128
+ b_outputs = torch.zeros(target_len, target_vocab_size).to(self.device)
129
+ b_outputs.to(self.device)
130
+
131
+ for i in range(
132
+ 1, target_len
133
+ ): # On va déterminer autant de mot que la taille du texte souhaité
134
+ # insert input token embedding, previous hidden and previous cell states
135
+ # receive output tensor (predictions) and new hidden and cell states.
136
+
137
+ # replace predictions in a tensor holding predictions for each token
138
+ # logging.debug(f"output : {output}")
139
+
140
+ ####### DÉBUT DU BEAM SEARCH ##########
141
+ if values is None:
142
+ # On calcule une première fois les premières probabilité de mot après <start>
143
+ output, hidden, cell = self.decoder(input, hidden, cell)
144
+ output.to(self.device)
145
+ b_hidden = hidden
146
+ b_cell = cell
147
+
148
+ # On choisi les k meilleurs scores pour choisir la meilleure probabilité
149
+ # sur deux itérations ensuite
150
+ values, indices = output.topk(num_beams, sorted=True)
151
+
152
+ else:
153
+ # On instancie le dictionnaire qui contiendra les scores pour chaque possibilité
154
+ scores = {}
155
+
156
+ # Pour chacune des meilleures valeurs, on va calculer l'output
157
+ for value, indice in zip(values, indices):
158
+ indice.to(self.device)
159
+
160
+ # On calcule l'output
161
+ b_output, b_hidden, b_cell = self.decoder(indice, b_hidden, b_cell)
162
+
163
+ # On empêche le modèle de se répéter d'un mot sur l'autre en mettant
164
+ # de force la probabilité du mot précédent à 0
165
+ b_output[indice] = torch.zeros(1)
166
+
167
+ # On choisit le meilleur résultat pour cette possibilité
168
+ highest_value = torch.log(b_output).max()
169
+
170
+ # On calcule le score des 2 itérations ensembles
171
+ score = highest_value * torch.log(value)
172
+ scores[score] = (b_output, b_hidden, b_cell)
173
+
174
+ # On garde le meilleur score sur LES 2 ITÉRATIONS
175
+ b_output, b_hidden, b_cell = scores.get(max(scores))
176
+
177
+ # Et du coup on rempli la place de i-1 à la place de i
178
+ b_outputs[i - 1] = b_output.to(self.device)
179
+
180
+ # On instancies nos nouvelles valeurs pour la prochaine itération
181
+ values, indices = b_output.topk(num_beams, sorted=True)
182
+
183
+ ##################################
184
+
185
+ # outputs[i] = output.to(self.device)
186
+ # input = output.argmax(dim=-1).to(self.device)
187
+ # input.to(self.device)
188
+
189
+ # logging.debug(f"{vectoriser.decode(outputs.argmax(dim=-1))}")
190
+ return b_outputs.to(self.device)
src/script.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ DONE :
3
+ - Separer la partie vectoriser du Classifeur
4
+ - Ajouter un LSTM au Classifieur
5
+ - entrainer le Classifieur
6
+ TO DO :
7
+ - Améliorer les résultats du modèle
8
+ """
9
+ import logging
10
+ import random
11
+ from typing import Sequence
12
+
13
+ import torch
14
+
15
+ import dataloader
16
+ from model import Decoder, Encoder, EncoderDecoderModel
17
+ from train import train_network
18
+
19
+ # logging INFO, WARNING, ERROR, CRITICAL, DEBUG
20
+ logging.basicConfig(level=logging.INFO)
21
+ logging.disable(level=10)
22
+
23
+ import os
24
+
25
+ os.environ[
26
+ "CUBLAS_WORKSPACE_CONFIG"
27
+ ] = ":16:8" # pour que ça marche en deterministe sur mon pc boulot
28
+ # variable environnement dans git bash export CUBLAS_WORKSPACE_CONFIG=:16:8
29
+ # from datasets import load_dataset
30
+
31
+ ### OPEN DATASET###
32
+ # dataset = load_dataset("newsroom", data_dir=DATA_PATH, data_files="data/train.jsonl")
33
+
34
+ data1 = dataloader.Data("data/train_extract.jsonl")
35
+ data2 = dataloader.Data("data/dev_extract.jsonl")
36
+ train_dataset = data1.make_dataset()
37
+ dev_dataset = data2.make_dataset()
38
+ words = data1.get_words()
39
+
40
+ vectoriser = dataloader.Vectoriser(words)
41
+ word_counts = vectoriser.word_count
42
+
43
+
44
+ def predict(model, tokens: Sequence[str]) -> Sequence[str]:
45
+ """Predict the POS for a tokenized sequence"""
46
+ words_idx = vectoriser.encode(tokens).to(device)
47
+ # Pas de calcul de gradient ici : c'est juste pour les prédictions
48
+ with torch.no_grad():
49
+ # equivalent to model(input) when called out of class
50
+ out = model(words_idx).to(device)
51
+ out_predictions = out.to(device)
52
+ return vectoriser.decode(out_predictions)
53
+
54
+
55
+ if __name__ == "__main__":
56
+ ### NEURAL NETWORK ###
57
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
58
+ print("Device check. You are using:", device)
59
+
60
+ ### RÉSEAU ENTRAÎNÉ ###
61
+ # Pour s'assurer que les résultats seront les mêmes à chaque run du notebook
62
+ torch.use_deterministic_algorithms(True)
63
+ torch.manual_seed(0)
64
+ random.seed(0)
65
+
66
+ # On peut également entraîner encoder séparemment
67
+ encoder = Encoder(len(vectoriser.idx_to_token) + 1, 256, 512, 0.5, device)
68
+ decoder = Decoder(len(vectoriser.idx_to_token) + 1, 256, 512, 0.5, device)
69
+ # S'ils sont entraînés, on peut les sauvegarder
70
+ torch.save(encoder.state_dict(), "model/encoder.pt")
71
+ torch.save(encoder.state_dict(), "model/encoder.pt")
72
+
73
+ trained_classifier = EncoderDecoderModel(encoder, decoder, device).to(device)
74
+
75
+ print(next(trained_classifier.parameters()).device)
76
+ # print(train_dataset.is_cuda)
77
+
78
+ train_network(
79
+ trained_classifier,
80
+ [vectoriser.vectorize(row) for index, row in train_dataset.iterrows()],
81
+ [vectoriser.vectorize(row) for index, row in dev_dataset.iterrows()],
82
+ 5,
83
+ )
84
+
85
+ torch.save(trained_classifier.state_dict(), "model/model.pt")
86
+
87
+ print(f'test text : {dev_dataset.iloc[6]["summary"]}')
88
+ print(
89
+ f'test prediction : {predict(trained_classifier, dev_dataset.iloc[6]["text"])}'
90
+ )
src/train.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Training the network
3
+ """
4
+ import datetime
5
+ import logging
6
+ import time
7
+ from typing import Sequence, Tuple
8
+
9
+ import torch
10
+
11
+ import dataloader
12
+
13
+ # logging INFO, WARNING, ERROR, CRITICAL, DEBUG
14
+ logging.basicConfig(level=logging.INFO)
15
+ logging.disable(level=10)
16
+
17
+ data1 = dataloader.Data("data/train_extract.jsonl")
18
+ words = data1.get_words()
19
+ vectoriser = dataloader.Vectoriser(words)
20
+
21
+
22
+ def train_network(
23
+ model: torch.nn.Module,
24
+ train_set: Sequence[Tuple[torch.tensor, torch.Tensor]],
25
+ dev_set: Sequence[Tuple[torch.tensor, torch.Tensor]],
26
+ epochs: int,
27
+ clip: int = 1,
28
+ ):
29
+ """
30
+ Train the EncoderDecoderModel network for a given number of epoch
31
+ -----------
32
+ Parameters
33
+ model: torch.nn.Module
34
+ EncoderDecoderModel defined in model.py
35
+ train_set: Sequence[Tuple[torch.tensor, torch.tensor]]
36
+ tuple of vectorized (text, summary) from the training set
37
+ dev_set: Sequence[Tuple[torch.tensor, torch.tensor]]
38
+ tuple of vectorized (text, summary) for the dev set
39
+ epochs: int
40
+ the number of epochs to train on
41
+ clip: int
42
+ no idea
43
+ Return
44
+ None
45
+ """
46
+
47
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
48
+ model = model.to(device)
49
+ print("Device check. You are using:", model.device)
50
+ model.train()
51
+
52
+ # with torch.no_grad():
53
+
54
+ optim = torch.optim.Adam(model.parameters(), lr=0.01)
55
+
56
+ print("Epoch\ttrain loss\tdev accuracy\tcompute time")
57
+
58
+ for epoch_n in range(epochs):
59
+ # Tell the model it's in train mode for layers designed to
60
+ # behave differently in train or evaluation
61
+ # https://stackoverflow.com/questions/51433378/what-does-model-train-do-in-pytorch
62
+ model.train()
63
+
64
+ # To get the computing time per epoch
65
+ epoch_start_time = time.time()
66
+
67
+ # To get the model accuracy per epoch
68
+ epoch_loss = 0.0
69
+ epoch_length = 0
70
+
71
+ # Iterates over all the text, summary tuples
72
+ for source, target in train_set:
73
+ source = source.to(device)
74
+ target = target.to(device)
75
+
76
+ # DEBUG Block
77
+ # logging.debug("TRAIN")
78
+ # logging.debug(f"cuda available ? {torch.cuda.is_available()}")
79
+ # logging.debug(f"Source sur cuda ? {source.is_cuda}")
80
+ # logging.debug(f"Target sur cuda ? {target.is_cuda}")
81
+
82
+ out = model(source).to(device)
83
+ logging.debug(f"outputs = {out.shape}")
84
+ target = torch.nn.functional.pad(
85
+ target, (0, len(out) - len(target)), value=-100
86
+ )
87
+ # logging.debug(f"predition : {vectoriser.decode(output_predictions)}")
88
+ loss = torch.nn.functional.nll_loss(out, target).to(device)
89
+ loss.backward()
90
+ torch.nn.utils.clip_grad_norm_(model.parameters(), clip)
91
+ optim.step()
92
+
93
+ epoch_loss += loss.item()
94
+ epoch_length += source.shape[0]
95
+
96
+ # To check the model accuracy on new data
97
+ dev_correct = 0
98
+ dev_total = 0
99
+
100
+ # Iterates over text, summary tuple from dev
101
+ for source, target in dev_set:
102
+ # We here want to evaluate the model
103
+ # so we're switching to evaluation mode
104
+ model.eval()
105
+
106
+ source = source.to(device)
107
+ target = target.to(device)
108
+
109
+ # We compute the result
110
+ output = model(source).to(device)
111
+
112
+ output_dim = output.shape[-1]
113
+
114
+ output = output[1:].view(-1, output_dim)
115
+ logging.debug(f"dev output : {output.shape}")
116
+ target = target[1:].view(-1)
117
+ # To compare the output with the target,
118
+ # they have to be of same length so we're
119
+ # padding the target with -100 idx that will
120
+ # be ignored by the nll_loss function
121
+ target = torch.nn.functional.pad(
122
+ target, (0, len(output) - len(target)), value=-100
123
+ )
124
+ dev_loss = torch.nn.functional.nll_loss(output, target)
125
+ dev_correct += dev_loss.item()
126
+ dev_total += source.shape[0]
127
+
128
+ # Compute of the epoch training time
129
+ epoch_compute_time = time.time() - epoch_start_time
130
+
131
+ print(
132
+ f"{epoch_n}\t{epoch_loss/epoch_length:.5}\t{abs(dev_correct/dev_total):.2%}\t\t{datetime.timedelta(seconds=epoch_compute_time)}"
133
+ )
static/plurital.jpg ADDED
static/styles.css ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ label,
2
+ textarea{
3
+ font-size: 0.8rem;
4
+ letter-spacing: 1px;
5
+ }
6
+
7
+ p {
8
+ font-size: 1rem;
9
+ letter-spacing: 1px;
10
+ }
11
+
12
+ textarea {
13
+ padding: 10px;
14
+ width: 100%;
15
+ height: 90%;
16
+ line-height: 1.5;
17
+ border-radius: 5px;
18
+ border: 1px solid #ccc;
19
+ box-shadow: 1px 1px 1px #999;
20
+ resize : none;
21
+ box-sizing:border-box;
22
+ }
23
+
24
+ label {
25
+ display: block;
26
+ margin-bottom: 10px;
27
+ }
28
+
29
+ h1 {
30
+ color: rgb(61, 99, 143);
31
+ text-align: center;
32
+ }
33
+
34
+ img {
35
+ display: block;
36
+ margin-left: auto;
37
+ margin-right: auto;
38
+ width: 15%;
39
+ }
40
+
41
+ select {
42
+ font-size: 0.9rem;
43
+ padding: 2px 5px;
44
+ }
45
+
46
+ div {
47
+ display: block;
48
+ margin-top: 30px;
49
+ }
50
+
51
+
52
+ .parent {
53
+ display: grid;
54
+ grid-template-columns: 1fr 1fr;
55
+ grid-gap: 20px;
56
+ width: 100%;
57
+ height: 300px;
58
+ }
59
+
60
+ .child {
61
+ margin: 10px;
62
+ }
templates/index.html.jinja ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <title>Text summarization API</title>
5
+ <meta charset="utf-8" />
6
+ {# <link href="{{ url_for('static', path='/styles.css') }}" rel="stylesheet"> #}
7
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
8
+ <link rel="stylesheet" href="{{ url_for('templates', path='site_helios/assets/css/main.css') }}" />
9
+ <script>
10
+ function customReset()
11
+ {
12
+ document.getElementById("my_form").value = "";
13
+ document.getElementById("text").value = "";
14
+ document.getElementById("summary").value = "";
15
+ }
16
+ </script>
17
+ </head>
18
+ <body>
19
+ <!-- Header -->
20
+ <div id="header">
21
+
22
+ <!-- Inner -->
23
+ <div class="inner">
24
+ <header>
25
+ <h1>Text summarization API</h1>
26
+ <hr />
27
+ </header>
28
+ </div>
29
+
30
+ <!-- Nav -->
31
+ <nav id="nav">
32
+ <hr/>
33
+ </nav>
34
+
35
+ <div class="choixModel">
36
+ <label for="model-select">Choose a model :</label>
37
+ <select name="model" id="model-select">
38
+ <option value="lstm">LSTM</option>
39
+ <option value="autre">Autre</option>
40
+ </select>
41
+ </div>
42
+
43
+ <div>
44
+ <table>
45
+ <tr>
46
+ <td>
47
+ <form id = "my_form" action="/" method="post" class="formulaire">
48
+ <textarea id="text" name="text" placeholder="Enter your text here!" rows="15" cols="75">{{text}}</textarea>
49
+ <input type="hidden" name="textarea_value" value="{{ text }}">
50
+ </form>
51
+ </td>
52
+ <td>
53
+ <textarea id="summary" name="summary" rows="15" cols="75">{{summary}}</textarea>
54
+ </td>
55
+ </tr>
56
+ </table>
57
+ </div>
58
+ <div class="buttons">
59
+ <button form ="my_form" class='search_bn' type="submit" class="btn btn-primary btn-block btn-large" rows="1" cols="50">Go !</button>
60
+ <button form ="my_form" type="button" value="Reset" onclick="customReset();">Reset</button>
61
+ </div>
62
+
63
+ <div class="copyright">
64
+ <ul class="menu">
65
+ <!-- <img src="{{ url_for('static', path='/plurital.jpg') }}" alt="Plurital"> -->
66
+ <li>&copy; Untitled. All rights reserved.</li>
67
+ </ul>
68
+ <ul>
69
+ <li>Projet mené dans le cadre des cours du master 2 TAL (Traitement Automatique des Langues)</li>
70
+ <li>Lingyun GAO -- Estelle SALMON -- Eve SAUVAGE</li>
71
+ </ul>
72
+ </div>
73
+
74
+
75
+
76
+ </div>
77
+ </body>
78
+ </html>
templates/site_helios/assets/css/fontawesome-all.min.css ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ */
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+ .fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900}
templates/site_helios/assets/css/main.css ADDED
@@ -0,0 +1,1068 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300italic,400,400italic,600");
2
+ @import url("fontawesome-all.min.css");
3
+
4
+ html, body, div, span, applet, object,
5
+ iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
6
+ pre, a, abbr, acronym, address, big, cite,
7
+ code, del, dfn, em, img, ins, kbd, q, s, samp,
8
+ small, strike, strong, sub, sup, tt, var, b,
9
+ u, i, center, dl, dt, dd, ol, ul, li, fieldset,
10
+ label, legend, caption, tbody,
11
+ tfoot, thead, tr, th, td, article, aside,
12
+ canvas, details, embed, figure, figcaption,
13
+ footer, header, hgroup, menu, nav, output, ruby,
14
+ section, summary, time, mark, audio, video {
15
+ margin: 0;
16
+ padding: 0;
17
+ border: 0;
18
+ font-size: 100%;
19
+ font: inherit;
20
+ vertical-align: baseline;}
21
+
22
+ article, aside, details, figcaption, figure,
23
+ footer, header, hgroup, menu, nav, section {
24
+ display: block;}
25
+
26
+
27
+
28
+ div {
29
+ margin-bottom: 20px;
30
+ }
31
+
32
+ body {
33
+ line-height: 1;
34
+ }
35
+
36
+ ol, ul {
37
+ list-style: none;
38
+ }
39
+
40
+ blockquote, q {
41
+ quotes: none;
42
+ }
43
+
44
+ blockquote:before, blockquote:after, q:before, q:after {
45
+ content: '';
46
+ content: none;
47
+ }
48
+
49
+
50
+ body {
51
+ -webkit-text-size-adjust: none;
52
+ }
53
+
54
+ mark {
55
+ background-color: transparent;
56
+ color: inherit;
57
+ }
58
+
59
+ input::-moz-focus-inner {
60
+ border: 0;
61
+ padding: 0;
62
+ }
63
+
64
+
65
+ /* Basic */
66
+
67
+ html {
68
+ box-sizing: border-box;
69
+ }
70
+
71
+ *, *:before, *:after {
72
+ box-sizing: inherit;
73
+ }
74
+
75
+ body {
76
+ color: #5b5b5b;
77
+ font-size: 15pt;
78
+ line-height: 1.85em;
79
+ font-family: 'Source Sans Pro', sans-serif;
80
+ font-weight: 300;
81
+ background-image: url("../../images/header.jpg");
82
+ background-size: cover;
83
+ background-position: center center;
84
+ background-attachment: fixed;
85
+ }
86
+
87
+
88
+
89
+
90
+ h1, h2, h3, h4, h5, h6 {
91
+ font-weight: 400;
92
+ color: #483949;
93
+ line-height: 1.25em;
94
+ }
95
+
96
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
97
+ color: inherit;
98
+ text-decoration: none;
99
+ border-bottom-color: transparent;
100
+ }
101
+
102
+ h1 strong, h2 strong, h3 strong, h4 strong, h5 strong, h6 strong {
103
+ font-weight: 600;
104
+ }
105
+
106
+ h2 {
107
+ font-size: 2.85em;
108
+ }
109
+
110
+ h3 {
111
+ font-size: 1.25em;
112
+ }
113
+
114
+ h4 {
115
+ font-size: 1em;
116
+ margin: 0 0 0.25em 0;
117
+ }
118
+
119
+ strong, b {
120
+ font-weight: 400;
121
+ color: #483949;
122
+ }
123
+
124
+ em, i {
125
+ font-style: italic;
126
+ }
127
+
128
+ a {
129
+ color: inherit;
130
+ border-bottom: solid 1px rgba(128, 128, 128, 0.15);
131
+ text-decoration: none;
132
+ -moz-transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
133
+ -webkit-transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
134
+ -ms-transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
135
+ transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
136
+ }
137
+
138
+ a:hover {
139
+ color: #ef8376;
140
+ border-bottom-color: transparent;
141
+ }
142
+
143
+ sub {
144
+ position: relative;
145
+ top: 0.5em;
146
+ font-size: 0.8em;
147
+ }
148
+
149
+ sup {
150
+ position: relative;
151
+ top: -0.5em;
152
+ font-size: 0.8em;
153
+ }
154
+
155
+ blockquote {
156
+ border-left: solid 0.5em #ddd;
157
+ padding: 1em 0 1em 2em;
158
+ font-style: italic;
159
+ }
160
+
161
+ p, ul, ol, dl {
162
+ margin-bottom: 1em;
163
+ }
164
+
165
+ p {
166
+ text-align: justify;
167
+ }
168
+
169
+ br.clear {
170
+ clear: both;
171
+ }
172
+
173
+ hr {
174
+ position: relative;
175
+ display: block;
176
+ border: 0;
177
+ top: 4.5em;
178
+ margin-bottom: 9em;
179
+ height: 6px;
180
+ border-top: solid 1px rgba(128, 128, 128, 0.2);
181
+ border-bottom: solid 1px rgba(128, 128, 128, 0.2);
182
+ }
183
+
184
+ hr:before, hr:after {
185
+ content: '';
186
+ position: absolute;
187
+ top: -8px;
188
+ display: block;
189
+ width: 1px;
190
+ height: 21px;
191
+ background: rgba(128, 128, 128, 0.2);
192
+ }
193
+
194
+ hr:before {
195
+ left: -1px;
196
+ }
197
+
198
+ hr:after {
199
+ right: -1px;
200
+ }
201
+
202
+ .timestamp {
203
+ color: rgba(128, 128, 128, 0.75);
204
+ font-size: 0.8em;
205
+ }
206
+
207
+
208
+
209
+
210
+ /* List */
211
+
212
+ ul {
213
+ list-style: disc;
214
+ padding-left: 1em;
215
+ }
216
+
217
+ ul li {
218
+ padding-left: 0.5em;
219
+ font-size: 85%;
220
+ list-style: none;
221
+ }
222
+
223
+ ol {
224
+ list-style: decimal;
225
+ padding-left: 1.25em;
226
+ }
227
+
228
+ ol li {
229
+ padding-left: 0.25em;
230
+ }
231
+
232
+
233
+ /* Form */
234
+ textarea {
235
+ border-radius: 10px;
236
+ resize: none;
237
+ padding: 10px;
238
+ line-height: 20px;
239
+ word-spacing: 1px;
240
+ font-size: 16px;
241
+ width: 85%;
242
+ height: 100%;
243
+ }
244
+
245
+ /* WebKit, Edge */
246
+ ::-webkit-input-placeholder {
247
+ font-size: 17px;
248
+ word-spacing: 1px;
249
+ }
250
+
251
+ /* Table */
252
+
253
+ table {
254
+ width: 100%;
255
+ }
256
+
257
+ table.default {
258
+ width: 100%;
259
+ }
260
+
261
+
262
+ table.default tbody tr:first-child {
263
+ border-top: 0;
264
+ }
265
+
266
+ table.default tbody tr:nth-child(2n+1) {
267
+ background: #fafafa;
268
+ }
269
+
270
+
271
+ table.default th {
272
+ text-align: left;
273
+ font-weight: 400;
274
+ padding: 0.5em 1em 0.5em 1em;
275
+ }
276
+
277
+ table.default thead {
278
+ border-bottom: solid 2px #e5e5e5;
279
+ }
280
+
281
+ table.default tfoot {
282
+ border-top: solid 2px #e5e5e5;
283
+ }
284
+
285
+ /* Button */
286
+
287
+ input[type="button"],
288
+ input[type="submit"],
289
+ input[type="reset"],
290
+ button,
291
+ .button {
292
+ position: relative;
293
+ display: inline-block;
294
+ background: #df7366;
295
+ color: #fff;
296
+ text-align: center;
297
+ border-radius: 0.5em;
298
+ text-decoration: none;
299
+ padding: 0.65em 3em 0.65em 3em;
300
+ border: 0;
301
+ cursor: pointer;
302
+ outline: 0;
303
+ font-weight: 300;
304
+ -moz-transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
305
+ -webkit-transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
306
+ -ms-transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
307
+ transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out, border-bottom-color 0.35s ease-in-out;
308
+ }
309
+
310
+ input[type="button"]:hover,
311
+ input[type="submit"]:hover,
312
+ input[type="reset"]:hover,
313
+ button:hover,
314
+ .button:hover {
315
+ color: #fff;
316
+ background: #ef8376;
317
+ }
318
+
319
+ input[type="button"].alt,
320
+ input[type="submit"].alt,
321
+ input[type="reset"].alt,
322
+ button.alt,
323
+ .button.alt {
324
+ background: #2B252C;
325
+ }
326
+
327
+ input[type="button"].alt:hover,
328
+ input[type="submit"].alt:hover,
329
+ input[type="reset"].alt:hover,
330
+ button.alt:hover,
331
+ .button.alt:hover {
332
+ background: #3B353C;
333
+ }
334
+
335
+ /* Post */
336
+
337
+ .post.stub {
338
+ text-align: center;
339
+ }
340
+
341
+ .post.stub header {
342
+ margin: 0;
343
+ }
344
+
345
+ /* Icons */
346
+
347
+ .icon {
348
+ text-decoration: none;
349
+ text-decoration: none;
350
+ }
351
+
352
+ .icon:before {
353
+ -moz-osx-font-smoothing: grayscale;
354
+ -webkit-font-smoothing: antialiased;
355
+ display: inline-block;
356
+ font-style: normal;
357
+ font-variant: normal;
358
+ text-rendering: auto;
359
+ line-height: 1;
360
+ text-transform: none !important;
361
+ font-family: 'Font Awesome 5 Free';
362
+ font-weight: 400;
363
+ }
364
+
365
+ .icon:before {
366
+ line-height: inherit;
367
+ font-size: 1.25em;
368
+ }
369
+
370
+ .icon > .label {
371
+ display: none;
372
+ }
373
+
374
+ .icon.solid:before {
375
+ font-weight: 900;
376
+ }
377
+
378
+ .icon.brands:before {
379
+ font-family: 'Font Awesome 5 Brands';
380
+ }
381
+
382
+ .icon.circled {
383
+ position: relative;
384
+ display: inline-block;
385
+ background: #2b252c;
386
+ color: #fff;
387
+ border-radius: 100%;
388
+ width: 3em;
389
+ height: 3em;
390
+ line-height: 3em;
391
+ text-align: center;
392
+ font-size: 1.25em;
393
+ }
394
+
395
+ header .icon.circled {
396
+ margin: 0 0 2em 0;
397
+ }
398
+
399
+ /* Wrapper */
400
+
401
+ .wrapper {
402
+ background: #fff;
403
+ margin: 0 0 2em 0;
404
+ padding: 6em 0 6em 0;
405
+ }
406
+
407
+ .wrapper.style2 {
408
+ padding-top: 0;
409
+ }
410
+
411
+ /* Header */
412
+
413
+ #header {
414
+ position: relative;
415
+ background-size: cover;
416
+ background-position: center center;
417
+ background-attachment: fixed;
418
+ color: #fff;
419
+ text-align: center;
420
+ padding: 5em 0 2em 0;
421
+ cursor: default;
422
+ height: 100%;
423
+ }
424
+
425
+
426
+
427
+
428
+
429
+ #header:before {
430
+ content: '';
431
+ display: inline-block;
432
+ vertical-align: middle;
433
+ height: 100%;
434
+ }
435
+
436
+ #header .inner {
437
+ position: relative;
438
+ z-index: 1;
439
+ margin: 0;
440
+ display: inline-block;
441
+ vertical-align: middle;
442
+ }
443
+
444
+ #header header {
445
+ display: inline-block;
446
+ }
447
+
448
+ #header header > p {
449
+ font-size: 1.25em;
450
+ margin: 0;
451
+ }
452
+
453
+ #header h1 {
454
+ color: #fff;
455
+ font-size: 3em;
456
+ line-height: 1em;
457
+ }
458
+
459
+ #header h1 a {
460
+ color: inherit;
461
+ }
462
+
463
+ #header .button {
464
+ display: inline-block;
465
+ border-radius: 100%;
466
+ width: 4.5em;
467
+ height: 4.5em;
468
+ line-height: 4.5em;
469
+ text-align: center;
470
+ font-size: 1.25em;
471
+ padding: 0;
472
+ }
473
+
474
+ #header hr {
475
+ top: 1.5em;
476
+ margin-bottom: 3em;
477
+ border-bottom-color: rgba(192, 192, 192, 0.35);
478
+ box-shadow: inset 0 1px 0 0 rgba(192, 192, 192, 0.35);
479
+ }
480
+
481
+ #header hr:before, #header hr:after {
482
+ background: rgba(192, 192, 192, 0.35);
483
+ }
484
+
485
+ #header footer {
486
+ margin: 1em 0 0 0;
487
+ }
488
+
489
+ body.homepage #header {
490
+ height: 100vh;
491
+ min-height: 40em;
492
+ }
493
+
494
+ body.homepage #header h1 {
495
+ font-size: 4em;
496
+ }
497
+
498
+ body.homepage #header:after {
499
+ content: '';
500
+ background: #1C0920;
501
+ display: block;
502
+ position: absolute;
503
+ left: 0;
504
+ top: 0;
505
+ width: 100%;
506
+ height: 100%;
507
+ opacity: 0;
508
+ -moz-transition: opacity 2.5s ease-in-out;
509
+ -webkit-transition: opacity 2.5s ease-in-out;
510
+ -ms-transition: opacity 2.5s ease-in-out;
511
+ transition: opacity 2.5s ease-in-out;
512
+ -moz-transition-delay: 0.5s;
513
+ -webkit-transition-delay: 0.5s;
514
+ -ms-transition-delay: 0.5s;
515
+ transition-delay: 0.5s;
516
+ }
517
+
518
+ body.homepage.is-preload #header:after {
519
+ opacity: 1;
520
+ }
521
+
522
+ /* Nav */
523
+
524
+ #nav {
525
+ position: absolute;
526
+ top: 0;
527
+ left: 0;
528
+ width: 100%;
529
+ text-align: center;
530
+ padding: 1.5em 0 1.5em 0;
531
+ z-index: 1;
532
+ overflow: hidden;
533
+ }
534
+
535
+ #nav > ul {
536
+ line-height: 0px;
537
+ position: relative;
538
+ display: inline-block;
539
+ margin: 0;
540
+ height: 21px;
541
+ border-left: solid 1px rgba(192, 192, 192, 0.35);
542
+ border-right: solid 1px rgba(192, 192, 192, 0.35);
543
+ }
544
+
545
+ #nav > ul:before, #nav > ul:after {
546
+ content: '';
547
+ display: block;
548
+ width: 300%;
549
+ position: absolute;
550
+ top: 50%;
551
+ margin-top: -2px;
552
+ height: 5px;
553
+ border-top: solid 1px rgba(192, 192, 192, 0.35);
554
+ border-bottom: solid 1px rgba(192, 192, 192, 0.35);
555
+ }
556
+
557
+ #nav > ul:before {
558
+ left: 100%;
559
+ margin-left: 1px;
560
+ }
561
+
562
+ #nav > ul:after {
563
+ right: 100%;
564
+ margin-right: 1px;
565
+ }
566
+
567
+ #nav > ul > li {
568
+ display: inline-block;
569
+ margin: -9px 0.5em 0 0.5em;
570
+ border-radius: 0.5em;
571
+ padding: 0.85em;
572
+ border: solid 1px transparent;
573
+ -moz-transition: color 0.35s ease-in-out, border-color 0.35s ease-in-out;
574
+ -webkit-transition: color 0.35s ease-in-out, border-color 0.35s ease-in-out;
575
+ -ms-transition: color 0.35s ease-in-out, border-color 0.35s ease-in-out;
576
+ transition: color 0.35s ease-in-out, border-color 0.35s ease-in-out;
577
+ }
578
+
579
+ #nav > ul > li.active {
580
+ border-color: rgba(192, 192, 192, 0.35);
581
+ }
582
+
583
+ #nav > ul > li > a, #nav > ul > li > span {
584
+ display: block;
585
+ color: inherit;
586
+ text-decoration: none;
587
+ border: 0;
588
+ outline: 0;
589
+ }
590
+
591
+ #nav > ul > li > ul {
592
+ display: none;
593
+ }
594
+
595
+ #nav > hr {
596
+ top: 0.5em;
597
+ margin-bottom: 6em;
598
+ }
599
+
600
+ .dropotron {
601
+ background: rgba(255, 255, 255, 0.975);
602
+ padding: 1em 1.25em 1em 1.25em;
603
+ line-height: 1em;
604
+ height: auto;
605
+ text-align: left;
606
+ border-radius: 0.5em;
607
+ box-shadow: 0 0.15em 0.25em 0 rgba(0, 0, 0, 0.25);
608
+ min-width: 12em;
609
+ margin-top: -1em;
610
+ list-style: none;
611
+ }
612
+
613
+ .dropotron li {
614
+ border-top: solid 1px rgba(128, 128, 128, 0.2);
615
+ color: #5b5b5b;
616
+ padding-left: 0;
617
+ }
618
+
619
+ .dropotron li:first-child {
620
+ border-top: 0;
621
+ }
622
+
623
+ .dropotron li:hover {
624
+ color: #ef8376;
625
+ }
626
+
627
+ .dropotron li a, .dropotron li span {
628
+ display: block;
629
+ border: 0;
630
+ padding: 0.5em 0 0.5em 0;
631
+ -moz-transition: color 0.35s ease-in-out;
632
+ -webkit-transition: color 0.35s ease-in-out;
633
+ -ms-transition: color 0.35s ease-in-out;
634
+ transition: color 0.35s ease-in-out;
635
+ }
636
+
637
+ .dropotron.level-0 {
638
+ margin-top: 2em;
639
+ font-size: 0.9em;
640
+ }
641
+
642
+ .dropotron.level-0:before {
643
+ content: '';
644
+ position: absolute;
645
+ left: 50%;
646
+ top: -0.7em;
647
+ margin-left: -0.75em;
648
+ border-bottom: solid 0.75em rgba(255, 255, 255, 0.975);
649
+ border-left: solid 0.75em rgba(64, 64, 64, 0);
650
+ border-right: solid 0.75em rgba(64, 64, 64, 0);
651
+ }
652
+
653
+ /* Banner */
654
+
655
+ #banner {
656
+ background: #fff;
657
+ text-align: center;
658
+ padding: 4.5em 0 4.5em 0;
659
+ margin-bottom: 0;
660
+ }
661
+
662
+ #banner header > p {
663
+ margin-bottom: 0;
664
+ }
665
+
666
+ /* Content */
667
+
668
+ #content > hr {
669
+ top: 3em;
670
+ margin-bottom: 6em;
671
+ }
672
+
673
+ #content > section {
674
+ margin-bottom: 0;
675
+ }
676
+
677
+ /* Sidebar */
678
+
679
+ #sidebar > hr {
680
+ top: 3em;
681
+ margin-bottom: 6em;
682
+ }
683
+
684
+ #sidebar > hr.first {
685
+ display: none;
686
+ }
687
+
688
+ #sidebar > section {
689
+ margin-bottom: 0;
690
+ }
691
+
692
+ /* Main */
693
+
694
+ #main {
695
+ margin-bottom: 0;
696
+ }
697
+
698
+ #main section:first-of-type {
699
+ padding-top: 2em;
700
+ }
701
+
702
+ /* Footer */
703
+
704
+ #footer {
705
+ position: relative;
706
+ overflow: hidden;
707
+ padding: 6em 0 6em 0;
708
+ background: #2b252c;
709
+ color: #fff;
710
+ }
711
+
712
+ #footer .icon.circled {
713
+ background: #fff;
714
+ color: #2b252c;
715
+ }
716
+
717
+ #footer header {
718
+ text-align: center;
719
+ cursor: default;
720
+ }
721
+
722
+ #footer h2, #footer h3, #footer h4, #footer h5, #footer h6 {
723
+ color: #fff;
724
+ }
725
+
726
+ #footer .contact {
727
+ text-align: center;
728
+ }
729
+
730
+ #footer .contact p {
731
+ text-align: center;
732
+ margin: 0 0 3em 0;
733
+ }
734
+
735
+ #footer .copyright {
736
+ text-align: center;
737
+ color: rgba(128, 128, 128, 0.75);
738
+ font-size: 0.8em;
739
+ }
740
+
741
+ .copyright{
742
+ margin-top: 50px;
743
+ }
744
+
745
+ #footer .copyright a {
746
+ color: rgba(128, 128, 128, 0.75);
747
+ }
748
+
749
+ #footer .copyright a:hover {
750
+ color: rgba(212, 212, 212, 0.85);
751
+ }
752
+
753
+ /* Carousel */
754
+
755
+ .carousel {
756
+ position: relative;
757
+ overflow: hidden;
758
+ padding: 2em 0 2em 0;
759
+ margin-bottom: 0;
760
+ }
761
+
762
+ .carousel .forward, .carousel .backward {
763
+ position: absolute;
764
+ top: 50%;
765
+ width: 6em;
766
+ height: 12em;
767
+ margin-top: -6em;
768
+ cursor: pointer;
769
+ }
770
+
771
+ .carousel .forward:before, .carousel .backward:before {
772
+ content: '';
773
+ display: block;
774
+ width: 6em;
775
+ height: 6em;
776
+ border-radius: 100%;
777
+ background-color: rgba(72, 57, 73, 0.5);
778
+ position: absolute;
779
+ top: 50%;
780
+ margin-top: -3em;
781
+ -moz-transition: background-color 0.35s ease-in-out;
782
+ -webkit-transition: background-color 0.35s ease-in-out;
783
+ -o-transition: background-color 0.35s ease-in-out;
784
+ -ms-transition: background-color 0.35s ease-in-out;
785
+ transition: background-color 0.35s ease-in-out;
786
+ -webkit-backface-visibility: hidden;
787
+ }
788
+
789
+ .carousel .forward:after, .carousel .backward:after {
790
+ content: '';
791
+ width: 3em;
792
+ height: 3em;
793
+ position: absolute;
794
+ top: 50%;
795
+ margin: -1.5em 0 0 0;
796
+ background: url("images/arrow.svg") no-repeat center center;
797
+ }
798
+
799
+ .carousel .forward:hover:before, .carousel .backward:hover:before {
800
+ background-color: rgba(239, 131, 118, 0.75);
801
+ }
802
+
803
+ .carousel .forward {
804
+ right: 0;
805
+ }
806
+
807
+ .carousel .forward:before {
808
+ right: -3em;
809
+ }
810
+
811
+ .carousel .forward:after {
812
+ right: -0.25em;
813
+ }
814
+
815
+ .carousel .backward {
816
+ left: 0;
817
+ }
818
+
819
+ .carousel .backward:before {
820
+ left: -3em;
821
+ }
822
+
823
+ .carousel .backward:after {
824
+ left: -0.25em;
825
+ -moz-transform: scaleX(-1);
826
+ -webkit-transform: scaleX(-1);
827
+ -ms-transform: scaleX(-1);
828
+ transform: scaleX(-1);
829
+ }
830
+
831
+ .carousel .reel {
832
+ white-space: nowrap;
833
+ position: relative;
834
+ -webkit-overflow-scrolling: touch;
835
+ padding: 0 2em 0 2em;
836
+ }
837
+
838
+ .carousel article {
839
+ display: inline-block;
840
+ width: 18em;
841
+ background: #fff;
842
+ text-align: center;
843
+ padding: 0 1em 3em 1em;
844
+ margin: 0 2em 0 0;
845
+ white-space: normal;
846
+ opacity: 1.0;
847
+ -moz-transition: opacity 0.75s ease-in-out;
848
+ -webkit-transition: opacity 0.75s ease-in-out;
849
+ -ms-transition: opacity 0.75s ease-in-out;
850
+ transition: opacity 0.75s ease-in-out;
851
+ }
852
+
853
+ .carousel article.loading {
854
+ opacity: 0;
855
+ }
856
+
857
+ .carousel article .image {
858
+ position: relative;
859
+ left: -1em;
860
+ top: 0;
861
+ width: auto;
862
+ margin-right: -2em;
863
+ margin-bottom: 3em;
864
+ }
865
+
866
+ .carousel article p {
867
+ text-align: center;
868
+ }
869
+
870
+ /* Wide */
871
+
872
+ @media screen and (max-width: 1680px) {
873
+
874
+ /* Basic */
875
+
876
+ body, input, select {
877
+ font-size: 14pt;
878
+ line-height: 1.75em;
879
+ }
880
+
881
+ /* Carousel */
882
+
883
+ .carousel {
884
+ padding: 1.5em 0 1.5em 0;
885
+ }
886
+
887
+ .carousel .reel {
888
+ padding: 0 1.5em 0 1.5em;
889
+ }
890
+
891
+ .carousel article {
892
+ width: 18em;
893
+ margin: 0 1.25em 0 0;
894
+ }
895
+
896
+ }
897
+
898
+ /* Normal */
899
+
900
+ @media screen and (max-width: 1280px) {
901
+
902
+ /* Basic */
903
+
904
+ body, input, select {
905
+ font-size: 12pt;
906
+ line-height: 1.5em;
907
+ }
908
+
909
+ /* Wrapper */
910
+
911
+ .wrapper {
912
+ padding-left: 2em;
913
+ padding-right: 2em;
914
+ }
915
+
916
+ /* Header */
917
+
918
+ #header {
919
+ background-attachment: scroll;
920
+ }
921
+
922
+ #header .inner {
923
+ padding-left: 2em;
924
+ padding-right: 2em;
925
+ }
926
+
927
+ /* Banner */
928
+
929
+ #banner {
930
+ padding-left: 2em;
931
+ padding-right: 2em;
932
+ }
933
+
934
+ /* Footer */
935
+
936
+ #footer {
937
+ padding-left: 2em;
938
+ padding-right: 2em;
939
+ }
940
+
941
+ }
942
+
943
+ /* Narrow */
944
+
945
+ /* Narrower */
946
+
947
+ @media screen and (max-width: 840px) {
948
+
949
+ /* Basic */
950
+
951
+ body, input, select {
952
+ font-size: 13pt;
953
+ line-height: 1.65em;
954
+ }
955
+
956
+ .tweet {
957
+ text-align: center;
958
+ }
959
+
960
+ .timestamp {
961
+ display: block;
962
+ text-align: center;
963
+ }
964
+
965
+ /* Footer */
966
+
967
+ #footer {
968
+ padding: 4em 2em 4em 2em;
969
+ }
970
+
971
+ /* Carousel */
972
+
973
+ .carousel {
974
+ padding: 1.25em 0 1.25em 0;
975
+ }
976
+
977
+ .carousel article {
978
+ width: 18em;
979
+ margin: 0 1em 0 0;
980
+ }
981
+
982
+ }
983
+
984
+ /* Mobile */
985
+
986
+ #navPanel, #titleBar {
987
+ display: none;
988
+ }
989
+
990
+ @media screen and (max-width: 736px) {
991
+
992
+ /* Basic */
993
+
994
+ html, body {
995
+ overflow-x: hidden;
996
+ }
997
+
998
+ body, input, select {
999
+ font-size: 12.5pt;
1000
+ line-height: 1.5em;
1001
+ }
1002
+
1003
+ h2 {
1004
+ font-size: 1.75em;
1005
+ }
1006
+
1007
+ h3 {
1008
+ font-size: 1.25em;
1009
+ }
1010
+
1011
+ hr {
1012
+ top: 3em;
1013
+ margin-bottom: 6em;
1014
+ }
1015
+
1016
+
1017
+
1018
+ #header {
1019
+ background-attachment: scroll;
1020
+ padding: 2.5em 0 0 0;
1021
+ }
1022
+
1023
+ #header .inner {
1024
+ padding-top: 1.5em;
1025
+ padding-left: 1em;
1026
+ padding-right: 1em;
1027
+ }
1028
+
1029
+ #header header > p {
1030
+ font-size: 1em;
1031
+ }
1032
+
1033
+ #header h1 {
1034
+ font-size: 1.75em;
1035
+ }
1036
+
1037
+ #header hr {
1038
+ top: 1em;
1039
+ margin-bottom: 2.5em;
1040
+ }
1041
+
1042
+ #nav {
1043
+ display: none;
1044
+ }
1045
+
1046
+ #main > header {
1047
+ text-align: center;
1048
+ }
1049
+
1050
+ div.copyright {
1051
+ margin-top: 10px;
1052
+ }
1053
+
1054
+
1055
+ label, textarea {
1056
+ font-size: 0.8rem;
1057
+ letter-spacing: 1px;
1058
+ font-family: Georgia, 'Times New Roman', Times, serif;
1059
+ }
1060
+
1061
+
1062
+ .buttons {
1063
+ display: flex;
1064
+ flex-direction: row;
1065
+ justify-content: center;
1066
+ margin-top: 20px;
1067
+ }
1068
+ }
templates/site_helios/assets/css/noscript.css ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Helios by HTML5 UP
3
+ html5up.net | @ajlkn
4
+ Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
5
+ */
6
+
7
+ /* Carousel */
8
+
9
+ .carousel {
10
+ overflow-x: auto;
11
+ }
12
+
13
+ /* Header */
14
+
15
+ body.homepage.is-preload #header:after {
16
+ opacity: 0;
17
+ }
templates/site_helios/images/header.jpg ADDED